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
__go_make_slice2(const struct __go_type_descriptor * td,uintptr_t len,uintptr_t cap)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
__go_make_slice1(const struct __go_type_descriptor * td,uintptr_t len)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
__go_make_slice2_big(const struct __go_type_descriptor * td,uint64_t len,uint64_t cap)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
__go_make_slice1_big(const struct __go_type_descriptor * td,uint64_t len)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 }
100