@@ -522,7 +522,12 @@ pub enum Insn {
522522 } ,
523523
524524 // Invoke a builtin function
525- InvokeBuiltin { bf : rb_builtin_function , args : Vec < InsnId > , state : InsnId } ,
525+ InvokeBuiltin {
526+ bf : rb_builtin_function ,
527+ args : Vec < InsnId > ,
528+ state : InsnId ,
529+ return_type : Option < Type > , // None for unannotated builtins
530+ } ,
526531
527532 /// Control flow instructions
528533 Return { val : InsnId } ,
@@ -1163,7 +1168,7 @@ impl Function {
11631168 args : find_vec ! ( args) ,
11641169 state,
11651170 } ,
1166- & InvokeBuiltin { bf, ref args, state } => InvokeBuiltin { bf : bf , args : find_vec ! ( args) , state } ,
1171+ & InvokeBuiltin { bf, ref args, state, return_type } => InvokeBuiltin { bf, args : find_vec ! ( args) , state, return_type } ,
11671172 & ArrayDup { val, state } => ArrayDup { val : find ! ( val) , state } ,
11681173 & HashDup { val, state } => HashDup { val : find ! ( val) , state } ,
11691174 & CCall { cfun, ref args, name, return_type, elidable } => CCall { cfun, args : find_vec ! ( args) , name, return_type, elidable } ,
@@ -1260,7 +1265,7 @@ impl Function {
12601265 Insn :: SendWithoutBlock { .. } => types:: BasicObject ,
12611266 Insn :: SendWithoutBlockDirect { .. } => types:: BasicObject ,
12621267 Insn :: Send { .. } => types:: BasicObject ,
1263- Insn :: InvokeBuiltin { .. } => types:: BasicObject ,
1268+ Insn :: InvokeBuiltin { return_type , .. } => return_type . unwrap_or ( types:: BasicObject ) ,
12641269 Insn :: Defined { .. } => types:: BasicObject ,
12651270 Insn :: DefinedIvar { .. } => types:: BasicObject ,
12661271 Insn :: GetConstantPath { .. } => types:: BasicObject ,
@@ -3119,7 +3124,18 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
31193124 args. reverse ( ) ;
31203125
31213126 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
3122- let insn_id = fun. push_insn ( block, Insn :: InvokeBuiltin { bf, args, state : exit_id } ) ;
3127+
3128+ // Check if this builtin is annotated
3129+ let return_type = ZJITState :: get_method_annotations ( )
3130+ . get_builtin_properties ( & bf)
3131+ . map ( |props| props. return_type ) ;
3132+
3133+ let insn_id = fun. push_insn ( block, Insn :: InvokeBuiltin {
3134+ bf,
3135+ args,
3136+ state : exit_id,
3137+ return_type,
3138+ } ) ;
31233139 state. stack_push ( insn_id) ;
31243140 }
31253141 YARVINSN_opt_invokebuiltin_delegate |
@@ -3134,7 +3150,18 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
31343150 }
31353151
31363152 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
3137- let insn_id = fun. push_insn ( block, Insn :: InvokeBuiltin { bf, args, state : exit_id } ) ;
3153+
3154+ // Check if this builtin is annotated
3155+ let return_type = ZJITState :: get_method_annotations ( )
3156+ . get_builtin_properties ( & bf)
3157+ . map ( |props| props. return_type ) ;
3158+
3159+ let insn_id = fun. push_insn ( block, Insn :: InvokeBuiltin {
3160+ bf,
3161+ args,
3162+ state : exit_id,
3163+ return_type,
3164+ } ) ;
31383165 state. stack_push ( insn_id) ;
31393166 }
31403167 YARVINSN_objtostring => {
@@ -4974,12 +5001,28 @@ mod tests {
49745001
49755002 #[ test]
49765003 fn test_invokebuiltin_delegate_with_args ( ) {
5004+ // Using an unannotated builtin to test InvokeBuiltin generation
5005+ let iseq = crate :: cruby:: with_rubyvm ( || get_method_iseq ( "GC" , "start" ) ) ;
5006+ assert ! ( iseq_contains_opcode( iseq, YARVINSN_invokebuiltin ) , "iseq GC.start does not contain invokebuiltin" ) ;
5007+ let function = iseq_to_hir ( iseq) . unwrap ( ) ;
5008+ assert_function_hir ( function, expect ! [ [ r#"
5009+ fn start@<internal:gc>:36:
5010+ bb0(v0:BasicObject, v1:BasicObject, v2:BasicObject, v3:BasicObject, v4:BasicObject):
5011+ v6:FalseClass = Const Value(false)
5012+ v8:BasicObject = InvokeBuiltin gc_start_internal, v0, v1, v2, v3, v6
5013+ Return v8
5014+ "# ] ] ) ;
5015+ }
5016+
5017+ #[ test]
5018+ fn test_invokebuiltin_delegate_annotated ( ) {
5019+ // Test that Float now generates InvokeBuiltin with correct return type
49775020 assert_method_hir_with_opcode ( "Float" , YARVINSN_opt_invokebuiltin_delegate_leave , expect ! [ [ r#"
49785021 fn Float@<internal:kernel>:197:
49795022 bb0(v0:BasicObject, v1:BasicObject, v2:BasicObject, v3:BasicObject):
4980- v6:BasicObject = InvokeBuiltin rb_f_float, v0, v1, v2
5023+ v6:Flonum = InvokeBuiltin rb_f_float, v0, v1, v2
49815024 Jump bb1(v0, v1, v2, v3, v6)
4982- bb1(v8:BasicObject, v9:BasicObject, v10:BasicObject, v11:BasicObject, v12:BasicObject ):
5025+ bb1(v8:BasicObject, v9:BasicObject, v10:BasicObject, v11:BasicObject, v12:Flonum ):
49835026 Return v12
49845027 "# ] ] ) ;
49855028 }
0 commit comments