summaryrefslogtreecommitdiff
path: root/libgo/runtime/go-make-slice.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/runtime/go-make-slice.c')
-rw-r--r--libgo/runtime/go-make-slice.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c
index 242c9bb7268..591ab37e0c6 100644
--- a/libgo/runtime/go-make-slice.c
+++ b/libgo/runtime/go-make-slice.c
@@ -15,6 +15,11 @@
#include "arch.h"
#include "malloc.h"
+/* Dummy word to use as base pointer for make([]T, 0).
+ Since you cannot take the address of such a slice,
+ you can't tell that they all have the same base pointer. */
+uintptr runtime_zerobase;
+
struct __go_open_array
__go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
uintptr_t cap)
@@ -24,7 +29,6 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
intgo icap;
uintptr_t size;
struct __go_open_array ret;
- unsigned int flag;
__go_assert (td->__code == GO_SLICE);
std = (const struct __go_slice_type *) td;
@@ -44,10 +48,19 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
ret.__capacity = icap;
size = cap * std->__element_type->__size;
- flag = ((std->__element_type->__code & GO_NO_POINTERS) != 0
- ? FlagNoPointers
- : 0);
- ret.__values = runtime_mallocgc (size, flag, 1, 1);
+
+ if (size == 0)
+ ret.__values = &runtime_zerobase;
+ else if ((std->__element_type->__code & GO_NO_POINTERS) != 0)
+ ret.__values = runtime_mallocgc (size, FlagNoPointers, 1, 1);
+ else
+ {
+ ret.__values = runtime_mallocgc (size, 0, 1, 1);
+
+ if (UseSpanType)
+ runtime_settype (ret.__values,
+ (uintptr) std->__element_type | TypeInfo_Array);
+ }
return ret;
}