示例#1
0
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
}
示例#2
0
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
}