// Copyright 2010 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.

// Export guts for testing.

package runtime

import "unsafe"

var Fadd64 = fadd64
var Fsub64 = fsub64
var Fmul64 = fmul64
var Fdiv64 = fdiv64
var F64to32 = f64to32
var F32to64 = f32to64
var Fcmp64 = fcmp64
var Fintto64 = fintto64
var F64toint = f64toint
var Sqrt = sqrt

var Entersyscall = entersyscall
var Exitsyscall = exitsyscall
var LockedOSThread = lockedOSThread
var Xadduintptr = xadduintptr

var FuncPC = funcPC

type LFNode struct {
	Next    uint64
	Pushcnt uintptr
}

func LFStackPush(head *uint64, node *LFNode) {
	lfstackpush(head, (*lfnode)(unsafe.Pointer(node)))
}

func LFStackPop(head *uint64) *LFNode {
	return (*LFNode)(unsafe.Pointer(lfstackpop(head)))
}

type ParFor struct {
	body   func(*ParFor, uint32)
	done   uint32
	Nthr   uint32
	thrseq uint32
	Cnt    uint32
	wait   bool
}

func NewParFor(nthrmax uint32) *ParFor {
	var desc *ParFor
	systemstack(func() {
		desc = (*ParFor)(unsafe.Pointer(parforalloc(nthrmax)))
	})
	return desc
}

func ParForSetup(desc *ParFor, nthr, n uint32, wait bool, body func(*ParFor, uint32)) {
	systemstack(func() {
		parforsetup((*parfor)(unsafe.Pointer(desc)), nthr, n, wait,
			*(*func(*parfor, uint32))(unsafe.Pointer(&body)))
	})
}

func ParForDo(desc *ParFor) {
	systemstack(func() {
		parfordo((*parfor)(unsafe.Pointer(desc)))
	})
}

func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) {
	desc1 := (*parfor)(unsafe.Pointer(desc))
	pos := desc1.thr[tid].pos
	return uint32(pos), uint32(pos >> 32)
}

func GCMask(x interface{}) (ret []byte) {
	systemstack(func() {
		ret = getgcmask(x)
	})
	return
}

func RunSchedLocalQueueTest() {
	testSchedLocalQueue()
}
func RunSchedLocalQueueStealTest() {
	testSchedLocalQueueSteal()
}

var StringHash = stringHash
var BytesHash = bytesHash
var Int32Hash = int32Hash
var Int64Hash = int64Hash
var EfaceHash = efaceHash
var IfaceHash = ifaceHash
var MemclrBytes = memclrBytes

var HashLoad = &hashLoad

// entry point for testing
func GostringW(w []uint16) (s string) {
	systemstack(func() {
		s = gostringw(&w[0])
	})
	return
}

var Gostringnocopy = gostringnocopy
var Maxstring = &maxstring

type Uintreg uintreg

var Open = open
var Close = closefd
var Read = read
var Write = write

func Envs() []string     { return envs }
func SetEnvs(e []string) { envs = e }

var BigEndian = _BigEndian

// For benchmarking.

func BenchSetType(n int, x interface{}) {
	e := *(*eface)(unsafe.Pointer(&x))
	t := e._type
	var size uintptr
	var p unsafe.Pointer
	switch t.kind & kindMask {
	case _KindPtr:
		t = (*ptrtype)(unsafe.Pointer(t)).elem
		size = t.size
		p = e.data
	case _KindSlice:
		slice := *(*struct {
			ptr      unsafe.Pointer
			len, cap uintptr
		})(e.data)
		t = (*slicetype)(unsafe.Pointer(t)).elem
		size = t.size * slice.len
		p = slice.ptr
	}
	allocSize := roundupsize(size)
	systemstack(func() {
		for i := 0; i < n; i++ {
			heapBitsSetType(uintptr(p), allocSize, size, t)
		}
	})
}

const PtrSize = ptrSize

var TestingAssertE2I2GC = &testingAssertE2I2GC
var TestingAssertE2T2GC = &testingAssertE2T2GC
