@@ -230,16 +230,87 @@ where
230230// LLIL_INTRINSIC, LLIL_INTRINSIC_SSA
231231pub struct Intrinsic ;
232232
233+ #[ derive( Debug , Clone , Copy ) ]
234+ pub enum RegOrFlag {
235+ Reg ( CoreRegister ) ,
236+ Flag ( CoreFlag ) ,
237+ }
238+
239+ impl From < CoreRegister > for RegOrFlag {
240+ fn from ( value : CoreRegister ) -> Self {
241+ Self :: Reg ( value)
242+ }
243+ }
244+
245+ impl From < CoreFlag > for RegOrFlag {
246+ fn from ( value : CoreFlag ) -> Self {
247+ Self :: Flag ( value)
248+ }
249+ }
250+
233251impl < M , F > Operation < ' _ , M , F , Intrinsic >
234252where
235253 M : FunctionMutability ,
236254 F : FunctionForm ,
237255{
256+ // Order of operands for this operation:
257+ // 1. Number of outputs in the reg or flag list
258+ // 2. Reg or flag list
259+ // 3. Intrinsic id
260+ // 4. Operand list
261+
238262 // TODO: Support register and expression lists
239263 pub fn intrinsic ( & self ) -> Option < CoreIntrinsic > {
240264 let raw_id = self . op . operands [ 2 ] as u32 ;
241265 self . function . arch ( ) . intrinsic_from_id ( IntrinsicId ( raw_id) )
242266 }
267+
268+ /// Number of outputs the intrinsic has.
269+ #[ inline]
270+ pub fn output_count ( & self ) -> usize {
271+ self . op . operands [ 0 ] as usize
272+ }
273+
274+ /// Get the output list.
275+ pub fn outputs ( & self ) -> Vec < RegOrFlag > {
276+ let mut outputs = Vec :: new ( ) ;
277+ let mut output_size = self . op . operands [ 0 ] as usize ;
278+ if output_size == 0 {
279+ return outputs;
280+ }
281+ let out_list = unsafe {
282+ BNLowLevelILGetOperandList (
283+ self . function . handle ,
284+ self . expr_idx . 0 ,
285+ 0 ,
286+ & mut output_size as * mut _ ,
287+ )
288+ } ;
289+ let out_list = unsafe { std:: slice:: from_raw_parts_mut ( out_list, output_size) } ;
290+ for val in out_list. iter ( ) {
291+ if * val & ( 1 << 32 ) != 0 {
292+ outputs. push (
293+ self . function
294+ . arch ( )
295+ . flag_from_id ( FlagId ( ( * val & 0xffffffff ) as u32 ) )
296+ . expect ( "Invalid core flag ID" )
297+ . into ( ) ,
298+ ) ;
299+ } else {
300+ outputs. push (
301+ self . function
302+ . arch ( )
303+ . register_from_id ( RegisterId ( ( * val & 0xffffffff ) as u32 ) )
304+ . expect ( "Invalid register ID" )
305+ . into ( ) ,
306+ ) ;
307+ }
308+ }
309+ // Need to drop the list at the end. This will get leaked if there's a panic anywhere.
310+ // TODO: Make a new type for this that implements drop so it can't be leaked.
311+ unsafe { BNLowLevelILFreeOperandList ( out_list. as_mut_ptr ( ) ) } ;
312+ outputs
313+ }
243314}
244315
245316impl < M , F > Debug for Operation < ' _ , M , F , Intrinsic >
0 commit comments