func main() { flag.Parse() if triple == "" { log.Fatal("No default triple set") } if clang == "" { clang = "clang" } llgobuildctx, err := llgobuild.ContextFromTriple(triple) if err != nil { log.Fatal(err) } buildctx = &llgobuildctx.Context // pkgroot = $GOPATH/pkg/llgo/<triple> gopath := os.Getenv("GOPATH") if gopath == "" { gopath = runtime.GOROOT() } else { gopath = filepath.SplitList(gopath)[0] } pkgroot = filepath.Join(gopath, "pkg", "llgo", triple) // Create a temporary work dir. workdir, err = ioutil.TempDir("", "llgo") if err != nil { log.Fatal(err) } if work { log.Println("Working directory:", workdir) } args := flag.Args() if test { if len(args) > 1 { err = fmt.Errorf("Multiple files/packages can not be specified when building a test binary") } else { err = buildPackageTests(args[0]) } } else { err = buildPackages(args) } if !work { os.RemoveAll(workdir) } if err != nil { log.Fatal(err) } }
func buildLlgo() error { log.Println("Building llgo") cmd := command("go", "get", "-d", llvmpkgpath) output, err := cmd.CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", string(output)) return err } pkg, err := gobuild.Import(llvmpkgpath, "", gobuild.FindOnly) if err != nil { return err } if alwaysbuild { if _, err := os.Stat(pkg.PkgObj); err == nil { log.Println("- Rebuilding go-llvm/llvm") os.Remove(pkg.PkgObj) } } cgoCflags := fmt.Sprintf("%s -I %s/../include", llvmcflags, pkg.Dir) cgoLdflags := fmt.Sprintf("-Wl,-L%s", llvmlibdir) ldflags := fmt.Sprintf("-r %q", llvmlibdir) if sharedllvm { cgoLdflags += fmt.Sprintf(" -lLLVM-%s ", llvmversion) } else { cgoLdflags += " " + llvmlibs + " -lstdc++ -lm " } cgoLdflags += " " + llvmldflags args := []string{"get", "-ldflags", ldflags} llvmtag := "llvm" + llvmversion if strings.HasSuffix(llvmversion, "svn") { llvmtag = "llvmsvn" } args = append(args, []string{"-tags", llvmtag}...) args = append(args, llgopkgpath) cmd = command("go", args...) cmd.Env = os.Environ() cmd.Env = append(cmd.Env, "CGO_CFLAGS="+cgoCflags) cmd.Env = append(cmd.Env, "CGO_LDFLAGS="+cgoLdflags) output, err = cmd.CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", string(output)) return err } if llgobin, err = findCommand(llgopkgpath); err != nil { return err } // If the user did not specify -triple on the command // line, ask llgo for it now. if triple == "" { output, err = command(llgobin, "-print-triple").CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", string(output)) return err } triple = strings.TrimSpace(string(output)) } llgobuildctx, err := build.ContextFromTriple(triple) if err != nil { return err } buildctx = &llgobuildctx.Context log.Printf("GOARCH = %s, GOOS = %s", buildctx.GOARCH, buildctx.GOOS) log.Printf("Built %s", llgobin) if install_name_tool && sharedllvm { // TODO: this was with the LLVM shipped with the pnacl sdk and might not be true of *all* libLLVM-xxx.dylibs. // Is there a link time commandline option that has the same effect? cmd = command("install_name_tool", "-change", fmt.Sprintf("@executable_path/../lib/libLLVM-%s.dylib", llvmversion), fmt.Sprintf("%s/libLLVM-%s.dylib", llvmlibdir, llvmversion), llgobin) output, err = cmd.CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", string(output)) return err } log.Printf("Successfully changed shared libLLVM path") } return nil }
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 (compiler *compiler) compile(filenames []string, importpath string) (m *Module, err error) { buildctx, err := llgobuild.ContextFromTriple(compiler.TargetTriple) if err != nil { return nil, err } impcfg := &loader.Config{ Fset: token.NewFileSet(), TypeChecker: types.Config{ Import: llgoimporter.NewImporter(buildctx).Import, 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, or the package's // name (not path) is "main", then set the import // path to be the same as the package's name. if pkgname := astFiles[0].Name.String(); importpath == "" || pkgname == "main" { importpath = pkgname } impcfg.CreateFromFiles(importpath, astFiles...) // Create a "runtime" package too, so we can reference // its types and functions in the compiler and generated // code. if importpath != "runtime" { astFiles, err := parseRuntime(&buildctx.Context, impcfg.Fset) if err != nil { return nil, err } impcfg.CreateFromFiles("runtime", astFiles...) } iprog, err := impcfg.Load() if err != nil { return nil, err } program := ssa.Create(iprog, 0) var mainPkginfo, runtimePkginfo *loader.PackageInfo if pkgs := iprog.InitialPackages(); len(pkgs) == 1 { mainPkginfo, runtimePkginfo = pkgs[0], pkgs[0] } else { mainPkginfo, runtimePkginfo = pkgs[0], pkgs[1] } mainPkg := program.CreatePackage(mainPkginfo) // Create a Module, which contains the LLVM bitcode. modulename := importpath compiler.module = &Module{Module: llvm.NewModule(modulename), Name: 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( runtimePkginfo.Pkg, compiler.module.Module, compiler.llvmtypes, FuncResolver(unit), ) if err != nil { return nil, err } // Create a struct responsible for mapping static types to LLVM types, // and to runtime/dynamic type values. compiler.types = NewTypeMap( importpath, compiler.llvmtypes, compiler.module.Module, compiler.runtime, MethodResolver(unit), ) // Create a Builder, for building LLVM instructions. compiler.builder = llvm.GlobalContext().NewBuilder() defer compiler.builder.Dispose() // Initialise debugging. compiler.debug.module = compiler.module.Module compiler.debug.Fset = impcfg.Fset compiler.debug.Sizes = compiler.llvmtypes mainPkg.Build() unit.translatePackage(mainPkg) compiler.processAnnotations(unit, mainPkginfo) if runtimePkginfo != mainPkginfo { compiler.processAnnotations(unit, runtimePkginfo) } // Finalise debugging. for _, cu := range compiler.debug.cu { compiler.module.AddNamedMetadataOperand( "llvm.dbg.cu", compiler.debug.MDNode(cu), ) } // Export runtime type information. var exportedTypes []types.Type for _, m := range mainPkg.Members { if t, ok := m.(*ssa.Type); ok && ast.IsExported(t.Name()) { exportedTypes = append(exportedTypes, t.Type()) } } compiler.exportRuntimeTypes(exportedTypes, importpath == "runtime") if importpath == "main" { // Wrap "main.main" in a call to runtime.main. if err = compiler.createMainFunction(); err != nil { return nil, fmt.Errorf("failed to create main.main: %v", err) } } else { if err := llgoimporter.Export(buildctx, mainPkg.Object); err != nil { return nil, fmt.Errorf("failed to export package data: %v", err) } } return compiler.module, nil }