mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 19:17:47 +00:00
runtime: implement command line arguments in hosted environments
Implement command line arguments for Linux, MacOS and WASI.
This commit is contained in:
committed by
Ron Evans
parent
c47cdfa66f
commit
7b761fac78
@@ -23,7 +23,9 @@ func GOROOT() string {
|
||||
return "/usr/local/go"
|
||||
}
|
||||
|
||||
// TODO: fill with real args.
|
||||
// This is the default set of arguments, if nothing else has been set.
|
||||
// This may be overriden by modifying this global at runtime init (for example,
|
||||
// on Linux where there are real command line arguments).
|
||||
var args = []string{"/proc/self/exe"}
|
||||
|
||||
//go:linkname os_runtime_args os.runtime_args
|
||||
@@ -47,6 +49,9 @@ func memmove(dst, src unsafe.Pointer, size uintptr)
|
||||
// llvm.memset.p0i8.i32(ptr, 0, size, false).
|
||||
func memzero(ptr unsafe.Pointer, size uintptr)
|
||||
|
||||
//export strlen
|
||||
func strlen(ptr unsafe.Pointer) uintptr
|
||||
|
||||
// Compare two same-size buffers for equality.
|
||||
func memequal(x, y unsafe.Pointer, n uintptr) bool {
|
||||
for i := uintptr(0); i < n; i++ {
|
||||
|
||||
@@ -43,9 +43,34 @@ func postinit() {}
|
||||
|
||||
// Entry point for Go. Initialize all packages and call main.main().
|
||||
//export main
|
||||
func main() int {
|
||||
func main(argc int32, argv *unsafe.Pointer) int {
|
||||
preinit()
|
||||
|
||||
// Make args global big enough so that it can store all command line
|
||||
// arguments. Unfortunately this has to be done with some magic as the heap
|
||||
// is not yet initialized.
|
||||
argsSlice := (*struct {
|
||||
ptr unsafe.Pointer
|
||||
len uintptr
|
||||
cap uintptr
|
||||
})(unsafe.Pointer(&args))
|
||||
argsSlice.ptr = malloc(uintptr(argc) * (unsafe.Sizeof(uintptr(0))) * 3)
|
||||
argsSlice.len = 0
|
||||
argsSlice.cap = uintptr(argc)
|
||||
|
||||
// Initialize command line parameters.
|
||||
for *argv != nil {
|
||||
// Convert the C string to a Go string.
|
||||
length := strlen(*argv)
|
||||
argString := _string{
|
||||
length: length,
|
||||
ptr: (*byte)(*argv),
|
||||
}
|
||||
args = append(args, *(*string)(unsafe.Pointer(&argString)))
|
||||
// This is the Go equivalent of "argc++" in C.
|
||||
argv = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + unsafe.Sizeof(argv)))
|
||||
}
|
||||
|
||||
// Obtain the initial stack pointer right before calling the run() function.
|
||||
// The run function has been moved to a separate (non-inlined) function so
|
||||
// that the correct stack pointer is read.
|
||||
@@ -65,9 +90,6 @@ func runMain() {
|
||||
//go:extern environ
|
||||
var environ *unsafe.Pointer
|
||||
|
||||
//export strlen
|
||||
func strlen(ptr unsafe.Pointer) uintptr
|
||||
|
||||
//go:linkname syscall_runtime_envs syscall.runtime_envs
|
||||
func syscall_runtime_envs() []string {
|
||||
// Count how many environment variables there are.
|
||||
|
||||
@@ -15,6 +15,11 @@ func _start() {
|
||||
run()
|
||||
}
|
||||
|
||||
//go:linkname syscall_runtime_envs syscall.runtime_envs
|
||||
func syscall_runtime_envs() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
var handleEvent func()
|
||||
|
||||
//go:linkname setEventHandler syscall/js.setEventHandler
|
||||
|
||||
@@ -21,6 +21,33 @@ func _start() {
|
||||
run()
|
||||
}
|
||||
|
||||
// Read the command line arguments from WASI.
|
||||
// For example, they can be passed to a program with wasmtime like this:
|
||||
//
|
||||
// wasmtime ./program.wasm arg1 arg2
|
||||
func init() {
|
||||
// Read the number of args (argc) and the buffer size required to store all
|
||||
// these args (argv).
|
||||
var argc, argv_buf_size uint32
|
||||
args_sizes_get(&argc, &argv_buf_size)
|
||||
|
||||
// Obtain the command line arguments
|
||||
argsSlice := make([]unsafe.Pointer, argc)
|
||||
buf := make([]byte, argv_buf_size)
|
||||
args_get(&argsSlice[0], unsafe.Pointer(&buf[0]))
|
||||
|
||||
// Convert the array of C strings to an array of Go strings.
|
||||
args = make([]string, argc)
|
||||
for i, cstr := range argsSlice {
|
||||
length := strlen(cstr)
|
||||
argString := _string{
|
||||
length: length,
|
||||
ptr: (*byte)(cstr),
|
||||
}
|
||||
args[i] = *(*string)(unsafe.Pointer(&argString))
|
||||
}
|
||||
}
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
return int64(ticks)
|
||||
}
|
||||
@@ -62,7 +89,15 @@ func ticks() timeUnit {
|
||||
return timeUnit(nano)
|
||||
}
|
||||
|
||||
// Implementations of wasi_unstable APIs
|
||||
// Implementations of WASI APIs
|
||||
|
||||
//go:wasm-module wasi_snapshot_preview1
|
||||
//export args_get
|
||||
func args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16)
|
||||
|
||||
//go:wasm-module wasi_snapshot_preview1
|
||||
//export args_sizes_get
|
||||
func args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16)
|
||||
|
||||
//go:wasm-module wasi_snapshot_preview1
|
||||
//export clock_time_get
|
||||
|
||||
Reference in New Issue
Block a user