1// Copyright 2014 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. 4 5package runtime 6 7import ( 8 "unsafe" 9) 10 11// For gccgo, use go:linkname to rename compiler-called functions to 12// themselves, so that the compiler will export them. 13// 14//go:linkname requireitab runtime.requireitab 15//go:linkname assertitab runtime.assertitab 16//go:linkname assertI2T runtime.assertI2T 17//go:linkname ifacetypeeq runtime.ifacetypeeq 18//go:linkname efacetype runtime.efacetype 19//go:linkname ifacetype runtime.ifacetype 20//go:linkname ifaceE2E2 runtime.ifaceE2E2 21//go:linkname ifaceI2E2 runtime.ifaceI2E2 22//go:linkname ifaceE2I2 runtime.ifaceE2I2 23//go:linkname ifaceI2I2 runtime.ifaceI2I2 24//go:linkname ifaceE2T2P runtime.ifaceE2T2P 25//go:linkname ifaceI2T2P runtime.ifaceI2T2P 26//go:linkname ifaceE2T2 runtime.ifaceE2T2 27//go:linkname ifaceI2T2 runtime.ifaceI2T2 28//go:linkname ifaceT2Ip runtime.ifaceT2Ip 29// Temporary for C code to call: 30//go:linkname getitab runtime.getitab 31 32// The gccgo itab structure is different than the gc one. 33// 34// Both gccgo and gc represent empty interfaces the same way: 35// a two field struct, where the first field points to a type descriptor 36// (a *_type) and the second field is the data pointer. 37// 38// Non-empty interfaces are also two-field structs, and the second 39// field is the data pointer. However, for gccgo, the first field, the 40// itab field, is different. The itab field points to the interface 41// method table, which is the implemention of a specific interface 42// type for a specific dynamic non-interface type. An interface 43// method table is a list of pointer values. The first pointer is the 44// type descriptor (a *_type) for the dynamic type. The subsequent 45// pointers are pointers to function code, which implement the methods 46// required by the interface. The pointers are sorted by name. 47// 48// The method pointers in the itab are C function pointers, not Go 49// function pointers; they may be called directly, and they have no 50// closures. The receiver is always passed as a pointer, and it is 51// always the same pointer stored in the interface value. A value 52// method starts by copying the receiver value out of the pointer into 53// a local variable. 54// 55// A method call on an interface value is by definition calling a 56// method at a known index m in the list of methods. Given a non-empty 57// interface value i, the call i.m(args) looks like 58// i.itab[m+1](i.iface, args) 59 60// Both an empty interface and a non-empty interface have a data 61// pointer field. The meaning of this field is determined by the 62// kindDirectIface bit in the `kind` field of the type descriptor of 63// the value stored in the interface. If kindDirectIface is set, then 64// the data pointer field in the interface value is exactly the value 65// stored in the interface. Otherwise, the data pointer field is a 66// pointer to memory that holds the value. It follows from this that 67// kindDirectIface can only be set for a type whose representation is 68// simply a pointer. In the current gccgo implementation, this is set 69// only for pointer types (including unsafe.Pointer). In the future it 70// could also be set for other types: channels, maps, functions, 71// single-field structs and single-element arrays whose single field 72// is simply a pointer. 73 74// For a nil interface value both fields in the interface struct are nil. 75 76// Return the interface method table for a value of type rhs converted 77// to an interface of type lhs. 78func getitab(lhs, rhs *_type, canfail bool) unsafe.Pointer { 79 if rhs == nil { 80 return nil 81 } 82 83 if lhs.kind&kindMask != kindInterface { 84 throw("getitab called for non-interface type") 85 } 86 87 lhsi := (*interfacetype)(unsafe.Pointer(lhs)) 88 89 if len(lhsi.methods) == 0 { 90 throw("getitab called for empty interface type") 91 } 92 93 if rhs.uncommontype == nil || len(rhs.methods) == 0 { 94 if canfail { 95 return nil 96 } 97 panic(&TypeAssertionError{nil, rhs, lhs, *lhsi.methods[0].name}) 98 } 99 100 methods := make([]unsafe.Pointer, len(lhsi.methods)+1) 101 methods[0] = unsafe.Pointer(rhs) 102 103 ri := 0 104 for li := range lhsi.methods { 105 lhsMethod := &lhsi.methods[li] 106 var rhsMethod *method 107 108 for { 109 if ri >= len(rhs.methods) { 110 if canfail { 111 return nil 112 } 113 panic(&TypeAssertionError{nil, rhs, lhs, *lhsMethod.name}) 114 } 115 116 rhsMethod = &rhs.methods[ri] 117 if (lhsMethod.name == rhsMethod.name || *lhsMethod.name == *rhsMethod.name) && 118 (lhsMethod.pkgPath == rhsMethod.pkgPath || *lhsMethod.pkgPath == *rhsMethod.pkgPath) { 119 break 120 } 121 122 ri++ 123 } 124 125 if !eqtype(lhsMethod.typ, rhsMethod.mtyp) { 126 if canfail { 127 return nil 128 } 129 panic(&TypeAssertionError{nil, rhs, lhs, *lhsMethod.name}) 130 } 131 132 methods[li+1] = unsafe.Pointer(rhsMethod.tfn) 133 ri++ 134 } 135 136 return unsafe.Pointer(&methods[0]) 137} 138 139// Return the interface method table for a value of type rhs converted 140// to an interface of type lhs. Panics if the conversion is impossible. 141func requireitab(lhs, rhs *_type) unsafe.Pointer { 142 return getitab(lhs, rhs, false) 143} 144 145// Return the interface method table for a value of type rhs converted 146// to an interface of type lhs. Panics if the conversion is 147// impossible or if the rhs type is nil. 148func assertitab(lhs, rhs *_type) unsafe.Pointer { 149 if rhs == nil { 150 panic(&TypeAssertionError{nil, nil, lhs, ""}) 151 } 152 153 if lhs.kind&kindMask != kindInterface { 154 throw("assertitab called for non-interface type") 155 } 156 157 lhsi := (*interfacetype)(unsafe.Pointer(lhs)) 158 159 if len(lhsi.methods) == 0 { 160 return unsafe.Pointer(rhs) 161 } 162 163 return getitab(lhs, rhs, false) 164} 165 166// Check whether an interface type may be converted to a non-interface 167// type, panicing if not. 168func assertI2T(lhs, rhs, inter *_type) { 169 if rhs == nil { 170 panic(&TypeAssertionError{nil, nil, lhs, ""}) 171 } 172 if !eqtype(lhs, rhs) { 173 panic(&TypeAssertionError{inter, rhs, lhs, ""}) 174 } 175} 176 177// Compare two type descriptors for equality. 178func ifacetypeeq(a, b *_type) bool { 179 return eqtype(a, b) 180} 181 182// Return the type descriptor of an empty interface. 183// FIXME: This should be inlined by the compiler. 184func efacetype(e eface) *_type { 185 return e._type 186} 187 188// Return the type descriptor of a non-empty interface. 189// FIXME: This should be inlined by the compiler. 190func ifacetype(i iface) *_type { 191 if i.tab == nil { 192 return nil 193 } 194 return *(**_type)(i.tab) 195} 196 197// Convert an empty interface to an empty interface, for a comma-ok 198// type assertion. 199func ifaceE2E2(e eface) (eface, bool) { 200 return e, e._type != nil 201} 202 203// Convert a non-empty interface to an empty interface, for a comma-ok 204// type assertion. 205func ifaceI2E2(i iface) (eface, bool) { 206 if i.tab == nil { 207 return eface{nil, nil}, false 208 } else { 209 return eface{*(**_type)(i.tab), i.data}, true 210 } 211} 212 213// Convert an empty interface to a non-empty interface, for a comma-ok 214// type assertion. 215func ifaceE2I2(inter *_type, e eface) (iface, bool) { 216 if e._type == nil { 217 return iface{nil, nil}, false 218 } else { 219 itab := getitab(inter, e._type, true) 220 if itab == nil { 221 return iface{nil, nil}, false 222 } else { 223 return iface{itab, e.data}, true 224 } 225 } 226} 227 228// Convert a non-empty interface to a non-empty interface, for a 229// comma-ok type assertion. 230func ifaceI2I2(inter *_type, i iface) (iface, bool) { 231 if i.tab == nil { 232 return iface{nil, nil}, false 233 } else { 234 itab := getitab(inter, *(**_type)(i.tab), true) 235 if itab == nil { 236 return iface{nil, nil}, false 237 } else { 238 return iface{itab, i.data}, true 239 } 240 } 241} 242 243// Convert an empty interface to a pointer non-interface type. 244func ifaceE2T2P(t *_type, e eface) (unsafe.Pointer, bool) { 245 if !eqtype(t, e._type) { 246 return nil, false 247 } else { 248 return e.data, true 249 } 250} 251 252// Convert a non-empty interface to a pointer non-interface type. 253func ifaceI2T2P(t *_type, i iface) (unsafe.Pointer, bool) { 254 if i.tab == nil || !eqtype(t, *(**_type)(i.tab)) { 255 return nil, false 256 } else { 257 return i.data, true 258 } 259} 260 261// Convert an empty interface to a non-pointer non-interface type. 262func ifaceE2T2(t *_type, e eface, ret unsafe.Pointer) bool { 263 if !eqtype(t, e._type) { 264 typedmemclr(t, ret) 265 return false 266 } else { 267 typedmemmove(t, ret, e.data) 268 return true 269 } 270} 271 272// Convert a non-empty interface to a non-pointer non-interface type. 273func ifaceI2T2(t *_type, i iface, ret unsafe.Pointer) bool { 274 if i.tab == nil || !eqtype(t, *(**_type)(i.tab)) { 275 typedmemclr(t, ret) 276 return false 277 } else { 278 typedmemmove(t, ret, i.data) 279 return true 280 } 281} 282 283// Return whether we can convert a type to an interface type. 284func ifaceT2Ip(to, from *_type) bool { 285 if from == nil { 286 return false 287 } 288 289 if to.kind&kindMask != kindInterface { 290 throw("ifaceT2Ip called with non-interface type") 291 } 292 toi := (*interfacetype)(unsafe.Pointer(to)) 293 294 if from.uncommontype == nil || len(from.methods) == 0 { 295 return len(toi.methods) == 0 296 } 297 298 ri := 0 299 for li := range toi.methods { 300 toMethod := &toi.methods[li] 301 var fromMethod *method 302 for { 303 if ri >= len(from.methods) { 304 return false 305 } 306 307 fromMethod = &from.methods[ri] 308 if (toMethod.name == fromMethod.name || *toMethod.name == *fromMethod.name) && 309 (toMethod.pkgPath == fromMethod.pkgPath || *toMethod.pkgPath == *fromMethod.pkgPath) { 310 break 311 } 312 313 ri++ 314 } 315 316 if !eqtype(fromMethod.mtyp, toMethod.typ) { 317 return false 318 } 319 320 ri++ 321 } 322 323 return true 324} 325 326//go:linkname reflect_ifaceE2I reflect.ifaceE2I 327func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) { 328 t := e._type 329 if t == nil { 330 panic(TypeAssertionError{nil, nil, &inter.typ, ""}) 331 } 332 dst.tab = requireitab((*_type)(unsafe.Pointer(inter)), t) 333 dst.data = e.data 334} 335 336// staticbytes is used to avoid convT2E for byte-sized values. 337var staticbytes = [...]byte{ 338 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 339 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 340 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 341 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 342 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 343 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 344 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 345 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 346 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 347 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 348 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 349 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 350 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 351 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 352 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 353 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 354 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 355 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 356 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 357 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 358 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 359 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 360 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 361 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 362 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 363 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 364 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 365 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 366 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 367 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 368 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 369 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 370} 371