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 runMainFunction(m *llgo.Module) (output []string, err error) { addExterns(m) err = addRuntime(m) if err != nil { return } err = llvm.VerifyModule(m.Module, llvm.ReturnStatusAction) if err != nil { err = fmt.Errorf("Verification failed: %v", err) return } engine, err := llvm.NewExecutionEngine(m.Module) if err != nil { return } defer engine.Dispose() fn := engine.FindFunction("main") if fn.IsNil() { err = fmt.Errorf("Couldn't find function 'main'") 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) // FIXME implement and use RunFunctionAsMain argv0 := []byte("llgo-test\000") var envs [1]*byte argv0ptr := &argv0 exec_args := []llvm.GenericValue{ llvm.NewGenericValueFromInt(llvm.Int32Type(), 1, true), llvm.NewGenericValueFromPointer(unsafe.Pointer(&argv0ptr)), llvm.NewGenericValueFromPointer(unsafe.Pointer(&envs)), } 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 }