func build(files []string, outputFile string, cg string, outputType LLVMCodegen.OutputType, optLevel int) { constructedModules, _ := parseFiles(files) // resolve log.Timed("resolve phase", "", func() { for _, module := range constructedModules { res := &parser.Resolver{Module: module} vis := parser.NewASTVisitor(res) vis.VisitModule(module) } }) // type inference log.Timed("inference phase", "", func() { for _, module := range constructedModules { inf := &parser.TypeInferer{Module: module} inf.Infer() // Dump AST log.Debugln("main", "AST of module `%s`:", module.Name) for _, node := range module.Nodes { log.Debugln("main", "%s", node.String()) } log.Debugln("main", "") } }) // semantic analysis log.Timed("semantic analysis phase", "", func() { for _, module := range constructedModules { sem := semantic.NewSemanticAnalyzer(module, *buildOwnership, *ignoreUnused) vis := parser.NewASTVisitor(sem) vis.VisitModule(module) sem.Finalize() } }) // codegen if cg != "none" { var gen codegen.Codegen switch cg { case "llvm": gen = &LLVMCodegen.Codegen{ OutputName: outputFile, OutputType: outputType, OptLevel: optLevel, } default: log.Error("main", util.Red("error: ")+"Invalid backend choice `"+cg+"`") os.Exit(1) } log.Timed("codegen phase", "", func() { gen.Generate(constructedModules) }) } }
func (v *Codegen) createBinary() { if v.OutputType == OUTPUT_LLVM_IR { for _, mod := range v.input { log.Timed("creating ir", mod.Name.String(), func() { v.createIR(mod) }) } return } else if v.OutputType == OUTPUT_ASSEMBLY { for _, mod := range v.input { log.Timed("creating assembly", mod.Name.String(), func() { v.createObjectOrAssembly(mod, llvm.AssemblyFile) }) } return } linkArgs := append(v.LinkerArgs, "-fno-PIE", "-nodefaultlibs", "-lc", "-lm") objFiles := []string{} for _, mod := range v.input { log.Timed("creating object", mod.Name.String(), func() { objName := v.createObjectOrAssembly(mod, llvm.ObjectFile) objFiles = append(objFiles, objName) linkArgs = append(linkArgs, objName) for _, lib := range mod.LinkedLibraries { linkArgs = append(linkArgs, fmt.Sprintf("-l%s", lib)) } }) } if v.OutputType == OUTPUT_OBJECT { return } if v.OutputName == "" { panic("OutputName is empty") } linkArgs = append(linkArgs, "-o", v.OutputName) if v.Linker == "" { v.Linker = "cc" } log.Timed("linking", "", func() { log.Verboseln("codegen", "%s %v", v.Linker, linkArgs) cmd := exec.Command(v.Linker, linkArgs...) if out, err := cmd.CombinedOutput(); err != nil { v.err("failed to link object files: `%s`\n%s", err.Error(), string(out)) } }) for _, objFile := range objFiles { os.Remove(objFile) } }
func Construct(module *Module, modules *ModuleLookup) { module.Parts = make(map[string]*Submodule) con := &Constructor{ modules: modules, module: module, } log.Timed("constructing module", module.Name.String(), func() { for _, tree := range con.module.Trees { log.Timed("constructing submodule", tree.Source.Name, func() { con.constructSubmodule(tree) }) } }) }
func Resolve(mod *Module, mods *ModuleLookup) { if mod.resolved { return } mod.resolved = true res := &Resolver{ modules: mods, module: mod, cModule: &Module{ Name: &ModuleName{Parts: []string{"C"}}, Parts: make(map[string]*Submodule), Dirpath: "", // not really a path for this module }, } res.cModule.ModScope = NewCScope(res.cModule) res.curScope = NewGlobalScope(mod) mod.ModScope = res.curScope // add a C module here which will contain all of the c bindings and what // not to keep everything separate mod.ModScope.UsedModules["C"] = res.cModule res.ResolveUsedModules() log.Timed("resolving module", mod.Name.String(), func() { res.ResolveTopLevelDecls() res.ResolveDescent() }) res.module.ModScope.Dump(0) }
func parseFiles(files []string) ([]*parser.Module, map[string]*parser.Module) { // read source files var sourcefiles []*lexer.Sourcefile log.Timed("reading sourcefiles", func() { for _, file := range files { sourcefile, err := lexer.NewSourcefile(file) if err != nil { setupErr("%s", err.Error()) } sourcefiles = append(sourcefiles, sourcefile) } }) // lexing log.Timed("lexing phase", func() { for _, file := range sourcefiles { file.Tokens = lexer.Lex(file) } }) // parsing var parsedFiles []*parser.ParseTree parsedFileMap := make(map[string]*parser.ParseTree) log.Timed("parsing phase", func() { for _, file := range sourcefiles { parsedFile := parser.Parse(file) parsedFiles = append(parsedFiles, parsedFile) parsedFileMap[parsedFile.Source.Name] = parsedFile } }) // construction var constructedModules []*parser.Module modules := make(map[string]*parser.Module) log.Timed("construction phase", func() { for _, file := range parsedFiles { constructedModules = append(constructedModules, parser.Construct(file, parsedFileMap, modules)) } }) return constructedModules, modules }
func SemCheck(module *ast.Module, ignoreUnused bool) { checks := []SemanticCheck{ &AttributeCheck{}, &UnreachableCheck{}, &BreakAndNextCheck{}, &DeprecatedCheck{}, &RecursiveDefinitionCheck{}, &TypeCheck{}, &ImmutableAssignCheck{}, &UseBeforeDeclareCheck{}, &MiscCheck{}, &ReferenceCheck{}, } if !ignoreUnused { checks = append(checks, &UnusedCheck{}) } for _, check := range checks { log.Timed("analysis pass", check.Name(), func() { for _, submod := range module.Parts { log.Timed("checking submodule", module.Name.String()+"/"+submod.File.Name, func() { res := &SemanticAnalyzer{} res.shouldExit = false res.Submodule = submod res.Check = check res.Init() vis := ast.NewASTVisitor(res) vis.VisitSubmodule(submod) res.Finalize() }) } }) } }
func Parse(input *lexer.Sourcefile) (*ParseTree, []*NameNode) { p := &parser{ input: input, binOpPrecedences: newBinOpPrecedenceMap(), tree: &ParseTree{Source: input}, } log.Timed("parsing", input.Name, func() { p.parse() }) return p.tree, p.deps }
func Lex(input *Sourcefile) []*Token { v := &lexer{ input: input, startPos: 0, endPos: 0, curPos: Position{Filename: input.Name, Line: 1, Char: 1}, tokStart: Position{Filename: input.Name, Line: 1, Char: 1}, } log.Timed("lexing", input.Name, func() { v.lex() }) return v.input.Tokens }
func Construct(tree *ParseTree, modules *ModuleLookup) *Module { c := &Constructor{ tree: tree, module: &Module{ Nodes: make([]Node, 0), File: tree.Source, Path: tree.Source.Path, Name: tree.Name, }, scope: NewGlobalScope(), } c.module.GlobalScope = c.scope c.modules = modules modules.Create(tree.Name).Module = c.module // add a C module here which will contain // all of the c bindings and what not to // keep everything separate cModule := &Module{ Nodes: make([]Node, 0), Path: "", // not really a path for this module Name: &ModuleName{Parts: []string{"C"}}, GlobalScope: NewCScope(), } c.module.GlobalScope.UsedModules["C"] = &ModuleLookup{ Name: "C", Module: cModule, Children: make(map[string]*ModuleLookup), } log.Timed("constructing", tree.Source.Name, func() { c.construct() }) return c.module }
func parseFiles(inputs []string) ([]*parser.Module, *parser.ModuleLookup) { if len(inputs) != 1 { setupErr("Please specify only one file or module to build") } var modulesToRead []*parser.ModuleName var modules []*parser.Module moduleLookup := parser.NewModuleLookup("") depGraph := parser.NewDependencyGraph() input := inputs[0] if strings.HasSuffix(input, ".ark") { // Handle the special case of a single .ark file modname := &parser.ModuleName{Parts: []string{"__main"}} module := &parser.Module{ Name: modname, Dirpath: "", } moduleLookup.Create(modname).Module = module // Read sourcefile, err := lexer.NewSourcefile(input) if err != nil { setupErr("%s", err.Error()) } // Lex sourcefile.Tokens = lexer.Lex(sourcefile) // Parse parsedFile, deps := parser.Parse(sourcefile) module.Trees = append(module.Trees, parsedFile) // Add dependencies to parse array for _, dep := range deps { depname := parser.NewModuleName(dep) modulesToRead = append(modulesToRead, depname) depGraph.AddDependency(modname, depname) } modules = append(modules, module) } else { if strings.ContainsAny(input, `\/. `) { setupErr("Invalid module name: %s", input) } modname := &parser.ModuleName{Parts: strings.Split(input, "::")} modulesToRead = append(modulesToRead, modname) } log.Timed("read/lex/parse phase", "", func() { for i := 0; i < len(modulesToRead); i++ { modname := modulesToRead[i] // Skip already loaded modules if _, err := moduleLookup.Get(modname); err == nil { continue } fi, dirpath := findModuleDir(*buildSearchpaths, modname.ToPath()) if fi == nil { setupErr("Couldn't find module `%s`", modname) } if !fi.IsDir() { setupErr("Expected path `%s` to be directory, was file.", dirpath) } module := &parser.Module{ Name: modname, Dirpath: dirpath, } moduleLookup.Create(modname).Module = module // Check module children childFiles, err := ioutil.ReadDir(dirpath) if err != nil { setupErr("%s", err.Error()) } for _, childFile := range childFiles { if strings.HasPrefix(childFile.Name(), ".") || !strings.HasSuffix(childFile.Name(), ".ark") { continue } actualFile := filepath.Join(dirpath, childFile.Name()) // Read sourcefile, err := lexer.NewSourcefile(actualFile) if err != nil { setupErr("%s", err.Error()) } // Lex sourcefile.Tokens = lexer.Lex(sourcefile) // Parse parsedFile, deps := parser.Parse(sourcefile) module.Trees = append(module.Trees, parsedFile) // Add dependencies to parse array for _, dep := range deps { depname := parser.NewModuleName(dep) modulesToRead = append(modulesToRead, depname) depGraph.AddDependency(modname, depname) } } modules = append(modules, module) } }) // Check for cyclic dependencies (in modules) log.Timed("cyclic dependency check", "", func() { errs := depGraph.DetectCycles() if len(errs) > 0 { log.Errorln("main", "error: Encountered cyclic dependecies:") for _, cycle := range errs { log.Errorln("main", "%s", cycle) } os.Exit(util.EXIT_FAILURE_SETUP) } }) // construction log.Timed("construction phase", "", func() { for _, module := range modules { parser.Construct(module, moduleLookup) } }) return modules, moduleLookup }
func build(files []string, outputFile string, cg string, outputType LLVMCodegen.OutputType, optLevel int) { constructedModules, moduleLookup := parseFiles(files) // resolve hasMainFunc := false log.Timed("resolve phase", "", func() { for _, module := range constructedModules { parser.Resolve(module, moduleLookup) // Use module scope to check for main function mainIdent := module.ModScope.GetIdent(parser.UnresolvedName{Name: "main"}) if mainIdent != nil && mainIdent.Type == parser.IDENT_FUNCTION && mainIdent.Public { hasMainFunc = true } } }) // and here we check if we should // bother continuing any further... if !hasMainFunc { log.Error("main", util.Red("error: ")+"main function not found\n") os.Exit(1) } // type inference log.Timed("inference phase", "", func() { for _, module := range constructedModules { for _, submod := range module.Parts { inf := &parser.TypeInferer{Submodule: submod} inf.Infer() // Dump AST log.Debugln("main", "AST of submodule `%s/%s`:", module.Name, submod.File.Name) for _, node := range submod.Nodes { log.Debugln("main", "%s", node.String()) } log.Debugln("main", "") } } }) // semantic analysis log.Timed("semantic analysis phase", "", func() { for _, module := range constructedModules { for _, submod := range module.Parts { sem := semantic.NewSemanticAnalyzer(submod, *buildOwnership, *ignoreUnused) vis := parser.NewASTVisitor(sem) vis.VisitSubmodule(submod) sem.Finalize() } } }) // codegen if cg != "none" { var gen codegen.Codegen switch cg { case "llvm": gen = &LLVMCodegen.Codegen{ OutputName: outputFile, OutputType: outputType, OptLevel: optLevel, } default: log.Error("main", util.Red("error: ")+"Invalid backend choice `"+cg+"`") os.Exit(1) } log.Timed("codegen phase", "", func() { gen.Generate(constructedModules) }) } }
func (v *Context) parseFiles() { if strings.HasSuffix(v.Input, ".ark") { // Handle the special case of a single .ark file modname := &ast.ModuleName{Parts: []string{"__main"}} module := &ast.Module{ Name: modname, Dirpath: "", } v.moduleLookup.Create(modname).Module = module v.parseFile(v.Input, module) v.modules = append(v.modules, module) } else { if strings.ContainsAny(v.Input, `\/. `) { setupErr("Invalid module name: %s", v.Input) } modname := &ast.ModuleName{Parts: strings.Split(v.Input, "::")} v.modulesToRead = append(v.modulesToRead, modname) } log.Timed("read/lex/parse phase", "", func() { for i := 0; i < len(v.modulesToRead); i++ { modname := v. modulesToRead[i] // Skip already loaded modules if _, err := v.moduleLookup.Get(modname); err == nil { continue } fi, dirpath, err := v.findModuleDir(modname.ToPath()) if err != nil { setupErr("Couldn't find module `%s`: %s", modname, err) } if !fi.IsDir() { setupErr("Expected path `%s` to be directory, was file.", dirpath) } module := &ast.Module{ Name: modname, Dirpath: dirpath, } v.moduleLookup.Create(modname).Module = module // Check module children childFiles, err := ioutil.ReadDir(dirpath) if err != nil { setupErr("%s", err.Error()) } for _, childFile := range childFiles { if strings.HasPrefix(childFile.Name(), ".") || !strings.HasSuffix(childFile.Name(), ".ark") { continue } actualFile := filepath.Join(dirpath, childFile.Name()) v.parseFile(actualFile, module) } v.modules = append(v.modules, module) } }) // Check for cyclic dependencies (in modules) log.Timed("cyclic dependency check", "", func() { errs := v.depGraph.DetectCycles() if len(errs) > 0 { log.Error("main", "%s: Encountered cyclic dependency between: ", util.Bold(util.Red("error"))) for _, cycle := range errs { log.Error("main", "%s", cycle) } log.Errorln("main", "") os.Exit(util.EXIT_FAILURE_SETUP) } }) // construction log.Timed("construction phase", "", func() { for _, module := range v.modules { ast.Construct(module, v.moduleLookup) } }) }
func parseFiles(inputs []string) ([]*parser.Module, *parser.ModuleLookup) { var modulesToRead []*parser.ModuleName for _, input := range inputs { if strings.ContainsAny(input, `\/. `) { setupErr("Invalid module name: %s", input) } modname := &parser.ModuleName{Parts: strings.Split(input, "::")} modulesToRead = append(modulesToRead, modname) } var parsedFiles []*parser.ParseTree moduleLookup := parser.NewModuleLookup("") depGraph := parser.NewDependencyGraph() log.Timed("read/lex/parse phase", "", func() { for i := 0; i < len(modulesToRead); i++ { modname := modulesToRead[i] actualFile := filepath.Join(*buildBasedir, modname.ToPath()) fi, err := os.Stat(actualFile + ".ark") shouldBeDir := false if os.IsNotExist(err) { fi, err = os.Stat(actualFile) shouldBeDir = true } if err != nil { setupErr("%s", err.Error()) } if !fi.IsDir() && shouldBeDir { setupErr("Expected file `%s` to be directory, was file.", actualFile) } // Check lookup ll := moduleLookup.Create(modname) if ll.Tree == nil { if shouldBeDir { // Setup dummy parse tree ll.Tree = &parser.ParseTree{} ll.Tree.Name = modname // Setup dummy module ll.Module = &parser.Module{} ll.Module.Path = actualFile ll.Module.Name = modname ll.Module.GlobalScope = parser.NewGlobalScope() // Check module children childFiles, err := ioutil.ReadDir(actualFile) if err != nil { setupErr("%s", err.Error()) } for _, childFile := range childFiles { if strings.HasPrefix(childFile.Name(), ".") { continue } if childFile.IsDir() || strings.HasSuffix(childFile.Name(), ".ark") { childmodname := parser.JoinModuleName(modname, strings.TrimSuffix(childFile.Name(), ".ark")) modulesToRead = append(modulesToRead, childmodname) ll.Module.GlobalScope.UsedModules[childmodname.Last()] = moduleLookup.Create(childmodname) } } } else { // Read sourcefile, err := lexer.NewSourcefile(actualFile + ".ark") if err != nil { setupErr("%s", err.Error()) } // Lex sourcefile.Tokens = lexer.Lex(sourcefile) // Parse parsedFile, deps := parser.Parse(sourcefile) parsedFile.Name = modname parsedFiles = append(parsedFiles, parsedFile) ll.Tree = parsedFile // Add dependencies to parse array for _, dep := range deps { depname := parser.NewModuleName(dep) modulesToRead = append(modulesToRead, depname) depGraph.AddDependency(modname, depname) } } } } }) // Check for cyclic dependencies (in modules) log.Timed("cyclic dependency check", "", func() { errs := depGraph.DetectCycles() if len(errs) > 0 { log.Errorln("main", "error: Encountered cyclic dependecies:") for _, cycle := range errs { log.Errorln("main", "%s", cycle) } os.Exit(util.EXIT_FAILURE_SETUP) } }) hasMainFunc := false // construction var constructedModules []*parser.Module log.Timed("construction phase", "", func() { for _, file := range parsedFiles { mod := parser.Construct(file, moduleLookup) constructedModules = append(constructedModules, mod) // not terribly efficient, but it's best // to catch out earlier on if we have // a main function or not rather than // figuring out at the codegen phase?? // maybe?? // TODO FIXME MAKEPRETTY for _, node := range mod.Nodes { switch node := node.(type) { case *parser.FunctionDecl: if node.Function.Name == "main" { hasMainFunc = true break } default: } } } }) // and here we check if we should // bother continuing any further... if !hasMainFunc { log.Error("main", util.Red("error: ")+"main function not found\n") os.Exit(1) } return constructedModules, moduleLookup }
func (v *Codegen) createBinary() { // god this is a long and ugly function if v.OutputType == OUTPUT_LLVM_IR { for _, file := range v.input { log.Timed("create ir "+file.Name, func() { v.createIR(file) }) } return } linkArgs := append(v.LinkerArgs, "-fno-PIE", "-nodefaultlibs", "-lc", "-lm") bitcodeFiles := []string{} for _, file := range v.input { log.Timed("create bitcode "+file.Name, func() { bitcodeFiles = append(bitcodeFiles, v.createBitcode(file)) }) } if v.OutputType == OUTPUT_LLVM_BC { return } asmFiles := []string{} for _, name := range bitcodeFiles { log.Timed("create asm "+name, func() { asmName := v.bitcodeToASM(name) asmFiles = append(asmFiles, asmName) }) } for _, bc := range bitcodeFiles { if err := os.Remove(bc); err != nil { v.err("Failed to remove "+bc+": `%s`", err.Error()) } } if v.OutputType == OUTPUT_ASSEMBLY { return } objFiles := []string{} for _, asmFile := range asmFiles { log.Timed("create obj "+asmFile, func() { objName := v.asmToObject(asmFile) objFiles = append(objFiles, objName) linkArgs = append(linkArgs, objName) }) } for _, asmFile := range asmFiles { os.Remove(asmFile) } if v.OutputType == OUTPUT_OBJECT { return } if v.OutputName == "" { panic("OutputName is empty") } linkArgs = append(linkArgs, "-o", v.OutputName) if v.Linker == "" { v.Linker = "cc" } log.Timed("link", func() { cmd := exec.Command(v.Linker, linkArgs...) if out, err := cmd.CombinedOutput(); err != nil { v.err("failed to link object files: `%s`\n%s", err.Error(), string(out)) } }) for _, objFile := range objFiles { os.Remove(objFile) } }
func (v *Codegen) Generate(input []*parser.Module) { v.builders = make(map[*parser.Function]llvm.Builder) v.inBlocks = make(map[*parser.Function][]*parser.Block) v.globalBuilder = llvm.NewBuilder() defer v.globalBuilder.Dispose() v.curLoopExits = make(map[*parser.Function][]llvm.BasicBlock) v.curLoopNexts = make(map[*parser.Function][]llvm.BasicBlock) v.input = make([]*WrappedModule, len(input)) for idx, mod := range input { v.input[idx] = &WrappedModule{Module: mod} } v.variableLookup = make(map[*parser.Variable]llvm.Value) v.namedTypeLookup = make(map[string]llvm.Type) // initialize llvm target llvm.InitializeNativeTarget() llvm.InitializeNativeAsmPrinter() // setup target stuff var err error v.target, err = llvm.GetTargetFromTriple(llvm.DefaultTargetTriple()) if err != nil { panic(err) } v.targetMachine = v.target.CreateTargetMachine(llvm.DefaultTargetTriple(), "", "", llvm.CodeGenLevelNone, llvm.RelocDefault, llvm.CodeModelDefault) v.targetData = v.targetMachine.TargetData() passManager := llvm.NewPassManager() passBuilder := llvm.NewPassManagerBuilder() if v.OptLevel > 0 { passBuilder.SetOptLevel(v.OptLevel) passBuilder.Populate(passManager) } v.blockDeferData = make(map[*parser.Block][]*deferData) for _, infile := range v.input { log.Timed("codegenning", infile.Name.String(), func() { infile.LlvmModule = llvm.NewModule(infile.Name.String()) v.curFile = infile for _, submod := range infile.Parts { v.declareDecls(submod.Nodes) for _, node := range submod.Nodes { v.genNode(node) } } if err := llvm.VerifyModule(infile.LlvmModule, llvm.ReturnStatusAction); err != nil { infile.LlvmModule.Dump() v.err("%s", err.Error()) } passManager.Run(infile.LlvmModule) if log.AtLevel(log.LevelDebug) { infile.LlvmModule.Dump() } }) } passManager.Dispose() log.Timed("creating binary", "", func() { v.createBinary() }) }
func (v *Context) Build(output string, outputType codegen.OutputType, usedCodegen string, optLevel int) { // Start by loading the runtime runtimeModule := LoadRuntime() // Parse the passed files v.parseFiles() // resolve hasMainFunc := false log.Timed("resolve phase", "", func() { for _, module := range v.modules { ast.Resolve(module, v.moduleLookup) // Use module scope to check for main function mainIdent := module.ModScope.GetIdent(ast.UnresolvedName{Name: "main"}) if mainIdent != nil && mainIdent.Type == ast.IDENT_FUNCTION && mainIdent.Public { hasMainFunc = true } } }) // and here we check if we should // bother continuing any further... if !hasMainFunc { log.Error("main", util.Red("error: ")+"main function not found\n") os.Exit(1) } // type inference log.Timed("inference phase", "", func() { for _, module := range v.modules { for _, submod := range module.Parts { ast.Infer(submod) // Dump AST log.Debugln("main", "AST of submodule `%s/%s`:", module.Name, submod.File.Name) for _, node := range submod.Nodes { log.Debugln("main", "%s", node.String()) } log.Debugln("main", "") } } }) // semantic analysis log.Timed("semantic analysis phase", "", func() { for _, module := range v.modules { semantic.SemCheck(module, *ignoreUnused) } }) // codegen if usedCodegen != "none" { var gen codegen.Codegen switch usedCodegen { case "llvm": gen = &LLVMCodegen.Codegen{ OutputName: output, OutputType: outputType, OptLevel: optLevel, } default: log.Error("main", util.Red("error: ")+"Invalid backend choice `"+usedCodegen+"`") os.Exit(1) } log.Timed("codegen phase", "", func() { mods := v.modules if runtimeModule != nil { mods = append(mods, runtimeModule) } gen.Generate(mods) }) } }
func (v *Codegen) Generate(input []*parser.Module, modules map[string]*parser.Module) { v.input = input v.builder = llvm.NewBuilder() v.variableLookup = make(map[*parser.Variable]llvm.Value) v.structLookup_UseHelperFunction = make(map[*parser.StructType]llvm.Type) v.enumLookup_UseHelperFunction = make(map[*parser.EnumType]llvm.Type) // initialize llvm target llvm.InitializeNativeTarget() // setup target stuff var err error v.target, err = llvm.GetTargetFromTriple(llvm.DefaultTargetTriple()) if err != nil { panic(err) } v.targetMachine = v.target.CreateTargetMachine(llvm.DefaultTargetTriple(), "", "", llvm.CodeGenLevelNone, llvm.RelocDefault, llvm.CodeModelDefault) v.targetData = v.targetMachine.TargetData() passManager := llvm.NewPassManager() passBuilder := llvm.NewPassManagerBuilder() if v.OptLevel > 0 { passBuilder.SetOptLevel(v.OptLevel) passBuilder.Populate(passManager) } v.modules = make(map[string]*parser.Module) v.blockDeferData = make(map[*parser.Block][]*deferData) for _, infile := range input { log.Verboseln("codegen", util.TEXT_BOLD+util.TEXT_GREEN+"Started codegenning "+util.TEXT_RESET+infile.Name) t := time.Now() infile.Module = llvm.NewModule(infile.Name) v.curFile = infile v.modules[v.curFile.Name] = v.curFile v.declareDecls(infile.Nodes) for _, node := range infile.Nodes { v.genNode(node) } if err := llvm.VerifyModule(infile.Module, llvm.ReturnStatusAction); err != nil { infile.Module.Dump() v.err("%s", err.Error()) } passManager.Run(infile.Module) if log.AtLevel(log.LevelVerbose) { infile.Module.Dump() } dur := time.Since(t) log.Verbose("codegen", util.TEXT_BOLD+util.TEXT_GREEN+"Finished codegenning "+util.TEXT_RESET+infile.Name+" (%.2fms)\n", float32(dur.Nanoseconds())/1000000) } passManager.Dispose() log.Timed("create binary", func() { v.createBinary() }) }