@@ -20,6 +20,31 @@ use super::{
2020 ptr_escape:: PtrEscapeSummary ,
2121} ;
2222
23+ #[ derive( Clone , Copy , Debug , Default , PartialEq , Eq ) ]
24+ pub ( crate ) struct MallocEscapeKind ( u8 ) ;
25+
26+ impl MallocEscapeKind {
27+ pub ( crate ) const RETURNS_TO_CALLER : Self = Self ( 1 << 0 ) ;
28+ pub ( crate ) const STORED_NON_LOCAL : Self = Self ( 1 << 1 ) ;
29+ pub ( crate ) const UNKNOWN : Self = Self ( 1 << 2 ) ;
30+
31+ pub ( crate ) fn has_global_or_unknown ( self ) -> bool {
32+ self . contains ( Self :: STORED_NON_LOCAL ) || self . contains ( Self :: UNKNOWN )
33+ }
34+
35+ pub ( crate ) fn is_return_only ( self ) -> bool {
36+ self . contains ( Self :: RETURNS_TO_CALLER ) && !self . has_global_or_unknown ( )
37+ }
38+
39+ fn contains ( self , other : Self ) -> bool {
40+ self . 0 & other. 0 != 0
41+ }
42+
43+ fn union ( self , other : Self ) -> Self {
44+ Self ( self . 0 | other. 0 )
45+ }
46+ }
47+
2348pub ( crate ) fn should_restore_free_ptr_on_internal_returns (
2449 function : & Function ,
2550 module : & ModuleCtx ,
@@ -202,7 +227,7 @@ pub(crate) fn compute_transient_mallocs(
202227 let local_mem = & prov_info. local_mem ;
203228
204229 let block_malloc_in = compute_block_malloc_in ( function, isa) ;
205- let escaping = compute_escaping_mallocs (
230+ let escape_kinds = compute_malloc_escape_kinds (
206231 function,
207232 module,
208233 isa,
@@ -212,8 +237,8 @@ pub(crate) fn compute_transient_mallocs(
212237 & block_malloc_in,
213238 ) ;
214239
215- for base in escaping {
216- mallocs. remove ( & base ) ;
240+ for malloc in escape_kinds . keys ( ) {
241+ mallocs. remove ( malloc ) ;
217242 }
218243
219244 for block in function. layout . iter_block ( ) {
@@ -269,12 +294,12 @@ pub(crate) fn compute_transient_mallocs(
269294 mallocs
270295}
271296
272- pub ( crate ) fn compute_escaping_mallocs_for_function (
297+ pub ( crate ) fn compute_malloc_escape_kinds_for_function (
273298 function : & Function ,
274299 module : & ModuleCtx ,
275300 isa : & Evm ,
276301 ptr_escape : & FxHashMap < FuncRef , PtrEscapeSummary > ,
277- ) -> FxHashSet < InstId > {
302+ ) -> FxHashMap < InstId , MallocEscapeKind > {
278303 let prov_info = compute_provenance ( function, module, isa, |callee| {
279304 ptr_escape
280305 . get ( & callee)
@@ -285,7 +310,7 @@ pub(crate) fn compute_escaping_mallocs_for_function(
285310 let prov = & prov_info. value ;
286311 let local_mem = & prov_info. local_mem ;
287312 let block_malloc_in = compute_block_malloc_in ( function, isa) ;
288- compute_escaping_mallocs (
313+ compute_malloc_escape_kinds (
289314 function,
290315 module,
291316 isa,
@@ -385,24 +410,50 @@ fn compute_block_malloc_in(
385410}
386411
387412fn record_escaping_mallocs (
388- escaping : & mut FxHashSet < InstId > ,
413+ escape_kinds : & mut FxHashMap < InstId , MallocEscapeKind > ,
389414 value : ValueId ,
390415 prov : & SecondaryMap < ValueId , Provenance > ,
391416 seen_mallocs : & BitSet < InstId > ,
417+ direct_kind : MallocEscapeKind ,
392418) {
393419 let p = & prov[ value] ;
394- record_escaping_provenance ( escaping , p, seen_mallocs) ;
420+ record_escaping_provenance ( escape_kinds , p, seen_mallocs, direct_kind ) ;
395421}
396422
397423fn record_escaping_provenance (
398- escaping : & mut FxHashSet < InstId > ,
424+ escape_kinds : & mut FxHashMap < InstId , MallocEscapeKind > ,
399425 p : & Provenance ,
400426 seen_mallocs : & BitSet < InstId > ,
427+ direct_kind : MallocEscapeKind ,
401428) {
402429 if p. is_unknown_ptr ( ) {
403- escaping. extend ( seen_mallocs. iter ( ) ) ;
430+ for malloc in seen_mallocs. iter ( ) {
431+ record_escape_kind ( escape_kinds, malloc, MallocEscapeKind :: UNKNOWN ) ;
432+ }
433+ }
434+ for malloc in p. malloc_insts ( ) {
435+ record_escape_kind ( escape_kinds, malloc, direct_kind) ;
436+ }
437+ }
438+
439+ fn record_escape_kind (
440+ escape_kinds : & mut FxHashMap < InstId , MallocEscapeKind > ,
441+ malloc : InstId ,
442+ kind : MallocEscapeKind ,
443+ ) {
444+ escape_kinds
445+ . entry ( malloc)
446+ . and_modify ( |cur| * cur = cur. union ( kind) )
447+ . or_insert ( kind) ;
448+ }
449+
450+ fn record_unknown_seen_mallocs (
451+ escape_kinds : & mut FxHashMap < InstId , MallocEscapeKind > ,
452+ seen_mallocs : & BitSet < InstId > ,
453+ ) {
454+ for malloc in seen_mallocs. iter ( ) {
455+ record_escape_kind ( escape_kinds, malloc, MallocEscapeKind :: UNKNOWN ) ;
404456 }
405- escaping. extend ( p. malloc_insts ( ) ) ;
406457}
407458
408459fn local_copy_source_may_be_heap_derived (
@@ -428,16 +479,16 @@ fn local_copy_source_may_be_heap_derived(
428479 !any
429480}
430481
431- fn compute_escaping_mallocs (
482+ fn compute_malloc_escape_kinds (
432483 function : & Function ,
433484 module : & ModuleCtx ,
434485 isa : & Evm ,
435486 ptr_escape : & FxHashMap < FuncRef , PtrEscapeSummary > ,
436487 prov : & SecondaryMap < ValueId , Provenance > ,
437488 local_mem : & FxHashMap < InstId , Provenance > ,
438489 block_malloc_in : & SecondaryMap < BlockId , BitSet < InstId > > ,
439- ) -> FxHashSet < InstId > {
440- let mut escaping : FxHashSet < InstId > = FxHashSet :: default ( ) ;
490+ ) -> FxHashMap < InstId , MallocEscapeKind > {
491+ let mut escape_kinds : FxHashMap < InstId , MallocEscapeKind > = FxHashMap :: default ( ) ;
441492
442493 for block in function. layout . iter_block ( ) {
443494 let mut seen_mallocs = block_malloc_in[ block] . clone ( ) ;
@@ -448,7 +499,13 @@ fn compute_escaping_mallocs(
448499 let Some ( ret_val) = * ret. arg ( ) else {
449500 continue ;
450501 } ;
451- record_escaping_mallocs ( & mut escaping, ret_val, prov, & seen_mallocs) ;
502+ record_escaping_mallocs (
503+ & mut escape_kinds,
504+ ret_val,
505+ prov,
506+ & seen_mallocs,
507+ MallocEscapeKind :: RETURNS_TO_CALLER ,
508+ ) ;
452509 }
453510 EvmInstKind :: Mstore ( mstore) => {
454511 let addr = * mstore. addr ( ) ;
@@ -457,7 +514,13 @@ fn compute_escaping_mallocs(
457514 }
458515
459516 let val = * mstore. value ( ) ;
460- record_escaping_mallocs ( & mut escaping, val, prov, & seen_mallocs) ;
517+ record_escaping_mallocs (
518+ & mut escape_kinds,
519+ val,
520+ prov,
521+ & seen_mallocs,
522+ MallocEscapeKind :: STORED_NON_LOCAL ,
523+ ) ;
461524 }
462525 EvmInstKind :: EvmMstore8 ( mstore8) => {
463526 let addr = * mstore8. addr ( ) ;
@@ -466,7 +529,13 @@ fn compute_escaping_mallocs(
466529 }
467530
468531 let val = * mstore8. val ( ) ;
469- record_escaping_mallocs ( & mut escaping, val, prov, & seen_mallocs) ;
532+ record_escaping_mallocs (
533+ & mut escape_kinds,
534+ val,
535+ prov,
536+ & seen_mallocs,
537+ MallocEscapeKind :: STORED_NON_LOCAL ,
538+ ) ;
470539 }
471540 EvmInstKind :: EvmMcopy ( mcopy) => {
472541 let dest = * mcopy. dest ( ) ;
@@ -481,16 +550,21 @@ fn compute_escaping_mallocs(
481550 for base in src_prov. alloca_insts ( ) {
482551 any = true ;
483552 if let Some ( stored) = local_mem. get ( & base) {
484- record_escaping_provenance ( & mut escaping, stored, & seen_mallocs) ;
553+ record_escaping_provenance (
554+ & mut escape_kinds,
555+ stored,
556+ & seen_mallocs,
557+ MallocEscapeKind :: STORED_NON_LOCAL ,
558+ ) ;
485559 }
486560 }
487561 if !any {
488- escaping . extend ( seen_mallocs. iter ( ) ) ;
562+ record_unknown_seen_mallocs ( & mut escape_kinds , & seen_mallocs) ;
489563 }
490564 } else {
491565 // Unknown source bytes copied to non-local memory may include malloc-derived
492566 // pointers from this function.
493- escaping . extend ( seen_mallocs. iter ( ) ) ;
567+ record_unknown_seen_mallocs ( & mut escape_kinds , & seen_mallocs) ;
494568 }
495569 }
496570 EvmInstKind :: Call ( call) => {
@@ -501,7 +575,13 @@ fn compute_escaping_mallocs(
501575 . unwrap_or_else ( || conservative_unknown_ptr_summary ( module, callee) ) ;
502576 for ( idx, & arg) in call. args ( ) . iter ( ) . enumerate ( ) {
503577 if idx < callee_sum. arg_may_escape . len ( ) && callee_sum. arg_may_escape [ idx] {
504- record_escaping_mallocs ( & mut escaping, arg, prov, & seen_mallocs) ;
578+ record_escaping_mallocs (
579+ & mut escape_kinds,
580+ arg,
581+ prov,
582+ & seen_mallocs,
583+ MallocEscapeKind :: STORED_NON_LOCAL ,
584+ ) ;
505585 }
506586 }
507587 }
@@ -514,7 +594,7 @@ fn compute_escaping_mallocs(
514594 }
515595 }
516596
517- escaping
597+ escape_kinds
518598}
519599
520600fn conservative_unknown_ptr_summary ( module : & ModuleCtx , func_ref : FuncRef ) -> PtrEscapeSummary {
0 commit comments