Fortran: fix ALLOCATE with SOURCE of deferred character length [PR114019]
[official-gcc.git] / libgo / go / runtime / type.go
blob9a418ea0aeeb82288413c4bcaeba4896eceb5aa8
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Runtime type representation.
7 package runtime
9 import (
10 "internal/goarch"
11 "runtime/internal/atomic"
12 "unsafe"
15 // tflag is documented in reflect/type.go.
17 // tflag values must be kept in sync with copies in:
18 // go/types.cc
19 // reflect/type.go
20 // internal/reflectlite/type.go
21 type tflag uint8
23 const (
24 tflagRegularMemory tflag = 1 << 3 // equal and hash can treat values of this type as a single region of t.size bytes
27 // Needs to be in sync with
28 // go/types.cc
29 // ../reflect/type.go:/^type.rtype.
30 // ../internal/reflectlite/type.go:/^type.rtype.
31 type _type struct {
32 size uintptr
33 ptrdata uintptr
34 hash uint32
35 tflag tflag
36 align uint8
37 fieldAlign uint8
38 kind uint8
39 // function for comparing objects of this type
40 // (ptr to object A, ptr to object B) -> ==?
41 equal func(unsafe.Pointer, unsafe.Pointer) bool
42 // gcdata stores the GC type data for the garbage collector.
43 // If the KindGCProg bit is set in kind, gcdata is a GC program.
44 // Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
45 gcdata *byte
46 _string *string
47 *uncommontype
48 ptrToThis *_type
51 func (t *_type) string() string {
52 // For gccgo, try to strip out quoted strings.
53 s := *t._string
54 q := false
55 started := false
56 var start int
57 var end int
58 for i := 0; i < len(s); i++ {
59 if s[i] == '\t' {
60 q = !q
61 } else if !q {
62 if !started {
63 start = i
64 started = true
66 end = i
69 return s[start : end+1]
72 // pkgpath returns the path of the package where t was defined, if
73 // available. This is not the same as the reflect package's PkgPath
74 // method, in that it returns the package path for struct and interface
75 // types, not just named types.
76 func (t *_type) pkgpath() string {
77 if u := t.uncommontype; u != nil {
78 if u.pkgPath == nil {
79 return ""
81 return *u.pkgPath
83 return ""
86 type method struct {
87 name *string
88 pkgPath *string
89 mtyp *_type
90 typ *_type
91 tfn unsafe.Pointer
94 type uncommontype struct {
95 name *string
96 pkgPath *string
97 methods []method
100 type imethod struct {
101 name *string
102 pkgPath *string
103 typ *_type
106 type interfacetype struct {
107 typ _type
108 methods []imethod
111 type maptype struct {
112 typ _type
113 key *_type
114 elem *_type
115 bucket *_type // internal type representing a hash bucket
116 // function for hashing keys (ptr to key, seed) -> hash
117 hasher func(unsafe.Pointer, uintptr) uintptr
118 keysize uint8 // size of key slot
119 elemsize uint8 // size of elem slot
120 bucketsize uint16 // size of bucket
121 flags uint32
124 // Note: flag values must match those used in the TMAP case
125 // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
126 func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself
127 return mt.flags&1 != 0
129 func (mt *maptype) indirectelem() bool { // store ptr to elem instead of elem itself
130 return mt.flags&2 != 0
132 func (mt *maptype) reflexivekey() bool { // true if k==k for all keys
133 return mt.flags&4 != 0
135 func (mt *maptype) needkeyupdate() bool { // true if we need to update key on an overwrite
136 return mt.flags&8 != 0
138 func (mt *maptype) hashMightPanic() bool { // true if hash function might panic
139 return mt.flags&16 != 0
142 type arraytype struct {
143 typ _type
144 elem *_type
145 slice *_type
146 len uintptr
149 type chantype struct {
150 typ _type
151 elem *_type
152 dir uintptr
155 type slicetype struct {
156 typ _type
157 elem *_type
160 type functype struct {
161 typ _type
162 dotdotdot bool
163 in []*_type
164 out []*_type
167 type ptrtype struct {
168 typ _type
169 elem *_type
172 type structfield struct {
173 name *string // nil for embedded fields
174 pkgPath *string // nil for exported Names; otherwise import path
175 typ *_type // type of field
176 tag *string // nil if no tag
177 offsetAnon uintptr // byte offset of field<<1 | isAnonymous
180 func (f *structfield) offset() uintptr {
181 return f.offsetAnon >> 1
184 func (f *structfield) anon() bool {
185 return f.offsetAnon&1 != 0
188 type structtype struct {
189 typ _type
190 fields []structfield
193 // typeDescriptorList holds a list of type descriptors generated
194 // by the compiler. This is used for the compiler to register
195 // type descriptors to the runtime.
196 // The layout is known to the compiler.
197 //go:notinheap
198 type typeDescriptorList struct {
199 count int
200 types [1]uintptr // variable length
203 // typelist holds all type descriptors generated by the comiler.
204 // This is for the reflect package to deduplicate type descriptors
205 // when it creates a type that is also a compiler-generated type.
206 var typelist struct {
207 initialized uint32
208 lists []*typeDescriptorList // one element per package
209 types map[string]uintptr // map from a type's string to *_type, lazily populated
210 // TODO: use a sorted array instead?
212 var typelistLock mutex
214 // The compiler generates a call of this function in the main
215 // package's init function, to register compiler-generated
216 // type descriptors.
217 // p points to a list of *typeDescriptorList, n is the length
218 // of the list.
219 //go:linkname registerTypeDescriptors
220 func registerTypeDescriptors(n int, p unsafe.Pointer) {
221 *(*slice)(unsafe.Pointer(&typelist.lists)) = slice{p, n, n}
224 // The reflect package uses this function to look up a compiler-
225 // generated type descriptor.
226 //go:linkname reflect_lookupType reflect.lookupType
227 func reflect_lookupType(s string) *_type {
228 // Lazy initialization. We don't need to do this if we never create
229 // types through reflection.
230 if atomic.Load(&typelist.initialized) == 0 {
231 lock(&typelistLock)
232 if atomic.Load(&typelist.initialized) == 0 {
233 n := 0
234 for _, list := range typelist.lists {
235 n += list.count
237 typelist.types = make(map[string]uintptr, n)
238 for _, list := range typelist.lists {
239 for i := 0; i < list.count; i++ {
240 typ := *(**_type)(add(unsafe.Pointer(&list.types), uintptr(i)*goarch.PtrSize))
241 typelist.types[typ.string()] = uintptr(unsafe.Pointer(typ))
244 atomic.Store(&typelist.initialized, 1)
246 unlock(&typelistLock)
249 return (*_type)(unsafe.Pointer(typelist.types[s]))