compiler: use config struct for options
Этот коммит содержится в:
родитель
ddd4a39cb8
коммит
8a468786df
2 изменённых файлов: 47 добавлений и 27 удалений
|
@ -28,10 +28,17 @@ func init() {
|
|||
llvm.InitializeAllAsmPrinters()
|
||||
}
|
||||
|
||||
// Configure the compiler.
|
||||
type Config struct {
|
||||
Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default)
|
||||
DumpSSA bool // dump Go SSA, for compiler debugging
|
||||
Debug bool // add debug symbols for gdb
|
||||
RootDir string // GOROOT for TinyGo
|
||||
BuildTags []string // build tags for TinyGo (empty means {runtime.GOOS/runtime.GOARCH})
|
||||
}
|
||||
|
||||
type Compiler struct {
|
||||
dumpSSA bool
|
||||
debug bool
|
||||
triple string
|
||||
Config
|
||||
mod llvm.Module
|
||||
ctx llvm.Context
|
||||
builder llvm.Builder
|
||||
|
@ -75,24 +82,28 @@ type Phi struct {
|
|||
llvm llvm.Value
|
||||
}
|
||||
|
||||
func NewCompiler(pkgName, triple string, dumpSSA bool) (*Compiler, error) {
|
||||
func NewCompiler(pkgName string, config Config) (*Compiler, error) {
|
||||
if config.Triple == "" {
|
||||
config.Triple = llvm.DefaultTargetTriple()
|
||||
}
|
||||
if len(config.BuildTags) == 0 {
|
||||
config.BuildTags = []string{runtime.GOOS, runtime.GOARCH}
|
||||
}
|
||||
c := &Compiler{
|
||||
dumpSSA: dumpSSA,
|
||||
debug: true, // TODO: make configurable
|
||||
triple: triple,
|
||||
Config: config,
|
||||
difiles: make(map[string]llvm.Metadata),
|
||||
ditypes: make(map[string]llvm.Metadata),
|
||||
}
|
||||
|
||||
target, err := llvm.GetTargetFromTriple(triple)
|
||||
target, err := llvm.GetTargetFromTriple(config.Triple)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.machine = target.CreateTargetMachine(triple, "", "", llvm.CodeGenLevelDefault, llvm.RelocStatic, llvm.CodeModelDefault)
|
||||
c.machine = target.CreateTargetMachine(config.Triple, "", "", llvm.CodeGenLevelDefault, llvm.RelocStatic, llvm.CodeModelDefault)
|
||||
c.targetData = c.machine.CreateTargetData()
|
||||
|
||||
c.mod = llvm.NewModule(pkgName)
|
||||
c.mod.SetTarget(triple)
|
||||
c.mod.SetTarget(config.Triple)
|
||||
c.mod.SetDataLayout(c.targetData.String())
|
||||
c.ctx = c.mod.Context()
|
||||
c.builder = c.ctx.NewBuilder()
|
||||
|
@ -134,8 +145,8 @@ func (c *Compiler) Module() llvm.Module {
|
|||
return c.mod
|
||||
}
|
||||
|
||||
func (c *Compiler) Parse(mainPath, sourceDir string, buildTags []string) error {
|
||||
tripleSplit := strings.Split(c.triple, "-")
|
||||
func (c *Compiler) Parse(mainPath string) error {
|
||||
tripleSplit := strings.Split(c.Triple, "-")
|
||||
|
||||
config := loader.Config{
|
||||
TypeChecker: types.Config{
|
||||
|
@ -148,12 +159,12 @@ func (c *Compiler) Parse(mainPath, sourceDir string, buildTags []string) error {
|
|||
Build: &build.Context{
|
||||
GOARCH: tripleSplit[0],
|
||||
GOOS: tripleSplit[2],
|
||||
GOROOT: sourceDir,
|
||||
GOROOT: c.RootDir,
|
||||
GOPATH: runtime.GOROOT(),
|
||||
CgoEnabled: true,
|
||||
UseAllFiles: false,
|
||||
Compiler: "gc", // must be one of the recognized compilers
|
||||
BuildTags: append([]string{"tgo"}, buildTags...),
|
||||
BuildTags: append([]string{"tgo"}, c.BuildTags...),
|
||||
},
|
||||
ParserMode: parser.ParseComments,
|
||||
AllowErrors: true,
|
||||
|
@ -303,7 +314,7 @@ func (c *Compiler) Parse(mainPath, sourceDir string, buildTags []string) error {
|
|||
// continues at runtime).
|
||||
// This should only happen when it hits a function call or the end
|
||||
// of the block, ideally.
|
||||
err := c.ir.Interpret(frame.fn.Blocks[0], c.dumpSSA)
|
||||
err := c.ir.Interpret(frame.fn.Blocks[0], c.DumpSSA)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -835,7 +846,7 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) {
|
|||
frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType)
|
||||
}
|
||||
|
||||
if c.debug && f.Syntax() != nil && len(f.Blocks) != 0 {
|
||||
if c.Debug && f.Syntax() != nil && len(f.Blocks) != 0 {
|
||||
// Create debug info file if needed.
|
||||
pos := c.ir.Program.Fset.Position(f.Syntax().Pos())
|
||||
if _, ok := c.difiles[pos.Filename]; !ok {
|
||||
|
@ -1165,14 +1176,14 @@ func (c *Compiler) getInterpretedValue(prefix string, value ir.Value) (llvm.Valu
|
|||
}
|
||||
|
||||
func (c *Compiler) parseFunc(frame *Frame) error {
|
||||
if c.dumpSSA {
|
||||
if c.DumpSSA {
|
||||
fmt.Printf("\nfunc %s:\n", frame.fn.Function)
|
||||
}
|
||||
if !frame.fn.IsExported() {
|
||||
frame.fn.LLVMFn.SetLinkage(llvm.InternalLinkage)
|
||||
}
|
||||
|
||||
if c.debug {
|
||||
if c.Debug {
|
||||
pos := c.ir.Program.Fset.Position(frame.fn.Pos())
|
||||
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
|
||||
}
|
||||
|
@ -1204,7 +1215,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
|
|||
frame.locals[param] = c.collapseFormalParam(llvmType, fields)
|
||||
|
||||
// Add debug information to this parameter (if available)
|
||||
if c.debug && frame.fn.Syntax() != nil {
|
||||
if c.Debug && frame.fn.Syntax() != nil {
|
||||
pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos())
|
||||
dityp, err := c.getDIType(param.Type())
|
||||
if err != nil {
|
||||
|
@ -1311,7 +1322,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
|
|||
|
||||
// Fill blocks with instructions.
|
||||
for _, block := range frame.fn.DomPreorder() {
|
||||
if c.dumpSSA {
|
||||
if c.DumpSSA {
|
||||
fmt.Printf("%s:\n", block.Comment)
|
||||
}
|
||||
c.builder.SetInsertPointAtEnd(frame.blocks[block])
|
||||
|
@ -1320,7 +1331,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
|
|||
if _, ok := instr.(*ssa.DebugRef); ok {
|
||||
continue
|
||||
}
|
||||
if c.dumpSSA {
|
||||
if c.DumpSSA {
|
||||
if val, ok := instr.(ssa.Value); ok && val.Name() != "" {
|
||||
fmt.Printf("\t%s = %s\n", val.Name(), val.String())
|
||||
} else {
|
||||
|
@ -1354,7 +1365,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
|
|||
}
|
||||
|
||||
func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
|
||||
if c.debug {
|
||||
if c.Debug {
|
||||
pos := c.ir.Program.Fset.Position(instr.Pos())
|
||||
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
|
||||
}
|
||||
|
|
19
main.go
19
main.go
|
@ -9,7 +9,6 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/aykevl/llvm/bindings/go/llvm"
|
||||
|
@ -18,7 +17,14 @@ import (
|
|||
|
||||
// Helper function for Compiler object.
|
||||
func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA bool, printSizes string, action func(string) error) error {
|
||||
c, err := compiler.NewCompiler(pkgName, spec.Triple, dumpSSA)
|
||||
config := compiler.Config{
|
||||
Triple: spec.Triple,
|
||||
Debug: true, // TODO: make configurable
|
||||
DumpSSA: dumpSSA,
|
||||
RootDir: sourceDir(),
|
||||
BuildTags: spec.BuildTags,
|
||||
}
|
||||
c, err := compiler.NewCompiler(pkgName, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -32,7 +38,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA bool, p
|
|||
fmt.Println(c.IR())
|
||||
}()
|
||||
}
|
||||
return c.Parse(pkgName, sourceDir(), spec.BuildTags)
|
||||
return c.Parse(pkgName)
|
||||
}()
|
||||
if parseErr != nil {
|
||||
return parseErr
|
||||
|
@ -190,11 +196,14 @@ func Flash(pkgName, target, port string, printIR, dumpSSA bool, printSizes strin
|
|||
|
||||
// Run the specified package directly (using JIT or interpretation).
|
||||
func Run(pkgName string) error {
|
||||
c, err := compiler.NewCompiler(pkgName, llvm.DefaultTargetTriple(), false)
|
||||
config := compiler.Config{
|
||||
RootDir: sourceDir(),
|
||||
}
|
||||
c, err := compiler.NewCompiler(pkgName, config)
|
||||
if err != nil {
|
||||
return errors.New("compiler: " + err.Error())
|
||||
}
|
||||
err = c.Parse(pkgName, sourceDir(), []string{runtime.GOOS, runtime.GOARCH})
|
||||
err = c.Parse(pkgName)
|
||||
if err != nil {
|
||||
return errors.New("compiler: " + err.Error())
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче