// 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 runtime

import (
	
	
	
	
	
)

// throwType indicates the current type of ongoing throw, which affects the
// amount of detail printed to stderr. Higher values include more detail.
type throwType uint32

const (
	// throwTypeNone means that we are not throwing.
	throwTypeNone throwType = iota

	// throwTypeUser is a throw due to a problem with the application.
	//
	// These throws do not include runtime frames, system goroutines, or
	// frame metadata.
	throwTypeUser

	// throwTypeRuntime is a throw due to a problem with Go itself.
	//
	// These throws include as much information as possible to aid in
	// debugging the runtime, including runtime frames, system goroutines,
	// and frame metadata.
	throwTypeRuntime
)

// We have two different ways of doing defers. The older way involves creating a
// defer record at the time that a defer statement is executing and adding it to a
// defer chain. This chain is inspected by the deferreturn call at all function
// exits in order to run the appropriate defer calls. A cheaper way (which we call
// open-coded defers) is used for functions in which no defer statements occur in
// loops. In that case, we simply store the defer function/arg information into
// specific stack slots at the point of each defer statement, as well as setting a
// bit in a bitmask. At each function exit, we add inline code to directly make
// the appropriate defer calls based on the bitmask and fn/arg information stored
// on the stack. During panic/Goexit processing, the appropriate defer calls are
// made using extra funcdata info that indicates the exact stack slots that
// contain the bitmask and defer fn/args.

// Check to make sure we can really generate a panic. If the panic
// was generated from the runtime, or from inside malloc, then convert
// to a throw of msg.
// pc should be the program counter of the compiler-generated code that
// triggered this panic.
func panicCheck1( uintptr,  string) {
	if goarch.IsWasm == 0 && hasPrefix(funcname(findfunc()), "runtime.") {
		// Note: wasm can't tail call, so we can't get the original caller's pc.
		throw()
	}
	// TODO: is this redundant? How could we be in malloc
	// but not in the runtime? runtime/internal/*, maybe?
	 := getg()
	if  != nil && .m != nil && .m.mallocing != 0 {
		throw()
	}
}

// Same as above, but calling from the runtime is allowed.
//
// Using this function is necessary for any panic that may be
// generated by runtime.sigpanic, since those are always called by the
// runtime.
func panicCheck2( string) {
	// panic allocates, so to avoid recursive malloc, turn panics
	// during malloc into throws.
	 := getg()
	if  != nil && .m != nil && .m.mallocing != 0 {
		throw()
	}
}

// Many of the following panic entry-points turn into throws when they
// happen in various runtime contexts. These should never happen in
// the runtime, and if they do, they indicate a serious issue and
// should not be caught by user code.
//
// The panic{Index,Slice,divide,shift} functions are called by
// code generated by the compiler for out of bounds index expressions,
// out of bounds slice expressions, division by zero, and shift by negative.
// The panicdivide (again), panicoverflow, panicfloat, and panicmem
// functions are called by the signal handler when a signal occurs
// indicating the respective problem.
//
// Since panic{Index,Slice,shift} are never called directly, and
// since the runtime package should never have an out of bounds slice
// or array reference or negative shift, if we see those functions called from the
// runtime package we turn the panic into a throw. That will dump the
// entire runtime stack for easier debugging.
//
// The entry points called by the signal handler will be called from
// runtime.sigpanic, so we can't disallow calls from the runtime to
// these (they always look like they're called from the runtime).
// Hence, for these, we just check for clearly bad runtime conditions.
//
// The panic{Index,Slice} functions are implemented in assembly and tail call
// to the goPanic{Index,Slice} functions below. This is done so we can use
// a space-minimal register calling convention.

// failures in the comparisons for s[x], 0 <= x < y (y == len(s))
//
//go:yeswritebarrierrec
func goPanicIndex( int,  int) {
	panicCheck1(getcallerpc(), "index out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsIndex})
}

//go:yeswritebarrierrec
func goPanicIndexU( uint,  int) {
	panicCheck1(getcallerpc(), "index out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsIndex})
}

// failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
//
//go:yeswritebarrierrec
func goPanicSliceAlen( int,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsSliceAlen})
}

//go:yeswritebarrierrec
func goPanicSliceAlenU( uint,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsSliceAlen})
}

//go:yeswritebarrierrec
func goPanicSliceAcap( int,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsSliceAcap})
}

//go:yeswritebarrierrec
func goPanicSliceAcapU( uint,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsSliceAcap})
}

// failures in the comparisons for s[x:y], 0 <= x <= y
//
//go:yeswritebarrierrec
func goPanicSliceB( int,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsSliceB})
}

//go:yeswritebarrierrec
func goPanicSliceBU( uint,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsSliceB})
}

// failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicSlice3Alen( int,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsSlice3Alen})
}
func goPanicSlice3AlenU( uint,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsSlice3Alen})
}
func goPanicSlice3Acap( int,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsSlice3Acap})
}
func goPanicSlice3AcapU( uint,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsSlice3Acap})
}

