func runMainFunction(m *llgo.Module) (output []string, err error) { runtimeModule, err := getRuntimeModuleFile() if err != nil { return } err = llvm.VerifyModule(m.Module, llvm.ReturnStatusAction) if err != nil { return nil, fmt.Errorf("Verification failed: %v", err) } bcpath := filepath.Join(tempdir, "test.bc") bcfile, err := os.Create(bcpath) if err != nil { return nil, err } llvm.WriteBitcodeToFile(m.Module, bcfile) bcfile.Close() cmd := exec.Command("llvm-link", "-o", bcpath, bcpath, runtimeModule) data, err := cmd.CombinedOutput() if err != nil { output = strings.Split(strings.TrimSpace(string(data)), "\n") return output, fmt.Errorf("llvm-link failed: %v", err) } exepath := filepath.Join(tempdir, "test") args := []string{"-pthread", "-o", exepath, bcpath} if runtime.GOOS != "darwin" { // TODO(q): -g breaks badly on my system at the moment, so is not enabled on darwin for now args = append([]string{"-g"}, args...) } cmd = exec.Command("clang", args...) data, err = cmd.CombinedOutput() if err != nil { output = strings.Split(strings.TrimSpace(string(data)), "\n") return output, fmt.Errorf("clang failed: %v", err) } cmd = exec.Command(exepath) data, err = cmd.CombinedOutput() output = strings.Split(strings.TrimSpace(string(data)), "\n") return output, err }
func writeObjectFile(m *llgo.Module) error { var outfile *os.File switch *outputFile { case "-": outfile = os.Stdout default: var err error outfile, err = os.Create(*outputFile) if err != nil { return err } } err := llvm.VerifyModule(m.Module, llvm.ReturnStatusAction) if err != nil { return fmt.Errorf("Verification failed: %v", err) } return llvm.WriteBitcodeToFile(m.Module, outfile) }
func test() { llvm.LinkInMCJIT() llvm.InitializeNativeTarget() llvm.InitializeNativeAsmPrinter() mod := llvm.NewModule("fac_module") // don't do that, because ExecutionEngine takes ownership over module //defer mod.Dispose() fac_args := []llvm.Type{llvm.Int32Type()} fac_type := llvm.FunctionType(llvm.Int32Type(), fac_args, false) fac := llvm.AddFunction(mod, "fac", fac_type) fac.SetFunctionCallConv(llvm.CCallConv) n := fac.Param(0) entry := llvm.AddBasicBlock(fac, "entry") iftrue := llvm.AddBasicBlock(fac, "iftrue") iffalse := llvm.AddBasicBlock(fac, "iffalse") end := llvm.AddBasicBlock(fac, "end") builder := llvm.NewBuilder() defer builder.Dispose() builder.SetInsertPointAtEnd(entry) If := builder.CreateICmp(llvm.IntEQ, n, llvm.ConstInt(llvm.Int32Type(), 0, false), "cmptmp") builder.CreateCondBr(If, iftrue, iffalse) builder.SetInsertPointAtEnd(iftrue) res_iftrue := llvm.ConstInt(llvm.Int32Type(), 1, false) builder.CreateBr(end) builder.SetInsertPointAtEnd(iffalse) n_minus := builder.CreateSub(n, llvm.ConstInt(llvm.Int32Type(), 1, false), "subtmp") call_fac_args := []llvm.Value{n_minus} call_fac := builder.CreateCall(fac, call_fac_args, "calltmp") res_iffalse := builder.CreateMul(n, call_fac, "multmp") builder.CreateBr(end) builder.SetInsertPointAtEnd(end) res := builder.CreatePHI(llvm.Int32Type(), "result") phi_vals := []llvm.Value{res_iftrue, res_iffalse} phi_blocks := []llvm.BasicBlock{iftrue, iffalse} res.AddIncoming(phi_vals, phi_blocks) builder.CreateRet(res) err := llvm.VerifyModule(mod, llvm.ReturnStatusAction) if err != nil { fmt.Println(err) return } engine, err := llvm.NewMCJITCompiler(mod, llvm.MCJITCompilerOptions{OptLevel: 2}) if err != nil { fmt.Println(err) return } defer engine.Dispose() pass := llvm.NewPassManager() defer pass.Dispose() pass.Add(engine.TargetData()) pass.AddConstantPropagationPass() pass.AddInstructionCombiningPass() pass.AddPromoteMemoryToRegisterPass() pass.AddGVNPass() pass.AddCFGSimplificationPass() pass.Run(mod) mod.Dump() exec_args := []llvm.GenericValue{llvm.NewGenericValueFromInt(llvm.Int32Type(), 10, false)} exec_res := engine.RunFunction(fac, exec_args) fmt.Println("-----------------------------------------") fmt.Println("Running fac(10) with JIT...") fmt.Printf("Result: %d\n", exec_res.Int(false)) }