func (in *interp) loadPackage(pkgpath string) (*types.Package, error) { pkg, err := in.copts.Importer(in.pkgmap, pkgpath) if err == nil { return pkg, nil } buildpkg, err := build.Import(pkgpath, ".", 0) if err != nil { return nil, err } if len(buildpkg.CgoFiles) != 0 { return nil, fmt.Errorf("%s: cannot load cgo package", pkgpath) } for _, imp := range buildpkg.Imports { _, err := in.loadPackage(imp) if err != nil { return nil, err } } fmt.Printf("# %s\n", pkgpath) inputs := make([]string, len(buildpkg.GoFiles)) for i, file := range buildpkg.GoFiles { inputs[i] = filepath.Join(buildpkg.Dir, file) } fset := token.NewFileSet() files, err := driver.ParseFiles(fset, inputs) if err != nil { return nil, err } return in.loadSourcePackage(fset, files, pkgpath, in.copts) }
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") } }