@@ -322,10 +322,10 @@ pub enum ComponentValType {
322322}
323323
324324impl ComponentValType {
325- pub ( crate ) fn requires_realloc ( & self , types : & TypeList ) -> bool {
325+ pub ( crate ) fn contains_ptr ( & self , types : & TypeList ) -> bool {
326326 match self {
327- ComponentValType :: Primitive ( ty) => ty. requires_realloc ( ) ,
328- ComponentValType :: Type ( ty) => types[ * ty] . unwrap_defined ( ) . requires_realloc ( types) ,
327+ ComponentValType :: Primitive ( ty) => ty. contains_ptr ( ) ,
328+ ComponentValType :: Type ( ty) => types[ * ty] . unwrap_defined ( ) . contains_ptr ( types) ,
329329 }
330330 }
331331
@@ -660,14 +660,24 @@ pub struct ComponentFuncType {
660660impl ComponentFuncType {
661661 /// Lowers the component function type to core parameter and result types for the
662662 /// canonical ABI.
663- pub ( crate ) fn lower ( & self , types : & TypeList , import : bool ) -> LoweringInfo {
663+ pub ( crate ) fn lower ( & self , types : & TypeList , is_lower : bool ) -> LoweringInfo {
664664 let mut info = LoweringInfo :: default ( ) ;
665665
666666 for ( _, ty) in self . params . iter ( ) {
667- // When `import` is false, it means we're lifting a core function,
668- // check if the parameters needs realloc
669- if !import && !info. requires_realloc {
670- info. requires_realloc = ty. requires_realloc ( types) ;
667+ // Check to see if `ty` has a pointer somewhere in it, needed for
668+ // any type that transitively contains either a string or a list.
669+ // In this situation lowered functions must specify `memory`, and
670+ // lifted functions must specify `realloc` as well. Lifted functions
671+ // gain their memory requirement through the final clause of this
672+ // function.
673+ if is_lower {
674+ if !info. requires_memory {
675+ info. requires_memory = ty. contains_ptr ( types) ;
676+ }
677+ } else {
678+ if !info. requires_realloc {
679+ info. requires_realloc = ty. contains_ptr ( types) ;
680+ }
671681 }
672682
673683 if !ty. push_wasm_types ( types, & mut info. params ) {
@@ -679,25 +689,27 @@ impl ComponentFuncType {
679689 info. requires_memory = true ;
680690
681691 // We need realloc as well when lifting a function
682- if !import {
692+ if !is_lower {
683693 info. requires_realloc = true ;
684694 }
685695 break ;
686696 }
687697 }
688698
689699 for ( _, ty) in self . results . iter ( ) {
690- // When `import` is true, it means we're lowering a component function,
691- // check if the result needs realloc
692- if import && !info. requires_realloc {
693- info. requires_realloc = ty. requires_realloc ( types) ;
700+ // Results of lowered functions that contains pointers must be
701+ // allocated by the callee meaning that realloc is required.
702+ // Results of lifted function are allocated by the guest which
703+ // means that no realloc option is necessary.
704+ if is_lower && !info. requires_realloc {
705+ info. requires_realloc = ty. contains_ptr ( types) ;
694706 }
695707
696708 if !ty. push_wasm_types ( types, & mut info. results ) {
697709 // Too many results to return directly, either a retptr parameter will be used (import)
698710 // or a single pointer will be returned (export)
699711 info. results . clear ( ) ;
700- if import {
712+ if is_lower {
701713 info. params . max = MAX_LOWERED_TYPES ;
702714 assert ! ( info. params. push( ValType :: I32 ) ) ;
703715 } else {
@@ -795,23 +807,22 @@ pub enum ComponentDefinedType {
795807}
796808
797809impl ComponentDefinedType {
798- pub ( crate ) fn requires_realloc ( & self , types : & TypeList ) -> bool {
810+ pub ( crate ) fn contains_ptr ( & self , types : & TypeList ) -> bool {
799811 match self {
800- Self :: Primitive ( ty) => ty. requires_realloc ( ) ,
801- Self :: Record ( r) => r. fields . values ( ) . any ( |ty| ty. requires_realloc ( types) ) ,
802- Self :: Variant ( v) => v. cases . values ( ) . any ( |case| {
803- case. ty
804- . map ( |ty| ty. requires_realloc ( types) )
805- . unwrap_or ( false )
806- } ) ,
812+ Self :: Primitive ( ty) => ty. contains_ptr ( ) ,
813+ Self :: Record ( r) => r. fields . values ( ) . any ( |ty| ty. contains_ptr ( types) ) ,
814+ Self :: Variant ( v) => v
815+ . cases
816+ . values ( )
817+ . any ( |case| case. ty . map ( |ty| ty. contains_ptr ( types) ) . unwrap_or ( false ) ) ,
807818 Self :: List ( _) => true ,
808- Self :: Tuple ( t) => t. types . iter ( ) . any ( |ty| ty. requires_realloc ( types) ) ,
809- Self :: Union ( u) => u. types . iter ( ) . any ( |ty| ty. requires_realloc ( types) ) ,
819+ Self :: Tuple ( t) => t. types . iter ( ) . any ( |ty| ty. contains_ptr ( types) ) ,
820+ Self :: Union ( u) => u. types . iter ( ) . any ( |ty| ty. contains_ptr ( types) ) ,
810821 Self :: Flags ( _) | Self :: Enum ( _) | Self :: Own ( _) | Self :: Borrow ( _) => false ,
811- Self :: Option ( ty) => ty. requires_realloc ( types) ,
822+ Self :: Option ( ty) => ty. contains_ptr ( types) ,
812823 Self :: Result { ok, err } => {
813- ok. map ( |ty| ty. requires_realloc ( types) ) . unwrap_or ( false )
814- || err. map ( |ty| ty. requires_realloc ( types) ) . unwrap_or ( false )
824+ ok. map ( |ty| ty. contains_ptr ( types) ) . unwrap_or ( false )
825+ || err. map ( |ty| ty. contains_ptr ( types) ) . unwrap_or ( false )
815826 }
816827 }
817828 }
0 commit comments