@@ -144,6 +144,14 @@ object (self)
144144 else
145145 None in
146146
147+ let is_tail_call () : bool =
148+ match instr#get_opcode with
149+ | Branch (ACCAlways , tgt, _)
150+ | BranchExchange (ACCAlways, tgt ) when tgt#is_absolute_address ->
151+ let tgtaddr = tgt#get_absolute_address in
152+ functions_data#is_function_entry_point tgtaddr
153+ | _ -> false in
154+
147155 let log_dc_error_result (file : string ) (line : int ) (e : string list ) =
148156 if BCHSystemSettings. system_settings#collect_data then
149157 log_error_result ~msg: (p2s floc#l#toPretty) file line e
@@ -397,7 +405,11 @@ object (self)
397405 (LBLOCK [
398406 STR __FILE__; STR " :" ; INT __LINE__; STR " : " ;
399407 STR " Empty tag list" ])) in
400- let rdefs = [get_rdef_r rv] @ (get_all_rdefs_r rrv) in
408+ let rdefs =
409+ if is_tail_call () then
410+ []
411+ else
412+ [get_rdef_r rv] @ (get_all_rdefs_r rrv) in
401413 let xtag = (List. hd tags) ^ " xxc" ^ (string_repeat " r" (List. length rdefs)) in
402414 let argslen = List. length args in
403415 let returntag = " return:" ^ (string_of_int argslen) in
@@ -704,7 +716,18 @@ object (self)
704716 else
705717 tagstring
706718 :: [" call" ; " argcount:" ^ (string_of_int (List. length callargs))] in
719+ let (tags, args) =
720+ if is_tail_call () then
721+ (* we cannot use R0 here, because its invariant value at this point
722+ will be the value at the start of the instruction, which is the
723+ value of the first argument *)
724+ let rvar = floc#env#mk_return_value floc#cia in
725+ let xr0_r = Ok (XVar rvar) in
726+ add_return_value tags args xr0_r xr0_r xr0_r
727+ else
728+ (tags, args) in
707729 let args =
730+ (* the call-target should always stay in last position *)
708731 args @ [ixd#index_call_target floc#get_call_target#get_target] in
709732 (tags, args) in
710733
0 commit comments