// failures in the comparisons for s[:x:y], 0 <= x <= y
func goPanicSlice3B( int,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsSlice3B})
}
func goPanicSlice3BU( uint,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsSlice3B})
}

// failures in the comparisons for s[x:y:], 0 <= x <= y
func goPanicSlice3C( int,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsSlice3C})
}
func goPanicSlice3CU( uint,  int) {
	panicCheck1(getcallerpc(), "slice bounds out of range")
	panic(boundsError{x: int64(), signed: false, y: , code: boundsSlice3C})
}

// failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s)
func goPanicSliceConvert( int,  int) {
	panicCheck1(getcallerpc(), "slice length too short to convert to array or pointer to array")
	panic(boundsError{x: int64(), signed: true, y: , code: boundsConvert})
}

// Implemented in assembly, as they take arguments in registers.
// Declared here to mark them as ABIInternal.
func panicIndex( int,  int)
func panicIndexU( uint,  int)
func panicSliceAlen( int,  int)
func panicSliceAlenU( uint,  int)
func panicSliceAcap( int,  int)
func panicSliceAcapU( uint,  int)
func panicSliceB( int,  int)
func panicSliceBU( uint,  int)
func panicSlice3Alen( int,  int)
func panicSlice3AlenU( uint,  int)
func panicSlice3Acap( int,  int)
func panicSlice3AcapU( uint,  int)
func panicSlice3B( int,  int)
func panicSlice3BU( uint,  int)
func panicSlice3C( int,  int)
func panicSlice3CU( uint,  int)
func panicSliceConvert( int,  int)

var shiftError = error(errorString("negative shift amount"))

//go:yeswritebarrierrec
func panicshift() {
	panicCheck1(getcallerpc(), "negative shift amount")
	panic(shiftError)
}

var divideError = error(errorString("integer divide by zero"))

//go:yeswritebarrierrec
func panicdivide() {
	panicCheck2("integer divide by zero")
	panic(divideError)
}

var overflowError = error(errorString("integer overflow"))

func panicoverflow() {
	panicCheck2("integer overflow")
	panic(overflowError)
}

var floatError = error(errorString("floating point error"))

func panicfloat() {
	panicCheck2("floating point error")
	panic(floatError)
}

var memoryError = error(errorString("invalid memory address or nil pointer dereference"))

func panicmem() {
	panicCheck2("invalid memory address or nil pointer dereference")
	panic(memoryError)
}

func panicmemAddr( uintptr) {
	panicCheck2("invalid memory address or nil pointer dereference")
	panic(errorAddressString{msg: "invalid memory address or nil pointer dereference", addr: })
}

// Create a new deferred function fn, which has no arguments and results.
// The compiler turns a defer statement into a call to this.
func deferproc( func()) {
	 := getg()
	if .m.curg !=  {
		// go code on the system stack can't defer
		throw("defer on system stack")
	}

	 := newdefer()
	if ._panic != nil {
		throw("deferproc: d.panic != nil after newdefer")
	}
	.link = ._defer
	._defer = 
	.fn = 
	.pc = getcallerpc()
	// We must not be preempted between calling getcallersp and
	// storing it to d.sp because getcallersp's result is a
	// uintptr stack pointer.
	.sp = getcallersp()

	// deferproc returns 0 normally.
	// a deferred func that stops a panic
	// makes the deferproc return 1.
	// the code the compiler generates always
	// checks the return value and jumps to the
	// end of the function if deferproc returns != 0.
	return0()
	// No code can go here - the C return register has
	// been set and must not be clobbered.
}

// deferprocStack queues a new deferred function with a defer record on the stack.
// The defer record must have its fn field initialized.
// All other fields can contain junk.
// Nosplit because of the uninitialized pointer fields on the stack.
//
//go:nosplit
func deferprocStack( *_defer) {
	 := getg()
	if .m.curg !=  {
		// go code on the system stack can't defer
		throw("defer on system stack")
	}
	// fn is already set.
	// The other fields are junk on entry to deferprocStack and
	// are initialized here.
	.started = false
	.heap = false
	.openDefer = false
	.sp = getcallersp()
	.pc = getcallerpc()
	.framepc = 0
	.varp = 0
	// The lines below implement:
	//   d.panic = nil
	//   d.fd = nil
	//   d.link = gp._defer
	//   gp._defer = d
	// But without write barriers. The first three are writes to
	// the stack so they don't need a write barrier, and furthermore
	// are to uninitialized memory, so they must not use a write barrier.
	// The fourth write does not require a write barrier because we
	// explicitly mark all the defer structures, so we don't need to
	// keep track of pointers to them with a write barrier.
	*(*uintptr)(unsafe.Pointer(&._panic)) = 0
	*(*uintptr)(unsafe.Pointer(&.fd)) = 0
	*(*uintptr)(unsafe.Pointer(&.link)) = uintptr(unsafe.Pointer(._defer))
	*(*uintptr)(unsafe.Pointer(&._defer)) = uintptr(unsafe.Pointer())

	return0()
	// No code can go here - the C return register has
	// been set and must not be clobbered.
}

// Each P holds a pool for defers.

