This commit is contained in:
xushiwei
2024-04-21 16:04:05 +08:00
parent c1cc078772
commit 7cab76f444
4 changed files with 120 additions and 16 deletions

79
chore/llgen/llgen.go Normal file
View File

@@ -0,0 +1,79 @@
/*
* 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 main
import (
"fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"os"
"path/filepath"
"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 main() {
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Usage: llgen xxx.go")
return
}
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)
outFile := dir + "out.ll"
err = os.WriteFile(outFile, []byte(ret.String()), 0644)
check(err)
}
func check(err error) {
if err != nil {
panic(err)
}
}

View File

@@ -18,13 +18,30 @@ package cl
import ( import (
"fmt" "fmt"
"log"
"sort" "sort"
llssa "github.com/goplus/llgo/ssa" llssa "github.com/goplus/llgo/ssa"
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
) )
type Config struct { // -----------------------------------------------------------------------------
type dbgFlags = int
const (
DbgFlagInstruction dbgFlags = 1 << iota
DbgFlagAll = DbgFlagInstruction
)
var (
debugInstr bool
)
// SetDebug sets debug flags.
func SetDebug(dbgFlags dbgFlags) {
debugInstr = (dbgFlags & DbgFlagInstruction) != 0
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -48,12 +65,20 @@ func (p *context) compileType(pkg llssa.Package, member *ssa.Type) {
// Global variable. // Global variable.
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) { func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
g := pkg.NewVar(gbl.Name(), gbl.Type()) name, typ := gbl.Name(), gbl.Type()
if debugInstr {
log.Println("==> NewVar", name, typ)
}
g := pkg.NewVar(name, typ)
g.Init(p.prog.Null(g.Type)) g.Init(p.prog.Null(g.Type))
} }
func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) { func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) {
fn := pkg.NewFunc(f.Name(), f.Signature) name := f.Name()
if debugInstr {
log.Println("==> NewFunc", name)
}
fn := pkg.NewFunc(name, f.Signature)
p.inits = append(p.inits, func() { p.inits = append(p.inits, func() {
p.fn = fn p.fn = fn
defer func() { defer func() {
@@ -63,6 +88,9 @@ func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) {
if nblk == 0 { // external function if nblk == 0 { // external function
return return
} }
if debugInstr {
log.Println("==> FuncBody", name)
}
fn.MakeBlocks(nblk) fn.MakeBlocks(nblk)
b := fn.NewBuilder() b := fn.NewBuilder()
for _, block := range f.Blocks { for _, block := range f.Blocks {
@@ -87,12 +115,10 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
} }
switch v := iv.(type) { switch v := iv.(type) {
case *ssa.Call: case *ssa.Call:
if false {
call := v.Call call := v.Call
fn := p.compileValue(b, call.Value) fn := p.compileValue(b, call.Value)
args := p.compileValues(b, call.Args) args := p.compileValues(b, call.Args)
ret = b.Call(fn, args...) ret = b.Call(fn, args...)
}
case *ssa.BinOp: case *ssa.BinOp:
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
y := p.compileValue(b, v.Y) y := p.compileValue(b, v.Y)
@@ -185,6 +211,9 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value) []llssa.Expr
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
type Config struct {
}
// NewPackage compiles a Go package to LLVM IR package. // NewPackage compiles a Go package to LLVM IR package.
func NewPackage(prog llssa.Program, pkg *ssa.Package, conf *Config) (ret llssa.Package, err error) { func NewPackage(prog llssa.Program, pkg *ssa.Package, conf *Config) (ret llssa.Package, err error) {
type namedMember struct { type namedMember struct {

View File

@@ -38,6 +38,7 @@ func TestFromTestdata(t *testing.T) {
} }
func init() { func init() {
SetDebug(DbgFlagAll)
llssa.Initialize(llssa.InitAll) llssa.Initialize(llssa.InitAll)
llssa.SetDebug(llssa.DbgFlagAll) llssa.SetDebug(llssa.DbgFlagAll)
} }

View File

@@ -19,12 +19,13 @@ package ssa
import ( import (
"go/constant" "go/constant"
"go/types" "go/types"
"log"
"github.com/goplus/llvm" "github.com/goplus/llvm"
"golang.org/x/tools/go/types/typeutil" "golang.org/x/tools/go/types/typeutil"
) )
// -----------------------------------------------------------------------------
type dbgFlags = int type dbgFlags = int
const ( const (
@@ -192,9 +193,6 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst {
// NewVar creates a new global variable. // NewVar creates a new global variable.
func (p Package) NewVar(name string, typ types.Type) Global { func (p Package) NewVar(name string, typ types.Type) Global {
if debugInstr {
log.Println("==> NewVar", name, typ)
}
t := p.prog.Type(typ) t := p.prog.Type(typ)
gbl := llvm.AddGlobal(p.mod, t.ll, name) gbl := llvm.AddGlobal(p.mod, t.ll, name)
ret := &aGlobal{Expr{gbl, t}} ret := &aGlobal{Expr{gbl, t}}
@@ -204,9 +202,6 @@ func (p Package) NewVar(name string, typ types.Type) Global {
// NewFunc creates a new function. // NewFunc creates a new function.
func (p Package) NewFunc(name string, sig *types.Signature) Function { func (p Package) NewFunc(name string, sig *types.Signature) Function {
if debugInstr {
log.Println("==> NewFunc", name)
}
t := p.prog.llvmSignature(sig) t := p.prog.llvmSignature(sig)
fn := llvm.AddFunction(p.mod, name, t.ll) fn := llvm.AddFunction(p.mod, name, t.ll)
ret := newFunction(fn, t, p.prog) ret := newFunction(fn, t, p.prog)