code: def _function_entry_stack_ops(op, to_pop):
      """Computes a set of stack operations for the entry to a FunctionCallOp.
  
      The function calling convention is
      - Push the arguments to the formal parameters
      - Pop any now-dead arguments so they're not on the stack during the call
      - Jump to the beginning of the function body
  
      This can be a little tricky for a self-call, because then the arguments and
      the formal parameters live in the same name space and can collide.  This
      helper does something reasonable, and errors out when it can't.
  
      Args:
        op: FunctionCallOp instance giving the call to make stack operations for.
        to_pop: Set of names to make sure are popped before entering.
  
      Returns:
        ops: List of instruction objects that accomplish the goal.
      """
      push_from = []
      push_to = []
      caller_side_vars = inst.pattern_flatten(op.vars_in)
      callee_side_vars = inst.pattern_flatten(op.function.vars_in)
      for caller_side, callee_side in inst.pattern_zip(
          caller_side_vars, callee_side_vars
      ):
          if caller_side == callee_side:
              # This can happen if this is a self-call and we're just passing the
              # variable through to itself
              if caller_side in to_pop:
                  # The top of the stack is already correct, and the callee will pop our
                  # unneeded value off it for us: skip the push and the pop.
                  to_pop = to_pop.difference([caller_side])
              else:
                  # The top of the stack is correct, but we need to push it anyway because
                  # the callee will (eventually) pop but we still need the current value
                  # when the callee returns.
                  push_from.append(caller_side)
                  push_to.append(callee_side)
          elif callee_side in caller_side_vars:
              # If the graph of transfers turns out not to be a DAG, can't implement it
              # without temporary space; and don't want to bother computing a safe order
              # even if it does.
              # Fixing this is b/135275883.
              msg = (
                  "Cannot lower FunctionCallOp that reuses its own input {}"
                  " as a formal parameter."
              )
              raise ValueError(msg.format(caller_side))
          # Checking `elif caller_side in callee_side_vars` is redundant because
          # the callee_side check will trigger on that pair sooner or later.
          else:
              # Ordinary transfer: push now and then pop if needed.  The pop will not
              # interfere with the push because only caller-side variables can possibly
              # be popped.
              assert callee_side not in to_pop
              push_from.append(caller_side)
              push_to.append(callee_side)
      push_inst = inst.push_op(push_from, push_to)
      if to_pop:
          return [push_inst, inst.PopOp(list(to_pop))]
      else:
          return [push_inst]
  
imports: import collections
  from tensorflow_probability.python.experimental.auto_batching import instructions
  from tensorflow_probability.python.experimental.auto_batching import liveness
label_desc: Use image node_id 6 for calling a global function with example usage: _function_entry_stack_ops(op, to_pop) and returns: list, list