@@ -286,12 +286,95 @@ impl Memory {
286
286
}
287
287
Ok ( addr. into ( ) )
288
288
}
289
+ #[ cfg( not( feature = "extensive_hints" ) ) ]
290
+ fn flatten_relocation_rules ( & mut self ) -> Result < ( ) , MemoryError > {
291
+ let keys: Vec < usize > = self . relocation_rules . keys ( ) . copied ( ) . collect ( ) ;
292
+ let max_hops = self . relocation_rules . len ( ) . saturating_add ( 1 ) ;
293
+ for key in keys {
294
+ let mut dst = * self
295
+ . relocation_rules
296
+ . get ( & key)
297
+ . expect ( "key taken from keys vec must exist" ) ;
298
+
299
+ let mut hops = 0usize ;
300
+ while dst. segment_index < 0 {
301
+ let next_key = ( -( dst. segment_index + 1 ) ) as usize ;
302
+ let next = * self . relocation_rules . get ( & next_key) . ok_or_else ( || {
303
+ MemoryError :: UnallocatedSegment ( Box :: new ( ( next_key, self . temp_data . len ( ) ) ) )
304
+ } ) ?;
305
+ dst = ( next + dst. offset ) . map_err ( MemoryError :: Math ) ?;
306
+ hops += 1 ;
307
+ if hops > max_hops {
308
+ return Err ( MemoryError :: Relocation ) ; // cycle guard
309
+ }
310
+ }
311
+ self . relocation_rules . insert ( key, dst) ;
312
+ }
313
+ Ok ( ( ) )
314
+ }
315
+
316
+ #[ cfg( feature = "extensive_hints" ) ]
317
+ fn flatten_relocation_rules ( & mut self ) -> Result < ( ) , MemoryError > {
318
+ let keys: Vec < usize > = self . relocation_rules . keys ( ) . copied ( ) . collect ( ) ;
319
+ let max_hops = self . relocation_rules . len ( ) . saturating_add ( 1 ) ;
320
+ for key in keys {
321
+ let mut dst = self
322
+ . relocation_rules
323
+ . get ( & key)
324
+ . expect ( "key taken from keys vec must exist" )
325
+ . clone ( ) ;
326
+
327
+ let mut hops = 0usize ;
328
+ loop {
329
+ match dst {
330
+ MaybeRelocatable :: RelocatableValue ( r) if r. segment_index < 0 => {
331
+ let next_key = ( -( r. segment_index + 1 ) ) as usize ;
332
+ let next = self
333
+ . relocation_rules
334
+ . get ( & next_key)
335
+ . ok_or_else ( || {
336
+ MemoryError :: UnallocatedSegment ( Box :: new ( (
337
+ next_key,
338
+ self . temp_data . len ( ) ,
339
+ ) ) )
340
+ } ) ?
341
+ . clone ( ) ;
342
+
343
+ match next {
344
+ MaybeRelocatable :: RelocatableValue ( nr) => {
345
+ dst = MaybeRelocatable :: RelocatableValue (
346
+ ( nr + r. offset ) . map_err ( MemoryError :: Math ) ?,
347
+ ) ;
348
+ }
349
+ MaybeRelocatable :: Int ( i) => {
350
+ if r. offset != 0 {
351
+ return Err ( MemoryError :: NonZeroOffset ( r. offset ) ) ;
352
+ }
353
+ MaybeRelocatable :: Int ( i)
354
+ }
355
+ }
356
+ }
357
+ _ => break ,
358
+ }
359
+ hops += 1 ;
360
+ if hops > max_hops {
361
+ return Err ( MemoryError :: Relocation ) ;
362
+ }
363
+ }
364
+ self . relocation_rules . insert ( key, dst) ;
365
+ }
366
+ Ok ( ( ) )
367
+ }
289
368
290
369
/// Relocates the memory according to the relocation rules and clears `self.relocaction_rules`.
291
370
pub fn relocate_memory ( & mut self ) -> Result < ( ) , MemoryError > {
292
371
if self . relocation_rules . is_empty ( ) || self . temp_data . is_empty ( ) {
293
372
return Ok ( ( ) ) ;
294
373
}
374
+
375
+ // flatten chains (temp->temp->...->real).
376
+ self . flatten_relocation_rules ( ) ?;
377
+
295
378
// Relocate temporary addresses in memory
296
379
for segment in self . data . iter_mut ( ) . chain ( self . temp_data . iter_mut ( ) ) {
297
380
for cell in segment. iter_mut ( ) {
@@ -345,6 +428,7 @@ impl Memory {
345
428
self . relocation_rules . clear ( ) ;
346
429
Ok ( ( ) )
347
430
}
431
+
348
432
/// Add a new relocation rule.
349
433
///
350
434
/// When using feature "extensive_hints" the destination is allowed to be an Integer (via
0 commit comments