func NewCG() *CG { cg := &CG{ Context: llvm.GlobalContext(), Builder: llvm.NewBuilder(), Mod: llvm.NewModule("kaleidoscope"), NamedValues: make(map[string]llvm.Value), Protos: make(map[string]*ProtoDecl), } cg.Init() return cg }
func Construct(tree *parser.AST) *Codegen { return &Codegen{ tree: tree, scope: &Scope{variables: map[string]llvm.Value{}}, module: llvm.NewModule("main"), builder: llvm.NewBuilder(), templates: map[string]*Template{}, functions: map[string]llvm.BasicBlock{}, } }
func (v *Codegen) Generate(input []*parser.Module, modules map[string]*parser.Module, verbose bool) { v.input = input v.builder = llvm.NewBuilder() v.variableLookup = make(map[*parser.Variable]llvm.Value) v.structLookup_UseHelperFunction = make(map[*parser.StructType]llvm.Type) if verbose { fmt.Println(util.TEXT_BOLD + util.TEXT_GREEN + "Started codegenning" + util.TEXT_RESET) } t := time.Now() passManager := llvm.NewPassManager() passBuilder := llvm.NewPassManagerBuilder() passBuilder.SetOptLevel(3) //passBuilder.Populate(passManager) //leave this off until the compiler is better v.modules = make(map[string]*parser.Module) for _, infile := range input { infile.Module = llvm.NewModule(infile.Name) v.curFile = infile fmt.Println("adding module " + v.curFile.Name) v.modules[v.curFile.Name] = v.curFile v.declareDecls(infile.Nodes) for _, node := range infile.Nodes { v.genNode(node) } if verbose { infile.Module.Dump() } if err := llvm.VerifyModule(infile.Module, llvm.ReturnStatusAction); err != nil { v.err("%s", err.Error()) } passManager.Run(infile.Module) } passManager.Dispose() v.createBinary() dur := time.Since(t) if verbose { fmt.Printf(util.TEXT_BOLD+util.TEXT_GREEN+"Finished codegenning"+util.TEXT_RESET+" (%.2fms)\n", float32(dur.Nanoseconds())/1000000) } }
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 (compiler *compiler) compile(filenames []string, importpath string) (m *Module, err error) { buildctx, err := llgobuild.ContextFromTriple(compiler.TargetTriple) if err != nil { return nil, err } initmap := make(map[*types.Package]gccgoimporter.InitData) var importer types.Importer if compiler.GccgoPath == "" { paths := append(append([]string{}, compiler.ImportPaths...), ".") importer = gccgoimporter.GetImporter(paths, initmap) } else { var inst gccgoimporter.GccgoInstallation err = inst.InitFromDriver(compiler.GccgoPath) if err != nil { return nil, err } importer = inst.GetImporter(compiler.ImportPaths, initmap) } impcfg := &loader.Config{ Fset: token.NewFileSet(), TypeChecker: types.Config{ Import: importer, Sizes: compiler.llvmtypes, }, Build: &buildctx.Context, } // Must use parseFiles, so we retain comments; // this is important for annotation processing. astFiles, err := parseFiles(impcfg.Fset, filenames) if err != nil { return nil, err } // If no import path is specified, then set the import // path to be the same as the package's name. if importpath == "" { importpath = astFiles[0].Name.String() } impcfg.CreateFromFiles(importpath, astFiles...) iprog, err := impcfg.Load() if err != nil { return nil, err } program := ssa.Create(iprog, ssa.BareInits) mainPkginfo := iprog.InitialPackages()[0] mainPkg := program.CreatePackage(mainPkginfo) // Create a Module, which contains the LLVM module. modulename := importpath compiler.module = &Module{Module: llvm.NewModule(modulename), Path: modulename} compiler.module.SetTarget(compiler.TargetTriple) compiler.module.SetDataLayout(compiler.dataLayout) // Create a new translation unit. unit := newUnit(compiler, mainPkg) // Create the runtime interface. compiler.runtime, err = newRuntimeInterface(compiler.module.Module, compiler.llvmtypes) if err != nil { return nil, err } mainPkg.Build() // Create a struct responsible for mapping static types to LLVM types, // and to runtime/dynamic type values. compiler.types = NewTypeMap( mainPkg, compiler.llvmtypes, compiler.module.Module, compiler.runtime, MethodResolver(unit), ) if compiler.GenerateDebug { compiler.debug = debug.NewDIBuilder( types.Sizes(compiler.llvmtypes), compiler.module.Module, impcfg.Fset, compiler.DebugPrefixMaps, ) defer compiler.debug.Destroy() defer compiler.debug.Finalize() } unit.translatePackage(mainPkg) compiler.processAnnotations(unit, mainPkginfo) if importpath == "main" { if err = compiler.createInitMainFunction(mainPkg, initmap); err != nil { return nil, fmt.Errorf("failed to create __go_init_main: %v", err) } } else { compiler.module.ExportData = compiler.buildExportData(mainPkg, initmap) } return compiler.module, nil }
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() }) }
func (compiler *compiler) compile(fset *token.FileSet, astFiles []*ast.File, importpath string) (m *Module, err error) { buildctx, err := llgobuild.ContextFromTriple(compiler.TargetTriple) if err != nil { return nil, err } if compiler.Importer == nil { err = compiler.MakeImporter() if err != nil { return nil, err } } impcfg := &loader.Config{ Fset: fset, TypeChecker: types.Config{ Packages: compiler.Packages, Import: compiler.Importer, Sizes: compiler.llvmtypes, DisableUnusedImportCheck: compiler.DisableUnusedImportCheck, }, ImportFromBinary: true, Build: &buildctx.Context, PackageCreated: compiler.PackageCreated, } // If no import path is specified, then set the import // path to be the same as the package's name. if importpath == "" { importpath = astFiles[0].Name.String() } impcfg.CreateFromFiles(importpath, astFiles...) iprog, err := impcfg.Load() if err != nil { return nil, err } program := ssa.Create(iprog, ssa.BareInits) mainPkginfo := iprog.InitialPackages()[0] mainPkg := program.CreatePackage(mainPkginfo) // Create a Module, which contains the LLVM module. modulename := importpath compiler.module = &Module{Module: llvm.NewModule(modulename), Path: modulename, Package: mainPkg.Object} compiler.module.SetTarget(compiler.TargetTriple) compiler.module.SetDataLayout(compiler.dataLayout) // Create a new translation unit. unit := newUnit(compiler, mainPkg) // Create the runtime interface. compiler.runtime, err = newRuntimeInterface(compiler.module.Module, compiler.llvmtypes) if err != nil { return nil, err } mainPkg.Build() // Create a struct responsible for mapping static types to LLVM types, // and to runtime/dynamic type values. compiler.types = NewTypeMap( mainPkg, compiler.llvmtypes, compiler.module.Module, compiler.runtime, MethodResolver(unit), ) if compiler.GenerateDebug { compiler.debug = debug.NewDIBuilder( types.Sizes(compiler.llvmtypes), compiler.module.Module, impcfg.Fset, compiler.DebugPrefixMaps, ) defer compiler.debug.Destroy() defer compiler.debug.Finalize() } unit.translatePackage(mainPkg) compiler.processAnnotations(unit, mainPkginfo) if importpath == "main" { compiler.createInitMainFunction(mainPkg) } else { compiler.module.ExportData = compiler.buildExportData(mainPkg) } return compiler.module, nil }
func performAction(opts *driverOptions, kind actionKind, inputs []string, output string) error { switch kind { case actionPrint: switch opts.output { case "-dumpversion": fmt.Println("llgo-" + llvmVersion()) return nil case "-print-libgcc-file-name": cmd := exec.Command(opts.bprefix+"gcc", "-print-libgcc-file-name") out, err := cmd.CombinedOutput() os.Stdout.Write(out) return err case "-print-multi-os-directory": fmt.Println(filepath.Join("..", getLibDir(opts))) return nil case "--version": displayVersion() return nil default: panic("unexpected print command") } case actionCompile, actionAssemble: compiler, err := initCompiler(opts) if err != nil { return err } fset := token.NewFileSet() files, err := driver.ParseFiles(fset, inputs) if err != nil { return err } module, err := compiler.Compile(fset, files, opts.pkgpath) if err != nil { return err } defer module.Dispose() target, err := llvm.GetTargetFromTriple(opts.triple) if err != nil { return err } optLevel := [...]llvm.CodeGenOptLevel{ llvm.CodeGenLevelNone, llvm.CodeGenLevelLess, llvm.CodeGenLevelDefault, llvm.CodeGenLevelAggressive, }[opts.optLevel] relocMode := llvm.RelocStatic if opts.pic { relocMode = llvm.RelocPIC } tm := target.CreateTargetMachine(opts.triple, "", "", optLevel, relocMode, llvm.CodeModelDefault) defer tm.Dispose() runPasses(opts, tm, module.Module) var file *os.File if output == "-" { file = os.Stdout } else { file, err = os.Create(output) if err != nil { return err } defer file.Close() } switch { case !opts.lto && !opts.emitIR: if module.ExportData != nil { asm := getMetadataSectionInlineAsm(".go_export") asm += getDataInlineAsm(module.ExportData) module.Module.SetInlineAsm(asm) } fileType := llvm.AssemblyFile if kind == actionCompile { fileType = llvm.ObjectFile } mb, err := tm.EmitToMemoryBuffer(module.Module, fileType) if err != nil { return err } defer mb.Dispose() bytes := mb.Bytes() _, err = file.Write(bytes) return err case opts.lto: bcmb := llvm.WriteBitcodeToMemoryBuffer(module.Module) defer bcmb.Dispose() // This is a bit of a hack. We just want an object file // containing some metadata sections. This might be simpler // if we had bindings for the MC library, but for now we create // a fresh module containing only inline asm that creates the // sections. outmodule := llvm.NewModule("") defer outmodule.Dispose() asm := getMetadataSectionInlineAsm(".llvmbc") asm += getDataInlineAsm(bcmb.Bytes()) if module.ExportData != nil { asm += getMetadataSectionInlineAsm(".go_export") asm += getDataInlineAsm(module.ExportData) } outmodule.SetInlineAsm(asm) fileType := llvm.AssemblyFile if kind == actionCompile { fileType = llvm.ObjectFile } mb, err := tm.EmitToMemoryBuffer(outmodule, fileType) if err != nil { return err } defer mb.Dispose() bytes := mb.Bytes() _, err = file.Write(bytes) return err case kind == actionCompile: err := llvm.WriteBitcodeToFile(module.Module, file) return err case kind == actionAssemble: _, err := file.WriteString(module.Module.String()) return err default: panic("unexpected action kind") } case actionLink: // TODO(pcc): Teach this to do LTO. args := []string{"-o", output} if opts.pic { args = append(args, "-fPIC") } if opts.pieLink { args = append(args, "-pie") } if opts.staticLink { args = append(args, "-static") } if opts.staticLibgcc { args = append(args, "-static-libgcc") } for _, p := range opts.libPaths { args = append(args, "-L", p) } for _, p := range opts.importPaths { args = append(args, "-I", p) } args = append(args, inputs...) var linkerPath string if opts.gccgoPath == "" { // TODO(pcc): See if we can avoid calling gcc here. // We currently rely on it to find crt*.o and compile // any C source files passed as arguments. linkerPath = opts.bprefix + "gcc" if opts.prefix != "" { libdir := filepath.Join(opts.prefix, getLibDir(opts)) args = append(args, "-L", libdir) if !opts.staticLibgo { args = append(args, "-Wl,-rpath,"+libdir) } } args = append(args, "-lgobegin-llgo") if opts.staticLibgo { args = append(args, "-Wl,-Bstatic", "-lgo-llgo", "-Wl,-Bdynamic", "-lpthread", "-lm") } else { args = append(args, "-lgo-llgo") } } else { linkerPath = opts.gccgoPath if opts.staticLibgo { args = append(args, "-static-libgo") } } args = opts.sanitizer.addLibs(opts.triple, args) cmd := exec.Command(linkerPath, args...) out, err := cmd.CombinedOutput() if err != nil { os.Stderr.Write(out) } return err default: panic("unexpected action kind") } }