Importing Upstream version 4.8.2
[platform/upstream/gcc48.git] / libgo / runtime / go-make-slice.c
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_SLICE);
34   std = (const struct __go_slice_type *) td;
35
36   ilen = (intgo) len;
37   if (ilen < 0 || (uintptr_t) ilen != len)
38     runtime_panicstring ("makeslice: len out of range");
39
40   icap = (intgo) cap;
41   if (cap < len
42       || (uintptr_t) icap != cap
43       || (std->__element_type->__size > 0
44           && cap > MaxMem / std->__element_type->__size))
45     runtime_panicstring ("makeslice: cap out of range");
46
47   ret.__count = ilen;
48   ret.__capacity = icap;
49
50   size = cap * std->__element_type->__size;
51
52   if (size == 0)
53     ret.__values = &runtime_zerobase;
54   else if ((std->__element_type->__code & GO_NO_POINTERS) != 0)
55     ret.__values = runtime_mallocgc (size, FlagNoPointers, 1, 1);
56   else
57     {
58       ret.__values = runtime_mallocgc (size, 0, 1, 1);
59
60       if (UseSpanType)
61         runtime_settype (ret.__values,
62                          (uintptr) std->__element_type | TypeInfo_Array);
63     }
64
65   return ret;
66 }
67
68 struct __go_open_array
69 __go_make_slice1 (const struct __go_type_descriptor *td, uintptr_t len)
70 {
71   return __go_make_slice2 (td, len, len);
72 }
73
74 struct __go_open_array
75 __go_make_slice2_big (const struct __go_type_descriptor *td, uint64_t len,
76                       uint64_t cap)
77 {
78   uintptr_t slen;
79   uintptr_t scap;
80
81   slen = (uintptr_t) len;
82   if ((uint64_t) slen != len)
83     runtime_panicstring ("makeslice: len out of range");
84
85   scap = (uintptr_t) cap;
86   if ((uint64_t) scap != cap)
87     runtime_panicstring ("makeslice: cap out of range");
88
89   return __go_make_slice2 (td, slen, scap);
90 }
91
92 struct __go_open_array
93 __go_make_slice1_big (const struct __go_type_descriptor *td, uint64_t len)
94 {
95   return __go_make_slice2_big (td, len, len);
96 }