// Allocate a Defer, usually using per-P pool.
// Each defer must be released with freedefer.  The defer is not
// added to any defer chain yet.
func newdefer() *_defer {
	var  *_defer
	 := acquirem()
	 := .p.ptr()
	if len(.deferpool) == 0 && sched.deferpool != nil {
		lock(&sched.deferlock)
		for len(.deferpool) < cap(.deferpool)/2 && sched.deferpool != nil {
			 := sched.deferpool
			sched.deferpool = .link
			.link = nil
			.deferpool = append(.deferpool, )
		}
		unlock(&sched.deferlock)
	}
	if  := len(.deferpool);  > 0 {
		 = .deferpool[-1]
		.deferpool[-1] = nil
		.deferpool = .deferpool[:-1]
	}
	releasem()
	,  = nil, nil

	if  == nil {
		// Allocate new defer.
		 = new(_defer)
	}
	.heap = true
	return 
}

// Free the given defer.
// The defer cannot be used after this call.
//
// This is nosplit because the incoming defer is in a perilous state.
// It's not on any defer list, so stack copying won't adjust stack
// pointers in it (namely, d.link). Hence, if we were to copy the
// stack, d could then contain a stale pointer.
//
//go:nosplit
func freedefer( *_defer) {
	.link = nil
	// After this point we can copy the stack.

	if ._panic != nil {
		freedeferpanic()
	}
	if .fn != nil {
		freedeferfn()
	}
	if !.heap {
		return
	}

	 := acquirem()
	 := .p.ptr()
	if len(.deferpool) == cap(.deferpool) {
		// Transfer half of local cache to the central cache.
		var ,  *_defer
		for len(.deferpool) > cap(.deferpool)/2 {
			 := len(.deferpool)
			 := .deferpool[-1]
			.deferpool[-1] = nil
			.deferpool = .deferpool[:-1]
			if  == nil {
				 = 
			} else {
				.link = 
			}
			 = 
		}
		lock(&sched.deferlock)
		.link = sched.deferpool
		sched.deferpool = 
		unlock(&sched.deferlock)
	}

	* = _defer{}

	.deferpool = append(.deferpool, )

	releasem()
	,  = nil, nil
}

// Separate function so that it can split stack.
// Windows otherwise runs out of stack space.
func freedeferpanic() {
	// _panic must be cleared before d is unlinked from gp.
	throw("freedefer with d._panic != nil")
}

func freedeferfn() {
	// fn must be cleared before d is unlinked from gp.
	throw("freedefer with d.fn != nil")
}

// deferreturn runs deferred functions for the caller's frame.
// The compiler inserts a call to this at the end of any
// function which calls defer.
func deferreturn() {
	 := getg()
	for {
		 := ._defer
		if  == nil {
			return
		}
		 := getcallersp()
		if .sp !=  {
			return
		}
		if .openDefer {
			 := runOpenDeferFrame()
			if ! {
				throw("unfinished open-coded defers in deferreturn")
			}
			._defer = .link
			freedefer()
			// If this frame uses open defers, then this
			// must be the only defer record for the
			// frame, so we can just return.
			return
		}

		 := .fn
		.fn = nil
		._defer = .link
		freedefer()
		()
	}
}

// Goexit terminates the goroutine that calls it. No other goroutine is affected.
// Goexit runs all deferred calls before terminating the goroutine. Because Goexit
// is not a panic, any recover calls in those deferred functions will return nil.
//
// Calling Goexit from the main goroutine terminates that goroutine
// without func main returning. Since func main has not returned,
// the program continues execution of other goroutines.
// If all other goroutines exit, the program crashes.
func () {
	// Run all deferred functions for the current goroutine.
	// This code is similar to gopanic, see that implementation
	// for detailed comments.
	 := getg()

	// Create a panic object for Goexit, so we can recognize when it might be
	// bypassed by a recover().
	var  _panic
	.goexit = true
	.link = ._panic
	._panic = (*_panic)(noescape(unsafe.Pointer(&)))

	addOneOpenDeferFrame(, getcallerpc(), unsafe.Pointer(getcallersp()))
	for {
		 := ._defer
		if  == nil {
			break
		}
		if .started {
			if ._panic != nil {
				._panic.aborted = true
				._panic = nil
			}
			if !.openDefer {
				.fn = nil
				._defer = .link
				freedefer()
				continue
			}
		}
		.started = true
		._panic = (*_panic)(noescape(unsafe.Pointer(&)))
		if .openDefer {
			 := runOpenDeferFrame()
			if ! {
				// We should always run all defers in the frame,
				// since there is no panic associated with this
				// defer that can be recovered.
				throw("unfinished open-coded defers in Goexit")
			}
			if .aborted {
				// Since our current defer caused a panic and may
				// have been already freed, just restart scanning
				// for open-coded defers from this frame again.
				addOneOpenDeferFrame(, getcallerpc(), unsafe.Pointer(getcallersp()))
			} else {
				addOneOpenDeferFrame(, 0, nil)
			}
		} else {
			// Save the pc/sp in deferCallSave(), so we can "recover" back to this
			// loop if necessary.
			deferCallSave(&, .fn)
		}
		if .aborted {
			// We had a recursive panic in the defer d we started, and
			// then did a recover in a defer that was further down the
			// defer chain than d. In the case of an outstanding Goexit,
			// we force the recover to return back to this loop. d will
			// have already been freed if completed, so just continue
			// immediately to the next defer on the chain.
			.aborted = false
			continue
		}
		if ._defer !=  {
			throw("bad defer entry in Goexit")
		}
		._panic = nil
		.fn = nil
		._defer = .link
		freedefer()
		// Note: we ignore recovers here because Goexit isn't a panic
	}
	goexit1()
}

