From 8e256a2d5d720bd9a073f8a9775f0b8607c26b24 Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 7 Jul 2024 06:22:46 +0800 Subject: [PATCH] ssa: select --- cl/_testgo/select/in.go | 45 +++++++++++++++++++ cl/_testgo/select/out.ll | 1 + cl/compile.go | 12 ++++++ ssa/datastruct.go | 93 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 cl/_testgo/select/in.go create mode 100644 cl/_testgo/select/out.ll diff --git a/cl/_testgo/select/in.go b/cl/_testgo/select/in.go new file mode 100644 index 00000000..a772e7ed --- /dev/null +++ b/cl/_testgo/select/in.go @@ -0,0 +1,45 @@ +package main + +func main() { + send() + recv() +} + +func send() { + ch1 := make(chan int) + ch2 := make(chan int) + + go func() { + println(<-ch1) + }() + go func() { + println(<-ch2) + }() + + select { + case ch1 <- 100: + case ch2 <- 200: + } +} + +func recv() { + c1 := make(chan string) + c2 := make(chan string) + go func() { + c1 <- "ch1" + }() + go func() { + c2 <- "ch2" + }() + + for i := 0; i < 2; i++ { + select { + case msg1 := <-c1: + println(msg1) + case msg2 := <-c2: + println(msg2) + default: + println("exit") + } + } +} diff --git a/cl/_testgo/select/out.ll b/cl/_testgo/select/out.ll new file mode 100644 index 00000000..1c8a0e79 --- /dev/null +++ b/cl/_testgo/select/out.ll @@ -0,0 +1 @@ +; \ No newline at end of file diff --git a/cl/compile.go b/cl/compile.go index df2fccd8..cd3acbfd 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -588,6 +588,18 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue t := v.Type() size := p.compileValue(b, v.Size) ret = b.MakeChan(p.prog.Type(t, llssa.InGo), size) + case *ssa.Select: + states := make([]*llssa.SelectState, len(v.States)) + for i, s := range v.States { + states[i] = &llssa.SelectState{ + Chan: p.compileValue(b, s.Chan), + Send: s.Dir == types.SendOnly, + } + if s.Send != nil { + states[i].Value = p.compileValue(b, s.Send) + } + } + ret = b.Select(states, v.Blocking) default: panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv)) } diff --git a/ssa/datastruct.go b/ssa/datastruct.go index 101f5c6f..6157d57d 100644 --- a/ssa/datastruct.go +++ b/ssa/datastruct.go @@ -681,4 +681,97 @@ func (b Builder) Recv(ch Expr, commaOk bool) (ret Expr) { } } +type SelectState struct { + Chan Expr // channel to use (for send or receive) + Value Expr // value to send (for send) + Send bool // direction of case (SendOnly or RecvOnly) +} + +// The Select instruction tests whether (or blocks until) one +// of the specified sent or received states is entered. +// +// Let n be the number of States for which Dir==RECV and T_i (0<=i