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

     1  /* go-make-slice.c -- make a slice.
     2  
     3     Copyright 2011 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 <stdint.h>
     8  
     9  #include "runtime.h"
    10  #include "go-alloc.h"
    11  #include "go-assert.h"
    12  #include "go-panic.h"
    13  #include "go-type.h"
    14  #include "array.h"
    15  #include "arch.h"
    16  #include "malloc.h"
    17  
    18  /* Dummy word to use as base pointer for make([]T, 0).
    19     Since you cannot take the address of such a slice,
    20     you can't tell that they all have the same base pointer.  */
    21  uintptr runtime_zerobase;
    22  
    23  struct __go_open_array
    24  __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
    25  		  uintptr_t cap)
    26  {
    27    const struct __go_slice_type* std;
    28    intgo ilen;
    29    intgo icap;
    30    uintptr_t size;
    31    struct __go_open_array ret;
    32  
    33    __go_assert ((td->__code & GO_CODE_MASK) == GO_SLICE);
    34    std = (const struct __go_slice_type *) td;
    35  
    36    ilen = (intgo) len;
    37    if (ilen < 0
    38        || (uintptr_t) ilen != len
    39        || (std->__element_type->__size > 0
    40  	  && len > MaxMem / std->__element_type->__size))
    41      runtime_panicstring ("makeslice: len out of range");
    42  
    43    icap = (intgo) cap;
    44    if (cap < len
    45        || (uintptr_t) icap != cap
    46        || (std->__element_type->__size > 0
    47  	  && cap > MaxMem / std->__element_type->__size))
    48      runtime_panicstring ("makeslice: cap out of range");
    49  
    50    ret.__count = ilen;
    51    ret.__capacity = icap;
    52  
    53    size = cap * std->__element_type->__size;
    54  
    55    if (size == 0)
    56      ret.__values = &runtime_zerobase;
    57    else if ((std->__element_type->__code & GO_NO_POINTERS) != 0)
    58      ret.__values =
    59        runtime_mallocgc (size,
    60  			(uintptr) std->__element_type | TypeInfo_Array,
    61  			FlagNoScan);
    62    else
    63      ret.__values =
    64        runtime_mallocgc (size,
    65  			(uintptr) std->__element_type | TypeInfo_Array,
    66  			0);
    67  
    68    return ret;
    69  }
    70  
    71  struct __go_open_array
    72  __go_make_slice1 (const struct __go_type_descriptor *td, uintptr_t len)
    73  {
    74    return __go_make_slice2 (td, len, len);
    75  }
    76  
    77  struct __go_open_array
    78  __go_make_slice2_big (const struct __go_type_descriptor *td, uint64_t len,
    79  		      uint64_t cap)
    80  {
    81    uintptr_t slen;
    82    uintptr_t scap;
    83  
    84    slen = (uintptr_t) len;
    85    if ((uint64_t) slen != len)
    86      runtime_panicstring ("makeslice: len out of range");
    87  
    88    scap = (uintptr_t) cap;
    89    if ((uint64_t) scap != cap)
    90      runtime_panicstring ("makeslice: cap out of range");
    91  
    92    return __go_make_slice2 (td, slen, scap);
    93  }
    94  
    95  struct __go_open_array
    96  __go_make_slice1_big (const struct __go_type_descriptor *td, uint64_t len)
    97  {
    98    return __go_make_slice2_big (td, len, len);
    99  }