From deeb95cd4b20dfe9ce2544ee9a0fa52350b6d60b Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Mon, 23 Jun 2025 13:36:51 +0300 Subject: [PATCH 01/18] Use new JAL opcode for function calls --- .../asm_generation/fuel/fuel_asm_builder.rs | 11 -------- .../src/asm_generation/fuel/functions.rs | 23 ++++++---------- sway-core/src/asm_lang/allocated_ops.rs | 4 +++ sway-core/src/asm_lang/mod.rs | 26 +------------------ sway-core/src/asm_lang/virtual_ops.rs | 9 +++++++ .../src/sdk-harness/test_projects/auth/mod.rs | 6 ++--- 6 files changed, 25 insertions(+), 54 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs index 468504e3ba6..08b86dcd2e2 100644 --- a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs +++ b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs @@ -163,15 +163,6 @@ impl AsmBuilder for FuelAsmBuilder<'_, '_> { owning_span: None, }); - // Set a new return address. - let ret_label = self.reg_seqr.get_label(); - self.before_entries.push(Op::save_ret_addr( - VirtualRegister::Constant(ConstantRegister::CallReturnAddress), - ret_label, - "set new return address", - None, - )); - // call decode self.before_entries.push(Op { opcode: Either::Right(crate::asm_lang::ControlFlowOp::Jump { @@ -181,8 +172,6 @@ impl AsmBuilder for FuelAsmBuilder<'_, '_> { comment: format!("decode configurable {}", name), owning_span: None, }); - - self.before_entries.push(Op::unowned_jump_label(ret_label)); } } } diff --git a/sway-core/src/asm_generation/fuel/functions.rs b/sway-core/src/asm_generation/fuel/functions.rs index 96c8b55479e..6f3c6973356 100644 --- a/sway-core/src/asm_generation/fuel/functions.rs +++ b/sway-core/src/asm_generation/fuel/functions.rs @@ -179,15 +179,6 @@ impl FuelAsmBuilder<'_, '_> { } } - // Set a new return address. - let ret_label = self.reg_seqr.get_label(); - self.cur_bytecode.push(Op::save_ret_addr( - VirtualRegister::Constant(ConstantRegister::CallReturnAddress), - ret_label, - "[call]: set new return address", - None, - )); - // Jump to function and insert return label. let (fn_label, _) = self.func_to_labels(function); self.cur_bytecode.push(Op { @@ -198,7 +189,6 @@ impl FuelAsmBuilder<'_, '_> { comment: format!("[call]: call {}", function.get_name(self.context)), owning_span: None, }); - self.cur_bytecode.push(Op::unowned_jump_label(ret_label)); // Save the return value. let ret_reg = self.reg_seqr.next(); @@ -368,11 +358,14 @@ impl FuelAsmBuilder<'_, '_> { }); // Jump to the return address. - self.cur_bytecode.push(Op::jump_to_register( - VirtualRegister::Constant(ConstantRegister::CallReturnAddress), - "return from call", - None, - )); + self.cur_bytecode.push( + Op { + opcode: Either::Left(VirtualOp::JAL(ConstantRegister::Zero.into(), + ConstantRegister::CallReturnAddress.into(), VirtualImmediate12::new_unchecked(0, "Zero must fit into 12 bits"))), + comment: "return from call".into(), + owning_span: None, + } + ); } // Save this function. diff --git a/sway-core/src/asm_lang/allocated_ops.rs b/sway-core/src/asm_lang/allocated_ops.rs index f9cf6135ea9..27aaaeee78d 100644 --- a/sway-core/src/asm_lang/allocated_ops.rs +++ b/sway-core/src/asm_lang/allocated_ops.rs @@ -151,6 +151,7 @@ pub(crate) enum AllocatedInstruction { JMPF(AllocatedRegister, VirtualImmediate18), JNZB(AllocatedRegister, AllocatedRegister, VirtualImmediate12), JNZF(AllocatedRegister, AllocatedRegister, VirtualImmediate12), + JAL(AllocatedRegister, AllocatedRegister, VirtualImmediate12), RET(AllocatedRegister), /* Memory Instructions */ @@ -355,6 +356,7 @@ impl AllocatedInstruction { JMPF(_r1, _i) => vec![], JNZB(_r1, _r2, _i) => vec![], JNZF(_r1, _r2, _i) => vec![], + JAL(r1, _r2, _i) => vec![r1], RET(_r1) => vec![], /* Memory Instructions */ @@ -486,6 +488,7 @@ impl fmt::Display for AllocatedInstruction { JMPF(a, b) => write!(fmtr, "jmpf {a} {b}"), JNZB(a, b, c) => write!(fmtr, "jnzb {a} {b} {c}"), JNZF(a, b, c) => write!(fmtr, "jnzf {a} {b} {c}"), + JAL(a, b, c) => write!(fmtr, "jal {a} {b} {c}"), RET(a) => write!(fmtr, "ret {a}"), /* Memory Instructions */ @@ -689,6 +692,7 @@ impl AllocatedOp { JMPF(a, b) => op::JMPF::new(a.to_reg_id(), b.value().into()).into(), JNZB(a, b, c) => op::JNZB::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), JNZF(a, b, c) => op::JNZF::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), + JAL(a, b, c) => op::JAL::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), RET(a) => op::RET::new(a.to_reg_id()).into(), /* Memory Instructions */ diff --git a/sway-core/src/asm_lang/mod.rs b/sway-core/src/asm_lang/mod.rs index 7c54a30eee2..d7806431161 100644 --- a/sway-core/src/asm_lang/mod.rs +++ b/sway-core/src/asm_lang/mod.rs @@ -209,19 +209,6 @@ impl Op { } } - /// Move an address at a label into a register. - pub(crate) fn save_ret_addr( - reg: VirtualRegister, - label: Label, - comment: impl Into, - owning_span: Option, - ) -> Self { - Op { - opcode: Either::Right(OrganizationalOp::SaveRetAddr(reg, label)), - comment: comment.into(), - owning_span, - } - } /// Moves the register in the second argument into the register in the first argument pub(crate) fn register_move( @@ -295,18 +282,6 @@ impl Op { } } - /// Dynamically jumps to a register value. - pub(crate) fn jump_to_register( - reg: VirtualRegister, - comment: impl Into, - owning_span: Option, - ) -> Self { - Op { - opcode: Either::Left(VirtualOp::JMP(reg)), - comment: comment.into(), - owning_span, - } - } pub(crate) fn parse_opcode( handler: &Handler, @@ -1211,6 +1186,7 @@ impl fmt::Display for VirtualOp { JNE(a, b, c) => write!(fmtr, "jne {a} {b} {c}"), JNEI(a, b, c) => write!(fmtr, "jnei {a} {b} {c}"), JNZI(a, b) => write!(fmtr, "jnzi {a} {b}"), + JAL(a, b, c) => write!(fmtr, "jal {a} {b} {c}"), RET(a) => write!(fmtr, "ret {a}"), /* Memory Instructions */ diff --git a/sway-core/src/asm_lang/virtual_ops.rs b/sway-core/src/asm_lang/virtual_ops.rs index 794500185e5..7ca7b6e9391 100644 --- a/sway-core/src/asm_lang/virtual_ops.rs +++ b/sway-core/src/asm_lang/virtual_ops.rs @@ -106,6 +106,7 @@ pub(crate) enum VirtualOp { JNE(VirtualRegister, VirtualRegister, VirtualRegister), JNEI(VirtualRegister, VirtualRegister, VirtualImmediate12), JNZI(VirtualRegister, VirtualImmediate18), + JAL(VirtualRegister, VirtualRegister, VirtualImmediate12), RET(VirtualRegister), /* Memory Instructions */ @@ -305,6 +306,7 @@ impl VirtualOp { JNE(r1, r2, r3) => vec![r1, r2, r3], JNEI(r1, r2, _i) => vec![r1, r2], JNZI(r1, _i) => vec![r1], + JAL(r1, r2, _i) => vec![r1, r2], RET(r1) => vec![r1], /* Memory Instructions */ @@ -446,6 +448,7 @@ impl VirtualOp { | JNE(_, _, _) | JNEI(_, _, _) | JNZI(_, _) + | JAL(_, _, _) | RET(_) | ALOC(..) | CFEI(..) @@ -557,6 +560,7 @@ impl VirtualOp { | JNE(_, _, _) | JNEI(_, _, _) | JNZI(_, _) + | JAL(_, _, _) | RET(_) | LB(_, _, _) | LW(_, _, _) @@ -664,6 +668,7 @@ impl VirtualOp { JNE(r1, r2, r3) => vec![r1, r2, r3], JNEI(r1, r2, _i) => vec![r1, r2], JNZI(r1, _i) => vec![r1], + JAL(_r1, r2, _i) => vec![r2], RET(r1) => vec![r1], /* Memory Instructions */ @@ -791,6 +796,7 @@ impl VirtualOp { JNE(r1, r2, r3) => vec![r1, r2, r3], JNEI(r1, r2, _i) => vec![r1, r2], JNZI(r1, _i) => vec![r1], + JAL(_r1, r2, _i) => vec![r2], RET(r1) => vec![r1], /* Memory Instructions */ @@ -916,6 +922,7 @@ impl VirtualOp { JNE(_r1, _r2, _r3) => vec![], JNEI(_r1, _r2, _i) => vec![], JNZI(_r1, _i) => vec![], + JAL(r1, _r2, _i) => vec![r1], RET(_r1) => vec![], /* Memory Instructions */ @@ -1219,6 +1226,7 @@ impl VirtualOp { i.clone(), ), JNZI(r1, i) => Self::JNZI(update_reg(reg_to_reg_map, r1), i.clone()), + JAL(r1, r2, i) => Self::JAL(update_reg(reg_to_reg_map, r1), update_reg(reg_to_reg_map, r2), i.clone()), RET(r1) => Self::RET(update_reg(reg_to_reg_map, r1)), /* Memory Instructions */ @@ -1727,6 +1735,7 @@ impl VirtualOp { imm.clone(), ), JNZI(reg1, imm) => AllocatedInstruction::JNZI(map_reg(&mapping, reg1), imm.clone()), + JAL(reg1, reg2, imm) => AllocatedInstruction::JAL(map_reg(&mapping, reg1), map_reg(&mapping, reg2), imm.clone()), RET(reg) => AllocatedInstruction::RET(map_reg(&mapping, reg)), /* Memory Instructions */ diff --git a/test/src/sdk-harness/test_projects/auth/mod.rs b/test/src/sdk-harness/test_projects/auth/mod.rs index 817ad8e9543..32077c9ab8b 100644 --- a/test/src/sdk-harness/test_projects/auth/mod.rs +++ b/test/src/sdk-harness/test_projects/auth/mod.rs @@ -585,7 +585,7 @@ async fn can_get_predicate_address() { // Setup predicate. let hex_predicate_address: &str = - "0xa9e0330870e3ed1f537684021c02ad88d8116e91daff9651413169a77b26e509"; + "0xeddbd8cc2be5fb1d4ae24a5f789e61308750ff698865f311c9818d7eb76d4777"; let predicate_address = Address::from_str(hex_predicate_address).expect("failed to create Address from string"); let predicate_data = AuthPredicateEncoder::default() @@ -599,7 +599,7 @@ async fn can_get_predicate_address() { // If this test fails, it can be that the predicate address got changed. // Uncomment the next line, get the predicate address, and update it above. - // dbg!(&predicate); + dbg!(&predicate); // Next, we lock some assets in this predicate using the first wallet: // First wallet transfers amount to predicate. @@ -710,7 +710,7 @@ async fn when_incorrect_predicate_address_passed() { async fn can_get_predicate_address_in_message() { // Setup predicate address. let hex_predicate_address: &str = - "0xa9e0330870e3ed1f537684021c02ad88d8116e91daff9651413169a77b26e509"; + "0xeddbd8cc2be5fb1d4ae24a5f789e61308750ff698865f311c9818d7eb76d4777"; let predicate_address = Address::from_str(hex_predicate_address).expect("failed to create Address from string"); From e29d4155ed437dce68a67902bc4af3c6f9be5320 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Mon, 23 Jun 2025 13:42:47 +0300 Subject: [PATCH 02/18] fmt --- sway-core/src/asm_generation/fuel/functions.rs | 17 +++++++++-------- sway-core/src/asm_lang/mod.rs | 2 -- sway-core/src/asm_lang/virtual_ops.rs | 12 ++++++++++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/functions.rs b/sway-core/src/asm_generation/fuel/functions.rs index 6f3c6973356..c8ba0cf78cb 100644 --- a/sway-core/src/asm_generation/fuel/functions.rs +++ b/sway-core/src/asm_generation/fuel/functions.rs @@ -358,14 +358,15 @@ impl FuelAsmBuilder<'_, '_> { }); // Jump to the return address. - self.cur_bytecode.push( - Op { - opcode: Either::Left(VirtualOp::JAL(ConstantRegister::Zero.into(), - ConstantRegister::CallReturnAddress.into(), VirtualImmediate12::new_unchecked(0, "Zero must fit into 12 bits"))), - comment: "return from call".into(), - owning_span: None, - } - ); + self.cur_bytecode.push(Op { + opcode: Either::Left(VirtualOp::JAL( + ConstantRegister::Zero.into(), + ConstantRegister::CallReturnAddress.into(), + VirtualImmediate12::new_unchecked(0, "Zero must fit into 12 bits"), + )), + comment: "return from call".into(), + owning_span: None, + }); } // Save this function. diff --git a/sway-core/src/asm_lang/mod.rs b/sway-core/src/asm_lang/mod.rs index d7806431161..e9e075a5087 100644 --- a/sway-core/src/asm_lang/mod.rs +++ b/sway-core/src/asm_lang/mod.rs @@ -209,7 +209,6 @@ impl Op { } } - /// Moves the register in the second argument into the register in the first argument pub(crate) fn register_move( r1: VirtualRegister, @@ -282,7 +281,6 @@ impl Op { } } - pub(crate) fn parse_opcode( handler: &Handler, name: &Ident, diff --git a/sway-core/src/asm_lang/virtual_ops.rs b/sway-core/src/asm_lang/virtual_ops.rs index 7ca7b6e9391..135567e4090 100644 --- a/sway-core/src/asm_lang/virtual_ops.rs +++ b/sway-core/src/asm_lang/virtual_ops.rs @@ -1226,7 +1226,11 @@ impl VirtualOp { i.clone(), ), JNZI(r1, i) => Self::JNZI(update_reg(reg_to_reg_map, r1), i.clone()), - JAL(r1, r2, i) => Self::JAL(update_reg(reg_to_reg_map, r1), update_reg(reg_to_reg_map, r2), i.clone()), + JAL(r1, r2, i) => Self::JAL( + update_reg(reg_to_reg_map, r1), + update_reg(reg_to_reg_map, r2), + i.clone(), + ), RET(r1) => Self::RET(update_reg(reg_to_reg_map, r1)), /* Memory Instructions */ @@ -1735,7 +1739,11 @@ impl VirtualOp { imm.clone(), ), JNZI(reg1, imm) => AllocatedInstruction::JNZI(map_reg(&mapping, reg1), imm.clone()), - JAL(reg1, reg2, imm) => AllocatedInstruction::JAL(map_reg(&mapping, reg1), map_reg(&mapping, reg2), imm.clone()), + JAL(reg1, reg2, imm) => AllocatedInstruction::JAL( + map_reg(&mapping, reg1), + map_reg(&mapping, reg2), + imm.clone(), + ), RET(reg) => AllocatedInstruction::RET(map_reg(&mapping, reg)), /* Memory Instructions */ From 9fc6fbe85d863cc23fbb7cee3e00990819225fc9 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Fri, 27 Jun 2025 01:59:02 +0300 Subject: [PATCH 03/18] Call addr generation --- .../allocated_abstract_instruction_set.rs | 255 ++++++++++++++---- .../asm_generation/fuel/programs/allocated.rs | 4 +- 2 files changed, 206 insertions(+), 53 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index cb37bddbb0e..416310ebc8e 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -15,7 +15,7 @@ use super::{ use fuel_vm::fuel_asm::Imm12; use indexmap::{IndexMap, IndexSet}; -use rustc_hash::FxHashSet; +use rustc_hash::FxHashMap; use sway_types::span::Span; use std::collections::{BTreeSet, HashMap}; @@ -198,18 +198,17 @@ impl AllocatedAbstractInstructionSet { pub(crate) fn realize_labels( mut self, data_section: &mut DataSection, - far_jump_indices: &FxHashSet, + far_jump_sizes: &FxHashMap, ) -> Result<(RealizedAbstractInstructionSet, LabeledBlocks), crate::CompileError> { let label_offsets = self.resolve_labels(data_section); let mut curr_offset = 0; let mut realized_ops = vec![]; for (op_idx, op) in self.ops.iter().enumerate() { - let op_size = if far_jump_indices.contains(&op_idx) { - 2 - } else { - Self::instruction_size_not_far_jump(op, data_section) - }; + let op_size = far_jump_sizes + .get(&op_idx) + .copied() + .unwrap_or_else(|| Self::instruction_size_not_far_jump(op, data_section)); let rel_offset = |curr_offset, lab| label_offsets.get(lab).unwrap().offs.abs_diff(curr_offset); let AllocatedAbstractOp { @@ -226,19 +225,31 @@ impl AllocatedAbstractInstructionSet { Either::Right(org_op) => match org_op { ControlFlowOp::Jump { to, type_ } => { let target_offset = label_offsets.get(&to).unwrap().offs; - let ops = compile_jump( - data_section, - curr_offset, - target_offset, - match type_ { - JumpType::NotZero(cond) => Some(cond), - _ => None, - }, - far_jump_indices.contains(&op_idx), - comment, - owning_span, - ); - debug_assert_eq!(ops.len() as u64, op_size); + let ops = if matches!(type_, JumpType::Call) { + compile_call( + data_section, + curr_offset, + target_offset, + far_jump_sizes.get(&op_idx).copied(), + comment, + owning_span, + ) + } else { + compile_jump( + data_section, + curr_offset, + target_offset, + match type_ { + JumpType::NotZero(cond) => Some(cond), + _ => None, + }, + far_jump_sizes.contains_key(&op_idx), + comment, + owning_span, + ) + }; + assert_eq!(far_jump_sizes.get(&op_idx).copied().unwrap_or(1), op_size); + assert_eq!(ops.len() as u64, op_size); realized_ops.extend(ops); } ControlFlowOp::SaveRetAddr(r1, ref to) => { @@ -348,8 +359,12 @@ impl AllocatedAbstractInstructionSet { // This is a concrete op, size is fixed Either::Left(_) => 1, - // Worst case for jump is 2 opcodes - Either::Right(Jump { .. }) => 2, + // Worst case for jump is 2 opcodes, and 3 for calls + Either::Right(Jump { ref type_, .. }) => match type_ { + JumpType::Unconditional => 2, + JumpType::NotZero(_) => 2, + JumpType::Call => 3, + }, // We use three instructions to save the absolute address for return. // SUB r1 $pc $is @@ -445,19 +460,19 @@ impl AllocatedAbstractInstructionSet { /// Go through all jumps and check if they could require a far jump in the worst case. /// For far jumps we have to reserve space for an extra opcode to load target address. + /// For far calls, we need to reserve two extra opcodes. /// Also, this will be mark self-jumps, as they require a noop to be inserted before them. - pub(crate) fn collect_far_jumps(&self) -> FxHashSet { + pub(crate) fn collect_far_jumps(&self) -> FxHashMap { let mut labelled_blocks = LabeledBlocks::new(); let mut cur_offset = 0; let mut cur_basic_block = None; - let mut far_jump_indices = FxHashSet::default(); + let mut far_jump_sizes = FxHashMap::default(); struct JumpInfo { to: Label, offset: u64, op_idx: usize, - limit: u64, } let mut jumps = Vec::new(); @@ -475,16 +490,11 @@ impl AllocatedAbstractInstructionSet { cur_basic_block = Some((cur_lab, op_idx, cur_offset)); } - if let Either::Right(ControlFlowOp::Jump { to, type_, .. }) = &op.opcode { + if let Either::Right(ControlFlowOp::Jump { to, .. }) = &op.opcode { jumps.push(JumpInfo { to: *to, offset: cur_offset, op_idx, - limit: if matches!(type_, JumpType::NotZero(_)) { - consts::TWELVE_BITS - } else { - consts::EIGHTEEN_BITS - }, }); } @@ -498,30 +508,52 @@ impl AllocatedAbstractInstructionSet { } for jump in jumps { - let rel_offset = labelled_blocks - .get(&jump.to) - .unwrap() - .offs - .abs_diff(jump.offset); + let offs = labelled_blocks.get(&jump.to).unwrap().offs; + let is_forward = offs > jump.offset; + let rel_offset = offs.abs_diff(jump.offset); // Self jumps need a NOOP inserted before it so that we can jump to the NOOP. - // This is handled by the force_far machinery as well. - if rel_offset == 0 || rel_offset > jump.limit { - debug_assert!(matches!( - self.ops[jump.op_idx].opcode, - Either::Right(ControlFlowOp::Jump { .. }) - )); - far_jump_indices.insert(jump.op_idx); - } + let Either::Right(ControlFlowOp::Jump { ref type_, .. }) = self.ops[jump.op_idx].opcode + else { + unreachable!("Jump info should only be collected for jumps"); + }; + match type_ { + JumpType::Unconditional => { + if rel_offset == 0 || rel_offset > consts::EIGHTEEN_BITS { + far_jump_sizes.insert(jump.op_idx, 2); + } + } + JumpType::NotZero(_) => { + if rel_offset == 0 || rel_offset > consts::TWELVE_BITS { + far_jump_sizes.insert(jump.op_idx, 2); + } + } + JumpType::Call => { + if is_forward { + if rel_offset > consts::TWELVE_BITS { + far_jump_sizes.insert(jump.op_idx, 3); + } + } else { + far_jump_sizes.insert( + jump.op_idx, + if rel_offset > consts::TWELVE_BITS { + 3 + } else { + 2 + }, + ); + } + } + }; } - far_jump_indices + far_jump_sizes } /// Map the labels to their offsets in the program. fn map_label_offsets( &self, data_section: &DataSection, - far_jump_indices: &FxHashSet, + far_jump_sizes: &FxHashMap, ) -> LabeledBlocks { let mut labelled_blocks = LabeledBlocks::new(); let mut cur_offset = 0; @@ -541,11 +573,10 @@ impl AllocatedAbstractInstructionSet { } // Update the offset. - let op_size = if far_jump_indices.contains(&op_idx) { - 2 - } else { - Self::instruction_size_not_far_jump(op, data_section) - }; + let op_size = far_jump_sizes + .get(&op_idx) + .copied() + .unwrap_or_else(|| Self::instruction_size_not_far_jump(op, data_section)); cur_offset += op_size; } @@ -727,3 +758,125 @@ pub(crate) fn compile_jump( }] } } + +/// Compiles a function call into the appropriate operations. +/// Near jumps are compiled into a single instruction, while far jumps are compiled into +/// two instructions: one to load the target address and another to jump to it. +pub(crate) fn compile_call( + data_section: &mut DataSection, + curr_offset: u64, + target_offset: u64, + far_size: Option, + comment: String, + owning_span: Option, +) -> Vec { + if curr_offset <= target_offset { + let delta = target_offset - curr_offset; + return if far_size == Some(3) { + let data_id = data_section.insert_data_value(Entry::new_word( + (delta - 1) * 4, + EntryName::NonConfigurable, + None, + )); + + vec![ + RealizedOp { + opcode: AllocatedInstruction::LoadDataId( + AllocatedRegister::Constant(ConstantRegister::Scratch), + data_id, + ), + owning_span: owning_span.clone(), + comment: "load far jump target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::ADD( + AllocatedRegister::Constant(ConstantRegister::Scratch), + AllocatedRegister::Constant(ConstantRegister::Scratch), + AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + ), + owning_span: owning_span.clone(), + comment: "load far jump target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::JAL( + AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), + AllocatedRegister::Constant(ConstantRegister::Scratch), + VirtualImmediate12::new_unchecked(0, "unreachable()"), + ), + owning_span, + comment, + }, + ] + } else { + vec![RealizedOp { + opcode: AllocatedInstruction::JAL( + AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), + AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + VirtualImmediate12::new_unchecked(delta, "unreachable()"), + ), + owning_span, + comment, + }] + }; + } + + let delta = curr_offset - target_offset; + + if far_size == Some(3) { + let data_id = data_section.insert_data_value(Entry::new_word( + (delta - 1) * 4, + EntryName::NonConfigurable, + None, + )); + + vec![ + RealizedOp { + opcode: AllocatedInstruction::LoadDataId( + AllocatedRegister::Constant(ConstantRegister::Scratch), + data_id, + ), + owning_span: owning_span.clone(), + comment: "load far jump target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::SUB( + AllocatedRegister::Constant(ConstantRegister::Scratch), + AllocatedRegister::Constant(ConstantRegister::Scratch), + AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + ), + owning_span: owning_span.clone(), + comment: "load far jump target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::JAL( + AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), + AllocatedRegister::Constant(ConstantRegister::Scratch), + VirtualImmediate12::new_unchecked(0, "unreachable()"), + ), + owning_span, + comment, + }, + ] + } else { + vec![ + RealizedOp { + opcode: AllocatedInstruction::SUBI( + AllocatedRegister::Constant(ConstantRegister::Scratch), + AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + VirtualImmediate12::new_unchecked(delta * 4, "unreachable()"), + ), + owning_span: owning_span.clone(), + comment: "load far jump target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::JAL( + AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), + AllocatedRegister::Constant(ConstantRegister::Scratch), + VirtualImmediate12::new_unchecked(0, "unreachable()"), + ), + owning_span, + comment, + }, + ] + } +} diff --git a/sway-core/src/asm_generation/fuel/programs/allocated.rs b/sway-core/src/asm_generation/fuel/programs/allocated.rs index a9e7866be0f..a3bfd689044 100644 --- a/sway-core/src/asm_generation/fuel/programs/allocated.rs +++ b/sway-core/src/asm_generation/fuel/programs/allocated.rs @@ -32,9 +32,9 @@ impl AllocatedProgram { .collect(), }; - let far_jump_indices = abstract_ops.collect_far_jumps(); + let far_jump_sizes = abstract_ops.collect_far_jumps(); let (realized_ops, mut label_offsets) = - abstract_ops.realize_labels(&mut self.data_section, &far_jump_indices)?; + abstract_ops.realize_labels(&mut self.data_section, &far_jump_sizes)?; let ops = realized_ops.allocated_ops(); // Collect the entry point offsets. From b992628d6660dcb7611dc33ac72ea05172c9bb90 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 06:11:32 +0300 Subject: [PATCH 04/18] Generate relative calls using JAL properly --- .../allocated_abstract_instruction_set.rs | 283 +++++++++++------- .../optimizations/const_indexed_aggregates.rs | 3 +- .../fuel/optimizations/constant_propagate.rs | 1 - sway-core/src/asm_lang/mod.rs | 27 +- 4 files changed, 178 insertions(+), 136 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index 416310ebc8e..ff2918784e4 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -13,7 +13,7 @@ use super::{ data_section::{DataSection, Entry}, }; -use fuel_vm::fuel_asm::Imm12; +use fuel_vm::{fuel_asm::Imm12, prelude::Instruction}; use indexmap::{IndexMap, IndexSet}; use rustc_hash::FxHashMap; use sway_types::span::Span; @@ -209,8 +209,6 @@ impl AllocatedAbstractInstructionSet { .get(&op_idx) .copied() .unwrap_or_else(|| Self::instruction_size_not_far_jump(op, data_section)); - let rel_offset = - |curr_offset, lab| label_offsets.get(lab).unwrap().offs.abs_diff(curr_offset); let AllocatedAbstractOp { opcode, comment, @@ -252,37 +250,6 @@ impl AllocatedAbstractInstructionSet { assert_eq!(ops.len() as u64, op_size); realized_ops.extend(ops); } - ControlFlowOp::SaveRetAddr(r1, ref to) => { - let imm = VirtualImmediate12::new_unchecked( - rel_offset(curr_offset, to), - "Programs with more than 2^12 relative offset are unsupported right now", - ); - assert!(curr_offset < label_offsets.get(to).unwrap().offs); - realized_ops.push(RealizedOp { - opcode: AllocatedInstruction::SUB( - r1.clone(), - AllocatedRegister::Constant(ConstantRegister::ProgramCounter), - AllocatedRegister::Constant(ConstantRegister::InstructionStart), - ), - owning_span: owning_span.clone(), - comment: "get current instruction offset from instructions start ($is)" - .into(), - }); - realized_ops.push(RealizedOp { - opcode: AllocatedInstruction::SRLI( - r1.clone(), - r1.clone(), - VirtualImmediate12::new_unchecked(2, "two must fit in 12 bits"), - ), - owning_span: owning_span.clone(), - comment: "get current instruction offset in 32-bit words".into(), - }); - realized_ops.push(RealizedOp { - opcode: AllocatedInstruction::ADDI(r1.clone(), r1, imm), - owning_span, - comment, - }); - } ControlFlowOp::DataSectionOffsetPlaceholder => { realized_ops.push(RealizedOp { opcode: AllocatedInstruction::DataSectionOffsetPlaceholder, @@ -366,12 +333,6 @@ impl AllocatedAbstractInstructionSet { JumpType::Call => 3, }, - // We use three instructions to save the absolute address for return. - // SUB r1 $pc $is - // SRLI r1 r1 2 / DIVI r1 r1 4 - // ADDI $r1 $r1 offset - Either::Right(SaveRetAddr(..)) => 3, - Either::Right(Comment) => 0, Either::Right(DataSectionOffsetPlaceholder) => { @@ -435,12 +396,6 @@ impl AllocatedAbstractInstructionSet { // Far jumps must be handled separately, as they require two instructions. Either::Right(Jump { .. }) => 1, - // We use three instructions to save the absolute address for return. - // SUB r1 $pc $is - // SRLI r1 r1 2 / DIVI r1 r1 4 - // ADDI $r1 $r1 offset - Either::Right(SaveRetAddr(..)) => 3, - Either::Right(Comment) => 0, Either::Right(DataSectionOffsetPlaceholder) => { @@ -509,39 +464,40 @@ impl AllocatedAbstractInstructionSet { for jump in jumps { let offs = labelled_blocks.get(&jump.to).unwrap().offs; - let is_forward = offs > jump.offset; let rel_offset = offs.abs_diff(jump.offset); - // Self jumps need a NOOP inserted before it so that we can jump to the NOOP. let Either::Right(ControlFlowOp::Jump { ref type_, .. }) = self.ops[jump.op_idx].opcode else { unreachable!("Jump info should only be collected for jumps"); }; + // Relative self jumps need a NOOP inserted before it so that we can jump to the NOOP. + let is_self_jump = rel_offset == 0; match type_ { JumpType::Unconditional => { - if rel_offset == 0 || rel_offset > consts::EIGHTEEN_BITS { + // Unconditional jumps have 18-bit immidate offset + if is_self_jump || rel_offset > consts::EIGHTEEN_BITS { far_jump_sizes.insert(jump.op_idx, 2); } } JumpType::NotZero(_) => { - if rel_offset == 0 || rel_offset > consts::TWELVE_BITS { + // Conditional jumps have 12-bit immidate offset + if is_self_jump || rel_offset > consts::TWELVE_BITS { far_jump_sizes.insert(jump.op_idx, 2); } } JumpType::Call => { - if is_forward { - if rel_offset > consts::TWELVE_BITS { - far_jump_sizes.insert(jump.op_idx, 3); - } - } else { - far_jump_sizes.insert( - jump.op_idx, - if rel_offset > consts::TWELVE_BITS { - 3 - } else { - 2 - }, - ); - } + // Use the actual codegen to estimate the size of the call. + // This can never generate a number that's too small, but in some + // corner cases it leads to reserving an extra opcode. + // See `compile_call` that inserts NOOPs to pad the call in these cases. + let len = compile_call_inner( + &mut DataSection::default(), + jump.offset, + offs, + String::new(), + None, + ) + .len(); + far_jump_sizes.insert(jump.op_idx, len as u64); } }; } @@ -760,42 +716,56 @@ pub(crate) fn compile_jump( } /// Compiles a function call into the appropriate operations. -/// Near jumps are compiled into a single instruction, while far jumps are compiled into -/// two instructions: one to load the target address and another to jump to it. -pub(crate) fn compile_call( +/// Generates 1 to 3 instruction depending on the distance to target. +pub(crate) fn compile_call_inner( data_section: &mut DataSection, curr_offset: u64, target_offset: u64, - far_size: Option, comment: String, owning_span: Option, ) -> Vec { + // Handle forwards and backwards jumps separately if curr_offset <= target_offset { let delta = target_offset - curr_offset; - return if far_size == Some(3) { - let data_id = data_section.insert_data_value(Entry::new_word( - (delta - 1) * 4, - EntryName::NonConfigurable, - None, - )); - vec![ + // If the offset is small enough for a single instruction, do it directly + if let Ok(imm) = VirtualImmediate12::new(delta, Span::dummy()) { + return vec![RealizedOp { + opcode: AllocatedInstruction::JAL( + AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), + AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + imm, + ), + owning_span, + comment, + }]; + } + + // The next approaches require an extra instruction before the PC is used, so we + // subtract 1 from the delta to account for that. It cannot underflow as otherwise the first + // approach would have been used. Then we multiply by instruction size for doing arithmetic + // with the PC register. The overflow cannot occur since programs cannot be 2**60 bytes large. + let delta_instr = (delta - 1) * (Instruction::SIZE as u64); + + // Attempt MOVI-based approach, that has larger immediate size but doens't require data section. + if let Ok(imm) = VirtualImmediate18::new(delta_instr, Span::dummy()) { + return vec![ RealizedOp { - opcode: AllocatedInstruction::LoadDataId( + opcode: AllocatedInstruction::MOVI( AllocatedRegister::Constant(ConstantRegister::Scratch), - data_id, + imm, ), owning_span: owning_span.clone(), - comment: "load far jump target address".into(), + comment: "load call target address".into(), }, RealizedOp { opcode: AllocatedInstruction::ADD( - AllocatedRegister::Constant(ConstantRegister::Scratch), AllocatedRegister::Constant(ConstantRegister::Scratch), AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + AllocatedRegister::Constant(ConstantRegister::Scratch), ), owning_span: owning_span.clone(), - comment: "load far jump target address".into(), + comment: "load call target address".into(), }, RealizedOp { opcode: AllocatedInstruction::JAL( @@ -806,46 +776,33 @@ pub(crate) fn compile_call( owning_span, comment, }, - ] - } else { - vec![RealizedOp { - opcode: AllocatedInstruction::JAL( - AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), - AllocatedRegister::Constant(ConstantRegister::ProgramCounter), - VirtualImmediate12::new_unchecked(delta, "unreachable()"), - ), - owning_span, - comment, - }] - }; - } - - let delta = curr_offset - target_offset; + ]; + } - if far_size == Some(3) { + // if the offset is too large for MOVI, use data section to store the full offset. let data_id = data_section.insert_data_value(Entry::new_word( - (delta - 1) * 4, + delta_instr, EntryName::NonConfigurable, None, )); - vec![ + return vec![ RealizedOp { opcode: AllocatedInstruction::LoadDataId( AllocatedRegister::Constant(ConstantRegister::Scratch), data_id, ), owning_span: owning_span.clone(), - comment: "load far jump target address".into(), + comment: "load call target address".into(), }, RealizedOp { - opcode: AllocatedInstruction::SUB( - AllocatedRegister::Constant(ConstantRegister::Scratch), + opcode: AllocatedInstruction::ADD( AllocatedRegister::Constant(ConstantRegister::Scratch), AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + AllocatedRegister::Constant(ConstantRegister::Scratch), ), owning_span: owning_span.clone(), - comment: "load far jump target address".into(), + comment: "load call target address".into(), }, RealizedOp { opcode: AllocatedInstruction::JAL( @@ -856,14 +813,25 @@ pub(crate) fn compile_call( owning_span, comment, }, - ] - } else { - vec![ + ]; + } + + // This is a jump backwards. The approaches are same as forward jumping, but + // the version with only a single instruction is not possible, and we have to replace + // ADD with SUB instructions. A SUBI-based approach can be used, for a cheap 2-instruction case. + let delta = curr_offset - target_offset; + + // Attempt SUBI-based approach + if let Ok(imm) = VirtualImmediate12::new( + delta.saturating_mul(Instruction::SIZE as u64), + Span::dummy(), + ) { + return vec![ RealizedOp { opcode: AllocatedInstruction::SUBI( AllocatedRegister::Constant(ConstantRegister::Scratch), AllocatedRegister::Constant(ConstantRegister::ProgramCounter), - VirtualImmediate12::new_unchecked(delta * 4, "unreachable()"), + imm, ), owning_span: owning_span.clone(), comment: "load far jump target address".into(), @@ -877,6 +845,107 @@ pub(crate) fn compile_call( owning_span, comment, }, - ] + ]; + } + + // Since the rest of the approaches require an extra instruction before the PC is used, we + // add 1 to the delta to account for that. It cannot underflow as otherwise the first + // approach would have been used. Then we multiply by instruction size for doing arithmetic + // with the PC register. The overflow cannot occur since programs cannot be 2**60 bytes large. + let delta_instr = (delta + 1) * (Instruction::SIZE as u64); + + // Attempt MOVI-based approach. + if let Ok(imm) = VirtualImmediate18::new(delta_instr, Span::dummy()) { + return vec![ + RealizedOp { + opcode: AllocatedInstruction::MOVI( + AllocatedRegister::Constant(ConstantRegister::Scratch), + imm, + ), + owning_span: owning_span.clone(), + comment: "load call target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::SUB( + AllocatedRegister::Constant(ConstantRegister::Scratch), + AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + AllocatedRegister::Constant(ConstantRegister::Scratch), + ), + owning_span: owning_span.clone(), + comment: "load call target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::JAL( + AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), + AllocatedRegister::Constant(ConstantRegister::Scratch), + VirtualImmediate12::new_unchecked(0, "unreachable()"), + ), + owning_span, + comment, + }, + ]; + } + + // And lastly, fall back to the data section backed approach. + let data_id = data_section.insert_data_value(Entry::new_word( + delta_instr, + EntryName::NonConfigurable, + None, + )); + + vec![ + RealizedOp { + opcode: AllocatedInstruction::LoadDataId( + AllocatedRegister::Constant(ConstantRegister::Scratch), + data_id, + ), + owning_span: owning_span.clone(), + comment: "load call target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::SUB( + AllocatedRegister::Constant(ConstantRegister::Scratch), + AllocatedRegister::Constant(ConstantRegister::ProgramCounter), + AllocatedRegister::Constant(ConstantRegister::Scratch), + ), + owning_span: owning_span.clone(), + comment: "load call target address".into(), + }, + RealizedOp { + opcode: AllocatedInstruction::JAL( + AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), + AllocatedRegister::Constant(ConstantRegister::Scratch), + VirtualImmediate12::new_unchecked(0, "unreachable()"), + ), + owning_span, + comment, + }, + ] +} + +/// Compiles a function call into the appropriate operations. +/// Pads the call to the size reserved for it. +pub(crate) fn compile_call( + data_section: &mut DataSection, + curr_offset: u64, + target_offset: u64, + far_size: Option, + comment: String, + owning_span: Option, +) -> Vec { + let mut res = compile_call_inner( + data_section, + curr_offset, + target_offset, + comment.clone(), + owning_span.clone(), + ); + while res.len() < far_size.unwrap_or(1) as usize { + res.push(RealizedOp { + opcode: AllocatedInstruction::NOOP, + owning_span: owning_span.clone(), + comment: comment.clone(), + }); } + res } diff --git a/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs b/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs index b1649bea23f..b2c68109fc9 100644 --- a/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs +++ b/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs @@ -2,7 +2,7 @@ use rustc_hash::FxHashMap; use crate::{ asm_generation::fuel::compiler_constants, - asm_lang::{ControlFlowOp, VirtualImmediate12, VirtualOp, VirtualRegister}, + asm_lang::{VirtualImmediate12, VirtualOp, VirtualRegister}, }; use super::super::{abstract_instruction_set::AbstractInstructionSet, data_section::DataSection}; @@ -210,7 +210,6 @@ impl AbstractInstructionSet { } } } - either::Either::Right(ControlFlowOp::SaveRetAddr(..)) => {} either::Either::Right(_) => { clear_state = true; } diff --git a/sway-core/src/asm_generation/fuel/optimizations/constant_propagate.rs b/sway-core/src/asm_generation/fuel/optimizations/constant_propagate.rs index 556352a5863..96a39ec4515 100644 --- a/sway-core/src/asm_generation/fuel/optimizations/constant_propagate.rs +++ b/sway-core/src/asm_generation/fuel/optimizations/constant_propagate.rs @@ -222,7 +222,6 @@ impl AbstractInstructionSet { }, // These ops mark their outputs properly and cause no control-flow effects ControlFlowOp::Comment - | ControlFlowOp::SaveRetAddr(_, _) | ControlFlowOp::ConfigurablesOffsetPlaceholder | ControlFlowOp::DataSectionOffsetPlaceholder => ResetKnown::Defs, // This changes the stack pointer diff --git a/sway-core/src/asm_lang/mod.rs b/sway-core/src/asm_lang/mod.rs index e9e075a5087..14f22fd6bef 100644 --- a/sway-core/src/asm_lang/mod.rs +++ b/sway-core/src/asm_lang/mod.rs @@ -1288,8 +1288,6 @@ pub(crate) enum ControlFlowOp { /// Jump type type_: JumpType, }, - // Save a return label address in a register. - SaveRetAddr(Reg, Label), // Placeholder for the offset into the configurables section. ConfigurablesOffsetPlaceholder, // placeholder for the DataSection offset @@ -1316,7 +1314,6 @@ impl fmt::Display for ControlFlowOp { JumpType::Call => format!("fncall {to}"), }, Comment => "".into(), - SaveRetAddr(r1, lab) => format!("mova {r1} {lab}"), DataSectionOffsetPlaceholder => "DATA SECTION OFFSET[0..32]\nDATA SECTION OFFSET[32..64]".into(), ConfigurablesOffsetPlaceholder => @@ -1339,8 +1336,6 @@ impl ControlFlowOp { | PushAll(_) | PopAll(_) => vec![], - SaveRetAddr(r1, _) => vec![r1], - Jump { type_, .. } => match type_ { JumpType::Unconditional => vec![], JumpType::NotZero(r1) => vec![r1], @@ -1356,7 +1351,6 @@ impl ControlFlowOp { (match self { Label(_) | Comment - | SaveRetAddr(..) | DataSectionOffsetPlaceholder | ConfigurablesOffsetPlaceholder | PushAll(_) @@ -1377,7 +1371,6 @@ impl ControlFlowOp { (match self { Label(_) | Comment - | SaveRetAddr(..) | DataSectionOffsetPlaceholder | ConfigurablesOffsetPlaceholder | PushAll(_) @@ -1393,20 +1386,7 @@ impl ControlFlowOp { } pub(crate) fn def_registers(&self) -> BTreeSet<&Reg> { - use ControlFlowOp::*; - (match self { - SaveRetAddr(reg, _) => vec![reg], - - Label(_) - | Comment - | Jump { .. } - | DataSectionOffsetPlaceholder - | ConfigurablesOffsetPlaceholder - | PushAll(_) - | PopAll(_) => vec![], - }) - .into_iter() - .collect() + BTreeSet::new() } pub(crate) fn def_const_registers(&self) -> BTreeSet<&VirtualRegister> { @@ -1432,8 +1412,6 @@ impl ControlFlowOp { }, _ => self.clone(), }, - - SaveRetAddr(r1, label) => Self::SaveRetAddr(update_reg(r1), *label), } } @@ -1450,7 +1428,6 @@ impl ControlFlowOp { match self { Label(_) | Comment - | SaveRetAddr(..) | DataSectionOffsetPlaceholder | ConfigurablesOffsetPlaceholder | PushAll(_) @@ -1534,8 +1511,6 @@ impl ControlFlowOp { ConfigurablesOffsetPlaceholder => ConfigurablesOffsetPlaceholder, PushAll(label) => PushAll(*label), PopAll(label) => PopAll(*label), - - SaveRetAddr(r1, label) => SaveRetAddr(map_reg(r1), *label), } } } From 788b3e09fd54ba018c0c2535475ada9eb46665a3 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 06:15:06 +0300 Subject: [PATCH 05/18] spellcheck --- .typos.toml | 1 + .../asm_generation/fuel/allocated_abstract_instruction_set.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.typos.toml b/.typos.toml index 61ae2104eb3..8dbeb3babe4 100644 --- a/.typos.toml +++ b/.typos.toml @@ -6,6 +6,7 @@ extend-ignore-identifiers-re = [ "TRO", "tro", "Tro", + "NOOP", "Nam", "typ", ] diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index ff2918784e4..8c2211ba598 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -747,7 +747,7 @@ pub(crate) fn compile_call_inner( // with the PC register. The overflow cannot occur since programs cannot be 2**60 bytes large. let delta_instr = (delta - 1) * (Instruction::SIZE as u64); - // Attempt MOVI-based approach, that has larger immediate size but doens't require data section. + // Attempt MOVI-based approach, that has larger immediate size but doesn't require data section. if let Ok(imm) = VirtualImmediate18::new(delta_instr, Span::dummy()) { return vec![ RealizedOp { From a8be94b477b8fae9ec510e2504dd09afa1defcd4 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 06:18:39 +0300 Subject: [PATCH 06/18] More spellcheck --- forc-plugins/forc-migrate/src/visiting/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forc-plugins/forc-migrate/src/visiting/mod.rs b/forc-plugins/forc-migrate/src/visiting/mod.rs index 4d9ad8046fa..1eace1bd5fe 100644 --- a/forc-plugins/forc-migrate/src/visiting/mod.rs +++ b/forc-plugins/forc-migrate/src/visiting/mod.rs @@ -1159,7 +1159,7 @@ impl __ProgramVisitor { // When visiting the RHS in the lexed tree, we need to skip the // operator method call in the typed tree, and provide the // typed arguments instead. - // To provide visiting without loosing the information about compound + // To provide visiting without losing the information about compound // reassignment, we will need to have a dedicated `visit_reassignment` // method. // TODO: Implement visiting expressions in the reassignment LHS. From f717e04d2e650e42e9c1697fba86b5434497fd55 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 06:18:46 +0300 Subject: [PATCH 07/18] Update hardcoded predicate address in tests --- test/src/sdk-harness/test_projects/auth/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/sdk-harness/test_projects/auth/mod.rs b/test/src/sdk-harness/test_projects/auth/mod.rs index 32077c9ab8b..a9b3aea82ef 100644 --- a/test/src/sdk-harness/test_projects/auth/mod.rs +++ b/test/src/sdk-harness/test_projects/auth/mod.rs @@ -585,7 +585,7 @@ async fn can_get_predicate_address() { // Setup predicate. let hex_predicate_address: &str = - "0xeddbd8cc2be5fb1d4ae24a5f789e61308750ff698865f311c9818d7eb76d4777"; + "0xdb6749fef741db73ad960d0eb2c601601d8794aeaf3e356be78650b756d7c5ed"; let predicate_address = Address::from_str(hex_predicate_address).expect("failed to create Address from string"); let predicate_data = AuthPredicateEncoder::default() @@ -599,7 +599,7 @@ async fn can_get_predicate_address() { // If this test fails, it can be that the predicate address got changed. // Uncomment the next line, get the predicate address, and update it above. - dbg!(&predicate); + // dbg!(&predicate); // Next, we lock some assets in this predicate using the first wallet: // First wallet transfers amount to predicate. @@ -665,7 +665,7 @@ async fn when_incorrect_predicate_address_passed() { // Setup predicate with incorrect address. let hex_predicate_address: &str = - "0xeddbd8cc2be5fb1d4ae24a5f789e61308750ff698865f311c9818d7eb76d4777"; + "0xdb6749fef741db73ad960d0eb2c601601d8794aeaf3e356be78650b756d7c5ed"; let predicate_address = Address::from_str(hex_predicate_address).expect("failed to create Address from string"); let predicate_data = AuthPredicateEncoder::default() @@ -710,7 +710,7 @@ async fn when_incorrect_predicate_address_passed() { async fn can_get_predicate_address_in_message() { // Setup predicate address. let hex_predicate_address: &str = - "0xeddbd8cc2be5fb1d4ae24a5f789e61308750ff698865f311c9818d7eb76d4777"; + "0xdb6749fef741db73ad960d0eb2c601601d8794aeaf3e356be78650b756d7c5ed"; let predicate_address = Address::from_str(hex_predicate_address).expect("failed to create Address from string"); From fb49cd2fdeea0215d9ceb235a5e926398cad7cef Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 06:41:33 +0300 Subject: [PATCH 08/18] Update test cases and snapshots --- sway-core/src/asm_lang/allocated_ops.rs | 4 +- .../language/const_generics/stdout.snap | 2 +- .../attributes_deprecated/stdout.snap | 3 +- .../configurable_dedup_decode/stdout.snap | 22 ++---- .../language/const_generics/stdout.snap | 5 +- .../language/intrinsics/dbg/stdout.snap | 5 +- .../panic_handling_in_unit_tests/stdout.snap | 73 +++++++++---------- .../panicking_contract/stdout.snap | 25 +++---- .../panicking_lib/stdout.snap | 37 +++++----- .../panicking_script/stdout.snap | 25 +++---- .../stdout.snap | 35 +++++---- test/src/ir_generation/tests/asm_block.sw | 7 +- test/src/ir_generation/tests/fn_call.sw | 4 +- .../tests/fn_call_noargs_nolocals.sw | 14 +--- .../ir_generation/tests/fn_call_nolocals.sw | 5 +- test/src/ir_generation/tests/jmp_mem.sw | 2 +- 16 files changed, 119 insertions(+), 149 deletions(-) diff --git a/sway-core/src/asm_lang/allocated_ops.rs b/sway-core/src/asm_lang/allocated_ops.rs index 27aaaeee78d..3172f09fc9f 100644 --- a/sway-core/src/asm_lang/allocated_ops.rs +++ b/sway-core/src/asm_lang/allocated_ops.rs @@ -479,7 +479,7 @@ impl fmt::Display for AllocatedInstruction { WQMM(a, b, c, d) => write!(fmtr, "wqmm {a} {b} {c} {d}"), /* Control Flow Instructions */ - JMP(a) => write!(fmtr, "jmp {a}"), + JMP(a) => write!(fmtr, "jmp {a}"), JI(a) => write!(fmtr, "ji {a}"), JNE(a, b, c) => write!(fmtr, "jne {a} {b} {c}"), JNEI(a, b, c) => write!(fmtr, "jnei {a} {b} {c}"), @@ -488,7 +488,7 @@ impl fmt::Display for AllocatedInstruction { JMPF(a, b) => write!(fmtr, "jmpf {a} {b}"), JNZB(a, b, c) => write!(fmtr, "jnzb {a} {b} {c}"), JNZF(a, b, c) => write!(fmtr, "jnzf {a} {b} {c}"), - JAL(a, b, c) => write!(fmtr, "jal {a} {b} {c}"), + JAL(a, b, c) => write!(fmtr, "jal {a} {b} {c}"), RET(a) => write!(fmtr, "ret {a}"), /* Memory Instructions */ diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics/stdout.snap index 489958fc376..c8b0e93b214 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics/stdout.snap @@ -28,4 +28,4 @@ output: Building test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics Compiling library std (sway-lib-std) Compiling script const_generics (test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics) - Finished debug [unoptimized + fuel] target(s) [304 B] in ??? + Finished debug [unoptimized + fuel] target(s) [288 B] in ??? diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap index 7cd3ddefa66..917acd0ea92 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated --release exit status: 0 @@ -183,4 +182,4 @@ warning: Function is deprecated ____ Compiled contract "attributes_deprecated" with 19 warnings. - Finished release [optimized + fuel] target(s) [848 B] in ??? + Finished release [optimized + fuel] target(s) [752 B] in ??? diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap index abe65e2f5eb..493b395c3da 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode --release --ir final --asm final exit status: 0 @@ -325,24 +324,15 @@ cfei i16 ; allocate stack space for globals addr $$arg0 data_Configurable_0; get pointer to configurable TUPLE default value addi $$arg1 $zero i8 ; get length of configurable TUPLE default value addi $$arg2 $ssp i0 ; get pointer to configurable TUPLE stack address -sub $$reta $pc $is ; get current instruction offset from instructions start ($is) -srli $$reta $$reta i2 ; get current instruction offset in 32-bit words -addi $$reta $$reta i4 ; set new return address -jmpf $zero i79 ; decode configurable TUPLE +jal $$reta $pc i74 ; decode configurable TUPLE addr $$arg0 data_Configurable_1; get pointer to configurable WRAPPED default value addi $$arg1 $zero i8 ; get length of configurable WRAPPED default value addi $$arg2 $ssp i8 ; get pointer to configurable WRAPPED stack address -sub $$reta $pc $is ; get current instruction offset from instructions start ($is) -srli $$reta $$reta i2 ; get current instruction offset in 32-bit words -addi $$reta $$reta i4 ; set new return address -jmpf $zero i72 ; decode configurable WRAPPED +jal $$reta $pc i70 ; decode configurable WRAPPED move $$locbase $sp ; save locals base register for function __entry cfei i360 ; allocate 360 bytes for locals and 0 slots for call arguments addi $r0 $$locbase i272 ; get offset to local -sub $$reta $pc $is ; get current instruction offset from instructions start ($is) -srli $$reta $$reta i2 ; get current instruction offset in 32-bit words -addi $$reta $$reta i4 ; [call]: set new return address -jmpf $zero i81 ; [call]: call main_8 +jal $$reta $pc i82 ; [call]: call main_8 move $r1 $$retv ; [call]: copy the return value movi $r2 i1024 ; initialize constant into register aloc $r2 @@ -423,7 +413,7 @@ cfsi i8 ; free 8 bytes for locals and 0 slots for extra ca move $$reta $r1 ; restore return address poph i524288 ; restore registers 40..64 popl i7 ; restore registers 16..40 -jmp $$reta ; return from call +jal $zero $$reta i0 ; return from call pshl i3 ; save registers 16..40 pshh i524288 ; save registers 40..64 move $$locbase $sp ; save locals base register for function main_8 @@ -433,10 +423,10 @@ add $r0 $r0 $r1 move $$retv $r0 ; set return value poph i524288 ; restore registers 40..64 popl i3 ; restore registers 16..40 -jmp $$reta ; return from call +jal $zero $$reta i0 ; return from call .data: data__0 .bytes[8] 00 00 00 00 00 00 00 02 ........ data__1 .bytes[8] 00 00 00 00 00 00 00 01 ........ - Finished release [optimized + fuel] target(s) [504 B] in ??? + Finished release [optimized + fuel] target(s) [464 B] in ??? diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap index 9ceff14abdc..026154da3a2 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics --release exit status: 1 @@ -293,12 +292,12 @@ output: Building test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics Compiling library std (sway-lib-std) Compiling script const_generics (test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics) - Finished debug [unoptimized + fuel] target(s) [7.736 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [6.952 KB] in ??? Running 1 test, filtered 0 tests tested -- const_generics - test run_main ... ok (???, 14112 gas) + test run_main ... ok (???, 13705 gas) debug output: [src/main.sw:65:13] a = [1, 2] [src/main.sw:69:13] [C {}].len() = 1 diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap index b90031bb580..425ff9f7d8e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg --asm final | sub ecal ecal $r1 $r0 $zero $zero ; ecal id fd zero zero @@ -72,12 +71,12 @@ output: Building test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg Compiling library std (sway-lib-std) Compiling script dbg (test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg) - Finished debug [unoptimized + fuel] target(s) [44.016 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [41.536 KB] in ??? Running 1 test, filtered 0 tests tested -- dbg - test call_main ... ok (???, 121654 gas) + test call_main ... ok (???, 118154 gas) debug output: [src/main.sw:13:13] () = () [src/main.sw:15:13] true = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap index 26686a15f65..8ffa778d6dc 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc test --path test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests --logs --raw-logs --dbgs --reverts passing_ exit status: 0 @@ -19,12 +18,12 @@ warning: Error message is empty ____ Compiled script "panic_handling_in_unit_tests" with 1 warning. - Finished debug [unoptimized + fuel] target(s) [10.456 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [9.504 KB] in ??? Running 2 tests, filtered 18 tests tested -- panic_handling_in_unit_tests - test passing_dbgs_and_logs ... ok (???, 2244 gas) + test passing_dbgs_and_logs ... ok (???, 2162 gas) debug output: [src/main.sw:23:13] "This is a passing test containing `__dbg` outputs." = "This is a passing test containing `__dbg` outputs." [src/main.sw:25:13] x = 42 @@ -32,7 +31,7 @@ tested -- panic_handling_in_unit_tests AsciiString { data: "This is a log from the passing test." }, log rb: 10098701174489624218 42, log rb: 1515152261580153489 raw logs: -[{"LogData":{"data":"0000000000000024546869732069732061206c6f672066726f6d207468652070617373696e6720746573742e","digest":"29d742ad9093cdf81404ff756467a44448729b85ab3c0d65197829fb61d2dd29","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":44,"pc":16900,"ptr":67107840,"ra":0,"rb":10098701174489624218}},{"LogData":{"data":"000000000000002a","digest":"a6bb133cb1e3638ad7b8a3ff0539668e9e56f9b850ef1b2a810f5422eaa6c323","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":17364,"ptr":67106816,"ra":0,"rb":1515152261580153489}}] +[{"LogData":{"data":"0000000000000024546869732069732061206c6f672066726f6d207468652070617373696e6720746573742e","digest":"29d742ad9093cdf81404ff756467a44448729b85ab3c0d65197829fb61d2dd29","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":44,"pc":16104,"ptr":67107840,"ra":0,"rb":10098701174489624218}},{"LogData":{"data":"000000000000002a","digest":"a6bb133cb1e3638ad7b8a3ff0539668e9e56f9b850ef1b2a810f5422eaa6c323","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":16540,"ptr":67106816,"ra":0,"rb":1515152261580153489}}] test passing_no_dbgs_or_logs ... ok (???, 18 gas) test result: OK. 2 passed; 0 failed; finished in ??? @@ -56,31 +55,31 @@ warning: Error message is empty ____ Compiled script "panic_handling_in_unit_tests" with 1 warning. - Finished debug [unoptimized + fuel] target(s) [10.456 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [9.504 KB] in ??? Running 20 tests, filtered 0 tests tested -- panic_handling_in_unit_tests - test passing_dbgs_and_logs ... ok (???, 2244 gas) + test passing_dbgs_and_logs ... ok (???, 2162 gas) test passing_no_dbgs_or_logs ... ok (???, 18 gas) test failing_revert_intrinsic ... FAILED (???, 19 gas) - test failing_revert_function_with_dbgs_and_logs ... FAILED (???, 2318 gas) - test failing_error_signal_assert ... FAILED (???, 507 gas) - test failing_error_signal_assert_eq ... FAILED (???, 1443 gas) - test failing_error_signal_assert_ne ... FAILED (???, 1438 gas) - test failing_error_signal_require_str_error ... FAILED (???, 328 gas) - test failing_error_signal_require_enum_error ... FAILED (???, 421 gas) - test failing_panic_no_arg ... FAILED (???, 203 gas) - test failing_panic_unit_arg ... FAILED (???, 203 gas) + test failing_revert_function_with_dbgs_and_logs ... FAILED (???, 2246 gas) + test failing_error_signal_assert ... FAILED (???, 480 gas) + test failing_error_signal_assert_eq ... FAILED (???, 1374 gas) + test failing_error_signal_assert_ne ... FAILED (???, 1369 gas) + test failing_error_signal_require_str_error ... FAILED (???, 318 gas) + test failing_error_signal_require_enum_error ... FAILED (???, 412 gas) + test failing_panic_no_arg ... FAILED (???, 194 gas) + test failing_panic_unit_arg ... FAILED (???, 194 gas) test failing_panic_const_eval_str_arg ... FAILED (???, 19 gas) test failing_panic_const_eval_empty_str_arg ... FAILED (???, 19 gas) test failing_panic_const_eval_whitespace_str_arg ... FAILED (???, 19 gas) - test failing_panic_non_const_eval_str_arg ... FAILED (???, 306 gas) - test failing_panic_non_const_eval_str_empty_arg ... FAILED (???, 300 gas) - test failing_panic_non_const_eval_str_whitespace_arg ... FAILED (???, 306 gas) - test failing_panic_error_enum_arg ... FAILED (???, 403 gas) - test failing_panic_error_enum_arg_with_empty_msg ... FAILED (???, 497 gas) - test failing_panic_error_enum_arg_with_whitespace_msg ... FAILED (???, 514 gas) + test failing_panic_non_const_eval_str_arg ... FAILED (???, 297 gas) + test failing_panic_non_const_eval_str_empty_arg ... FAILED (???, 291 gas) + test failing_panic_non_const_eval_str_whitespace_arg ... FAILED (???, 297 gas) + test failing_panic_error_enum_arg ... FAILED (???, 394 gas) + test failing_panic_error_enum_arg_with_empty_msg ... FAILED (???, 486 gas) + test failing_panic_error_enum_arg_with_whitespace_msg ... FAILED (???, 503 gas) failures: test failing_revert_intrinsic, "test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/src/main.sw":34 @@ -103,7 +102,7 @@ AsciiString { data: "This is a log from the reverting test." }, log rb: 10098701 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 46, - "pc": 16900, + "pc": 16104, "ptr": 67107840, "ra": 0, "rb": 10098701174489624218 @@ -137,7 +136,7 @@ AsciiString { data: "We will get logged the asserted values and this message." } "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 64, - "pc": 16900, + "pc": 16104, "ptr": 67107840, "ra": 0, "rb": 10098701174489624218 @@ -150,7 +149,7 @@ AsciiString { data: "We will get logged the asserted values and this message." } "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 8, - "pc": 17364, + "pc": 16540, "ptr": 67106816, "ra": 0, "rb": 1515152261580153489 @@ -163,7 +162,7 @@ AsciiString { data: "We will get logged the asserted values and this message." } "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 8, - "pc": 17364, + "pc": 16540, "ptr": 67105792, "ra": 0, "rb": 1515152261580153489 @@ -190,7 +189,7 @@ AsciiString { data: "We will get logged the asserted values and this message." } "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 64, - "pc": 16900, + "pc": 16104, "ptr": 67107840, "ra": 0, "rb": 10098701174489624218 @@ -203,7 +202,7 @@ AsciiString { data: "We will get logged the asserted values and this message." } "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 8, - "pc": 17364, + "pc": 16540, "ptr": 67106816, "ra": 0, "rb": 1515152261580153489 @@ -216,7 +215,7 @@ AsciiString { data: "We will get logged the asserted values and this message." } "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 8, - "pc": 17364, + "pc": 16540, "ptr": 67105792, "ra": 0, "rb": 1515152261580153489 @@ -239,7 +238,7 @@ AsciiString { data: "This is an error message in a `require` call." }, log rb: 1 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 53, - "pc": 16900, + "pc": 16104, "ptr": 67107840, "ra": 0, "rb": 10098701174489624218 @@ -262,7 +261,7 @@ B(true), log rb: 8516346929033386016 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 9, - "pc": 14216, + "pc": 13676, "ptr": 67107840, "ra": 0, "rb": 8516346929033386016 @@ -286,7 +285,7 @@ B(true), log rb: 8516346929033386016 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 0, - "pc": 14300, + "pc": 13748, "ptr": 67107840, "ra": 0, "rb": 3330666440490685604 @@ -310,7 +309,7 @@ B(true), log rb: 8516346929033386016 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 0, - "pc": 14372, + "pc": 13808, "ptr": 67107840, "ra": 0, "rb": 3330666440490685604 @@ -352,7 +351,7 @@ AsciiString { data: "Panicked with a non-const evaluated string argument." }, lo "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 60, - "pc": 19348, + "pc": 18388, "ptr": 67107840, "ra": 0, "rb": 10098701174489624218 @@ -376,7 +375,7 @@ AsciiString { data: "" }, log rb: 10098701174489624218 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 8, - "pc": 19348, + "pc": 18388, "ptr": 67107840, "ra": 0, "rb": 10098701174489624218 @@ -400,7 +399,7 @@ AsciiString { data: " " }, log rb: 10098701174489624218 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 12, - "pc": 19348, + "pc": 18388, "ptr": 67107840, "ra": 0, "rb": 10098701174489624218 @@ -425,7 +424,7 @@ B(true), log rb: 8516346929033386016 "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 9, - "pc": 14908, + "pc": 14260, "ptr": 67107840, "ra": 0, "rb": 8516346929033386016 @@ -450,7 +449,7 @@ C(AsciiString { data: "This is an error with an empty error message." }), log rb "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 61, - "pc": 15048, + "pc": 14388, "ptr": 67107840, "ra": 0, "rb": 8516346929033386016 @@ -475,7 +474,7 @@ D(AsciiString { data: "This is an error with a whitespace error message." }), lo "id": "0000000000000000000000000000000000000000000000000000000000000000", "is": 10368, "len": 65, - "pc": 15188, + "pc": 14516, "ptr": 67107840, "ra": 0, "rb": 8516346929033386016 diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap index 3c6261138e5..9a314ba012e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc test --path test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract --release --test-threads 1 --logs --reverts exit status: 0 @@ -9,78 +8,78 @@ output: Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) Compiling library panicking_lib (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib) Compiling contract panicking_contract (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract) - Finished release [optimized + fuel] target(s) [8.68 KB] in ??? + Finished release [optimized + fuel] target(s) [7.936 KB] in ??? Running 11 tests, filtered 0 tests tested -- panicking_contract - test test_directly_panicking_method ... ok (???, 1648 gas) + test test_directly_panicking_method ... ok (???, 1595 gas) revert code: ffffffff00000000 ├─ panic message: Error C. ├─ panic value: C(true) └─ panicked in: panicking_contract@1.2.3, src/main.sw:22:9 decoded log values: C(true), log rb: 5503570629422409978 - test test_nested_panic_inlined ... ok (???, 3051 gas) + test test_nested_panic_inlined ... ok (???, 2913 gas) revert code: ffffffff00000005 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 5503570629422409978 - test test_nested_panic_inlined_same_revert_code ... ok (???, 3051 gas) + test test_nested_panic_inlined_same_revert_code ... ok (???, 2913 gas) revert code: ffffffff00000005 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 5503570629422409978 - test test_nested_panic_not_inlined ... ok (???, 3264 gas) + test test_nested_panic_not_inlined ... ok (???, 3110 gas) revert code: ffffffff00000006 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 5503570629422409978 - test test_nested_panic_not_inlined_same_revert_code ... ok (???, 3264 gas) + test test_nested_panic_not_inlined_same_revert_code ... ok (???, 3110 gas) revert code: ffffffff00000006 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 5503570629422409978 - test test_generic_panic_with_unit ... ok (???, 2136 gas) + test test_generic_panic_with_unit ... ok (???, 2035 gas) revert code: ffffffff00000004 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_unit_same_revert_code ... ok (???, 2136 gas) + test test_generic_panic_with_unit_same_revert_code ... ok (???, 2035 gas) revert code: ffffffff00000004 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_str ... ok (???, 2152 gas) + test test_generic_panic_with_str ... ok (???, 2057 gas) revert code: ffffffff00000002 ├─ panic message: generic panic with string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic with string" }, log rb: 10098701174489624218 - test test_generic_panic_with_different_str_same_revert_code ... ok (???, 1798 gas) + test test_generic_panic_with_different_str_same_revert_code ... ok (???, 1730 gas) revert code: ffffffff00000002 ├─ panic message: generic panic with different string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic with different string" }, log rb: 10098701174489624218 - test test_generic_panic_with_error_type_enum ... ok (???, 1934 gas) + test test_generic_panic_with_error_type_enum ... ok (???, 1854 gas) revert code: ffffffff00000003 ├─ panic message: Error A. ├─ panic value: A └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: A, log rb: 5503570629422409978 - test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 2112 gas) + test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 2023 gas) revert code: ffffffff00000003 ├─ panic message: Error B. ├─ panic value: B(42) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap index 78234e057c0..db5fd53c34d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc test --path test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib --release --test-threads 1 --logs --reverts exit status: 0 @@ -8,84 +7,84 @@ output: Building test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) Compiling library panicking_lib (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib) - Finished release [optimized + fuel] target(s) [6.304 KB] in ??? + Finished release [optimized + fuel] target(s) [5.68 KB] in ??? Running 18 tests, filtered 0 tests tested -- panicking_lib - test test_nested_panic_inlined ... ok (???, 837 gas) + test test_nested_panic_inlined ... ok (???, 810 gas) revert code: ffffffff00000000 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 2721958641300806892 - test test_nested_panic_inlined_same_revert_code ... ok (???, 837 gas) + test test_nested_panic_inlined_same_revert_code ... ok (???, 810 gas) revert code: ffffffff00000000 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 2721958641300806892 - test test_nested_panic_not_inlined ... ok (???, 810 gas) + test test_nested_panic_not_inlined ... ok (???, 789 gas) revert code: ffffffff00000001 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 2721958641300806892 - test test_nested_panic_not_inlined_same_revert_code ... ok (???, 810 gas) + test test_nested_panic_not_inlined_same_revert_code ... ok (???, 789 gas) revert code: ffffffff00000001 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 2721958641300806892 - test test_generic_panic_with_unit ... ok (???, 160 gas) + test test_generic_panic_with_unit ... ok (???, 154 gas) revert code: ffffffff00000002 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_unit_same_revert_code ... ok (???, 160 gas) + test test_generic_panic_with_unit_same_revert_code ... ok (???, 154 gas) revert code: ffffffff00000002 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_str ... ok (???, 294 gas) + test test_generic_panic_with_str ... ok (???, 285 gas) revert code: ffffffff00000003 ├─ panic message: generic panic with string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic with string" }, log rb: 10098701174489624218 - test test_generic_panic_with_different_str_same_revert_code ... ok (???, 294 gas) + test test_generic_panic_with_different_str_same_revert_code ... ok (???, 285 gas) revert code: ffffffff00000003 ├─ panic message: generic panic different string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic different string" }, log rb: 10098701174489624218 - test test_generic_panic_with_error_type_enum_variant ... ok (???, 317 gas) + test test_generic_panic_with_error_type_enum_variant ... ok (???, 305 gas) revert code: ffffffff00000004 ├─ panic message: Error A. ├─ panic value: A └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: A, log rb: 2721958641300806892 - test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 317 gas) + test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 305 gas) revert code: ffffffff00000004 ├─ panic message: Error A. ├─ panic value: A └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: A, log rb: 2721958641300806892 - test test_panic_without_arg ... ok (???, 160 gas) + test test_panic_without_arg ... ok (???, 154 gas) revert code: ffffffff00000005 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:113:5 decoded log values: (), log rb: 3330666440490685604 - test test_panic_with_unit ... ok (???, 160 gas) + test test_panic_with_unit ... ok (???, 154 gas) revert code: ffffffff00000006 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:118:5 @@ -95,32 +94,32 @@ A, log rb: 2721958641300806892 revert code: ffffffff00000007 ├─ panic message: panic with string └─ panicked in: panicking_lib, src/lib.sw:123:5 - test test_panic_with_error_type_enum ... ok (???, 412 gas) + test test_panic_with_error_type_enum ... ok (???, 397 gas) revert code: ffffffff00000008 ├─ panic message: Error C. ├─ panic value: C(true) └─ panicked in: panicking_lib, src/lib.sw:128:5 decoded log values: C(true), log rb: 2721958641300806892 - test test_panic_with_generic_error_type_enum ... ok (???, 348 gas) + test test_panic_with_generic_error_type_enum ... ok (???, 337 gas) revert code: ffffffff00000009 ├─ panic value: A(42) └─ panicked in: panicking_lib, src/lib.sw:133:5 decoded log values: A(42), log rb: 12408470889216862137 - test test_panic_with_nested_generic_error_type ... ok (???, 635 gas) + test test_panic_with_nested_generic_error_type ... ok (???, 616 gas) revert code: ffffffff0000000a ├─ panic value: B(B(C(true))) └─ panicked in: panicking_lib, src/lib.sw:138:5 decoded log values: B(B(C(true))), log rb: 14988555917426256081 - test test_panic_with_generic_error_type_enum_with_abi_encode ... ok (???, 348 gas) + test test_panic_with_generic_error_type_enum_with_abi_encode ... ok (???, 337 gas) revert code: ffffffff0000000b ├─ panic value: A(42) └─ panicked in: panicking_lib, src/lib.sw:143:5 decoded log values: A(42), log rb: 17388243649088655852 - test test_panic_with_nested_generic_error_type_enum_with_abi_encode ... ok (???, 635 gas) + test test_panic_with_nested_generic_error_type_enum_with_abi_encode ... ok (???, 616 gas) revert code: ffffffff0000000c ├─ panic value: B(B(C(true))) └─ panicked in: panicking_lib, src/lib.sw:148:5 diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap index 4e69ddb441b..eee575f29ec 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc test --path test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script --release --test-threads 1 --logs --reverts exit status: 0 @@ -9,78 +8,78 @@ output: Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) Compiling library panicking_lib (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib) Compiling script panicking_script (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script) - Finished release [optimized + fuel] target(s) [4.088 KB] in ??? + Finished release [optimized + fuel] target(s) [3.712 KB] in ??? Running 11 tests, filtered 0 tests tested -- panicking_script - test test_panic_in_main ... ok (???, 389 gas) + test test_panic_in_main ... ok (???, 374 gas) revert code: ffffffff00000000 ├─ panic message: Error C. ├─ panic value: C(true) └─ panicked in: panicking_script, src/main.sw:6:5 decoded log values: C(true), log rb: 5503570629422409978 - test test_nested_panic_inlined ... ok (???, 838 gas) + test test_nested_panic_inlined ... ok (???, 812 gas) revert code: ffffffff00000001 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 5503570629422409978 - test test_nested_panic_inlined_same_revert_code ... ok (???, 838 gas) + test test_nested_panic_inlined_same_revert_code ... ok (???, 812 gas) revert code: ffffffff00000001 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 5503570629422409978 - test test_nested_panic_not_inlined ... ok (???, 815 gas) + test test_nested_panic_not_inlined ... ok (???, 792 gas) revert code: ffffffff00000002 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 5503570629422409978 - test test_nested_panic_not_inlined_same_revert_code ... ok (???, 815 gas) + test test_nested_panic_not_inlined_same_revert_code ... ok (???, 792 gas) revert code: ffffffff00000002 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 5503570629422409978 - test test_generic_panic_with_unit ... ok (???, 160 gas) + test test_generic_panic_with_unit ... ok (???, 154 gas) revert code: ffffffff00000003 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_unit_same_revert_code ... ok (???, 160 gas) + test test_generic_panic_with_unit_same_revert_code ... ok (???, 154 gas) revert code: ffffffff00000003 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_str ... ok (???, 294 gas) + test test_generic_panic_with_str ... ok (???, 285 gas) revert code: ffffffff00000004 ├─ panic message: generic panic with string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic with string" }, log rb: 10098701174489624218 - test test_generic_panic_with_different_str_same_revert_code ... ok (???, 294 gas) + test test_generic_panic_with_different_str_same_revert_code ... ok (???, 285 gas) revert code: ffffffff00000004 ├─ panic message: generic panic with different string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic with different string" }, log rb: 10098701174489624218 - test test_generic_panic_with_error_type_enum ... ok (???, 312 gas) + test test_generic_panic_with_error_type_enum ... ok (???, 300 gas) revert code: ffffffff00000005 ├─ panic message: Error A. ├─ panic value: A └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: A, log rb: 5503570629422409978 - test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 371 gas) + test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 359 gas) revert code: ffffffff00000005 ├─ panic message: Error B. ├─ panic value: B(42) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/panic_in_non_statement_positions/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/panic_in_non_statement_positions/stdout.snap index fc4e56c4fb5..361ddb4a4c4 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/panic_in_non_statement_positions/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/panic_in_non_statement_positions/stdout.snap @@ -1,6 +1,5 @@ --- source: test/src/snapshot/mod.rs -assertion_line: 162 --- > forc test --path test/src/e2e_vm_tests/test_programs/should_pass/panic_in_non_statement_positions --logs --test-threads 1 exit status: 0 @@ -287,57 +286,57 @@ warning ____ Compiled library "panic_in_non_statement_positions" with 23 warnings. - Finished debug [unoptimized + fuel] target(s) [2.344 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [2.128 KB] in ??? Running 16 tests, filtered 0 tests tested -- panic_in_non_statement_positions - test in_init ... ok (???, 360 gas) + test in_init ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_array ... ok (???, 360 gas) + test in_array ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_length_1_array ... ok (???, 360 gas) + test in_length_1_array ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_length_2_array_first ... ok (???, 360 gas) + test in_length_2_array_first ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_length_2_array_second ... ok (???, 360 gas) + test in_length_2_array_second ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_tuple ... ok (???, 360 gas) + test in_tuple ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_struct ... ok (???, 360 gas) + test in_struct ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_parentheses ... ok (???, 360 gas) + test in_parentheses ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_if_condition ... ok (???, 360 gas) + test in_if_condition ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_while_condition ... ok (???, 360 gas) + test in_while_condition ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_enum ... ok (???, 360 gas) + test in_enum ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_enum_multivariant ... ok (???, 360 gas) + test in_enum_multivariant ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_fun_arg ... ok (???, 360 gas) + test in_fun_arg ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_lazy_and ... ok (???, 360 gas) + test in_lazy_and ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_lazy_or ... ok (???, 360 gas) + test in_lazy_or ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 - test in_match_scrutinee ... ok (???, 360 gas) + test in_match_scrutinee ... ok (???, 351 gas) decoded log values: E(42), log rb: 5087777005172090899 diff --git a/test/src/ir_generation/tests/asm_block.sw b/test/src/ir_generation/tests/asm_block.sw index 1c9658963b4..0f85321459e 100644 --- a/test/src/ir_generation/tests/asm_block.sw +++ b/test/src/ir_generation/tests/asm_block.sw @@ -31,13 +31,10 @@ fn main() -> u64 { // regex: IMM=i\d+ // Call get_global_gas() and then return the result of the bhei instruction. -// check: sub $$$$reta $$pc $$is -// check: srli $$$$reta $$$$reta $IMM -// check: addi $$$$reta $$$$reta $IMM -// check: jmpf $$zero $IMM +// check: jal $$$$reta $$pc $IMM // check: bhei $(ret_val=$REG) // check: ret $ret_val // The get_global_gas() function: // check: move $$$$retv $$ggas -// check: jmp $$$$reta +// check: jal $$zero $$$$reta i0 diff --git a/test/src/ir_generation/tests/fn_call.sw b/test/src/ir_generation/tests/fn_call.sw index e6eb4343b63..6e5543925a3 100644 --- a/test/src/ir_generation/tests/fn_call.sw +++ b/test/src/ir_generation/tests/fn_call.sw @@ -43,7 +43,7 @@ fn main() -> u64 { // Matching fn a() here, which just returns its arg: // // check: move $$$$retv $REG -// check: jmp $$$$reta +// check: jal $$zero $$$$reta i0 // // Matching fn b() here, which has a local bool var, initialised to false/$zero: // @@ -53,4 +53,4 @@ fn main() -> u64 { // check: sb $$$$locbase $$zero i0 // ... // check: cfsi i24 -// check: jmp $$$$reta +// check: jal $$zero $$$$reta i0 diff --git a/test/src/ir_generation/tests/fn_call_noargs_nolocals.sw b/test/src/ir_generation/tests/fn_call_noargs_nolocals.sw index 49591342ffd..568d2ea09ec 100644 --- a/test/src/ir_generation/tests/fn_call_noargs_nolocals.sw +++ b/test/src/ir_generation/tests/fn_call_noargs_nolocals.sw @@ -24,23 +24,17 @@ fn main() { // Call a function: // -// check: sub $$$$reta $$pc $$is -// check: srli $$$$reta $$$$reta $IMM -// check: addi $$$$reta $$$$reta $IMM -// check: jmpf $$zero $IMM +// check: jal $$$$reta $$pc $IMM // Function calls other function, ignores result, returns unit/$zero. // // check: move $(reta_bk=$REG) $$$$reta -// check: sub $$$$reta $$pc $$is -// check: srli $$$$reta $$$$reta $IMM -// check: addi $$$$reta $$$$reta $IMM -// check: jmpf $$zero $IMM +// check: jal $$$$reta $$pc $IMM // check: move $$$$retv $$zero // check: move $$$$reta $reta_bk -// check: jmp $$$$reta +// check: jal $$zero $$$$reta i0 // Function returns unit. // // check: move $$$$retv $$zero -// check: jmp $$$$reta +// check: jal $$zero $$$$reta i0 diff --git a/test/src/ir_generation/tests/fn_call_nolocals.sw b/test/src/ir_generation/tests/fn_call_nolocals.sw index fbdb9c1f136..bcd8a959e2e 100644 --- a/test/src/ir_generation/tests/fn_call_nolocals.sw +++ b/test/src/ir_generation/tests/fn_call_nolocals.sw @@ -33,8 +33,5 @@ fn main() -> u64 { // check: move $$$$arg0 $REG // check: move $$$$arg1 $REG // check: move $$$$arg2 $REG -// check: sub $$$$reta $$pc $$is -// check: srli $$$$reta $$$$reta i2 -// check: addi $$$$reta $$$$reta i4 -// check: jmpf $$zero $IMM +// check: jal $$$$reta $$pc i2 // check: ret $$$$retv diff --git a/test/src/ir_generation/tests/jmp_mem.sw b/test/src/ir_generation/tests/jmp_mem.sw index 7861956060b..b3178f1d615 100644 --- a/test/src/ir_generation/tests/jmp_mem.sw +++ b/test/src/ir_generation/tests/jmp_mem.sw @@ -52,4 +52,4 @@ impl MyContract for Contract { // check: lw $(target=$REG) $$hp i0 // check: sub $(jmp_target_4=$REG) $target $$is // check: divi $(jmp_target=$REG) $jmp_target_4 i4 -// check: jmp $jmp_target +// check: jmp $jmp_target From 76c00b2f5cb9bb88ef5639f0d3952be599f8208f Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 07:32:22 +0300 Subject: [PATCH 09/18] Update hardcoded test values --- forc-plugins/forc-client/tests/deploy.rs | 6 +++--- forc/tests/cli_integration.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/forc-plugins/forc-client/tests/deploy.rs b/forc-plugins/forc-client/tests/deploy.rs index 83e6c1313c9..f35d6a24fdb 100644 --- a/forc-plugins/forc-client/tests/deploy.rs +++ b/forc-plugins/forc-client/tests/deploy.rs @@ -377,7 +377,7 @@ async fn test_simple_deploy() { node.kill().unwrap(); let expected = vec![DeployedPackage::Contract(DeployedContract { id: ContractId::from_str( - "b338487c480d4c0f69351564659644023aafbcb86e8cbaccf881975a7ec51f12", + "b45b5f58ff2f05c3593ffe4241188c14644aaa1e42dc7defae12b8d09cc6a292", ) .unwrap(), proxy: None, @@ -421,7 +421,7 @@ async fn test_deploy_submit_only() { node.kill().unwrap(); let expected = vec![DeployedPackage::Contract(DeployedContract { id: ContractId::from_str( - "b338487c480d4c0f69351564659644023aafbcb86e8cbaccf881975a7ec51f12", + "b45b5f58ff2f05c3593ffe4241188c14644aaa1e42dc7defae12b8d09cc6a292", ) .unwrap(), proxy: None, @@ -468,7 +468,7 @@ async fn test_deploy_fresh_proxy() { node.kill().unwrap(); let impl_contract = DeployedPackage::Contract(DeployedContract { id: ContractId::from_str( - "b338487c480d4c0f69351564659644023aafbcb86e8cbaccf881975a7ec51f12", + "b45b5f58ff2f05c3593ffe4241188c14644aaa1e42dc7defae12b8d09cc6a292", ) .unwrap(), proxy: Some( diff --git a/forc/tests/cli_integration.rs b/forc/tests/cli_integration.rs index 44a1f7097ad..0911e2e0d5b 100644 --- a/forc/tests/cli_integration.rs +++ b/forc/tests/cli_integration.rs @@ -51,10 +51,10 @@ fn test_forc_test_raw_logs() -> Result<(), rexpect::error::Error> { // Assert that the output is correct process.exp_string(" test test_log_4")?; process.exp_string("raw logs:")?; - process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12644,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12448,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; process.exp_string(" test test_log_2")?; process.exp_string("raw logs:")?; - process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12644,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12448,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; process.process.exit()?; Ok(()) @@ -77,12 +77,12 @@ fn test_forc_test_both_logs() -> Result<(), rexpect::error::Error> { process.exp_string("decoded log values:")?; process.exp_string("4, log rb: 1515152261580153489")?; process.exp_string("raw logs:")?; - process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12644,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12448,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; process.exp_string(" test test_log_2")?; process.exp_string("decoded log values:")?; process.exp_string("2, log rb: 1515152261580153489")?; process.exp_string("raw logs:")?; - process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12644,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12448,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; process.process.exit()?; Ok(()) } From 9015f026026cc71418f7f9dc6228982095c853a2 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 07:34:17 +0300 Subject: [PATCH 10/18] ./test/update-contract-ids.sh --- .../array_of_structs_caller/src/main.sw | 2 +- .../require_contract_deployment/asset_ops_test/src/main.sw | 4 ++-- .../require_contract_deployment/bal_opcode/src/main.sw | 2 +- .../call_abi_with_tuples/src/main.sw | 2 +- .../call_basic_storage/src/main.sw | 2 +- .../call_contract_with_type_aliases/src/main.sw | 2 +- .../call_increment_contract/src/main.sw | 2 +- .../require_contract_deployment/call_storage_enum/src/main.sw | 2 +- .../require_contract_deployment/caller_auth_test/src/main.sw | 2 +- .../caller_context_test/src/main.sw | 2 +- .../nested_struct_args_caller/src/main.sw | 2 +- .../storage_access_caller/src/main.sw | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw index 1406d00d80e..fc75db79229 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw @@ -6,7 +6,7 @@ use std::hash::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x14ed3cd06c2947248f69d54bfa681fe40d26267be84df7e19e253622b7921bbe; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x334268ffc3350517784398be52cdb7daef62fc65c2dcc5f8990b96131380a479; // AUTO-CONTRACT-ID ../../test_contracts/array_of_structs_contract --release +const CONTRACT_ID = 0xf106a79029b4b175cbd3c403328947431c4cc39913d5c03bb88011a190cf7cd1; // AUTO-CONTRACT-ID ../../test_contracts/array_of_structs_contract --release fn get_address() -> Option { Some(CONTRACT_ID.into()) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw index 149d4a0a065..307328179f3 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw @@ -9,12 +9,12 @@ use test_fuel_coin_abi::*; #[cfg(experimental_new_encoding = false)] const FUEL_COIN_CONTRACT_ID = 0xec2277ebe007ade87e3d797c3b1e070dcd542d5ef8f038b471f262ef9cebc87c; #[cfg(experimental_new_encoding = true)] -const FUEL_COIN_CONTRACT_ID = 0x73afe3669fc4b788f989132b55550fdab7ae503f61df8d761e814953720d7035; // AUTO-CONTRACT-ID ../../test_contracts/test_fuel_coin_contract --release +const FUEL_COIN_CONTRACT_ID = 0x8476fc28f7ae3cad8b654176dc9f72417d4ddf0fbb9da24ade268e9ae8b82933; // AUTO-CONTRACT-ID ../../test_contracts/test_fuel_coin_contract --release #[cfg(experimental_new_encoding = false)] const BALANCE_CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df; #[cfg(experimental_new_encoding = true)] -const BALANCE_CONTRACT_ID = 0x937265d7f7db821c5a175bf3e7dd01b2822934b356c69b9b3bb87dcbd86eacab; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release +const BALANCE_CONTRACT_ID = 0x49460391f59d838a381add127bd3bc47a840c18e78d55df0d332159dfb01acfa; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release fn main() -> bool { let default_gas = 1_000_000_000_000; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw index 7c8c9ba4817..9894df5918f 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw @@ -5,7 +5,7 @@ use balance_test_abi::BalanceTest; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x937265d7f7db821c5a175bf3e7dd01b2822934b356c69b9b3bb87dcbd86eacab; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release +const CONTRACT_ID = 0x49460391f59d838a381add127bd3bc47a840c18e78d55df0d332159dfb01acfa; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release fn main() -> bool { let balance_test_contract = abi(BalanceTest, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw index 691388a4a7c..93b6083a9a4 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw @@ -6,7 +6,7 @@ use abi_with_tuples::{MyContract, Location, Person}; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xfdc14550c8aee742cd556d0ab7f378b7be0d3b1e6e086c097352e94590d4ed02; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x0bc90060d4a15254088386bfc0922a0f67666ece10ba1a45a5f42349cded949a; // AUTO-CONTRACT-ID ../../test_contracts/abi_with_tuples_contract --release +const CONTRACT_ID = 0xa2a538dd3a09bda5ded434a7c4f7b91dd1c7ac8e1a74ef14693224bf210a7474; // AUTO-CONTRACT-ID ../../test_contracts/abi_with_tuples_contract --release fn main() -> bool { let the_abi = abi(MyContract, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw index a96d415c7c7..4ca06290859 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw @@ -4,7 +4,7 @@ use basic_storage_abi::{BasicStorage, Quad}; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x94db39f409a31b9f2ebcadeea44378e419208c20de90f5d8e1e33dc1523754cb; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x3b0939d9173db0f75ff6f9a11320929a7d78ae183c5702ae4587abe590711497; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release +const CONTRACT_ID = 0xcd95389a1c96d7527caf131a0758986c6733375387b222ead91edebc2f8dbbc8; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release fn main() -> u64 { let addr = abi(BasicStorage, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw index 4c2da9732ce..476cb77a81d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw @@ -5,7 +5,7 @@ use contract_with_type_aliases_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x0cbeb6efe3104b460be769bdc4ea101ebf16ccc16f2d7b667ec3e1c7f5ce35b5; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x6cfbf04a102a4f250c63e7609fa64c25eb880d4c5f981302c863b824b245bf48; // AUTO-CONTRACT-ID ../../test_contracts/contract_with_type_aliases --release +const CONTRACT_ID = 0x1f4cb193e171334b5a19715805957e5f2076b1cb8ae2b2579eb8bbce5fce310f; // AUTO-CONTRACT-ID ../../test_contracts/contract_with_type_aliases --release fn main() { let caller = abi(MyContract, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw index 5edf1fc706c..254a6a7538e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw @@ -6,7 +6,7 @@ use dynamic_contract_call::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xd1b4047af7ef111c023ab71069e01dc2abfde487c0a0ce1268e4f447e6c6e4c2; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x4b93a566961d26a0d23702be66c33361355e338ed2ac78870c63685a39ea92a7; // AUTO-CONTRACT-ID ../../test_contracts/increment_contract --release +const CONTRACT_ID = 0xcea7265b9985e45584844a3e473f77396b9d2b19c5e82449b8d0403d6b1bc019; // AUTO-CONTRACT-ID ../../test_contracts/increment_contract --release fn main() -> bool { let the_abi = abi(Incrementor, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw index 8e36c459bf4..dde53847ab2 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw @@ -5,7 +5,7 @@ use storage_enum_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xc601d11767195485a6654d566c67774134668863d8c797a8c69e8778fb1f89e9; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x996c1d876587e975f5fe8c170d721d193335bfd4b9abb343e8ba283f7338edef; // AUTO-CONTRACT-ID ../../test_contracts/storage_enum_contract --release +const CONTRACT_ID = 0x3223c0382a2ba0ba6a98d9f389776ba7595ef7396e007911fc7ee6c2d1a465d9; // AUTO-CONTRACT-ID ../../test_contracts/storage_enum_contract --release fn main() -> u64 { let caller = abi(StorageEnum, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw index 0806c8a3157..203afd03b22 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw @@ -5,7 +5,7 @@ use auth_testing_abi::AuthTesting; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xc2eec20491b53aab7232cbd27c31d15417b4e9daf0b89c74cc242ef1295f681f; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x699395b6197070e134a0c0b3eba01411a8fc197a29c75785eb21fe65b949ad3b; // AUTO-CONTRACT-ID ../../test_contracts/auth_testing_contract --release +const CONTRACT_ID = 0x3c940400fecfb98fb14ade0e76b1f115cdb92a829c7eb0349de88326fb910fa8; // AUTO-CONTRACT-ID ../../test_contracts/auth_testing_contract --release // should be false in the case of a script fn main() -> bool { diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw index 7d0abd3077a..35c5b895910 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw @@ -6,7 +6,7 @@ use context_testing_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x6054c11cda000f5990373a4d61929396165be4dfdd61d5b7bd26da60ab0d8577; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x515e86ff9125107a493946e8607c422dc87d712443f17de0181ff6220f50c2fd; // AUTO-CONTRACT-ID ../../test_contracts/context_testing_contract --release +const CONTRACT_ID = 0x4b93165110ed4cd9b85b1f5127fa1e6330138baa82cb8fa1fe101678c6e57a78; // AUTO-CONTRACT-ID ../../test_contracts/context_testing_contract --release fn main() -> bool { let gas: u64 = u64::max(); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw index 84d41dfd3a6..20140f48667 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw @@ -5,7 +5,7 @@ use nested_struct_args_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xe63d33a1b3a6903808b379f6a41a72fa8a370e8b76626775e7d9d2f9c4c5da40; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x7c34b3ccbf7ef60a1a04015fb15e508e1ab3b9f1cda19d22b0ee94cb30815e81; // AUTO-CONTRACT-ID ../../test_contracts/nested_struct_args_contract --release +const CONTRACT_ID = 0x8dbe4018418007f05e643cbed3e95e1fce0a83f9dd651fee9ec73924f856c8bb; // AUTO-CONTRACT-ID ../../test_contracts/nested_struct_args_contract --release fn main() -> bool { let caller = abi(NestedStructArgs, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw index 416ca9d543d..05d0712a148 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw @@ -6,7 +6,7 @@ use std::hash::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x3bc28acd66d327b8c1b9624c1fabfc07e9ffa1b5d71c2832c3bfaaf8f4b805e9; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0xfdb2062a723341ffa71ad8fdf5a0abbadc484dd2beeee9a1cb2a9ccee8a9d9ba; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release +const CONTRACT_ID = 0x0a882ead5e3f817cfa18d79828117b38a4cb2f3ca82eee2fa7530665bf0f8ace; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release fn main() -> bool { let caller = abi(StorageAccess, CONTRACT_ID); From d1d4a909aee5b2c06704c48b2d901b0383d3a1ee Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 08:52:47 +0300 Subject: [PATCH 11/18] Update more hardcoded test values --- forc-plugins/forc-client/tests/deploy.rs | 2 +- .../json_abi_oracle_new_encoding.json | 32 +++++++++---------- .../json_abi_oracle_new_encoding.json | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/forc-plugins/forc-client/tests/deploy.rs b/forc-plugins/forc-client/tests/deploy.rs index f35d6a24fdb..43b146583d2 100644 --- a/forc-plugins/forc-client/tests/deploy.rs +++ b/forc-plugins/forc-client/tests/deploy.rs @@ -473,7 +473,7 @@ async fn test_deploy_fresh_proxy() { .unwrap(), proxy: Some( ContractId::from_str( - "f10ec690d2439dc4c3ec1c3dda0d97c46c7799f51f4cb6c186b3c7f014c07458", + "58d6efc775fee5c76fa4f28be28cca8c8abe360e4665f4976833dccca13f7ace", ) .unwrap(), ), diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json index 2f0f533773a..85b45d611ae 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json @@ -63,97 +63,97 @@ "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", "indirect": false, "name": "BOOL", - "offset": 5016 + "offset": 4576 }, { "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", "indirect": false, "name": "U8", - "offset": 5208 + "offset": 4768 }, { "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", "indirect": false, "name": "ANOTHER_U8", - "offset": 4944 + "offset": 4504 }, { "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef", "indirect": false, "name": "U16", - "offset": 5152 + "offset": 4712 }, { "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", "indirect": false, "name": "U32", - "offset": 5192 + "offset": 4752 }, { "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", "indirect": false, "name": "U64", - "offset": 5200 + "offset": 4760 }, { "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e", "indirect": false, "name": "U256", - "offset": 5160 + "offset": 4720 }, { "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b", "indirect": false, "name": "B256", - "offset": 4984 + "offset": 4544 }, { "concreteTypeId": "81fc10c4681a3271cf2d66b2ec6fbc8ed007a442652930844fcf11818c295bff", "indirect": false, "name": "CONFIGURABLE_STRUCT", - "offset": 5104 + "offset": 4664 }, { "concreteTypeId": "a2922861f03be8a650595dd76455b95383a61b46dd418f02607fa2e00dc39d5c", "indirect": false, "name": "CONFIGURABLE_ENUM_A", - "offset": 5024 + "offset": 4584 }, { "concreteTypeId": "a2922861f03be8a650595dd76455b95383a61b46dd418f02607fa2e00dc39d5c", "indirect": false, "name": "CONFIGURABLE_ENUM_B", - "offset": 5064 + "offset": 4624 }, { "concreteTypeId": "4926d35d1a5157936b0a29bc126b8aace6d911209a5c130e9b716b0c73643ea6", "indirect": false, "name": "ARRAY_BOOL", - "offset": 4952 + "offset": 4512 }, { "concreteTypeId": "776fb5a3824169d6736138565fdc20aad684d9111266a5ff6d5c675280b7e199", "indirect": false, "name": "ARRAY_U64", - "offset": 4960 + "offset": 4520 }, { "concreteTypeId": "c998ca9a5f221fe7b5c66ae70c8a9562b86d964408b00d17f883c906bc1fe4be", "indirect": false, "name": "TUPLE_BOOL_U64", - "offset": 5136 + "offset": 4696 }, { "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a", "indirect": false, "name": "STR_4", - "offset": 5128 + "offset": 4688 }, { "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", "indirect": false, "name": "NOT_USED", - "offset": 5120 + "offset": 4680 } ], "encodingVersion": "1", diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json index 88580a92d40..5300ce0f3bc 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json @@ -10,7 +10,7 @@ "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e", "indirect": false, "name": "SOME_U256", - "offset": 760 + "offset": 712 } ], "encodingVersion": "1", From 73dd59ec0f8848a5cefd78fad711bd01f90b7b21 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Tue, 1 Jul 2025 08:54:58 +0300 Subject: [PATCH 12/18] Change back to debug assert --- .../asm_generation/fuel/allocated_abstract_instruction_set.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index 8c2211ba598..e63d5da0dda 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -246,8 +246,7 @@ impl AllocatedAbstractInstructionSet { owning_span, ) }; - assert_eq!(far_jump_sizes.get(&op_idx).copied().unwrap_or(1), op_size); - assert_eq!(ops.len() as u64, op_size); + debug_assert_eq!(ops.len() as u64, op_size); realized_ops.extend(ops); } ControlFlowOp::DataSectionOffsetPlaceholder => { From d139c3fef65b27f8cb77fe0abce6403f073c7de9 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Thu, 3 Jul 2025 12:05:46 +0300 Subject: [PATCH 13/18] First iteration --- forc-pkg/src/pkg.rs | 10 +- .../src/server/handlers/handle_variables.rs | 4 + sway-core/src/asm_generation/finalized_asm.rs | 25 +- .../allocated_abstract_instruction_set.rs | 8 +- .../src/asm_generation/fuel/data_section.rs | 197 +++++++++------ .../asm_generation/fuel/fuel_asm_builder.rs | 24 +- .../optimizations/const_indexed_aggregates.rs | 2 +- .../asm_generation/fuel/programs/abstract.rs | 2 +- sway-core/src/asm_lang/allocated_ops.rs | 227 ++++++++++++------ sway-core/src/asm_lang/mod.rs | 4 + sway-core/src/asm_lang/virtual_ops.rs | 68 ++++++ sway-ir/src/irtype.rs | 19 +- 12 files changed, 406 insertions(+), 184 deletions(-) diff --git a/forc-pkg/src/pkg.rs b/forc-pkg/src/pkg.rs index 1c8d3fdd5cc..f91896746fb 100644 --- a/forc-pkg/src/pkg.rs +++ b/forc-pkg/src/pkg.rs @@ -1947,12 +1947,12 @@ fn report_assembly_information( // https://github.com/FuelLabs/sway/blob/afd6a6709e7cb11c676059a5004012cc466e653b/sway-core/src/asm_generation/fuel/data_section.rs#L147 fn calculate_entry_size(entry: &sway_core::asm_generation::Entry) -> u64 { match &entry.value { - sway_core::asm_generation::Datum::Byte(value) => std::mem::size_of_val(value) as u64, + sway_core::asm_generation::Datum::U8(value) => std::mem::size_of_val(value) as u64, + sway_core::asm_generation::Datum::U16(value) => std::mem::size_of_val(value) as u64, + sway_core::asm_generation::Datum::U32(value) => std::mem::size_of_val(value) as u64, + sway_core::asm_generation::Datum::U64(value) => std::mem::size_of_val(value) as u64, - sway_core::asm_generation::Datum::Word(value) => std::mem::size_of_val(value) as u64, - - sway_core::asm_generation::Datum::ByteArray(bytes) - | sway_core::asm_generation::Datum::Slice(bytes) => { + sway_core::asm_generation::Datum::ByRef(bytes) => { if bytes.len() % 8 == 0 { bytes.len() as u64 } else { diff --git a/forc-plugins/forc-debug/src/server/handlers/handle_variables.rs b/forc-plugins/forc-debug/src/server/handlers/handle_variables.rs index 498413a0a80..185d4cc563e 100644 --- a/forc-plugins/forc-debug/src/server/handlers/handle_variables.rs +++ b/forc-plugins/forc-debug/src/server/handlers/handle_variables.rs @@ -169,8 +169,12 @@ fn ra(instruction: Instruction) -> Option { Instruction::XORI(op) => Some(op.ra()), Instruction::JNEI(op) => Some(op.ra()), Instruction::LB(op) => Some(op.ra()), + Instruction::LQW(op) => Some(op.ra()), + Instruction::LHW(op) => Some(op.ra()), Instruction::LW(op) => Some(op.ra()), Instruction::SB(op) => Some(op.ra()), + Instruction::SQW(op) => Some(op.ra()), + Instruction::SHW(op) => Some(op.ra()), Instruction::SW(op) => Some(op.ra()), Instruction::MCPI(op) => Some(op.ra()), Instruction::GTF(op) => Some(op.ra()), diff --git a/sway-core/src/asm_generation/finalized_asm.rs b/sway-core/src/asm_generation/finalized_asm.rs index bf94f4ce522..6a350e6815e 100644 --- a/sway-core/src/asm_generation/finalized_asm.rs +++ b/sway-core/src/asm_generation/finalized_asm.rs @@ -314,11 +314,11 @@ fn to_bytecode_mut( print!("{}{:#010x} ", " ".repeat(indentation), offset); match &pair.value { - Datum::Byte(w) => println!(".byte i{w}, as hex {w:02X}"), - Datum::Word(w) => { - println!(".word i{w}, as hex be bytes ({:02X?})", w.to_be_bytes()) - } - Datum::ByteArray(bs) => { + Datum::U8(v) => println!(".byte i{}, as hex {:02X}", v, v), + Datum::U16(v) => println!(".quarterword i{}, as hex {:02X?}", v, v.to_be_bytes()), + Datum::U32(v) => println!(".halfword i{}, as hex {:02X?}", v, v.to_be_bytes()), + Datum::U64(v) => println!(".word i{}, as hex {:02X?}", v, v.to_be_bytes()), + Datum::ByRef(bs) => { print!(".bytes as hex ({bs:02X?}), len i{}, as ascii \"", bs.len()); for b in bs { @@ -333,21 +333,6 @@ fn to_bytecode_mut( } println!("\""); } - Datum::Slice(bs) => { - print!(".slice as hex ({bs:02X?}), len i{}, as ascii \"", bs.len()); - - for b in bs { - print!( - "{}", - if *b == b' ' || b.is_ascii_graphic() { - *b as char - } else { - '.' - } - ); - } - println!("\""); - } Datum::Collection(els) => { println!(".collection"); for e in els { diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index e63d5da0dda..d489b39352c 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -607,7 +607,7 @@ pub(crate) fn compile_jump( if curr_offset > target_offset { let delta = curr_offset - target_offset - 1; return if far { - let data_id = data_section.insert_data_value(Entry::new_word( + let data_id = data_section.insert_data_value(Entry::new_min_int( delta + 1, // +1 since the load instruction must be skipped as well EntryName::NonConfigurable, None, @@ -662,7 +662,7 @@ pub(crate) fn compile_jump( let delta = target_offset - curr_offset - 1; if far { - let data_id = data_section.insert_data_value(Entry::new_word( + let data_id = data_section.insert_data_value(Entry::new_min_int( delta - 1, EntryName::NonConfigurable, None, @@ -779,7 +779,7 @@ pub(crate) fn compile_call_inner( } // if the offset is too large for MOVI, use data section to store the full offset. - let data_id = data_section.insert_data_value(Entry::new_word( + let data_id = data_section.insert_data_value(Entry::new_min_int( delta_instr, EntryName::NonConfigurable, None, @@ -886,7 +886,7 @@ pub(crate) fn compile_call_inner( } // And lastly, fall back to the data section backed approach. - let data_id = data_section.insert_data_value(Entry::new_word( + let data_id = data_section.insert_data_value(Entry::new_min_int( delta_instr, EntryName::NonConfigurable, None, diff --git a/sway-core/src/asm_generation/fuel/data_section.rs b/sway-core/src/asm_generation/fuel/data_section.rs index d4edb72d657..7c6434b413c 100644 --- a/sway-core/src/asm_generation/fuel/data_section.rs +++ b/sway-core/src/asm_generation/fuel/data_section.rs @@ -31,27 +31,47 @@ pub struct Entry { #[derive(Clone, Debug, serde::Serialize)] pub enum Datum { - Byte(u8), - Word(u64), - ByteArray(Vec), - Slice(Vec), + /// A single byte, loaded into a register. + U8(u8), + /// A quarterword, loaded into a register. + U16(u16), + /// A halfword, loaded into a register. + U32(u32), + /// A word, loaded into a register. + U64(u64), + /// Data behind a pointer. + ByRef(Vec), + /// Collection of entries. Collection(Vec), } impl Entry { - pub(crate) fn new_byte(value: u8, name: EntryName, padding: Option) -> Entry { - Entry { - value: Datum::Byte(value), - padding: padding.unwrap_or(Padding::default_for_u8(value)), - name, - } - } - - pub(crate) fn new_word(value: u64, name: EntryName, padding: Option) -> Entry { - Entry { - value: Datum::Word(value), - padding: padding.unwrap_or(Padding::default_for_u64(value)), - name, + /// Creates smallest integer entry that can hold the value. + pub(crate) fn new_min_int(value: u64, name: EntryName, padding: Option) -> Entry { + if value <= u8::MAX as u64 { + Self { + value: Datum::U8(value as u8), + padding: padding.unwrap_or(Padding::default_for_u8(value as u8)), + name, + } + } else if value <= u16::MAX as u64 { + Self { + value: Datum::U16(value as u16), + padding: padding.unwrap_or(Padding::default_for_u16(value as u16)), + name, + } + } else if value <= u32::MAX as u64 { + Self { + value: Datum::U32(value as u32), + padding: padding.unwrap_or(Padding::default_for_u32(value as u32)), + name, + } + } else { + Self { + value: Datum::U64(value), + padding: padding.unwrap_or(Padding::default_for_u64(value)), + name, + } } } @@ -62,15 +82,7 @@ impl Entry { ) -> Entry { Entry { padding: padding.unwrap_or(Padding::default_for_byte_array(&bytes)), - value: Datum::ByteArray(bytes), - name, - } - } - - pub(crate) fn new_slice(bytes: Vec, name: EntryName, padding: Option) -> Entry { - Entry { - padding: padding.unwrap_or(Padding::default_for_byte_array(&bytes)), - value: Datum::Slice(bytes), + value: Datum::ByRef(bytes), name, } } @@ -110,13 +122,41 @@ impl Entry { // Not an enum, no more special handling required. match &constant.value { - ConstantValue::Undef | ConstantValue::Unit => Entry::new_byte(0, name, padding), - ConstantValue::Bool(value) => Entry::new_byte(u8::from(*value), name, padding), + ConstantValue::Undef | ConstantValue::Unit => Entry { + value: Datum::U8(0), + padding: padding.unwrap_or(Padding::default_for_u8(0)), + name, + }, + ConstantValue::Bool(value) => Entry { + value: Datum::U8(*value as u8), + padding: padding.unwrap_or(Padding::default_for_u8(0)), + name, + }, ConstantValue::Uint(value) => { if constant.ty.is_uint8(context) { - Entry::new_byte(*value as u8, name, padding) + Entry { + value: Datum::U8(*value as u8), + padding: Padding::default_for_u8(0), + name, + } + } else if constant.ty.is_uint16(context) { + Entry { + value: Datum::U16(*value as u16), + padding: Padding::default_for_u16(0), + name, + } + } else if constant.ty.is_uint32(context) { + Entry { + value: Datum::U32(*value as u32), + padding: Padding::default_for_u32(0), + name, + } } else { - Entry::new_word(*value, name, padding) + Entry { + value: Datum::U64(*value as u64), + padding: Padding::default_for_u64(0), + name, + } } } ConstantValue::U256(value) => { @@ -126,31 +166,29 @@ impl Entry { Entry::new_byte_array(value.to_be_bytes().to_vec(), name, padding) } ConstantValue::String(bytes) => Entry::new_byte_array(bytes.clone(), name, padding), - ConstantValue::Array(_) => Entry::new_collection( - constant - .array_elements_with_padding(context) - .expect("Constant is an array.") + ConstantValue::Array(elements) => Entry::new_collection( + elements .into_iter() - .map(|(elem, padding)| { + .map(|elem| { Entry::from_constant(context, elem, EntryName::NonConfigurable, padding) }) .collect(), name, padding, ), - ConstantValue::Struct(_) => Entry::new_collection( - constant - .struct_fields_with_padding(context) - .expect("Constant is a struct.") + ConstantValue::Struct(fields) => Entry::new_collection( + fields .into_iter() - .map(|(elem, padding)| { + .map(|elem| { Entry::from_constant(context, elem, EntryName::NonConfigurable, padding) }) .collect(), name, padding, ), - ConstantValue::RawUntypedSlice(bytes) => Entry::new_slice(bytes.clone(), name, padding), + ConstantValue::RawUntypedSlice(bytes) => { + Entry::new_byte_array(bytes.clone(), name, padding) + } ConstantValue::Reference(_) => { todo!("Constant references are currently not supported.") } @@ -164,10 +202,12 @@ impl Entry { pub(crate) fn to_bytes(&self) -> Vec { // Get the big-endian byte representation of the basic value. let bytes = match &self.value { - Datum::Byte(value) => vec![*value], - Datum::Word(value) => value.to_be_bytes().to_vec(), - Datum::ByteArray(bytes) | Datum::Slice(bytes) if bytes.len() % 8 == 0 => bytes.clone(), - Datum::ByteArray(bytes) | Datum::Slice(bytes) => bytes + Datum::U8(value) => vec![*value], + Datum::U16(value) => value.to_be_bytes().to_vec(), + Datum::U32(value) => value.to_be_bytes().to_vec(), + Datum::U64(value) => value.to_be_bytes().to_vec(), + Datum::ByRef(bytes) if bytes.len() % 8 == 0 => bytes.clone(), + Datum::ByRef(bytes) => bytes .iter() .chain([0; 8].iter()) .copied() @@ -188,19 +228,20 @@ impl Entry { } pub(crate) fn has_copy_type(&self) -> bool { - matches!(self.value, Datum::Word(_) | Datum::Byte(_)) - } - - pub(crate) fn is_byte(&self) -> bool { - matches!(self.value, Datum::Byte(_)) + matches!( + self.value, + Datum::U64(_) | Datum::U32(_) | Datum::U16(_) | Datum::U8(_) + ) } pub(crate) fn equiv(&self, entry: &Entry) -> bool { fn equiv_data(lhs: &Datum, rhs: &Datum) -> bool { match (lhs, rhs) { - (Datum::Byte(l), Datum::Byte(r)) => l == r, - (Datum::Word(l), Datum::Word(r)) => l == r, - (Datum::ByteArray(l), Datum::ByteArray(r)) => l == r, + (Datum::U8(l), Datum::U8(r)) => l == r, + (Datum::U16(l), Datum::U16(r)) => l == r, + (Datum::U32(l), Datum::U32(r)) => l == r, + (Datum::U64(l), Datum::U64(r)) => l == r, + (Datum::ByRef(l), Datum::ByRef(r)) => l == r, (Datum::Collection(l), Datum::Collection(r)) => { l.len() == r.len() && l.iter() @@ -219,7 +260,7 @@ impl Entry { } } -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub enum DataIdEntryKind { NonConfigurable, Configurable, @@ -235,7 +276,7 @@ impl fmt::Display for DataIdEntryKind { } /// An address which refers to a value in the data section of the asm. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub(crate) struct DataId { pub(crate) idx: u32, pub(crate) kind: DataIdEntryKind, @@ -278,7 +319,7 @@ impl DataSection { } /// Get entry at id - fn get(&self, id: &DataId) -> Option<&Entry> { + pub(crate) fn get(&self, id: &DataId) -> Option<&Entry> { match id.kind { DataIdEntryKind::NonConfigurable => self.non_configurables.get(id.idx as usize), DataIdEntryKind::Configurable => self.configurables.get(id.idx as usize), @@ -319,11 +360,6 @@ impl DataSection { self.get(id).map(|entry| entry.has_copy_type()) } - /// Returns whether a specific [DataId] value is a byte entry. - pub(crate) fn is_byte(&self, id: &DataId) -> Option { - self.get(id).map(|entry| entry.is_byte()) - } - /// When generating code, sometimes a hard-coded data pointer is needed to reference /// static values that have a length longer than one word. /// This method appends pointers to the end of the data section (thus, not altering the data @@ -332,7 +368,7 @@ impl DataSection { /// relative to the current (load) instruction. pub(crate) fn append_pointer(&mut self, pointer_value: u64) -> DataId { // The 'pointer' is just a literal 64 bit address. - let data_id = self.insert_data_value(Entry::new_word( + let data_id = self.insert_data_value(Entry::new_min_int( pointer_value, EntryName::NonConfigurable, None, @@ -376,19 +412,21 @@ impl DataSection { } } - // If the stored data is Datum::Word, return the inner value. - pub(crate) fn get_data_word(&self, data_id: &DataId) -> Option { - let value_pairs = match data_id.kind { - DataIdEntryKind::NonConfigurable => &self.non_configurables, - DataIdEntryKind::Configurable => &self.configurables, - }; - value_pairs.get(data_id.idx as usize).and_then(|entry| { - if let Datum::Word(w) = entry.value { - Some(w) - } else { - None - } - }) + /// When a load from data section is realized and targets a (register-placeable) copy type, + /// this is the value that will be loaded into the register. + /// For non-copy types or configurable values, returns `None` instead. + pub(crate) fn get_const_reg_value(&self, data_id: DataId) -> Option { + let entry = self.get(&data_id)?; + if matches!(entry.name, EntryName::Configurable(_)) { + return None; + } + match &entry.value { + Datum::U8(v) => Some(*v as u64), + Datum::U16(v) => Some(*v as u64), + Datum::U32(v) => Some(*v as u64), + Datum::U64(v) => Some(*v), + _ => None, + } } } @@ -396,10 +434,11 @@ impl fmt::Display for DataSection { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn display_entry(datum: &Datum) -> String { match datum { - Datum::Byte(w) => format!(".byte {w}"), - Datum::Word(w) => format!(".word {w}"), - Datum::ByteArray(bs) => display_bytes_for_data_section(bs, ".bytes"), - Datum::Slice(bs) => display_bytes_for_data_section(bs, ".slice"), + Datum::U8(v) => format!(".byte {v}"), + Datum::U16(v) => format!(".quarterword {v}"), + Datum::U32(v) => format!(".word {v}"), + Datum::U64(v) => format!(".half {v}"), + Datum::ByRef(bs) => display_bytes_for_data_section(bs, ".bytes"), Datum::Collection(els) => format!( ".collection {{ {} }}", els.iter() diff --git a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs index 08b86dcd2e2..b2c52277f5e 100644 --- a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs +++ b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs @@ -1464,6 +1464,28 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { owning_span, }); } + 2 => { + self.cur_bytecode.push(Op { + opcode: Either::Left(VirtualOp::LQW( + instr_reg.clone(), + src_reg, + VirtualImmediate12::new_unchecked(0, "Zero must fit in 12 bits"), + )), + comment: "load quadword".into(), + owning_span, + }); + } + 4 => { + self.cur_bytecode.push(Op { + opcode: Either::Left(VirtualOp::LHW( + instr_reg.clone(), + src_reg, + VirtualImmediate12::new_unchecked(0, "Zero must fit in 12 bits"), + )), + comment: "load halfword".into(), + owning_span, + }); + } 8.. => { self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::LW( @@ -2252,7 +2274,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { } } else { let comment = comment.into(); - let data_id = self.data_section.insert_data_value(Entry::new_word( + let data_id = self.data_section.insert_data_value(Entry::new_min_int( imm, EntryName::NonConfigurable, None, diff --git a/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs b/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs index b2c68109fc9..9dd6ebadfae 100644 --- a/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs +++ b/sway-core/src/asm_generation/fuel/optimizations/const_indexed_aggregates.rs @@ -125,7 +125,7 @@ impl AbstractInstructionSet { } } VirtualOp::LoadDataId(dest, data_id) => { - if let Some(c) = data_section.get_data_word(data_id) { + if let Some(c) = data_section.get_const_reg_value(*data_id) { reg_contents.insert(dest.clone(), RegContents::Constant(c)); } else { reg_contents.remove(dest); diff --git a/sway-core/src/asm_generation/fuel/programs/abstract.rs b/sway-core/src/asm_generation/fuel/programs/abstract.rs index fe95b4ec993..67e6b53ec01 100644 --- a/sway-core/src/asm_generation/fuel/programs/abstract.rs +++ b/sway-core/src/asm_generation/fuel/programs/abstract.rs @@ -311,7 +311,7 @@ impl AbstractProgram { }; // Put the selector in the data section. - let data_label = self.data_section.insert_data_value(Entry::new_word( + let data_label = self.data_section.insert_data_value(Entry::new_min_int( u32::from_be_bytes(selector) as u64, EntryName::NonConfigurable, None, diff --git a/sway-core/src/asm_lang/allocated_ops.rs b/sway-core/src/asm_lang/allocated_ops.rs index 3172f09fc9f..1cb8b0fbae1 100644 --- a/sway-core/src/asm_lang/allocated_ops.rs +++ b/sway-core/src/asm_lang/allocated_ops.rs @@ -11,9 +11,12 @@ use super::*; use crate::{ - asm_generation::fuel::{ - compiler_constants::DATA_SECTION_REGISTER, - data_section::{DataId, DataSection}, + asm_generation::{ + fuel::{ + compiler_constants::DATA_SECTION_REGISTER, + data_section::{DataId, DataSection}, + }, + Datum, }, fuel_prelude::fuel_asm::{self, op}, }; @@ -161,6 +164,8 @@ pub(crate) enum AllocatedInstruction { CFE(AllocatedRegister), CFS(AllocatedRegister), LB(AllocatedRegister, AllocatedRegister, VirtualImmediate12), + LQW(AllocatedRegister, AllocatedRegister, VirtualImmediate12), + LHW(AllocatedRegister, AllocatedRegister, VirtualImmediate12), LW(AllocatedRegister, AllocatedRegister, VirtualImmediate12), MCL(AllocatedRegister, AllocatedRegister), MCLI(AllocatedRegister, VirtualImmediate18), @@ -177,6 +182,8 @@ pub(crate) enum AllocatedInstruction { POPH(VirtualImmediate24), POPL(VirtualImmediate24), SB(AllocatedRegister, AllocatedRegister, VirtualImmediate12), + SQW(AllocatedRegister, AllocatedRegister, VirtualImmediate12), + SHW(AllocatedRegister, AllocatedRegister, VirtualImmediate12), SW(AllocatedRegister, AllocatedRegister, VirtualImmediate12), /* Contract Instructions */ @@ -366,6 +373,8 @@ impl AllocatedInstruction { CFE(_r1) => vec![], CFS(_r1) => vec![], LB(r1, _r2, _i) => vec![r1], + LQW(r1, _r2, _i) => vec![r1], + LHW(r1, _r2, _i) => vec![r1], LW(r1, _r2, _i) => vec![r1], MCL(_r1, _r2) => vec![], MCLI(_r1, _imm) => vec![], @@ -376,6 +385,8 @@ impl AllocatedInstruction { panic!("Cannot determine defined registers for register PUSH/POP instructions") } SB(_r1, _r2, _i) => vec![], + SQW(_r1, _r2, _i) => vec![], + SHW(_r1, _r2, _i) => vec![], SW(_r1, _r2, _i) => vec![], /* Contract Instructions */ @@ -498,6 +509,8 @@ impl fmt::Display for AllocatedInstruction { CFE(a) => write!(fmtr, "cfe {a}"), CFS(a) => write!(fmtr, "cfs {a}"), LB(a, b, c) => write!(fmtr, "lb {a} {b} {c}"), + LQW(a, b, c) => write!(fmtr, "lqw {a} {b} {c}"), + LHW(a, b, c) => write!(fmtr, "lhw {a} {b} {c}"), LW(a, b, c) => write!(fmtr, "lw {a} {b} {c}"), MCL(a, b) => write!(fmtr, "mcl {a} {b}"), MCLI(a, b) => write!(fmtr, "mcli {a} {b}"), @@ -509,6 +522,8 @@ impl fmt::Display for AllocatedInstruction { POPH(mask) => write!(fmtr, "poph {mask}"), POPL(mask) => write!(fmtr, "popl {mask}"), SB(a, b, c) => write!(fmtr, "sb {a} {b} {c}"), + SQW(a, b, c) => write!(fmtr, "sqw {a} {b} {c}"), + SHW(a, b, c) => write!(fmtr, "shw {a} {b} {c}"), SW(a, b, c) => write!(fmtr, "sw {a} {b} {c}"), /* Contract Instructions */ @@ -704,6 +719,8 @@ impl AllocatedOp { CFE(a) => op::CFE::new(a.to_reg_id()).into(), CFS(a) => op::CFS::new(a.to_reg_id()).into(), LB(a, b, c) => op::LB::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), + LQW(a, b, c) => op::LQW::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), + LHW(a, b, c) => op::LHW::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), LW(a, b, c) => op::LW::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), MCL(a, b) => op::MCL::new(a.to_reg_id(), b.to_reg_id()).into(), MCLI(a, b) => op::MCLI::new(a.to_reg_id(), b.value().into()).into(), @@ -717,6 +734,8 @@ impl AllocatedOp { POPH(mask) => op::POPH::new(mask.value().into()).into(), POPL(mask) => op::POPL::new(mask.value().into()).into(), SB(a, b, c) => op::SB::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), + SQW(a, b, c) => op::SQW::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), + SHW(a, b, c) => op::SHW::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), SW(a, b, c) => op::SW::new(a.to_reg_id(), b.to_reg_id(), c.value().into()).into(), /* Contract Instructions */ @@ -863,81 +882,145 @@ fn realize_load( offset_to_data_section: u64, offset_from_instr_start: u64, ) -> Vec { - // if this data is larger than a word, instead of loading the data directly - // into the register, we want to load a pointer to the data into the register - // this appends onto the data section and mutates it by adding the pointer as a literal - let has_copy_type = data_section.has_copy_type(data_id).expect( + let entry = data_section.get(data_id).expect( "Internal miscalculation in data section -- data id did not match up to any actual data", ); - - let is_byte = data_section.is_byte(data_id).expect( - "Internal miscalculation in data section -- data id did not match up to any actual data", - ); - - // all data is word-aligned right now, and `offset_to_id` returns the offset in bytes let offset_bytes = data_section.data_id_to_offset(data_id) as u64; - assert!( - offset_bytes % 8 == 0, - "Internal miscalculation in data section -- data offset is not aligned to a word", - ); - let offset_words = offset_bytes / 8; - let imm = VirtualImmediate12::new( - if is_byte { offset_bytes } else { offset_words }, - Span::new(" ".into(), 0, 0, None).unwrap(), - ); - let offset = match imm { - Ok(value) => value, - Err(_) => panic!( - "Unable to offset into the data section more than 2^12 bits. \ - Unsupported data section length: {} words.", - offset_words - ), - }; - - if !has_copy_type { - // load the pointer itself into the register. `offset_to_data_section` is in bytes. - // The -4 is because $pc is added in the *next* instruction. - let pointer_offset_from_current_instr = - offset_to_data_section - offset_from_instr_start + offset_bytes - 4; - - // insert the pointer as bytes as a new data section entry at the end of the data - let data_id_for_pointer = data_section - .data_id_of_pointer(pointer_offset_from_current_instr) - .expect("Pointer offset must be in data_section"); - - // now load the pointer we just created into the `dest`ination - let mut buf = Vec::with_capacity(2); - buf.append(&mut realize_load( - dest, - &data_id_for_pointer, - data_section, - offset_to_data_section, - offset_from_instr_start, - )); - // add $pc to the pointer since it is relative to the current instruction. - buf.push( - fuel_asm::op::ADD::new( + match entry.value { + Datum::U8(_) => { + let Ok(imm) = VirtualImmediate12::new(offset_bytes, Span::dummy()) else { + panic!( + "Unable to offset into the data section more than 2^12 bits. \ + Unsupported data section length: {} bytes.", + offset_bytes + ); + }; + vec![fuel_asm::op::LB::new( dest.to_reg_id(), + fuel_asm::RegId::new(DATA_SECTION_REGISTER), + imm.value().into(), + ) + .into()] + } + Datum::U16(_) => { + assert!( + offset_bytes % 2 == 0, + "Internal miscalculation in data section -- invalid alignment for u16 data", + ); + let Ok(imm) = VirtualImmediate12::new(offset_bytes / 2, Span::dummy()) else { + panic!( + "Unable to offset into the data section more than 2^12 bits. \ + Unsupported data section length: {} bytes.", + offset_bytes + ); + }; + vec![fuel_asm::op::LQW::new( dest.to_reg_id(), - ConstantRegister::ProgramCounter.to_reg_id(), + fuel_asm::RegId::new(DATA_SECTION_REGISTER), + imm.value().into(), ) - .into(), - ); - buf - } else if is_byte { - vec![fuel_asm::op::LB::new( - dest.to_reg_id(), - fuel_asm::RegId::new(DATA_SECTION_REGISTER), - offset.value().into(), - ) - .into()] - } else { - vec![fuel_asm::op::LW::new( - dest.to_reg_id(), - fuel_asm::RegId::new(DATA_SECTION_REGISTER), - offset.value().into(), - ) - .into()] + .into()] + } + Datum::U32(_) => { + assert!( + offset_bytes % 4 == 0, + "Internal miscalculation in data section -- invalid alignment for u16 data", + ); + let Ok(imm) = VirtualImmediate12::new(offset_bytes / 4, Span::dummy()) else { + panic!( + "Unable to offset into the data section more than 2^12 bits. \ + Unsupported data section length: {} bytes.", + offset_bytes + ); + }; + vec![fuel_asm::op::LHW::new( + dest.to_reg_id(), + fuel_asm::RegId::new(DATA_SECTION_REGISTER), + imm.value().into(), + ) + .into()] + } + Datum::U64(_) => { + assert!( + offset_bytes % 8 == 0, + "Internal miscalculation in data section -- invalid alignment for u16 data", + ); + let Ok(imm) = VirtualImmediate12::new(offset_bytes / 8, Span::dummy()) else { + panic!( + "Unable to offset into the data section more than 2^12 bits. \ + Unsupported data section length: {} bytes.", + offset_bytes + ); + }; + vec![fuel_asm::op::LW::new( + dest.to_reg_id(), + fuel_asm::RegId::new(DATA_SECTION_REGISTER), + imm.value().into(), + ) + .into()] + } + _ => { + // if this data is larger than a word, instead of loading the data directly + // into the register, we want to load a pointer to the data into the register + // this appends onto the data section and mutates it by adding the pointer as a literal + + // load the pointer itself into the register. `offset_to_data_section` is in bytes. + // The -4 is because $pc is added in the *next* instruction. + let pointer_offset_from_current_instr = + offset_to_data_section - offset_from_instr_start + offset_bytes - 4; + + // insert the pointer as bytes as a new data section entry at the end of the data + let data_id_for_pointer = data_section + .data_id_of_pointer(pointer_offset_from_current_instr) + .expect("Pointer offset must be in data_section"); + + // now load the pointer we just created into the `dest`ination + let mut buf = Vec::with_capacity(2); + buf.append(&mut realize_load( + dest, + &data_id_for_pointer, + data_section, + offset_to_data_section, + offset_from_instr_start, + )); + // add $pc to the pointer since it is relative to the current instruction. + buf.push( + fuel_asm::op::ADD::new( + dest.to_reg_id(), + dest.to_reg_id(), + ConstantRegister::ProgramCounter.to_reg_id(), + ) + .into(), + ); + buf + } } + + // let is_byte = data_section.is_byte(data_id).expect( + // "Internal miscalculation in data section -- data id did not match up to any actual data", + // ); + + // let imm = VirtualImmediate12::new( + // if is_byte { offset_bytes } else { offset_words }, + // Span::new(" ".into(), 0, 0, None).unwrap(), + // ); + // let offset = match imm { + // Ok(value) => value, + // Err(_) => panic!( + // "Unable to offset into the data section more than 2^12 bits. \ + // Unsupported data section length: {} words.", + // offset_words + // ), + // }; + + // if is_byte { + // } else { + // vec![fuel_asm::op::LW::new( + // dest.to_reg_id(), + // fuel_asm::RegId::new(DATA_SECTION_REGISTER), + // offset.value().into(), + // ) + // .into()] + // } } diff --git a/sway-core/src/asm_lang/mod.rs b/sway-core/src/asm_lang/mod.rs index 14f22fd6bef..255e73e94f6 100644 --- a/sway-core/src/asm_lang/mod.rs +++ b/sway-core/src/asm_lang/mod.rs @@ -1194,6 +1194,8 @@ impl fmt::Display for VirtualOp { CFE(_sp, a) => write!(fmtr, "cfe {a}"), CFS(_sp, a) => write!(fmtr, "cfs {a}"), LB(a, b, c) => write!(fmtr, "lb {a} {b} {c}"), + LQW(a, b, c) => write!(fmtr, "lqw {a} {b} {c}"), + LHW(a, b, c) => write!(fmtr, "lhw {a} {b} {c}"), LW(a, b, c) => write!(fmtr, "lw {a} {b} {c}"), MCL(a, b) => write!(fmtr, "mcl {a} {b}"), MCLI(a, b) => write!(fmtr, "mcli {a} {b}"), @@ -1201,6 +1203,8 @@ impl fmt::Display for VirtualOp { MCPI(a, b, c) => write!(fmtr, "mcpi {a} {b} {c}"), MEQ(a, b, c, d) => write!(fmtr, "meq {a} {b} {c} {d}"), SB(a, b, c) => write!(fmtr, "sb {a} {b} {c}"), + SQW(a, b, c) => write!(fmtr, "sqw {a} {b} {c}"), + SHW(a, b, c) => write!(fmtr, "shw {a} {b} {c}"), SW(a, b, c) => write!(fmtr, "sw {a} {b} {c}"), /* Contract Instructions */ diff --git a/sway-core/src/asm_lang/virtual_ops.rs b/sway-core/src/asm_lang/virtual_ops.rs index 135567e4090..659977cc50c 100644 --- a/sway-core/src/asm_lang/virtual_ops.rs +++ b/sway-core/src/asm_lang/virtual_ops.rs @@ -116,6 +116,8 @@ pub(crate) enum VirtualOp { CFE(VirtualRegister, VirtualRegister), CFS(VirtualRegister, VirtualRegister), LB(VirtualRegister, VirtualRegister, VirtualImmediate12), + LQW(VirtualRegister, VirtualRegister, VirtualImmediate12), + LHW(VirtualRegister, VirtualRegister, VirtualImmediate12), LW(VirtualRegister, VirtualRegister, VirtualImmediate12), MCL(VirtualRegister, VirtualRegister), MCLI(VirtualRegister, VirtualImmediate18), @@ -128,6 +130,8 @@ pub(crate) enum VirtualOp { VirtualRegister, ), SB(VirtualRegister, VirtualRegister, VirtualImmediate12), + SQW(VirtualRegister, VirtualRegister, VirtualImmediate12), + SHW(VirtualRegister, VirtualRegister, VirtualImmediate12), SW(VirtualRegister, VirtualRegister, VirtualImmediate12), /* Contract Instructions */ @@ -316,6 +320,8 @@ impl VirtualOp { CFE(sp, r1) => vec![sp, r1], CFS(sp, r1) => vec![sp, r1], LB(r1, r2, _i) => vec![r1, r2], + LQW(r1, r2, _i) => vec![r1, r2], + LHW(r1, r2, _i) => vec![r1, r2], LW(r1, r2, _i) => vec![r1, r2], MCL(r1, r2) => vec![r1, r2], MCLI(r1, _imm) => vec![r1], @@ -323,6 +329,8 @@ impl VirtualOp { MCPI(r1, r2, _imm) => vec![r1, r2], MEQ(r1, r2, r3, r4) => vec![r1, r2, r3, r4], SB(r1, r2, _i) => vec![r1, r2], + SQW(r1, r2, _i) => vec![r1, r2], + SHW(r1, r2, _i) => vec![r1, r2], SW(r1, r2, _i) => vec![r1, r2], /* Contract Instructions */ @@ -420,6 +428,8 @@ impl VirtualOp { | XORI(_, _, _) // Memory load | LB(_, _, _) + | LQW(_, _, _) + | LHW(_, _, _) | LW(_, _, _) // Blockchain read | BAL(_, _, _) @@ -461,6 +471,8 @@ impl VirtualOp { | MCPI(_, _, _) | MEQ(_, _, _, _) | SB(_, _, _) + | SQW(_, _, _) + | SHW(_, _, _) | SW(_, _, _) // Other blockchain etc ... | BHSH(_, _) @@ -563,6 +575,8 @@ impl VirtualOp { | JAL(_, _, _) | RET(_) | LB(_, _, _) + | LQW(_, _, _) + | LHW(_, _, _) | LW(_, _, _) | MCL(_, _) | MCLI(_, _) @@ -570,6 +584,8 @@ impl VirtualOp { | MCPI(_, _, _) | MEQ(_, _, _, _) | SB(_, _, _) + | SQW(_, _, _) + | SHW(_, _, _) | SW(_, _, _) | BAL(_, _, _) | BHEI(_) @@ -678,6 +694,8 @@ impl VirtualOp { CFE(sp, r1) => vec![sp, r1], CFS(sp, r1) => vec![sp, r1], LB(_r1, r2, _i) => vec![r2], + LQW(_r1, r2, _i) => vec![r2], + LHW(_r1, r2, _i) => vec![r2], LW(_r1, r2, _i) => vec![r2], MCL(r1, r2) => vec![r1, r2], MCLI(r1, _imm) => vec![r1], @@ -685,6 +703,8 @@ impl VirtualOp { MCPI(r1, r2, _imm) => vec![r1, r2], MEQ(_r1, r2, r3, r4) => vec![r2, r3, r4], SB(r1, r2, _i) => vec![r1, r2], + SQW(r1, r2, _i) => vec![r1, r2], + SHW(r1, r2, _i) => vec![r1, r2], SW(r1, r2, _i) => vec![r1, r2], /* Contract Instructions */ @@ -806,6 +826,8 @@ impl VirtualOp { CFE(sp, r1) => vec![sp, r1], CFS(sp, r1) => vec![sp, r1], LB(_r1, r2, _i) => vec![r2], + LQW(_r1, r2, _i) => vec![r2], + LHW(_r1, r2, _i) => vec![r2], LW(_r1, r2, _i) => vec![r2], MCL(r1, r2) => vec![r1, r2], MCLI(r1, _imm) => vec![r1], @@ -813,6 +835,8 @@ impl VirtualOp { MCPI(r1, r2, _imm) => vec![r1, r2], MEQ(_r1, r2, r3, r4) => vec![r2, r3, r4], SB(r1, r2, _i) => vec![r1, r2], + SQW(r1, r2, _i) => vec![r1, r2], + SHW(r1, r2, _i) => vec![r1, r2], SW(r1, r2, _i) => vec![r1, r2], /* Contract Instructions */ @@ -932,6 +956,8 @@ impl VirtualOp { CFE(sp, _r1) => vec![sp], CFS(sp, _r1) => vec![sp], LB(r1, _r2, _i) => vec![r1], + LHW(r1, _r2, _i) => vec![r1], + LQW(r1, _r2, _i) => vec![r1], LW(r1, _r2, _i) => vec![r1], MCL(_r1, _r2) => vec![], MCLI(_r1, _imm) => vec![], @@ -939,6 +965,8 @@ impl VirtualOp { MCPI(_r1, _r2, _imm) => vec![], MEQ(r1, _r2, _r3, _r4) => vec![r1], SB(_r1, _r2, _i) => vec![], + SQW(_r1, _r2, _i) => vec![], + SHW(_r1, _r2, _i) => vec![], SW(_r1, _r2, _i) => vec![], /* Contract Instructions */ @@ -1244,6 +1272,16 @@ impl VirtualOp { update_reg(reg_to_reg_map, r2), i.clone(), ), + LQW(r1, r2, i) => Self::LQW( + update_reg(reg_to_reg_map, r1), + update_reg(reg_to_reg_map, r2), + i.clone(), + ), + LHW(r1, r2, i) => Self::LHW( + update_reg(reg_to_reg_map, r1), + update_reg(reg_to_reg_map, r2), + i.clone(), + ), LW(r1, r2, i) => Self::LW( update_reg(reg_to_reg_map, r1), update_reg(reg_to_reg_map, r2), @@ -1275,6 +1313,16 @@ impl VirtualOp { update_reg(reg_to_reg_map, r2), i.clone(), ), + SQW(r1, r2, i) => Self::SQW( + update_reg(reg_to_reg_map, r1), + update_reg(reg_to_reg_map, r2), + i.clone(), + ), + SHW(r1, r2, i) => Self::SHW( + update_reg(reg_to_reg_map, r1), + update_reg(reg_to_reg_map, r2), + i.clone(), + ), SW(r1, r2, i) => Self::SW( update_reg(reg_to_reg_map, r1), update_reg(reg_to_reg_map, r2), @@ -1757,6 +1805,16 @@ impl VirtualOp { map_reg(&mapping, reg2), imm.clone(), ), + LQW(reg1, reg2, imm) => AllocatedInstruction::LQW( + map_reg(&mapping, reg1), + map_reg(&mapping, reg2), + imm.clone(), + ), + LHW(reg1, reg2, imm) => AllocatedInstruction::LHW( + map_reg(&mapping, reg1), + map_reg(&mapping, reg2), + imm.clone(), + ), LW(reg1, reg2, imm) => AllocatedInstruction::LW( map_reg(&mapping, reg1), map_reg(&mapping, reg2), @@ -1787,6 +1845,16 @@ impl VirtualOp { map_reg(&mapping, reg2), imm.clone(), ), + SQW(reg1, reg2, imm) => AllocatedInstruction::SQW( + map_reg(&mapping, reg1), + map_reg(&mapping, reg2), + imm.clone(), + ), + SHW(reg1, reg2, imm) => AllocatedInstruction::SHW( + map_reg(&mapping, reg1), + map_reg(&mapping, reg2), + imm.clone(), + ), SW(reg1, reg2, imm) => AllocatedInstruction::SW( map_reg(&mapping, reg1), map_reg(&mapping, reg2), diff --git a/sway-ir/src/irtype.rs b/sway-ir/src/irtype.rs index 9457442ff3f..a7bfd7f30ab 100644 --- a/sway-ir/src/irtype.rs +++ b/sway-ir/src/irtype.rs @@ -259,6 +259,11 @@ impl Type { matches!(*self.get_content(context), TypeContent::Uint(8)) } + /// Is u16 type + pub fn is_uint16(&self, context: &Context) -> bool { + matches!(*self.get_content(context), TypeContent::Uint(16)) + } + /// Is u32 type pub fn is_uint32(&self, context: &Context) -> bool { matches!(*self.get_content(context), TypeContent::Uint(32)) @@ -663,7 +668,7 @@ impl TypeSize { /// the value in aggregates. E.g., in an array of `u8`, each `u8` is "padded" /// to its size of one byte while as a struct field, it will be right padded /// to 8 bytes. -#[derive(Clone, Debug, serde::Serialize)] +#[derive(Clone, Copy, Debug, serde::Serialize)] pub enum Padding { Left { target_size: usize }, Right { target_size: usize }, @@ -676,6 +681,18 @@ impl Padding { Self::Right { target_size: 1 } } + /// Returns the default [Padding] for `u16`. + pub fn default_for_u16(_value: u16) -> Self { + // Dummy _value is used only to ensure correct usage at the call site. + Self::Right { target_size: 2 } + } + + /// Returns the default [Padding] for `u32`. + pub fn default_for_u32(_value: u32) -> Self { + // Dummy _value is used only to ensure correct usage at the call site. + Self::Right { target_size: 4 } + } + /// Returns the default [Padding] for `u64`. pub fn default_for_u64(_value: u64) -> Self { // Dummy _value is used only to ensure correct usage at the call site. From 4fa0a6d6f3945ef454c012c89f9334e883186039 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Thu, 3 Jul 2025 12:18:08 +0300 Subject: [PATCH 14/18] clippy --- sway-core/src/asm_generation/fuel/data_section.rs | 8 ++++---- .../src/asm_generation/fuel/fuel_asm_builder.rs | 14 ++++---------- sway-core/src/asm_lang/virtual_ops.rs | 8 ++++---- sway-ir/src/constant.rs | 4 ++-- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/data_section.rs b/sway-core/src/asm_generation/fuel/data_section.rs index 7c6434b413c..34b372f5cfb 100644 --- a/sway-core/src/asm_generation/fuel/data_section.rs +++ b/sway-core/src/asm_generation/fuel/data_section.rs @@ -153,7 +153,7 @@ impl Entry { } } else { Entry { - value: Datum::U64(*value as u64), + value: Datum::U64(*value), padding: Padding::default_for_u64(0), name, } @@ -168,7 +168,7 @@ impl Entry { ConstantValue::String(bytes) => Entry::new_byte_array(bytes.clone(), name, padding), ConstantValue::Array(elements) => Entry::new_collection( elements - .into_iter() + .iter() .map(|elem| { Entry::from_constant(context, elem, EntryName::NonConfigurable, padding) }) @@ -178,7 +178,7 @@ impl Entry { ), ConstantValue::Struct(fields) => Entry::new_collection( fields - .into_iter() + .iter() .map(|elem| { Entry::from_constant(context, elem, EntryName::NonConfigurable, padding) }) @@ -373,7 +373,7 @@ impl DataSection { EntryName::NonConfigurable, None, )); - self.pointer_id.insert(pointer_value, data_id.clone()); + self.pointer_id.insert(pointer_value, data_id); data_id } diff --git a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs index b2c52277f5e..6f73eefaa98 100644 --- a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs +++ b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs @@ -1276,7 +1276,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { // Allocate a register for it, and an address_of instruction. let reg = self.reg_seqr.next(); self.cur_bytecode.push(Op { - opcode: either::Either::Left(VirtualOp::AddrDataId(reg.clone(), data_id.clone())), + opcode: either::Either::Left(VirtualOp::AddrDataId(reg.clone(), data_id)), comment: "get constant's address in data section".into(), owning_span: Some(span), }); @@ -1351,7 +1351,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { Some(Storage::Data(data_id)) => { let instr_reg = self.reg_seqr.next(); self.cur_bytecode.push(Op { - opcode: Either::Left(VirtualOp::LoadDataId(instr_reg.clone(), data_id.clone())), + opcode: Either::Left(VirtualOp::LoadDataId(instr_reg.clone(), *data_id)), comment: "get local constant".into(), owning_span, }); @@ -1401,10 +1401,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { // Otherwise it is a configurable with encoding v0 and must be at configurable_v0_data_id let dataid = self.configurable_v0_data_id.get(name).unwrap(); self.cur_bytecode.push(Op { - opcode: either::Either::Left(VirtualOp::AddrDataId( - addr_reg.clone(), - dataid.clone(), - )), + opcode: either::Either::Left(VirtualOp::AddrDataId(addr_reg.clone(), *dataid)), comment: format!("get address of configurable {}", name), owning_span: self.md_mgr.val_to_span(self.context, *addr_val), }); @@ -2160,10 +2157,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { // Allocate a register for it, and a load instruction. let reg = self.reg_seqr.next(); self.cur_bytecode.push(Op { - opcode: either::Either::Left(VirtualOp::LoadDataId( - reg.clone(), - data_id.clone(), - )), + opcode: either::Either::Left(VirtualOp::LoadDataId(reg.clone(), data_id)), comment: "load constant from data section".into(), owning_span: span, }); diff --git a/sway-core/src/asm_lang/virtual_ops.rs b/sway-core/src/asm_lang/virtual_ops.rs index 659977cc50c..3decf5b7588 100644 --- a/sway-core/src/asm_lang/virtual_ops.rs +++ b/sway-core/src/asm_lang/virtual_ops.rs @@ -1510,8 +1510,8 @@ impl VirtualOp { BLOB(i) => Self::BLOB(i.clone()), DataSectionOffsetPlaceholder => Self::DataSectionOffsetPlaceholder, ConfigurablesOffsetPlaceholder => Self::ConfigurablesOffsetPlaceholder, - LoadDataId(r1, i) => Self::LoadDataId(update_reg(reg_to_reg_map, r1), i.clone()), - AddrDataId(r1, i) => Self::AddrDataId(update_reg(reg_to_reg_map, r1), i.clone()), + LoadDataId(r1, i) => Self::LoadDataId(update_reg(reg_to_reg_map, r1), *i), + AddrDataId(r1, i) => Self::AddrDataId(update_reg(reg_to_reg_map, r1), *i), Undefined => Self::Undefined, } } @@ -2035,10 +2035,10 @@ impl VirtualOp { DataSectionOffsetPlaceholder => AllocatedInstruction::DataSectionOffsetPlaceholder, ConfigurablesOffsetPlaceholder => AllocatedInstruction::ConfigurablesOffsetPlaceholder, LoadDataId(reg1, label) => { - AllocatedInstruction::LoadDataId(map_reg(&mapping, reg1), label.clone()) + AllocatedInstruction::LoadDataId(map_reg(&mapping, reg1), *label) } AddrDataId(reg1, label) => { - AllocatedInstruction::AddrDataId(map_reg(&mapping, reg1), label.clone()) + AllocatedInstruction::AddrDataId(map_reg(&mapping, reg1), *label) } Undefined => AllocatedInstruction::Undefined, } diff --git a/sway-ir/src/constant.rs b/sway-ir/src/constant.rs index c91fcf5efbb..0e4028ae4c9 100644 --- a/sway-ir/src/constant.rs +++ b/sway-ir/src/constant.rs @@ -229,8 +229,8 @@ impl ConstantContent { debug_assert!(tag_and_value_with_paddings.len() == 2, "In case of enums, `elements_of_aggregate_with_padding` must return exactly two elements, the tag and the value."); - let tag = tag_and_value_with_paddings[0].clone(); - let value = tag_and_value_with_paddings[1].clone(); + let tag = tag_and_value_with_paddings[0]; + let value = tag_and_value_with_paddings[1]; Some((tag, value)) } From 8c623ae9d6366a22a90e2b15918a3ed37d582534 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Sun, 13 Jul 2025 12:16:24 +0300 Subject: [PATCH 15/18] Be smarter about pointer allocation, prefer movi --- sway-core/src/asm_generation/finalized_asm.rs | 7 +- .../allocated_abstract_instruction_set.rs | 179 ++++++------------ sway-core/src/asm_lang/allocated_ops.rs | 78 +++----- sway-core/src/asm_lang/mod.rs | 14 +- 4 files changed, 93 insertions(+), 185 deletions(-) diff --git a/sway-core/src/asm_generation/finalized_asm.rs b/sway-core/src/asm_generation/finalized_asm.rs index 6a350e6815e..2843602a0f3 100644 --- a/sway-core/src/asm_generation/finalized_asm.rs +++ b/sway-core/src/asm_generation/finalized_asm.rs @@ -3,6 +3,7 @@ use super::{ fuel::{checks, data_section::DataSection}, ProgramABI, ProgramKind, }; +use crate::asm_generation::fuel::compiler_constants::EIGHTEEN_BITS; use crate::asm_generation::fuel::data_section::{Datum, Entry, EntryName}; use crate::asm_lang::allocated_ops::{AllocatedInstruction, AllocatedOp, FuelAsmData}; use crate::decl_engine::DeclRefFunction; @@ -180,7 +181,11 @@ fn to_bytecode_mut( // The -4 is because $pc is added in the *next* instruction. let pointer_offset_from_current_instr = offset_to_data_section_in_bytes - offset_from_instr_start + offset_bytes - 4; - data_section.append_pointer(pointer_offset_from_current_instr); + + // If the pointer can't be loaded using a simple MOVI op, we need to use the data section + if pointer_offset_from_current_instr > EIGHTEEN_BITS { + data_section.append_pointer(pointer_offset_from_current_instr); + } } _ => (), } diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index d489b39352c..0e025ece168 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -607,21 +607,14 @@ pub(crate) fn compile_jump( if curr_offset > target_offset { let delta = curr_offset - target_offset - 1; return if far { - let data_id = data_section.insert_data_value(Entry::new_min_int( - delta + 1, // +1 since the load instruction must be skipped as well - EntryName::NonConfigurable, - None, - )); - vec![ - RealizedOp { - opcode: AllocatedInstruction::LoadDataId( - AllocatedRegister::Constant(ConstantRegister::Scratch), - data_id, - ), - owning_span: owning_span.clone(), - comment: "load far jump target address".into(), - }, + compile_load_integer_constant( + data_section, + AllocatedRegister::Constant(ConstantRegister::Scratch), + delta + 1, // +1 since the load instruction must be skipped as well + "load far jump target address".into(), + owning_span.clone(), + ), RealizedOp { opcode: if let Some(cond_nz) = condition_nonzero { AllocatedInstruction::JNZB( @@ -662,21 +655,14 @@ pub(crate) fn compile_jump( let delta = target_offset - curr_offset - 1; if far { - let data_id = data_section.insert_data_value(Entry::new_min_int( - delta - 1, - EntryName::NonConfigurable, - None, - )); - vec![ - RealizedOp { - opcode: AllocatedInstruction::LoadDataId( - AllocatedRegister::Constant(ConstantRegister::Scratch), - data_id, - ), - owning_span: owning_span.clone(), - comment: "load far jump target address".into(), - }, + compile_load_integer_constant( + data_section, + AllocatedRegister::Constant(ConstantRegister::Scratch), + delta - 1, + "load far jump target address".into(), + owning_span.clone(), + ), RealizedOp { opcode: if let Some(cond_nz) = condition_nonzero { AllocatedInstruction::JNZF( @@ -746,54 +732,14 @@ pub(crate) fn compile_call_inner( // with the PC register. The overflow cannot occur since programs cannot be 2**60 bytes large. let delta_instr = (delta - 1) * (Instruction::SIZE as u64); - // Attempt MOVI-based approach, that has larger immediate size but doesn't require data section. - if let Ok(imm) = VirtualImmediate18::new(delta_instr, Span::dummy()) { - return vec![ - RealizedOp { - opcode: AllocatedInstruction::MOVI( - AllocatedRegister::Constant(ConstantRegister::Scratch), - imm, - ), - owning_span: owning_span.clone(), - comment: "load call target address".into(), - }, - RealizedOp { - opcode: AllocatedInstruction::ADD( - AllocatedRegister::Constant(ConstantRegister::Scratch), - AllocatedRegister::Constant(ConstantRegister::ProgramCounter), - AllocatedRegister::Constant(ConstantRegister::Scratch), - ), - owning_span: owning_span.clone(), - comment: "load call target address".into(), - }, - RealizedOp { - opcode: AllocatedInstruction::JAL( - AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), - AllocatedRegister::Constant(ConstantRegister::Scratch), - VirtualImmediate12::new_unchecked(0, "unreachable()"), - ), - owning_span, - comment, - }, - ]; - } - - // if the offset is too large for MOVI, use data section to store the full offset. - let data_id = data_section.insert_data_value(Entry::new_min_int( - delta_instr, - EntryName::NonConfigurable, - None, - )); - return vec![ - RealizedOp { - opcode: AllocatedInstruction::LoadDataId( - AllocatedRegister::Constant(ConstantRegister::Scratch), - data_id, - ), - owning_span: owning_span.clone(), - comment: "load call target address".into(), - }, + compile_load_integer_constant( + data_section, + AllocatedRegister::Constant(ConstantRegister::Scratch), + delta_instr, + "load call target address".into(), + owning_span.clone(), + ), RealizedOp { opcode: AllocatedInstruction::ADD( AllocatedRegister::Constant(ConstantRegister::Scratch), @@ -853,54 +799,14 @@ pub(crate) fn compile_call_inner( // with the PC register. The overflow cannot occur since programs cannot be 2**60 bytes large. let delta_instr = (delta + 1) * (Instruction::SIZE as u64); - // Attempt MOVI-based approach. - if let Ok(imm) = VirtualImmediate18::new(delta_instr, Span::dummy()) { - return vec![ - RealizedOp { - opcode: AllocatedInstruction::MOVI( - AllocatedRegister::Constant(ConstantRegister::Scratch), - imm, - ), - owning_span: owning_span.clone(), - comment: "load call target address".into(), - }, - RealizedOp { - opcode: AllocatedInstruction::SUB( - AllocatedRegister::Constant(ConstantRegister::Scratch), - AllocatedRegister::Constant(ConstantRegister::ProgramCounter), - AllocatedRegister::Constant(ConstantRegister::Scratch), - ), - owning_span: owning_span.clone(), - comment: "load call target address".into(), - }, - RealizedOp { - opcode: AllocatedInstruction::JAL( - AllocatedRegister::Constant(ConstantRegister::CallReturnAddress), - AllocatedRegister::Constant(ConstantRegister::Scratch), - VirtualImmediate12::new_unchecked(0, "unreachable()"), - ), - owning_span, - comment, - }, - ]; - } - - // And lastly, fall back to the data section backed approach. - let data_id = data_section.insert_data_value(Entry::new_min_int( - delta_instr, - EntryName::NonConfigurable, - None, - )); - vec![ - RealizedOp { - opcode: AllocatedInstruction::LoadDataId( - AllocatedRegister::Constant(ConstantRegister::Scratch), - data_id, - ), - owning_span: owning_span.clone(), - comment: "load call target address".into(), - }, + compile_load_integer_constant( + data_section, + AllocatedRegister::Constant(ConstantRegister::Scratch), + delta_instr, + "load call target address".into(), + owning_span.clone(), + ), RealizedOp { opcode: AllocatedInstruction::SUB( AllocatedRegister::Constant(ConstantRegister::Scratch), @@ -948,3 +854,32 @@ pub(crate) fn compile_call( } res } + +/// Compiles loading of an integer constant into a register, +/// possibly using the data section if that's more efficient. +pub(crate) fn compile_load_integer_constant( + data_section: &mut DataSection, + register: AllocatedRegister, + value: u64, + comment: String, + owning_span: Option, +) -> RealizedOp { + // Attempt MOVI + if let Ok(imm) = VirtualImmediate18::new(value, Span::dummy()) { + return RealizedOp { + opcode: AllocatedInstruction::MOVI(register, imm), + owning_span, + comment, + }; + } + + // Fall back to the data section backed approach. + let data_id = + data_section.insert_data_value(Entry::new_min_int(value, EntryName::NonConfigurable, None)); + + RealizedOp { + opcode: AllocatedInstruction::LoadDataId(register, data_id), + owning_span, + comment, + } +} diff --git a/sway-core/src/asm_lang/allocated_ops.rs b/sway-core/src/asm_lang/allocated_ops.rs index 1cb8b0fbae1..7572f333e8f 100644 --- a/sway-core/src/asm_lang/allocated_ops.rs +++ b/sway-core/src/asm_lang/allocated_ops.rs @@ -13,7 +13,7 @@ use super::*; use crate::{ asm_generation::{ fuel::{ - compiler_constants::DATA_SECTION_REGISTER, + compiler_constants::{DATA_SECTION_REGISTER, EIGHTEEN_BITS}, data_section::{DataId, DataSection}, }, Datum, @@ -874,7 +874,7 @@ fn addr_of( /// Converts a virtual load word instruction which uses data labels into one which uses /// actual bytewise offsets for use in bytecode. /// Returns one op if the type is less than one word big, but two ops if it has to construct -/// a pointer and add it to $is. +/// a pointer and add it to $pc. fn realize_load( dest: &AllocatedRegister, data_id: &DataId, @@ -891,8 +891,7 @@ fn realize_load( Datum::U8(_) => { let Ok(imm) = VirtualImmediate12::new(offset_bytes, Span::dummy()) else { panic!( - "Unable to offset into the data section more than 2^12 bits. \ - Unsupported data section length: {} bytes.", + "Data section offset {} too large of 12 bit offset of u8 units.", offset_bytes ); }; @@ -910,8 +909,7 @@ fn realize_load( ); let Ok(imm) = VirtualImmediate12::new(offset_bytes / 2, Span::dummy()) else { panic!( - "Unable to offset into the data section more than 2^12 bits. \ - Unsupported data section length: {} bytes.", + "Data section offset {} too large of 12 bit offset of u16 units.", offset_bytes ); }; @@ -929,8 +927,7 @@ fn realize_load( ); let Ok(imm) = VirtualImmediate12::new(offset_bytes / 4, Span::dummy()) else { panic!( - "Unable to offset into the data section more than 2^12 bits. \ - Unsupported data section length: {} bytes.", + "Data section offset {} too large of 12 bit offset of u32 units.", offset_bytes ); }; @@ -948,8 +945,7 @@ fn realize_load( ); let Ok(imm) = VirtualImmediate12::new(offset_bytes / 8, Span::dummy()) else { panic!( - "Unable to offset into the data section more than 2^12 bits. \ - Unsupported data section length: {} bytes.", + "Data section offset {} too large of 12 bit offset of u64 units.", offset_bytes ); }; @@ -970,20 +966,31 @@ fn realize_load( let pointer_offset_from_current_instr = offset_to_data_section - offset_from_instr_start + offset_bytes - 4; - // insert the pointer as bytes as a new data section entry at the end of the data - let data_id_for_pointer = data_section - .data_id_of_pointer(pointer_offset_from_current_instr) - .expect("Pointer offset must be in data_section"); - // now load the pointer we just created into the `dest`ination let mut buf = Vec::with_capacity(2); - buf.append(&mut realize_load( - dest, - &data_id_for_pointer, - data_section, - offset_to_data_section, - offset_from_instr_start, - )); + + // load the value of pointer offset + if pointer_offset_from_current_instr <= EIGHTEEN_BITS { + buf.push( + fuel_asm::op::MOVI::new( + dest.to_reg_id(), + Imm18::new(pointer_offset_from_current_instr as u32), + ) + .into(), + ) + } else { + let data_id_for_pointer = data_section + .data_id_of_pointer(pointer_offset_from_current_instr) + .expect("Pointer offset must be in data_section"); + buf.append(&mut realize_load( + dest, + &data_id_for_pointer, + data_section, + offset_to_data_section, + offset_from_instr_start, + )); + } + // add $pc to the pointer since it is relative to the current instruction. buf.push( fuel_asm::op::ADD::new( @@ -996,31 +1003,4 @@ fn realize_load( buf } } - - // let is_byte = data_section.is_byte(data_id).expect( - // "Internal miscalculation in data section -- data id did not match up to any actual data", - // ); - - // let imm = VirtualImmediate12::new( - // if is_byte { offset_bytes } else { offset_words }, - // Span::new(" ".into(), 0, 0, None).unwrap(), - // ); - // let offset = match imm { - // Ok(value) => value, - // Err(_) => panic!( - // "Unable to offset into the data section more than 2^12 bits. \ - // Unsupported data section length: {} words.", - // offset_words - // ), - // }; - - // if is_byte { - // } else { - // vec![fuel_asm::op::LW::new( - // dest.to_reg_id(), - // fuel_asm::RegId::new(DATA_SECTION_REGISTER), - // offset.value().into(), - // ) - // .into()] - // } } diff --git a/sway-core/src/asm_lang/mod.rs b/sway-core/src/asm_lang/mod.rs index 255e73e94f6..ba51f29cf65 100644 --- a/sway-core/src/asm_lang/mod.rs +++ b/sway-core/src/asm_lang/mod.rs @@ -15,7 +15,7 @@ pub(crate) use virtual_ops::*; pub(crate) use virtual_register::*; use crate::{ - asm_generation::fuel::{data_section::DataId, register_allocator::RegisterPool}, + asm_generation::fuel::register_allocator::RegisterPool, asm_lang::allocated_ops::{AllocatedInstruction, AllocatedRegister}, language::AsmRegister, Ident, @@ -163,18 +163,6 @@ impl Op { owning_span: Some(owning_span), } } - /// Loads the data from [DataId] `data` into [VirtualRegister] `reg`. - pub(crate) fn unowned_load_data_comment( - reg: VirtualRegister, - data: DataId, - comment: impl Into, - ) -> Self { - Op { - opcode: Either::Left(VirtualOp::LoadDataId(reg, data)), - comment: comment.into(), - owning_span: None, - } - } /// Given a label, creates the actual asm line to put in the ASM which represents a label. /// Also attaches a comment to it. From ec4d4f1a46aeb5ade34cdc743fef3204b620b6c3 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Sun, 13 Jul 2025 13:34:05 +0300 Subject: [PATCH 16/18] Use u64 for constants for now --- .../allocated_abstract_instruction_set.rs | 22 +++++++++++++ .../src/asm_generation/fuel/data_section.rs | 33 ++++--------------- sway-ir/src/irtype.rs | 8 ++--- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index 0e025ece168..896dd5afa53 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -873,6 +873,28 @@ pub(crate) fn compile_load_integer_constant( }; } + // Attempt various tricks for known constants + if value == u64::MAX { + return RealizedOp { + opcode: AllocatedInstruction::NOT( + register, + AllocatedRegister::Constant(ConstantRegister::Zero), + ), + owning_span, + comment, + }; + } + if value == u64::MAX - 1 { + return RealizedOp { + opcode: AllocatedInstruction::NOT( + register, + AllocatedRegister::Constant(ConstantRegister::One), + ), + owning_span, + comment, + }; + } + // Fall back to the data section backed approach. let data_id = data_section.insert_data_value(Entry::new_min_int(value, EntryName::NonConfigurable, None)); diff --git a/sway-core/src/asm_generation/fuel/data_section.rs b/sway-core/src/asm_generation/fuel/data_section.rs index 34b372f5cfb..df56dc9b4b5 100644 --- a/sway-core/src/asm_generation/fuel/data_section.rs +++ b/sway-core/src/asm_generation/fuel/data_section.rs @@ -122,6 +122,7 @@ impl Entry { // Not an enum, no more special handling required. match &constant.value { + // TODO: why ZSTs can be allocated? ConstantValue::Undef | ConstantValue::Unit => Entry { value: Datum::U8(0), padding: padding.unwrap_or(Padding::default_for_u8(0)), @@ -132,33 +133,11 @@ impl Entry { padding: padding.unwrap_or(Padding::default_for_u8(0)), name, }, - ConstantValue::Uint(value) => { - if constant.ty.is_uint8(context) { - Entry { - value: Datum::U8(*value as u8), - padding: Padding::default_for_u8(0), - name, - } - } else if constant.ty.is_uint16(context) { - Entry { - value: Datum::U16(*value as u16), - padding: Padding::default_for_u16(0), - name, - } - } else if constant.ty.is_uint32(context) { - Entry { - value: Datum::U32(*value as u32), - padding: Padding::default_for_u32(0), - name, - } - } else { - Entry { - value: Datum::U64(*value), - padding: Padding::default_for_u64(0), - name, - } - } - } + ConstantValue::Uint(value) => Entry { + value: Datum::U64(*value), + padding: padding.unwrap_or(Padding::default_for_u64(0)), + name, + }, ConstantValue::U256(value) => { Entry::new_byte_array(value.to_be_bytes().to_vec(), name, padding) } diff --git a/sway-ir/src/irtype.rs b/sway-ir/src/irtype.rs index a7bfd7f30ab..f476a9de18b 100644 --- a/sway-ir/src/irtype.rs +++ b/sway-ir/src/irtype.rs @@ -579,11 +579,9 @@ impl Type { TypeContent::Uint(8) | TypeContent::Bool | TypeContent::Unit | TypeContent::Never => { TypeSize::new(1) } - // All integers larger than a byte are words since FuelVM only has memory operations on those two units. - TypeContent::Uint(16) - | TypeContent::Uint(32) - | TypeContent::Uint(64) - | TypeContent::Pointer(_) => TypeSize::new(8), + TypeContent::Uint(16) => TypeSize::new(2), + TypeContent::Uint(32) => TypeSize::new(4), + TypeContent::Uint(64) | TypeContent::Pointer(_) => TypeSize::new(8), TypeContent::Uint(256) => TypeSize::new(32), TypeContent::Uint(_) => unreachable!(), TypeContent::Slice => TypeSize::new(16), From 0e69371a2749527cc93cc2ec68b5929b64279ed3 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Sun, 13 Jul 2025 19:54:40 +0300 Subject: [PATCH 17/18] Fix data section printing --- sway-core/src/asm_generation/fuel/data_section.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/data_section.rs b/sway-core/src/asm_generation/fuel/data_section.rs index df56dc9b4b5..eada7f07045 100644 --- a/sway-core/src/asm_generation/fuel/data_section.rs +++ b/sway-core/src/asm_generation/fuel/data_section.rs @@ -415,8 +415,8 @@ impl fmt::Display for DataSection { match datum { Datum::U8(v) => format!(".byte {v}"), Datum::U16(v) => format!(".quarterword {v}"), - Datum::U32(v) => format!(".word {v}"), - Datum::U64(v) => format!(".half {v}"), + Datum::U32(v) => format!(".halfword {v}"), + Datum::U64(v) => format!(".word {v}"), Datum::ByRef(bs) => display_bytes_for_data_section(bs, ".bytes"), Datum::Collection(els) => format!( ".collection {{ {} }}", From efd91b5e9d0b9dc59ae56f40dd7271ddca811072 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Mon, 14 Jul 2025 08:42:17 +0300 Subject: [PATCH 18/18] Update test cases --- forc-plugins/forc-client/tests/deploy.rs | 6 ++--- sway-ir/src/irtype.rs | 26 +++++++------------ .../attributes_deprecated/stdout.snap | 2 +- .../language/const_generics/stdout.snap | 2 +- .../language/intrinsics/dbg/stdout.snap | 2 +- .../panic_handling_in_unit_tests/stdout.snap | 4 +-- .../panicking_contract/stdout.snap | 24 ++++++++--------- .../panicking_lib/stdout.snap | 2 +- .../panicking_script/stdout.snap | 2 +- .../array_of_structs_caller/src/main.sw | 2 +- .../asset_ops_test/src/main.sw | 4 +-- .../bal_opcode/src/main.sw | 2 +- .../call_abi_with_tuples/src/main.sw | 2 +- .../call_basic_storage/src/main.sw | 2 +- .../src/main.sw | 2 +- .../call_increment_contract/src/main.sw | 2 +- .../call_storage_enum/src/main.sw | 2 +- .../caller_auth_test/src/main.sw | 2 +- .../caller_context_test/src/main.sw | 2 +- .../nested_struct_args_caller/src/main.sw | 2 +- .../storage_access_caller/src/main.sw | 2 +- .../ir_generation/tests/simple_contract.sw | 6 ++--- 22 files changed, 48 insertions(+), 54 deletions(-) diff --git a/forc-plugins/forc-client/tests/deploy.rs b/forc-plugins/forc-client/tests/deploy.rs index 43b146583d2..a40e1e5a04f 100644 --- a/forc-plugins/forc-client/tests/deploy.rs +++ b/forc-plugins/forc-client/tests/deploy.rs @@ -377,7 +377,7 @@ async fn test_simple_deploy() { node.kill().unwrap(); let expected = vec![DeployedPackage::Contract(DeployedContract { id: ContractId::from_str( - "b45b5f58ff2f05c3593ffe4241188c14644aaa1e42dc7defae12b8d09cc6a292", + "654c47c7cc216cd33480712fccf5998ba89874e669ee9b07d4f835f3cba85aba", ) .unwrap(), proxy: None, @@ -421,7 +421,7 @@ async fn test_deploy_submit_only() { node.kill().unwrap(); let expected = vec![DeployedPackage::Contract(DeployedContract { id: ContractId::from_str( - "b45b5f58ff2f05c3593ffe4241188c14644aaa1e42dc7defae12b8d09cc6a292", + "654c47c7cc216cd33480712fccf5998ba89874e669ee9b07d4f835f3cba85aba", ) .unwrap(), proxy: None, @@ -468,7 +468,7 @@ async fn test_deploy_fresh_proxy() { node.kill().unwrap(); let impl_contract = DeployedPackage::Contract(DeployedContract { id: ContractId::from_str( - "b45b5f58ff2f05c3593ffe4241188c14644aaa1e42dc7defae12b8d09cc6a292", + "654c47c7cc216cd33480712fccf5998ba89874e669ee9b07d4f835f3cba85aba", ) .unwrap(), proxy: Some( diff --git a/sway-ir/src/irtype.rs b/sway-ir/src/irtype.rs index f476a9de18b..84ddebdb8ab 100644 --- a/sway-ir/src/irtype.rs +++ b/sway-ir/src/irtype.rs @@ -753,32 +753,26 @@ mod tests { } #[test] - /// `u8`, when not embedded in aggregates, has a size of 1 byte. - fn unsigned_u8() { + /// Aligned size is always 8 bytes, while unaligned is the size of the type. + fn unsigned_u8_u16_u32_u64() { let context = create_context(); let s_u8 = Type::get_uint8(&context).size(&context); - - assert_eq!(s_u8.in_bytes(), 1); - } - - #[test] - /// `u16`, `u32`, and `u64,`, when not embedded in aggregates, have a size of 8 bytes/1 word. - fn unsigned_u16_u32_u64() { - let context = create_context(); - let s_u16 = Type::get_uint16(&context).size(&context); let s_u32 = Type::get_uint32(&context).size(&context); let s_u64 = Type::get_uint64(&context).size(&context); - assert_eq!(s_u16.in_bytes(), 8); - assert_eq!(s_u16.in_bytes(), s_u16.in_bytes_aligned()); + assert_eq!(s_u8.in_bytes(), 1); + assert_eq!(s_u8.in_bytes_aligned(), 8); + + assert_eq!(s_u16.in_bytes(), 2); + assert_eq!(s_u16.in_bytes_aligned(), 8); - assert_eq!(s_u32.in_bytes(), 8); - assert_eq!(s_u32.in_bytes(), s_u32.in_bytes_aligned()); + assert_eq!(s_u32.in_bytes(), 4); + assert_eq!(s_u32.in_bytes_aligned(), 8); assert_eq!(s_u64.in_bytes(), 8); - assert_eq!(s_u64.in_bytes(), s_u64.in_bytes_aligned()); + assert_eq!(s_u64.in_bytes_aligned(), 8); } #[test] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap index 917acd0ea92..00fde4dbd0e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/attributes_deprecated/stdout.snap @@ -182,4 +182,4 @@ warning: Function is deprecated ____ Compiled contract "attributes_deprecated" with 19 warnings. - Finished release [optimized + fuel] target(s) [752 B] in ??? + Finished release [optimized + fuel] target(s) [736 B] in ??? diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap index 026154da3a2..ee27fc1d966 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics/stdout.snap @@ -292,7 +292,7 @@ output: Building test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics Compiling library std (sway-lib-std) Compiling script const_generics (test/src/e2e_vm_tests/test_programs/should_pass/language/const_generics) - Finished debug [unoptimized + fuel] target(s) [6.952 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [6.704 KB] in ??? Running 1 test, filtered 0 tests tested -- const_generics diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap index 425ff9f7d8e..e3d2f454ee3 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg/stdout.snap @@ -71,7 +71,7 @@ output: Building test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg Compiling library std (sway-lib-std) Compiling script dbg (test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/dbg) - Finished debug [unoptimized + fuel] target(s) [41.536 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [39.824 KB] in ??? Running 1 test, filtered 0 tests tested -- dbg diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap index 8ffa778d6dc..d6931dc8f8a 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panic_handling_in_unit_tests/stdout.snap @@ -18,7 +18,7 @@ warning: Error message is empty ____ Compiled script "panic_handling_in_unit_tests" with 1 warning. - Finished debug [unoptimized + fuel] target(s) [9.504 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [9.208 KB] in ??? Running 2 tests, filtered 18 tests tested -- panic_handling_in_unit_tests @@ -55,7 +55,7 @@ warning: Error message is empty ____ Compiled script "panic_handling_in_unit_tests" with 1 warning. - Finished debug [unoptimized + fuel] target(s) [9.504 KB] in ??? + Finished debug [unoptimized + fuel] target(s) [9.208 KB] in ??? Running 20 tests, filtered 0 tests tested -- panic_handling_in_unit_tests diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap index 9a314ba012e..0b27461ddc1 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract/stdout.snap @@ -8,78 +8,78 @@ output: Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) Compiling library panicking_lib (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib) Compiling contract panicking_contract (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_contract) - Finished release [optimized + fuel] target(s) [7.936 KB] in ??? + Finished release [optimized + fuel] target(s) [7.656 KB] in ??? Running 11 tests, filtered 0 tests tested -- panicking_contract - test test_directly_panicking_method ... ok (???, 1595 gas) + test test_directly_panicking_method ... ok (???, 1594 gas) revert code: ffffffff00000000 ├─ panic message: Error C. ├─ panic value: C(true) └─ panicked in: panicking_contract@1.2.3, src/main.sw:22:9 decoded log values: C(true), log rb: 5503570629422409978 - test test_nested_panic_inlined ... ok (???, 2913 gas) + test test_nested_panic_inlined ... ok (???, 2912 gas) revert code: ffffffff00000005 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 5503570629422409978 - test test_nested_panic_inlined_same_revert_code ... ok (???, 2913 gas) + test test_nested_panic_inlined_same_revert_code ... ok (???, 2912 gas) revert code: ffffffff00000005 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]) └─ panicked in: panicking_lib, src/lib.sw:41:9 decoded log values: E([AsciiString { data: "this" }, AsciiString { data: "is not" }, AsciiString { data: "the best practice" }]), log rb: 5503570629422409978 - test test_nested_panic_not_inlined ... ok (???, 3110 gas) + test test_nested_panic_not_inlined ... ok (???, 3109 gas) revert code: ffffffff00000006 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 5503570629422409978 - test test_nested_panic_not_inlined_same_revert_code ... ok (???, 3110 gas) + test test_nested_panic_not_inlined_same_revert_code ... ok (???, 3109 gas) revert code: ffffffff00000006 ├─ panic message: Error E. ├─ panic value: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]) └─ panicked in: panicking_lib, src/lib.sw:35:5 decoded log values: E([AsciiString { data: "to have" }, AsciiString { data: "strings" }, AsciiString { data: "in error enum variants" }]), log rb: 5503570629422409978 - test test_generic_panic_with_unit ... ok (???, 2035 gas) + test test_generic_panic_with_unit ... ok (???, 2034 gas) revert code: ffffffff00000004 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_unit_same_revert_code ... ok (???, 2035 gas) + test test_generic_panic_with_unit_same_revert_code ... ok (???, 2034 gas) revert code: ffffffff00000004 ├─ panic value: () └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: (), log rb: 3330666440490685604 - test test_generic_panic_with_str ... ok (???, 2057 gas) + test test_generic_panic_with_str ... ok (???, 2056 gas) revert code: ffffffff00000002 ├─ panic message: generic panic with string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic with string" }, log rb: 10098701174489624218 - test test_generic_panic_with_different_str_same_revert_code ... ok (???, 1730 gas) + test test_generic_panic_with_different_str_same_revert_code ... ok (???, 1729 gas) revert code: ffffffff00000002 ├─ panic message: generic panic with different string └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: AsciiString { data: "generic panic with different string" }, log rb: 10098701174489624218 - test test_generic_panic_with_error_type_enum ... ok (???, 1854 gas) + test test_generic_panic_with_error_type_enum ... ok (???, 1853 gas) revert code: ffffffff00000003 ├─ panic message: Error A. ├─ panic value: A └─ panicked in: panicking_lib, src/lib.sw:74:5 decoded log values: A, log rb: 5503570629422409978 - test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 2023 gas) + test test_generic_panic_with_error_type_enum_different_variant_same_revert_code ... ok (???, 2022 gas) revert code: ffffffff00000003 ├─ panic message: Error B. ├─ panic value: B(42) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap index db5fd53c34d..2e9a7b39491 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib/stdout.snap @@ -7,7 +7,7 @@ output: Building test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) Compiling library panicking_lib (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib) - Finished release [optimized + fuel] target(s) [5.68 KB] in ??? + Finished release [optimized + fuel] target(s) [5.648 KB] in ??? Running 18 tests, filtered 0 tests tested -- panicking_lib diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap index eee575f29ec..cb65d9bafa9 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script/stdout.snap @@ -8,7 +8,7 @@ output: Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) Compiling library panicking_lib (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_lib) Compiling script panicking_script (test/src/e2e_vm_tests/test_programs/should_pass/language/panic_expression/panicking_script) - Finished release [optimized + fuel] target(s) [3.712 KB] in ??? + Finished release [optimized + fuel] target(s) [3.68 KB] in ??? Running 11 tests, filtered 0 tests tested -- panicking_script diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw index fc75db79229..cdb3ec09f5b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw @@ -6,7 +6,7 @@ use std::hash::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x14ed3cd06c2947248f69d54bfa681fe40d26267be84df7e19e253622b7921bbe; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0xf106a79029b4b175cbd3c403328947431c4cc39913d5c03bb88011a190cf7cd1; // AUTO-CONTRACT-ID ../../test_contracts/array_of_structs_contract --release +const CONTRACT_ID = 0x0e2a44193851f9d58b1fe0b96de2f585831f98fefe82d2cc9fb3611db3a70d30; // AUTO-CONTRACT-ID ../../test_contracts/array_of_structs_contract --release fn get_address() -> Option { Some(CONTRACT_ID.into()) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw index 307328179f3..ca2dd7931e8 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw @@ -9,12 +9,12 @@ use test_fuel_coin_abi::*; #[cfg(experimental_new_encoding = false)] const FUEL_COIN_CONTRACT_ID = 0xec2277ebe007ade87e3d797c3b1e070dcd542d5ef8f038b471f262ef9cebc87c; #[cfg(experimental_new_encoding = true)] -const FUEL_COIN_CONTRACT_ID = 0x8476fc28f7ae3cad8b654176dc9f72417d4ddf0fbb9da24ade268e9ae8b82933; // AUTO-CONTRACT-ID ../../test_contracts/test_fuel_coin_contract --release +const FUEL_COIN_CONTRACT_ID = 0xd32bbc84ccf4377593fa5c65d45c5db8e6985e168eefa406210db89f812a1d4c; // AUTO-CONTRACT-ID ../../test_contracts/test_fuel_coin_contract --release #[cfg(experimental_new_encoding = false)] const BALANCE_CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df; #[cfg(experimental_new_encoding = true)] -const BALANCE_CONTRACT_ID = 0x49460391f59d838a381add127bd3bc47a840c18e78d55df0d332159dfb01acfa; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release +const BALANCE_CONTRACT_ID = 0xd2460efc3154f67c36ef1b15f55b42e079cda8bfa5e0a47dd681206e10061154; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release fn main() -> bool { let default_gas = 1_000_000_000_000; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw index 9894df5918f..b6be6f9a459 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw @@ -5,7 +5,7 @@ use balance_test_abi::BalanceTest; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x49460391f59d838a381add127bd3bc47a840c18e78d55df0d332159dfb01acfa; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release +const CONTRACT_ID = 0xd2460efc3154f67c36ef1b15f55b42e079cda8bfa5e0a47dd681206e10061154; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release fn main() -> bool { let balance_test_contract = abi(BalanceTest, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw index 93b6083a9a4..6a24fe72325 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw @@ -6,7 +6,7 @@ use abi_with_tuples::{MyContract, Location, Person}; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xfdc14550c8aee742cd556d0ab7f378b7be0d3b1e6e086c097352e94590d4ed02; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0xa2a538dd3a09bda5ded434a7c4f7b91dd1c7ac8e1a74ef14693224bf210a7474; // AUTO-CONTRACT-ID ../../test_contracts/abi_with_tuples_contract --release +const CONTRACT_ID = 0xbefa77c8410c41546d12d69e521284e6ac9c3226c8b68515c94ba3b808d93bd6; // AUTO-CONTRACT-ID ../../test_contracts/abi_with_tuples_contract --release fn main() -> bool { let the_abi = abi(MyContract, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw index 4ca06290859..ab34a2fb569 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw @@ -4,7 +4,7 @@ use basic_storage_abi::{BasicStorage, Quad}; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x94db39f409a31b9f2ebcadeea44378e419208c20de90f5d8e1e33dc1523754cb; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0xcd95389a1c96d7527caf131a0758986c6733375387b222ead91edebc2f8dbbc8; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release +const CONTRACT_ID = 0xe606cb3dc0cab1a135c91ea8d3ca9716353b2a20fd50aca8b7662e36e02ae765; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release fn main() -> u64 { let addr = abi(BasicStorage, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw index 476cb77a81d..4bdd36eb6e9 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw @@ -5,7 +5,7 @@ use contract_with_type_aliases_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x0cbeb6efe3104b460be769bdc4ea101ebf16ccc16f2d7b667ec3e1c7f5ce35b5; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x1f4cb193e171334b5a19715805957e5f2076b1cb8ae2b2579eb8bbce5fce310f; // AUTO-CONTRACT-ID ../../test_contracts/contract_with_type_aliases --release +const CONTRACT_ID = 0xf569be058a703b44320391849a2739081bb6df8aa120a1689cf5785c3f4dd40e; // AUTO-CONTRACT-ID ../../test_contracts/contract_with_type_aliases --release fn main() { let caller = abi(MyContract, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw index 254a6a7538e..02442283e87 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw @@ -6,7 +6,7 @@ use dynamic_contract_call::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xd1b4047af7ef111c023ab71069e01dc2abfde487c0a0ce1268e4f447e6c6e4c2; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0xcea7265b9985e45584844a3e473f77396b9d2b19c5e82449b8d0403d6b1bc019; // AUTO-CONTRACT-ID ../../test_contracts/increment_contract --release +const CONTRACT_ID = 0xfe4662688024dd97fc3d61ce32ba76a6ba86fb6471c4f713c8ca7ba820acc1da; // AUTO-CONTRACT-ID ../../test_contracts/increment_contract --release fn main() -> bool { let the_abi = abi(Incrementor, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw index dde53847ab2..be4aa419e54 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw @@ -5,7 +5,7 @@ use storage_enum_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xc601d11767195485a6654d566c67774134668863d8c797a8c69e8778fb1f89e9; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x3223c0382a2ba0ba6a98d9f389776ba7595ef7396e007911fc7ee6c2d1a465d9; // AUTO-CONTRACT-ID ../../test_contracts/storage_enum_contract --release +const CONTRACT_ID = 0x8a62c72e1a272f34c876380815634100d6e6f483c0a8380c155b4af5da63e7e6; // AUTO-CONTRACT-ID ../../test_contracts/storage_enum_contract --release fn main() -> u64 { let caller = abi(StorageEnum, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw index 203afd03b22..958875a9495 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw @@ -5,7 +5,7 @@ use auth_testing_abi::AuthTesting; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xc2eec20491b53aab7232cbd27c31d15417b4e9daf0b89c74cc242ef1295f681f; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x3c940400fecfb98fb14ade0e76b1f115cdb92a829c7eb0349de88326fb910fa8; // AUTO-CONTRACT-ID ../../test_contracts/auth_testing_contract --release +const CONTRACT_ID = 0xbf960f601c08a56aa63ee5aff94bde2af2f5a0a941640b67a63458c17f28ebf7; // AUTO-CONTRACT-ID ../../test_contracts/auth_testing_contract --release // should be false in the case of a script fn main() -> bool { diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw index 35c5b895910..e4724fffd28 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw @@ -6,7 +6,7 @@ use context_testing_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x6054c11cda000f5990373a4d61929396165be4dfdd61d5b7bd26da60ab0d8577; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x4b93165110ed4cd9b85b1f5127fa1e6330138baa82cb8fa1fe101678c6e57a78; // AUTO-CONTRACT-ID ../../test_contracts/context_testing_contract --release +const CONTRACT_ID = 0x736f038b079e17f7c0baddfc6aba4a943c84e1b3786ec55379387e51a91da30a; // AUTO-CONTRACT-ID ../../test_contracts/context_testing_contract --release fn main() -> bool { let gas: u64 = u64::max(); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw index 20140f48667..e712a148773 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw @@ -5,7 +5,7 @@ use nested_struct_args_abi::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0xe63d33a1b3a6903808b379f6a41a72fa8a370e8b76626775e7d9d2f9c4c5da40; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x8dbe4018418007f05e643cbed3e95e1fce0a83f9dd651fee9ec73924f856c8bb; // AUTO-CONTRACT-ID ../../test_contracts/nested_struct_args_contract --release +const CONTRACT_ID = 0x405e9416f613caab229589ed4997ea15a12775653bcd558b6c75c7354a12bbac; // AUTO-CONTRACT-ID ../../test_contracts/nested_struct_args_contract --release fn main() -> bool { let caller = abi(NestedStructArgs, CONTRACT_ID); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw index 05d0712a148..7a8881841cc 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw @@ -6,7 +6,7 @@ use std::hash::*; #[cfg(experimental_new_encoding = false)] const CONTRACT_ID = 0x3bc28acd66d327b8c1b9624c1fabfc07e9ffa1b5d71c2832c3bfaaf8f4b805e9; #[cfg(experimental_new_encoding = true)] -const CONTRACT_ID = 0x0a882ead5e3f817cfa18d79828117b38a4cb2f3ca82eee2fa7530665bf0f8ace; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release +const CONTRACT_ID = 0x514ab1a5bd29ce475bf75f70c873ab1d1346c72d09528db6b024650b45695666; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release fn main() -> bool { let caller = abi(StorageAccess, CONTRACT_ID); diff --git a/test/src/ir_generation/tests/simple_contract.sw b/test/src/ir_generation/tests/simple_contract.sw index ae79851d32e..6c8ea42de85 100644 --- a/test/src/ir_generation/tests/simple_contract.sw +++ b/test/src/ir_generation/tests/simple_contract.sw @@ -69,6 +69,6 @@ impl Test for Contract { // check: lw $REG $$fp i74 // check: .data: -// check: $get_b256_sel_data .word 1108491158 -// check: $get_s_sel_data .word 4234334249 -// check: $get_u64_sel_data .word 2559618804 +// check: $get_b256_sel_data .halfword 1108491158 +// check: $get_s_sel_data .halfword 4234334249 +// check: $get_u64_sel_data .halfword 2559618804