@@ -34,6 +34,13 @@ use crate::variable::Variable;
3434// CallingConvention impl
3535// dataflow callbacks
3636
37+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
38+ #[ repr( u32 ) ]
39+ pub enum RegisterListKind {
40+ IntegerSemantics = 0 ,
41+ FloatSemantics = 1 ,
42+ }
43+
3744pub trait CallingConvention : Sync {
3845 fn caller_saved_registers ( & self ) -> Vec < RegisterId > ;
3946 fn callee_saved_registers ( & self ) -> Vec < RegisterId > ;
@@ -53,6 +60,27 @@ pub trait CallingConvention: Sync {
5360
5461 fn implicitly_defined_registers ( & self ) -> Vec < RegisterId > ;
5562 fn are_argument_registers_used_for_var_args ( & self ) -> bool ;
63+
64+ // Register-list/class based API with default implementations
65+ fn register_argument_classes ( & self ) -> Vec < u32 > {
66+ Vec :: new ( )
67+ }
68+
69+ fn register_argument_class_lists ( & self , _class_id : u32 ) -> Vec < u32 > {
70+ Vec :: new ( )
71+ }
72+
73+ fn register_argument_lists ( & self ) -> Vec < u32 > {
74+ Vec :: new ( )
75+ }
76+
77+ fn register_argument_list_regs ( & self , _reg_list_id : u32 ) -> Vec < RegisterId > {
78+ Vec :: new ( )
79+ }
80+
81+ fn register_argument_list_kind ( & self , _reg_list_id : u32 ) -> RegisterListKind {
82+ RegisterListKind :: IntegerSemantics
83+ }
5684}
5785
5886pub fn register_calling_convention < A , C > ( arch : & A , name : & str , cc : C ) -> Ref < CoreCallingConvention >
@@ -290,6 +318,102 @@ where
290318 } )
291319 }
292320
321+ extern "C" fn cb_register_argument_classes < C > ( ctxt : * mut c_void , count : * mut usize ) -> * mut u32
322+ where
323+ C : CallingConvention ,
324+ {
325+ ffi_wrap ! ( "CallingConvention::register_argument_classes" , unsafe {
326+ let ctxt = & * ( ctxt as * mut CustomCallingConventionContext <C >) ;
327+ let mut class_ids = ctxt. cc. register_argument_classes( ) ;
328+
329+ // SAFETY: `count` is an out parameter
330+ * count = class_ids. len( ) ;
331+ let ptr = class_ids. as_mut_ptr( ) ;
332+ std:: mem:: forget( class_ids) ;
333+ ptr
334+ } )
335+ }
336+
337+ extern "C" fn cb_register_argument_class_lists < C > (
338+ ctxt : * mut c_void ,
339+ class_id : u32 ,
340+ count : * mut usize ,
341+ ) -> * mut u32
342+ where
343+ C : CallingConvention ,
344+ {
345+ ffi_wrap ! ( "CallingConvention::register_argument_class_lists" , unsafe {
346+ let ctxt = & * ( ctxt as * mut CustomCallingConventionContext <C >) ;
347+ let mut list_ids = ctxt. cc. register_argument_class_lists( class_id) ;
348+
349+ // SAFETY: `count` is an out parameter
350+ * count = list_ids. len( ) ;
351+ let ptr = list_ids. as_mut_ptr( ) ;
352+ std:: mem:: forget( list_ids) ;
353+ ptr
354+ } )
355+ }
356+
357+ extern "C" fn cb_register_argument_lists < C > (
358+ ctxt : * mut c_void ,
359+ count : * mut usize ,
360+ ) -> * mut u32
361+ where
362+ C : CallingConvention ,
363+ {
364+ ffi_wrap ! ( "CallingConvention::register_argument_lists" , unsafe {
365+ let ctxt = & * ( ctxt as * mut CustomCallingConventionContext <C >) ;
366+ let mut list_ids = ctxt. cc. register_argument_lists( ) ;
367+
368+ // SAFETY: `count` is an out parameter
369+ * count = list_ids. len( ) ;
370+ let ptr = list_ids. as_mut_ptr( ) ;
371+ std:: mem:: forget( list_ids) ;
372+ ptr
373+ } )
374+ }
375+
376+ extern "C" fn cb_register_argument_list_regs < C > (
377+ ctxt : * mut c_void ,
378+ reg_list_id : u32 ,
379+ count : * mut usize ,
380+ ) -> * mut u32
381+ where
382+ C : CallingConvention ,
383+ {
384+ ffi_wrap ! ( "CallingConvention::register_argument_list_regs" , unsafe {
385+ let ctxt = & * ( ctxt as * mut CustomCallingConventionContext <C >) ;
386+ let mut regs: Vec <_> = ctxt
387+ . cc
388+ . register_argument_list_regs( reg_list_id)
389+ . iter( )
390+ . map( |r| r. 0 )
391+ . collect( ) ;
392+
393+ // SAFETY: `count` is an out parameter
394+ * count = regs. len( ) ;
395+ let ptr = regs. as_mut_ptr( ) ;
396+ std:: mem:: forget( regs) ;
397+ ptr
398+ } )
399+ }
400+
401+ extern "C" fn cb_register_argument_list_kind < C > (
402+ ctxt : * mut c_void ,
403+ reg_list_id : u32 ,
404+ ) -> BNRegisterListKind
405+ where
406+ C : CallingConvention ,
407+ {
408+ ffi_wrap ! ( "CallingConvention::register_argument_list_kind" , unsafe {
409+ let ctxt = & * ( ctxt as * mut CustomCallingConventionContext <C >) ;
410+ match ctxt. cc. register_argument_list_kind( reg_list_id) {
411+ RegisterListKind :: IntegerSemantics => BNRegisterListKind :: REGISTER_LIST_KIND_INTEGER_SEMANTICS ,
412+ RegisterListKind :: FloatSemantics => BNRegisterListKind :: REGISTER_LIST_KIND_FLOAT_SEMANTICS ,
413+ }
414+ } )
415+ }
416+
293417 #[ allow( clippy:: extra_unused_type_parameters) ]
294418 extern "C" fn cb_incoming_reg_value < C > (
295419 _ctxt : * mut c_void ,
@@ -392,6 +516,12 @@ where
392516 getFloatArgumentRegisters : Some ( cb_float_args :: < C > ) ,
393517 freeRegisterList : Some ( cb_free_register_list) ,
394518
519+ getRegisterArgumentClasses : Some ( cb_register_argument_classes :: < C > ) ,
520+ getRegisterArgumentClassLists : Some ( cb_register_argument_class_lists :: < C > ) ,
521+ getRegisterArgumentListRegs : Some ( cb_register_argument_list_regs :: < C > ) ,
522+ getRegisterArgumentLists : Some ( cb_register_argument_lists :: < C > ) ,
523+ getRegisterArgumentListKind : Some ( cb_register_argument_list_kind :: < C > ) ,
524+
395525 areArgumentRegistersSharedIndex : Some ( cb_arg_shared_index :: < C > ) ,
396526 isStackReservedForArgumentRegisters : Some ( cb_stack_reserved_arg_regs :: < C > ) ,
397527 isStackAdjustedOnReturn : Some ( cb_stack_adjusted_on_return :: < C > ) ,
@@ -611,6 +741,69 @@ impl CallingConvention for CoreCallingConvention {
611741 }
612742 }
613743
744+ fn register_argument_classes ( & self ) -> Vec < u32 > {
745+ unsafe {
746+ let mut count = 0 ;
747+ let classes_ptr = BNGetRegisterArgumentClasses ( self . handle , & mut count) ;
748+ let classes: Vec < u32 > = std:: slice:: from_raw_parts ( classes_ptr, count)
749+ . iter ( )
750+ . copied ( )
751+ . collect ( ) ;
752+ BNFreeRegisterList ( classes_ptr) ;
753+ classes
754+ }
755+ }
756+
757+ fn register_argument_class_lists ( & self , class_id : u32 ) -> Vec < u32 > {
758+ unsafe {
759+ let mut count = 0 ;
760+ let lists_ptr = BNGetRegisterArgumentClassLists ( self . handle , class_id, & mut count) ;
761+ let lists: Vec < u32 > = std:: slice:: from_raw_parts ( lists_ptr, count)
762+ . iter ( )
763+ . copied ( )
764+ . collect ( ) ;
765+ BNFreeRegisterList ( lists_ptr) ;
766+ lists
767+ }
768+ }
769+
770+ fn register_argument_list_regs ( & self , reg_list_id : u32 ) -> Vec < RegisterId > {
771+ unsafe {
772+ let mut count = 0 ;
773+ let regs_ptr = BNGetRegisterArgumentListRegs ( self . handle , reg_list_id, & mut count) ;
774+ let regs: Vec < RegisterId > = std:: slice:: from_raw_parts ( regs_ptr, count)
775+ . iter ( )
776+ . copied ( )
777+ . map ( RegisterId :: from)
778+ . collect ( ) ;
779+ BNFreeRegisterList ( regs_ptr) ;
780+ regs
781+ }
782+ }
783+
784+ fn register_argument_lists ( & self ) -> Vec < u32 > {
785+ unsafe {
786+ let mut count = 0 ;
787+ let lists_ptr = BNGetRegisterArgumentLists ( self . handle , & mut count) ;
788+ let lists: Vec < u32 > = std:: slice:: from_raw_parts ( lists_ptr, count)
789+ . iter ( )
790+ . copied ( )
791+ . collect ( ) ;
792+ BNFreeRegisterList ( lists_ptr) ;
793+ lists
794+ }
795+ }
796+
797+ fn register_argument_list_kind ( & self , reg_list_id : u32 ) -> RegisterListKind {
798+ unsafe {
799+ let kind = BNGetRegisterArgumentListKind ( self . handle , reg_list_id) ;
800+ match kind {
801+ BNRegisterListKind :: REGISTER_LIST_KIND_INTEGER_SEMANTICS => RegisterListKind :: IntegerSemantics ,
802+ BNRegisterListKind :: REGISTER_LIST_KIND_FLOAT_SEMANTICS => RegisterListKind :: FloatSemantics ,
803+ }
804+ }
805+ }
806+
614807 fn arg_registers_shared_index ( & self ) -> bool {
615808 unsafe { BNAreArgumentRegistersSharedIndex ( self . handle ) }
616809 }
0 commit comments