llgo/x/llgen

This commit is contained in:
xushiwei
2024-04-22 00:03:49 +08:00
parent 7ffedc2da7
commit 0b7713dbdb
7 changed files with 90 additions and 45 deletions

1
.gitignore vendored
View File

@@ -15,6 +15,7 @@ _tinygo/
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out
*.swp
# Dependency directories (remove the comment below to include it) # Dependency directories (remove the comment below to include it)
# vendor/ # vendor/

View File

@@ -18,19 +18,10 @@ package main
import ( import (
"fmt" "fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"os" "os"
"path/filepath" "path/filepath"
"github.com/goplus/llgo/cl" "github.com/goplus/llgo/x/llgen"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
llssa "github.com/goplus/llgo/ssa"
) )
func main() { func main() {
@@ -40,40 +31,10 @@ func main() {
} }
inFile := os.Args[1] inFile := os.Args[1]
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, inFile, nil, parser.ParseComments)
check(err)
files := []*ast.File{f}
name := f.Name.Name
pkg := types.NewPackage(name, name)
foo, _, err := ssautil.BuildPackage(
&types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)
check(err)
foo.WriteTo(os.Stderr)
for _, m := range foo.Members {
if f, ok := m.(*ssa.Function); ok {
f.WriteTo(os.Stderr)
}
}
llssa.Initialize(llssa.InitAll)
llssa.SetDebug(llssa.DbgFlagAll)
cl.SetDebug(cl.DbgFlagAll)
prog := llssa.NewProgram(nil)
ret, err := cl.NewPackage(prog, foo, nil)
check(err)
dir, _ := filepath.Split(inFile) dir, _ := filepath.Split(inFile)
outFile := dir + "out.ll" outFile := dir + "out.ll"
err = os.WriteFile(outFile, []byte(ret.String()), 0644)
check(err)
}
func check(err error) { llgen.Init()
if err != nil { llgen.Do(inFile, outFile)
panic(err)
}
} }

View File

@@ -30,6 +30,7 @@ _llgo_2: ; preds = %_llgo_0
define void @main() { define void @main() {
_llgo_0: _llgo_0:
call void @init()
%0 = call i64 @max(i64 1, i64 2) %0 = call i64 @max(i64 1, i64 2)
ret void ret void
} }

View File

@@ -28,6 +28,7 @@ declare void @printf(ptr, ...)
define void @main() { define void @main() {
_llgo_0: _llgo_0:
call void @init()
call void (ptr, ...) @printf(ptr @hello) call void (ptr, ...) @printf(ptr @hello)
ret void ret void
} }

View File

@@ -20,6 +20,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
define void @main() { define void @main() {
_llgo_0: _llgo_0:
call void @init()
%0 = load i64, ptr @a, align 4 %0 = load i64, ptr @a, align 4
%1 = add i64 %0, 1 %1 = add i64 %0, 1
store i64 %1, ptr @a, align 4 store i64 %1, ptr @a, align 4

View File

@@ -73,6 +73,10 @@ func funcKind(vfn ssa.Value) int {
return fnNormal return fnNormal
} }
func isMainFunc(fn *ssa.Function) bool {
return fn.Name() == "main" && fn.Pkg.Pkg.Path() == "main"
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
type instrAndValue interface { type instrAndValue interface {
@@ -126,16 +130,21 @@ func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) {
} }
fn.MakeBlocks(nblk) fn.MakeBlocks(nblk)
b := fn.NewBuilder() b := fn.NewBuilder()
for _, block := range f.Blocks { isMain := isMainFunc(f)
p.compileBlock(b, block) for i, block := range f.Blocks {
p.compileBlock(b, block, isMain && i == 0)
} }
}) })
} }
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock) llssa.BasicBlock { func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, doInit bool) llssa.BasicBlock {
ret := p.fn.Block(block.Index) ret := p.fn.Block(block.Index)
b.SetBlock(ret) b.SetBlock(ret)
p.bvals = make(map[ssa.Value]llssa.Expr) p.bvals = make(map[ssa.Value]llssa.Expr)
if doInit {
fn := p.pkg.FuncOf("init")
b.Call(fn.Expr)
}
for _, instr := range block.Instrs { for _, instr := range block.Instrs {
p.compileInstr(b, instr) p.compileInstr(b, instr)
} }

71
x/llgen/llgen.go Normal file
View File

@@ -0,0 +1,71 @@
/*
* 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 llgen
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"os"
"github.com/goplus/llgo/cl"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
llssa "github.com/goplus/llgo/ssa"
)
func Init() {
llssa.Initialize(llssa.InitAll)
llssa.SetDebug(llssa.DbgFlagAll)
cl.SetDebug(cl.DbgFlagAll)
}
func Do(inFile, outFile string) {
ret := Gen(inFile, nil)
err := os.WriteFile(outFile, []byte(ret), 0644)
check(err)
}
func Gen(inFile string, src any) string {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, inFile, src, parser.ParseComments)
check(err)
files := []*ast.File{f}
name := f.Name.Name
pkg := types.NewPackage(name, name)
ssaPkg, _, err := ssautil.BuildPackage(
&types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)
check(err)
ssaPkg.WriteTo(os.Stderr)
prog := llssa.NewProgram(nil)
ret, err := cl.NewPackage(prog, ssaPkg, nil)
check(err)
return ret.String()
}
func check(err error) {
if err != nil {
panic(err)
}
}