// Call all Error and String methods before freezing the world.
// Used when crashing with panicking.
func preprintpanics( *_panic) {
	defer func() {
		 := "panic while printing panic value"
		switch r := recover().(type) {
		case nil:
			// nothing to do
		case string:
			throw( + ": " + )
		default:
			throw( + ": type " + toRType(efaceOf(&)._type).string())
		}
	}()
	for  != nil {
		switch v := .arg.(type) {
		case error:
			.arg = .Error()
		case stringer:
			.arg = .String()
		}
		 = .link
	}
}

// Print all currently active panics. Used when crashing.
// Should only be called after preprintpanics.
func printpanics( *_panic) {
	if .link != nil {
		(.link)
		if !.link.goexit {
			print("\t")
		}
	}
	if .goexit {
		return
	}
	print("panic: ")
	printany(.arg)
	if .recovered {
		print(" [recovered]")
	}
	print("\n")
}

// addOneOpenDeferFrame scans the stack (in gentraceback order, from inner frames to
// outer frames) for the first frame (if any) with open-coded defers. If it finds
// one, it adds a single entry to the defer chain for that frame. The entry added
// represents all the defers in the associated open defer frame, and is sorted in
// order with respect to any non-open-coded defers.
//
// addOneOpenDeferFrame stops (possibly without adding a new entry) if it encounters
// an in-progress open defer entry. An in-progress open defer entry means there has
// been a new panic because of a defer in the associated frame. addOneOpenDeferFrame
// does not add an open defer entry past a started entry, because that started entry
// still needs to finished, and addOneOpenDeferFrame will be called when that started
// entry is completed. The defer removal loop in gopanic() similarly stops at an
// in-progress defer entry. Together, addOneOpenDeferFrame and the defer removal loop
// ensure the invariant that there is no open defer entry further up the stack than
// an in-progress defer, and also that the defer removal loop is guaranteed to remove
// all not-in-progress open defer entries from the defer chain.
//
// If sp is non-nil, addOneOpenDeferFrame starts the stack scan from the frame
// specified by sp. If sp is nil, it uses the sp from the current defer record (which
// has just been finished). Hence, it continues the stack scan from the frame of the
// defer that just finished. It skips any frame that already has a (not-in-progress)
// open-coded _defer record in the defer chain.
//
// Note: All entries of the defer chain (including this new open-coded entry) have
// their pointers (including sp) adjusted properly if the stack moves while
// running deferred functions. Also, it is safe to pass in the sp arg (which is
// the direct result of calling getcallersp()), because all pointer variables
// (including arguments) are adjusted as needed during stack copies.
func addOneOpenDeferFrame( *g,  uintptr,  unsafe.Pointer) {
	var  *_defer
	if  == nil {
		 = ._defer
		 = .framepc
		 = unsafe.Pointer(.sp)
	}
	systemstack(func() {
		var  unwinder
	:
		for .initAt(, uintptr(), 0, , 0); .valid(); .next() {
			 := &.frame
			if  != nil && .sp == .sp {
				// Skip the frame for the previous defer that
				// we just finished (and was used to set
				// where we restarted the stack scan)
				continue
			}
			 := .fn
			 := funcdata(, abi.FUNCDATA_OpenCodedDeferInfo)
			if  == nil {
				continue
			}
			// Insert the open defer record in the
			// chain, in order sorted by sp.
			 := ._defer
			var  *_defer
			for  != nil {
				 := .sp
				if .sp <  {
					break
				}
				if .sp ==  {
					if !.openDefer {
						throw("duplicated defer entry")
					}
					// Don't add any record past an
					// in-progress defer entry. We don't
					// need it, and more importantly, we
					// want to keep the invariant that
					// there is no open defer entry
					// passed an in-progress entry (see
					// header comment).
					if .started {
						break 
					}
					continue 
				}
				 = 
				 = .link
			}
			if .fn.deferreturn == 0 {
				throw("missing deferreturn")
			}

			 := newdefer()
			.openDefer = true
			._panic = nil
			// These are the pc/sp to set after we've
			// run a defer in this frame that did a
			// recover. We return to a special
			// deferreturn that runs any remaining
			// defers and then returns from the
			// function.
			.pc = .fn.entry() + uintptr(.fn.deferreturn)
			.varp = .varp
			.fd = 
			// Save the SP/PC associated with current frame,
			// so we can continue stack trace later if needed.
			.framepc = .pc
			.sp = .sp
			.link = 
			if  == nil {
				._defer = 
			} else {
				.link = 
			}
			// Stop stack scanning after adding one open defer record
			break
		}
	})
}

