From 25b104cf132eb04a24a464753553f783098bfc65 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Thu, 2 May 2024 07:37:31 +0800 Subject: [PATCH] llgo/ssa: PhisExpr --- cl/compile.go | 2 +- cl/compile_test.go | 2 +- ssa/expr.go | 65 +++++++++++++++++++++++++++++++++++++++++----- ssa/type.go | 1 + 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index 1d09b2fc..c8b4ded9 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -400,7 +400,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue for i, pred := range preds { bblks[i] = p.fn.Block(pred.Index) } - phi.AddIncoming(vals, bblks) + phi.AddIncoming(b, vals, bblks) }) case *ssa.ChangeType: t := v.Type() diff --git a/cl/compile_test.go b/cl/compile_test.go index b9c3443f..6efd7574 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -29,7 +29,7 @@ func testCompile(t *testing.T, src, expected string) { } func TestFromTestrt(t *testing.T) { - cltest.FromDir(t, "", "./_testrt", true) + cltest.FromDir(t, "concat", "./_testrt", true) } func TestFromTestdata(t *testing.T) { diff --git a/ssa/expr.go b/ssa/expr.go index e19c7a12..ef607af1 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -50,12 +50,17 @@ func (v Expr) TypeOf() types.Type { // Do evaluates the delay expression and returns the result. func (v Expr) Do() Expr { - if vt := v.Type; vt.kind == vkDelayExpr { + switch vt := v.Type; vt.kind { + case vkDelayExpr: return vt.t.(delayExprTy)() + case vkPhisExpr: + panic("unreachable") } return v } +// ----------------------------------------------------------------------------- + // DelayExpr returns a delay expression. func DelayExpr(f func() Expr) Expr { return Expr{Type: &aType{t: delayExprTy(f), kind: vkDelayExpr}} @@ -73,6 +78,24 @@ func (p delayExprTy) String() string { // ----------------------------------------------------------------------------- +type phisExprTy struct { + phis []llvm.Value +} + +func (p phisExprTy) Underlying() types.Type { + panic("don't call") +} + +func (p phisExprTy) String() string { + return "phisExpr" +} + +func phisExpr(phis []llvm.Value) Expr { + return Expr{Type: &aType{t: &phisExprTy{phis}, kind: vkPhisExpr}} +} + +// ----------------------------------------------------------------------------- + // Null returns a null constant expression. func (p Program) Null(t Type) Expr { return Expr{llvm.ConstNull(t.ll), t} @@ -337,6 +360,14 @@ func llvmValues(vals []Expr) []llvm.Value { return ret } +func fieldValues(b llvm.Builder, vals []Expr, fldIdx int) []llvm.Value { + ret := make([]llvm.Value, len(vals)) + for i, v := range vals { + ret[i] = llvm.CreateExtractValue(b, v.impl, fldIdx) + } + return ret +} + func llvmBlocks(bblks []BasicBlock) []llvm.BasicBlock { ret := make([]llvm.BasicBlock, len(bblks)) for i, v := range bblks { @@ -351,15 +382,37 @@ type Phi struct { } // AddIncoming adds incoming values to a phi node. -func (p Phi) AddIncoming(vals []Expr, bblks []BasicBlock) { - v := llvmValues(vals) - b := llvmBlocks(bblks) - p.impl.AddIncoming(v, b) +func (p Phi) AddIncoming(b Builder, vals []Expr, bblks []BasicBlock) { + bs := llvmBlocks(bblks) + if p.kind != vkPhisExpr { // normal phi node + vs := llvmValues(vals) + p.impl.AddIncoming(vs, bs) + return + } + phis := p.t.(*phisExprTy).phis + for i, phi := range phis { + flds := fieldValues(b.impl, vals, i) + phi.AddIncoming(flds, bs) + } } // Phi returns a phi node. func (b Builder) Phi(t Type) Phi { - return Phi{Expr{llvm.CreatePHI(b.impl, t.ll), t}} + impl := b.impl + switch tund := t.t.Underlying().(type) { + case *types.Basic: + kind := tund.Kind() + switch kind { + case types.String: + prog := b.Prog + phis := make([]llvm.Value, 2) + phis[0] = llvm.CreatePHI(impl, prog.tyVoidPtr()) + phis[1] = llvm.CreatePHI(impl, prog.tyInt()) + return Phi{phisExpr(phis)} + } + } + phi := llvm.CreatePHI(impl, t.ll) + return Phi{Expr{phi, t}} } // ----------------------------------------------------------------------------- diff --git a/ssa/type.go b/ssa/type.go index 8dfcd58b..c33b1e5d 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -43,6 +43,7 @@ const ( vkFunc vkTuple vkDelayExpr = -1 + vkPhisExpr = -2 ) // -----------------------------------------------------------------------------