@@ -10,7 +10,7 @@ use crate::oomir;
10
10
11
11
use rustc_middle:: {
12
12
mir:: {
13
- BasicBlock , BasicBlockData , Body , Operand as MirOperand , Place , StatementKind ,
13
+ BasicBlock , BasicBlockData , Body , Local , Operand as MirOperand , Place , StatementKind ,
14
14
TerminatorKind ,
15
15
} ,
16
16
ty:: TyCtxt ,
@@ -33,6 +33,8 @@ pub fn convert_basic_block<'tcx>(
33
33
// Use the basic block index as its label.
34
34
let label = format ! ( "bb{}" , bb. index( ) ) ;
35
35
let mut instructions = Vec :: new ( ) ;
36
+ let mut mutable_borrow_arrays: HashMap < Local , ( Place < ' tcx > , String , oomir:: Type ) > =
37
+ HashMap :: new ( ) ;
36
38
37
39
// Convert each MIR statement in the block.
38
40
for stmt in & bb_data. statements {
@@ -48,6 +50,53 @@ pub fn convert_basic_block<'tcx>(
48
50
// Add instructions needed to calculate the Rvalue
49
51
instructions. extend ( rvalue_instructions) ;
50
52
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
+
51
100
// 2. Generate instructions to store the computed value into the destination place
52
101
let assignment_instructions = emit_instructions_to_set_value (
53
102
place, // The actual destination Place
@@ -158,25 +207,110 @@ pub fn convert_basic_block<'tcx>(
158
207
} => {
159
208
println ! ( "the function name is {:?}" , func) ;
160
209
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) ) ;
166
210
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 ---
167
247
instructions. push ( oomir:: Instruction :: Call {
168
- dest,
248
+ dest : dest_var_name ,
169
249
function : function_name,
170
250
args : oomir_args,
171
251
} ) ;
172
252
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) ---
173
307
if let Some ( target_bb) = target {
174
308
let target_label = format ! ( "bb{}" , target_bb. index( ) ) ;
175
309
println ! (
176
310
"Info: Adding Jump to {} after Call in bb{}" ,
177
311
target_label,
178
312
bb. index( )
179
- ) ; // Add log
313
+ ) ;
180
314
instructions. push ( oomir:: Instruction :: Jump {
181
315
target : target_label,
182
316
} ) ;
0 commit comments