// readvarintUnsafe reads the uint32 in varint format starting at fd, and returns the
// uint32 and a pointer to the byte following the varint.
//
// There is a similar function runtime.readvarint, which takes a slice of bytes,
// rather than an unsafe pointer. These functions are duplicated, because one of
// the two use cases for the functions would get slower if the functions were
// combined.
func readvarintUnsafe( unsafe.Pointer) (uint32, unsafe.Pointer) {
	var  uint32
	var  int
	for {
		 := *(*uint8)((unsafe.Pointer()))
		 = add(, unsafe.Sizeof())
		if  < 128 {
			return  + uint32()<<, 
		}
		 += ((uint32() &^ 128) << )
		 += 7
		if  > 28 {
			panic("Bad varint")
		}
	}
}

// runOpenDeferFrame runs the active open-coded defers in the frame specified by
// d. It normally processes all active defers in the frame, but stops immediately
// if a defer does a successful recover. It returns true if there are no
// remaining defers to run in the frame.
func runOpenDeferFrame( *_defer) bool {
	 := true
	 := .fd

	,  := readvarintUnsafe()
	,  := readvarintUnsafe()
	 := *(*uint8)(unsafe.Pointer(.varp - uintptr()))

	for  := int() - 1;  >= 0; -- {
		// read the funcdata info for this defer
		var  uint32
		,  = readvarintUnsafe()
		if &(1<<) == 0 {
			continue
		}
		 := *(*func())(unsafe.Pointer(.varp - uintptr()))
		.fn = 
		 =  &^ (1 << )
		*(*uint8)(unsafe.Pointer(.varp - uintptr())) = 
		 := ._panic
		// Call the defer. Note that this can change d.varp if
		// the stack moves.
		deferCallSave(, .fn)
		if  != nil && .aborted {
			break
		}
		.fn = nil
		if ._panic != nil && ._panic.recovered {
			 =  == 0
			break
		}
	}

	return 
}

// deferCallSave calls fn() after saving the caller's pc and sp in the
// panic record. This allows the runtime to return to the Goexit defer
// processing loop, in the unusual case where the Goexit may be
// bypassed by a successful recover.
//
// This is marked as a wrapper by the compiler so it doesn't appear in
// tracebacks.
func deferCallSave( *_panic,  func()) {
	if  != nil {
		.argp = unsafe.Pointer(getargp())
		.pc = getcallerpc()
		.sp = unsafe.Pointer(getcallersp())
	}
	()
	if  != nil {
		.pc = 0
		.sp = unsafe.Pointer(nil)
	}
}

// A PanicNilError happens when code calls panic(nil).
//
// Before Go 1.21, programs that called panic(nil) observed recover returning nil.
// Starting in Go 1.21, programs that call panic(nil) observe recover returning a *PanicNilError.
// Programs can change back to the old behavior by setting GODEBUG=panicnil=1.
type PanicNilError struct {
	// This field makes PanicNilError structurally different from
	// any other struct in this package, and the _ makes it different
	// from any struct in other packages too.
	// This avoids any accidental conversions being possible
	// between this struct and some other struct sharing the same fields,
	// like happened in go.dev/issue/56603.
	_ [0]*PanicNilError
}

func (*PanicNilError) () string { return "panic called with nil argument" }
func (*PanicNilError) () {}

var panicnil = &godebugInc{name: "panicnil"}

