day1
This commit is contained in:
commit
17119d9298
|
@ -0,0 +1,32 @@
|
|||
# git remote add github git@github.com:wit-go/log.git
|
||||
|
||||
all: vet
|
||||
@#GO111MODULE=off go vet -x
|
||||
@echo this go library builds ok
|
||||
|
||||
vet:
|
||||
@GO111MODULE=off go vet
|
||||
|
||||
redomod:
|
||||
rm -f go.*
|
||||
GO111MODULE= go mod init
|
||||
GO111MODULE= go mod tidy
|
||||
|
||||
goimport:
|
||||
goimports -w *.go
|
||||
|
||||
github:
|
||||
git push origin master
|
||||
git push origin devel
|
||||
git push origin --tags
|
||||
git push github master
|
||||
git push github devel
|
||||
git push github --tags
|
||||
@echo
|
||||
@echo check https://github.com/wit-go/log
|
||||
@echo
|
||||
|
||||
init-github:
|
||||
git push -u github master
|
||||
git push -u github devel
|
||||
git push github --tags
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
import (
|
||||
"internal/goarch"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// RegArgs is a struct that has space for each argument
|
||||
// and return value register on the current architecture.
|
||||
//
|
||||
// Assembly code knows the layout of the first two fields
|
||||
// of RegArgs.
|
||||
//
|
||||
// RegArgs also contains additional space to hold pointers
|
||||
// when it may not be safe to keep them only in the integer
|
||||
// register space otherwise.
|
||||
type RegArgs struct {
|
||||
// Values in these slots should be precisely the bit-by-bit
|
||||
// representation of how they would appear in a register.
|
||||
//
|
||||
// This means that on big endian arches, integer values should
|
||||
// be in the top bits of the slot. Floats are usually just
|
||||
// directly represented, but some architectures treat narrow
|
||||
// width floating point values specially (e.g. they're promoted
|
||||
// first, or they need to be NaN-boxed).
|
||||
Ints [IntArgRegs]uintptr // untyped integer registers
|
||||
Floats [FloatArgRegs]uint64 // untyped float registers
|
||||
|
||||
// Fields above this point are known to assembly.
|
||||
|
||||
// Ptrs is a space that duplicates Ints but with pointer type,
|
||||
// used to make pointers passed or returned in registers
|
||||
// visible to the GC by making the type unsafe.Pointer.
|
||||
Ptrs [IntArgRegs]unsafe.Pointer
|
||||
|
||||
// ReturnIsPtr is a bitmap that indicates which registers
|
||||
// contain or will contain pointers on the return path from
|
||||
// a reflectcall. The i'th bit indicates whether the i'th
|
||||
// register contains or will contain a valid Go pointer.
|
||||
ReturnIsPtr IntArgRegBitmap
|
||||
}
|
||||
|
||||
func (r *RegArgs) Dump() {
|
||||
print("Ints:")
|
||||
for _, x := range r.Ints {
|
||||
print(" ", x)
|
||||
}
|
||||
println()
|
||||
print("Floats:")
|
||||
for _, x := range r.Floats {
|
||||
print(" ", x)
|
||||
}
|
||||
println()
|
||||
print("Ptrs:")
|
||||
for _, x := range r.Ptrs {
|
||||
print(" ", x)
|
||||
}
|
||||
println()
|
||||
}
|
||||
|
||||
// IntRegArgAddr returns a pointer inside of r.Ints[reg] that is appropriately
|
||||
// offset for an argument of size argSize.
|
||||
//
|
||||
// argSize must be non-zero, fit in a register, and a power-of-two.
|
||||
//
|
||||
// This method is a helper for dealing with the endianness of different CPU
|
||||
// architectures, since sub-word-sized arguments in big endian architectures
|
||||
// need to be "aligned" to the upper edge of the register to be interpreted
|
||||
// by the CPU correctly.
|
||||
func (r *RegArgs) IntRegArgAddr(reg int, argSize uintptr) unsafe.Pointer {
|
||||
if argSize > goarch.PtrSize || argSize == 0 || argSize&(argSize-1) != 0 {
|
||||
panic("invalid argSize")
|
||||
}
|
||||
offset := uintptr(0)
|
||||
if goarch.BigEndian {
|
||||
offset = goarch.PtrSize - argSize
|
||||
}
|
||||
return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Ints[reg])) + offset)
|
||||
}
|
||||
|
||||
// IntArgRegBitmap is a bitmap large enough to hold one bit per
|
||||
// integer argument/return register.
|
||||
type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8
|
||||
|
||||
// Set sets the i'th bit of the bitmap to 1.
|
||||
func (b *IntArgRegBitmap) Set(i int) {
|
||||
b[i/8] |= uint8(1) << (i % 8)
|
||||
}
|
||||
|
||||
// Get returns whether the i'th bit of the bitmap is set.
|
||||
//
|
||||
// nosplit because it's called in extremely sensitive contexts, like
|
||||
// on the reflectcall return path.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *IntArgRegBitmap) Get(i int) bool {
|
||||
return b[i/8]&(uint8(1)<<(i%8)) != 0
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
const (
|
||||
// See abi_generic.go.
|
||||
|
||||
// RAX, RBX, RCX, RDI, RSI, R8, R9, R10, R11.
|
||||
IntArgRegs = 9
|
||||
|
||||
// X0 -> X14.
|
||||
FloatArgRegs = 15
|
||||
|
||||
// We use SSE2 registers which support 64-bit float operations.
|
||||
EffectiveFloatRegSize = 8
|
||||
)
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
const (
|
||||
// See abi_generic.go.
|
||||
|
||||
// R0 - R15.
|
||||
IntArgRegs = 16
|
||||
|
||||
// F0 - F15.
|
||||
FloatArgRegs = 16
|
||||
|
||||
EffectiveFloatRegSize = 8
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !goexperiment.regabiargs && !amd64 && !arm64 && !loong64 && !ppc64 && !ppc64le && !riscv64
|
||||
|
||||
package abi
|
||||
|
||||
const (
|
||||
// ABI-related constants.
|
||||
//
|
||||
// In the generic case, these are all zero
|
||||
// which lets them gracefully degrade to ABI0.
|
||||
|
||||
// IntArgRegs is the number of registers dedicated
|
||||
// to passing integer argument values. Result registers are identical
|
||||
// to argument registers, so this number is used for those too.
|
||||
IntArgRegs = 0
|
||||
|
||||
// FloatArgRegs is the number of registers dedicated
|
||||
// to passing floating-point argument values. Result registers are
|
||||
// identical to argument registers, so this number is used for
|
||||
// those too.
|
||||
FloatArgRegs = 0
|
||||
|
||||
// EffectiveFloatRegSize describes the width of floating point
|
||||
// registers on the current platform from the ABI's perspective.
|
||||
//
|
||||
// Since Go only supports 32-bit and 64-bit floating point primitives,
|
||||
// this number should be either 0, 4, or 8. 0 indicates no floating
|
||||
// point registers for the ABI or that floating point values will be
|
||||
// passed via the softfloat ABI.
|
||||
//
|
||||
// For platforms that support larger floating point register widths,
|
||||
// such as x87's 80-bit "registers" (not that we support x87 currently),
|
||||
// use 8.
|
||||
EffectiveFloatRegSize = 0
|
||||
)
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
const (
|
||||
// See abi_generic.go.
|
||||
|
||||
// R4 - R19
|
||||
IntArgRegs = 16
|
||||
|
||||
// F0 - F15
|
||||
FloatArgRegs = 16
|
||||
|
||||
EffectiveFloatRegSize = 8
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ppc64 || ppc64le
|
||||
|
||||
package abi
|
||||
|
||||
const (
|
||||
// See abi_generic.go.
|
||||
|
||||
// R3 - R10, R14 - R17.
|
||||
IntArgRegs = 12
|
||||
|
||||
// F1 - F12.
|
||||
FloatArgRegs = 12
|
||||
|
||||
EffectiveFloatRegSize = 8
|
||||
)
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
const (
|
||||
// See abi_generic.go.
|
||||
|
||||
// X8 - X23
|
||||
IntArgRegs = 16
|
||||
|
||||
// F8 - F23.
|
||||
FloatArgRegs = 16
|
||||
|
||||
EffectiveFloatRegSize = 8
|
||||
)
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
#ifdef GOARCH_386
|
||||
#define PTRSIZE 4
|
||||
#endif
|
||||
#ifdef GOARCH_arm
|
||||
#define PTRSIZE 4
|
||||
#endif
|
||||
#ifdef GOARCH_mips
|
||||
#define PTRSIZE 4
|
||||
#endif
|
||||
#ifdef GOARCH_mipsle
|
||||
#define PTRSIZE 4
|
||||
#endif
|
||||
#ifndef PTRSIZE
|
||||
#define PTRSIZE 8
|
||||
#endif
|
||||
|
||||
TEXT internal∕abi·FuncPCTestFn(SB),NOSPLIT,$0-0
|
||||
RET
|
||||
|
||||
GLOBL internal∕abi·FuncPCTestFnAddr(SB), NOPTR, $PTRSIZE
|
||||
DATA internal∕abi·FuncPCTestFnAddr(SB)/PTRSIZE, $internal∕abi·FuncPCTestFn(SB)
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
// These functions are the build-time version of the Go type data structures.
|
||||
|
||||
// Their contents must be kept in sync with their definitions.
|
||||
// Because the host and target type sizes can differ, the compiler and
|
||||
// linker cannot use the host information that they might get from
|
||||
// either unsafe.Sizeof and Alignof, nor runtime, reflect, or reflectlite.
|
||||
|
||||
// CommonSize returns sizeof(Type) for a compilation target with a given ptrSize
|
||||
func CommonSize(ptrSize int) int { return 4*ptrSize + 8 + 8 }
|
||||
|
||||
// StructFieldSize returns sizeof(StructField) for a compilation target with a given ptrSize
|
||||
func StructFieldSize(ptrSize int) int { return 3 * ptrSize }
|
||||
|
||||
// UncommonSize returns sizeof(UncommonType). This currently does not depend on ptrSize.
|
||||
// This exported function is in an internal package, so it may change to depend on ptrSize in the future.
|
||||
func UncommonSize() uint64 { return 4 + 2 + 2 + 4 + 4 }
|
||||
|
||||
// TFlagOff returns the offset of Type.TFlag for a compilation target with a given ptrSize
|
||||
func TFlagOff(ptrSize int) int { return 2*ptrSize + 4 }
|
||||
|
||||
// ITabTypeOff returns the offset of ITab.Type for a compilation target with a given ptrSize
|
||||
func ITabTypeOff(ptrSize int) int { return ptrSize }
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// NoEscape hides the pointer p from escape analysis, preventing it
|
||||
// from escaping to the heap. It compiles down to nothing.
|
||||
//
|
||||
// WARNING: This is very subtle to use correctly. The caller must
|
||||
// ensure that it's truly safe for p to not escape to the heap by
|
||||
// maintaining runtime pointer invariants (for example, that globals
|
||||
// and the heap may not generally point into a stack).
|
||||
//
|
||||
//go:nosplit
|
||||
//go:nocheckptr
|
||||
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
||||
x := uintptr(p)
|
||||
return unsafe.Pointer(x ^ 0)
|
||||
}
|
||||
|
||||
var alwaysFalse bool
|
||||
var escapeSink any
|
||||
|
||||
// Escape forces any pointers in x to escape to the heap.
|
||||
func Escape[T any](x T) T {
|
||||
if alwaysFalse {
|
||||
escapeSink = x
|
||||
}
|
||||
return x
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
func FuncPCTestFn()
|
||||
|
||||
var FuncPCTestFnAddr uintptr // address of FuncPCTestFn, directly retrieved from assembly
|
||||
|
||||
//go:noinline
|
||||
func FuncPCTest() uintptr {
|
||||
return FuncPCABI0(FuncPCTestFn)
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gccgo
|
||||
|
||||
package abi
|
||||
|
||||
// FuncPC* intrinsics.
|
||||
//
|
||||
// CAREFUL: In programs with plugins, FuncPC* can return different values
|
||||
// for the same function (because there are actually multiple copies of
|
||||
// the same function in the address space). To be safe, don't use the
|
||||
// results of this function in any == expression. It is only safe to
|
||||
// use the result as an address at which to start executing code.
|
||||
|
||||
// FuncPCABI0 returns the entry PC of the function f, which must be a
|
||||
// direct reference of a function defined as ABI0. Otherwise it is a
|
||||
// compile-time error.
|
||||
//
|
||||
// Implemented as a compile intrinsic.
|
||||
func FuncPCABI0(f interface{}) uintptr
|
||||
|
||||
// FuncPCABIInternal returns the entry PC of the function f. If f is a
|
||||
// direct reference of a function, it must be defined as ABIInternal.
|
||||
// Otherwise it is a compile-time error. If f is not a direct reference
|
||||
// of a defined function, it assumes that f is a func value. Otherwise
|
||||
// the behavior is undefined.
|
||||
//
|
||||
// Implemented as a compile intrinsic.
|
||||
func FuncPCABIInternal(f interface{}) uintptr
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// For bootstrapping with gccgo.
|
||||
|
||||
//go:build gccgo
|
||||
|
||||
package abi
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func FuncPCABI0(f interface{}) uintptr {
|
||||
words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f))
|
||||
return *(*uintptr)(unsafe.Pointer(words[1]))
|
||||
}
|
||||
|
||||
func FuncPCABIInternal(f interface{}) uintptr {
|
||||
words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f))
|
||||
return *(*uintptr)(unsafe.Pointer(words[1]))
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// The first word of every non-empty interface type contains an *ITab.
|
||||
// It records the underlying concrete type (Type), the interface type it
|
||||
// is implementing (Inter), and some ancillary information.
|
||||
//
|
||||
// allocated in non-garbage-collected memory
|
||||
type ITab struct {
|
||||
Inter *InterfaceType
|
||||
Type *Type
|
||||
Hash uint32 // copy of Type.Hash. Used for type switches.
|
||||
Fun [1]uintptr // variable sized. fun[0]==0 means Type does not implement Inter.
|
||||
}
|
||||
|
||||
// EmptyInterface describes the layout of a "interface{}" or a "any."
|
||||
// These are represented differently than non-empty interface, as the first
|
||||
// word always points to an abi.Type.
|
||||
type EmptyInterface struct {
|
||||
Type *Type
|
||||
Data unsafe.Pointer
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Map constants common to several packages
|
||||
// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
|
||||
const (
|
||||
// Maximum number of key/elem pairs a bucket can hold.
|
||||
OldMapBucketCountBits = 3 // log2 of number of elements in a bucket.
|
||||
OldMapBucketCount = 1 << OldMapBucketCountBits
|
||||
|
||||
// Maximum key or elem size to keep inline (instead of mallocing per element).
|
||||
// Must fit in a uint8.
|
||||
// Note: fast map functions cannot handle big elems (bigger than MapMaxElemBytes).
|
||||
OldMapMaxKeyBytes = 128
|
||||
OldMapMaxElemBytes = 128 // Must fit in a uint8.
|
||||
)
|
||||
|
||||
type OldMapType struct {
|
||||
Type
|
||||
Key *Type
|
||||
Elem *Type
|
||||
Bucket *Type // internal type representing a hash bucket
|
||||
// function for hashing keys (ptr to key, seed) -> hash
|
||||
Hasher func(unsafe.Pointer, uintptr) uintptr
|
||||
KeySize uint8 // size of key slot
|
||||
ValueSize uint8 // size of elem slot
|
||||
BucketSize uint16 // size of bucket
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// Note: flag values must match those used in the TMAP case
|
||||
// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
|
||||
func (mt *OldMapType) IndirectKey() bool { // store ptr to key instead of key itself
|
||||
return mt.Flags&1 != 0
|
||||
}
|
||||
func (mt *OldMapType) IndirectElem() bool { // store ptr to elem instead of elem itself
|
||||
return mt.Flags&2 != 0
|
||||
}
|
||||
func (mt *OldMapType) ReflexiveKey() bool { // true if k==k for all keys
|
||||
return mt.Flags&4 != 0
|
||||
}
|
||||
func (mt *OldMapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
|
||||
return mt.Flags&8 != 0
|
||||
}
|
||||
func (mt *OldMapType) HashMightPanic() bool { // true if hash function might panic
|
||||
return mt.Flags&16 != 0
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !goexperiment.swissmap
|
||||
|
||||
package abi
|
||||
|
||||
// See comment in map_select_swiss.go.
|
||||
type mapType = OldMapType
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build goexperiment.swissmap
|
||||
|
||||
package abi
|
||||
|
||||
// Select the map type that this binary is built using. This is for common
|
||||
// lookup methods like Type.Key to know which type to use.
|
||||
//
|
||||
// Note that mapType *must not be used by any functions called in the
|
||||
// compiler to build a target program* because the compiler must use the map
|
||||
// type determined by run-time GOEXPERIMENT, not the build tags used to build
|
||||
// the compiler.
|
||||
//
|
||||
// TODO(prattmic): This package is rather confusing because it has many
|
||||
// functions that can't be used by the compiler (e.g., Type.Uncommon depends on
|
||||
// the layout of type + uncommon objects in the binary. It would be incorrect
|
||||
// for an ad-hoc local Type object). It may be best to move code that isn't
|
||||
// usable by the compiler out of the package.
|
||||
type mapType = SwissMapType
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Map constants common to several packages
|
||||
// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
|
||||
const (
|
||||
// Number of bits in the group.slot count.
|
||||
SwissMapGroupSlotsBits = 3
|
||||
|
||||
// Number of slots in a group.
|
||||
SwissMapGroupSlots = 1 << SwissMapGroupSlotsBits // 8
|
||||
|
||||
// Maximum key or elem size to keep inline (instead of mallocing per element).
|
||||
// Must fit in a uint8.
|
||||
SwissMapMaxKeyBytes = 128
|
||||
SwissMapMaxElemBytes = 128
|
||||
|
||||
ctrlEmpty = 0b10000000
|
||||
bitsetLSB = 0x0101010101010101
|
||||
|
||||
// Value of control word with all empty slots.
|
||||
SwissMapCtrlEmpty = bitsetLSB * uint64(ctrlEmpty)
|
||||
)
|
||||
|
||||
type SwissMapType struct {
|
||||
Type
|
||||
Key *Type
|
||||
Elem *Type
|
||||
Group *Type // internal type representing a slot group
|
||||
// function for hashing keys (ptr to key, seed) -> hash
|
||||
Hasher func(unsafe.Pointer, uintptr) uintptr
|
||||
GroupSize uintptr // == Group.Size_
|
||||
SlotSize uintptr // size of key/elem slot
|
||||
ElemOff uintptr // offset of elem in key/elem slot
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// Flag values
|
||||
const (
|
||||
SwissMapNeedKeyUpdate = 1 << iota
|
||||
SwissMapHashMightPanic
|
||||
SwissMapIndirectKey
|
||||
SwissMapIndirectElem
|
||||
)
|
||||
|
||||
func (mt *SwissMapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
|
||||
return mt.Flags&SwissMapNeedKeyUpdate != 0
|
||||
}
|
||||
func (mt *SwissMapType) HashMightPanic() bool { // true if hash function might panic
|
||||
return mt.Flags&SwissMapHashMightPanic != 0
|
||||
}
|
||||
func (mt *SwissMapType) IndirectKey() bool { // store ptr to key instead of key itself
|
||||
return mt.Flags&SwissMapIndirectKey != 0
|
||||
}
|
||||
func (mt *SwissMapType) IndirectElem() bool { // store ptr to elem instead of elem itself
|
||||
return mt.Flags&SwissMapIndirectElem != 0
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
type RF_State int
|
||||
|
||||
// These constants are shared between the compiler, which uses them for state functions
|
||||
// and panic indicators, and the runtime, which turns them into more meaningful strings
|
||||
// For best code generation, RF_DONE and RF_READY should be 0 and 1.
|
||||
const (
|
||||
RF_DONE = RF_State(iota) // body of loop has exited in a non-panic way
|
||||
RF_READY // body of loop has not exited yet, is not running -- this is not a panic index
|
||||
RF_PANIC // body of loop is either currently running, or has panicked
|
||||
RF_EXHAUSTED // iterator function return, i.e., sequence is "exhausted"
|
||||
RF_MISSING_PANIC = 4 // body of loop panicked but iterator function defer-recovered it away
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
// ZeroValSize is the size in bytes of runtime.zeroVal.
|
||||
const ZeroValSize = 1024
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
const (
|
||||
// StackNosplitBase is the base maximum number of bytes that a chain of
|
||||
// NOSPLIT functions can use.
|
||||
//
|
||||
// This value must be multiplied by the stack guard multiplier, so do not
|
||||
// use it directly. See runtime/stack.go:stackNosplit and
|
||||
// cmd/internal/objabi/stack.go:StackNosplit.
|
||||
StackNosplitBase = 800
|
||||
|
||||
// We have three different sequences for stack bounds checks, depending on
|
||||
// whether the stack frame of a function is small, big, or huge.
|
||||
|
||||
// After a stack split check the SP is allowed to be StackSmall bytes below
|
||||
// the stack guard.
|
||||
//
|
||||
// Functions that need frames <= StackSmall can perform the stack check
|
||||
// using a single comparison directly between the stack guard and the SP
|
||||
// because we ensure that StackSmall bytes of stack space are available
|
||||
// beyond the stack guard.
|
||||
StackSmall = 128
|
||||
|
||||
// Functions that need frames <= StackBig can assume that neither
|
||||
// SP-framesize nor stackGuard-StackSmall will underflow, and thus use a
|
||||
// more efficient check. In order to ensure this, StackBig must be <= the
|
||||
// size of the unmapped space at zero.
|
||||
StackBig = 4096
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file silences errors about body-less functions
|
||||
// that are provided by intrinsics in the latest version of the compiler,
|
||||
// but may not be known to the bootstrap compiler.
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
import "internal/goarch"
|
||||
|
||||
type InterfaceSwitch struct {
|
||||
Cache *InterfaceSwitchCache
|
||||
NCases int
|
||||
|
||||
// Array of NCases elements.
|
||||
// Each case must be a non-empty interface type.
|
||||
Cases [1]*InterfaceType
|
||||
}
|
||||
|
||||
type InterfaceSwitchCache struct {
|
||||
Mask uintptr // mask for index. Must be a power of 2 minus 1
|
||||
Entries [1]InterfaceSwitchCacheEntry // Mask+1 entries total
|
||||
}
|
||||
|
||||
type InterfaceSwitchCacheEntry struct {
|
||||
// type of source value (a *Type)
|
||||
Typ uintptr
|
||||
// case # to dispatch to
|
||||
Case int
|
||||
// itab to use for resulting case variable (a *runtime.itab)
|
||||
Itab uintptr
|
||||
}
|
||||
|
||||
func UseInterfaceSwitchCache(arch goarch.ArchFamilyType) bool {
|
||||
// We need an atomic load instruction to make the cache multithreaded-safe.
|
||||
// (AtomicLoadPtr needs to be implemented in cmd/compile/internal/ssa/_gen/ARCH.rules.)
|
||||
switch arch {
|
||||
case goarch.AMD64, goarch.ARM64, goarch.LOONG64, goarch.MIPS, goarch.MIPS64, goarch.PPC64, goarch.RISCV64, goarch.S390X:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type TypeAssert struct {
|
||||
Cache *TypeAssertCache
|
||||
Inter *InterfaceType
|
||||
CanFail bool
|
||||
}
|
||||
type TypeAssertCache struct {
|
||||
Mask uintptr
|
||||
Entries [1]TypeAssertCacheEntry
|
||||
}
|
||||
type TypeAssertCacheEntry struct {
|
||||
// type of source value (a *runtime._type)
|
||||
Typ uintptr
|
||||
// itab to use for result (a *runtime.itab)
|
||||
// nil if CanFail is set and conversion would fail.
|
||||
Itab uintptr
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
// A FuncFlag records bits about a function, passed to the runtime.
|
||||
type FuncFlag uint8
|
||||
|
||||
const (
|
||||
// FuncFlagTopFrame indicates a function that appears at the top of its stack.
|
||||
// The traceback routine stop at such a function and consider that a
|
||||
// successful, complete traversal of the stack.
|
||||
// Examples of TopFrame functions include goexit, which appears
|
||||
// at the top of a user goroutine stack, and mstart, which appears
|
||||
// at the top of a system goroutine stack.
|
||||
FuncFlagTopFrame FuncFlag = 1 << iota
|
||||
|
||||
// FuncFlagSPWrite indicates a function that writes an arbitrary value to SP
|
||||
// (any write other than adding or subtracting a constant amount).
|
||||
// The traceback routines cannot encode such changes into the
|
||||
// pcsp tables, so the function traceback cannot safely unwind past
|
||||
// SPWrite functions. Stopping at an SPWrite function is considered
|
||||
// to be an incomplete unwinding of the stack. In certain contexts
|
||||
// (in particular garbage collector stack scans) that is a fatal error.
|
||||
FuncFlagSPWrite
|
||||
|
||||
// FuncFlagAsm indicates that a function was implemented in assembly.
|
||||
FuncFlagAsm
|
||||
)
|
||||
|
||||
// A FuncID identifies particular functions that need to be treated
|
||||
// specially by the runtime.
|
||||
// Note that in some situations involving plugins, there may be multiple
|
||||
// copies of a particular special runtime function.
|
||||
type FuncID uint8
|
||||
|
||||
const (
|
||||
// If you add a FuncID, you probably also want to add an entry to the map in
|
||||
// ../../cmd/internal/objabi/funcid.go
|
||||
|
||||
FuncIDNormal FuncID = iota // not a special function
|
||||
FuncID_abort
|
||||
FuncID_asmcgocall
|
||||
FuncID_asyncPreempt
|
||||
FuncID_cgocallback
|
||||
FuncID_corostart
|
||||
FuncID_debugCallV2
|
||||
FuncID_gcBgMarkWorker
|
||||
FuncID_goexit
|
||||
FuncID_gogo
|
||||
FuncID_gopanic
|
||||
FuncID_handleAsyncEvent
|
||||
FuncID_mcall
|
||||
FuncID_morestack
|
||||
FuncID_mstart
|
||||
FuncID_panicwrap
|
||||
FuncID_rt0_go
|
||||
FuncID_runfinq
|
||||
FuncID_runtime_main
|
||||
FuncID_sigpanic
|
||||
FuncID_systemstack
|
||||
FuncID_systemstack_switch
|
||||
FuncIDWrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
|
||||
)
|
||||
|
||||
// ArgsSizeUnknown is set in Func.argsize to mark all functions
|
||||
// whose argument size is unknown (C vararg functions, and
|
||||
// assembly code without an explicit specification).
|
||||
// This value is generated by the compiler, assembler, or linker.
|
||||
const ArgsSizeUnknown = -0x80000000
|
||||
|
||||
// IDs for PCDATA and FUNCDATA tables in Go binaries.
|
||||
//
|
||||
// These must agree with ../../../runtime/funcdata.h.
|
||||
const (
|
||||
PCDATA_UnsafePoint = 0
|
||||
PCDATA_StackMapIndex = 1
|
||||
PCDATA_InlTreeIndex = 2
|
||||
PCDATA_ArgLiveIndex = 3
|
||||
|
||||
FUNCDATA_ArgsPointerMaps = 0
|
||||
FUNCDATA_LocalsPointerMaps = 1
|
||||
FUNCDATA_StackObjects = 2
|
||||
FUNCDATA_InlTree = 3
|
||||
FUNCDATA_OpenCodedDeferInfo = 4
|
||||
FUNCDATA_ArgInfo = 5
|
||||
FUNCDATA_ArgLiveInfo = 6
|
||||
FUNCDATA_WrapInfo = 7
|
||||
)
|
||||
|
||||
// Special values for the PCDATA_UnsafePoint table.
|
||||
const (
|
||||
UnsafePointSafe = -1 // Safe for async preemption
|
||||
UnsafePointUnsafe = -2 // Unsafe for async preemption
|
||||
|
||||
// UnsafePointRestart1(2) apply on a sequence of instructions, within
|
||||
// which if an async preemption happens, we should back off the PC
|
||||
// to the start of the sequence when resuming.
|
||||
// We need two so we can distinguish the start/end of the sequence
|
||||
// in case that two sequences are next to each other.
|
||||
UnsafePointRestart1 = -3
|
||||
UnsafePointRestart2 = -4
|
||||
|
||||
// Like UnsafePointRestart1, but back to function entry if async preempted.
|
||||
UnsafePointRestartAtEntry = -5
|
||||
)
|
||||
|
||||
const MINFUNC = 16 // minimum size for a function
|
||||
|
||||
const FuncTabBucketSize = 256 * MINFUNC // size of bucket in the pc->func lookup table
|
|
@ -0,0 +1,779 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package abi
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Type is the runtime representation of a Go type.
|
||||
//
|
||||
// Be careful about accessing this type at build time, as the version
|
||||
// of this type in the compiler/linker may not have the same layout
|
||||
// as the version in the target binary, due to pointer width
|
||||
// differences and any experiments. Use cmd/compile/internal/rttype
|
||||
// or the functions in compiletype.go to access this type instead.
|
||||
// (TODO: this admonition applies to every type in this package.
|
||||
// Put it in some shared location?)
|
||||
type Type struct {
|
||||
Size_ uintptr
|
||||
PtrBytes uintptr // number of (prefix) bytes in the type that can contain pointers
|
||||
Hash uint32 // hash of type; avoids computation in hash tables
|
||||
TFlag TFlag // extra type information flags
|
||||
Align_ uint8 // alignment of variable with this type
|
||||
FieldAlign_ uint8 // alignment of struct field with this type
|
||||
Kind_ Kind // enumeration for C
|
||||
// function for comparing objects of this type
|
||||
// (ptr to object A, ptr to object B) -> ==?
|
||||
Equal func(unsafe.Pointer, unsafe.Pointer) bool
|
||||
// GCData stores the GC type data for the garbage collector.
|
||||
// Normally, GCData points to a bitmask that describes the
|
||||
// ptr/nonptr fields of the type. The bitmask will have at
|
||||
// least PtrBytes/ptrSize bits.
|
||||
// If the TFlagGCMaskOnDemand bit is set, GCData is instead a
|
||||
// **byte and the pointer to the bitmask is one dereference away.
|
||||
// The runtime will build the bitmask if needed.
|
||||
// (See runtime/type.go:getGCMask.)
|
||||
// Note: multiple types may have the same value of GCData,
|
||||
// including when TFlagGCMaskOnDemand is set. The types will, of course,
|
||||
// have the same pointer layout (but not necessarily the same size).
|
||||
GCData *byte
|
||||
Str NameOff // string form
|
||||
PtrToThis TypeOff // type for pointer to this type, may be zero
|
||||
}
|
||||
|
||||
// A Kind represents the specific kind of type that a Type represents.
|
||||
// The zero Kind is not a valid kind.
|
||||
type Kind uint8
|
||||
|
||||
const (
|
||||
Invalid Kind = iota
|
||||
Bool
|
||||
Int
|
||||
Int8
|
||||
Int16
|
||||
Int32
|
||||
Int64
|
||||
Uint
|
||||
Uint8
|
||||
Uint16
|
||||
Uint32
|
||||
Uint64
|
||||
Uintptr
|
||||
Float32
|
||||
Float64
|
||||
Complex64
|
||||
Complex128
|
||||
Array
|
||||
Chan
|
||||
Func
|
||||
Interface
|
||||
Map
|
||||
Pointer
|
||||
Slice
|
||||
String
|
||||
Struct
|
||||
UnsafePointer
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO (khr, drchase) why aren't these in TFlag? Investigate, fix if possible.
|
||||
KindDirectIface Kind = 1 << 5
|
||||
KindMask Kind = (1 << 5) - 1
|
||||
)
|
||||
|
||||
// TFlag is used by a Type to signal what extra type information is
|
||||
// available in the memory directly following the Type value.
|
||||
type TFlag uint8
|
||||
|
||||
const (
|
||||
// TFlagUncommon means that there is a data with a type, UncommonType,
|
||||
// just beyond the shared-per-type common data. That is, the data
|
||||
// for struct types will store their UncommonType at one offset, the
|
||||
// data for interface types will store their UncommonType at a different
|
||||
// offset. UncommonType is always accessed via a pointer that is computed
|
||||
// using trust-us-we-are-the-implementors pointer arithmetic.
|
||||
//
|
||||
// For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0,
|
||||
// then t has UncommonType data and it can be accessed as:
|
||||
//
|
||||
// type structTypeUncommon struct {
|
||||
// structType
|
||||
// u UncommonType
|
||||
// }
|
||||
// u := &(*structTypeUncommon)(unsafe.Pointer(t)).u
|
||||
TFlagUncommon TFlag = 1 << 0
|
||||
|
||||
// TFlagExtraStar means the name in the str field has an
|
||||
// extraneous '*' prefix. This is because for most types T in
|
||||
// a program, the type *T also exists and reusing the str data
|
||||
// saves binary size.
|
||||
TFlagExtraStar TFlag = 1 << 1
|
||||
|
||||
// TFlagNamed means the type has a name.
|
||||
TFlagNamed TFlag = 1 << 2
|
||||
|
||||
// TFlagRegularMemory means that equal and hash functions can treat
|
||||
// this type as a single region of t.size bytes.
|
||||
TFlagRegularMemory TFlag = 1 << 3
|
||||
|
||||
// TFlagGCMaskOnDemand means that the GC pointer bitmask will be
|
||||
// computed on demand at runtime instead of being precomputed at
|
||||
// compile time. If this flag is set, the GCData field effectively
|
||||
// has type **byte instead of *byte. The runtime will store a
|
||||
// pointer to the GC pointer bitmask in *GCData.
|
||||
TFlagGCMaskOnDemand TFlag = 1 << 4
|
||||
)
|
||||
|
||||
// NameOff is the offset to a name from moduledata.types. See resolveNameOff in runtime.
|
||||
type NameOff int32
|
||||
|
||||
// TypeOff is the offset to a type from moduledata.types. See resolveTypeOff in runtime.
|
||||
type TypeOff int32
|
||||
|
||||
// TextOff is an offset from the top of a text section. See (rtype).textOff in runtime.
|
||||
type TextOff int32
|
||||
|
||||
// String returns the name of k.
|
||||
func (k Kind) String() string {
|
||||
if int(k) < len(kindNames) {
|
||||
return kindNames[k]
|
||||
}
|
||||
return kindNames[0]
|
||||
}
|
||||
|
||||
var kindNames = []string{
|
||||
Invalid: "invalid",
|
||||
Bool: "bool",
|
||||
Int: "int",
|
||||
Int8: "int8",
|
||||
Int16: "int16",
|
||||
Int32: "int32",
|
||||
Int64: "int64",
|
||||
Uint: "uint",
|
||||
Uint8: "uint8",
|
||||
Uint16: "uint16",
|
||||
Uint32: "uint32",
|
||||
Uint64: "uint64",
|
||||
Uintptr: "uintptr",
|
||||
Float32: "float32",
|
||||
Float64: "float64",
|
||||
Complex64: "complex64",
|
||||
Complex128: "complex128",
|
||||
Array: "array",
|
||||
Chan: "chan",
|
||||
Func: "func",
|
||||
Interface: "interface",
|
||||
Map: "map",
|
||||
Pointer: "ptr",
|
||||
Slice: "slice",
|
||||
String: "string",
|
||||
Struct: "struct",
|
||||
UnsafePointer: "unsafe.Pointer",
|
||||
}
|
||||
|
||||
// TypeOf returns the abi.Type of some value.
|
||||
func TypeOf(a any) *Type {
|
||||
eface := *(*EmptyInterface)(unsafe.Pointer(&a))
|
||||
// Types are either static (for compiler-created types) or
|
||||
// heap-allocated but always reachable (for reflection-created
|
||||
// types, held in the central map). So there is no need to
|
||||
// escape types. noescape here help avoid unnecessary escape
|
||||
// of v.
|
||||
return (*Type)(NoEscape(unsafe.Pointer(eface.Type)))
|
||||
}
|
||||
|
||||
// TypeFor returns the abi.Type for a type parameter.
|
||||
func TypeFor[T any]() *Type {
|
||||
return (*PtrType)(unsafe.Pointer(TypeOf((*T)(nil)))).Elem
|
||||
}
|
||||
|
||||
func (t *Type) Kind() Kind { return t.Kind_ & KindMask }
|
||||
|
||||
func (t *Type) HasName() bool {
|
||||
return t.TFlag&TFlagNamed != 0
|
||||
}
|
||||
|
||||
// Pointers reports whether t contains pointers.
|
||||
func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
|
||||
|
||||
// IfaceIndir reports whether t is stored indirectly in an interface value.
|
||||
func (t *Type) IfaceIndir() bool {
|
||||
return t.Kind_&KindDirectIface == 0
|
||||
}
|
||||
|
||||
// isDirectIface reports whether t is stored directly in an interface value.
|
||||
func (t *Type) IsDirectIface() bool {
|
||||
return t.Kind_&KindDirectIface != 0
|
||||
}
|
||||
|
||||
func (t *Type) GcSlice(begin, end uintptr) []byte {
|
||||
if t.TFlag&TFlagGCMaskOnDemand != 0 {
|
||||
panic("GcSlice can't handle on-demand gcdata types")
|
||||
}
|
||||
return unsafe.Slice(t.GCData, int(end))[begin:]
|
||||
}
|
||||
|
||||
// Method on non-interface type
|
||||
type Method struct {
|
||||
Name NameOff // name of method
|
||||
Mtyp TypeOff // method type (without receiver)
|
||||
Ifn TextOff // fn used in interface call (one-word receiver)
|
||||
Tfn TextOff // fn used for normal method call
|
||||
}
|
||||
|
||||
// UncommonType is present only for defined types or types with methods
|
||||
// (if T is a defined type, the uncommonTypes for T and *T have methods).
|
||||
// Using a pointer to this struct reduces the overall size required
|
||||
// to describe a non-defined type with no methods.
|
||||
type UncommonType struct {
|
||||
PkgPath NameOff // import path; empty for built-in types like int, string
|
||||
Mcount uint16 // number of methods
|
||||
Xcount uint16 // number of exported methods
|
||||
Moff uint32 // offset from this uncommontype to [mcount]Method
|
||||
_ uint32 // unused
|
||||
}
|
||||
|
||||
func (t *UncommonType) Methods() []Method {
|
||||
if t.Mcount == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
|
||||
}
|
||||
|
||||
func (t *UncommonType) ExportedMethods() []Method {
|
||||
if t.Xcount == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
|
||||
}
|
||||
|
||||
// addChecked returns p+x.
|
||||
//
|
||||
// The whySafe string is ignored, so that the function still inlines
|
||||
// as efficiently as p+x, but all call sites should use the string to
|
||||
// record why the addition is safe, which is to say why the addition
|
||||
// does not cause x to advance to the very end of p's allocation
|
||||
// and therefore point incorrectly at the next block in memory.
|
||||
func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(p) + x)
|
||||
}
|
||||
|
||||
// Imethod represents a method on an interface type
|
||||
type Imethod struct {
|
||||
Name NameOff // name of method
|
||||
Typ TypeOff // .(*FuncType) underneath
|
||||
}
|
||||
|
||||
// ArrayType represents a fixed array type.
|
||||
type ArrayType struct {
|
||||
Type
|
||||
Elem *Type // array element type
|
||||
Slice *Type // slice type
|
||||
Len uintptr
|
||||
}
|
||||
|
||||
// Len returns the length of t if t is an array type, otherwise 0
|
||||
func (t *Type) Len() int {
|
||||
if t.Kind() == Array {
|
||||
return int((*ArrayType)(unsafe.Pointer(t)).Len)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (t *Type) Common() *Type {
|
||||
return t
|
||||
}
|
||||
|
||||
type ChanDir int
|
||||
|
||||
const (
|
||||
RecvDir ChanDir = 1 << iota // <-chan
|
||||
SendDir // chan<-
|
||||
BothDir = RecvDir | SendDir // chan
|
||||
InvalidDir ChanDir = 0
|
||||
)
|
||||
|
||||
// ChanType represents a channel type
|
||||
type ChanType struct {
|
||||
Type
|
||||
Elem *Type
|
||||
Dir ChanDir
|
||||
}
|
||||
|
||||
type structTypeUncommon struct {
|
||||
StructType
|
||||
u UncommonType
|
||||
}
|
||||
|
||||
// ChanDir returns the direction of t if t is a channel type, otherwise InvalidDir (0).
|
||||
func (t *Type) ChanDir() ChanDir {
|
||||
if t.Kind() == Chan {
|
||||
ch := (*ChanType)(unsafe.Pointer(t))
|
||||
return ch.Dir
|
||||
}
|
||||
return InvalidDir
|
||||
}
|
||||
|
||||
// Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nil
|
||||
func (t *Type) Uncommon() *UncommonType {
|
||||
if t.TFlag&TFlagUncommon == 0 {
|
||||
return nil
|
||||
}
|
||||
switch t.Kind() {
|
||||
case Struct:
|
||||
return &(*structTypeUncommon)(unsafe.Pointer(t)).u
|
||||
case Pointer:
|
||||
type u struct {
|
||||
PtrType
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
case Func:
|
||||
type u struct {
|
||||
FuncType
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
case Slice:
|
||||
type u struct {
|
||||
SliceType
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
case Array:
|
||||
type u struct {
|
||||
ArrayType
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
case Chan:
|
||||
type u struct {
|
||||
ChanType
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
case Map:
|
||||
type u struct {
|
||||
mapType
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
case Interface:
|
||||
type u struct {
|
||||
InterfaceType
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
default:
|
||||
type u struct {
|
||||
Type
|
||||
u UncommonType
|
||||
}
|
||||
return &(*u)(unsafe.Pointer(t)).u
|
||||
}
|
||||
}
|
||||
|
||||
// Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
|
||||
func (t *Type) Elem() *Type {
|
||||
switch t.Kind() {
|
||||
case Array:
|
||||
tt := (*ArrayType)(unsafe.Pointer(t))
|
||||
return tt.Elem
|
||||
case Chan:
|
||||
tt := (*ChanType)(unsafe.Pointer(t))
|
||||
return tt.Elem
|
||||
case Map:
|
||||
tt := (*mapType)(unsafe.Pointer(t))
|
||||
return tt.Elem
|
||||
case Pointer:
|
||||
tt := (*PtrType)(unsafe.Pointer(t))
|
||||
return tt.Elem
|
||||
case Slice:
|
||||
tt := (*SliceType)(unsafe.Pointer(t))
|
||||
return tt.Elem
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StructType returns t cast to a *StructType, or nil if its tag does not match.
|
||||
func (t *Type) StructType() *StructType {
|
||||
if t.Kind() != Struct {
|
||||
return nil
|
||||
}
|
||||
return (*StructType)(unsafe.Pointer(t))
|
||||
}
|
||||
|
||||
// MapType returns t cast to a *OldMapType or *SwissMapType, or nil if its tag does not match.
|
||||
func (t *Type) MapType() *mapType {
|
||||
if t.Kind() != Map {
|
||||
return nil
|
||||
}
|
||||
return (*mapType)(unsafe.Pointer(t))
|
||||
}
|
||||
|
||||
// ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
|
||||
func (t *Type) ArrayType() *ArrayType {
|
||||
if t.Kind() != Array {
|
||||
return nil
|
||||
}
|
||||
return (*ArrayType)(unsafe.Pointer(t))
|
||||
}
|
||||
|
||||
// FuncType returns t cast to a *FuncType, or nil if its tag does not match.
|
||||
func (t *Type) FuncType() *FuncType {
|
||||
if t.Kind() != Func {
|
||||
return nil
|
||||
}
|
||||
return (*FuncType)(unsafe.Pointer(t))
|
||||
}
|
||||
|
||||
// InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
|
||||
func (t *Type) InterfaceType() *InterfaceType {
|
||||
if t.Kind() != Interface {
|
||||
return nil
|
||||
}
|
||||
return (*InterfaceType)(unsafe.Pointer(t))
|
||||
}
|
||||
|
||||
// Size returns the size of data with type t.
|
||||
func (t *Type) Size() uintptr { return t.Size_ }
|
||||
|
||||
// Align returns the alignment of data with type t.
|
||||
func (t *Type) Align() int { return int(t.Align_) }
|
||||
|
||||
func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
|
||||
|
||||
type InterfaceType struct {
|
||||
Type
|
||||
PkgPath Name // import path
|
||||
Methods []Imethod // sorted by hash
|
||||
}
|
||||
|
||||
func (t *Type) ExportedMethods() []Method {
|
||||
ut := t.Uncommon()
|
||||
if ut == nil {
|
||||
return nil
|
||||
}
|
||||
return ut.ExportedMethods()
|
||||
}
|
||||
|
||||
func (t *Type) NumMethod() int {
|
||||
if t.Kind() == Interface {
|
||||
tt := (*InterfaceType)(unsafe.Pointer(t))
|
||||
return tt.NumMethod()
|
||||
}
|
||||
return len(t.ExportedMethods())
|
||||
}
|
||||
|
||||
// NumMethod returns the number of interface methods in the type's method set.
|
||||
func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
|
||||
|
||||
func (t *Type) Key() *Type {
|
||||
if t.Kind() == Map {
|
||||
return (*mapType)(unsafe.Pointer(t)).Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SliceType struct {
|
||||
Type
|
||||
Elem *Type // slice element type
|
||||
}
|
||||
|
||||
// funcType represents a function type.
|
||||
//
|
||||
// A *Type for each in and out parameter is stored in an array that
|
||||
// directly follows the funcType (and possibly its uncommonType). So
|
||||
// a function type with one method, one input, and one output is:
|
||||
//
|
||||
// struct {
|
||||
// funcType
|
||||
// uncommonType
|
||||
// [2]*rtype // [0] is in, [1] is out
|
||||
// }
|
||||
type FuncType struct {
|
||||
Type
|
||||
InCount uint16
|
||||
OutCount uint16 // top bit is set if last input parameter is ...
|
||||
}
|
||||
|
||||
func (t *FuncType) In(i int) *Type {
|
||||
return t.InSlice()[i]
|
||||
}
|
||||
|
||||
func (t *FuncType) NumIn() int {
|
||||
return int(t.InCount)
|
||||
}
|
||||
|
||||
func (t *FuncType) NumOut() int {
|
||||
return int(t.OutCount & (1<<15 - 1))
|
||||
}
|
||||
|
||||
func (t *FuncType) Out(i int) *Type {
|
||||
return (t.OutSlice()[i])
|
||||
}
|
||||
|
||||
func (t *FuncType) InSlice() []*Type {
|
||||
uadd := unsafe.Sizeof(*t)
|
||||
if t.TFlag&TFlagUncommon != 0 {
|
||||
uadd += unsafe.Sizeof(UncommonType{})
|
||||
}
|
||||
if t.InCount == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
|
||||
}
|
||||
func (t *FuncType) OutSlice() []*Type {
|
||||
outCount := uint16(t.NumOut())
|
||||
if outCount == 0 {
|
||||
return nil
|
||||
}
|
||||
uadd := unsafe.Sizeof(*t)
|
||||
if t.TFlag&TFlagUncommon != 0 {
|
||||
uadd += unsafe.Sizeof(UncommonType{})
|
||||
}
|
||||
return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
|
||||
}
|
||||
|
||||
func (t *FuncType) IsVariadic() bool {
|
||||
return t.OutCount&(1<<15) != 0
|
||||
}
|
||||
|
||||
type PtrType struct {
|
||||
Type
|
||||
Elem *Type // pointer element (pointed at) type
|
||||
}
|
||||
|
||||
type StructField struct {
|
||||
Name Name // name is always non-empty
|
||||
Typ *Type // type of field
|
||||
Offset uintptr // byte offset of field
|
||||
}
|
||||
|
||||
func (f *StructField) Embedded() bool {
|
||||
return f.Name.IsEmbedded()
|
||||
}
|
||||
|
||||
type StructType struct {
|
||||
Type
|
||||
PkgPath Name
|
||||
Fields []StructField
|
||||
}
|
||||
|
||||
// Name is an encoded type Name with optional extra data.
|
||||
//
|
||||
// The first byte is a bit field containing:
|
||||
//
|
||||
// 1<<0 the name is exported
|
||||
// 1<<1 tag data follows the name
|
||||
// 1<<2 pkgPath nameOff follows the name and tag
|
||||
// 1<<3 the name is of an embedded (a.k.a. anonymous) field
|
||||
//
|
||||
// Following that, there is a varint-encoded length of the name,
|
||||
// followed by the name itself.
|
||||
//
|
||||
// If tag data is present, it also has a varint-encoded length
|
||||
// followed by the tag itself.
|
||||
//
|
||||
// If the import path follows, then 4 bytes at the end of
|
||||
// the data form a nameOff. The import path is only set for concrete
|
||||
// methods that are defined in a different package than their type.
|
||||
//
|
||||
// If a name starts with "*", then the exported bit represents
|
||||
// whether the pointed to type is exported.
|
||||
//
|
||||
// Note: this encoding must match here and in:
|
||||
// cmd/compile/internal/reflectdata/reflect.go
|
||||
// cmd/link/internal/ld/decodesym.go
|
||||
|
||||
type Name struct {
|
||||
Bytes *byte
|
||||
}
|
||||
|
||||
// DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
|
||||
// be safe for the reason in whySafe (which can appear in a backtrace, etc.)
|
||||
func (n Name) DataChecked(off int, whySafe string) *byte {
|
||||
return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
|
||||
}
|
||||
|
||||
// Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
|
||||
// be safe because the runtime made the call (other packages use DataChecked)
|
||||
func (n Name) Data(off int) *byte {
|
||||
return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
|
||||
}
|
||||
|
||||
// IsExported returns "is n exported?"
|
||||
func (n Name) IsExported() bool {
|
||||
return (*n.Bytes)&(1<<0) != 0
|
||||
}
|
||||
|
||||
// HasTag returns true iff there is tag data following this name
|
||||
func (n Name) HasTag() bool {
|
||||
return (*n.Bytes)&(1<<1) != 0
|
||||
}
|
||||
|
||||
// IsEmbedded returns true iff n is embedded (an anonymous field).
|
||||
func (n Name) IsEmbedded() bool {
|
||||
return (*n.Bytes)&(1<<3) != 0
|
||||
}
|
||||
|
||||
// ReadVarint parses a varint as encoded by encoding/binary.
|
||||
// It returns the number of encoded bytes and the encoded value.
|
||||
func (n Name) ReadVarint(off int) (int, int) {
|
||||
v := 0
|
||||
for i := 0; ; i++ {
|
||||
x := *n.DataChecked(off+i, "read varint")
|
||||
v += int(x&0x7f) << (7 * i)
|
||||
if x&0x80 == 0 {
|
||||
return i + 1, v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsBlank indicates whether n is "_".
|
||||
func (n Name) IsBlank() bool {
|
||||
if n.Bytes == nil {
|
||||
return false
|
||||
}
|
||||
_, l := n.ReadVarint(1)
|
||||
return l == 1 && *n.Data(2) == '_'
|
||||
}
|
||||
|
||||
// writeVarint writes n to buf in varint form. Returns the
|
||||
// number of bytes written. n must be nonnegative.
|
||||
// Writes at most 10 bytes.
|
||||
func writeVarint(buf []byte, n int) int {
|
||||
for i := 0; ; i++ {
|
||||
b := byte(n & 0x7f)
|
||||
n >>= 7
|
||||
if n == 0 {
|
||||
buf[i] = b
|
||||
return i + 1
|
||||
}
|
||||
buf[i] = b | 0x80
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the tag string for n, or empty if there is none.
|
||||
func (n Name) Name() string {
|
||||
if n.Bytes == nil {
|
||||
return ""
|
||||
}
|
||||
i, l := n.ReadVarint(1)
|
||||
return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
|
||||
}
|
||||
|
||||
// Tag returns the tag string for n, or empty if there is none.
|
||||
func (n Name) Tag() string {
|
||||
if !n.HasTag() {
|
||||
return ""
|
||||
}
|
||||
i, l := n.ReadVarint(1)
|
||||
i2, l2 := n.ReadVarint(1 + i + l)
|
||||
return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
|
||||
}
|
||||
|
||||
func NewName(n, tag string, exported, embedded bool) Name {
|
||||
if len(n) >= 1<<29 {
|
||||
panic("abi.NewName: name too long: " + n[:1024] + "...")
|
||||
}
|
||||
if len(tag) >= 1<<29 {
|
||||
panic("abi.NewName: tag too long: " + tag[:1024] + "...")
|
||||
}
|
||||
var nameLen [10]byte
|
||||
var tagLen [10]byte
|
||||
nameLenLen := writeVarint(nameLen[:], len(n))
|
||||
tagLenLen := writeVarint(tagLen[:], len(tag))
|
||||
|
||||
var bits byte
|
||||
l := 1 + nameLenLen + len(n)
|
||||
if exported {
|
||||
bits |= 1 << 0
|
||||
}
|
||||
if len(tag) > 0 {
|
||||
l += tagLenLen + len(tag)
|
||||
bits |= 1 << 1
|
||||
}
|
||||
if embedded {
|
||||
bits |= 1 << 3
|
||||
}
|
||||
|
||||
b := make([]byte, l)
|
||||
b[0] = bits
|
||||
copy(b[1:], nameLen[:nameLenLen])
|
||||
copy(b[1+nameLenLen:], n)
|
||||
if len(tag) > 0 {
|
||||
tb := b[1+nameLenLen+len(n):]
|
||||
copy(tb, tagLen[:tagLenLen])
|
||||
copy(tb[tagLenLen:], tag)
|
||||
}
|
||||
|
||||
return Name{Bytes: &b[0]}
|
||||
}
|
||||
|
||||
const (
|
||||
TraceArgsLimit = 10 // print no more than 10 args/components
|
||||
TraceArgsMaxDepth = 5 // no more than 5 layers of nesting
|
||||
|
||||
// maxLen is a (conservative) upper bound of the byte stream length. For
|
||||
// each arg/component, it has no more than 2 bytes of data (size, offset),
|
||||
// and no more than one {, }, ... at each level (it cannot have both the
|
||||
// data and ... unless it is the last one, just be conservative). Plus 1
|
||||
// for _endSeq.
|
||||
TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
|
||||
)
|
||||
|
||||
// Populate the data.
|
||||
// The data is a stream of bytes, which contains the offsets and sizes of the
|
||||
// non-aggregate arguments or non-aggregate fields/elements of aggregate-typed
|
||||
// arguments, along with special "operators". Specifically,
|
||||
// - for each non-aggregate arg/field/element, its offset from FP (1 byte) and
|
||||
// size (1 byte)
|
||||
// - special operators:
|
||||
// - 0xff - end of sequence
|
||||
// - 0xfe - print { (at the start of an aggregate-typed argument)
|
||||
// - 0xfd - print } (at the end of an aggregate-typed argument)
|
||||
// - 0xfc - print ... (more args/fields/elements)
|
||||
// - 0xfb - print _ (offset too large)
|
||||
const (
|
||||
TraceArgsEndSeq = 0xff
|
||||
TraceArgsStartAgg = 0xfe
|
||||
TraceArgsEndAgg = 0xfd
|
||||
TraceArgsDotdotdot = 0xfc
|
||||
TraceArgsOffsetTooLarge = 0xfb
|
||||
TraceArgsSpecial = 0xf0 // above this are operators, below this are ordinary offsets
|
||||
)
|
||||
|
||||
// MaxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
|
||||
// which holds 1-bit entries describing where pointers are in a given type.
|
||||
// Above this length, the GC information is recorded as a GC program,
|
||||
// which can express repetition compactly. In either form, the
|
||||
// information is used by the runtime to initialize the heap bitmap,
|
||||
// and for large types (like 128 or more words), they are roughly the
|
||||
// same speed. GC programs are never much larger and often more
|
||||
// compact. (If large arrays are involved, they can be arbitrarily
|
||||
// more compact.)
|
||||
//
|
||||
// The cutoff must be large enough that any allocation large enough to
|
||||
// use a GC program is large enough that it does not share heap bitmap
|
||||
// bytes with any other objects, allowing the GC program execution to
|
||||
// assume an aligned start and not use atomic operations. In the current
|
||||
// runtime, this means all malloc size classes larger than the cutoff must
|
||||
// be multiples of four words. On 32-bit systems that's 16 bytes, and
|
||||
// all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
|
||||
// On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
|
||||
// for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
|
||||
// is 32 pointers, the bits for which fit in 4 bytes. So MaxPtrmaskBytes
|
||||
// must be >= 4.
|
||||
//
|
||||
// We used to use 16 because the GC programs do have some constant overhead
|
||||
// to get started, and processing 128 pointers seems to be enough to
|
||||
// amortize that overhead well.
|
||||
//
|
||||
// To make sure that the runtime's chansend can call typeBitsBulkBarrier,
|
||||
// we raised the limit to 2048, so that even 32-bit systems are guaranteed to
|
||||
// use bitmaps for objects up to 64 kB in size.
|
||||
const MaxPtrmaskBytes = 2048
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var goarches []string
|
||||
|
||||
func main() {
|
||||
data, err := os.ReadFile("../../internal/syslist/syslist.go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
const goarchPrefix = `var KnownArch = map[string]bool{`
|
||||
inGOARCH := false
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.HasPrefix(line, goarchPrefix) {
|
||||
inGOARCH = true
|
||||
} else if inGOARCH && strings.HasPrefix(line, "}") {
|
||||
break
|
||||
} else if inGOARCH {
|
||||
goarch := strings.Fields(line)[0]
|
||||
goarch = strings.TrimPrefix(goarch, `"`)
|
||||
goarch = strings.TrimSuffix(goarch, `":`)
|
||||
goarches = append(goarches, goarch)
|
||||
}
|
||||
}
|
||||
|
||||
for _, target := range goarches {
|
||||
if target == "amd64p32" {
|
||||
continue
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.\n\n")
|
||||
fmt.Fprintf(&buf, "//go:build %s\n\n", target) // must explicitly include target for bootstrapping purposes
|
||||
fmt.Fprintf(&buf, "package goarch\n\n")
|
||||
fmt.Fprintf(&buf, "const GOARCH = `%s`\n\n", target)
|
||||
for _, goarch := range goarches {
|
||||
value := 0
|
||||
if goarch == target {
|
||||
value = 1
|
||||
}
|
||||
fmt.Fprintf(&buf, "const Is%s = %d\n", strings.Title(goarch), value)
|
||||
}
|
||||
err := os.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// package goarch contains GOARCH-specific constants.
|
||||
package goarch
|
||||
|
||||
// The next line makes 'go generate' write the zgoarch*.go files with
|
||||
// per-arch information, including constants named $GOARCH for every
|
||||
// GOARCH. The constant is 1 on the current system, 0 otherwise; multiplying
|
||||
// by them is useful for defining GOARCH-specific constants.
|
||||
//
|
||||
//go:generate go run gengoarch.go
|
||||
|
||||
// ArchFamilyType represents a family of one or more related architectures.
|
||||
// For example, ppc64 and ppc64le are both members of the PPC64 family.
|
||||
type ArchFamilyType int
|
||||
|
||||
const (
|
||||
AMD64 ArchFamilyType = iota
|
||||
ARM
|
||||
ARM64
|
||||
I386
|
||||
LOONG64
|
||||
MIPS
|
||||
MIPS64
|
||||
PPC64
|
||||
RISCV64
|
||||
S390X
|
||||
WASM
|
||||
)
|
||||
|
||||
// PtrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant.
|
||||
// It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit).
|
||||
const PtrSize = 4 << (^uintptr(0) >> 63)
|
||||
|
||||
// ArchFamily is the architecture family (AMD64, ARM, ...)
|
||||
const ArchFamily ArchFamilyType = _ArchFamily
|
||||
|
||||
// BigEndian reports whether the architecture is big-endian.
|
||||
const BigEndian = IsArmbe|IsArm64be|IsMips|IsMips64|IsPpc|IsPpc64|IsS390|IsS390x|IsSparc|IsSparc64 == 1
|
||||
|
||||
// DefaultPhysPageSize is the default physical page size.
|
||||
const DefaultPhysPageSize = _DefaultPhysPageSize
|
||||
|
||||
// PCQuantum is the minimal unit for a program counter (1 on x86, 4 on most other systems).
|
||||
// The various PC tables record PC deltas pre-divided by PCQuantum.
|
||||
const PCQuantum = _PCQuantum
|
||||
|
||||
// Int64Align is the required alignment for a 64-bit integer (4 on 32-bit systems, 8 on 64-bit).
|
||||
const Int64Align = PtrSize
|
||||
|
||||
// MinFrameSize is the size of the system-reserved words at the bottom
|
||||
// of a frame (just above the architectural stack pointer).
|
||||
// It is zero on x86 and PtrSize on most non-x86 (LR-based) systems.
|
||||
// On PowerPC it is larger, to cover three more reserved words:
|
||||
// the compiler word, the link editor word, and the TOC save word.
|
||||
const MinFrameSize = _MinFrameSize
|
||||
|
||||
// StackAlign is the required alignment of the SP register.
|
||||
// The stack must be at least word aligned, but some architectures require more.
|
||||
const StackAlign = _StackAlign
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = I386
|
||||
_DefaultPhysPageSize = 4096
|
||||
_PCQuantum = 1
|
||||
_MinFrameSize = 0
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = AMD64
|
||||
_DefaultPhysPageSize = 4096
|
||||
_PCQuantum = 1
|
||||
_MinFrameSize = 0
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = ARM
|
||||
_DefaultPhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 4
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = ARM64
|
||||
_DefaultPhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 8
|
||||
_StackAlign = 16
|
||||
)
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build loong64
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = LOONG64
|
||||
_DefaultPhysPageSize = 16384
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 8
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = MIPS
|
||||
_DefaultPhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 4
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = MIPS64
|
||||
_DefaultPhysPageSize = 16384
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 8
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = MIPS64
|
||||
_DefaultPhysPageSize = 16384
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 8
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = MIPS
|
||||
_DefaultPhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 4
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = PPC64
|
||||
_DefaultPhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 32
|
||||
_StackAlign = 16
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = PPC64
|
||||
_DefaultPhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 32
|
||||
_StackAlign = 16
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = RISCV64
|
||||
_DefaultPhysPageSize = 4096
|
||||
_PCQuantum = 4
|
||||
_MinFrameSize = 8
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = S390X
|
||||
_DefaultPhysPageSize = 4096
|
||||
_PCQuantum = 2
|
||||
_MinFrameSize = 8
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goarch
|
||||
|
||||
const (
|
||||
_ArchFamily = WASM
|
||||
_DefaultPhysPageSize = 65536
|
||||
_PCQuantum = 1
|
||||
_MinFrameSize = 0
|
||||
_StackAlign = PtrSize
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build 386
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `386`
|
||||
|
||||
const Is386 = 1
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build amd64
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `amd64`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 1
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build arm
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `arm`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 1
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build arm64
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `arm64`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 1
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build arm64be
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `arm64be`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 1
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build armbe
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `armbe`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 1
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build loong64
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `loong64`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 1
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build mips
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `mips`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 1
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build mips64
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `mips64`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 1
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build mips64le
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `mips64le`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 1
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build mips64p32
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `mips64p32`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 1
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build mips64p32le
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `mips64p32le`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 1
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build mipsle
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `mipsle`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 1
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build ppc
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `ppc`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 1
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build ppc64
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `ppc64`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 1
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build ppc64le
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `ppc64le`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 1
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build riscv
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `riscv`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 1
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build riscv64
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `riscv64`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 1
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build s390
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `s390`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 1
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build s390x
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `s390x`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 1
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build sparc
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `sparc`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 1
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build sparc64
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `sparc64`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 1
|
||||
const IsWasm = 0
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build wasm
|
||||
|
||||
package goarch
|
||||
|
||||
const GOARCH = `wasm`
|
||||
|
||||
const Is386 = 0
|
||||
const IsAmd64 = 0
|
||||
const IsAmd64p32 = 0
|
||||
const IsArm = 0
|
||||
const IsArmbe = 0
|
||||
const IsArm64 = 0
|
||||
const IsArm64be = 0
|
||||
const IsLoong64 = 0
|
||||
const IsMips = 0
|
||||
const IsMipsle = 0
|
||||
const IsMips64 = 0
|
||||
const IsMips64le = 0
|
||||
const IsMips64p32 = 0
|
||||
const IsMips64p32le = 0
|
||||
const IsPpc = 0
|
||||
const IsPpc64 = 0
|
||||
const IsPpc64le = 0
|
||||
const IsRiscv = 0
|
||||
const IsRiscv64 = 0
|
||||
const IsS390 = 0
|
||||
const IsS390x = 0
|
||||
const IsSparc = 0
|
||||
const IsSparc64 = 0
|
||||
const IsWasm = 1
|
|
@ -0,0 +1,471 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package iter provides basic definitions and operations related to
|
||||
iterators over sequences.
|
||||
|
||||
# Iterators
|
||||
|
||||
An iterator is a function that passes successive elements of a
|
||||
sequence to a callback function, conventionally named yield.
|
||||
The function stops either when the sequence is finished or
|
||||
when yield returns false, indicating to stop the iteration early.
|
||||
This package defines [Seq] and [Seq2]
|
||||
(pronounced like seek—the first syllable of sequence)
|
||||
as shorthands for iterators that pass 1 or 2 values per sequence element
|
||||
to yield:
|
||||
|
||||
type (
|
||||
Seq[V any] func(yield func(V) bool)
|
||||
Seq2[K, V any] func(yield func(K, V) bool)
|
||||
)
|
||||
|
||||
Seq2 represents a sequence of paired values, conventionally key-value
|
||||
or index-value pairs.
|
||||
|
||||
Yield returns true if the iterator should continue with the next
|
||||
element in the sequence, false if it should stop.
|
||||
|
||||
For instance, [maps.Keys] returns an iterator that produces the sequence
|
||||
of keys of the map m, implemented as follows:
|
||||
|
||||
func Keys[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[K] {
|
||||
return func(yield func(K) bool) {
|
||||
for k := range m {
|
||||
if !yield(k) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Further examples can be found in [The Go Blog: Range Over Function Types].
|
||||
|
||||
Iterator functions are most often called by a [range loop], as in:
|
||||
|
||||
func PrintAll[V any](seq iter.Seq[V]) {
|
||||
for v := range seq {
|
||||
fmt.Println(v)
|
||||
}
|
||||
}
|
||||
|
||||
# Naming Conventions
|
||||
|
||||
Iterator functions and methods are named for the sequence being walked:
|
||||
|
||||
// All returns an iterator over all elements in s.
|
||||
func (s *Set[V]) All() iter.Seq[V]
|
||||
|
||||
The iterator method on a collection type is conventionally named All,
|
||||
because it iterates a sequence of all the values in the collection.
|
||||
|
||||
For a type containing multiple possible sequences, the iterator's name
|
||||
can indicate which sequence is being provided:
|
||||
|
||||
// Cities returns an iterator over the major cities in the country.
|
||||
func (c *Country) Cities() iter.Seq[*City]
|
||||
|
||||
// Languages returns an iterator over the official spoken languages of the country.
|
||||
func (c *Country) Languages() iter.Seq[string]
|
||||
|
||||
If an iterator requires additional configuration, the constructor function
|
||||
can take additional configuration arguments:
|
||||
|
||||
// Scan returns an iterator over key-value pairs with min ≤ key ≤ max.
|
||||
func (m *Map[K, V]) Scan(min, max K) iter.Seq2[K, V]
|
||||
|
||||
// Split returns an iterator over the (possibly-empty) substrings of s
|
||||
// separated by sep.
|
||||
func Split(s, sep string) iter.Seq[string]
|
||||
|
||||
When there are multiple possible iteration orders, the method name may
|
||||
indicate that order:
|
||||
|
||||
// All returns an iterator over the list from head to tail.
|
||||
func (l *List[V]) All() iter.Seq[V]
|
||||
|
||||
// Backward returns an iterator over the list from tail to head.
|
||||
func (l *List[V]) Backward() iter.Seq[V]
|
||||
|
||||
// Preorder returns an iterator over all nodes of the syntax tree
|
||||
// beneath (and including) the specified root, in depth-first preorder,
|
||||
// visiting a parent node before its children.
|
||||
func Preorder(root Node) iter.Seq[Node]
|
||||
|
||||
# Single-Use Iterators
|
||||
|
||||
Most iterators provide the ability to walk an entire sequence:
|
||||
when called, the iterator does any setup necessary to start the
|
||||
sequence, then calls yield on successive elements of the sequence,
|
||||
and then cleans up before returning. Calling the iterator again
|
||||
walks the sequence again.
|
||||
|
||||
Some iterators break that convention, providing the ability to walk a
|
||||
sequence only once. These “single-use iterators” typically report values
|
||||
from a data stream that cannot be rewound to start over.
|
||||
Calling the iterator again after stopping early may continue the
|
||||
stream, but calling it again after the sequence is finished will yield
|
||||
no values at all. Doc comments for functions or methods that return
|
||||
single-use iterators should document this fact:
|
||||
|
||||
// Lines returns an iterator over lines read from r.
|
||||
// It returns a single-use iterator.
|
||||
func (r *Reader) Lines() iter.Seq[string]
|
||||
|
||||
# Pulling Values
|
||||
|
||||
Functions and methods that accept or return iterators
|
||||
should use the standard [Seq] or [Seq2] types, to ensure
|
||||
compatibility with range loops and other iterator adapters.
|
||||
The standard iterators can be thought of as “push iterators”, which
|
||||
push values to the yield function.
|
||||
|
||||
Sometimes a range loop is not the most natural way to consume values
|
||||
of the sequence. In this case, [Pull] converts a standard push iterator
|
||||
to a “pull iterator”, which can be called to pull one value at a time
|
||||
from the sequence. [Pull] starts an iterator and returns a pair
|
||||
of functions—next and stop—which return the next value from the iterator
|
||||
and stop it, respectively.
|
||||
|
||||
For example:
|
||||
|
||||
// Pairs returns an iterator over successive pairs of values from seq.
|
||||
func Pairs[V any](seq iter.Seq[V]) iter.Seq2[V, V] {
|
||||
return func(yield func(V, V) bool) {
|
||||
next, stop := iter.Pull(seq)
|
||||
defer stop()
|
||||
for {
|
||||
v1, ok1 := next()
|
||||
if !ok1 {
|
||||
return
|
||||
}
|
||||
v2, ok2 := next()
|
||||
// If ok2 is false, v2 should be the
|
||||
// zero value; yield one last pair.
|
||||
if !yield(v1, v2) {
|
||||
return
|
||||
}
|
||||
if !ok2 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
If clients do not consume the sequence to completion, they must call stop,
|
||||
which allows the iterator function to finish and return. As shown in
|
||||
the example, the conventional way to ensure this is to use defer.
|
||||
|
||||
# Standard Library Usage
|
||||
|
||||
A few packages in the standard library provide iterator-based APIs,
|
||||
most notably the [maps] and [slices] packages.
|
||||
For example, [maps.Keys] returns an iterator over the keys of a map,
|
||||
while [slices.Sorted] collects the values of an iterator into a slice,
|
||||
sorts them, and returns the slice, so to iterate over the sorted keys of a map:
|
||||
|
||||
for _, key := range slices.Sorted(maps.Keys(m)) {
|
||||
...
|
||||
}
|
||||
|
||||
# Mutation
|
||||
|
||||
Iterators provide only the values of the sequence, not any direct way
|
||||
to modify it. If an iterator wishes to provide a mechanism for modifying
|
||||
a sequence during iteration, the usual approach is to define a position type
|
||||
with the extra operations and then provide an iterator over positions.
|
||||
|
||||
For example, a tree implementation might provide:
|
||||
|
||||
// Positions returns an iterator over positions in the sequence.
|
||||
func (t *Tree[V]) Positions() iter.Seq[*Pos]
|
||||
|
||||
// A Pos represents a position in the sequence.
|
||||
// It is only valid during the yield call it is passed to.
|
||||
type Pos[V any] struct { ... }
|
||||
|
||||
// Pos returns the value at the cursor.
|
||||
func (p *Pos[V]) Value() V
|
||||
|
||||
// Delete deletes the value at this point in the iteration.
|
||||
func (p *Pos[V]) Delete()
|
||||
|
||||
// Set changes the value v at the cursor.
|
||||
func (p *Pos[V]) Set(v V)
|
||||
|
||||
And then a client could delete boring values from the tree using:
|
||||
|
||||
for p := range t.Positions() {
|
||||
if boring(p.Value()) {
|
||||
p.Delete()
|
||||
}
|
||||
}
|
||||
|
||||
[The Go Blog: Range Over Function Types]: https://go.dev/blog/range-functions
|
||||
[range loop]: https://go.dev/ref/spec#For_range
|
||||
*/
|
||||
package iter
|
||||
|
||||
import (
|
||||
"internal/race"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Seq is an iterator over sequences of individual values.
|
||||
// When called as seq(yield), seq calls yield(v) for each value v in the sequence,
|
||||
// stopping early if yield returns false.
|
||||
// See the [iter] package documentation for more details.
|
||||
type Seq[V any] func(yield func(V) bool)
|
||||
|
||||
// Seq2 is an iterator over sequences of pairs of values, most commonly key-value pairs.
|
||||
// When called as seq(yield), seq calls yield(k, v) for each pair (k, v) in the sequence,
|
||||
// stopping early if yield returns false.
|
||||
// See the [iter] package documentation for more details.
|
||||
type Seq2[K, V any] func(yield func(K, V) bool)
|
||||
|
||||
type coro struct{}
|
||||
|
||||
//go:linkname newcoro runtime.newcoro
|
||||
func newcoro(func(*coro)) *coro
|
||||
|
||||
//go:linkname coroswitch runtime.coroswitch
|
||||
func coroswitch(*coro)
|
||||
|
||||
// Pull converts the “push-style” iterator sequence seq
|
||||
// into a “pull-style” iterator accessed by the two functions
|
||||
// next and stop.
|
||||
//
|
||||
// Next returns the next value in the sequence
|
||||
// and a boolean indicating whether the value is valid.
|
||||
// When the sequence is over, next returns the zero V and false.
|
||||
// It is valid to call next after reaching the end of the sequence
|
||||
// or after calling stop. These calls will continue
|
||||
// to return the zero V and false.
|
||||
//
|
||||
// Stop ends the iteration. It must be called when the caller is
|
||||
// no longer interested in next values and next has not yet
|
||||
// signaled that the sequence is over (with a false boolean return).
|
||||
// It is valid to call stop multiple times and when next has
|
||||
// already returned false. Typically, callers should “defer stop()”.
|
||||
//
|
||||
// It is an error to call next or stop from multiple goroutines
|
||||
// simultaneously.
|
||||
//
|
||||
// If the iterator panics during a call to next (or stop),
|
||||
// then next (or stop) itself panics with the same value.
|
||||
func Pull[V any](seq Seq[V]) (next func() (V, bool), stop func()) {
|
||||
var (
|
||||
v V
|
||||
ok bool
|
||||
done bool
|
||||
yieldNext bool
|
||||
racer int
|
||||
panicValue any
|
||||
seqDone bool // to detect Goexit
|
||||
)
|
||||
c := newcoro(func(c *coro) {
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
if done {
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
return
|
||||
}
|
||||
yield := func(v1 V) bool {
|
||||
if done {
|
||||
return false
|
||||
}
|
||||
if !yieldNext {
|
||||
panic("iter.Pull: yield called again before next")
|
||||
}
|
||||
yieldNext = false
|
||||
v, ok = v1, true
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
coroswitch(c)
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
return !done
|
||||
}
|
||||
// Recover and propagate panics from seq.
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
panicValue = p
|
||||
} else if !seqDone {
|
||||
panicValue = goexitPanicValue
|
||||
}
|
||||
done = true // Invalidate iterator
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
}()
|
||||
seq(yield)
|
||||
var v0 V
|
||||
v, ok = v0, false
|
||||
seqDone = true
|
||||
})
|
||||
next = func() (v1 V, ok1 bool) {
|
||||
race.Write(unsafe.Pointer(&racer)) // detect races
|
||||
|
||||
if done {
|
||||
return
|
||||
}
|
||||
if yieldNext {
|
||||
panic("iter.Pull: next called again before yield")
|
||||
}
|
||||
yieldNext = true
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
coroswitch(c)
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
|
||||
// Propagate panics and goexits from seq.
|
||||
if panicValue != nil {
|
||||
if panicValue == goexitPanicValue {
|
||||
// Propagate runtime.Goexit from seq.
|
||||
runtime.Goexit()
|
||||
} else {
|
||||
panic(panicValue)
|
||||
}
|
||||
}
|
||||
return v, ok
|
||||
}
|
||||
stop = func() {
|
||||
race.Write(unsafe.Pointer(&racer)) // detect races
|
||||
|
||||
if !done {
|
||||
done = true
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
coroswitch(c)
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
|
||||
// Propagate panics and goexits from seq.
|
||||
if panicValue != nil {
|
||||
if panicValue == goexitPanicValue {
|
||||
// Propagate runtime.Goexit from seq.
|
||||
runtime.Goexit()
|
||||
} else {
|
||||
panic(panicValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return next, stop
|
||||
}
|
||||
|
||||
// Pull2 converts the “push-style” iterator sequence seq
|
||||
// into a “pull-style” iterator accessed by the two functions
|
||||
// next and stop.
|
||||
//
|
||||
// Next returns the next pair in the sequence
|
||||
// and a boolean indicating whether the pair is valid.
|
||||
// When the sequence is over, next returns a pair of zero values and false.
|
||||
// It is valid to call next after reaching the end of the sequence
|
||||
// or after calling stop. These calls will continue
|
||||
// to return a pair of zero values and false.
|
||||
//
|
||||
// Stop ends the iteration. It must be called when the caller is
|
||||
// no longer interested in next values and next has not yet
|
||||
// signaled that the sequence is over (with a false boolean return).
|
||||
// It is valid to call stop multiple times and when next has
|
||||
// already returned false. Typically, callers should “defer stop()”.
|
||||
//
|
||||
// It is an error to call next or stop from multiple goroutines
|
||||
// simultaneously.
|
||||
//
|
||||
// If the iterator panics during a call to next (or stop),
|
||||
// then next (or stop) itself panics with the same value.
|
||||
func Pull2[K, V any](seq Seq2[K, V]) (next func() (K, V, bool), stop func()) {
|
||||
var (
|
||||
k K
|
||||
v V
|
||||
ok bool
|
||||
done bool
|
||||
yieldNext bool
|
||||
racer int
|
||||
panicValue any
|
||||
seqDone bool
|
||||
)
|
||||
c := newcoro(func(c *coro) {
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
if done {
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
return
|
||||
}
|
||||
yield := func(k1 K, v1 V) bool {
|
||||
if done {
|
||||
return false
|
||||
}
|
||||
if !yieldNext {
|
||||
panic("iter.Pull2: yield called again before next")
|
||||
}
|
||||
yieldNext = false
|
||||
k, v, ok = k1, v1, true
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
coroswitch(c)
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
return !done
|
||||
}
|
||||
// Recover and propagate panics from seq.
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
panicValue = p
|
||||
} else if !seqDone {
|
||||
panicValue = goexitPanicValue
|
||||
}
|
||||
done = true // Invalidate iterator.
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
}()
|
||||
seq(yield)
|
||||
var k0 K
|
||||
var v0 V
|
||||
k, v, ok = k0, v0, false
|
||||
seqDone = true
|
||||
})
|
||||
next = func() (k1 K, v1 V, ok1 bool) {
|
||||
race.Write(unsafe.Pointer(&racer)) // detect races
|
||||
|
||||
if done {
|
||||
return
|
||||
}
|
||||
if yieldNext {
|
||||
panic("iter.Pull2: next called again before yield")
|
||||
}
|
||||
yieldNext = true
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
coroswitch(c)
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
|
||||
// Propagate panics and goexits from seq.
|
||||
if panicValue != nil {
|
||||
if panicValue == goexitPanicValue {
|
||||
// Propagate runtime.Goexit from seq.
|
||||
runtime.Goexit()
|
||||
} else {
|
||||
panic(panicValue)
|
||||
}
|
||||
}
|
||||
return k, v, ok
|
||||
}
|
||||
stop = func() {
|
||||
race.Write(unsafe.Pointer(&racer)) // detect races
|
||||
|
||||
if !done {
|
||||
done = true
|
||||
race.Release(unsafe.Pointer(&racer))
|
||||
coroswitch(c)
|
||||
race.Acquire(unsafe.Pointer(&racer))
|
||||
|
||||
// Propagate panics and goexits from seq.
|
||||
if panicValue != nil {
|
||||
if panicValue == goexitPanicValue {
|
||||
// Propagate runtime.Goexit from seq.
|
||||
runtime.Goexit()
|
||||
} else {
|
||||
panic(panicValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return next, stop
|
||||
}
|
||||
|
||||
// goexitPanicValue is a sentinel value indicating that an iterator
|
||||
// exited via runtime.Goexit.
|
||||
var goexitPanicValue any = new(int)
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package race contains helper functions for manually instrumenting code for the race detector.
|
||||
|
||||
The runtime package intentionally exports these functions only in the race build;
|
||||
this package exports them unconditionally but without the "race" build tag they are no-ops.
|
||||
*/
|
||||
package race
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !race
|
||||
|
||||
package race
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const Enabled = false
|
||||
|
||||
func Acquire(addr unsafe.Pointer) {
|
||||
}
|
||||
|
||||
func Release(addr unsafe.Pointer) {
|
||||
}
|
||||
|
||||
func ReleaseMerge(addr unsafe.Pointer) {
|
||||
}
|
||||
|
||||
func Disable() {
|
||||
}
|
||||
|
||||
func Enable() {
|
||||
}
|
||||
|
||||
func Read(addr unsafe.Pointer) {
|
||||
}
|
||||
|
||||
func ReadPC(addr unsafe.Pointer, callerpc, pc uintptr) {
|
||||
}
|
||||
|
||||
//func ReadObjectPC(t *abi.Type, addr unsafe.Pointer, callerpc, pc uintptr) {
|
||||
//}
|
||||
|
||||
func Write(addr unsafe.Pointer) {
|
||||
}
|
||||
|
||||
func WritePC(addr unsafe.Pointer, callerpc, pc uintptr) {
|
||||
}
|
||||
|
||||
//func WriteObjectPC(t *abi.Type, addr unsafe.Pointer, callerpc, pc uintptr) {
|
||||
//}
|
||||
|
||||
func ReadRange(addr unsafe.Pointer, len int) {
|
||||
}
|
||||
|
||||
func WriteRange(addr unsafe.Pointer, len int) {
|
||||
}
|
||||
|
||||
func Errors() int { return 0 }
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build race
|
||||
|
||||
package race
|
||||
|
||||
import (
|
||||
"internal/abi"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const Enabled = true
|
||||
|
||||
// Functions below pushed from runtime.
|
||||
|
||||
//go:linkname Acquire
|
||||
func Acquire(addr unsafe.Pointer)
|
||||
|
||||
//go:linkname Release
|
||||
func Release(addr unsafe.Pointer)
|
||||
|
||||
//go:linkname ReleaseMerge
|
||||
func ReleaseMerge(addr unsafe.Pointer)
|
||||
|
||||
//go:linkname Disable
|
||||
func Disable()
|
||||
|
||||
//go:linkname Enable
|
||||
func Enable()
|
||||
|
||||
//go:linkname Read
|
||||
func Read(addr unsafe.Pointer)
|
||||
|
||||
//go:linkname ReadPC
|
||||
func ReadPC(addr unsafe.Pointer, callerpc, pc uintptr)
|
||||
|
||||
//go:linkname ReadObjectPC
|
||||
func ReadObjectPC(t *abi.Type, addr unsafe.Pointer, callerpc, pc uintptr)
|
||||
|
||||
//go:linkname Write
|
||||
func Write(addr unsafe.Pointer)
|
||||
|
||||
//go:linkname WritePC
|
||||
func WritePC(addr unsafe.Pointer, callerpc, pc uintptr)
|
||||
|
||||
//go:linkname WriteObjectPC
|
||||
func WriteObjectPC(t *abi.Type, addr unsafe.Pointer, callerpc, pc uintptr)
|
||||
|
||||
//go:linkname ReadRange
|
||||
func ReadRange(addr unsafe.Pointer, len int)
|
||||
|
||||
//go:linkname WriteRange
|
||||
func WriteRange(addr unsafe.Pointer, len int)
|
||||
|
||||
//go:linkname Errors
|
||||
func Errors() int
|
Loading…
Reference in New Issue