From d843ebfe40725aa0123f15ac93a6336d13e88069 Mon Sep 17 00:00:00 2001 From: Jaden Weiss Date: Sun, 22 Sep 2019 11:58:00 -0400 Subject: Improved blocking (#513) core: major improvements to blocking, including support for buffered channels. --- compiler/channel.go | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'compiler/channel.go') 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, "") -- cgit v1.2.3