// The implementation of the predeclared function panic.
func gopanic( any) {
	if  == nil {
		if debug.panicnil.Load() != 1 {
			 = new(PanicNilError)
		} else {
			panicnil.IncNonDefault()
		}
	}

	 := getg()
	if .m.curg !=  {
		print("panic: ")
		printany()
		print("\n")
		throw("panic on system stack")
	}

	if .m.mallocing != 0 {
		print("panic: ")
		printany()
		print("\n")
		throw("panic during malloc")
	}
	if .m.preemptoff != "" {
		print("panic: ")
		printany()
		print("\n")
		print("preempt off reason: ")
		print(.m.preemptoff)
		print("\n")
		throw("panic during preemptoff")
	}
	if .m.locks != 0 {
		print("panic: ")
		printany()
		print("\n")
		throw("panic holding locks")
	}

	var  _panic
	.arg = 
	.link = ._panic
	._panic = (*_panic)(noescape(unsafe.Pointer(&)))

	runningPanicDefers.Add(1)

	// By calculating getcallerpc/getcallersp here, we avoid scanning the
	// gopanic frame (stack scanning is slow...)
	addOneOpenDeferFrame(, getcallerpc(), unsafe.Pointer(getcallersp()))

	for {
		 := ._defer
		if  == nil {
			break
		}

		// If defer was started by earlier panic or Goexit (and, since we're back here, that triggered a new panic),
		// take defer off list. An earlier panic will not continue running, but we will make sure below that an
		// earlier Goexit does continue running.
		if .started {
			if ._panic != nil {
				._panic.aborted = true
			}
			._panic = nil
			if !.openDefer {
				// For open-coded defers, we need to process the
				// defer again, in case there are any other defers
				// to call in the frame (not including the defer
				// call that caused the panic).
				.fn = nil
				._defer = .link
				freedefer()
				continue
			}
		}

		// Mark defer as started, but keep on list, so that traceback
		// can find and update the defer's argument frame if stack growth
		// or a garbage collection happens before executing d.fn.
		.started = true

		// Record the panic that is running the defer.
		// If there is a new panic during the deferred call, that panic
		// will find d in the list and will mark d._panic (this panic) aborted.
		._panic = (*_panic)(noescape(unsafe.Pointer(&)))

		 := true
		if .openDefer {
			 = runOpenDeferFrame()
			if  && !._panic.recovered {
				addOneOpenDeferFrame(, 0, nil)
			}
		} else {
			.argp = unsafe.Pointer(getargp())
			.fn()
		}
		.argp = nil

		// Deferred function did not panic. Remove d.
		if ._defer !=  {
			throw("bad defer entry in panic")
		}
		._panic = nil

		// trigger shrinkage to test stack copy. See stack_test.go:TestStackPanic
		//GC()

		 := .pc
		 := unsafe.Pointer(.sp) // must be pointer so it gets adjusted during stack copy
		if  {
			.fn = nil
			._defer = .link
			freedefer()
		}
		if .recovered {
			._panic = .link
			if ._panic != nil && ._panic.goexit && ._panic.aborted {
				// A normal recover would bypass/abort the Goexit.  Instead,
				// we return to the processing loop of the Goexit.
				.sigcode0 = uintptr(._panic.sp)
				.sigcode1 = uintptr(._panic.pc)
				mcall(recovery)
				throw("bypassed recovery failed") // mcall should not return
			}
			runningPanicDefers.Add(-1)

			// After a recover, remove any remaining non-started,
			// open-coded defer entries, since the corresponding defers
			// will be executed normally (inline). Any such entry will
			// become stale once we run the corresponding defers inline
			// and exit the associated stack frame. We only remove up to
			// the first started (in-progress) open defer entry, not
			// including the current frame, since any higher entries will
			// be from a higher panic in progress, and will still be
			// needed.
			 := ._defer
			var  *_defer
			if ! {
				// Skip our current frame, if not done. It is
				// needed to complete any remaining defers in
				// deferreturn()
				 = 
				 = .link
			}
			for  != nil {
				if .started {
					// This defer is started but we
					// are in the middle of a
					// defer-panic-recover inside of
					// it, so don't remove it or any
					// further defer entries
					break
				}
				if .openDefer {
					if  == nil {
						._defer = .link
					} else {
						.link = .link
					}
					 := .link
					freedefer()
					 = 
				} else {
					 = 
					 = .link
				}
			}

			._panic = .link
			// Aborted panics are marked but remain on the g.panic list.
			// Remove them from the list.
			for ._panic != nil && ._panic.aborted {
				._panic = ._panic.link
			}
			if ._panic == nil { // must be done with signal
				.sig = 0
			}
			// Pass information about recovering frame to recovery.
			.sigcode0 = uintptr()
			.sigcode1 = 
			mcall(recovery)
			throw("recovery failed") // mcall should not return
		}
	}

	// ran out of deferred calls - old-school panic now
	// Because it is unsafe to call arbitrary user code after freezing
	// the world, we call preprintpanics to invoke all necessary Error
	// and String methods to prepare the panic strings before startpanic.
	preprintpanics(._panic)

	fatalpanic(._panic) // should not return
	*(*int)(nil) = 0      // not reached
}

// getargp returns the location where the caller
// writes outgoing function call arguments.
//
//go:nosplit
//go:noinline
func getargp() uintptr {
	return getcallersp() + sys.MinFrameSize
}

// The implementation of the predeclared function recover.
// Cannot split the stack because it needs to reliably
// find the stack segment of its caller.
//
// TODO(rsc): Once we commit to CopyStackAlways,
// this doesn't need to be nosplit.
//
//go:nosplit
func gorecover( uintptr) any {
	// Must be in a function running as part of a deferred call during the panic.
	// Must be called from the topmost function of the call
	// (the function used in the defer statement).
	// p.argp is the argument pointer of that topmost deferred function call.
	// Compare against argp reported by caller.
	// If they match, the caller is the one who can recover.
	 := getg()
	 := ._panic
	if  != nil && !.goexit && !.recovered &&  == uintptr(.argp) {
		.recovered = true
		return .arg
	}
	return nil
}

//go:linkname sync_throw sync.throw
func sync_throw( string) {
	throw()
}

//go:linkname sync_fatal sync.fatal
func sync_fatal( string) {
	fatal()
}

// throw triggers a fatal error that dumps a stack trace and exits.
//
// throw should be used for runtime-internal fatal errors where Go itself,
// rather than user code, may be at fault for the failure.
//
//go:nosplit
func throw( string) {
	// Everything throw does should be recursively nosplit so it
	// can be called even when it's unsafe to grow the stack.
	systemstack(func() {
		print("fatal error: ", , "\n")
	})

	fatalthrow(throwTypeRuntime)
}

