From fecb6aef38fab569b5418d903b1b6ba466fb8944 Mon Sep 17 00:00:00 2001 From: Mohammad Fawaz Date: Sun, 13 Mar 2022 16:46:47 -0400 Subject: [PATCH 1/3] initial commit --- sway-core/src/asm_generation/from_ir.rs | 325 +++++++++++++++++- sway-core/src/optimize.rs | 24 +- sway-core/tests/ir_to_asm/bigger_asm_block.ir | 5 +- .../ir_to_asm/let_reassign_while_loop.ir | 10 +- sway-core/tests/ir_to_asm/mutable_struct.ir | 6 +- sway-core/tests/ir_to_asm/simple_array.ir | 4 +- sway-core/tests/ir_to_asm/simple_enum.ir | 4 +- sway-core/tests/ir_to_asm/simple_struct.ir | 4 +- sway-core/tests/ir_to_asm/storage_load.asm | 44 +++ sway-core/tests/ir_to_asm/storage_load.ir | 34 ++ sway-core/tests/ir_to_asm/storage_store.asm | 47 +++ sway-core/tests/ir_to_asm/storage_store.ir | 36 ++ sway-core/tests/sway_to_ir/array_simple.ir | 4 +- sway-core/tests/sway_to_ir/b256_immeds.ir | 4 +- sway-core/tests/sway_to_ir/enum.ir | 4 +- .../sway_to_ir/let_reassign_while_loop.ir | 10 +- sway-core/tests/sway_to_ir/mutable_struct.ir | 6 +- sway-core/tests/sway_to_ir/shadowed_locals.ir | 12 +- .../tests/sway_to_ir/shadowed_struct_init.ir | 8 +- sway-core/tests/sway_to_ir/struct.ir | 4 +- sway-core/tests/sway_to_ir/struct_enum.ir | 4 +- sway-core/tests/sway_to_ir/struct_struct.ir | 4 +- sway-core/tests/sway_to_ir/trait.ir | 8 +- sway-ir/src/instruction.rs | 113 ++++-- sway-ir/src/optimize/inline.rs | 37 +- sway-ir/src/parser.rs | 125 ++++--- sway-ir/src/printer.rs | 41 ++- sway-ir/src/verify.rs | 52 ++- .../ir_to_ir/constants_insert_value.in_ir | 4 +- .../ir_to_ir/constants_insert_value.out_ir | 4 +- .../tests/ir_to_ir/constants_storage.in_ir | 23 -- .../tests/ir_to_ir/constants_storage.out_ir | 23 -- .../ir_to_ir/constants_storage_load.in_ir | 32 ++ .../ir_to_ir/constants_storage_load.out_ir | 32 ++ .../ir_to_ir/constants_storage_store.in_ir | 36 ++ .../ir_to_ir/constants_storage_store.out_ir | 36 ++ sway-ir/tests/ir_to_ir/inline_bigger.in_ir | 10 +- sway-ir/tests/ir_to_ir/inline_bigger.out_ir | 14 +- 38 files changed, 937 insertions(+), 256 deletions(-) create mode 100644 sway-core/tests/ir_to_asm/storage_load.asm create mode 100644 sway-core/tests/ir_to_asm/storage_load.ir create mode 100644 sway-core/tests/ir_to_asm/storage_store.asm create mode 100644 sway-core/tests/ir_to_asm/storage_store.ir delete mode 100644 sway-ir/tests/ir_to_ir/constants_storage.in_ir delete mode 100644 sway-ir/tests/ir_to_ir/constants_storage.out_ir create mode 100644 sway-ir/tests/ir_to_ir/constants_storage_load.in_ir create mode 100644 sway-ir/tests/ir_to_ir/constants_storage_load.out_ir create mode 100644 sway-ir/tests/ir_to_ir/constants_storage_store.in_ir create mode 100644 sway-ir/tests/ir_to_ir/constants_storage_store.out_ir diff --git a/sway-core/src/asm_generation/from_ir.rs b/sway-core/src/asm_generation/from_ir.rs index 12f4888cd22..a26dc533c35 100644 --- a/sway-core/src/asm_generation/from_ir.rs +++ b/sway-core/src/asm_generation/from_ir.rs @@ -394,7 +394,11 @@ impl<'ir> AsmBuilder<'ir> { ty, indices, } => self.compile_extract_value(instr_val, aggregate, ty, indices), - Instruction::GetPointer(ptr) => self.compile_get_pointer(instr_val, ptr), + Instruction::GetPointer { + base_ptr, + ptr_ty, + offset, + } => self.compile_get_pointer(instr_val, base_ptr, ptr_ty, *offset), Instruction::InsertElement { array, ty, @@ -415,10 +419,31 @@ impl<'ir> AsmBuilder<'ir> { ), Instruction::Nop => (), Instruction::Phi(_) => (), // Managing the phi value is done in br and cbr compilation. - Instruction::PointerCast(..) => todo!(), Instruction::Ret(ret_val, ty) => self.compile_ret(instr_val, ret_val, ty), - Instruction::StateLoad { .. } => todo!(), - Instruction::StateStore { .. } => todo!(), + Instruction::StateLoadQuadWord { load_val, key } => check!( + self.compile_state_load_quad_word(instr_val, load_val, key), + return err(warnings, errors), + warnings, + errors + ), + Instruction::StateLoadWord(key) => check!( + self.compile_state_load_word(instr_val, key), + return err(warnings, errors), + warnings, + errors + ), + Instruction::StateStoreQuadWord { stored_val, key } => check!( + self.compile_state_store_quad_word(instr_val, stored_val, key), + return err(warnings, errors), + warnings, + errors + ), + Instruction::StateStoreWord { stored_val, key } => check!( + self.compile_state_store_word(instr_val, stored_val, key), + return err(warnings, errors), + warnings, + errors + ), Instruction::Store { dst_val, stored_val, @@ -810,9 +835,15 @@ impl<'ir> AsmBuilder<'ir> { self.reg_map.insert(*instr_val, instr_reg); } - fn compile_get_pointer(&mut self, instr_val: &Value, ptr: &Pointer) { + fn compile_get_pointer( + &mut self, + instr_val: &Value, + base_ptr: &Pointer, + ptr_ty: &Type, + offset: u64, + ) { // `get_ptr` is like a `load` except the value isn't dereferenced. - match self.ptr_map.get(ptr) { + match self.ptr_map.get(base_ptr) { None => unimplemented!("BUG? Uninitialised pointer."), Some(storage) => match storage.clone() { Storage::Data(_data_id) => { @@ -820,20 +851,31 @@ impl<'ir> AsmBuilder<'ir> { unimplemented!("TODO get_ptr() into the data section."); } Storage::Register(var_reg) => { + // Not expecting an offset here nor a pointer cast + assert!(offset == 0); + assert!(ptr_ty == base_ptr.get_type(self.context)); self.reg_map.insert(*instr_val, var_reg); } Storage::Stack(word_offs) => { - let word_offs = word_offs * 8; + let ptr_ty_size_in_bytes = self + .type_analyzer + .ir_type_size_in_bytes(self.context, ptr_ty); + + let offset_in_bytes = word_offs * 8 + ptr_ty_size_in_bytes * offset; let instr_reg = self.reg_seqr.next(); - if word_offs > crate::asm_generation::compiler_constants::TWELVE_BITS { - self.number_to_reg(word_offs, &instr_reg, instr_val.get_span(self.context)); + if offset_in_bytes > crate::asm_generation::compiler_constants::TWELVE_BITS { + self.number_to_reg( + offset_in_bytes, + &instr_reg, + instr_val.get_span(self.context), + ); } else { self.bytecode.push(Op { opcode: either::Either::Left(VirtualOp::ADDI( instr_reg.clone(), self.stack_base_reg.as_ref().unwrap().clone(), VirtualImmediate12 { - value: (word_offs) as u16, + value: (offset_in_bytes) as u16, }, )), comment: "get_ptr".into(), @@ -1048,7 +1090,7 @@ impl<'ir> AsmBuilder<'ir> { if ptr.value.is_none() { return ptr.map(|_| ()); } - let ptr = ptr.value.unwrap(); + let (ptr, _ptr_ty, _offset) = ptr.value.unwrap(); let load_size_in_words = size_bytes_in_words!(self .type_analyzer .ir_type_size_in_bytes(self.context, ptr.get_type(self.context))); @@ -1196,6 +1238,255 @@ impl<'ir> AsmBuilder<'ir> { } } + fn offset_reg( + &mut self, + base_reg: &VirtualRegister, + offset_in_bytes: u64, + span: Option, + ) -> VirtualRegister { + let offset_reg = self.reg_seqr.next(); + if offset_in_bytes > crate::asm_generation::compiler_constants::TWELVE_BITS { + let offs_reg = self.reg_seqr.next(); + self.number_to_reg(offset_in_bytes, &offs_reg, span.clone()); + self.bytecode.push(Op { + opcode: either::Either::Left(VirtualOp::ADD( + offset_reg.clone(), + base_reg.clone(), + offs_reg, + )), + comment: "get offset".into(), + owning_span: span, + }); + } else { + self.bytecode.push(Op { + opcode: either::Either::Left(VirtualOp::ADDI( + offset_reg.clone(), + base_reg.clone(), + VirtualImmediate12 { + value: offset_in_bytes as u16, + }, + )), + comment: "get offset".into(), + owning_span: span, + }); + } + + offset_reg + } + + fn compile_state_load_quad_word( + &mut self, + instr_val: &Value, + load_val: &Value, + key: &Value, + ) -> CompileResult<()> { + // Make sure that both val and key are pointers to B256. + assert!(matches!(load_val.get_type(self.context), Some(Type::B256))); + assert!(matches!(key.get_type(self.context), Some(Type::B256))); + + let key_ptr = self.resolve_ptr(key); + if key_ptr.value.is_none() { + return key_ptr.map(|_| ()); + } + let (key_ptr, ptr_ty, offset) = key_ptr.value.unwrap(); + + // Not expecting an offset here nor a pointer cast + assert!(offset == 0); + assert!(ptr_ty == Type::B256); + + // Expect ptr_ty here to also be b256 and offset to be whatever... + let load_val_ptr = self.resolve_ptr(load_val); + if load_val_ptr.value.is_none() { + return load_val_ptr.map(|_| ()); + } + let (load_val_ptr, ptr_ty, offset) = load_val_ptr.value.unwrap(); + + // Expect the ptr_ty for val to also be B256 + assert!(ptr_ty == Type::B256); + + match (self.ptr_map.get(&load_val_ptr), self.ptr_map.get(&key_ptr)) { + (Some(load_val_storage), Some(key_storage)) => { + match (load_val_storage.clone(), key_storage.clone()) { + (Storage::Stack(load_val_offset), Storage::Stack(key_offset)) => { + let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + let load_val_reg = self.offset_reg( + &base_reg, + load_val_offset * 8 + offset * 32, + instr_val.get_span(self.context), + ); + + let key_reg = self.offset_reg( + &base_reg, + key_offset * 8, + instr_val.get_span(self.context), + ); + + self.bytecode.push(Op { + opcode: Either::Left(VirtualOp::SRWQ(load_val_reg, key_reg)), + comment: "quad state load value".into(), + owning_span: instr_val.get_span(self.context), + }); + } + _ => unreachable!("Unexpected storage locations for key and load_val"), + } + } + _ => unreachable!("Unexpected uninitialised pointers"), + } + + ok((), Vec::new(), Vec::new()) + } + + fn compile_state_load_word(&mut self, instr_val: &Value, key: &Value) -> CompileResult<()> { + // Make sure that the key is a pointers to B256. + assert!(matches!(key.get_type(self.context), Some(Type::B256))); + + let key_ptr = self.resolve_ptr(key); + if key_ptr.value.is_none() { + return key_ptr.map(|_| ()); + } + let (key_ptr, ptr_ty, offset) = key_ptr.value.unwrap(); + + // Not expecting an offset here nor a pointer cast + assert!(offset == 0); + assert!(ptr_ty == Type::B256); + + let load_reg = self.reg_seqr.next(); + match self.ptr_map.get(&key_ptr) { + Some(key_storage) => match key_storage.clone() { + Storage::Stack(key_offset) => { + let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + let key_reg = self.offset_reg( + &base_reg, + key_offset * 8, + instr_val.get_span(self.context), + ); + + self.bytecode.push(Op { + opcode: Either::Left(VirtualOp::SRW(load_reg.clone(), key_reg)), + comment: "state load value".into(), + owning_span: instr_val.get_span(self.context), + }); + } + _ => unreachable!("Unexpected storage location for key"), + }, + _ => unreachable!("Unexpected uninitialised pointers"), + } + + self.reg_map.insert(*instr_val, load_reg); + ok((), Vec::new(), Vec::new()) + } + + fn compile_state_store_quad_word( + &mut self, + instr_val: &Value, + store_val: &Value, + key: &Value, + ) -> CompileResult<()> { + // Make sure that both val and key are pointers to B256. + assert!(matches!(store_val.get_type(self.context), Some(Type::B256))); + assert!(matches!(key.get_type(self.context), Some(Type::B256))); + + let key_ptr = self.resolve_ptr(key); + if key_ptr.value.is_none() { + return key_ptr.map(|_| ()); + } + let (key_ptr, ptr_ty, offset) = key_ptr.value.unwrap(); + + // Not expecting an offset here nor a pointer cast + assert!(offset == 0); + assert!(ptr_ty == Type::B256); + + let store_val_ptr = self.resolve_ptr(store_val); + if store_val_ptr.value.is_none() { + return store_val_ptr.map(|_| ()); + } + let (store_val_ptr, ptr_ty, offset) = store_val_ptr.value.unwrap(); + assert!(ptr_ty == Type::B256); + + match (self.ptr_map.get(&store_val_ptr), self.ptr_map.get(&key_ptr)) { + (Some(store_val_storage), Some(key_storage)) => { + match (store_val_storage.clone(), key_storage.clone()) { + (Storage::Stack(store_val_offset), Storage::Stack(key_offset)) => { + let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + let store_val_reg = self.offset_reg( + &base_reg, + store_val_offset * 8 + offset * 32, + instr_val.get_span(self.context), + ); + + let key_reg = self.offset_reg( + &base_reg, + key_offset * 8, + instr_val.get_span(self.context), + ); + + self.bytecode.push(Op { + opcode: Either::Left(VirtualOp::SWWQ(store_val_reg, key_reg)), + comment: "quad state store value".into(), + owning_span: instr_val.get_span(self.context), + }); + } + _ => unreachable!("Unexpected storage locations for key and store_val"), + } + } + _ => unreachable!("Unexpected uninitialised pointer"), + } + + ok((), Vec::new(), Vec::new()) + } + + fn compile_state_store_word( + &mut self, + instr_val: &Value, + store_val: &Value, + key: &Value, + ) -> CompileResult<()> { + // Make sure that key is a pointer to B256. + assert!(matches!(key.get_type(self.context), Some(Type::B256))); + + // Make sure that store_val is a U64 value. + assert!(matches!( + store_val.get_type(self.context), + Some(Type::Uint(64)) + )); + let store_reg = self.value_to_register(store_val); + + // Expect the get_ptr here to have type b256 and offset = 0??? + let key_ptr = self.resolve_ptr(key); + if key_ptr.value.is_none() { + return key_ptr.map(|_| ()); + } + let (key_ptr, ptr_ty, offset) = key_ptr.value.unwrap(); + + // Not expecting an offset here nor a pointer cast + assert!(offset == 0); + assert!(ptr_ty == Type::B256); + + match self.ptr_map.get(&key_ptr) { + Some(key_storage) => match key_storage.clone() { + Storage::Stack(key_offset) => { + let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + + let key_reg = self.offset_reg( + &base_reg, + key_offset * 8, + instr_val.get_span(self.context), + ); + + self.bytecode.push(Op { + opcode: Either::Left(VirtualOp::SWW(store_reg, key_reg)), + comment: "state load value".into(), + owning_span: instr_val.get_span(self.context), + }); + } + _ => unreachable!("Unexpected storage locations for key and store_val"), + }, + _ => unreachable!("Unexpected uninitialised pointer"), + } + + ok((), Vec::new(), Vec::new()) + } + fn compile_store( &mut self, instr_val: &Value, @@ -1206,7 +1497,7 @@ impl<'ir> AsmBuilder<'ir> { if ptr.value.is_none() { return ptr.map(|_| ()); } - let ptr = ptr.value.unwrap(); + let (ptr, _ptr_ty, _offset) = ptr.value.unwrap(); let stored_reg = self.value_to_register(stored_val); let is_aggregate_ptr = ptr.is_aggregate_ptr(self.context); match self.ptr_map.get(&ptr) { @@ -1363,11 +1654,13 @@ impl<'ir> AsmBuilder<'ir> { ok((), Vec::new(), Vec::new()) } - fn resolve_ptr(&self, ptr_val: &Value) -> CompileResult { + fn resolve_ptr(&self, ptr_val: &Value) -> CompileResult<(Pointer, Type, u64)> { match &self.context.values[ptr_val.0].value { - ValueDatum::Instruction(Instruction::GetPointer(ptr)) => { - ok(*ptr, Vec::new(), Vec::new()) - } + ValueDatum::Instruction(Instruction::GetPointer { + base_ptr, + ptr_ty, + offset, + }) => ok((*base_ptr, *ptr_ty, *offset), Vec::new(), Vec::new()), _otherwise => err( Vec::new(), vec![CompileError::Internal( diff --git a/sway-core/src/optimize.rs b/sway-core/src/optimize.rs index 44f07e966e2..cce5ab1cc66 100644 --- a/sway-core/src/optimize.rs +++ b/sway-core/src/optimize.rs @@ -1003,7 +1003,11 @@ impl FnCompiler { .get(name) .and_then(|local_name| self.function.get_local_ptr(context, local_name)) { - let ptr_val = self.current_block.ins(context).get_ptr(ptr, span_md_idx); + let ptr_ty = *ptr.get_type(context); + let ptr_val = self + .current_block + .ins(context) + .get_ptr(ptr, ptr_ty, 0, span_md_idx); Ok(if ptr.is_aggregate_ptr(context) { ptr_val } else { @@ -1061,7 +1065,11 @@ impl FnCompiler { .new_local_ptr(context, local_name, return_type, is_mutable.into(), None) .map_err(|ir_error| ir_error.to_string())?; - let ptr_val = self.current_block.ins(context).get_ptr(ptr, span_md_idx); + let ptr_ty = *ptr.get_type(context); + let ptr_val = self + .current_block + .ins(context) + .get_ptr(ptr, ptr_ty, 0, span_md_idx); self.current_block .ins(context) .store(ptr_val, init_val, span_md_idx); @@ -1122,7 +1130,11 @@ impl FnCompiler { if ast_reassignment.lhs.len() == 1 { // A non-aggregate; use a `store`. - let ptr_val = self.current_block.ins(context).get_ptr(ptr, span_md_idx); + let ptr_ty = *ptr.get_type(context); + let ptr_val = self + .current_block + .ins(context) + .get_ptr(ptr, ptr_ty, 0, span_md_idx); self.current_block .ins(context) .store(ptr_val, reassign_val, span_md_idx); @@ -1172,7 +1184,11 @@ impl FnCompiler { } }; - let ptr_val = self.current_block.ins(context).get_ptr(ptr, span_md_idx); + let ptr_ty = *ptr.get_type(context); + let ptr_val = self + .current_block + .ins(context) + .get_ptr(ptr, ptr_ty, 0, span_md_idx); self.current_block.ins(context).insert_value( ptr_val, ty, diff --git a/sway-core/tests/ir_to_asm/bigger_asm_block.ir b/sway-core/tests/ir_to_asm/bigger_asm_block.ir index 0fe91d5b650..811004ded1d 100644 --- a/sway-core/tests/ir_to_asm/bigger_asm_block.ir +++ b/sway-core/tests/ir_to_asm/bigger_asm_block.ir @@ -3,10 +3,11 @@ script { local ptr b256 a entry: - v0 = get_ptr ptr b256 a + v0 = get_ptr ptr b256 a, ptr b256, 0 v1 = const b256 0x0202020202020202020202020202020202020202020202020202020202020202 store v1, ptr v0 - v2 = get_ptr ptr b256 a + v2 = get_ptr ptr b256 a, ptr b256, 0 + v3 = load ptr v2 v4 = const b256 0x0303030303030303030303030303030303030303030303030303030303030303 v5 = asm(lhs: v3, rhs: v4, sz, res) -> res { diff --git a/sway-core/tests/ir_to_asm/let_reassign_while_loop.ir b/sway-core/tests/ir_to_asm/let_reassign_while_loop.ir index cf6ac3fae90..60e539a858d 100644 --- a/sway-core/tests/ir_to_asm/let_reassign_while_loop.ir +++ b/sway-core/tests/ir_to_asm/let_reassign_while_loop.ir @@ -3,18 +3,18 @@ script { local mut ptr bool a entry: - v0 = get_ptr mut ptr bool a + v0 = get_ptr mut ptr bool a, ptr bool, 0 v1 = const bool true store v1, ptr v0 br while while: - v2 = get_ptr mut ptr bool a + v2 = get_ptr mut ptr bool a, ptr bool, 0 v3 = load ptr v2 cbr v3, while_body, end_while while_body: - v4 = get_ptr mut ptr bool a + v4 = get_ptr mut ptr bool a, ptr bool, 0 v5 = load ptr v4 cbr v5, block0, block1 @@ -25,12 +25,12 @@ script { block1: v8 = phi(while_body: v5, block0: v7) - v9 = get_ptr mut ptr bool a + v9 = get_ptr mut ptr bool a, ptr bool, 0 store v8, ptr v9 br while end_while: - v10 = get_ptr mut ptr bool a + v10 = get_ptr mut ptr bool a, ptr bool, 0 v11 = load ptr v10 ret bool v11 } diff --git a/sway-core/tests/ir_to_asm/mutable_struct.ir b/sway-core/tests/ir_to_asm/mutable_struct.ir index a0326ae5a14..48931ce4eda 100644 --- a/sway-core/tests/ir_to_asm/mutable_struct.ir +++ b/sway-core/tests/ir_to_asm/mutable_struct.ir @@ -8,12 +8,12 @@ script { v2 = insert_value v0, { u64, u64 }, v1, 0 v3 = const u64 2 v4 = insert_value v2, { u64, u64 }, v3, 1 - v5 = get_ptr mut ptr { u64, u64 } record + v5 = get_ptr mut ptr { u64, u64 } record, ptr { u64, u64 }, 0 store v4, ptr v5 - v6 = get_ptr mut ptr { u64, u64 } record + v6 = get_ptr mut ptr { u64, u64 } record, ptr { u64, u64 }, 0 v7 = const u64 50 v8 = insert_value v6, { u64, u64 }, v7, 0 - v9 = get_ptr mut ptr { u64, u64 } record + v9 = get_ptr mut ptr { u64, u64 } record, ptr { u64, u64 }, 0 v10 = extract_value v9, { u64, u64 }, 1 ret u64 v10 } diff --git a/sway-core/tests/ir_to_asm/simple_array.ir b/sway-core/tests/ir_to_asm/simple_array.ir index 360a731bd9d..1b8a7dadcb3 100644 --- a/sway-core/tests/ir_to_asm/simple_array.ir +++ b/sway-core/tests/ir_to_asm/simple_array.ir @@ -13,9 +13,9 @@ script { v7 = const bool false v8 = const u64 2 v9 = insert_element v6, [bool; 3], v7, v8 - v10 = get_ptr ptr [bool; 3] a + v10 = get_ptr ptr [bool; 3] a, ptr [bool; 3], 0 store v9, ptr v10 - v11 = get_ptr ptr [bool; 3] a + v11 = get_ptr ptr [bool; 3] a, ptr [bool; 3], 0 v12 = const u64 1 v13 = extract_element v11, [bool; 3], v12 ret bool v13 diff --git a/sway-core/tests/ir_to_asm/simple_enum.ir b/sway-core/tests/ir_to_asm/simple_enum.ir index e0e49df060b..e65f4b3f7f4 100644 --- a/sway-core/tests/ir_to_asm/simple_enum.ir +++ b/sway-core/tests/ir_to_asm/simple_enum.ir @@ -6,9 +6,9 @@ script { v0 = const { u64, { () | () | u64 } } { u64 undef, { () | () | u64 } undef } v1 = const u64 1 v2 = insert_value v0, { u64, { () | () | u64 } }, v1, 0 - v3 = get_ptr ptr { u64, { () | () | u64 } } lunch + v3 = get_ptr ptr { u64, { () | () | u64 } } lunch, ptr { u64, { () | () | u64 } }, 0 store v2, ptr v3 - v4 = get_ptr ptr { u64, { () | () | u64 } } lunch + v4 = get_ptr ptr { u64, { () | () | u64 } } lunch, ptr { u64, { () | () | u64 } }, 0 v5 = const bool false br block0 diff --git a/sway-core/tests/ir_to_asm/simple_struct.ir b/sway-core/tests/ir_to_asm/simple_struct.ir index c8ae40c555e..8cec83a3342 100644 --- a/sway-core/tests/ir_to_asm/simple_struct.ir +++ b/sway-core/tests/ir_to_asm/simple_struct.ir @@ -8,9 +8,9 @@ script { v2 = insert_value v0, { u64, u64 }, v1, 0 v3 = const u64 2 v4 = insert_value v2, { u64, u64 }, v3, 1 - v5 = get_ptr ptr { u64, u64 } record + v5 = get_ptr ptr { u64, u64 } record, ptr { u64, u64 }, 0 store v4, ptr v5 - v6 = get_ptr ptr { u64, u64 } record + v6 = get_ptr ptr { u64, u64 } record, ptr { u64, u64 }, 0 v7 = extract_value v6, { u64, u64 }, 0 ret u64 v7 } diff --git a/sway-core/tests/ir_to_asm/storage_load.asm b/sway-core/tests/ir_to_asm/storage_load.asm new file mode 100644 index 00000000000..7bb56213625 --- /dev/null +++ b/sway-core/tests/ir_to_asm/storage_load.asm @@ -0,0 +1,44 @@ +.program: +ji i4 +noop +DATA_SECTION_OFFSET[0..32] +DATA_SECTION_OFFSET[32..64] +lw $ds $is 1 +add $$ds $$ds $is +lw $r1 $fp i73 ; load input function selector +lw $r0 data_3 ; load fn selector for comparison +eq $r0 $r1 $r0 ; function selector comparison +jnei $zero $r0 i14 ; jump to selected function +lw $r0 data_4 ; load fn selector for comparison +eq $r0 $r1 $r0 ; function selector comparison +jnei $zero $r0 i24 ; jump to selected function +rvrt $zero ; revert if no selectors matched +move $r2 $sp ; save locals base register +cfei i32 ; allocate 32 bytes for all locals +addi $r0 $r2 i0 ; get_ptr +lw $r1 data_0 ; literal instantiation +addi $r0 $r2 i0 ; get store offset +mcpi $r0 $r1 i32 ; store value +addi $r0 $r2 i0 ; get offset +srw $r0 $r0 ; state load value +ret $r0 +move $r1 $sp ; save locals base register +cfei i64 ; allocate 64 bytes for all locals +addi $r0 $r1 i0 ; get_ptr +lw $r2 data_1 ; literal instantiation +addi $r0 $r1 i0 ; get store offset +mcpi $r0 $r2 i32 ; store value +addi $r0 $r1 i32 ; get_ptr +addi $r2 $r1 i32 ; get offset +addi $r0 $r1 i0 ; get offset +srwq $r2 $r0 ; quad state load value +addi $r0 $r1 i32 ; get_ptr +addi $r1 $r1 i32 ; load address +lw $r0 data_2 ; loading size for RETD +retd $r1 $r0 +.data: +data_0 .b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 +data_1 .b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c +data_2 .u64 0x20 +data_3 .u32 0x8e277065 +data_4 .u32 0x449e8e93 diff --git a/sway-core/tests/ir_to_asm/storage_load.ir b/sway-core/tests/ir_to_asm/storage_load.ir new file mode 100644 index 00000000000..e662cb98c73 --- /dev/null +++ b/sway-core/tests/ir_to_asm/storage_load.ir @@ -0,0 +1,34 @@ +contract { + fn get_x<8e277065>() -> u64 { + local mut ptr b256 key_for_x + local mut ptr u64 value_for_x + + entry: + v0 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 + v1 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 + store v1, ptr v0 + v2 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v3 = state_load_word ptr v0 + store v3, ptr v2 + v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v5 = load ptr v4 + ret u64 v5 + } + + fn get_y<449e8e93>() -> b256 { + local mut ptr b256 key_for_y + local mut ptr b256 value_for_y + + entry: + v0 = get_ptr mut ptr b256 key_for_y, ptr b256, 0 + v1 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c + store v1, ptr v0 + v2 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + state_load_quad_word ptr v2, ptr v0 + v3 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + v4 = load ptr v3 + ret b256 v4 + } +} + + diff --git a/sway-core/tests/ir_to_asm/storage_store.asm b/sway-core/tests/ir_to_asm/storage_store.asm new file mode 100644 index 00000000000..d5ef518897d --- /dev/null +++ b/sway-core/tests/ir_to_asm/storage_store.asm @@ -0,0 +1,47 @@ +.program: +ji i4 +noop +DATA_SECTION_OFFSET[0..32] +DATA_SECTION_OFFSET[32..64] +lw $ds $is 1 +add $$ds $$ds $is +lw $r1 $fp i73 ; load input function selector +lw $r0 data_4 ; load fn selector for comparison +eq $r0 $r1 $r0 ; function selector comparison +jnei $zero $r0 i14 ; jump to selected function +lw $r0 data_5 ; load fn selector for comparison +eq $r0 $r1 $r0 ; function selector comparison +jnei $zero $r0 i25 ; jump to selected function +rvrt $zero ; revert if no selectors matched +move $r2 $sp ; save locals base register +cfei i32 ; allocate 32 bytes for all locals +lw $r0 data_0 ; literal instantiation +addi $r0 $r2 i0 ; get_ptr +lw $r1 data_1 ; literal instantiation +addi $r0 $r2 i0 ; get store offset +mcpi $r0 $r1 i32 ; store value +addi $r0 $r2 i0 ; get offset +srw $r0 $r0 ; state load value +ret $zero ; returning unit as zero +move $r1 $sp ; save locals base register +cfei i64 ; allocate 64 bytes for all locals +addi $r0 $r1 i32 ; get_ptr +lw $r2 data_2 ; literal instantiation +addi $r0 $r1 i32 ; get store offset +mcpi $r0 $r2 i32 ; store value +addi $r0 $r1 i0 ; get_ptr +lw $r2 data_3 ; literal instantiation +addi $r0 $r1 i0 ; get store offset +mcpi $r0 $r2 i32 ; store value +addi $r0 $r1 i32 ; get_ptr +addi $r2 $r1 i32 ; get offset +addi $r0 $r1 i0 ; get offset +swwq $r2 $r0 ; quad state store value +ret $zero ; returning unit as zero +.data: +data_0 .u64 0x00 +data_1 .b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 +data_2 .b256 0x0000000000000000000000000000000000000000000000000000000000000000 +data_3 .b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c +data_4 .u32 0x1b9b478f +data_5 .u32 0x858a3d18 diff --git a/sway-core/tests/ir_to_asm/storage_store.ir b/sway-core/tests/ir_to_asm/storage_store.ir new file mode 100644 index 00000000000..8417b628e86 --- /dev/null +++ b/sway-core/tests/ir_to_asm/storage_store.ir @@ -0,0 +1,36 @@ +contract { + fn set_x<1b9b478f>() -> () { + local mut ptr b256 key_for_x + local mut ptr u64 value_for_x + + entry: + v0 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v1 = const u64 0 + store v1, ptr v0 + v2 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 + v3 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 + store v3, ptr v2 + v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v5 = state_load_word ptr v2 + store v5, ptr v4 + v6 = const unit () + ret () v6 + } + + fn set_y<858a3d18>() -> () { + local mut ptr b256 key_for_y + local mut ptr b256 value_for_y + + entry: + v0 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + v1 = const b256 0x0000000000000000000000000000000000000000000000000000000000000000 + store v1, ptr v0 + v2 = get_ptr mut ptr b256 key_for_y, ptr b256, 0 + v3 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c + store v3, ptr v2 + v4 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + state_store_quad_word ptr v4, ptr v2 + v5 = const unit () + ret () v5 + } +} diff --git a/sway-core/tests/sway_to_ir/array_simple.ir b/sway-core/tests/sway_to_ir/array_simple.ir index d9b75fa55f7..9a0ad2b0645 100644 --- a/sway-core/tests/sway_to_ir/array_simple.ir +++ b/sway-core/tests/sway_to_ir/array_simple.ir @@ -13,9 +13,9 @@ script { v7 = const bool false, !4 v8 = const u64 2, !1 v9 = insert_element v6, [bool; 3], v7, v8, !1 - v10 = get_ptr ptr [bool; 3] a, !5 + v10 = get_ptr ptr [bool; 3] a, ptr [bool; 3], 0, !5 store v9, ptr v10, !5 - v11 = get_ptr ptr [bool; 3] a, !6 + v11 = get_ptr ptr [bool; 3] a, ptr [bool; 3], 0, !6 v12 = const u64 1, !7 v13 = extract_element v11, [bool; 3], v12, !8 ret bool v13 diff --git a/sway-core/tests/sway_to_ir/b256_immeds.ir b/sway-core/tests/sway_to_ir/b256_immeds.ir index 4eeec6fab90..b9e4a3f2216 100644 --- a/sway-core/tests/sway_to_ir/b256_immeds.ir +++ b/sway-core/tests/sway_to_ir/b256_immeds.ir @@ -3,10 +3,10 @@ script { local ptr b256 a entry: - v0 = get_ptr ptr b256 a, !1 + v0 = get_ptr ptr b256 a, ptr b256, 0, !1 v1 = const b256 0x0202020202020202020202020202020202020202020202020202020202020202, !2 store v1, ptr v0, !1 - v2 = get_ptr ptr b256 a, !3 + v2 = get_ptr ptr b256 a, ptr b256, 0, !3 v3 = load ptr v2, !3 v4 = const b256 0x0303030303030303030303030303030303030303030303030303030303030303, !4 v5 = call anon_0(v3, v4), !5 diff --git a/sway-core/tests/sway_to_ir/enum.ir b/sway-core/tests/sway_to_ir/enum.ir index 3fc40bfad1b..190705b87b4 100644 --- a/sway-core/tests/sway_to_ir/enum.ir +++ b/sway-core/tests/sway_to_ir/enum.ir @@ -6,9 +6,9 @@ script { v0 = const { u64, { () | () | u64 } } { u64 undef, { () | () | u64 } undef }, !1 v1 = const u64 1, !1 v2 = insert_value v0, { u64, { () | () | u64 } }, v1, 0, !1 - v3 = get_ptr ptr { u64, { () | () | u64 } } lunch, !2 + v3 = get_ptr ptr { u64, { () | () | u64 } } lunch, ptr { u64, { () | () | u64 } }, 0, !2 store v2, ptr v3, !2 - v4 = get_ptr ptr { u64, { () | () | u64 } } lunch, !3 + v4 = get_ptr ptr { u64, { () | () | u64 } } lunch, ptr { u64, { () | () | u64 } }, 0, !3 v5 = call anon_0(v4), !4 v6 = const { u64, { () | () | u64 } } { u64 undef, { () | () | u64 } undef }, !5 v7 = const u64 2, !5 diff --git a/sway-core/tests/sway_to_ir/let_reassign_while_loop.ir b/sway-core/tests/sway_to_ir/let_reassign_while_loop.ir index 7033df3b1c6..2525f7f26b6 100644 --- a/sway-core/tests/sway_to_ir/let_reassign_while_loop.ir +++ b/sway-core/tests/sway_to_ir/let_reassign_while_loop.ir @@ -3,18 +3,18 @@ script { local mut ptr bool a entry: - v0 = get_ptr mut ptr bool a, !1 + v0 = get_ptr mut ptr bool a, ptr bool, 0, !1 v1 = const bool true, !2 store v1, ptr v0, !1 br while while: - v2 = get_ptr mut ptr bool a, !3 + v2 = get_ptr mut ptr bool a, ptr bool, 0, !3 v3 = load ptr v2, !3 cbr v3, while_body, end_while while_body: - v4 = get_ptr mut ptr bool a, !4 + v4 = get_ptr mut ptr bool a, ptr bool, 0, !4 v5 = load ptr v4, !4 cbr v5, block0, block1, !5 @@ -25,12 +25,12 @@ script { block1: v8 = phi(while_body: v5, block0: v7) - v9 = get_ptr mut ptr bool a, !7 + v9 = get_ptr mut ptr bool a, ptr bool, 0, !7 store v8, ptr v9, !7 br while end_while: - v10 = get_ptr mut ptr bool a, !8 + v10 = get_ptr mut ptr bool a, ptr bool, 0, !8 v11 = load ptr v10, !8 ret bool v11 } diff --git a/sway-core/tests/sway_to_ir/mutable_struct.ir b/sway-core/tests/sway_to_ir/mutable_struct.ir index fcc453fe5dc..1d154f3e889 100644 --- a/sway-core/tests/sway_to_ir/mutable_struct.ir +++ b/sway-core/tests/sway_to_ir/mutable_struct.ir @@ -8,12 +8,12 @@ script { v2 = insert_value v0, { u64, u64 }, v1, 0, !1 v3 = const u64 2, !3 v4 = insert_value v2, { u64, u64 }, v3, 1, !1 - v5 = get_ptr mut ptr { u64, u64 } record, !4 + v5 = get_ptr mut ptr { u64, u64 } record, ptr { u64, u64 }, 0, !4 store v4, ptr v5, !4 - v6 = get_ptr mut ptr { u64, u64 } record, !5 + v6 = get_ptr mut ptr { u64, u64 } record, ptr { u64, u64 }, 0, !5 v7 = const u64 50, !6 v8 = insert_value v6, { u64, u64 }, v7, 0, !5 - v9 = get_ptr mut ptr { u64, u64 } record, !7 + v9 = get_ptr mut ptr { u64, u64 } record, ptr { u64, u64 }, 0, !7 v10 = extract_value v9, { u64, u64 }, 1, !8 ret u64 v10 } diff --git a/sway-core/tests/sway_to_ir/shadowed_locals.ir b/sway-core/tests/sway_to_ir/shadowed_locals.ir index 2600f0f9d11..85cb5872f13 100644 --- a/sway-core/tests/sway_to_ir/shadowed_locals.ir +++ b/sway-core/tests/sway_to_ir/shadowed_locals.ir @@ -5,10 +5,10 @@ script { local ptr { u64 } a__ entry: - v0 = get_ptr ptr bool a, !1 + v0 = get_ptr ptr bool a, ptr bool, 0, !1 v1 = const bool true, !2 store v1, ptr v0, !1 - v2 = get_ptr ptr bool a, !3 + v2 = get_ptr ptr bool a, ptr bool, 0, !3 v3 = load ptr v2, !3 cbr v3, block0, block1, !4 @@ -22,15 +22,15 @@ script { block2: v6 = phi(block0: v4, block1: v5) - v7 = get_ptr ptr u64 a_, !7 + v7 = get_ptr ptr u64 a_, ptr u64, 0, !7 store v6, ptr v7, !7 - v8 = get_ptr ptr u64 a_, !8 + v8 = get_ptr ptr u64 a_, ptr u64, 0, !8 v9 = load ptr v8, !8 v10 = const { u64 } { u64 undef }, !9 v11 = insert_value v10, { u64 }, v9, 0, !9 - v12 = get_ptr ptr { u64 } a__, !10 + v12 = get_ptr ptr { u64 } a__, ptr { u64 }, 0, !10 store v11, ptr v12, !10 - v13 = get_ptr ptr { u64 } a__, !11 + v13 = get_ptr ptr { u64 } a__, ptr { u64 }, 0, !11 v14 = extract_value v13, { u64 }, 0, !12 ret u64 v14 } diff --git a/sway-core/tests/sway_to_ir/shadowed_struct_init.ir b/sway-core/tests/sway_to_ir/shadowed_struct_init.ir index 6597dacf903..1e609774b40 100644 --- a/sway-core/tests/sway_to_ir/shadowed_struct_init.ir +++ b/sway-core/tests/sway_to_ir/shadowed_struct_init.ir @@ -12,15 +12,15 @@ script { local ptr bool b_ entry: - v0 = get_ptr ptr bool a_, !6 + v0 = get_ptr ptr bool a_, ptr bool, 0, !6 v1 = const bool false, !7 store v1, ptr v0, !6 - v2 = get_ptr ptr bool b_, !8 + v2 = get_ptr ptr bool b_, ptr bool, 0, !8 v3 = const bool true, !9 store v3, ptr v2, !8 - v4 = get_ptr ptr bool a_, !10 + v4 = get_ptr ptr bool a_, ptr bool, 0, !10 v5 = load ptr v4, !10 - v6 = get_ptr ptr bool b_, !11 + v6 = get_ptr ptr bool b_, ptr bool, 0, !11 v7 = load ptr v6, !11 v8 = const { bool, bool } { bool undef, bool undef }, !12 v9 = insert_value v8, { bool, bool }, v5, 0, !12 diff --git a/sway-core/tests/sway_to_ir/struct.ir b/sway-core/tests/sway_to_ir/struct.ir index 7ed9c6af641..36c2607107d 100644 --- a/sway-core/tests/sway_to_ir/struct.ir +++ b/sway-core/tests/sway_to_ir/struct.ir @@ -8,9 +8,9 @@ script { v2 = insert_value v0, { u64, u64 }, v1, 0, !1 v3 = const u64 2, !3 v4 = insert_value v2, { u64, u64 }, v3, 1, !1 - v5 = get_ptr ptr { u64, u64 } record, !4 + v5 = get_ptr ptr { u64, u64 } record, ptr { u64, u64 }, 0, !4 store v4, ptr v5, !4 - v6 = get_ptr ptr { u64, u64 } record, !5 + v6 = get_ptr ptr { u64, u64 } record, ptr { u64, u64 }, 0, !5 v7 = extract_value v6, { u64, u64 }, 0, !6 ret u64 v7 } diff --git a/sway-core/tests/sway_to_ir/struct_enum.ir b/sway-core/tests/sway_to_ir/struct_enum.ir index 78091961ea9..6924db4a992 100644 --- a/sway-core/tests/sway_to_ir/struct_enum.ir +++ b/sway-core/tests/sway_to_ir/struct_enum.ir @@ -10,9 +10,9 @@ script { v4 = const bool false, !3 v5 = insert_value v3, { bool, { u64, { () | () | u64 } } }, v4, 0, !2 v6 = insert_value v5, { bool, { u64, { () | () | u64 } } }, v2, 1, !2 - v7 = get_ptr ptr { bool, { u64, { () | () | u64 } } } record, !4 + v7 = get_ptr ptr { bool, { u64, { () | () | u64 } } } record, ptr { bool, { u64, { () | () | u64 } } }, 0, !4 store v6, ptr v7, !4 - v8 = get_ptr ptr { bool, { u64, { () | () | u64 } } } record, !5 + v8 = get_ptr ptr { bool, { u64, { () | () | u64 } } } record, ptr { bool, { u64, { () | () | u64 } } }, 0, !5 v9 = extract_value v8, { bool, { u64, { () | () | u64 } } }, 0, !6 ret bool v9 } diff --git a/sway-core/tests/sway_to_ir/struct_struct.ir b/sway-core/tests/sway_to_ir/struct_struct.ir index 065c867c9b2..d9d0b59aa08 100644 --- a/sway-core/tests/sway_to_ir/struct_struct.ir +++ b/sway-core/tests/sway_to_ir/struct_struct.ir @@ -12,9 +12,9 @@ script { v6 = const b256 0x0102030405060708010203040506070801020304050607080102030405060708, !5 v7 = insert_value v5, { b256, { bool, u64 } }, v6, 0, !4 v8 = insert_value v7, { b256, { bool, u64 } }, v4, 1, !4 - v9 = get_ptr ptr { b256, { bool, u64 } } record, !6 + v9 = get_ptr ptr { b256, { bool, u64 } } record, ptr { b256, { bool, u64 } }, 0, !6 store v8, ptr v9, !6 - v10 = get_ptr ptr { b256, { bool, u64 } } record, !7 + v10 = get_ptr ptr { b256, { bool, u64 } } record, ptr { b256, { bool, u64 } }, 0, !7 v11 = extract_value v10, { b256, { bool, u64 } }, 1, !8 v12 = extract_value v11, { bool, u64 }, 1, !9 ret u64 v12 diff --git a/sway-core/tests/sway_to_ir/trait.ir b/sway-core/tests/sway_to_ir/trait.ir index 8fba5d097c0..f4296e09616 100644 --- a/sway-core/tests/sway_to_ir/trait.ir +++ b/sway-core/tests/sway_to_ir/trait.ir @@ -7,15 +7,15 @@ script { v0 = const { bool } { bool undef }, !1 v1 = const bool true, !2 v2 = insert_value v0, { bool }, v1, 0, !1 - v3 = get_ptr ptr { bool } foo, !3 + v3 = get_ptr ptr { bool } foo, ptr { bool }, 0, !3 store v2, ptr v3, !3 v4 = const { bool } { bool undef }, !4 v5 = const bool false, !5 v6 = insert_value v4, { bool }, v5, 0, !4 - v7 = get_ptr ptr { bool } bar, !6 + v7 = get_ptr ptr { bool } bar, ptr { bool }, 0, !6 store v6, ptr v7, !6 - v8 = get_ptr ptr { bool } foo, !7 - v9 = get_ptr ptr { bool } bar, !8 + v8 = get_ptr ptr { bool } foo, ptr { bool }, 0, !7 + v9 = get_ptr ptr { bool } bar, ptr { bool }, 0, !8 v10 = call anon_0(v8, v9), !9 ret bool v10 } diff --git a/sway-ir/src/instruction.rs b/sway-ir/src/instruction.rs index 5e0d499e79b..60c68a64255 100644 --- a/sway-ir/src/instruction.rs +++ b/sway-ir/src/instruction.rs @@ -48,7 +48,11 @@ pub enum Instruction { indices: Vec, }, /// Return a pointer as a value. - GetPointer(Pointer), + GetPointer { + base_ptr: Pointer, + ptr_ty: Type, + offset: u64, + }, /// Writing a specific value to an array. InsertElement { array: Value, @@ -69,16 +73,19 @@ pub enum Instruction { Nop, /// Choose a value from a list depending on the preceding block. Phi(Vec<(Block, Value)>), - /// A cast from one pointer type to another. Value must be either a GetPointer instruction or - /// another PointerCast. - PointerCast(Value, Type), /// Return from a function. Ret(Value, Type), - /// Read a value from a storage slot. Type of `load_val` must be a Uint(64) or B256 ptr. - StateLoad { load_val: Value, key: Value }, + /// Read a quad word from a storage slot. Type of `load_val` must be a B256 ptr. + StateLoadQuadWord { load_val: Value, key: Value }, + /// Read a single word from a storage slot. + StateLoadWord(Value), + /// Write a value to a storage slot. Key must be a B256, type of `stored_val` must be a + /// Uint(256) ptr. + StateStoreQuadWord { stored_val: Value, key: Value }, /// Write a value to a storage slot. Key must be a B256, type of `stored_val` must be a - /// Uint(64) or B256 ptr. - StateStore { stored_val: Value, key: Value }, + /// Uint(64) value. + StateStoreWord { stored_val: Value, key: Value }, + /// Write a value to a memory pointer. Store { dst_val: Value, stored_val: Value }, } @@ -106,8 +113,7 @@ impl Instruction { } // These can be recursed to via Load, so we return the pointer type. - Instruction::GetPointer(ptr) => Some(context.pointers[ptr.0].ty), - Instruction::PointerCast(_, ty) => Some(*ty), + Instruction::GetPointer { ptr_ty, .. } => Some(*ptr_ty), // These are all terminators which don't return, essentially. No type. Instruction::Branch(_) => None, @@ -117,8 +123,10 @@ impl Instruction { // These write values but don't return one. If we're explicit we could return Unit. Instruction::InsertElement { .. } => None, Instruction::InsertValue { .. } => None, - Instruction::StateLoad { .. } => None, - Instruction::StateStore { .. } => None, + Instruction::StateLoadQuadWord { .. } => None, + Instruction::StateLoadWord(_) => Some(Type::Uint(64)), + Instruction::StateStoreQuadWord { .. } => None, + Instruction::StateStoreWord { .. } => None, Instruction::Store { .. } => None, // No-op is also no-type. @@ -129,7 +137,7 @@ impl Instruction { /// Some [`Instruction`]s may have struct arguments. Return it if so for this instruction. pub fn get_aggregate(&self, context: &Context) -> Option { match self { - Instruction::GetPointer(ptr) => match ptr.get_type(context) { + Instruction::GetPointer { ptr_ty, .. } => match ptr_ty { Type::Array(aggregate) => Some(*aggregate), Type::Struct(aggregate) => Some(*aggregate), _otherwise => None, @@ -172,7 +180,7 @@ impl Instruction { Instruction::Branch(_) => (), Instruction::Call(_, args) => args.iter_mut().for_each(replace), Instruction::ConditionalBranch { cond_value, .. } => replace(cond_value), - Instruction::GetPointer(_) => (), + Instruction::GetPointer { .. } => (), Instruction::InsertElement { array, value, @@ -199,13 +207,19 @@ impl Instruction { Instruction::Load(_) => (), Instruction::Nop => (), Instruction::Phi(pairs) => pairs.iter_mut().for_each(|(_, val)| replace(val)), - Instruction::PointerCast(..) => (), Instruction::Ret(ret_val, _) => replace(ret_val), - Instruction::StateLoad { load_val, key } => { + Instruction::StateLoadQuadWord { load_val, key } => { replace(load_val); replace(key); } - Instruction::StateStore { stored_val, key } => { + Instruction::StateLoadWord(key) => { + replace(key); + } + Instruction::StateStoreQuadWord { stored_val, key } => { + replace(key); + replace(stored_val); + } + Instruction::StateStoreWord { stored_val, key } => { replace(key); replace(stored_val); } @@ -399,9 +413,22 @@ impl<'a> InstructionInserter<'a> { extract_value_val } - pub fn get_ptr(self, ptr: Pointer, span_md_idx: Option) -> Value { - let get_ptr_val = - Value::new_instruction(self.context, Instruction::GetPointer(ptr), span_md_idx); + pub fn get_ptr( + self, + base_ptr: Pointer, + ptr_ty: Type, + offset: u64, + span_md_idx: Option, + ) -> Value { + let get_ptr_val = Value::new_instruction( + self.context, + Instruction::GetPointer { + base_ptr, + ptr_ty, + offset, + }, + span_md_idx, + ); self.context.blocks[self.block.0] .instructions .push(get_ptr_val); @@ -471,18 +498,6 @@ impl<'a> InstructionInserter<'a> { nop_val } - pub fn ptr_cast(self, ptr_val: Value, ty: Type, span_md_idx: Option) -> Value { - let ptr_cast_val = Value::new_instruction( - self.context, - Instruction::PointerCast(ptr_val, ty), - span_md_idx, - ); - self.context.blocks[self.block.0] - .instructions - .push(ptr_cast_val); - ptr_cast_val - } - pub fn ret(self, value: Value, ty: Type, span_md_idx: Option) -> Value { let ret_val = Value::new_instruction(self.context, Instruction::Ret(value, ty), span_md_idx); @@ -490,7 +505,7 @@ impl<'a> InstructionInserter<'a> { ret_val } - pub fn state_load( + pub fn state_load_quad_word( self, load_val: Value, key: Value, @@ -498,7 +513,7 @@ impl<'a> InstructionInserter<'a> { ) -> Value { let state_load_val = Value::new_instruction( self.context, - Instruction::StateLoad { load_val, key }, + Instruction::StateLoadQuadWord { load_val, key }, span_md_idx, ); self.context.blocks[self.block.0] @@ -507,7 +522,33 @@ impl<'a> InstructionInserter<'a> { state_load_val } - pub fn state_store( + pub fn state_load_word(self, key: Value, span_md_idx: Option) -> Value { + let state_load_val = + Value::new_instruction(self.context, Instruction::StateLoadWord(key), span_md_idx); + self.context.blocks[self.block.0] + .instructions + .push(state_load_val); + state_load_val + } + + pub fn state_store_quad_word( + self, + stored_val: Value, + key: Value, + span_md_idx: Option, + ) -> Value { + let state_store_val = Value::new_instruction( + self.context, + Instruction::StateStoreQuadWord { stored_val, key }, + span_md_idx, + ); + self.context.blocks[self.block.0] + .instructions + .push(state_store_val); + state_store_val + } + + pub fn state_store_word( self, stored_val: Value, key: Value, @@ -515,7 +556,7 @@ impl<'a> InstructionInserter<'a> { ) -> Value { let state_store_val = Value::new_instruction( self.context, - Instruction::StateStore { stored_val, key }, + Instruction::StateStoreWord { stored_val, key }, span_md_idx, ); self.context.blocks[self.block.0] diff --git a/sway-ir/src/optimize/inline.rs b/sway-ir/src/optimize/inline.rs index 4a779a9d11c..8ce739ff373 100644 --- a/sway-ir/src/optimize/inline.rs +++ b/sway-ir/src/optimize/inline.rs @@ -257,9 +257,13 @@ fn inline_instruction( .ins(context) .extract_value(map_value(aggregate), ty, indices, span_md_idx) } - Instruction::GetPointer(ptr) => { - new_block.ins(context).get_ptr(map_ptr(ptr), span_md_idx) - } + Instruction::GetPointer { + base_ptr, + ptr_ty, + offset, + } => new_block + .ins(context) + .get_ptr(map_ptr(base_ptr), ptr_ty, offset, span_md_idx), Instruction::InsertElement { array, ty, @@ -288,27 +292,24 @@ fn inline_instruction( new_block.ins(context).load(map_value(src_val), span_md_idx) } Instruction::Nop => new_block.ins(context).nop(), - Instruction::PointerCast(ptr_val, ty) => { - new_block - .ins(context) - .ptr_cast(map_value(ptr_val), ty, span_md_idx) - } // We convert `ret` to `br post_block` and add the returned value as a phi value. Instruction::Ret(val, _) => { new_block .ins(context) .branch(*post_block, Some(map_value(val)), span_md_idx) } - Instruction::StateLoad { load_val, key } => { - new_block - .ins(context) - .state_load(map_value(load_val), map_value(key), span_md_idx) - } - Instruction::StateStore { stored_val, key } => new_block.ins(context).state_store( - map_value(stored_val), - map_value(key), - span_md_idx, - ), + Instruction::StateLoadQuadWord { load_val, key } => new_block + .ins(context) + .state_load_quad_word(map_value(load_val), map_value(key), span_md_idx), + Instruction::StateLoadWord(key) => new_block + .ins(context) + .state_load_word(map_value(key), span_md_idx), + Instruction::StateStoreQuadWord { stored_val, key } => new_block + .ins(context) + .state_store_quad_word(map_value(stored_val), map_value(key), span_md_idx), + Instruction::StateStoreWord { stored_val, key } => new_block + .ins(context) + .state_store_word(map_value(stored_val), map_value(key), span_md_idx), Instruction::Store { dst_val, stored_val, diff --git a/sway-ir/src/parser.rs b/sway-ir/src/parser.rs index 378322ae7ad..7771805b200 100644 --- a/sway-ir/src/parser.rs +++ b/sway-ir/src/parser.rs @@ -31,6 +31,9 @@ mod ir_builder { = _ s:script() eoi() { s } + / _ s:contract() eoi() { + s + } rule script() -> IrAstModule = "script" _ "{" _ fn_decls:fn_decl()* "}" _ metadata:metadata_decl()* { @@ -41,8 +44,18 @@ mod ir_builder { } } + rule contract() -> IrAstModule + = "contract" _ "{" _ fn_decls:fn_decl()* "}" _ metadata:metadata_decl()* { + IrAstModule { + kind: crate::module::Kind::Contract, + fn_decls, + metadata + } + } + rule fn_decl() -> IrAstFnDecl - = "fn" _ name:id() "(" _ args:(fn_arg() ** comma()) ")" _ "->" _ ret_type:ast_ty() "{" _ + = "fn" _ name:id() _ selector:selector_id()? _ "(" _ + args:(fn_arg() ** comma()) ")" _ "->" _ ret_type:ast_ty() "{" _ locals:fn_local()* blocks:block_decl()* "}" _ { @@ -52,9 +65,24 @@ mod ir_builder { ret_type, locals, blocks, + selector } } + rule selector_id() -> [u8; 4] + = "<" _ s:$(['0'..='9' | 'a'..='f' | 'A'..='F']*<8>) _ ">" _ { + let mut bytes: [u8; 4] = [0; 4]; + let mut cur_byte: u8 = 0; + for (idx, ch) in s.chars().enumerate() { + cur_byte = (cur_byte << 4) | ch.to_digit(16).unwrap() as u8; + if idx % 2 == 1 { + bytes[idx / 2] = cur_byte; + cur_byte = 0; + } + } + bytes + } + rule fn_arg() -> (IrAstTy, String, Option) = name:id() mdi:metadata_idx()? ":" _ ty:ast_ty() { (ty, name, mdi) @@ -116,10 +144,11 @@ mod ir_builder { / op_load() / op_nop() / op_phi() - / op_ptr_cast() / op_ret() - / op_state_load() - / op_state_store() + / op_state_load_quad_word() + / op_state_load_word() + / op_state_store_quad_word() + / op_state_store_word() / op_store() rule op_asm() -> IrAstOperation @@ -160,8 +189,9 @@ mod ir_builder { } rule op_get_ptr() -> IrAstOperation - = "get_ptr" _ mut_ptr() ty:ast_ty() name:id() { - IrAstOperation::GetPtr(name) + = "get_ptr" _ mut_ptr() ty:ast_ty() name:id() + comma() ptr() ty:ast_ty() comma() offset:(decimal()) { + IrAstOperation::GetPtr(name, ty, offset) } rule op_insert_element() -> IrAstOperation @@ -189,24 +219,29 @@ mod ir_builder { IrAstOperation::Phi(pairs) } - rule op_ptr_cast() -> IrAstOperation - = "ptr_cast" _ ptr() vn:id() "to" _ ptr() ty:ast_ty() { - IrAstOperation::PtrCast(vn, ty) - } - rule op_ret() -> IrAstOperation = "ret" _ ty:ast_ty() vn:id() { IrAstOperation::Ret(ty, vn) } - rule op_state_load() -> IrAstOperation - = "state_load" _ ptr() dst:id() comma() "key" _ key:id() { - IrAstOperation::StateLoad(dst, key) + rule op_state_load_quad_word() -> IrAstOperation + = "state_load_quad_word" _ ptr() dst:id() comma() ptr() _ key:id() { + IrAstOperation::StateLoadQuadWord(dst, key) + } + + rule op_state_load_word() -> IrAstOperation + = "state_load_word" _ ptr() _ key:id() { + IrAstOperation::StateLoadWord(key) + } + + rule op_state_store_quad_word() -> IrAstOperation + = "state_store_quad_word" _ ptr() src:id() comma() ptr() _ key:id() { + IrAstOperation::StateStoreQuadWord(src, key) } - rule op_state_store() -> IrAstOperation - = "state_store" _ ptr() src:id() comma() "key" _ key:id() { - IrAstOperation::StateStore(src, key) + rule op_state_store_word() -> IrAstOperation + = "state_store_word" _ src:id() comma() ptr() _ key:id() { + IrAstOperation::StateStoreWord(src, key) } rule op_store() -> IrAstOperation @@ -434,6 +469,7 @@ mod ir_builder { ret_type: IrAstTy, locals: Vec<(IrAstTy, String, bool, Option)>, blocks: Vec, + selector: Option<[u8; 4]>, } #[derive(Debug)] @@ -463,16 +499,17 @@ mod ir_builder { Const(IrAstConst), ExtractElement(String, IrAstTy, String), ExtractValue(String, IrAstTy, Vec), - GetPtr(String), + GetPtr(String, IrAstTy, u64), InsertElement(String, IrAstTy, String, String), InsertValue(String, IrAstTy, String, Vec), Load(String), Nop, Phi(Vec<(String, String)>), - PtrCast(String, IrAstTy), Ret(IrAstTy, String), - StateLoad(String, String), - StateStore(String, String), + StateLoadQuadWord(String, String), + StateLoadWord(String), + StateStoreQuadWord(String, String), + StateStoreWord(String, String), Store(String, String), } @@ -653,7 +690,7 @@ mod ir_builder { fn_decl.name, args.clone(), ret_type, - None, + fn_decl.selector, false, ); @@ -805,9 +842,15 @@ mod ir_builder { opt_ins_md_idx, ) } - IrAstOperation::GetPtr(src_name) => block - .ins(context) - .get_ptr(*ptr_map.get(&src_name).unwrap(), opt_ins_md_idx), + IrAstOperation::GetPtr(base_ptr, ptr_ty, offset) => { + let ptr_ir_ty = ptr_ty.to_ir_type(context); + block.ins(context).get_ptr( + *ptr_map.get(&base_ptr).unwrap(), + ptr_ir_ty, + offset, + opt_ins_md_idx, + ) + } IrAstOperation::InsertElement(aval, ty, val, idx) => { let ir_ty = ty.to_ir_aggregate_type(context); block.ins(context).insert_element( @@ -842,26 +885,30 @@ mod ir_builder { } block.get_phi(context) } - IrAstOperation::PtrCast(value_name, ty) => { - let ty = ty.to_ir_type(context); - block.ins(context).ptr_cast( - *val_map.get(&value_name).unwrap(), - ty, - opt_ins_md_idx, - ) - } IrAstOperation::Ret(ty, ret_val_name) => { let ty = ty.to_ir_type(context); block .ins(context) .ret(*val_map.get(&ret_val_name).unwrap(), ty, opt_ins_md_idx) } - IrAstOperation::StateLoad(dst, key) => block.ins(context).state_load( - *val_map.get(&dst).unwrap(), - *val_map.get(&key).unwrap(), - opt_ins_md_idx, - ), - IrAstOperation::StateStore(src, key) => block.ins(context).state_store( + IrAstOperation::StateLoadQuadWord(dst, key) => { + block.ins(context).state_load_quad_word( + *val_map.get(&dst).unwrap(), + *val_map.get(&key).unwrap(), + opt_ins_md_idx, + ) + } + IrAstOperation::StateLoadWord(key) => block + .ins(context) + .state_load_word(*val_map.get(&key).unwrap(), opt_ins_md_idx), + IrAstOperation::StateStoreQuadWord(src, key) => { + block.ins(context).state_store_quad_word( + *val_map.get(&src).unwrap(), + *val_map.get(&key).unwrap(), + opt_ins_md_idx, + ) + } + IrAstOperation::StateStoreWord(src, key) => block.ins(context).state_store_word( *val_map.get(&src).unwrap(), *val_map.get(&key).unwrap(), opt_ins_md_idx, diff --git a/sway-ir/src/printer.rs b/sway-ir/src/printer.rs index cdbc99a7edd..1fdc99b5e98 100644 --- a/sway-ir/src/printer.rs +++ b/sway-ir/src/printer.rs @@ -375,15 +375,21 @@ fn instruction_to_doc<'a>( Some(_) => Doc::text(md_namer.meta_as_string(context, span_md_idx, true)), }), ), - Instruction::GetPointer(ptr) => { + Instruction::GetPointer { + base_ptr, + ptr_ty, + offset, + } => { let name = block .get_function(context) - .lookup_local_name(context, ptr) + .lookup_local_name(context, base_ptr) .unwrap(); Doc::text_line(format!( - "{} = get_ptr {}{}", + "{} = get_ptr {}, ptr {}, {}{}", namer.name(context, ins_value), - ptr.as_string(context, name), + base_ptr.as_string(context, name), + ptr_ty.as_string(context), + offset, md_namer.meta_as_string(context, span_md_idx, true), )) } @@ -461,13 +467,6 @@ fn instruction_to_doc<'a>( ) } } - Instruction::PointerCast(ptr_value, ty) => Doc::text_line(format!( - "{} = ptr_cast ptr {} to ptr {}{}", - namer.name(context, ins_value), - namer.name(context, ptr_value), - ty.as_string(context), - md_namer.meta_as_string(context, span_md_idx, true) - )), Instruction::Ret(v, t) => { maybe_constant_to_doc(context, md_namer, namer, v).append(Doc::text_line(format!( "ret {} {}{}", @@ -476,14 +475,26 @@ fn instruction_to_doc<'a>( md_namer.meta_as_string(context, span_md_idx, true), ))) } - Instruction::StateLoad { load_val, key } => Doc::text_line(format!( - "state_load ptr {}, key {}{}", + Instruction::StateLoadQuadWord { load_val, key } => Doc::text_line(format!( + "state_load_quad_word ptr {}, ptr {}{}", namer.name(context, load_val), namer.name(context, key), md_namer.meta_as_string(context, span_md_idx, true), )), - Instruction::StateStore { stored_val, key } => Doc::text_line(format!( - "state_store ptr {}, key {}{}", + Instruction::StateLoadWord(key) => Doc::text_line(format!( + "{} = state_load_word ptr {}{}", + namer.name(context, ins_value), + namer.name(context, key), + md_namer.meta_as_string(context, span_md_idx, true), + )), + Instruction::StateStoreQuadWord { stored_val, key } => Doc::text_line(format!( + "state_store_quad_word ptr {}, ptr {}{}", + namer.name(context, stored_val), + namer.name(context, key), + md_namer.meta_as_string(context, span_md_idx, true), + )), + Instruction::StateStoreWord { stored_val, key } => Doc::text_line(format!( + "state_store_word {}, ptr {}{}", namer.name(context, stored_val), namer.name(context, key), md_namer.meta_as_string(context, span_md_idx, true), diff --git a/sway-ir/src/verify.rs b/sway-ir/src/verify.rs index fc83b22e793..419eb2f995f 100644 --- a/sway-ir/src/verify.rs +++ b/sway-ir/src/verify.rs @@ -95,7 +95,11 @@ impl Context { ty, indices, } => self.verify_extract_value(aggregate, ty, indices)?, - Instruction::GetPointer(ptr) => self.verify_get_ptr(ptr)?, + Instruction::GetPointer { + base_ptr, + ptr_ty, + offset, + } => self.verify_get_ptr(base_ptr, ptr_ty, *offset)?, Instruction::InsertElement { array, ty, @@ -111,13 +115,16 @@ impl Context { Instruction::Load(ptr) => self.verify_load(ptr)?, Instruction::Nop => (), Instruction::Phi(pairs) => self.verify_phi(&pairs[..])?, - Instruction::PointerCast(ptr_val, ty) => self.verify_ptr_cast(ptr_val, ty)?, Instruction::Ret(val, ty) => self.verify_ret(function, val, ty)?, - Instruction::StateLoad { load_val, key } => { - self.verify_state_load(load_val, key)? + Instruction::StateLoadWord(key) => self.verify_state_load_word(key)?, + Instruction::StateLoadQuadWord { load_val, key } => { + self.verify_state_load_quad_word(load_val, key)? } - Instruction::StateStore { stored_val, key } => { - self.verify_state_store(stored_val, key)? + Instruction::StateStoreWord { stored_val, key } => { + self.verify_state_store_word(stored_val, key)? + } + Instruction::StateStoreQuadWord { stored_val, key } => { + self.verify_state_store_quad_word(stored_val, key)? } Instruction::Store { dst_val, @@ -179,7 +186,12 @@ impl Context { Ok(()) } - fn verify_get_ptr(&self, _ptr: &Pointer) -> Result<(), IrError> { + fn verify_get_ptr( + &self, + _base_ptr: &Pointer, + _ptr_ty: &Type, + _offset: u64, + ) -> Result<(), IrError> { // XXX get_ptr() shouldn't exist in the final IR? Ok(()) } @@ -222,12 +234,6 @@ impl Context { } } - fn verify_ptr_cast(&self, _ptr_val: &Value, _ty: &Type) -> Result<(), IrError> { - // XXX Make sure the pointer itself doesn't change, just the type, and is definitely either - // a get_ptr or ptr_cast. - Ok(()) - } - fn verify_ret( &self, function: &FunctionContent, @@ -245,13 +251,27 @@ impl Context { } } - fn verify_state_load(&self, _load_val: &Value, _key: &Value) -> Result<(), IrError> { + fn verify_state_load_quad_word(&self, _load_val: &Value, _key: &Value) -> Result<(), IrError> { // XXX key must be a pointer to B256, load_val ty must by pointer to either Uint(64) or B256. Ok(()) } - fn verify_state_store(&self, _stored_val: &Value, _key: &Value) -> Result<(), IrError> { - // XXX key must be a pointer to B256, stored val ty must be pointer to either Uint(64) or B256. + fn verify_state_load_word(&self, _key: &Value) -> Result<(), IrError> { + // XXX key must be a pointer to B256, load_val ty must by pointer to either Uint(64) or B256. + Ok(()) + } + + fn verify_state_store_quad_word( + &self, + _stored_val: &Value, + _key: &Value, + ) -> Result<(), IrError> { + // XXX key must be a pointer to B256, stored val ty must be pointer to a B256. + Ok(()) + } + + fn verify_state_store_word(&self, _stored_val: &Value, _key: &Value) -> Result<(), IrError> { + // XXX key must be a pointer to B256, stored val ty must be a Uint(64). Ok(()) } diff --git a/sway-ir/tests/ir_to_ir/constants_insert_value.in_ir b/sway-ir/tests/ir_to_ir/constants_insert_value.in_ir index d4bdf9503c2..9d93fdd5610 100644 --- a/sway-ir/tests/ir_to_ir/constants_insert_value.in_ir +++ b/sway-ir/tests/ir_to_ir/constants_insert_value.in_ir @@ -36,9 +36,9 @@ script { v6 = const b256 0x0102030405060708010203040506070801020304050607080102030405060708 v7 = insert_value v5, { b256, { bool, u64 } }, v6, 0 v8 = insert_value v7, { b256, { bool, u64 } }, v4, 1 - v9 = get_ptr ptr { b256, { bool, u64 } } record + v9 = get_ptr ptr { b256, { bool, u64 } } record, ptr { b256, { bool, u64 } }, 0 store v8, ptr v9 - v10 = get_ptr ptr { b256, { bool, u64 } } record + v10 = get_ptr ptr { b256, { bool, u64 } } record, ptr { b256, { bool, u64 } }, 0 v11 = extract_value v10, { b256, { bool, u64 } }, 1 v12 = extract_value v11, { bool, u64 }, 1 ret u64 v12 diff --git a/sway-ir/tests/ir_to_ir/constants_insert_value.out_ir b/sway-ir/tests/ir_to_ir/constants_insert_value.out_ir index bf7e4bb35a1..465944b9ac8 100644 --- a/sway-ir/tests/ir_to_ir/constants_insert_value.out_ir +++ b/sway-ir/tests/ir_to_ir/constants_insert_value.out_ir @@ -3,10 +3,10 @@ script { local ptr { b256, { bool, u64 } } record entry: - v0 = get_ptr ptr { b256, { bool, u64 } } record + v0 = get_ptr ptr { b256, { bool, u64 } } record, ptr { b256, { bool, u64 } }, 0 v1 = const { b256, { bool, u64 } } { b256 0x0102030405060708010203040506070801020304050607080102030405060708, { bool, u64 } { bool true, u64 76 } } store v1, ptr v0 - v2 = get_ptr ptr { b256, { bool, u64 } } record + v2 = get_ptr ptr { b256, { bool, u64 } } record, ptr { b256, { bool, u64 } }, 0 v3 = extract_value v2, { b256, { bool, u64 } }, 1 v4 = extract_value v3, { bool, u64 }, 1 ret u64 v4 diff --git a/sway-ir/tests/ir_to_ir/constants_storage.in_ir b/sway-ir/tests/ir_to_ir/constants_storage.in_ir deleted file mode 100644 index 16a90907f49..00000000000 --- a/sway-ir/tests/ir_to_ir/constants_storage.in_ir +++ /dev/null @@ -1,23 +0,0 @@ -script { - fn main() -> () { - local ptr b256 key - local mut ptr { u64, u64 } pair - local mut ptr u64 stored_number - - entry: - v0 = get_ptr ptr b256 key - v1 = const b256 0x1111111111111111111111111111111111111111111111111111111111111111 - store v1, ptr v0 - v2 = get_ptr mut ptr u64 stored_number - state_load ptr v2, key v0 - v3 = const { u64, u64 } { u64 undef, u64 undef } - v4 = insert_value v3, { u64, u64 }, v2, 0 - v5 = insert_value v4, { u64, u64 }, v2, 1 - v6 = get_ptr mut ptr { u64, u64 } pair - store v5, ptr v6 - v7 = ptr_cast ptr v6 to ptr b256 - state_store ptr v7, key v0 - v8 = const unit () - ret () v8 - } -} diff --git a/sway-ir/tests/ir_to_ir/constants_storage.out_ir b/sway-ir/tests/ir_to_ir/constants_storage.out_ir deleted file mode 100644 index 16a90907f49..00000000000 --- a/sway-ir/tests/ir_to_ir/constants_storage.out_ir +++ /dev/null @@ -1,23 +0,0 @@ -script { - fn main() -> () { - local ptr b256 key - local mut ptr { u64, u64 } pair - local mut ptr u64 stored_number - - entry: - v0 = get_ptr ptr b256 key - v1 = const b256 0x1111111111111111111111111111111111111111111111111111111111111111 - store v1, ptr v0 - v2 = get_ptr mut ptr u64 stored_number - state_load ptr v2, key v0 - v3 = const { u64, u64 } { u64 undef, u64 undef } - v4 = insert_value v3, { u64, u64 }, v2, 0 - v5 = insert_value v4, { u64, u64 }, v2, 1 - v6 = get_ptr mut ptr { u64, u64 } pair - store v5, ptr v6 - v7 = ptr_cast ptr v6 to ptr b256 - state_store ptr v7, key v0 - v8 = const unit () - ret () v8 - } -} diff --git a/sway-ir/tests/ir_to_ir/constants_storage_load.in_ir b/sway-ir/tests/ir_to_ir/constants_storage_load.in_ir new file mode 100644 index 00000000000..1b32ff93b3b --- /dev/null +++ b/sway-ir/tests/ir_to_ir/constants_storage_load.in_ir @@ -0,0 +1,32 @@ +script { + fn main() -> () { + local mut ptr b256 key_for_x + local mut ptr b256 key_for_y + local mut ptr u64 value_for_x + local mut ptr b256 value_for_y + local ptr u64 x + local ptr b256 y + + entry: + v0 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 + v1 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 + store v1, ptr v0 + v2 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v3 = state_load_word ptr v0 + store v3, ptr v2 + v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v5 = load ptr v4 + v6 = get_ptr ptr u64 x, ptr u64, 0 + store v5, ptr v6 + v7 = get_ptr mut ptr b256 key_for_y, ptr b256, 0 + v8 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c + store v8, ptr v7 + v9 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + state_load_quad_word ptr v9, ptr v7 + v10 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + v11 = load ptr v10 + v12 = get_ptr ptr b256 y, ptr b256, 0 + store v11, ptr v12 + ret () v11 + } +} diff --git a/sway-ir/tests/ir_to_ir/constants_storage_load.out_ir b/sway-ir/tests/ir_to_ir/constants_storage_load.out_ir new file mode 100644 index 00000000000..1b32ff93b3b --- /dev/null +++ b/sway-ir/tests/ir_to_ir/constants_storage_load.out_ir @@ -0,0 +1,32 @@ +script { + fn main() -> () { + local mut ptr b256 key_for_x + local mut ptr b256 key_for_y + local mut ptr u64 value_for_x + local mut ptr b256 value_for_y + local ptr u64 x + local ptr b256 y + + entry: + v0 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 + v1 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 + store v1, ptr v0 + v2 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v3 = state_load_word ptr v0 + store v3, ptr v2 + v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v5 = load ptr v4 + v6 = get_ptr ptr u64 x, ptr u64, 0 + store v5, ptr v6 + v7 = get_ptr mut ptr b256 key_for_y, ptr b256, 0 + v8 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c + store v8, ptr v7 + v9 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + state_load_quad_word ptr v9, ptr v7 + v10 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + v11 = load ptr v10 + v12 = get_ptr ptr b256 y, ptr b256, 0 + store v11, ptr v12 + ret () v11 + } +} diff --git a/sway-ir/tests/ir_to_ir/constants_storage_store.in_ir b/sway-ir/tests/ir_to_ir/constants_storage_store.in_ir new file mode 100644 index 00000000000..8417b628e86 --- /dev/null +++ b/sway-ir/tests/ir_to_ir/constants_storage_store.in_ir @@ -0,0 +1,36 @@ +contract { + fn set_x<1b9b478f>() -> () { + local mut ptr b256 key_for_x + local mut ptr u64 value_for_x + + entry: + v0 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v1 = const u64 0 + store v1, ptr v0 + v2 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 + v3 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 + store v3, ptr v2 + v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v5 = state_load_word ptr v2 + store v5, ptr v4 + v6 = const unit () + ret () v6 + } + + fn set_y<858a3d18>() -> () { + local mut ptr b256 key_for_y + local mut ptr b256 value_for_y + + entry: + v0 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + v1 = const b256 0x0000000000000000000000000000000000000000000000000000000000000000 + store v1, ptr v0 + v2 = get_ptr mut ptr b256 key_for_y, ptr b256, 0 + v3 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c + store v3, ptr v2 + v4 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + state_store_quad_word ptr v4, ptr v2 + v5 = const unit () + ret () v5 + } +} diff --git a/sway-ir/tests/ir_to_ir/constants_storage_store.out_ir b/sway-ir/tests/ir_to_ir/constants_storage_store.out_ir new file mode 100644 index 00000000000..8417b628e86 --- /dev/null +++ b/sway-ir/tests/ir_to_ir/constants_storage_store.out_ir @@ -0,0 +1,36 @@ +contract { + fn set_x<1b9b478f>() -> () { + local mut ptr b256 key_for_x + local mut ptr u64 value_for_x + + entry: + v0 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v1 = const u64 0 + store v1, ptr v0 + v2 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 + v3 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 + store v3, ptr v2 + v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 + v5 = state_load_word ptr v2 + store v5, ptr v4 + v6 = const unit () + ret () v6 + } + + fn set_y<858a3d18>() -> () { + local mut ptr b256 key_for_y + local mut ptr b256 value_for_y + + entry: + v0 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + v1 = const b256 0x0000000000000000000000000000000000000000000000000000000000000000 + store v1, ptr v0 + v2 = get_ptr mut ptr b256 key_for_y, ptr b256, 0 + v3 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c + store v3, ptr v2 + v4 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 + state_store_quad_word ptr v4, ptr v2 + v5 = const unit () + ret () v5 + } +} diff --git a/sway-ir/tests/ir_to_ir/inline_bigger.in_ir b/sway-ir/tests/ir_to_ir/inline_bigger.in_ir index 5381b580827..c2325baf506 100644 --- a/sway-ir/tests/ir_to_ir/inline_bigger.in_ir +++ b/sway-ir/tests/ir_to_ir/inline_bigger.in_ir @@ -22,13 +22,13 @@ script { local ptr u64 x entry: - v0 = get_ptr ptr u64 x + v0 = get_ptr ptr u64 x, ptr u64, 0 v1 = const u64 10 store v1, ptr v0 cbr b, block0, block1 block0: - v2 = get_ptr ptr u64 x + v2 = get_ptr ptr u64 x, ptr u64, 0 v3 = load ptr v2 br block2 @@ -45,14 +45,14 @@ script { local mut ptr u64 x entry: - v0 = get_ptr mut ptr u64 x + v0 = get_ptr mut ptr u64 x, ptr u64, 0 v1 = const u64 0 store v1, ptr v0 v2 = const bool true v3 = call a(v2) - v4 = get_ptr mut ptr u64 x + v4 = get_ptr mut ptr u64 x, ptr u64, 0 store v3, ptr v4 - v5 = get_ptr mut ptr u64 x + v5 = get_ptr mut ptr u64 x, ptr u64, 0 v6 = load ptr v5 ret u64 v6 } diff --git a/sway-ir/tests/ir_to_ir/inline_bigger.out_ir b/sway-ir/tests/ir_to_ir/inline_bigger.out_ir index acdf1930158..f0e5435ba53 100644 --- a/sway-ir/tests/ir_to_ir/inline_bigger.out_ir +++ b/sway-ir/tests/ir_to_ir/inline_bigger.out_ir @@ -3,13 +3,13 @@ script { local ptr u64 x entry: - v0 = get_ptr ptr u64 x + v0 = get_ptr ptr u64 x, ptr u64, 0 v1 = const u64 10 store v1, ptr v0 cbr b, block0, block1 block0: - v2 = get_ptr ptr u64 x + v2 = get_ptr ptr u64 x, ptr u64, 0 v3 = load ptr v2 br block2 @@ -27,17 +27,17 @@ script { local ptr u64 x0 entry: - v0 = get_ptr mut ptr u64 x + v0 = get_ptr mut ptr u64 x, ptr u64, 0 v1 = const u64 0 store v1, ptr v0 - v2 = get_ptr ptr u64 x0 + v2 = get_ptr ptr u64 x0, ptr u64, 0 v3 = const u64 10 store v3, ptr v2 v4 = const bool true cbr v4, a_block0, a_block1 a_block0: - v5 = get_ptr ptr u64 x0 + v5 = get_ptr ptr u64 x0, ptr u64, 0 v6 = load ptr v5 br a_block2 @@ -51,9 +51,9 @@ script { block0: v9 = phi(a_block2: v8) - v10 = get_ptr mut ptr u64 x + v10 = get_ptr mut ptr u64 x, ptr u64, 0 store v9, ptr v10 - v11 = get_ptr mut ptr u64 x + v11 = get_ptr mut ptr u64 x, ptr u64, 0 v12 = load ptr v11 ret u64 v12 } From f768cc5e716161b85d3a513694a4d074fc71c5fd Mon Sep 17 00:00:00 2001 From: Mohammad Fawaz Date: Tue, 15 Mar 2022 10:30:43 -0400 Subject: [PATCH 2/3] address Toby's comments --- sway-core/src/asm_generation/from_ir.rs | 205 +++++++----------- sway-core/tests/ir_to_asm/storage_load.asm | 4 +- sway-core/tests/ir_to_asm/storage_load.ir | 4 +- sway-core/tests/ir_to_asm/storage_store.asm | 8 +- sway-core/tests/ir_to_asm/storage_store.ir | 10 +- sway-ir/src/parser.rs | 45 ++-- sway-ir/src/printer.rs | 8 +- .../ir_to_ir/constants_storage_load.in_ir | 4 +- .../ir_to_ir/constants_storage_load.out_ir | 4 +- .../ir_to_ir/constants_storage_store.in_ir | 10 +- .../ir_to_ir/constants_storage_store.out_ir | 10 +- 11 files changed, 130 insertions(+), 182 deletions(-) diff --git a/sway-core/src/asm_generation/from_ir.rs b/sway-core/src/asm_generation/from_ir.rs index a26dc533c35..62b41d2bc3c 100644 --- a/sway-core/src/asm_generation/from_ir.rs +++ b/sway-core/src/asm_generation/from_ir.rs @@ -192,6 +192,11 @@ pub(super) enum Storage { Stack(u64), // Storage in the runtime stack starting at an absolute word offset. Essentially a global. } +pub enum StateAccessType { + Read, + Write, +} + impl<'ir> AsmBuilder<'ir> { fn new(data_section: DataSection, reg_seqr: RegisterSequencer, context: &'ir Context) -> Self { AsmBuilder { @@ -421,7 +426,12 @@ impl<'ir> AsmBuilder<'ir> { Instruction::Phi(_) => (), // Managing the phi value is done in br and cbr compilation. Instruction::Ret(ret_val, ty) => self.compile_ret(instr_val, ret_val, ty), Instruction::StateLoadQuadWord { load_val, key } => check!( - self.compile_state_load_quad_word(instr_val, load_val, key), + self.compile_state_access_quad_word( + instr_val, + load_val, + key, + StateAccessType::Read + ), return err(warnings, errors), warnings, errors @@ -433,7 +443,12 @@ impl<'ir> AsmBuilder<'ir> { errors ), Instruction::StateStoreQuadWord { stored_val, key } => check!( - self.compile_state_store_quad_word(instr_val, stored_val, key), + self.compile_state_access_quad_word( + instr_val, + stored_val, + key, + StateAccessType::Write + ), return err(warnings, errors), warnings, errors @@ -1274,14 +1289,15 @@ impl<'ir> AsmBuilder<'ir> { offset_reg } - fn compile_state_load_quad_word( + fn compile_state_access_quad_word( &mut self, instr_val: &Value, - load_val: &Value, + val: &Value, key: &Value, + access_type: StateAccessType, ) -> CompileResult<()> { // Make sure that both val and key are pointers to B256. - assert!(matches!(load_val.get_type(self.context), Some(Type::B256))); + assert!(matches!(val.get_type(self.context), Some(Type::B256))); assert!(matches!(key.get_type(self.context), Some(Type::B256))); let key_ptr = self.resolve_ptr(key); @@ -1295,42 +1311,43 @@ impl<'ir> AsmBuilder<'ir> { assert!(ptr_ty == Type::B256); // Expect ptr_ty here to also be b256 and offset to be whatever... - let load_val_ptr = self.resolve_ptr(load_val); - if load_val_ptr.value.is_none() { - return load_val_ptr.map(|_| ()); + let val_ptr = self.resolve_ptr(val); + if val_ptr.value.is_none() { + return val_ptr.map(|_| ()); } - let (load_val_ptr, ptr_ty, offset) = load_val_ptr.value.unwrap(); + let (val_ptr, ptr_ty, offset) = val_ptr.value.unwrap(); // Expect the ptr_ty for val to also be B256 assert!(ptr_ty == Type::B256); - match (self.ptr_map.get(&load_val_ptr), self.ptr_map.get(&key_ptr)) { - (Some(load_val_storage), Some(key_storage)) => { - match (load_val_storage.clone(), key_storage.clone()) { - (Storage::Stack(load_val_offset), Storage::Stack(key_offset)) => { - let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); - let load_val_reg = self.offset_reg( - &base_reg, - load_val_offset * 8 + offset * 32, - instr_val.get_span(self.context), - ); + match (self.ptr_map.get(&val_ptr), self.ptr_map.get(&key_ptr)) { + (Some(Storage::Stack(val_offset)), Some(Storage::Stack(key_offset))) => { + let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + let val_offset_in_bytes = val_offset * 8 + offset * 32; + let key_offset_in_bytes = key_offset * 8; - let key_reg = self.offset_reg( - &base_reg, - key_offset * 8, - instr_val.get_span(self.context), - ); + let val_reg = self.offset_reg( + &base_reg, + val_offset_in_bytes, + instr_val.get_span(self.context), + ); - self.bytecode.push(Op { - opcode: Either::Left(VirtualOp::SRWQ(load_val_reg, key_reg)), - comment: "quad state load value".into(), - owning_span: instr_val.get_span(self.context), - }); - } - _ => unreachable!("Unexpected storage locations for key and load_val"), - } + let key_reg = self.offset_reg( + &base_reg, + key_offset_in_bytes, + instr_val.get_span(self.context), + ); + + self.bytecode.push(Op { + opcode: Either::Left(match access_type { + StateAccessType::Read => VirtualOp::SRWQ(val_reg, key_reg), + StateAccessType::Write => VirtualOp::SWWQ(val_reg, key_reg), + }), + comment: "quad word state access".into(), + owning_span: instr_val.get_span(self.context), + }); } - _ => unreachable!("Unexpected uninitialised pointers"), + _ => unreachable!("Unexpected storage locations for key and val"), } ok((), Vec::new(), Vec::new()) @@ -1352,86 +1369,26 @@ impl<'ir> AsmBuilder<'ir> { let load_reg = self.reg_seqr.next(); match self.ptr_map.get(&key_ptr) { - Some(key_storage) => match key_storage.clone() { - Storage::Stack(key_offset) => { - let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); - let key_reg = self.offset_reg( - &base_reg, - key_offset * 8, - instr_val.get_span(self.context), - ); - - self.bytecode.push(Op { - opcode: Either::Left(VirtualOp::SRW(load_reg.clone(), key_reg)), - comment: "state load value".into(), - owning_span: instr_val.get_span(self.context), - }); - } - _ => unreachable!("Unexpected storage location for key"), - }, - _ => unreachable!("Unexpected uninitialised pointers"), - } - - self.reg_map.insert(*instr_val, load_reg); - ok((), Vec::new(), Vec::new()) - } - - fn compile_state_store_quad_word( - &mut self, - instr_val: &Value, - store_val: &Value, - key: &Value, - ) -> CompileResult<()> { - // Make sure that both val and key are pointers to B256. - assert!(matches!(store_val.get_type(self.context), Some(Type::B256))); - assert!(matches!(key.get_type(self.context), Some(Type::B256))); + Some(Storage::Stack(key_offset)) => { + let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + let key_offset_in_bytes = key_offset * 8; - let key_ptr = self.resolve_ptr(key); - if key_ptr.value.is_none() { - return key_ptr.map(|_| ()); - } - let (key_ptr, ptr_ty, offset) = key_ptr.value.unwrap(); - - // Not expecting an offset here nor a pointer cast - assert!(offset == 0); - assert!(ptr_ty == Type::B256); - - let store_val_ptr = self.resolve_ptr(store_val); - if store_val_ptr.value.is_none() { - return store_val_ptr.map(|_| ()); - } - let (store_val_ptr, ptr_ty, offset) = store_val_ptr.value.unwrap(); - assert!(ptr_ty == Type::B256); - - match (self.ptr_map.get(&store_val_ptr), self.ptr_map.get(&key_ptr)) { - (Some(store_val_storage), Some(key_storage)) => { - match (store_val_storage.clone(), key_storage.clone()) { - (Storage::Stack(store_val_offset), Storage::Stack(key_offset)) => { - let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); - let store_val_reg = self.offset_reg( - &base_reg, - store_val_offset * 8 + offset * 32, - instr_val.get_span(self.context), - ); - - let key_reg = self.offset_reg( - &base_reg, - key_offset * 8, - instr_val.get_span(self.context), - ); + let key_reg = self.offset_reg( + &base_reg, + key_offset_in_bytes, + instr_val.get_span(self.context), + ); - self.bytecode.push(Op { - opcode: Either::Left(VirtualOp::SWWQ(store_val_reg, key_reg)), - comment: "quad state store value".into(), - owning_span: instr_val.get_span(self.context), - }); - } - _ => unreachable!("Unexpected storage locations for key and store_val"), - } + self.bytecode.push(Op { + opcode: Either::Left(VirtualOp::SRW(load_reg.clone(), key_reg)), + comment: "single word state access".into(), + owning_span: instr_val.get_span(self.context), + }); } - _ => unreachable!("Unexpected uninitialised pointer"), + _ => unreachable!("Unexpected storage location for key"), } + self.reg_map.insert(*instr_val, load_reg); ok((), Vec::new(), Vec::new()) } @@ -1463,25 +1420,23 @@ impl<'ir> AsmBuilder<'ir> { assert!(ptr_ty == Type::B256); match self.ptr_map.get(&key_ptr) { - Some(key_storage) => match key_storage.clone() { - Storage::Stack(key_offset) => { - let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + Some(Storage::Stack(key_offset)) => { + let base_reg = self.stack_base_reg.as_ref().unwrap().clone(); + let key_offset_in_bytes = key_offset * 8; - let key_reg = self.offset_reg( - &base_reg, - key_offset * 8, - instr_val.get_span(self.context), - ); + let key_reg = self.offset_reg( + &base_reg, + key_offset_in_bytes, + instr_val.get_span(self.context), + ); - self.bytecode.push(Op { - opcode: Either::Left(VirtualOp::SWW(store_reg, key_reg)), - comment: "state load value".into(), - owning_span: instr_val.get_span(self.context), - }); - } - _ => unreachable!("Unexpected storage locations for key and store_val"), - }, - _ => unreachable!("Unexpected uninitialised pointer"), + self.bytecode.push(Op { + opcode: Either::Left(VirtualOp::SWW(store_reg, key_reg)), + comment: "single word state access".into(), + owning_span: instr_val.get_span(self.context), + }); + } + _ => unreachable!("Unexpected storage locations for key and store_val"), } ok((), Vec::new(), Vec::new()) diff --git a/sway-core/tests/ir_to_asm/storage_load.asm b/sway-core/tests/ir_to_asm/storage_load.asm index 7bb56213625..89fed7a1350 100644 --- a/sway-core/tests/ir_to_asm/storage_load.asm +++ b/sway-core/tests/ir_to_asm/storage_load.asm @@ -20,7 +20,7 @@ lw $r1 data_0 ; literal instantiation addi $r0 $r2 i0 ; get store offset mcpi $r0 $r1 i32 ; store value addi $r0 $r2 i0 ; get offset -srw $r0 $r0 ; state load value +srw $r0 $r0 ; single word state access ret $r0 move $r1 $sp ; save locals base register cfei i64 ; allocate 64 bytes for all locals @@ -31,7 +31,7 @@ mcpi $r0 $r2 i32 ; store value addi $r0 $r1 i32 ; get_ptr addi $r2 $r1 i32 ; get offset addi $r0 $r1 i0 ; get offset -srwq $r2 $r0 ; quad state load value +srwq $r2 $r0 ; quad word state access addi $r0 $r1 i32 ; get_ptr addi $r1 $r1 i32 ; load address lw $r0 data_2 ; loading size for RETD diff --git a/sway-core/tests/ir_to_asm/storage_load.ir b/sway-core/tests/ir_to_asm/storage_load.ir index e662cb98c73..033fbdd57bb 100644 --- a/sway-core/tests/ir_to_asm/storage_load.ir +++ b/sway-core/tests/ir_to_asm/storage_load.ir @@ -8,7 +8,7 @@ contract { v1 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 store v1, ptr v0 v2 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 - v3 = state_load_word ptr v0 + v3 = state_load_word key ptr v0 store v3, ptr v2 v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 v5 = load ptr v4 @@ -24,7 +24,7 @@ contract { v1 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c store v1, ptr v0 v2 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 - state_load_quad_word ptr v2, ptr v0 + state_load_quad_word ptr v2, key ptr v0 v3 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 v4 = load ptr v3 ret b256 v4 diff --git a/sway-core/tests/ir_to_asm/storage_store.asm b/sway-core/tests/ir_to_asm/storage_store.asm index d5ef518897d..cfd15ea75eb 100644 --- a/sway-core/tests/ir_to_asm/storage_store.asm +++ b/sway-core/tests/ir_to_asm/storage_store.asm @@ -11,7 +11,7 @@ eq $r0 $r1 $r0 ; function selector comparison jnei $zero $r0 i14 ; jump to selected function lw $r0 data_5 ; load fn selector for comparison eq $r0 $r1 $r0 ; function selector comparison -jnei $zero $r0 i25 ; jump to selected function +jnei $zero $r0 i26 ; jump to selected function rvrt $zero ; revert if no selectors matched move $r2 $sp ; save locals base register cfei i32 ; allocate 32 bytes for all locals @@ -20,8 +20,9 @@ addi $r0 $r2 i0 ; get_ptr lw $r1 data_1 ; literal instantiation addi $r0 $r2 i0 ; get store offset mcpi $r0 $r1 i32 ; store value +lw $r1 data_0 ; literal instantiation addi $r0 $r2 i0 ; get offset -srw $r0 $r0 ; state load value +sww $r1 $r0 ; single word state access ret $zero ; returning unit as zero move $r1 $sp ; save locals base register cfei i64 ; allocate 64 bytes for all locals @@ -36,8 +37,9 @@ mcpi $r0 $r2 i32 ; store value addi $r0 $r1 i32 ; get_ptr addi $r2 $r1 i32 ; get offset addi $r0 $r1 i0 ; get offset -swwq $r2 $r0 ; quad state store value +swwq $r2 $r0 ; quad word state access ret $zero ; returning unit as zero +noop ; word-alignment of data section .data: data_0 .u64 0x00 data_1 .b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 diff --git a/sway-core/tests/ir_to_asm/storage_store.ir b/sway-core/tests/ir_to_asm/storage_store.ir index 8417b628e86..2e46041a225 100644 --- a/sway-core/tests/ir_to_asm/storage_store.ir +++ b/sway-core/tests/ir_to_asm/storage_store.ir @@ -10,11 +10,9 @@ contract { v2 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 v3 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 store v3, ptr v2 - v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 - v5 = state_load_word ptr v2 - store v5, ptr v4 - v6 = const unit () - ret () v6 + state_store_word v1, key ptr v2 + v4 = const unit () + ret () v4 } fn set_y<858a3d18>() -> () { @@ -29,7 +27,7 @@ contract { v3 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c store v3, ptr v2 v4 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 - state_store_quad_word ptr v4, ptr v2 + state_store_quad_word ptr v4, key ptr v2 v5 = const unit () ret () v5 } diff --git a/sway-ir/src/parser.rs b/sway-ir/src/parser.rs index 7771805b200..a5175f6dbed 100644 --- a/sway-ir/src/parser.rs +++ b/sway-ir/src/parser.rs @@ -69,18 +69,11 @@ mod ir_builder { } } + + rule selector_id() -> [u8; 4] = "<" _ s:$(['0'..='9' | 'a'..='f' | 'A'..='F']*<8>) _ ">" _ { - let mut bytes: [u8; 4] = [0; 4]; - let mut cur_byte: u8 = 0; - for (idx, ch) in s.chars().enumerate() { - cur_byte = (cur_byte << 4) | ch.to_digit(16).unwrap() as u8; - if idx % 2 == 1 { - bytes[idx / 2] = cur_byte; - cur_byte = 0; - } - } - bytes + string_to_hex::<4>(s) } rule fn_arg() -> (IrAstTy, String, Option) @@ -225,22 +218,22 @@ mod ir_builder { } rule op_state_load_quad_word() -> IrAstOperation - = "state_load_quad_word" _ ptr() dst:id() comma() ptr() _ key:id() { + = "state_load_quad_word" _ ptr() dst:id() comma() "key" _ ptr() _ key:id() { IrAstOperation::StateLoadQuadWord(dst, key) } rule op_state_load_word() -> IrAstOperation - = "state_load_word" _ ptr() _ key:id() { + = "state_load_word" _ "key" _ ptr() _ key:id() { IrAstOperation::StateLoadWord(key) } rule op_state_store_quad_word() -> IrAstOperation - = "state_store_quad_word" _ ptr() src:id() comma() ptr() _ key:id() { + = "state_store_quad_word" _ ptr() src:id() comma() "key" _ ptr() _ key:id() { IrAstOperation::StateStoreQuadWord(src, key) } rule op_state_store_word() -> IrAstOperation - = "state_store_word" _ src:id() comma() ptr() _ key:id() { + = "state_store_word" _ src:id() comma() "key" _ ptr() _ key:id() { IrAstOperation::StateStoreWord(src, key) } @@ -303,16 +296,7 @@ mod ir_builder { / "true" _ { IrAstConstValue::Bool(true) } / "false" _ { IrAstConstValue::Bool(false) } / "0x" s:$(['0'..='9' | 'a'..='f' | 'A'..='F']*<64>) _ { - let mut bytes: [u8; 32] = [0; 32]; - let mut cur_byte: u8 = 0; - for (idx, ch) in s.chars().enumerate() { - cur_byte = (cur_byte << 4) | ch.to_digit(16).unwrap() as u8; - if idx % 2 == 1 { - bytes[idx / 2] = cur_byte; - cur_byte = 0; - } - } - IrAstConstValue::B256(bytes) + IrAstConstValue::B256(string_to_hex::<32>(s)) } / n:decimal() { IrAstConstValue::Number(n) } / string_const() @@ -988,6 +972,19 @@ mod ir_builder { } Ok(()) } + + fn string_to_hex(s: &str) -> [u8; N] { + let mut bytes: [u8; N] = [0; N]; + let mut cur_byte: u8 = 0; + for (idx, ch) in s.chars().enumerate() { + cur_byte = (cur_byte << 4) | ch.to_digit(16).unwrap() as u8; + if idx % 2 == 1 { + bytes[idx / 2] = cur_byte; + cur_byte = 0; + } + } + bytes + } } // ------------------------------------------------------------------------------------------------- diff --git a/sway-ir/src/printer.rs b/sway-ir/src/printer.rs index 1fdc99b5e98..346fe9d16c4 100644 --- a/sway-ir/src/printer.rs +++ b/sway-ir/src/printer.rs @@ -476,25 +476,25 @@ fn instruction_to_doc<'a>( ))) } Instruction::StateLoadQuadWord { load_val, key } => Doc::text_line(format!( - "state_load_quad_word ptr {}, ptr {}{}", + "state_load_quad_word ptr {}, key ptr {}{}", namer.name(context, load_val), namer.name(context, key), md_namer.meta_as_string(context, span_md_idx, true), )), Instruction::StateLoadWord(key) => Doc::text_line(format!( - "{} = state_load_word ptr {}{}", + "{} = state_load_word key ptr {}{}", namer.name(context, ins_value), namer.name(context, key), md_namer.meta_as_string(context, span_md_idx, true), )), Instruction::StateStoreQuadWord { stored_val, key } => Doc::text_line(format!( - "state_store_quad_word ptr {}, ptr {}{}", + "state_store_quad_word ptr {}, key ptr {}{}", namer.name(context, stored_val), namer.name(context, key), md_namer.meta_as_string(context, span_md_idx, true), )), Instruction::StateStoreWord { stored_val, key } => Doc::text_line(format!( - "state_store_word {}, ptr {}{}", + "state_store_word {}, key ptr {}{}", namer.name(context, stored_val), namer.name(context, key), md_namer.meta_as_string(context, span_md_idx, true), diff --git a/sway-ir/tests/ir_to_ir/constants_storage_load.in_ir b/sway-ir/tests/ir_to_ir/constants_storage_load.in_ir index 1b32ff93b3b..744e2e3cdf2 100644 --- a/sway-ir/tests/ir_to_ir/constants_storage_load.in_ir +++ b/sway-ir/tests/ir_to_ir/constants_storage_load.in_ir @@ -12,7 +12,7 @@ script { v1 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 store v1, ptr v0 v2 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 - v3 = state_load_word ptr v0 + v3 = state_load_word key ptr v0 store v3, ptr v2 v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 v5 = load ptr v4 @@ -22,7 +22,7 @@ script { v8 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c store v8, ptr v7 v9 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 - state_load_quad_word ptr v9, ptr v7 + state_load_quad_word ptr v9, key ptr v7 v10 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 v11 = load ptr v10 v12 = get_ptr ptr b256 y, ptr b256, 0 diff --git a/sway-ir/tests/ir_to_ir/constants_storage_load.out_ir b/sway-ir/tests/ir_to_ir/constants_storage_load.out_ir index 1b32ff93b3b..744e2e3cdf2 100644 --- a/sway-ir/tests/ir_to_ir/constants_storage_load.out_ir +++ b/sway-ir/tests/ir_to_ir/constants_storage_load.out_ir @@ -12,7 +12,7 @@ script { v1 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 store v1, ptr v0 v2 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 - v3 = state_load_word ptr v0 + v3 = state_load_word key ptr v0 store v3, ptr v2 v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 v5 = load ptr v4 @@ -22,7 +22,7 @@ script { v8 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c store v8, ptr v7 v9 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 - state_load_quad_word ptr v9, ptr v7 + state_load_quad_word ptr v9, key ptr v7 v10 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 v11 = load ptr v10 v12 = get_ptr ptr b256 y, ptr b256, 0 diff --git a/sway-ir/tests/ir_to_ir/constants_storage_store.in_ir b/sway-ir/tests/ir_to_ir/constants_storage_store.in_ir index 8417b628e86..2e46041a225 100644 --- a/sway-ir/tests/ir_to_ir/constants_storage_store.in_ir +++ b/sway-ir/tests/ir_to_ir/constants_storage_store.in_ir @@ -10,11 +10,9 @@ contract { v2 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 v3 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 store v3, ptr v2 - v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 - v5 = state_load_word ptr v2 - store v5, ptr v4 - v6 = const unit () - ret () v6 + state_store_word v1, key ptr v2 + v4 = const unit () + ret () v4 } fn set_y<858a3d18>() -> () { @@ -29,7 +27,7 @@ contract { v3 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c store v3, ptr v2 v4 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 - state_store_quad_word ptr v4, ptr v2 + state_store_quad_word ptr v4, key ptr v2 v5 = const unit () ret () v5 } diff --git a/sway-ir/tests/ir_to_ir/constants_storage_store.out_ir b/sway-ir/tests/ir_to_ir/constants_storage_store.out_ir index 8417b628e86..2e46041a225 100644 --- a/sway-ir/tests/ir_to_ir/constants_storage_store.out_ir +++ b/sway-ir/tests/ir_to_ir/constants_storage_store.out_ir @@ -10,11 +10,9 @@ contract { v2 = get_ptr mut ptr b256 key_for_x, ptr b256, 0 v3 = const b256 0x7fbd1192666bfac3767b890bd4d048c940879d316071e20c7c8c81bce2ca41c5 store v3, ptr v2 - v4 = get_ptr mut ptr u64 value_for_x, ptr u64, 0 - v5 = state_load_word ptr v2 - store v5, ptr v4 - v6 = const unit () - ret () v6 + state_store_word v1, key ptr v2 + v4 = const unit () + ret () v4 } fn set_y<858a3d18>() -> () { @@ -29,7 +27,7 @@ contract { v3 = const b256 0xa15d6d36b54df993ed1fbe4544a45d4c4f70d81b4229861dfde0e20eb652202c store v3, ptr v2 v4 = get_ptr mut ptr b256 value_for_y, ptr b256, 0 - state_store_quad_word ptr v4, ptr v2 + state_store_quad_word ptr v4, key ptr v2 v5 = const unit () ret () v5 } From 528a5b87a22e867530181176b3a054a8a137c781 Mon Sep 17 00:00:00 2001 From: Mohammad Fawaz Date: Tue, 15 Mar 2022 10:36:59 -0400 Subject: [PATCH 3/3] fmt --- sway-ir/src/parser.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway-ir/src/parser.rs b/sway-ir/src/parser.rs index a5175f6dbed..ffa53dacb19 100644 --- a/sway-ir/src/parser.rs +++ b/sway-ir/src/parser.rs @@ -69,7 +69,7 @@ mod ir_builder { } } - + rule selector_id() -> [u8; 4] = "<" _ s:$(['0'..='9' | 'a'..='f' | 'A'..='F']*<8>) _ ">" _ { @@ -972,7 +972,7 @@ mod ir_builder { } Ok(()) } - + fn string_to_hex(s: &str) -> [u8; N] { let mut bytes: [u8; N] = [0; N]; let mut cur_byte: u8 = 0;