func runFunction(m *llgo.Module, name string) (output []string, err error) { addExterns(m) err = addRuntime(m) if err != nil { return } err = llvm.VerifyModule(m.Module, llvm.ReturnStatusAction) if err != nil { return } engine, err := llvm.NewJITCompiler(m.Module, 0) if err != nil { return } defer engine.Dispose() fn := engine.FindFunction(name) if fn.IsNil() { err = fmt.Errorf("Couldn't find function '%s'", name) return } // Redirect stdout to a pipe. pipe_fds := make([]int, 2) err = syscall.Pipe(pipe_fds) if err != nil { return } defer syscall.Close(pipe_fds[0]) defer syscall.Close(pipe_fds[1]) old_stdout, err := syscall.Dup(syscall.Stdout) if err != nil { return } defer syscall.Close(old_stdout) err = syscall.Dup2(pipe_fds[1], syscall.Stdout) if err != nil { return } defer syscall.Dup2(old_stdout, syscall.Stdout) c := make(chan string) go readPipe(pipe_fds[0], c) exec_args := []llvm.GenericValue{} engine.RunStaticConstructors() engine.RunFunction(fn, exec_args) defer engine.RunStaticDestructors() // Call fflush to flush stdio (printf), then sync and close the write // end of the pipe. fflush := engine.FindFunction("fflush") ptr0 := unsafe.Pointer(uintptr(0)) exec_args = []llvm.GenericValue{llvm.NewGenericValueFromPointer(ptr0)} engine.RunFunction(fflush, exec_args) syscall.Fsync(pipe_fds[1]) syscall.Close(pipe_fds[1]) syscall.Close(syscall.Stdout) output_str := <-c output = strings.Split(strings.TrimSpace(output_str), "\n") return }
func test() { llvm.LinkInJIT() llvm.InitializeNativeTarget() 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.NewJITCompiler(mod, 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)) }