compiler: use config struct for options

Этот коммит содержится в:
Ayke van Laethem 2018-09-24 14:18:50 +02:00
родитель ddd4a39cb8
коммит 8a468786df
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
2 изменённых файлов: 47 добавлений и 27 удалений

Просмотреть файл

@ -28,10 +28,17 @@ func init() {
llvm.InitializeAllAsmPrinters() 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 { type Compiler struct {
dumpSSA bool Config
debug bool
triple string
mod llvm.Module mod llvm.Module
ctx llvm.Context ctx llvm.Context
builder llvm.Builder builder llvm.Builder
@ -75,24 +82,28 @@ type Phi struct {
llvm llvm.Value 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{ c := &Compiler{
dumpSSA: dumpSSA, Config: config,
debug: true, // TODO: make configurable
triple: triple,
difiles: make(map[string]llvm.Metadata), difiles: make(map[string]llvm.Metadata),
ditypes: 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 { if err != nil {
return nil, err 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.targetData = c.machine.CreateTargetData()
c.mod = llvm.NewModule(pkgName) c.mod = llvm.NewModule(pkgName)
c.mod.SetTarget(triple) c.mod.SetTarget(config.Triple)
c.mod.SetDataLayout(c.targetData.String()) c.mod.SetDataLayout(c.targetData.String())
c.ctx = c.mod.Context() c.ctx = c.mod.Context()
c.builder = c.ctx.NewBuilder() c.builder = c.ctx.NewBuilder()
@ -134,8 +145,8 @@ func (c *Compiler) Module() llvm.Module {
return c.mod return c.mod
} }
func (c *Compiler) Parse(mainPath, sourceDir string, buildTags []string) error { func (c *Compiler) Parse(mainPath string) error {
tripleSplit := strings.Split(c.triple, "-") tripleSplit := strings.Split(c.Triple, "-")
config := loader.Config{ config := loader.Config{
TypeChecker: types.Config{ TypeChecker: types.Config{
@ -148,12 +159,12 @@ func (c *Compiler) Parse(mainPath, sourceDir string, buildTags []string) error {
Build: &build.Context{ Build: &build.Context{
GOARCH: tripleSplit[0], GOARCH: tripleSplit[0],
GOOS: tripleSplit[2], GOOS: tripleSplit[2],
GOROOT: sourceDir, GOROOT: c.RootDir,
GOPATH: runtime.GOROOT(), GOPATH: runtime.GOROOT(),
CgoEnabled: true, CgoEnabled: true,
UseAllFiles: false, UseAllFiles: false,
Compiler: "gc", // must be one of the recognized compilers Compiler: "gc", // must be one of the recognized compilers
BuildTags: append([]string{"tgo"}, buildTags...), BuildTags: append([]string{"tgo"}, c.BuildTags...),
}, },
ParserMode: parser.ParseComments, ParserMode: parser.ParseComments,
AllowErrors: true, AllowErrors: true,
@ -303,7 +314,7 @@ func (c *Compiler) Parse(mainPath, sourceDir string, buildTags []string) error {
// continues at runtime). // continues at runtime).
// This should only happen when it hits a function call or the end // This should only happen when it hits a function call or the end
// of the block, ideally. // 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 { if err != nil {
return err return err
} }
@ -835,7 +846,7 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) {
frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType) 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. // Create debug info file if needed.
pos := c.ir.Program.Fset.Position(f.Syntax().Pos()) pos := c.ir.Program.Fset.Position(f.Syntax().Pos())
if _, ok := c.difiles[pos.Filename]; !ok { 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 { func (c *Compiler) parseFunc(frame *Frame) error {
if c.dumpSSA { if c.DumpSSA {
fmt.Printf("\nfunc %s:\n", frame.fn.Function) fmt.Printf("\nfunc %s:\n", frame.fn.Function)
} }
if !frame.fn.IsExported() { if !frame.fn.IsExported() {
frame.fn.LLVMFn.SetLinkage(llvm.InternalLinkage) frame.fn.LLVMFn.SetLinkage(llvm.InternalLinkage)
} }
if c.debug { if c.Debug {
pos := c.ir.Program.Fset.Position(frame.fn.Pos()) pos := c.ir.Program.Fset.Position(frame.fn.Pos())
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{}) 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) frame.locals[param] = c.collapseFormalParam(llvmType, fields)
// Add debug information to this parameter (if available) // 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()) pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos())
dityp, err := c.getDIType(param.Type()) dityp, err := c.getDIType(param.Type())
if err != nil { if err != nil {
@ -1311,7 +1322,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
// Fill blocks with instructions. // Fill blocks with instructions.
for _, block := range frame.fn.DomPreorder() { for _, block := range frame.fn.DomPreorder() {
if c.dumpSSA { if c.DumpSSA {
fmt.Printf("%s:\n", block.Comment) fmt.Printf("%s:\n", block.Comment)
} }
c.builder.SetInsertPointAtEnd(frame.blocks[block]) c.builder.SetInsertPointAtEnd(frame.blocks[block])
@ -1320,7 +1331,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
if _, ok := instr.(*ssa.DebugRef); ok { if _, ok := instr.(*ssa.DebugRef); ok {
continue continue
} }
if c.dumpSSA { if c.DumpSSA {
if val, ok := instr.(ssa.Value); ok && val.Name() != "" { if val, ok := instr.(ssa.Value); ok && val.Name() != "" {
fmt.Printf("\t%s = %s\n", val.Name(), val.String()) fmt.Printf("\t%s = %s\n", val.Name(), val.String())
} else { } else {
@ -1354,7 +1365,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
} }
func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) 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()) pos := c.ir.Program.Fset.Position(instr.Pos())
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{}) c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
} }

19
main.go
Просмотреть файл

@ -9,7 +9,6 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"github.com/aykevl/llvm/bindings/go/llvm" "github.com/aykevl/llvm/bindings/go/llvm"
@ -18,7 +17,14 @@ import (
// Helper function for Compiler object. // Helper function for Compiler object.
func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA bool, printSizes string, action func(string) error) error { 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 { if err != nil {
return err return err
} }
@ -32,7 +38,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA bool, p
fmt.Println(c.IR()) fmt.Println(c.IR())
}() }()
} }
return c.Parse(pkgName, sourceDir(), spec.BuildTags) return c.Parse(pkgName)
}() }()
if parseErr != nil { if parseErr != nil {
return parseErr 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). // Run the specified package directly (using JIT or interpretation).
func Run(pkgName string) error { 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 { if err != nil {
return errors.New("compiler: " + err.Error()) return errors.New("compiler: " + err.Error())
} }
err = c.Parse(pkgName, sourceDir(), []string{runtime.GOOS, runtime.GOARCH}) err = c.Parse(pkgName)
if err != nil { if err != nil {
return errors.New("compiler: " + err.Error()) return errors.New("compiler: " + err.Error())
} }