From 2bc5eb1f49e221c296aad6c7b4d6138d9a651aa7 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 11 Feb 2024 01:55:07 -0500 Subject: [PATCH] Break fsplc Compiler type into a different file --- cmd/fsplc/compiler.go | 105 ++++++++++++++++++++++++++++++++++++++++++ cmd/fsplc/main.go | 92 ------------------------------------ 2 files changed, 105 insertions(+), 92 deletions(-) create mode 100644 cmd/fsplc/compiler.go diff --git a/cmd/fsplc/compiler.go b/cmd/fsplc/compiler.go new file mode 100644 index 0000000..dd1e050 --- /dev/null +++ b/cmd/fsplc/compiler.go @@ -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() +} diff --git a/cmd/fsplc/main.go b/cmd/fsplc/main.go index 9b7abfc..0bec766 100644 --- a/cmd/fsplc/main.go +++ b/cmd/fsplc/main.go @@ -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() -}