func (v *Codegen) createBitcode(file *parser.Module) string { filename := file.Name + ".bc" fileHandle, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { v.err("Couldn't create bitcode file "+filename+": `%s`", err.Error()) } defer fileHandle.Close() if err := llvm.WriteBitcodeToFile(file.Module, fileHandle); err != nil { v.err("failed to write bitcode to file for "+file.Name+": `%s`", err.Error()) } return filename }
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") } }