<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def teardown_callsite(self, state, return_val=None, arg_types=None, force_callee_cleanup=False):
 """ This function performs the actions of the callee as it's getting ready to return. It returns the address to return to. :param state: The state to mutate :param return_val: The value to return :param arg_types: The fp-ness of each of the args. Used to calculate sizes to clean up :param force_callee_cleanup: If we should clean up the stack allocation for the arguments even if it's not the callee's job to do so Maybe it could make sense by saying that you pass it in as something like the "saved base pointer" value? """

        if return_val is not None:
            self.set_return_val(state, return_val)

        ret_addr = self.return_addr.get_value(state)

        if state.arch.sp_offset is not None:
            if force_callee_cleanup or self.CALLEE_CLEANUP:
                if arg_types is not None:
                    session = self.arg_session
                    state.regs.sp += self.stack_space([session.next_arg(x) for x in arg_types])
                elif self.args is not None:
                    state.regs.sp += self.stack_space(self.args)
                else:
                    l.warning("Can't perform callee cleanup when I have no idea how many arguments there are! Assuming 0")
                    state.regs.sp += self.STACKARG_SP_DIFF
            else:
                state.regs.sp += self.STACKARG_SP_DIFF

        return ret_addr