code: def generate_specific_arg_handling_body(
      function_name,
      num_cl_args,
      arg_types,
      *,
      work_around_arg_count_bug,
      warn_about_arg_count_bug,
      in_enqueue,
      include_debug_code,
  ):
      assert work_around_arg_count_bug is not None
      assert warn_about_arg_count_bug is not None
  
      fp_arg_count = 0
      cl_arg_idx = 0
  
      gen = PythonCodeGenerator()
  
      if not arg_types:
          gen("pass")
  
      gen_indices_and_args = []
      buf_indices_and_args = []
      buf_pack_indices_and_args = []
  
      def add_buf_arg(arg_idx, typechar, expr_str):
          if typechar in BUF_PACK_TYPECHARS:
              buf_pack_indices_and_args.append(arg_idx)
              buf_pack_indices_and_args.append(repr(typechar.encode()))
              buf_pack_indices_and_args.append(expr_str)
          else:
              buf_indices_and_args.append(arg_idx)
              buf_indices_and_args.append(
                  f"pack('{typechar}', {expr_str})"
              )
  
      wait_for_parts = []
  
      for arg_idx, arg_type in enumerate(arg_types):
          arg_var = "arg%d" % arg_idx
  
          if arg_type is None:
              gen_indices_and_args.append(cl_arg_idx)
              gen_indices_and_args.append(arg_var)
              cl_arg_idx += 1
              gen("")
              continue
  
          elif isinstance(arg_type, VectorArg):
              if include_debug_code:
                  gen(f"if not {arg_var}.flags.forc:")
                  with Indentation(gen):
                      gen(
                          "raise RuntimeError('only contiguous arrays may '"
                      )
                      gen(
                          "   'be used as arguments to this operation')"
                      )
                      gen("")
  
              if in_enqueue and include_debug_code:
                  gen(
                      f"assert {arg_var}.queue is None or {arg_var}.queue == queue, "
                      "'queues for all arrays must match the queue supplied "
                      "to enqueue'"
                  )
  
              gen_indices_and_args.append(cl_arg_idx)
              gen_indices_and_args.append(f"{arg_var}.base_data")
              cl_arg_idx += 1
  
              if arg_type.with_offset:
                  add_buf_arg(
                      cl_arg_idx,
                      np.dtype(np.int64).char,
                      f"{arg_var}.offset",
                  )
                  cl_arg_idx += 1
  
              if in_enqueue:
                  wait_for_parts.append(f"{arg_var}.events")
  
              continue
  
          arg_dtype = np.dtype(arg_type)
  
          if arg_dtype.char == "V":
              buf_indices_and_args.append(cl_arg_idx)
              buf_indices_and_args.append(arg_var)
              cl_arg_idx += 1
  
          elif arg_dtype.kind == "c":
              if warn_about_arg_count_bug:
                  warn(
                      "{knl_name}: arguments include complex numbers, and "
                      "some (but not all) of the target devices mishandle "
                      "struct kernel arguments (hence the workaround is "
                      "disabled".format(knl_name=function_name),
                      stacklevel=2,
                  )
  
              if arg_dtype == np.complex64:
                  arg_char = "f"
              elif arg_dtype == np.complex128:
                  arg_char = "d"
              else:
                  raise TypeError(
                      "unexpected complex type: %s" % arg_dtype
                  )
  
              if (
                  work_around_arg_count_bug == "pocl"
                  and arg_dtype == np.complex128
                  and fp_arg_count + 2 <= 8
              ):
                  add_buf_arg(cl_arg_idx, arg_char, f"{arg_var}.real")
                  cl_arg_idx += 1
                  add_buf_arg(cl_arg_idx, arg_char, f"{arg_var}.imag")
                  cl_arg_idx += 1
  
              elif (
                  work_around_arg_count_bug == "apple"
                  and arg_dtype == np.complex128
                  and fp_arg_count + 2 <= 8
              ):
                  raise NotImplementedError(
                      "No work-around to "
                      "Apple's broken structs-as-kernel arg "
                      "handling has been found. "
                      "Cannot pass complex numbers to kernels."
                  )
  
              else:
                  buf_indices_and_args.append(cl_arg_idx)
                  buf_indices_and_args.append(
                      f"pack('{arg_char}{arg_char}', {arg_var}.real, {arg_var}.imag)"
                  )
                  cl_arg_idx += 1
  
              fp_arg_count += 2
  
          else:
              if arg_dtype.kind == "f":
                  fp_arg_count += 1
  
              arg_char = arg_dtype.char
              arg_char = _type_char_map.get(arg_char, arg_char)
              add_buf_arg(cl_arg_idx, arg_char, arg_var)
              cl_arg_idx += 1
  
          gen("")
  
      for arg_kind, args_and_indices, entry_length in [
          ("", gen_indices_and_args, 2),
          ("_buf", buf_indices_and_args, 2),
          ("_buf_pack", buf_pack_indices_and_args, 3),
      ]:
          assert len(args_and_indices) % entry_length == 0
          if args_and_indices:
              gen(
                  f"self._set_arg{arg_kind}_multi("
                  f"({', '.join(str(i) for i in args_and_indices)},), "
                  ")"
              )
  
      if cl_arg_idx != num_cl_args:
          raise TypeError(
              "length of argument list (%d) and "
              "CL-generated number of arguments (%d) do not agree"
              % (cl_arg_idx, num_cl_args)
          )
  
      if in_enqueue:
          return gen, wait_for_parts
      else:
          return gen
  
file_path: pyopencl/pyopencl/invoker.py
imports: import numpy
  from warnings import warn
  import pyopencl._cl
  from pytools.persistent_dict import WriteOncePersistentDict
  from pytools.py_codegen import Indentation, PythonCodeGenerator
  from pyopencl.tools import _NumpyTypesKeyBuilder, VectorArg
  import pyopencl
label_desc: Use image node_id 2 for calling a global function with example usage: generate_specific_arg_handling_body(function_name, num_cl_args, arg_types) and returns: gen,  wait_for_parts, gen