ssa: chan send/recv
This commit is contained in:
@@ -65,6 +65,18 @@ func UnderlyingKind(t types.Type) abi.Kind {
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
func ChanDir(dir types.ChanDir) (abi.ChanDir, string) {
|
||||
switch dir {
|
||||
case types.SendRecv:
|
||||
return abi.BothDir, "chan"
|
||||
case types.SendOnly:
|
||||
return abi.SendDir, "chan->"
|
||||
case types.RecvOnly:
|
||||
return abi.RecvDir, "<-chan"
|
||||
}
|
||||
panic("invlid chan dir")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type DataKind int
|
||||
@@ -165,6 +177,18 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) {
|
||||
key, pub1 := b.TypeName(t.Key())
|
||||
elem, pub2 := b.TypeName(t.Elem())
|
||||
return fmt.Sprintf("map[%s]%s", key, elem), pub1 && pub2
|
||||
case *types.Chan:
|
||||
elem, pub := b.TypeName(t.Elem())
|
||||
var s string
|
||||
switch t.Dir() {
|
||||
case types.SendRecv:
|
||||
s = "chan"
|
||||
case types.SendOnly:
|
||||
s = "chan<-"
|
||||
case types.RecvOnly:
|
||||
s = "<-chan"
|
||||
}
|
||||
return fmt.Sprintf("%s %s", s, elem), pub
|
||||
}
|
||||
log.Panicf("todo: %T\n", t)
|
||||
return
|
||||
|
||||
@@ -68,6 +68,8 @@ func (b Builder) abiTypeOf(t types.Type) func() Expr {
|
||||
return b.abiSliceOf(t)
|
||||
case *types.Array:
|
||||
return b.abiArrayOf(t)
|
||||
case *types.Chan:
|
||||
return b.abiChanOf(t)
|
||||
}
|
||||
panic("todo")
|
||||
}
|
||||
@@ -274,6 +276,14 @@ func (b Builder) abiArrayOf(t *types.Array) func() Expr {
|
||||
}
|
||||
}
|
||||
|
||||
func (b Builder) abiChanOf(t *types.Chan) func() Expr {
|
||||
elem := b.abiTypeOf(t.Elem())
|
||||
return func() Expr {
|
||||
dir, s := abi.ChanDir(t.Dir())
|
||||
return b.Call(b.Pkg.rtFunc("ChanOf"), b.Prog.IntVal(uint64(dir), b.Prog.Int()), b.Str(s), elem())
|
||||
}
|
||||
}
|
||||
|
||||
// func StructField(name string, typ *abi.Type, off uintptr, tag string, embedded bool)
|
||||
// func Struct(pkgPath string, size uintptr, fields []abi.StructField)
|
||||
func (b Builder) abiStructOf(t *types.Struct) func() Expr {
|
||||
|
||||
@@ -540,4 +540,75 @@ func (b Builder) Next(iter Expr, isString bool) (ret Expr) {
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
// The MakeChan instruction creates a new channel object and yields a
|
||||
// value of kind chan.
|
||||
//
|
||||
// Type() returns a (possibly named) *types.Chan.
|
||||
//
|
||||
// Pos() returns the ast.CallExpr.Lparen for the make(chan) that
|
||||
// created it.
|
||||
//
|
||||
// Example printed form:
|
||||
//
|
||||
// t0 = make chan int 0
|
||||
// t0 = make IntChan 0
|
||||
//
|
||||
// type MakeChan struct {
|
||||
// register
|
||||
// Size Value // int; size of buffer; zero => synchronous.
|
||||
// }
|
||||
func (b Builder) MakeChan(t Type, size Expr) (ret Expr) {
|
||||
if debugInstr {
|
||||
log.Printf("MakeChan %v, %v\n", t.RawType(), size.impl)
|
||||
}
|
||||
prog := b.Prog
|
||||
eltSize := prog.IntVal(prog.SizeOf(prog.Elem(t)), prog.Int())
|
||||
ret.Type = t
|
||||
ret.impl = b.InlineCall(b.Pkg.rtFunc("NewChan"), eltSize, size).impl
|
||||
return
|
||||
}
|
||||
|
||||
// The Send instruction sends X on channel Chan.
|
||||
//
|
||||
// Pos() returns the ast.SendStmt.Arrow, if explicit in the source.
|
||||
//
|
||||
// Example printed form:
|
||||
//
|
||||
// send t0 <- t1
|
||||
func (b Builder) Send(ch Expr, x Expr) (ret Expr) {
|
||||
if debugInstr {
|
||||
log.Printf("Send %v, %v\n", ch.impl, x.impl)
|
||||
}
|
||||
prog := b.Prog
|
||||
eltSize := prog.IntVal(prog.SizeOf(prog.Elem(ch.Type)), prog.Int())
|
||||
ret = b.InlineCall(b.Pkg.rtFunc("ChanSend"), ch, b.toPtr(x), eltSize)
|
||||
return
|
||||
}
|
||||
|
||||
func (b Builder) toPtr(x Expr) Expr {
|
||||
typ := x.Type
|
||||
vtyp := b.Prog.VoidPtr()
|
||||
vptr := b.Alloc(typ, false)
|
||||
b.Store(vptr, x)
|
||||
return Expr{vptr.impl, vtyp}
|
||||
}
|
||||
|
||||
func (b Builder) Recv(ch Expr, commaOk bool) (ret Expr) {
|
||||
if debugInstr {
|
||||
log.Printf("Recv %v, %v\n", ch.impl, commaOk)
|
||||
}
|
||||
prog := b.Prog
|
||||
eltSize := prog.IntVal(prog.SizeOf(prog.Elem(ch.Type)), prog.Int())
|
||||
etyp := prog.Elem(ch.Type)
|
||||
ptr := b.Alloc(etyp, false)
|
||||
ok := b.InlineCall(b.Pkg.rtFunc("ChanRecv"), ch, ptr, eltSize)
|
||||
if commaOk {
|
||||
val := b.Load(ptr)
|
||||
t := prog.Struct(etyp, prog.Bool())
|
||||
return b.aggregateValue(t, val.impl, ok.impl)
|
||||
} else {
|
||||
return b.Load(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
15
ssa/expr.go
15
ssa/expr.go
@@ -1001,6 +1001,8 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
||||
return b.SliceLen(arg)
|
||||
case vkString:
|
||||
return b.StringLen(arg)
|
||||
case vkChan:
|
||||
return b.InlineCall(b.Pkg.rtFunc("ChanLen"), arg)
|
||||
}
|
||||
}
|
||||
case "cap":
|
||||
@@ -1009,6 +1011,8 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
||||
switch arg.kind {
|
||||
case vkSlice:
|
||||
return b.SliceCap(arg)
|
||||
case vkChan:
|
||||
return b.InlineCall(b.Pkg.rtFunc("ChanCap"), arg)
|
||||
}
|
||||
}
|
||||
case "append":
|
||||
@@ -1047,6 +1051,14 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
case "close":
|
||||
if len(args) == 1 {
|
||||
arg := args[0]
|
||||
switch arg.kind {
|
||||
case vkChan:
|
||||
return b.InlineCall(b.Pkg.rtFunc("ChanClose"), arg)
|
||||
}
|
||||
}
|
||||
case "recover":
|
||||
return b.Recover()
|
||||
case "print", "println":
|
||||
@@ -1114,6 +1126,9 @@ func (b Builder) PrintEx(ln bool, args ...Expr) (ret Expr) {
|
||||
case vkComplex:
|
||||
fn = "PrintComplex"
|
||||
typ = prog.Complex128()
|
||||
case vkChan:
|
||||
fn = "PrintPointer"
|
||||
typ = prog.VoidPtr()
|
||||
default:
|
||||
panic(fmt.Errorf("illegal types for operand: print %v", arg.RawType()))
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ type aProgram struct {
|
||||
rtIfaceTy llvm.Type
|
||||
rtSliceTy llvm.Type
|
||||
rtMapTy llvm.Type
|
||||
rtChanTy llvm.Type
|
||||
|
||||
anyTy Type
|
||||
voidTy Type
|
||||
@@ -287,6 +288,13 @@ func (p Program) rtString() llvm.Type {
|
||||
return p.rtStringTy
|
||||
}
|
||||
|
||||
func (p Program) rtChan() llvm.Type {
|
||||
if p.rtChanTy.IsNil() {
|
||||
p.rtChanTy = p.rtType("Chan").ll
|
||||
}
|
||||
return p.rtChanTy
|
||||
}
|
||||
|
||||
func (p Program) tyComplex64() llvm.Type {
|
||||
if p.c64Type.IsNil() {
|
||||
ctx := p.ctx
|
||||
|
||||
@@ -57,6 +57,7 @@ const (
|
||||
vkEface
|
||||
vkIface
|
||||
vkStruct
|
||||
vkChan
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -371,6 +372,7 @@ func (p Program) toType(raw types.Type) Type {
|
||||
elem := p.rawType(t.Elem())
|
||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkArray}
|
||||
case *types.Chan:
|
||||
return &aType{llvm.PointerType(p.rtChan(), 0), typ, vkChan}
|
||||
}
|
||||
panic(fmt.Sprintf("toLLVMType: todo - %T\n", raw))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user