@@ -230,19 +230,19 @@ where
230230// LLIL_INTRINSIC, LLIL_INTRINSIC_SSA
231231pub struct Intrinsic ;
232232
233- #[ derive( Debug , Clone , Copy ) ]
234- pub enum RegOrFlag {
233+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
234+ pub enum IntrinsicOutput {
235235 Reg ( CoreRegister ) ,
236236 Flag ( CoreFlag ) ,
237237}
238238
239- impl From < CoreRegister > for RegOrFlag {
239+ impl From < CoreRegister > for IntrinsicOutput {
240240 fn from ( value : CoreRegister ) -> Self {
241241 Self :: Reg ( value)
242242 }
243243}
244244
245- impl From < CoreFlag > for RegOrFlag {
245+ impl From < CoreFlag > for IntrinsicOutput {
246246 fn from ( value : CoreFlag ) -> Self {
247247 Self :: Flag ( value)
248248 }
@@ -253,63 +253,34 @@ where
253253 M : FunctionMutability ,
254254 F : FunctionForm ,
255255{
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-
262- // TODO: Support register and expression lists
263256 pub fn intrinsic ( & self ) -> Option < CoreIntrinsic > {
264257 let raw_id = self . op . operands [ 2 ] as u32 ;
265258 self . function . arch ( ) . intrinsic_from_id ( IntrinsicId ( raw_id) )
266259 }
267260
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-
274261 /// 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- ) ;
262+ pub fn outputs ( & self ) -> Vec < IntrinsicOutput > {
263+ // Convert the operand to either a register or flag id.
264+ let operand_to_output = |o : u64 | {
265+ if o & ( 1 << 32 ) != 0 {
266+ self . function
267+ . arch ( )
268+ . flag_from_id ( FlagId ( ( o & 0xffffffff ) as u32 ) )
269+ . expect ( "Invalid core flag ID" )
270+ . into ( )
299271 } 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- ) ;
272+ self . function
273+ . arch ( )
274+ . register_from_id ( RegisterId ( ( o & 0xffffffff ) as u32 ) )
275+ . expect ( "Invalid register ID" )
276+ . into ( )
307277 }
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
278+ } ;
279+
280+ self . get_operand_list ( 0 )
281+ . into_iter ( )
282+ . map ( operand_to_output)
283+ . collect :: < Vec < _ > > ( )
313284 }
314285
315286 /// Get the input list for the intrinsic.
@@ -330,9 +301,15 @@ where
330301 F : FunctionForm ,
331302{
332303 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
304+ use crate :: architecture:: Intrinsic ;
333305 f. debug_struct ( "Intrinsic" )
334306 . field ( "address" , & self . address ( ) )
335- . field ( "size" , & self . intrinsic ( ) )
307+ . field (
308+ "intrinsic" ,
309+ & self . intrinsic ( ) . expect ( "Valid intrinsic" ) . name ( ) ,
310+ )
311+ . field ( "outputs" , & self . outputs ( ) )
312+ . field ( "inputs" , & self . inputs ( ) )
336313 . finish ( )
337314 }
338315}
0 commit comments