github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/runtime/go-append.c (about)

     1  /* go-append.c -- the go builtin append function.
     2  
     3     Copyright 2010 The Go Authors. All rights reserved.
     4     Use of this source code is governed by a BSD-style
     5     license that can be found in the LICENSE file.  */
     6  
     7  #include "runtime.h"
     8  #include "go-panic.h"
     9  #include "go-type.h"
    10  #include "array.h"
    11  #include "arch.h"
    12  #include "malloc.h"
    13  
    14  /* We should be OK if we don't split the stack here, since the only
    15     libc functions we call are memcpy and memmove.  If we don't do
    16     this, we will always split the stack, because of memcpy and
    17     memmove.  */
    18  extern struct __go_open_array
    19  __go_append (struct __go_open_array, void *, uintptr_t, uintptr_t)
    20    __attribute__ ((no_split_stack));
    21  
    22  struct __go_open_array
    23  __go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount,
    24  	     uintptr_t element_size)
    25  {
    26    uintptr_t ucount;
    27    intgo count;
    28  
    29    if (bvalues == NULL || bcount == 0)
    30      return a;
    31  
    32    ucount = (uintptr_t) a.__count + bcount;
    33    count = (intgo) ucount;
    34    if ((uintptr_t) count != ucount || count <= a.__count)
    35      runtime_panicstring ("append: slice overflow");
    36  
    37    if (count > a.__capacity)
    38      {
    39        intgo m;
    40        uintptr capmem;
    41        void *n;
    42  
    43        m = a.__capacity;
    44        if (m + m < count)
    45  	m = count;
    46        else
    47  	{
    48  	  do
    49  	    {
    50  	      if (a.__count < 1024)
    51  		m += m;
    52  	      else
    53  		m += m / 4;
    54  	    }
    55  	  while (m < count);
    56  	}
    57  
    58        if (element_size > 0 && (uintptr) m > MaxMem / element_size)
    59  	runtime_panicstring ("growslice: cap out of range");
    60  
    61        capmem = runtime_roundupsize (m * element_size);
    62  
    63        n = __go_alloc (capmem);
    64        __builtin_memcpy (n, a.__values, a.__count * element_size);
    65  
    66        a.__values = n;
    67        a.__capacity = m;
    68      }
    69  
    70    __builtin_memmove ((char *) a.__values + a.__count * element_size,
    71  		     bvalues, bcount * element_size);
    72    a.__count = count;
    73    return a;
    74  }