Skip to content

Commit 3b80c81

Browse files
committed
improve transmute ir codegen
1 parent e2f5150 commit 3b80c81

File tree

2 files changed

+55
-36
lines changed
  • sway-core/src/ir_generation
  • test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute

2 files changed

+55
-36
lines changed

sway-core/src/ir_generation/function.rs

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,7 +2428,6 @@ impl<'a> FnCompiler<'a> {
24282428
return_type,
24292429
span,
24302430
)?;
2431-
let return_type_ir_type_ptr = Type::new_typed_pointer(context, return_type_ir_type);
24322431

24332432
let first_argument_expr = &arguments[0];
24342433
let first_argument_value = return_on_termination_or_extract!(
@@ -2437,24 +2436,50 @@ impl<'a> FnCompiler<'a> {
24372436
let first_argument_type = first_argument_value
24382437
.get_type(context)
24392438
.expect("transmute first argument type not found");
2440-
let first_argument_ptr =
2441-
store_to_memory(self, context, first_argument_value)?.expect_memory();
24422439

2443-
// check IR sizes match
2444-
let first_arg_size = first_argument_type.size(context).in_bytes();
2445-
let return_type_size = return_type_ir_type.size(context).in_bytes();
2446-
if first_arg_size != return_type_size {
2447-
return Err(CompileError::Internal(
2448-
"Types size do not match",
2449-
span.clone(),
2450-
));
2451-
}
2440+
let is_first_argument_ptr = first_argument_type.is_ptr(context);
2441+
let is_return_type_ptr = return_type_ir_type.is_ptr(context);
2442+
2443+
// Both types needs to be pointers
2444+
// or both need to be non pointers
2445+
let final_value = match (is_first_argument_ptr, is_return_type_ptr) {
2446+
(true, false) | (false, true) => {
2447+
return Err(CompileError::Internal(
2448+
"__transmute both types need to be references, or both need to be not references",
2449+
span.clone(),
2450+
));
2451+
},
2452+
(true, true) => {
2453+
let first_argument_value = first_argument_value.value();
2454+
self
2455+
.current_block
2456+
.append(context)
2457+
.cast_ptr(first_argument_value, return_type_ir_type)
2458+
},
2459+
(false, false) => {
2460+
// check IR sizes match
2461+
let first_arg_size = first_argument_type.size(context).in_bytes();
2462+
let return_type_size = return_type_ir_type.size(context).in_bytes();
2463+
2464+
if first_arg_size != return_type_size {
2465+
return Err(CompileError::Internal(
2466+
"Types size do not match",
2467+
span.clone(),
2468+
));
2469+
}
2470+
2471+
let return_type_ir_type_ptr = Type::new_typed_pointer(context, return_type_ir_type);
2472+
let first_argument_ptr = store_to_memory(self, context, first_argument_value)?.expect_memory();
2473+
2474+
let casted_ptr = self
2475+
.current_block
2476+
.append(context)
2477+
.cast_ptr(first_argument_ptr, return_type_ir_type_ptr);
2478+
2479+
self.current_block.append(context).load(casted_ptr)
2480+
},
2481+
};
24522482

2453-
let casted_ptr = self
2454-
.current_block
2455-
.append(context)
2456-
.cast_ptr(first_argument_ptr, return_type_ir_type_ptr);
2457-
let final_value = self.current_block.append(context).load(casted_ptr);
24582483
Ok(TerminatorValue::new(
24592484
CompiledValue::InRegister(final_value),
24602485
context,

test/src/e2e_vm_tests/test_programs/should_pass/language/intrinsics/transmute/stdout.snap

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ source: test/src/snapshot/mod.rs
55

66
fn transmute_by_reference_7(__ret_value: __ptr u256) -> __ptr u256 {
77
local [u8; 32] __anon_0
8-
local __ptr [u8; 32] __anon_1
98
local mut [u8; 32] bytes
109
local __ptr u256 v
1110

@@ -15,37 +14,32 @@ fn transmute_by_reference_7(__ret_value: __ptr u256) -> __ptr u256 {
1514
v1 = get_local __ptr [u8; 32], bytes
1615
mem_copy_val v1, v0
1716
v2 = get_local __ptr [u8; 32], bytes
18-
v3 = get_local __ptr __ptr [u8; 32], __anon_1
19-
store v2 to v3
20-
v4 = cast_ptr v3 to __ptr __ptr u256
17+
v3 = cast_ptr v2 to __ptr u256
18+
v4 = get_local __ptr __ptr u256, v
19+
store v3 to v4
2120
v5 = get_local __ptr __ptr u256, v
22-
mem_copy_val v5, v4
23-
v6 = get_local __ptr __ptr u256, v
24-
v7 = load v6
25-
mem_copy_val __ret_value, v7
21+
v6 = load v5
22+
mem_copy_val __ret_value, v6
2623
ret __ptr u256 __ret_value
2724
}
2825

2926

30-
pshl i15 ; save registers 16..40
27+
pshl i7 ; save registers 16..40
3128
pshh i524288 ; save registers 40..64
3229
move $$locbase $sp ; save locals base register for function transmute_by_reference_7
33-
cfei i80 ; allocate 80 bytes for locals and 0 slots for call arguments
30+
cfei i72 ; allocate 72 bytes for locals and 0 slots for call arguments
3431
move $r0 $$arg0 ; save argument 0 (__ret_value)
3532
move $r1 $$reta ; save return address
3633
mcli $$locbase i32 ; clear memory [u8; 32], 32 bytes
37-
addi $r2 $$locbase i40 ; get offset to local __ptr [u8; 32]
34+
addi $r2 $$locbase i32 ; get offset to local __ptr [u8; 32]
3835
mcpi $r2 $$locbase i32 ; copy memory
39-
addi $r2 $$locbase i40 ; get offset to local __ptr [u8; 32]
40-
addi $r3 $$locbase i32 ; get offset to local __ptr __ptr [u8; 32]
41-
sw $$locbase $r2 i4 ; store word
42-
addi $r2 $$locbase i72 ; get offset to local __ptr __ptr u256
43-
mcpi $r2 $r3 i8 ; copy memory
44-
lw $r2 $$locbase i9 ; load word
36+
addi $r2 $$locbase i32 ; get offset to local __ptr [u8; 32]
37+
sw $$locbase $r2 i8 ; store word
38+
lw $r2 $$locbase i8 ; load word
4539
mcpi $r0 $r2 i32 ; copy memory
4640
move $$retv $r0 ; set return value
47-
cfsi i80 ; free 80 bytes for locals and 0 slots for extra call arguments
41+
cfsi i72 ; free 72 bytes for locals and 0 slots for extra call arguments
4842
move $$reta $r1 ; restore return address
4943
poph i524288 ; restore registers 40..64
50-
popl i15 ; restore registers 16..40
44+
popl i7 ; restore registers 16..40
5145
jal $zero $$reta i0 ; return from call

0 commit comments

Comments
 (0)