docs: def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder,
                      dynamic_offset_counter=None, datamem_start=None, zero_pad_i=None, pos=None):
      """
      Copy necessary variables to pre-allocated memory section.
  
      :param holder: Complete holder for all args
      :param maxlen: Total length in bytes of the full arg section (static + dynamic).
      :param arg: Current arg to pack
      :param context: Context of arg
      :param placeholder: Static placeholder for static argument part.
      :param dynamic_offset_counter: position counter stored in static args.
      :param dynamic_placeholder: pointer to current position in memory to write dynamic values to.
      :param datamem_start: position where the whole datemem section starts.
      """
  
      if isinstance(typ, BaseType):
          if isinstance(arg, LLLnode):
              value = unwrap_location(arg)
          else:
              value = parse_expr(arg, context)
              value = base_type_conversion(value, value.typ, typ, pos)
          holder.append(LLLnode.from_list(['mstore', placeholder, value], typ=typ, location='memory'))
      elif isinstance(typ, ByteArrayLike):
  
          if isinstance(arg, LLLnode):  # Is prealloacted variable.
              source_lll = arg
          else:
              source_lll = parse_expr(arg, context)
  
          # Set static offset, in arg slot.
          holder.append(LLLnode.from_list(['mstore', placeholder, ['mload', dynamic_offset_counter]]))
          # Get the biginning to write the ByteArray to.
          dest_placeholder = LLLnode.from_list(
              ['add', datamem_start, ['mload', dynamic_offset_counter]],
              typ=typ, location='memory', annotation="pack_args_by_32:dest_placeholder")
          copier = make_byte_array_copier(dest_placeholder, source_lll, pos=pos)
          holder.append(copier)
          # Add zero padding.
          new_maxlen = ceil32(source_lll.typ.maxlen)
  
          holder.append([
              'with', '_ceil32_end', ['ceil32', ['mload', dest_placeholder]], [
                  'seq', ['with', '_bytearray_loc', dest_placeholder, [
                      'seq', ['repeat', zero_pad_i, ['mload', '_bytearray_loc'], new_maxlen, [
                          'seq',
                          # stay within allocated bounds
                          ['if', ['ge', ['mload', zero_pad_i], '_ceil32_end'], 'break'],
                          [
                              'mstore8',
                              ['add', ['add', '_bytearray_loc', 32], ['mload', zero_pad_i]],
                              0,
                          ],
                      ]],
                  ]],
              ]
          ])
  
          # Increment offset counter.
          increment_counter = LLLnode.from_list([
              'mstore', dynamic_offset_counter,
              [
                  'add',
                  ['add', ['mload', dynamic_offset_counter], ['ceil32', ['mload', dest_placeholder]]],
                  32,
              ],
          ], annotation='Increment dynamic offset counter')
          holder.append(increment_counter)
      elif isinstance(typ, ListType):
          maxlen += (typ.count - 1) * 32
          typ = typ.subtype
  
          def check_list_type_match(provided):  # Check list types match.
              if provided != typ:
                  raise TypeMismatchException(
                      "Log list type '%s' does not match provided, expected '%s'" % (provided, typ)
                  )
  
          # List from storage
          if isinstance(arg, ast.Attribute) and arg.value.id == 'self':
              stor_list = context.globals[arg.attr]
              check_list_type_match(stor_list.typ.subtype)
              size = stor_list.typ.count
              mem_offset = 0
              for i in range(0, size):
                  storage_offset = i
                  arg2 = LLLnode.from_list(
                      ['sload', ['add', ['sha3_32', Expr(arg, context).lll_node], storage_offset]],
                      typ=typ,
                  )
                  holder, maxlen = pack_args_by_32(
                      holder,
                      maxlen,
                      arg2,
                      typ,
                      context,
                      placeholder + mem_offset,
                      pos=pos,
                  )
                  mem_offset += get_size_of_type(typ) * 32
  
          # List from variable.
          elif isinstance(arg, ast.Name):
              size = context.vars[arg.id].size
              pos = context.vars[arg.id].pos
              check_list_type_match(context.vars[arg.id].typ.subtype)
              mem_offset = 0
              for _ in range(0, size):
                  arg2 = LLLnode.from_list(pos + mem_offset, typ=typ, location='memory')
                  holder, maxlen = pack_args_by_32(
                      holder,
                      maxlen,
                      arg2,
                      typ,
                      context,
                      placeholder + mem_offset,
                      pos=pos,
                  )
                  mem_offset += get_size_of_type(typ) * 32
  
          # List from list literal.
          else:
              mem_offset = 0
              for arg2 in arg.elts:
                  holder, maxlen = pack_args_by_32(
                      holder,
                      maxlen,
                      arg2,
                      typ,
                      context,
                      placeholder + mem_offset,
                      pos=pos,
                  )
                  mem_offset += get_size_of_type(typ) * 32
      return holder, maxlen