implement-modules #43

Closed
sashakoshka wants to merge 502 commits from implement-modules into main
Showing only changes of commit 8258c4f400 - Show all commits

View File

@ -1,5 +1,95 @@
package main
func main () {
import "os"
import "fmt"
import "flag"
import "errors"
import "strings"
import "os/exec"
import "path/filepath"
import "git.tebibyte.media/sashakoshka/fspl/llvm"
import "git.tebibyte.media/sashakoshka/fspl/parser"
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
import "git.tebibyte.media/sashakoshka/fspl/generator"
type Compiler struct {
Output string
EmitIr bool
Optimization int
}
func main () {
compiler := new(Compiler)
flag.StringVar(&compiler.Output, "o", "", "Output filename")
flag.BoolVar(&compiler.EmitIr, "emit-llvm-ir", false, "Output LLVM IR instead of an object file")
flag.IntVar(&compiler.Optimization, "O", 0, "Optimization level (0-3)")
flag.Parse()
err := compiler.Compile(flag.Args())
if err != nil {
fmt.Println(err)
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 {
err := syntaxTree.ParseFile(name)
if err != nil { return err }
}
var semanticTree analyzer.Tree
err := semanticTree.Analyze(syntaxTree)
if err != nil { return err }
module, err := generator.NativeTarget().Generate(semanticTree)
if err != nil { return err }
if this.EmitIr {
if this.Output == "" {
this.Output = strings.TrimSuffix (
inputs[0],
filepath.Ext(inputs[0])) + ".ll"
}
file, err := os.Create(this.Output)
if err != nil { return err }
defer file.Close()
_, err = module.WriteTo(file)
return err
} else {
if this.Output == "" {
this.Output = strings.TrimSuffix (
inputs[0],
filepath.Ext(inputs[0])) + ".o"
}
return this.CompileModule(module)
}
}
func (this *Compiler) CompileModule (module *llvm.Module) error {
args := []string {
"-",
"-filetype=obj",
"-o", this.Output,
fmt.Sprintf("-O=%d", this.Optimization),
}
command := exec.Command("llc", 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()
}