// fatal triggers a fatal error that dumps a stack trace and exits.
//
// fatal is equivalent to throw, but is used when user code is expected to be
// at fault for the failure, such as racing map writes.
//
// fatal does not include runtime frames, system goroutines, or frame metadata
// (fp, sp, pc) in the stack trace unless GOTRACEBACK=system or higher.
//
//go:nosplit
func fatal( string) {
	// Everything fatal does should be recursively nosplit so it
	// can be called even when it's unsafe to grow the stack.
	systemstack(func() {
		print("fatal error: ", , "\n")
	})

	fatalthrow(throwTypeUser)
}

// runningPanicDefers is non-zero while running deferred functions for panic.
// This is used to try hard to get a panic stack trace out when exiting.
var runningPanicDefers atomic.Uint32

// panicking is non-zero when crashing the program for an unrecovered panic.
var panicking atomic.Uint32

// paniclk is held while printing the panic information and stack trace,
// so that two concurrent panics don't overlap their output.
var paniclk mutex

// Unwind the stack after a deferred function calls recover
// after a panic. Then arrange to continue running as though
// the caller of the deferred function returned normally.
func recovery( *g) {
	// Info about defer passed in G struct.
	 := .sigcode0
	 := .sigcode1

	// d's arguments need to be in the stack.
	if  != 0 && ( < .stack.lo || .stack.hi < ) {
		print("recover: ", hex(), " not in [", hex(.stack.lo), ", ", hex(.stack.hi), "]\n")
		throw("bad recovery")
	}

	// Make the deferproc for this d return again,
	// this time returning 1. The calling function will
	// jump to the standard return epilogue.
	.sched.sp = 
	.sched.pc = 
	.sched.lr = 0
	// Restore the bp on platforms that support frame pointers.
	// N.B. It's fine to not set anything for platforms that don't
	// support frame pointers, since nothing consumes them.
	switch {
	case goarch.IsAmd64 != 0:
		// On x86, the architectural bp is stored 2 words below the
		// stack pointer.
		.sched.bp = *(*uintptr)(unsafe.Pointer( - 2*goarch.PtrSize))
	case goarch.IsArm64 != 0:
		// on arm64, the architectural bp points one word higher
		// than the sp.
		.sched.bp =  - goarch.PtrSize
	}
	.sched.ret = 1
	gogo(&.sched)
}

// fatalthrow implements an unrecoverable runtime throw. It freezes the
// system, prints stack traces starting from its caller, and terminates the
// process.
//
//go:nosplit
func fatalthrow( throwType) {
	 := getcallerpc()
	 := getcallersp()
	 := getg()

	if .m.throwing == throwTypeNone {
		.m.throwing = 
	}

	// Switch to the system stack to avoid any stack growth, which may make
	// things worse if the runtime is in a bad state.
	systemstack(func() {
		if isSecureMode() {
			exit(2)
		}

		startpanic_m()

		if dopanic_m(, , ) {
			// crash uses a decent amount of nosplit stack and we're already
			// low on stack in throw, so crash on the system stack (unlike
			// fatalpanic).
			crash()
		}

		exit(2)
	})

	*(*int)(nil) = 0 // not reached
}

// fatalpanic implements an unrecoverable panic. It is like fatalthrow, except
// that if msgs != nil, fatalpanic also prints panic messages and decrements
// runningPanicDefers once main is blocked from exiting.
//
//go:nosplit
func fatalpanic( *_panic) {
	 := getcallerpc()
	 := getcallersp()
	 := getg()
	var  bool
	// Switch to the system stack to avoid any stack growth, which
	// may make things worse if the runtime is in a bad state.
	systemstack(func() {
		if startpanic_m() &&  != nil {
			// There were panic messages and startpanic_m
			// says it's okay to try to print them.

			// startpanic_m set panicking, which will
			// block main from exiting, so now OK to
			// decrement runningPanicDefers.
			runningPanicDefers.Add(-1)

			printpanics()
		}

		 = dopanic_m(, , )
	})

	if  {
		// By crashing outside the above systemstack call, debuggers
		// will not be confused when generating a backtrace.
		// Function crash is marked nosplit to avoid stack growth.
		crash()
	}

	systemstack(func() {
		exit(2)
	})

	*(*int)(nil) = 0 // not reached
}

