@@ -77,20 +77,43 @@ impl RawCode {
77
77
}
78
78
79
79
/// Returns `Some(code)` iff the raw code is a function that can be inlined
80
+ ///
81
+ /// Type hints and breakpoints are stripped.
80
82
pub fn inlined_body ( & self ) -> Option < Vec < LabelledInstruction > > {
81
- // If the RawCode contains a recurse, it cannot be inlined
82
- if self
83
+ let is_label = |x : & _ | matches ! ( x, LabelledInstruction :: Label ( _) ) ;
84
+ let is_instruction = |x : & _ | matches ! ( x, LabelledInstruction :: Instruction ( _) ) ;
85
+ let is_recursive = |x : & _ | {
86
+ matches ! (
87
+ x,
88
+ LabelledInstruction :: Instruction ( AnInstruction :: Recurse )
89
+ | LabelledInstruction :: Instruction ( AnInstruction :: RecurseOrReturn )
90
+ )
91
+ } ;
92
+
93
+ if self . function . iter ( ) . any ( is_recursive) {
94
+ // recursion needs to be wrapped in a function
95
+ return None ;
96
+ }
97
+
98
+ let mut labels_and_instructions = self
83
99
. function
84
100
. iter ( )
85
- . any ( |x| matches ! ( x, LabelledInstruction :: Instruction ( AnInstruction :: Recurse ) ) )
86
- {
87
- None
88
- } else if self . function . len ( ) == 2 {
89
- Some ( triton_asm ! ( ) )
90
- } else {
91
- // Remove label and `return`
92
- Some ( self . function [ 1 ..=self . function . len ( ) - 2 ] . to_vec ( ) )
93
- }
101
+ . filter ( |i| is_label ( i) || is_instruction ( i) ) ;
102
+
103
+ let Some ( first_thing) = labels_and_instructions. next ( ) else {
104
+ return Some ( triton_asm ! ( ) ) ;
105
+ } ;
106
+ let LabelledInstruction :: Label ( _) = first_thing else {
107
+ panic ! ( "Raw Code must start with a label." )
108
+ } ;
109
+
110
+ let Some ( LabelledInstruction :: Instruction ( AnInstruction :: Return ) ) =
111
+ labels_and_instructions. next_back ( )
112
+ else {
113
+ panic ! ( "Raw Code is probably buggy: too short, or doesn't end with `return`." ) ;
114
+ } ;
115
+
116
+ Some ( labels_and_instructions. cloned ( ) . collect ( ) )
94
117
}
95
118
}
96
119
@@ -219,3 +242,30 @@ impl InnerFunction {
219
242
} ;
220
243
}
221
244
}
245
+
246
+ #[ cfg( test) ]
247
+ mod tests {
248
+ use super :: * ;
249
+
250
+ #[ test]
251
+ fn breakpoint_does_not_influence_raw_code_inlining ( ) {
252
+ let raw_code = RawCode {
253
+ function : triton_asm ! { my_label: return break } ,
254
+ input_type : DataType :: VoidPointer ,
255
+ output_type : DataType :: VoidPointer ,
256
+ } ;
257
+ let inlined_code = raw_code. inlined_body ( ) . unwrap ( ) ;
258
+ assert_eq ! ( triton_asm!( ) , inlined_code) ;
259
+ }
260
+
261
+ #[ test]
262
+ fn type_hints_do_not_influence_raw_code_inlining ( ) {
263
+ let raw_code = RawCode {
264
+ function : triton_asm ! { my_label: hint a = stack[ 0 ] hint b = stack[ 1 ] return } ,
265
+ input_type : DataType :: VoidPointer ,
266
+ output_type : DataType :: VoidPointer ,
267
+ } ;
268
+ let inlined_code = raw_code. inlined_body ( ) . unwrap ( ) ;
269
+ assert_eq ! ( triton_asm!( ) , inlined_code) ;
270
+ }
271
+ }
0 commit comments