docs: 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
  
          TODO: support the stack_base parameter from setup_callsite...? Does that make sense in this context?
          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