Break fsplc Compiler type into a different file
This commit is contained in:
parent
4895f09f99
commit
2bc5eb1f49
105
cmd/fsplc/compiler.go
Normal file
105
cmd/fsplc/compiler.go
Normal file
@ -0,0 +1,105 @@
|
||||
package main
|
||||
|
||||
import "os"
|
||||
import "fmt"
|
||||
import "errors"
|
||||
import "strings"
|
||||
import "os/exec"
|
||||
import "path/filepath"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/llvm"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/lexer"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/parser"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/generator/native"
|
||||
|
||||
type Compiler struct {
|
||||
Output string
|
||||
Optimization int
|
||||
}
|
||||
|
||||
func (this *Compiler) Compile (inputs []string) error {
|
||||
if len(inputs) == 0 {
|
||||
return errors.New("no input files specified")
|
||||
}
|
||||
|
||||
var syntaxTree parser.Tree
|
||||
for _, name := range inputs {
|
||||
lx, err := lexer.LexFile(name)
|
||||
if err != nil { return err }
|
||||
err = syntaxTree.Parse(lx)
|
||||
if err != nil { return err }
|
||||
}
|
||||
|
||||
var semanticTree analyzer.Tree
|
||||
err := semanticTree.Analyze(syntaxTree)
|
||||
if err != nil { return err }
|
||||
|
||||
module, err := native.NativeTarget().Generate(semanticTree)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("internal errror: %v", err))
|
||||
}
|
||||
|
||||
if this.Output == "" {
|
||||
this.Output = strings.TrimSuffix (
|
||||
inputs[0],
|
||||
filepath.Ext(inputs[0])) + ".o"
|
||||
}
|
||||
|
||||
extension := filepath.Ext(this.Output)
|
||||
switch extension {
|
||||
case ".s":
|
||||
return this.CompileModule(module, "asm")
|
||||
case ".o":
|
||||
return this.CompileModule(module, "obj")
|
||||
case ".ll":
|
||||
file, err := os.Create(this.Output)
|
||||
if err != nil { return err }
|
||||
defer file.Close()
|
||||
_, err = module.WriteTo(file)
|
||||
return err
|
||||
default:
|
||||
return errors.New(fmt.Sprintf (
|
||||
"unknown output type %s", extension))
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Compiler) CompileModule (module *llvm.Module, filetype string) error {
|
||||
var commandName string
|
||||
var args []string
|
||||
_, err := exec.LookPath("llc")
|
||||
if err == nil {
|
||||
commandName = "llc"
|
||||
args = []string {
|
||||
"-",
|
||||
fmt.Sprintf("-filetype=%s", filetype),
|
||||
"-o", this.Output,
|
||||
fmt.Sprintf("-O=%d", this.Optimization),
|
||||
}
|
||||
} else {
|
||||
commandName = "clang"
|
||||
if filetype != "obj" {
|
||||
return errors.New("need 'llc' to compile to " + filetype)
|
||||
}
|
||||
args = []string {
|
||||
"-c",
|
||||
"-x", "ir",
|
||||
"-o", this.Output,
|
||||
fmt.Sprintf("-O%d", this.Optimization),
|
||||
"-",
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
command := exec.Command(commandName, args...)
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
pipe, err := command.StdinPipe()
|
||||
if err != nil { return err }
|
||||
|
||||
err = command.Start()
|
||||
if err != nil { return err }
|
||||
_, err = module.WriteTo(pipe)
|
||||
if err != nil { return err }
|
||||
pipe.Close()
|
||||
return command.Wait()
|
||||
}
|
@ -14,11 +14,6 @@ import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
||||
import ferrors "git.tebibyte.media/sashakoshka/fspl/errors"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/generator/native"
|
||||
|
||||
type Compiler struct {
|
||||
Output string
|
||||
Optimization int
|
||||
}
|
||||
|
||||
func main () {
|
||||
compiler := new(Compiler)
|
||||
|
||||
@ -37,90 +32,3 @@ func main () {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Compiler) Compile (inputs []string) error {
|
||||
if len(inputs) == 0 {
|
||||
return errors.New("no input files specified")
|
||||
}
|
||||
|
||||
var syntaxTree parser.Tree
|
||||
for _, name := range inputs {
|
||||
lx, err := lexer.LexFile(name)
|
||||
if err != nil { return err }
|
||||
err = syntaxTree.Parse(lx)
|
||||
if err != nil { return err }
|
||||
}
|
||||
|
||||
var semanticTree analyzer.Tree
|
||||
err := semanticTree.Analyze(syntaxTree)
|
||||
if err != nil { return err }
|
||||
|
||||
module, err := native.NativeTarget().Generate(semanticTree)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("internal errror: %v", err))
|
||||
}
|
||||
|
||||
if this.Output == "" {
|
||||
this.Output = strings.TrimSuffix (
|
||||
inputs[0],
|
||||
filepath.Ext(inputs[0])) + ".o"
|
||||
}
|
||||
|
||||
extension := filepath.Ext(this.Output)
|
||||
switch extension {
|
||||
case ".s":
|
||||
return this.CompileModule(module, "asm")
|
||||
case ".o":
|
||||
return this.CompileModule(module, "obj")
|
||||
case ".ll":
|
||||
file, err := os.Create(this.Output)
|
||||
if err != nil { return err }
|
||||
defer file.Close()
|
||||
_, err = module.WriteTo(file)
|
||||
return err
|
||||
default:
|
||||
return errors.New(fmt.Sprintf (
|
||||
"unknown output type %s", extension))
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Compiler) CompileModule (module *llvm.Module, filetype string) error {
|
||||
var commandName string
|
||||
var args []string
|
||||
_, err := exec.LookPath("llc")
|
||||
if err == nil {
|
||||
commandName = "llc"
|
||||
args = []string {
|
||||
"-",
|
||||
fmt.Sprintf("-filetype=%s", filetype),
|
||||
"-o", this.Output,
|
||||
fmt.Sprintf("-O=%d", this.Optimization),
|
||||
}
|
||||
} else {
|
||||
commandName = "clang"
|
||||
if filetype != "obj" {
|
||||
return errors.New("need 'llc' to compile to " + filetype)
|
||||
}
|
||||
args = []string {
|
||||
"-c",
|
||||
"-x", "ir",
|
||||
"-o", this.Output,
|
||||
fmt.Sprintf("-O%d", this.Optimization),
|
||||
"-",
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
command := exec.Command(commandName, args...)
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
pipe, err := command.StdinPipe()
|
||||
if err != nil { return err }
|
||||
|
||||
err = command.Start()
|
||||
if err != nil { return err }
|
||||
_, err = module.WriteTo(pipe)
|
||||
if err != nil { return err }
|
||||
pipe.Close()
|
||||
return command.Wait()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user