runtime: add cap and len support for chans

Этот коммит содержится в:
cornelk 2020-05-11 20:54:22 +03:00 коммит произвёл Ayke
родитель 1461563e3f
коммит 7e64bc8f77
4 изменённых файлов: 40 добавлений и 7 удалений

Просмотреть файл

@ -1201,9 +1201,7 @@ func (b *builder) createBuiltin(args []ssa.Value, callName string, pos token.Pos
var llvmCap llvm.Value
switch args[0].Type().(type) {
case *types.Chan:
// Channel. Buffered channels haven't been implemented yet so always
// return 0.
llvmCap = llvm.ConstInt(b.intType, 0, false)
llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap")
case *types.Slice:
llvmCap = b.CreateExtractValue(value, 2, "cap")
default:
@ -1259,9 +1257,7 @@ func (b *builder) createBuiltin(args []ssa.Value, callName string, pos token.Pos
// string or slice
llvmLen = b.CreateExtractValue(value, 1, "len")
case *types.Chan:
// Channel. Buffered channels haven't been implemented yet so always
// return 0.
llvmLen = llvm.ConstInt(b.intType, 0, false)
llvmLen = b.createRuntimeCall("chanLen", []llvm.Value{value}, "len")
case *types.Map:
llvmLen = b.createRuntimeCall("hashmapLen", []llvm.Value{value}, "len")
default:

Просмотреть файл

@ -136,6 +136,38 @@ func chanMake(elementSize uintptr, bufSize uintptr) *channel {
}
}
// Return the number of entries in this chan, called from the len builtin.
// A nil chan is defined as having length 0.
//go:inline
func chanLen(c *channel) int {
if c == nil {
return 0
}
return int(c.bufUsed)
}
// wrapper for use in reflect
func chanLenUnsafePointer(p unsafe.Pointer) int {
c := (*channel)(p)
return chanLen(c)
}
// Return the capacity of this chan, called from the cap builtin.
// A nil chan is defined as having capacity 0.
//go:inline
func chanCap(c *channel) int {
if c == nil {
return 0
}
return int(c.bufSize)
}
// wrapper for use in reflect
func chanCapUnsafePointer(p unsafe.Pointer) int {
c := (*channel)(p)
return chanCap(c)
}
// resumeRX resumes the next receiver and returns the destination pointer.
// If the ok value is true, then the caller is expected to store a value into this pointer.
func (ch *channel) resumeRX(ok bool) unsafe.Pointer {

6
testdata/channel.go предоставленный
Просмотреть файл

@ -9,7 +9,11 @@ import (
var wg sync.WaitGroup
func main() {
ch := make(chan int)
ch := make(chan int, 2)
ch <- 1
println("len, cap of channel:", len(ch), cap(ch), ch == nil)
ch = make(chan int)
println("len, cap of channel:", len(ch), cap(ch), ch == nil)
wg.Add(1)

1
testdata/channel.txt предоставленный
Просмотреть файл

@ -1,3 +1,4 @@
len, cap of channel: 1 2 false
len, cap of channel: 0 0 false
recv from open channel: 1 true
received num: 2