// startpanic_m prepares for an unrecoverable panic.
//
// It returns true if panic messages should be printed, or false if
// the runtime is in bad shape and should just print stacks.
//
// It must not have write barriers even though the write barrier
// explicitly ignores writes once dying > 0. Write barriers still
// assume that g.m.p != nil, and this function may not have P
// in some contexts (e.g. a panic in a signal handler for a signal
// sent to an M with no P).
//
//go:nowritebarrierrec
func startpanic_m() bool {
	 := getg()
	if mheap_.cachealloc.size == 0 { // very early
		print("runtime: panic before malloc heap initialized\n")
	}
	// Disallow malloc during an unrecoverable panic. A panic
	// could happen in a signal handler, or in a throw, or inside
	// malloc itself. We want to catch if an allocation ever does
	// happen (even if we're not in one of these situations).
	.m.mallocing++

	// If we're dying because of a bad lock count, set it to a
	// good lock count so we don't recursively panic below.
	if .m.locks < 0 {
		.m.locks = 1
	}

	switch .m.dying {
	case 0:
		// Setting dying >0 has the side-effect of disabling this G's writebuf.
		.m.dying = 1
		panicking.Add(1)
		lock(&paniclk)
		if debug.schedtrace > 0 || debug.scheddetail > 0 {
			schedtrace(true)
		}
		freezetheworld()
		return true
	case 1:
		// Something failed while panicking.
		// Just print a stack trace and exit.
		.m.dying = 2
		print("panic during panic\n")
		return false
	case 2:
		// This is a genuine bug in the runtime, we couldn't even
		// print the stack trace successfully.
		.m.dying = 3
		print("stack trace unavailable\n")
		exit(4)
		fallthrough
	default:
		// Can't even print! Just exit.
		exit(5)
		return false // Need to return something.
	}
}

var didothers bool
var deadlock mutex

// gp is the crashing g running on this M, but may be a user G, while getg() is
// always g0.
func dopanic_m( *g, ,  uintptr) bool {
	if .sig != 0 {
		 := signame(.sig)
		if  != "" {
			print("[signal ", )
		} else {
			print("[signal ", hex(.sig))
		}
		print(" code=", hex(.sigcode0), " addr=", hex(.sigcode1), " pc=", hex(.sigpc), "]\n")
	}

	, ,  := gotraceback()
	if  > 0 {
		if  != .m.curg {
			 = true
		}
		if  != .m.g0 {
			print("\n")
			goroutineheader()
			traceback(, , 0, )
		} else if  >= 2 || .m.throwing >= throwTypeRuntime {
			print("\nruntime stack:\n")
			traceback(, , 0, )
		}
		if !didothers &&  {
			didothers = true
			tracebackothers()
		}
	}
	unlock(&paniclk)

	if panicking.Add(-1) != 0 {
		// Some other m is panicking too.
		// Let it print what it needs to print.
		// Wait forever without chewing up cpu.
		// It will exit when it's done.
		lock(&deadlock)
		lock(&deadlock)
	}

	printDebugLog()

	return 
}

// canpanic returns false if a signal should throw instead of
// panicking.
//
//go:nosplit
func canpanic() bool {
	 := getg()
	 := acquirem()

	// Is it okay for gp to panic instead of crashing the program?
	// Yes, as long as it is running Go code, not runtime code,
	// and not stuck in a system call.
	if  != .curg {
		releasem()
		return false
	}
	// N.B. mp.locks != 1 instead of 0 to account for acquirem.
	if .locks != 1 || .mallocing != 0 || .throwing != throwTypeNone || .preemptoff != "" || .dying != 0 {
		releasem()
		return false
	}
	 := readgstatus()
	if &^_Gscan != _Grunning || .syscallsp != 0 {
		releasem()
		return false
	}
	if GOOS == "windows" && .libcallsp != 0 {
		releasem()
		return false
	}
	releasem()
	return true
}

// shouldPushSigpanic reports whether pc should be used as sigpanic's
// return PC (pushing a frame for the call). Otherwise, it should be
// left alone so that LR is used as sigpanic's return PC, effectively
// replacing the top-most frame with sigpanic. This is used by
// preparePanic.
func shouldPushSigpanic( *g, ,  uintptr) bool {
	if  == 0 {
		// Probably a call to a nil func. The old LR is more
		// useful in the stack trace. Not pushing the frame
		// will make the trace look like a call to sigpanic
		// instead. (Otherwise the trace will end at sigpanic
		// and we won't get to see who faulted.)
		return false
	}
	// If we don't recognize the PC as code, but we do recognize
	// the link register as code, then this assumes the panic was
	// caused by a call to non-code. In this case, we want to
	// ignore this call to make unwinding show the context.
	//
	// If we running C code, we're not going to recognize pc as a
	// Go function, so just assume it's good. Otherwise, traceback
	// may try to read a stale LR that looks like a Go code
	// pointer and wander into the woods.
	if .m.incgo || findfunc().valid() {
		// This wasn't a bad call, so use PC as sigpanic's
		// return PC.
		return true
	}
	if findfunc().valid() {
		// This was a bad call, but the LR is good, so use the
		// LR as sigpanic's return PC.
		return false
	}
	// Neither the PC or LR is good. Hopefully pushing a frame
	// will work.
	return true
}

// isAbortPC reports whether pc is the program counter at which
// runtime.abort raises a signal.
//
// It is nosplit because it's part of the isgoexception
// implementation.
//
//go:nosplit
func isAbortPC( uintptr) bool {
	 := findfunc()
	if !.valid() {
		return false
	}
	return .funcID == abi.FuncID_abort
}