From 7328c45b71fa9116ec7589a74346946dd64cb0c6 Mon Sep 17 00:00:00 2001 From: Mohammad Fawaz Date: Thu, 21 Apr 2022 00:30:19 -0400 Subject: [PATCH] Correct handling string return values (#1292) * Correct handling string return values * Fix tests --- sway-core/src/asm_generation/from_ir.rs | 6 ++--- .../tests/ir_to_asm/enum_struct_string.asm | 24 +++++++++---------- sway-ir/src/irtype.rs | 3 +++ .../language/is_reference_type/src/main.sw | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/sway-core/src/asm_generation/from_ir.rs b/sway-core/src/asm_generation/from_ir.rs index 746c3fbd1cf..4d3fa1b138d 100644 --- a/sway-core/src/asm_generation/from_ir.rs +++ b/sway-core/src/asm_generation/from_ir.rs @@ -352,11 +352,11 @@ impl<'ir> AsmBuilder<'ir> { self.ptr_map.insert(*ptr, Storage::Stack(stack_base)); stack_base += 4; } - Type::String(_) => { + Type::String(n) => { // Strings are always constant and used by reference, so we only store the // pointer on the stack. self.ptr_map.insert(*ptr, Storage::Stack(stack_base)); - stack_base += 1; + stack_base += size_bytes_round_up_to_word_alignment!(n) } Type::Array(_) | Type::Struct(_) | Type::Union(_) => { // Store this aggregate at the current stack base. @@ -2119,7 +2119,7 @@ pub fn ir_type_size_in_bytes(context: &Context, ty: &Type) -> u64 { match ty { Type::Unit | Type::Bool | Type::Uint(_) => 8, Type::B256 => 32, - Type::String(_) => 8, + Type::String(n) => size_bytes_round_up_to_word_alignment!(n), Type::Array(aggregate) => { if let AggregateContent::ArrayType(el_ty, cnt) = &context.aggregates[aggregate.0] { cnt * ir_type_size_in_bytes(context, el_ty) diff --git a/sway-core/tests/ir_to_asm/enum_struct_string.asm b/sway-core/tests/ir_to_asm/enum_struct_string.asm index 5b223b65bce..148f0f70500 100644 --- a/sway-core/tests/ir_to_asm/enum_struct_string.asm +++ b/sway-core/tests/ir_to_asm/enum_struct_string.asm @@ -6,28 +6,28 @@ DATA_SECTION_OFFSET[32..64] lw $ds $is 1 add $$ds $$ds $is move $r4 $sp ; save locals base register -cfei i32 ; allocate 32 bytes for all locals +cfei i48 ; allocate 48 bytes for all locals move $r3 $sp ; save register for temporary stack value -cfei i40 ; allocate 40 bytes for temporary struct +cfei i56 ; allocate 56 bytes for temporary struct lw $r0 data_0 ; literal instantiation sw $r3 $r0 i0 ; insert_value @ 0 move $r2 $sp ; save register for temporary stack value -cfei i16 ; allocate 16 bytes for temporary struct +cfei i32 ; allocate 32 bytes for temporary struct lw $r1 data_1 ; literal instantiation addi $r0 $r2 i0 ; get struct field(s) 0 offset -mcpi $r0 $r1 i8 ; store struct field value +mcpi $r0 $r1 i24 ; store struct field value lw $r0 data_2 ; literal instantiation -sw $r2 $r0 i1 ; insert_value @ 1 +sw $r2 $r0 i3 ; insert_value @ 1 move $r1 $sp ; save register for temporary stack value -cfei i32 ; allocate 32 bytes for temporary struct +cfei i48 ; allocate 48 bytes for temporary struct addi $r0 $r1 i0 ; get struct field(s) 0 offset -mcpi $r0 $r2 i16 ; store struct field value +mcpi $r0 $r2 i32 ; store struct field value lw $r0 data_3 ; literal instantiation -sw $r1 $r0 i2 ; insert_value @ 1 +sw $r1 $r0 i4 ; insert_value @ 1 lw $r0 data_4 ; literal instantiation -sw $r1 $r0 i3 ; insert_value @ 2 +sw $r1 $r0 i5 ; insert_value @ 2 addi $r0 $r3 i8 ; get struct field(s) 1 offset -mcpi $r0 $r1 i32 ; store struct field value +mcpi $r0 $r1 i48 ; store struct field value lw $r1 $r3 i0 ; extract_value @ 0 lw $r0 data_0 ; literal instantiation eq $r0 $r1 $r0 @@ -35,9 +35,9 @@ jnei $r0 $one i41 addi $r1 $r3 i8 ; extract address addi $r0 $r4 i0 ; get_ptr addi $r0 $r4 i0 ; get store offset -mcpi $r0 $r1 i32 ; store value +mcpi $r0 $r1 i48 ; store value addi $r0 $r4 i0 ; get_ptr -lw $r0 $r0 i2 ; extract_value @ 1 +lw $r0 $r0 i4 ; extract_value @ 1 ji i42 lw $r0 data_0 ; literal instantiation ret $r0 diff --git a/sway-ir/src/irtype.rs b/sway-ir/src/irtype.rs index 5548742e572..5cb3a8e2504 100644 --- a/sway-ir/src/irtype.rs +++ b/sway-ir/src/irtype.rs @@ -26,6 +26,9 @@ pub enum Type { impl Type { /// Return whether this is a 'copy' type, one whose value will always fit in a register. pub fn is_copy_type(&self) -> bool { + if let Type::String(n) = self { + return *n <= 8; + } matches!(self, Type::Unit | Type::Bool | Type::Uint(_)) } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/src/main.sw index 5bbc1318d7c..cda82573a78 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/src/main.sw @@ -20,7 +20,7 @@ fn main() -> bool { assert(!is_reference_type::()); assert(!is_reference_type::()); - assert(is_reference_type::()); + assert(!is_reference_type::()); assert(is_reference_type::()); assert(is_reference_type::()); assert(is_reference_type::());