From 519e69a7f81b0ff1db1eb9bbbfd0207674c3e5fc Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 5 Jun 2024 13:48:11 +0800 Subject: [PATCH 1/6] cl/blocks --- cl/_testdefer/loop/in.go | 20 ++++ cl/_testdefer/loop/out.txt | 7 ++ cl/_testdefer/multiret/in.go | 18 ++++ cl/_testdefer/multiret/out.txt | 4 + cl/_testdefer/print/in.go | 52 +++++++++++ cl/_testdefer/print/out.txt | 0 cl/_testdefer/singleret/in.go | 17 ++++ cl/_testdefer/singleret/out.txt | 5 + cl/blocks/block.go | 156 ++++++++++++++++++++++++++++++++ cl/blocks/block_test.go | 129 ++++++++++++++++++++++++++ 10 files changed, 408 insertions(+) create mode 100644 cl/_testdefer/loop/in.go create mode 100644 cl/_testdefer/loop/out.txt create mode 100644 cl/_testdefer/multiret/in.go create mode 100644 cl/_testdefer/multiret/out.txt create mode 100644 cl/_testdefer/print/in.go create mode 100644 cl/_testdefer/print/out.txt create mode 100644 cl/_testdefer/singleret/in.go create mode 100644 cl/_testdefer/singleret/out.txt create mode 100644 cl/blocks/block.go create mode 100644 cl/blocks/block_test.go diff --git a/cl/_testdefer/loop/in.go b/cl/_testdefer/loop/in.go new file mode 100644 index 00000000..ebd8938e --- /dev/null +++ b/cl/_testdefer/loop/in.go @@ -0,0 +1,20 @@ +package main + +func f(s string) bool { + return len(s) > 2 +} + +func main() { + defer func() { + println("hi") + }() + for i := 0; i < 3; i++ { + if s := "hello"; f(s) { + defer println(s) + } else { + defer println("world") + return + } + } + defer println("bye") +} diff --git a/cl/_testdefer/loop/out.txt b/cl/_testdefer/loop/out.txt new file mode 100644 index 00000000..f8981ee0 --- /dev/null +++ b/cl/_testdefer/loop/out.txt @@ -0,0 +1,7 @@ +0: always +2: loop +4: loop +5: loop +3: cond +6: cond +1: cond diff --git a/cl/_testdefer/multiret/in.go b/cl/_testdefer/multiret/in.go new file mode 100644 index 00000000..82d34e31 --- /dev/null +++ b/cl/_testdefer/multiret/in.go @@ -0,0 +1,18 @@ +package main + +func f(s string) bool { + return len(s) > 2 +} + +func main() { + defer func() { + println("hi") + }() + if s := "hello"; f(s) { + defer println(s) + } else { + defer println("world") + return + } + defer println("bye") +} diff --git a/cl/_testdefer/multiret/out.txt b/cl/_testdefer/multiret/out.txt new file mode 100644 index 00000000..c47bbe4c --- /dev/null +++ b/cl/_testdefer/multiret/out.txt @@ -0,0 +1,4 @@ + 0: always + 1: cond + 2: cond + 3: cond diff --git a/cl/_testdefer/print/in.go b/cl/_testdefer/print/in.go new file mode 100644 index 00000000..c9726adc --- /dev/null +++ b/cl/_testdefer/print/in.go @@ -0,0 +1,52 @@ +package main + +func f() float64 { + return 1.0 +} + +func main() { + var v = f() + const n = 7 // digits printed + var buf [n + 7]byte + buf[0] = '+' + e := 0 // exp + if v == 0 { + if 1/v < 0 { + buf[0] = '-' + } + } else { + if v < 0 { + v = -v + buf[0] = '-' + } + + // normalize + for v >= 10 { + e++ + v /= 10 + } + for v < 1 { + e-- + v *= 10 + } + + // round + h := 5.0 + for i := 0; i < n; i++ { + h /= 10 + } + v += h + if v >= 10 { + e++ + v /= 10 + } + } + + // format +d.dddd+edd + for i := 0; i < n; i++ { + s := int(v) + buf[i+2] = byte(s + '0') + v -= float64(s) + v *= 10 + } +} diff --git a/cl/_testdefer/print/out.txt b/cl/_testdefer/print/out.txt new file mode 100644 index 00000000..e69de29b diff --git a/cl/_testdefer/singleret/in.go b/cl/_testdefer/singleret/in.go new file mode 100644 index 00000000..cd95da67 --- /dev/null +++ b/cl/_testdefer/singleret/in.go @@ -0,0 +1,17 @@ +package main + +func f(s string) bool { + return len(s) > 2 +} + +func main() { + defer func() { + println("hi") + }() + if s := "hello"; f(s) { + defer println(s) + } else { + defer println("world") + } + defer println("bye") +} diff --git a/cl/_testdefer/singleret/out.txt b/cl/_testdefer/singleret/out.txt new file mode 100644 index 00000000..530763ee --- /dev/null +++ b/cl/_testdefer/singleret/out.txt @@ -0,0 +1,5 @@ + 0: always + 1: cond + 2: cond + 4: cond + 3: always diff --git a/cl/blocks/block.go b/cl/blocks/block.go new file mode 100644 index 00000000..a617c612 --- /dev/null +++ b/cl/blocks/block.go @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blocks + +import ( + llssa "github.com/goplus/llgo/ssa" + "golang.org/x/tools/go/ssa" +) + +type Info struct { + Kind llssa.DoAction + Next int +} + +// ----------------------------------------------------------------------------- + +type blockState struct { + self *ssa.BasicBlock + preds int + succs []int + loop bool + always bool + fdel bool +} + +func (p *blockState) kind() llssa.DoAction { + if p.loop { + return llssa.DeferInLoop + } + if p.always { + return llssa.DeferAlways + } + return llssa.DeferInCond +} + +func newSuccs(succs []*ssa.BasicBlock) []int { + ret := make([]int, len(succs)) + for i, blk := range succs { + ret[i] = blk.Index + } + return ret +} + +func findLoop(states []*blockState, path []int, from, iblk int) []int { + path = append(path, iblk) + self := states[iblk] + for _, succ := range self.succs { + if states[succ].fdel { + continue + } + if succ == from { + for _, i := range path { + states[i].loop = true + } + return path + } + if ret := findLoop(states, path, from, succ); ret != nil { + return ret + } + } + return nil +} + +// https://en.wikipedia.org/wiki/Topological_sorting +func Infos(blks []*ssa.BasicBlock) []Info { + n := len(blks) + order := make([]int, 1, n+1) + order[0] = 0 + end, iend := 0, 0 + states := make([]*blockState, n) + for i, blk := range blks { + preds := len(blk.Preds) + if preds == 0 && i != 0 { + order = append(order, i) + } + if isEnd(blk) { + end++ + iend = i + } + states[i] = &blockState{ + self: blk, + preds: preds, + succs: newSuccs(blk.Succs), + } + } + + path := make([]int, 0, n) + if states[0].preds != 0 { + if loop := findLoop(states, path, 0, 0); len(loop) > 0 { + order = append(order, loop[1:]...) + } + } else { + states[0].always = true + } + if end == 1 { + states[iend].always = true + } + pos := 0 + +retry: + for pos < len(order) { + iblk := order[pos] + pos++ + state := states[iblk] + state.fdel = true + for _, succ := range state.succs { + s := states[succ] + if s.fdel { + continue + } + if s.preds--; s.preds == 0 { + order = append(order, succ) + } + } + } + if pos < n { + for iblk, state := range states { + if state.fdel { + continue + } + if loop := findLoop(states, path, iblk, iblk); len(loop) > 0 { + order = append(order, loop...) + goto retry + } + } + panic("unreachable") + } + order = append(order, -1) + ret := make([]Info, n) + for i := 0; i < n; i++ { + iblk := order[i] + ret[iblk] = Info{states[iblk].kind(), order[i+1]} + } + return ret +} + +func isEnd(blk *ssa.BasicBlock) bool { + // Note: skip recover block + return len(blk.Succs) == 0 && (len(blk.Preds) > 0 || blk.Index == 0) +} + +// ----------------------------------------------------------------------------- diff --git a/cl/blocks/block_test.go b/cl/blocks/block_test.go new file mode 100644 index 00000000..ee171acf --- /dev/null +++ b/cl/blocks/block_test.go @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blocks + +import ( + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/token" + "go/types" + "log" + "os" + "path" + "strings" + "testing" + + "github.com/goplus/gogen/packages" + "golang.org/x/tools/go/ssa" + "golang.org/x/tools/go/ssa/ssautil" + + llssa "github.com/goplus/llgo/ssa" +) + +func TestTestdefer(t *testing.T) { + // debug = true + fromDir(t, "loop", "../_testdefer") +} + +func fromDir(t *testing.T, sel, relDir string) { + dir, err := os.Getwd() + if err != nil { + t.Fatal("Getwd failed:", err) + } + dir = path.Join(dir, relDir) + fis, err := os.ReadDir(dir) + if err != nil { + t.Fatal("ReadDir failed:", err) + } + for _, fi := range fis { + name := fi.Name() + if !fi.IsDir() || strings.HasPrefix(name, "_") { + continue + } + t.Run(name, func(t *testing.T) { + testFrom(t, dir+"/"+name, sel) + }) + } +} + +func testFrom(t *testing.T, pkgDir, sel string) { + if sel != "" && !strings.Contains(pkgDir, sel) { + return + } + log.Println("Parsing", pkgDir) + in := pkgDir + "/in.go" + out := pkgDir + "/out.txt" + b, err := os.ReadFile(out) + if err != nil { + t.Fatal("ReadFile failed:", err) + } + expected := string(b) + testBlockInfo(t, nil, in, expected) +} + +func testBlockInfo(t *testing.T, src any, fname, expected string) { + t.Helper() + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, fname, src, parser.ParseComments) + if err != nil { + t.Fatal("ParseFile failed:", err) + } + files := []*ast.File{f} + name := f.Name.Name + pkg := types.NewPackage(name, name) + imp := packages.NewImporter(fset) + foo, _, err := ssautil.BuildPackage( + &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) + if err != nil { + t.Fatal("BuildPackage failed:", err) + } + foo.WriteTo(os.Stderr) + + for _, member := range foo.Members { + switch f := member.(type) { + case *ssa.Function: + if f.Name() == "main" { + f.WriteTo(os.Stderr) + infos := Infos(f.Blocks) + if v := resultOf(infos); v != expected { + t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) + } + return + } + } + } +} + +func resultOf(infos []Info) string { + var b bytes.Buffer + i := 0 + for { + fmt.Fprintf(&b, "%2d: %s\n", i, kinds[infos[i].Kind]) + if i = infos[i].Next; i < 0 { + break + } + } + return b.String() +} + +var kinds = [...]string{ + llssa.DeferAlways: "always", + llssa.DeferInCond: "cond", + llssa.DeferInLoop: "loop", +} From a226a70383d75a3c6dbfc5c254ee70c807213d47 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 5 Jun 2024 14:14:12 +0800 Subject: [PATCH 2/6] findLoop: mark fdel --- cl/_testdefer/loop/out.txt | 14 +++++++------- cl/blocks/block.go | 18 ++++++++++++++++-- cl/blocks/block_test.go | 2 +- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/cl/_testdefer/loop/out.txt b/cl/_testdefer/loop/out.txt index f8981ee0..e5dba5bf 100644 --- a/cl/_testdefer/loop/out.txt +++ b/cl/_testdefer/loop/out.txt @@ -1,7 +1,7 @@ -0: always -2: loop -4: loop -5: loop -3: cond -6: cond -1: cond + 0: always + 1: cond + 2: loop + 5: loop + 4: loop + 6: cond + 3: cond diff --git a/cl/blocks/block.go b/cl/blocks/block.go index a617c612..afd112b9 100644 --- a/cl/blocks/block.go +++ b/cl/blocks/block.go @@ -26,6 +26,8 @@ type Info struct { Next int } +// var debug = false + // ----------------------------------------------------------------------------- type blockState struct { @@ -62,9 +64,12 @@ func findLoop(states []*blockState, path []int, from, iblk int) []int { if states[succ].fdel { continue } - if succ == from { + if pos := find(path, succ); pos >= 0 { + path = path[pos:] for _, i := range path { - states[i].loop = true + s := states[i] + s.loop = true + s.fdel = true } return path } @@ -153,4 +158,13 @@ func isEnd(blk *ssa.BasicBlock) bool { return len(blk.Succs) == 0 && (len(blk.Preds) > 0 || blk.Index == 0) } +func find(path []int, fv int) int { + for i, v := range path { + if v == fv { + return i + } + } + return -1 +} + // ----------------------------------------------------------------------------- diff --git a/cl/blocks/block_test.go b/cl/blocks/block_test.go index ee171acf..d02c75a8 100644 --- a/cl/blocks/block_test.go +++ b/cl/blocks/block_test.go @@ -38,7 +38,7 @@ import ( func TestTestdefer(t *testing.T) { // debug = true - fromDir(t, "loop", "../_testdefer") + fromDir(t, "print", "../_testdefer") } func fromDir(t *testing.T, sel, relDir string) { From fd7d2765c8ef97435f060257271e0483c561150e Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 5 Jun 2024 15:02:11 +0800 Subject: [PATCH 3/6] findLoop: reach --- cl/_testdefer/loop/out.txt | 4 ++-- cl/_testdefer/print/out.txt | 18 ++++++++++++++++++ cl/blocks/block.go | 11 +++++++---- cl/blocks/block_test.go | 2 +- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/cl/_testdefer/loop/out.txt b/cl/_testdefer/loop/out.txt index e5dba5bf..ad86720d 100644 --- a/cl/_testdefer/loop/out.txt +++ b/cl/_testdefer/loop/out.txt @@ -1,7 +1,7 @@ 0: always 1: cond + 4: loop 2: loop 5: loop - 4: loop - 6: cond 3: cond + 6: cond diff --git a/cl/_testdefer/print/out.txt b/cl/_testdefer/print/out.txt index e69de29b..85787635 100644 --- a/cl/_testdefer/print/out.txt +++ b/cl/_testdefer/print/out.txt @@ -0,0 +1,18 @@ + 0: always + 1: cond + 3: cond + 4: cond + 5: cond + 7: loop + 6: loop +10: loop + 8: loop + 9: cond +13: loop +11: loop +12: cond +14: cond + 2: cond +17: loop +15: loop +16: always diff --git a/cl/blocks/block.go b/cl/blocks/block.go index afd112b9..21960751 100644 --- a/cl/blocks/block.go +++ b/cl/blocks/block.go @@ -26,8 +26,6 @@ type Info struct { Next int } -// var debug = false - // ----------------------------------------------------------------------------- type blockState struct { @@ -36,6 +34,7 @@ type blockState struct { succs []int loop bool always bool + reach bool fdel bool } @@ -65,7 +64,9 @@ func findLoop(states []*blockState, path []int, from, iblk int) []int { continue } if pos := find(path, succ); pos >= 0 { - path = path[pos:] + if pos > 0 { + continue + } for _, i := range path { s := states[i] s.loop = true @@ -129,12 +130,14 @@ retry: } if s.preds--; s.preds == 0 { order = append(order, succ) + } else { + s.reach = true } } } if pos < n { for iblk, state := range states { - if state.fdel { + if state.fdel || !state.reach { continue } if loop := findLoop(states, path, iblk, iblk); len(loop) > 0 { diff --git a/cl/blocks/block_test.go b/cl/blocks/block_test.go index d02c75a8..ba941fa7 100644 --- a/cl/blocks/block_test.go +++ b/cl/blocks/block_test.go @@ -38,7 +38,7 @@ import ( func TestTestdefer(t *testing.T) { // debug = true - fromDir(t, "print", "../_testdefer") + fromDir(t, "", "../_testdefer") } func fromDir(t *testing.T, sel, relDir string) { From fe548e580dd476cdeda8505e5153eb4b13189523 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 5 Jun 2024 15:08:05 +0800 Subject: [PATCH 4/6] use cl/blocks --- cl/blocks/block_test.go | 11 +++++++++++ cl/compile.go | 27 +++++---------------------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/cl/blocks/block_test.go b/cl/blocks/block_test.go index ba941fa7..2cad3c86 100644 --- a/cl/blocks/block_test.go +++ b/cl/blocks/block_test.go @@ -41,6 +41,17 @@ func TestTestdefer(t *testing.T) { fromDir(t, "", "../_testdefer") } +func TestFirstLoop(t *testing.T) { + blk := &ssa.BasicBlock{} + blk.Index = 0 + blk.Preds = []*ssa.BasicBlock{blk} + blk.Succs = []*ssa.BasicBlock{blk} + infos := Infos([]*ssa.BasicBlock{blk}) + if infos[0].Kind != llssa.DeferInLoop { + t.Fatal("TestFirstLoop") + } +} + func fromDir(t *testing.T, sel, relDir string) { dir, err := os.Getwd() if err != nil { diff --git a/cl/compile.go b/cl/compile.go index 199e10ba..469cd296 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -27,6 +27,7 @@ import ( "sort" "strings" + "github.com/goplus/llgo/cl/blocks" llssa "github.com/goplus/llgo/ssa" "golang.org/x/tools/go/ssa" ) @@ -149,7 +150,7 @@ type context struct { bvals map[ssa.Value]llssa.Expr // block values vargs map[*ssa.Alloc][]llssa.Expr // varargs - blkInfos []blockInfo + blkInfos []blocks.Info inits []func() phis []func() @@ -280,14 +281,14 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun for i, block := range f.Blocks { off[i] = p.compilePhis(b, block) } - p.blkInfos = blockInfos(f.Blocks) + p.blkInfos = blocks.Infos(f.Blocks) i := 0 for { block := f.Blocks[i] doMainInit := (i == 0 && name == "main") doModInit := (i == 1 && f.Name() == "init" && sig.Recv() == nil) p.compileBlock(b, block, off[i], doMainInit, doModInit) - if i = p.blkInfos[i].next; i < 0 { + if i = p.blkInfos[i].Next; i < 0 { break } } @@ -300,24 +301,6 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun return fn, nil, goFunc } -type blockInfo struct { - kind llssa.DoAction - next int -} - -func blockInfos(blks []*ssa.BasicBlock) []blockInfo { - n := len(blks) - infos := make([]blockInfo, n) - for i := range blks { - next := i + 1 - if next >= n { - next = -1 - } - infos[i] = blockInfo{kind: llssa.DeferInCond, next: next} - } - return infos -} - // funcOf returns a function by name and set ftype = goFunc, cFunc, etc. // or returns nil and set ftype = llgoCstr, llgoAlloca, llgoUnreachable, etc. func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObjRef, ftype int) { @@ -829,7 +812,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) { val := p.compileValue(b, v.Value) b.MapUpdate(m, key, val) case *ssa.Defer: - p.call(b, p.blkInfos[v.Block().Index].kind, &v.Call) + p.call(b, p.blkInfos[v.Block().Index].Kind, &v.Call) case *ssa.Go: p.call(b, llssa.Go, &v.Call) case *ssa.RunDefers: From b9d1d52ab35cc62c66784179f7cd464e357d37f0 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 5 Jun 2024 15:10:35 +0800 Subject: [PATCH 5/6] gentests --- cl/_testdata/print/out.ll | 4 +- cl/_testdata/utf8/out.ll | 4 +- cl/_testgo/defer/out.ll | 121 ++++++++++++++++-------------------- cl/_testgo/strucintf/out.ll | 20 +++--- 4 files changed, 69 insertions(+), 80 deletions(-) diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll index 9fadd77e..1744b3f4 100644 --- a/cl/_testdata/print/out.ll +++ b/cl/_testdata/print/out.ll @@ -191,7 +191,7 @@ _llgo_1: ; preds = %_llgo_3 call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %47) br label %_llgo_2 -_llgo_2: ; preds = %_llgo_3, %_llgo_1, %_llgo_0 +_llgo_2: ; preds = %_llgo_1, %_llgo_3, %_llgo_0 %48 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48) %49 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %48, i64 0 %50 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 @@ -1451,7 +1451,7 @@ _llgo_1: ; preds = %_llgo_3 %7 = icmp ult i64 %9, 10 br i1 %7, label %_llgo_2, label %_llgo_4 -_llgo_2: ; preds = %_llgo_3, %_llgo_1 +_llgo_2: ; preds = %_llgo_1, %_llgo_3 %8 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %10, i64 100, i64 100) call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %8) ret void diff --git a/cl/_testdata/utf8/out.ll b/cl/_testdata/utf8/out.ll index 964a3e9c..e24d991d 100644 --- a/cl/_testdata/utf8/out.ll +++ b/cl/_testdata/utf8/out.ll @@ -53,7 +53,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_3 %2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0 - store ptr @0, ptr %3, align 8 + store ptr @1, ptr %3, align 8 %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1 store i64 7, ptr %4, align 4 %5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8 @@ -79,7 +79,7 @@ _llgo_3: ; preds = %_llgo_1, %_llgo_0 %15 = phi i64 [ 0, %_llgo_0 ], [ %11, %_llgo_1 ] %16 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 0 - store ptr @1, ptr %17, align 8 + store ptr @0, ptr %17, align 8 %18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 1 store i64 7, ptr %18, align 4 %19 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8 diff --git a/cl/_testgo/defer/out.ll b/cl/_testgo/defer/out.ll index ebb35a1c..0a15d5ef 100644 --- a/cl/_testgo/defer/out.ll +++ b/cl/_testgo/defer/out.ll @@ -53,108 +53,97 @@ _llgo_0: call void @main.init() %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 3 - %11 = load i64, ptr %9, align 4 - %12 = or i64 %11, 1 - store i64 %12, ptr %9, align 4 - %13 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 0 - store ptr @0, ptr %14, align 8 - %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 1 - store i64 5, ptr %15, align 4 - %16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8 - %17 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %16) - br i1 %17, label %_llgo_2, label %_llgo_3 + %11 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %11, i32 0, i32 0 + store ptr @0, ptr %12, align 8 + %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %11, i32 0, i32 1 + store i64 5, ptr %13, align 4 + %14 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %11, align 8 + %15 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %14) + br i1 %15, label %_llgo_2, label %_llgo_3 _llgo_1: ; No predecessors! ret i32 0 _llgo_2: ; preds = %_llgo_0 - %18 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 0 - store ptr @1, ptr %19, align 8 - %20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 1 - store i64 5, ptr %20, align 4 - %21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %18, align 8 - %22 = load i64, ptr %9, align 4 - %23 = or i64 %22, 2 - store i64 %23, ptr %9, align 4 - %24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 0 - store ptr @2, ptr %25, align 8 - %26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 1 - store i64 3, ptr %26, align 4 - %27 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %24, align 8 - %28 = load i64, ptr %9, align 4 - %29 = or i64 %28, 4 - store i64 %29, ptr %9, align 4 + %16 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 0 + store ptr @1, ptr %17, align 8 + %18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 1 + store i64 5, ptr %18, align 4 + %19 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8 + %20 = load i64, ptr %9, align 4 + %21 = or i64 %20, 1 + store i64 %21, ptr %9, align 4 + %22 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 0 + store ptr @2, ptr %23, align 8 + %24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 1 + store i64 3, ptr %24, align 4 + %25 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %22, align 8 + %26 = load i64, ptr %9, align 4 + %27 = or i64 %26, 2 + store i64 %27, ptr %9, align 4 store i64 0, ptr %10, align 4 br label %_llgo_4 _llgo_3: ; preds = %_llgo_0 - %30 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 0 - store ptr @3, ptr %31, align 8 - %32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 1 - store i64 5, ptr %32, align 4 - %33 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %30, align 8 - %34 = load i64, ptr %9, align 4 - %35 = or i64 %34, 8 - store i64 %35, ptr %9, align 4 + %28 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %29 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %28, i32 0, i32 0 + store ptr @3, ptr %29, align 8 + %30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %28, i32 0, i32 1 + store i64 5, ptr %30, align 4 + %31 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %28, align 8 + %32 = load i64, ptr %9, align 4 + %33 = or i64 %32, 4 + store i64 %33, ptr %9, align 4 store i64 1, ptr %10, align 4 br label %_llgo_4 _llgo_4: ; preds = %_llgo_3, %_llgo_2 - %36 = load i64, ptr %9, align 4 - %37 = and i64 %36, 8 - %38 = icmp ne i64 %37, 0 - br i1 %38, label %_llgo_7, label %_llgo_8 + %34 = load i64, ptr %9, align 4 + %35 = and i64 %34, 4 + %36 = icmp ne i64 %35, 0 + br i1 %36, label %_llgo_7, label %_llgo_8 -_llgo_5: ; preds = %_llgo_14 +_llgo_5: ; preds = %_llgo_12 ret i32 0 -_llgo_6: ; preds = %_llgo_14 +_llgo_6: ; preds = %_llgo_12 ret i32 0 _llgo_7: ; preds = %_llgo_4 - call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %33) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %31) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) br label %_llgo_8 _llgo_8: ; preds = %_llgo_7, %_llgo_4 - %39 = and i64 %36, 4 - %40 = icmp ne i64 %39, 0 - br i1 %40, label %_llgo_9, label %_llgo_10 + %37 = and i64 %34, 2 + %38 = icmp ne i64 %37, 0 + br i1 %38, label %_llgo_9, label %_llgo_10 _llgo_9: ; preds = %_llgo_8 - call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %27) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %25) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) br label %_llgo_10 _llgo_10: ; preds = %_llgo_9, %_llgo_8 - %41 = and i64 %36, 2 - %42 = icmp ne i64 %41, 0 - br i1 %42, label %_llgo_11, label %_llgo_12 + %39 = and i64 %34, 1 + %40 = icmp ne i64 %39, 0 + br i1 %40, label %_llgo_11, label %_llgo_12 _llgo_11: ; preds = %_llgo_10 - call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %21) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %19) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) br label %_llgo_12 _llgo_12: ; preds = %_llgo_11, %_llgo_10 - %43 = and i64 %36, 1 - %44 = icmp ne i64 %43, 0 - br i1 %44, label %_llgo_13, label %_llgo_14 - -_llgo_13: ; preds = %_llgo_12 call void @"main.main$1"() - br label %_llgo_14 - -_llgo_14: ; preds = %_llgo_13, %_llgo_12 - %45 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, align 8 - %46 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %45, 2 - %47 = call i32 @pthread_setspecific(ptr %2, ptr %46) - %48 = load i64, ptr %10, align 4 - switch i64 %48, label %_llgo_5 [ + %41 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, align 8 + %42 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %41, 2 + %43 = call i32 @pthread_setspecific(ptr %2, ptr %42) + %44 = load i64, ptr %10, align 4 + switch i64 %44, label %_llgo_5 [ i64 1, label %_llgo_6 ] } diff --git a/cl/_testgo/strucintf/out.ll b/cl/_testgo/strucintf/out.ll index fada9257..131b5bb5 100644 --- a/cl/_testgo/strucintf/out.ll +++ b/cl/_testgo/strucintf/out.ll @@ -15,11 +15,11 @@ source_filename = "main" @2 = private unnamed_addr constant [5 x i8] c"main\00", align 1 @__llgo_argc = global ptr null @__llgo_argv = global ptr null +@3 = private unnamed_addr constant [12 x i8] c"Foo: not ok\00", align 1 @"_llgo_struct$K-dZ9QotZfVPz2a0YdRa9vmZUuDXPTqZOlMShKEDJtk" = linkonce global ptr null -@3 = private unnamed_addr constant [2 x i8] c"V\00", align 1 -@4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 -@5 = private unnamed_addr constant [5 x i8] c"main\00", align 1 -@6 = private unnamed_addr constant [12 x i8] c"Foo: not ok\00", align 1 +@4 = private unnamed_addr constant [2 x i8] c"V\00", align 1 +@5 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@6 = private unnamed_addr constant [5 x i8] c"main\00", align 1 @7 = private unnamed_addr constant [12 x i8] c"Bar: not ok\00", align 1 @8 = private unnamed_addr constant [10 x i8] c"F: not ok\00", align 1 @@ -94,7 +94,7 @@ _llgo_2: ; preds = %_llgo_3, %_llgo_1 _llgo_3: ; preds = %_llgo_12 %16 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 0 - store ptr @6, ptr %17, align 8 + store ptr @3, ptr %17, align 8 %18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 1 store i64 11, ptr %18, align 4 %19 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8 @@ -299,20 +299,20 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 _llgo_3: ; preds = %_llgo_2 %28 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %29 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %28, i32 0, i32 0 - store ptr @3, ptr %29, align 8 + store ptr @4, ptr %29, align 8 %30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %28, i32 0, i32 1 store i64 1, ptr %30, align 4 %31 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %28, align 8 %32 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %32, i32 0, i32 0 - store ptr @4, ptr %33, align 8 + store ptr @5, ptr %33, align 8 %34 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %32, i32 0, i32 1 store i64 0, ptr %34, align 4 %35 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %32, align 8 %36 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %31, ptr %25, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %35, i1 false) %37 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %38 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %37, i32 0, i32 0 - store ptr @5, ptr %38, align 8 + store ptr @6, ptr %38, align 8 %39 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %37, i32 0, i32 1 store i64 4, ptr %39, align 4 %40 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %37, align 8 @@ -351,8 +351,8 @@ declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) -declare %"github.com/goplus/llgo/internal/runtime.eface" @"github.com/goplus/llgo/cl/internal/foo.Bar"() - declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String") +declare %"github.com/goplus/llgo/internal/runtime.eface" @"github.com/goplus/llgo/cl/internal/foo.Bar"() + declare %"github.com/goplus/llgo/internal/runtime.eface" @"github.com/goplus/llgo/cl/internal/foo.F"() From 11b4de63ee86da0ce67332ffe8b569e21a3c5d5e Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 5 Jun 2024 15:14:34 +0800 Subject: [PATCH 6/6] llgo_autogen.lla --- c/sqlite/llgo_autogen.lla | Bin 850 -> 850 bytes internal/abi/llgo_autogen.lla | Bin 3631 -> 3631 bytes internal/runtime/llgo_autogen.lla | Bin 13092 -> 13082 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/c/sqlite/llgo_autogen.lla b/c/sqlite/llgo_autogen.lla index 4672bbad117371310a588d00910e30502db68dc4..93b7c3ad89c466cb889cea4ee81c084e1de2f389 100644 GIT binary patch delta 49 zcmcb_c8QHQz?+#xgn@y9gW*`^(TTjO?9KuSX)Xc@8!dM+F$0Are`7Lc28vDAVO9eG DPVf#O delta 49 zcmcb_c8QHQz?+#xgn@y9gFz_m$V6UM_QiAJ(w5GN+i1Cqi5Vy~`5TilGf-@@4zn5n DTWb$b diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index eb0833a52b935b58b9da512baaa15a58ea7d1dec..55b792624dca0ee630e76101c83d9f5f5dd0bb6e 100644 GIT binary patch delta 49 zcmZ24vtEWbz?+#xgn@y9gJF5)(TTjO?3@A#Y1{${8!e~vG6RJsU*>0~q(z2GtY_y!t%M28ne3{pn87MZHlTQr* DRmKk9 diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index bd50b82b8dddce78e909b9445a58ac7950ef2085..f66c4e86e50a1b106af492f9408d82e2308c39ab 100644 GIT binary patch delta 7250 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 delta 7260 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