@@ -96,8 +96,9 @@ pub struct TraceCompiler {
96
96
available_regs : Vec < u8 > ,
97
97
/// Maps locals to their assigned registers.
98
98
assigned_regs : HashMap < Local , u8 > ,
99
- /// Stores the destination locals to which we copy RAX to after leaving an inlined call.
100
- leaves : Vec < Option < Place > > ,
99
+ /// Stores the destination local of the outermost function and moves its content into RAX at
100
+ /// the end of the trace.
101
+ rtn_var : Option < Place > ,
101
102
}
102
103
103
104
impl TraceCompiler {
@@ -127,6 +128,15 @@ impl TraceCompiler {
127
128
128
129
fn free_register ( & mut self , local : & Local ) {
129
130
if let Some ( reg) = self . assigned_regs . remove ( local) {
131
+ if local == & self . rtn_var . as_ref ( ) . unwrap ( ) . local {
132
+ // We currently assume that we only trace a single function which leaves its return
133
+ // value in RAX. Since we now inline a function's return variable this won't happen
134
+ // automatically anymore. To keep things working, we thus copy the return value of
135
+ // the most outer function into RAX at the end of the trace.
136
+ dynasm ! ( self . asm
137
+ ; mov rax, Rq ( reg)
138
+ ) ;
139
+ }
130
140
self . available_regs . push ( reg) ;
131
141
}
132
142
}
@@ -217,19 +227,9 @@ impl TraceCompiler {
217
227
} ,
218
228
}
219
229
}
220
- // Remember the return destination.
221
- self . leaves . push ( dest. as_ref ( ) . cloned ( ) ) ;
222
- Ok ( ( ) )
223
- }
224
-
225
- fn c_leave ( & mut self ) -> Result < ( ) , CompileError > {
226
- let dest = self . leaves . pop ( ) ;
227
- if let Some ( d) = dest {
228
- if let Some ( d) = d {
229
- // When we see a leave statement move whatever's left in RAX into the destination
230
- // local.
231
- self . mov_local_local ( d. local , Local ( 0 ) ) ?;
232
- }
230
+ if self . rtn_var . is_none ( ) {
231
+ // Remember the return variable of the most outer function.
232
+ self . rtn_var = dest. as_ref ( ) . cloned ( ) ;
233
233
}
234
234
Ok ( ( ) )
235
235
}
@@ -313,7 +313,7 @@ impl TraceCompiler {
313
313
} ;
314
314
}
315
315
Statement :: Enter ( op, args, dest, off) => self . c_enter ( op, args, dest, * off) ?,
316
- Statement :: Leave => self . c_leave ( ) ? ,
316
+ Statement :: Leave => { }
317
317
Statement :: StorageLive ( _) => { }
318
318
Statement :: StorageDead ( l) => self . free_register ( l) ,
319
319
Statement :: Call ( target, args, dest) => self . c_call ( target, args, dest) ?,
@@ -388,7 +388,7 @@ impl TraceCompiler {
388
388
// Use all the 64-bit registers we can (R15-R8, RDX, RCX).
389
389
available_regs : vec ! [ 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 2 , 1 ] ,
390
390
assigned_regs : HashMap :: new ( ) ,
391
- leaves : Vec :: new ( ) ,
391
+ rtn_var : None ,
392
392
} ;
393
393
394
394
for i in 0 ..tt. len ( ) {
@@ -452,7 +452,7 @@ mod tests {
452
452
asm : dynasmrt:: x64:: Assembler :: new ( ) . unwrap ( ) ,
453
453
available_regs : vec ! [ 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 2 , 1 ] ,
454
454
assigned_regs : HashMap :: new ( ) ,
455
- leaves : Vec :: new ( ) ,
455
+ rtn_var : None ,
456
456
} ;
457
457
458
458
for _ in 0 ..32 {
@@ -470,7 +470,7 @@ mod tests {
470
470
asm : dynasmrt:: x64:: Assembler :: new ( ) . unwrap ( ) ,
471
471
available_regs : vec ! [ 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 2 , 1 ] ,
472
472
assigned_regs : HashMap :: new ( ) ,
473
- leaves : Vec :: new ( ) ,
473
+ rtn_var : None ,
474
474
} ;
475
475
476
476
let mut seen = HashSet :: new ( ) ;
0 commit comments