github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/runtime_wasip1.go (about) 1 //go:build wasip1 2 3 package runtime 4 5 import ( 6 "unsafe" 7 ) 8 9 type timeUnit int64 10 11 // libc constructors 12 // 13 //export __wasm_call_ctors 14 func __wasm_call_ctors() 15 16 //export _start 17 func _start() { 18 // These need to be initialized early so that the heap can be initialized. 19 heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) 20 heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize) 21 run() 22 } 23 24 // Read the command line arguments from WASI. 25 // For example, they can be passed to a program with wasmtime like this: 26 // 27 // wasmtime run ./program.wasm arg1 arg2 28 func init() { 29 __wasm_call_ctors() 30 } 31 32 var args []string 33 34 //go:linkname os_runtime_args os.runtime_args 35 func os_runtime_args() []string { 36 if args == nil { 37 // Read the number of args (argc) and the buffer size required to store 38 // all these args (argv). 39 var argc, argv_buf_size uint32 40 args_sizes_get(&argc, &argv_buf_size) 41 if argc == 0 { 42 return nil 43 } 44 45 // Obtain the command line arguments 46 argsSlice := make([]unsafe.Pointer, argc) 47 buf := make([]byte, argv_buf_size) 48 args_get(&argsSlice[0], unsafe.Pointer(&buf[0])) 49 50 // Convert the array of C strings to an array of Go strings. 51 args = make([]string, argc) 52 for i, cstr := range argsSlice { 53 length := strlen(cstr) 54 argString := _string{ 55 length: length, 56 ptr: (*byte)(cstr), 57 } 58 args[i] = *(*string)(unsafe.Pointer(&argString)) 59 } 60 } 61 return args 62 } 63 64 func ticksToNanoseconds(ticks timeUnit) int64 { 65 return int64(ticks) 66 } 67 68 func nanosecondsToTicks(ns int64) timeUnit { 69 return timeUnit(ns) 70 } 71 72 const timePrecisionNanoseconds = 1000 // TODO: how can we determine the appropriate `precision`? 73 74 var ( 75 sleepTicksSubscription = __wasi_subscription_t{ 76 userData: 0, 77 u: __wasi_subscription_u_t{ 78 tag: __wasi_eventtype_t_clock, 79 u: __wasi_subscription_clock_t{ 80 id: 0, 81 timeout: 0, 82 precision: timePrecisionNanoseconds, 83 flags: 0, 84 }, 85 }, 86 } 87 sleepTicksResult = __wasi_event_t{} 88 sleepTicksNEvents uint32 89 ) 90 91 func sleepTicks(d timeUnit) { 92 sleepTicksSubscription.u.u.timeout = uint64(d) 93 poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents) 94 } 95 96 func ticks() timeUnit { 97 var nano uint64 98 clock_time_get(0, timePrecisionNanoseconds, &nano) 99 return timeUnit(nano) 100 } 101 102 // Implementations of WASI APIs 103 104 //go:wasmimport wasi_snapshot_preview1 args_get 105 func args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16) 106 107 //go:wasmimport wasi_snapshot_preview1 args_sizes_get 108 func args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16) 109 110 //go:wasmimport wasi_snapshot_preview1 clock_time_get 111 func clock_time_get(clockid uint32, precision uint64, time *uint64) (errno uint16) 112 113 //go:wasmimport wasi_snapshot_preview1 poll_oneoff 114 func poll_oneoff(in *__wasi_subscription_t, out *__wasi_event_t, nsubscriptions uint32, nevents *uint32) (errno uint16) 115 116 type __wasi_eventtype_t = uint8 117 118 const ( 119 __wasi_eventtype_t_clock __wasi_eventtype_t = 0 120 // TODO: __wasi_eventtype_t_fd_read __wasi_eventtype_t = 1 121 // TODO: __wasi_eventtype_t_fd_write __wasi_eventtype_t = 2 122 ) 123 124 type ( 125 // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription-record 126 __wasi_subscription_t struct { 127 userData uint64 128 u __wasi_subscription_u_t 129 } 130 131 __wasi_subscription_u_t struct { 132 tag __wasi_eventtype_t 133 134 // TODO: support fd_read/fd_write event 135 u __wasi_subscription_clock_t 136 } 137 138 // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription_clock-record 139 __wasi_subscription_clock_t struct { 140 id uint32 141 timeout uint64 142 precision uint64 143 flags uint16 144 } 145 ) 146 147 type ( 148 // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-event-record 149 __wasi_event_t struct { 150 userData uint64 151 errno uint16 152 eventType __wasi_eventtype_t 153 154 // only used for fd_read or fd_write events 155 // TODO: support fd_read/fd_write event 156 _ struct { 157 nBytes uint64 158 flags uint16 159 } 160 } 161 )