@@ -82,6 +82,16 @@ pub trait CallingConvention: Sync {
8282 fn register_argument_list_kind ( & self , _reg_list_id : u32 ) -> RegisterListKind {
8383 RegisterListKind :: IntegerSemantics
8484 }
85+
86+ // Optional method for custom parameter allocation
87+ // Returns None to use default implementation, or Some(Vec<Variable>) for custom allocation
88+ fn variables_for_parameters (
89+ & self ,
90+ _params : & [ FunctionParameter ] ,
91+ _permitted_regs : Option < & [ RegisterId ] > ,
92+ ) -> Option < Vec < Variable > > {
93+ None
94+ }
8595}
8696
8797pub fn register_calling_convention < A , C > ( arch : & A , name : & str , cc : C ) -> Ref < CoreCallingConvention >
@@ -502,6 +512,69 @@ where
502512 )
503513 }
504514
515+ extern "C" fn cb_variable_for_parameters < C > (
516+ ctxt : * mut c_void ,
517+ params : * const BNFunctionParameter ,
518+ param_count : usize ,
519+ permitted_regs : * const u32 ,
520+ permitted_reg_count : usize ,
521+ result_count : * mut usize ,
522+ ) -> * mut BNVariable
523+ where
524+ C : CallingConvention ,
525+ {
526+ ffi_wrap ! ( "CallingConvention::variables_for_parameters" , unsafe {
527+ let ctxt = & * ( ctxt as * mut CustomCallingConventionContext <C >) ;
528+
529+ // Convert C parameters to Rust
530+ let params_slice = std:: slice:: from_raw_parts( params, param_count) ;
531+ let rust_params: Vec <FunctionParameter > = params_slice
532+ . iter( )
533+ . map( |p| FunctionParameter :: from_raw( p) )
534+ . collect( ) ;
535+
536+ // Convert permitted registers if provided
537+ let permitted_reg_ids: Option <Vec <RegisterId >> = if permitted_regs. is_null( ) {
538+ None
539+ } else {
540+ let regs_slice = std:: slice:: from_raw_parts( permitted_regs, permitted_reg_count) ;
541+ Some ( regs_slice. iter( ) . map( |& id| RegisterId ( id) ) . collect( ) )
542+ } ;
543+
544+ // Call the trait method
545+ if let Some ( variables) = ctxt. cc. variables_for_parameters(
546+ & rust_params,
547+ permitted_reg_ids. as_ref( ) . map( |v| v. as_slice( ) ) ,
548+ ) {
549+ // Convert Vec<Variable> to *mut BNVariable using From trait
550+ let mut raw_variables: Vec <BNVariable > = variables
551+ . into_iter( )
552+ . map( |v| BNVariable :: from( v) )
553+ . collect( ) ;
554+
555+ * result_count = raw_variables. len( ) ;
556+ let ptr = raw_variables. as_mut_ptr( ) ;
557+ std:: mem:: forget( raw_variables) ;
558+ ptr
559+ } else {
560+ // Return null to use default implementation
561+ * result_count = 0 ;
562+ std:: ptr:: null_mut( )
563+ }
564+ } )
565+ }
566+
567+ extern "C" fn cb_free_variable_list ( _ctxt : * mut c_void , vars : * mut BNVariable , count : usize ) {
568+ ffi_wrap ! ( "CallingConvention::free_variable_list" , unsafe {
569+ if vars. is_null( ) {
570+ return ;
571+ }
572+
573+ let vars_ptr = std:: ptr:: slice_from_raw_parts_mut( vars, count) ;
574+ let _vars = Box :: from_raw( vars_ptr) ;
575+ } )
576+ }
577+
505578 let name = name. to_cstr ( ) ;
506579 let raw = Box :: into_raw ( Box :: new ( CustomCallingConventionContext {
507580 raw_handle : std:: ptr:: null_mut ( ) ,
@@ -524,6 +597,9 @@ where
524597 getRegisterArgumentLists : Some ( cb_register_argument_lists :: < C > ) ,
525598 getRegisterArgumentListKind : Some ( cb_register_argument_list_kind :: < C > ) ,
526599
600+ getVariablesForParameters : Some ( cb_variable_for_parameters :: < C > ) ,
601+ freeVariableList : Some ( cb_free_variable_list) ,
602+
527603 areArgumentRegistersSharedIndex : Some ( cb_arg_shared_index :: < C > ) ,
528604 isStackReservedForArgumentRegisters : Some ( cb_stack_reserved_arg_regs :: < C > ) ,
529605 isStackAdjustedOnReturn : Some ( cb_stack_adjusted_on_return :: < C > ) ,
0 commit comments