aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler/channel.go
diff options
context:
space:
mode:
authorJaden Weiss <[email protected]>2019-09-22 11:58:00 -0400
committerRon Evans <[email protected]>2019-09-22 17:58:00 +0200
commitd843ebfe40725aa0123f15ac93a6336d13e88069 (patch)
treebd3dee1a1895104b146f1cf732b41ad6bbd2dbd7 /compiler/channel.go
parentd17f500c8b5e77cc0b524e228a7526ce320dbcc8 (diff)
downloadtinygo-d843ebfe40725aa0123f15ac93a6336d13e88069.tar.gz
tinygo-d843ebfe40725aa0123f15ac93a6336d13e88069.zip
Improved blocking (#513)
core: major improvements to blocking, including support for buffered channels.
Diffstat (limited to 'compiler/channel.go')
-rw-r--r--compiler/channel.go31
1 files changed, 6 insertions, 25 deletions
diff --git a/compiler/channel.go b/compiler/channel.go
index 55fb6920d..9f033098e 100644
--- a/compiler/channel.go
+++ b/compiler/channel.go
@@ -4,32 +4,17 @@ package compiler
// or pseudo-operations that are lowered during goroutine lowering.
import (
- "fmt"
"go/types"
"golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm"
)
-// emitMakeChan returns a new channel value for the given channel type.
-func (c *Compiler) emitMakeChan(expr *ssa.MakeChan) (llvm.Value, error) {
- chanType := c.getLLVMType(expr.Type())
- size := c.targetData.TypeAllocSize(chanType.ElementType())
- sizeValue := llvm.ConstInt(c.uintptrType, size, false)
- ptr := c.createRuntimeCall("alloc", []llvm.Value{sizeValue}, "chan.alloc")
- ptr = c.builder.CreateBitCast(ptr, chanType, "chan")
- // Set the elementSize field
- elementSizePtr := c.builder.CreateGEP(ptr, []llvm.Value{
- llvm.ConstInt(c.ctx.Int32Type(), 0, false),
- llvm.ConstInt(c.ctx.Int32Type(), 0, false),
- }, "")
+func (c *Compiler) emitMakeChan(frame *Frame, expr *ssa.MakeChan) llvm.Value {
elementSize := c.targetData.TypeAllocSize(c.getLLVMType(expr.Type().(*types.Chan).Elem()))
- if elementSize > 0xffff {
- return ptr, c.makeError(expr.Pos(), fmt.Sprintf("element size is %d bytes, which is bigger than the maximum of %d bytes", elementSize, 0xffff))
- }
- elementSizeValue := llvm.ConstInt(c.ctx.Int16Type(), elementSize, false)
- c.builder.CreateStore(elementSizeValue, elementSizePtr)
- return ptr, nil
+ elementSizeValue := llvm.ConstInt(c.uintptrType, elementSize, false)
+ bufSize := c.getValue(frame, expr.Size)
+ return c.createRuntimeCall("chanMake", []llvm.Value{elementSizeValue, bufSize}, "")
}
// emitChanSend emits a pseudo chan send operation. It is lowered to the actual
@@ -44,8 +29,7 @@ func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) {
c.builder.CreateStore(chanValue, valueAlloca)
// Do the send.
- coroutine := c.createRuntimeCall("getCoroutine", nil, "")
- c.createRuntimeCall("chanSend", []llvm.Value{coroutine, ch, valueAllocaCast}, "")
+ c.createRuntimeCall("chanSend", []llvm.Value{ch, valueAllocaCast}, "")
// End the lifetime of the alloca.
// This also works around a bug in CoroSplit, at least in LLVM 8:
@@ -63,14 +47,11 @@ func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) llvm.Value {
valueAlloca, valueAllocaCast, valueAllocaSize := c.createTemporaryAlloca(valueType, "chan.value")
// Do the receive.
- coroutine := c.createRuntimeCall("getCoroutine", nil, "")
- c.createRuntimeCall("chanRecv", []llvm.Value{coroutine, ch, valueAllocaCast}, "")
+ commaOk := c.createRuntimeCall("chanRecv", []llvm.Value{ch, valueAllocaCast}, "")
received := c.builder.CreateLoad(valueAlloca, "chan.received")
c.emitLifetimeEnd(valueAllocaCast, valueAllocaSize)
if unop.CommaOk {
- commaOk := c.createRuntimeCall("getTaskStateData", []llvm.Value{coroutine}, "chan.commaOk.wide")
- commaOk = c.builder.CreateTrunc(commaOk, c.ctx.Int1Type(), "chan.commaOk")
tuple := llvm.Undef(c.ctx.StructType([]llvm.Type{valueType, c.ctx.Int1Type()}, false))
tuple = c.builder.CreateInsertValue(tuple, received, 0, "")
tuple = c.builder.CreateInsertValue(tuple, commaOk, 1, "")