@@ -10,7 +10,7 @@ use crate::oomir;
1010
1111use rustc_middle:: {
1212 mir:: {
13- BasicBlock , BasicBlockData , Body , Operand as MirOperand , Place , StatementKind ,
13+ BasicBlock , BasicBlockData , Body , Local , Operand as MirOperand , Place , StatementKind ,
1414 TerminatorKind ,
1515 } ,
1616 ty:: TyCtxt ,
@@ -33,6 +33,8 @@ pub fn convert_basic_block<'tcx>(
3333 // Use the basic block index as its label.
3434 let label = format ! ( "bb{}" , bb. index( ) ) ;
3535 let mut instructions = Vec :: new ( ) ;
36+ let mut mutable_borrow_arrays: HashMap < Local , ( Place < ' tcx > , String , oomir:: Type ) > =
37+ HashMap :: new ( ) ;
3638
3739 // Convert each MIR statement in the block.
3840 for stmt in & bb_data. statements {
@@ -48,6 +50,53 @@ pub fn convert_basic_block<'tcx>(
4850 // Add instructions needed to calculate the Rvalue
4951 instructions. extend ( rvalue_instructions) ;
5052
53+ if let rustc_middle:: mir:: Rvalue :: Ref (
54+ _,
55+ rustc_middle:: mir:: BorrowKind :: Mut { .. } ,
56+ borrowed_place,
57+ ) = rvalue
58+ {
59+ // Check if the destination is a simple local (most common case for &mut assignment)
60+ if place. projection . is_empty ( ) {
61+ if let oomir:: Operand :: Variable {
62+ name : array_var_name,
63+ ty : array_ty,
64+ } = & source_operand
65+ {
66+ // Extract element type from array type
67+ if let oomir:: Type :: MutableReference ( element_ty) = array_ty {
68+ println ! (
69+ "Info: Tracking mutable borrow array for place {:?} stored in local {:?}. Original: {:?}, ArrayVar: {}, ElementTy: {:?}" ,
70+ place, place. local, borrowed_place, array_var_name, element_ty
71+ ) ;
72+ mutable_borrow_arrays. insert (
73+ place. local , // The local holding the array reference (e.g., _3)
74+ (
75+ borrowed_place. clone ( ) , // The original place borrowed (e.g., _1)
76+ array_var_name. clone ( ) , // The OOMIR name of the array var (e.g., "3_tmp0")
77+ * element_ty. clone ( ) , // The type of the element in the array
78+ ) ,
79+ ) ;
80+ } else {
81+ println ! (
82+ "Warning: Expected type for mutable borrow ref, found {:?}" ,
83+ array_ty
84+ ) ;
85+ }
86+ } else {
87+ println ! (
88+ "Warning: Expected variable operand for mutable borrow ref assignment result, found {:?}" ,
89+ source_operand
90+ ) ;
91+ }
92+ } else {
93+ println ! (
94+ "Warning: Mutable borrow assigned to complex place {:?}, write-back might not work correctly." ,
95+ place
96+ ) ;
97+ }
98+ }
99+
51100 // 2. Generate instructions to store the computed value into the destination place
52101 let assignment_instructions = emit_instructions_to_set_value (
53102 place, // The actual destination Place
@@ -158,25 +207,110 @@ pub fn convert_basic_block<'tcx>(
158207 } => {
159208 println ! ( "the function name is {:?}" , func) ;
160209 let function_name = make_jvm_safe ( format ! ( "{:?}" , func) . as_str ( ) ) ; // Get function name - needs refinement to extract actual name
161- let oomir_args = args
162- . iter ( )
163- . map ( |arg| convert_operand ( & arg. node , tcx, mir, data_types, & mut instructions) )
164- . collect ( ) ;
165- let dest = Some ( format ! ( "{:?}" , destination. local) ) ;
166210
211+ // --- Track Argument Origins ---
212+ // Store tuples: (Maybe Original MIR Place of Arg, OOMIR Operand for Arg)
213+ let mut processed_args: Vec < ( Option < Place < ' tcx > > , oomir:: Operand ) > = Vec :: new ( ) ;
214+ let mut pre_call_instructions = Vec :: new ( ) ; // Instructions needed *before* the call for args
215+
216+ for arg in args {
217+ let mir_op = & arg. node ;
218+ // Important: Pass pre_call_instructions here to collect setup code for this arg
219+ let oomir_op =
220+ convert_operand ( mir_op, tcx, mir, data_types, & mut pre_call_instructions) ;
221+
222+ // Identify if the MIR operand is a direct use of a local Place
223+ let maybe_arg_place = match mir_op {
224+ MirOperand :: Move ( p) | MirOperand :: Copy ( p) if p. projection . is_empty ( ) => {
225+ Some ( p. clone ( ) )
226+ }
227+ _ => None ,
228+ } ;
229+ processed_args. push ( ( maybe_arg_place, oomir_op) ) ;
230+ }
231+ // Add instructions needed to prepare arguments *before* the call
232+ instructions. extend ( pre_call_instructions) ;
233+
234+ // Collect just the OOMIR operands for the call itself
235+ let oomir_args: Vec < oomir:: Operand > =
236+ processed_args. iter ( ) . map ( |( _, op) | op. clone ( ) ) . collect ( ) ;
237+
238+ // Determine destination OOMIR variable name (if any)
239+ let dest_var_name = destination. projection . is_empty ( )
240+ . then ( || format ! ( "_{}" , destination. local. index( ) ) )
241+ . or_else ( || {
242+ println ! ( "Warning: Call destination {:?} is complex, return value might be lost." , destination) ;
243+ None // Handle complex destinations if needed later
244+ } ) ;
245+
246+ // --- Emit the Call Instruction ---
167247 instructions. push ( oomir:: Instruction :: Call {
168- dest,
248+ dest : dest_var_name ,
169249 function : function_name,
170250 args : oomir_args,
171251 } ) ;
172252
253+ let mut write_back_instrs = Vec :: new ( ) ;
254+ for ( maybe_arg_place, oomir_arg_operand) in & processed_args {
255+ if let Some ( arg_place) = maybe_arg_place {
256+ // Check if the local used for this argument is one we tracked as a mutable borrow array
257+ if let Some ( ( original_place, array_var_name, element_ty) ) =
258+ mutable_borrow_arrays. get ( & arg_place. local )
259+ {
260+ // Double-check if the operand passed was indeed the variable we expected
261+ if let oomir:: Operand :: Variable {
262+ name : passed_var_name,
263+ ..
264+ } = oomir_arg_operand
265+ {
266+ println ! (
267+ "Info: Emitting write-back for mutable borrow. Arg Place: {:?}, Original Place: {:?}, Array Var: {}" ,
268+ arg_place, original_place, array_var_name
269+ ) ;
270+
271+ // Create a temporary variable for the value read from the array
272+ let temp_writeback_var =
273+ format ! ( "_writeback_{}" , original_place. local. index( ) ) ;
274+
275+ // 1. Get value from array (using the tracked array_var_name)
276+ let array_operand = oomir:: Operand :: Variable {
277+ name : array_var_name. clone ( ) ,
278+ // Reconstruct array type for clarity (though not strictly needed by ArrayGet)
279+ ty : oomir:: Type :: Array ( Box :: new ( element_ty. clone ( ) ) ) ,
280+ } ;
281+ write_back_instrs. push ( oomir:: Instruction :: ArrayGet {
282+ dest : temp_writeback_var. clone ( ) ,
283+ array : array_operand,
284+ index : oomir:: Operand :: Constant ( oomir:: Constant :: I32 ( 0 ) ) , // Always index 0
285+ } ) ;
286+
287+ // 2. Set value back to original place
288+ let value_to_set = oomir:: Operand :: Variable {
289+ name : temp_writeback_var,
290+ ty : element_ty. clone ( ) , // Use the tracked element type
291+ } ;
292+ let set_instrs = emit_instructions_to_set_value (
293+ original_place, // The original Place (_1)
294+ value_to_set, // The value read from the array
295+ tcx,
296+ mir,
297+ data_types,
298+ ) ;
299+ write_back_instrs. extend ( set_instrs) ;
300+ }
301+ }
302+ }
303+ }
304+ instructions. extend ( write_back_instrs) ;
305+
306+ // --- Add Jump to Target Block (if call returns) ---
173307 if let Some ( target_bb) = target {
174308 let target_label = format ! ( "bb{}" , target_bb. index( ) ) ;
175309 println ! (
176310 "Info: Adding Jump to {} after Call in bb{}" ,
177311 target_label,
178312 bb. index( )
179- ) ; // Add log
313+ ) ;
180314 instructions. push ( oomir:: Instruction :: Jump {
181315 target : target_label,
182316 } ) ;
0 commit comments