Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 1 | //===- subzero/runtime/wasm-runtime.cpp - Subzero WASM runtime source -----===// |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 2 | // |
| 3 | // The Subzero Code Generator |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements the system calls required by the libc that is included |
| 11 | // in WebAssembly programs. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Eric Holk | 179a55d | 2016-05-02 10:42:27 -0700 | [diff] [blame] | 15 | #include <algorithm> |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 16 | #include <cassert> |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 17 | #include <cmath> |
Eric Holk | 179a55d | 2016-05-02 10:42:27 -0700 | [diff] [blame] | 18 | #include <iostream> |
| 19 | #include <vector> |
| 20 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 21 | #include <errno.h> |
| 22 | #include <fcntl.h> |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 23 | #include <math.h> |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 24 | #include <stdint.h> |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> |
| 27 | #include <string.h> |
| 28 | #include <sys/ioctl.h> |
| 29 | #include <sys/types.h> |
| 30 | #include <sys/stat.h> |
| 31 | #include <termios.h> |
| 32 | #include <time.h> |
| 33 | #include <unistd.h> |
| 34 | |
| 35 | #ifdef WASM_TRACE_RUNTIME |
| 36 | #define TRACE_ENTRY() \ |
| 37 | { std::cerr << __func__ << "(...) = "; } |
| 38 | template <typename T> T trace(T x) { |
| 39 | std::cerr << x << std::endl; |
| 40 | return x; |
| 41 | } |
| 42 | void trace() { std::cerr << "(void)" << std::endl; } |
| 43 | #else |
| 44 | #define TRACE_ENTRY() |
| 45 | template <typename T> T trace(T x) { return x; } |
| 46 | void trace() {} |
| 47 | #endif // WASM_TRACE_RUNTIME |
| 48 | |
| 49 | extern "C" { |
Eric Holk | 179a55d | 2016-05-02 10:42:27 -0700 | [diff] [blame] | 50 | char *WASM_MEMORY; |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 51 | extern uint32_t WASM_DATA_SIZE; |
| 52 | extern uint32_t WASM_NUM_PAGES; |
| 53 | } // end of extern "C" |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 54 | |
| 55 | namespace { |
| 56 | uint32_t HeapBreak; |
| 57 | |
| 58 | // TODO (eholk): make all of these constexpr. |
| 59 | const uint32_t PageSizeLog2 = 16; |
| 60 | const uint32_t PageSize = 1 << PageSizeLog2; // 64KB |
| 61 | const uint32_t StackPtrLoc = 1024; // defined by emscripten |
| 62 | |
| 63 | uint32_t pageNum(uint32_t Index) { return Index >> PageSizeLog2; } |
| 64 | } // end of anonymous namespace |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 65 | |
| 66 | namespace env { |
| 67 | double floor(double X) { return std::floor(X); } |
| 68 | |
| 69 | float floor(float X) { return std::floor(X); } |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 70 | } // end of namespace env |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 71 | |
| 72 | // TODO (eholk): move the C parts outside and use C++ name mangling. |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 73 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 74 | namespace { |
| 75 | |
| 76 | /// Some runtime functions need to return pointers. The WasmData struct is used |
| 77 | /// to preallocate space for these on the heap. |
| 78 | struct WasmData { |
| 79 | |
| 80 | /// StrBuf is returned by functions that return strings. |
| 81 | char StrBuf[256]; |
| 82 | }; |
| 83 | |
| 84 | WasmData *GlobalData = NULL; |
| 85 | |
| 86 | int toWasm(void *Ptr) { |
| 87 | return reinterpret_cast<int>(reinterpret_cast<char *>(Ptr) - WASM_MEMORY); |
| 88 | } |
| 89 | |
| 90 | template <typename T> T *wasmPtr(int Index) { |
| 91 | if (pageNum(Index) < WASM_NUM_PAGES) { |
| 92 | return reinterpret_cast<T *>(WASM_MEMORY + Index); |
| 93 | } |
| 94 | abort(); |
| 95 | } |
| 96 | |
| 97 | template <typename T> class WasmPtr { |
| 98 | int Ptr; |
| 99 | |
| 100 | public: |
| 101 | WasmPtr(int Ptr) : Ptr(Ptr) { |
| 102 | // TODO (eholk): make this a static_assert once we have C++11 |
| 103 | assert(sizeof(*this) == sizeof(int)); |
| 104 | } |
| 105 | |
| 106 | WasmPtr(T *Ptr) : Ptr(toWasm(Ptr)) {} |
| 107 | |
| 108 | T &operator*() const { return *asPtr(); } |
| 109 | |
| 110 | T *asPtr() const { return wasmPtr<T>(Ptr); } |
| 111 | |
| 112 | int asInt() const { return Ptr; } |
| 113 | }; |
| 114 | |
| 115 | typedef WasmPtr<char> WasmCharPtr; |
| 116 | |
| 117 | template <typename T> class WasmArray { |
| 118 | int Ptr; |
| 119 | |
| 120 | public: |
| 121 | WasmArray(int Ptr) : Ptr(Ptr) { |
| 122 | // TODO (eholk): make this a static_assert once we have C++11. |
| 123 | assert(sizeof(*this) == sizeof(int)); |
| 124 | } |
| 125 | |
| 126 | T &operator[](unsigned int Index) const { return wasmPtr<T>(Ptr)[Index]; } |
| 127 | }; |
| 128 | } // end of anonymous namespace |
| 129 | |
| 130 | // TODO (eholk): move the C parts outside and use C++ name mangling. |
| 131 | extern "C" { |
| 132 | |
| 133 | void __Sz_bounds_fail() { |
| 134 | std::cerr << "Bounds check failure" << std::endl; |
| 135 | abort(); |
| 136 | } |
| 137 | |
| 138 | void __Sz_indirect_fail() { |
| 139 | std::cerr << "Invalid indirect call target" << std::endl; |
| 140 | abort(); |
| 141 | } |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 142 | |
Eric Holk | 179a55d | 2016-05-02 10:42:27 -0700 | [diff] [blame] | 143 | extern char WASM_DATA_INIT[]; |
| 144 | |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 145 | void env$$abort() { |
| 146 | fprintf(stderr, "Aborting...\n"); |
| 147 | abort(); |
| 148 | } |
| 149 | |
| 150 | void env$$_abort() { env$$abort(); } |
| 151 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 152 | double env$$floor_f(float X) { |
| 153 | TRACE_ENTRY(); |
| 154 | return env::floor(X); |
| 155 | } |
| 156 | double env$$floor_d(double X) { |
| 157 | TRACE_ENTRY(); |
| 158 | return env::floor(X); |
| 159 | } |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 160 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 161 | void env$$exit(int Status) { |
| 162 | TRACE_ENTRY(); |
| 163 | exit(Status); |
| 164 | } |
| 165 | void env$$_exit(int Status) { |
| 166 | TRACE_ENTRY(); |
| 167 | env$$exit(Status); |
| 168 | } |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 169 | |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 170 | #define UNIMPLEMENTED(f) \ |
| 171 | void env$$##f() { \ |
| 172 | fprintf(stderr, "Unimplemented: " #f "\n"); \ |
| 173 | abort(); \ |
| 174 | } |
| 175 | |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 176 | int32_t env$$sbrk(int32_t Increment) { |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 177 | TRACE_ENTRY(); |
| 178 | uint32_t OldBreak = HeapBreak; |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 179 | HeapBreak += Increment; |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 180 | return trace(OldBreak); |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 181 | } |
| 182 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 183 | UNIMPLEMENTED(__addtf3) |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 184 | UNIMPLEMENTED(__assert_fail) |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 185 | UNIMPLEMENTED(__builtin_apply) |
| 186 | UNIMPLEMENTED(__builtin_apply_args) |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 187 | UNIMPLEMENTED(__builtin_isinff) |
| 188 | UNIMPLEMENTED(__builtin_isinfl) |
| 189 | UNIMPLEMENTED(__builtin_malloc) |
| 190 | UNIMPLEMENTED(__divtf3) |
| 191 | UNIMPLEMENTED(__eqtf2) |
| 192 | UNIMPLEMENTED(__extenddftf2) |
| 193 | UNIMPLEMENTED(__extendsftf2) |
| 194 | UNIMPLEMENTED(__fixsfti) |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 195 | UNIMPLEMENTED(__fixtfdi) |
| 196 | UNIMPLEMENTED(__fixtfsi) |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 197 | UNIMPLEMENTED(__fixunstfsi) |
| 198 | UNIMPLEMENTED(__floatditf) |
| 199 | UNIMPLEMENTED(__floatsitf) |
| 200 | UNIMPLEMENTED(__floatunsitf) |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 201 | UNIMPLEMENTED(__getf2) |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 202 | UNIMPLEMENTED(__letf2) |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 203 | UNIMPLEMENTED(__lttf2) |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 204 | UNIMPLEMENTED(__multf3) |
| 205 | UNIMPLEMENTED(__multi3) |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 206 | UNIMPLEMENTED(__netf2) |
| 207 | UNIMPLEMENTED(__subtf3) |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 208 | UNIMPLEMENTED(__syscall140) // sys_llseek |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 209 | UNIMPLEMENTED(__syscall221) // sys_fcntl64 |
| 210 | UNIMPLEMENTED(__trunctfdf2) |
| 211 | UNIMPLEMENTED(__trunctfsf2) |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 212 | UNIMPLEMENTED(__unordtf2) |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 213 | UNIMPLEMENTED(longjmp) |
| 214 | UNIMPLEMENTED(pthread_cleanup_pop) |
| 215 | UNIMPLEMENTED(pthread_cleanup_push) |
| 216 | UNIMPLEMENTED(pthread_self) |
| 217 | UNIMPLEMENTED(setjmp) |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 218 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 219 | extern int __szwasm_main(int, WasmPtr<WasmCharPtr>); |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 220 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 221 | #define WASM_REF(Type, Index) (WasmPtr<Type>(Index).asPtr()) |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 222 | #define WASM_DEREF(Type, Index) (*WASM_REF(Type, Index)) |
| 223 | |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 224 | int main(int argc, const char **argv) { |
Eric Holk | 179a55d | 2016-05-02 10:42:27 -0700 | [diff] [blame] | 225 | // Create the heap. |
| 226 | std::vector<char> WasmHeap(WASM_NUM_PAGES << PageSizeLog2); |
| 227 | WASM_MEMORY = WasmHeap.data(); |
| 228 | std::copy(WASM_DATA_INIT, WASM_DATA_INIT + WASM_DATA_SIZE, WasmHeap.begin()); |
| 229 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 230 | // TODO (eholk): align these allocations correctly. |
| 231 | |
| 232 | // Allocate space for the global data. |
| 233 | HeapBreak = WASM_DATA_SIZE; |
| 234 | GlobalData = WASM_REF(WasmData, HeapBreak); |
| 235 | HeapBreak += sizeof(WasmData); |
| 236 | |
| 237 | // copy the command line arguments. |
| 238 | WasmPtr<WasmCharPtr> WasmArgV = HeapBreak; |
| 239 | WasmPtr<char> *WasmArgVPtr = WasmArgV.asPtr(); |
| 240 | HeapBreak += argc * sizeof(*WasmArgVPtr); |
| 241 | |
| 242 | for (int i = 0; i < argc; ++i) { |
| 243 | WasmArgVPtr[i] = HeapBreak; |
| 244 | strcpy(WASM_REF(char, HeapBreak), argv[i]); |
| 245 | HeapBreak += strlen(argv[i]) + 1; |
| 246 | } |
| 247 | |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 248 | // Initialize the break to the nearest page boundary after the data segment |
| 249 | HeapBreak = (WASM_DATA_SIZE + PageSize - 1) & ~(PageSize - 1); |
| 250 | |
| 251 | // Initialize the stack pointer. |
| 252 | WASM_DEREF(int32_t, StackPtrLoc) = WASM_NUM_PAGES << PageSizeLog2; |
| 253 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 254 | return __szwasm_main(argc, WasmArgV); |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 255 | } |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 256 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 257 | int env$$abs(int a) { |
| 258 | TRACE_ENTRY(); |
| 259 | return trace(abs(a)); |
| 260 | } |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 261 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 262 | clock_t env$$clock() { |
| 263 | TRACE_ENTRY(); |
| 264 | return trace(clock()); |
| 265 | } |
| 266 | |
| 267 | int env$$ctime(WasmPtr<time_t> Time) { |
| 268 | TRACE_ENTRY(); |
| 269 | char *CTime = ctime(Time.asPtr()); |
| 270 | strncpy(GlobalData->StrBuf, CTime, sizeof(GlobalData->StrBuf)); |
| 271 | GlobalData->StrBuf[sizeof(GlobalData->StrBuf) - 1] = '\0'; |
| 272 | return trace(WasmPtr<char>(GlobalData->StrBuf).asInt()); |
| 273 | } |
| 274 | |
| 275 | double env$$pow(double x, double y) { |
| 276 | TRACE_ENTRY(); |
| 277 | return trace(pow(x, y)); |
| 278 | } |
| 279 | |
| 280 | time_t env$$time(WasmPtr<time_t> Time) { |
| 281 | TRACE_ENTRY(); |
| 282 | time_t *TimePtr = WASM_REF(time_t, Time); |
| 283 | return trace(time(TimePtr)); |
| 284 | } |
| 285 | |
| 286 | // lock and unlock are no-ops in wasm.js, so we mimic that behavior. |
| 287 | void env$$__lock(int32_t) { |
| 288 | TRACE_ENTRY(); |
| 289 | trace(); |
| 290 | } |
| 291 | |
| 292 | void env$$__unlock(int32_t) { |
| 293 | TRACE_ENTRY(); |
| 294 | trace(); |
| 295 | } |
| 296 | |
| 297 | /// sys_read |
| 298 | int env$$__syscall3(int Which, WasmArray<int> VarArgs) { |
| 299 | TRACE_ENTRY(); |
| 300 | int Fd = VarArgs[0]; |
| 301 | int Buffer = VarArgs[1]; |
| 302 | int Length = VarArgs[2]; |
| 303 | |
| 304 | return trace(read(Fd, WASM_REF(char *, Buffer), Length)); |
| 305 | } |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 306 | |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 307 | /// sys_write |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 308 | int env$$__syscall4(int Which, WasmArray<int> VarArgs) { |
| 309 | TRACE_ENTRY(); |
| 310 | int Fd = VarArgs[0]; |
| 311 | int Buffer = VarArgs[1]; |
| 312 | int Length = VarArgs[2]; |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 313 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 314 | return trace(write(Fd, WASM_REF(char *, Buffer), Length)); |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 315 | } |
| 316 | |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 317 | /// sys_open |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 318 | int env$$__syscall5(int Which, WasmArray<int> VarArgs) { |
| 319 | TRACE_ENTRY(); |
| 320 | int WasmPath = VarArgs[0]; |
| 321 | int Flags = VarArgs[1]; |
| 322 | int Mode = VarArgs[2]; |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 323 | const char *Path = WASM_REF(char, WasmPath); |
| 324 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 325 | return trace(open(Path, Flags, Mode)); |
| 326 | } |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 327 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 328 | /// sys_close |
| 329 | int env$$__syscall6(int Which, WasmArray<int> VarArgs) { |
| 330 | TRACE_ENTRY(); |
| 331 | int Fd = VarArgs[0]; |
| 332 | |
| 333 | return trace(close(Fd)); |
| 334 | } |
| 335 | |
| 336 | /// sys_unlink |
| 337 | int env$$__syscall10(int Which, WasmArray<int> VarArgs) { |
| 338 | TRACE_ENTRY(); |
| 339 | int WasmPath = VarArgs[0]; |
| 340 | const char *Path = WASM_REF(char, WasmPath); |
| 341 | |
| 342 | return trace(unlink(Path)); |
Eric Holk | 085bdae | 2016-04-18 15:08:19 -0700 | [diff] [blame] | 343 | } |
| 344 | |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 345 | /// sys_getpid |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 346 | int env$$__syscall20(int Which, WasmArray<int> VarArgs) { |
| 347 | TRACE_ENTRY(); |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 348 | (void)Which; |
| 349 | (void)VarArgs; |
| 350 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 351 | return trace(getpid()); |
| 352 | } |
| 353 | |
| 354 | /// sys_rmdir |
| 355 | int env$$__syscall40(int Which, WasmArray<int> VarArgs) { |
| 356 | TRACE_ENTRY(); |
| 357 | int WasmPath = VarArgs[0]; |
| 358 | const char *Path = WASM_REF(char, WasmPath); |
| 359 | |
| 360 | return trace(rmdir(Path)); |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 361 | } |
| 362 | |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 363 | /// sys_ioctl |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 364 | int env$$__syscall54(int Which, WasmArray<int> VarArgs) { |
| 365 | TRACE_ENTRY(); |
| 366 | int Fd = VarArgs[0]; |
| 367 | int Op = VarArgs[1]; |
| 368 | int ArgP = VarArgs[2]; |
| 369 | |
| 370 | switch (Op) { |
| 371 | case TCGETS: { |
| 372 | // struct termios has no pointers. Otherwise, we'd have to rewrite them. |
| 373 | struct termios *TermIOS = WASM_REF(struct termios, ArgP); |
| 374 | return trace(ioctl(Fd, TCGETS, TermIOS)); |
| 375 | } |
| 376 | default: |
| 377 | // TODO (eholk): implement more ioctls |
| 378 | return trace(-ENOTTY); |
| 379 | } |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 380 | } |
| 381 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 382 | struct IoVec { |
| 383 | WasmPtr<char> Ptr; |
| 384 | int Length; |
| 385 | }; |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 386 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 387 | /// sys_readv |
| 388 | int env$$__syscall145(int Which, WasmArray<int> VarArgs) { |
| 389 | TRACE_ENTRY(); |
| 390 | int Fd = VarArgs[0]; |
| 391 | WasmArray<IoVec> Iov = VarArgs[1]; |
| 392 | int Iovcnt = VarArgs[2]; |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 393 | |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 394 | int Count = 0; |
| 395 | |
| 396 | for (int I = 0; I < Iovcnt; ++I) { |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 397 | int Curr = read(Fd, Iov[I].Ptr.asPtr(), Iov[I].Length); |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 398 | |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 399 | if (Curr < 0) { |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 400 | return trace(-1); |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 401 | } |
| 402 | Count += Curr; |
| 403 | } |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 404 | return trace(Count); |
| 405 | } |
| 406 | |
| 407 | /// sys_writev |
| 408 | int env$$__syscall146(int Which, WasmArray<int> VarArgs) { |
| 409 | TRACE_ENTRY(); |
| 410 | int Fd = VarArgs[0]; |
| 411 | WasmArray<IoVec> Iov = VarArgs[1]; |
| 412 | int Iovcnt = VarArgs[2]; |
| 413 | |
| 414 | int Count = 0; |
| 415 | |
| 416 | for (int I = 0; I < Iovcnt; ++I) { |
| 417 | int Curr = write(Fd, Iov[I].Ptr.asPtr(), Iov[I].Length); |
| 418 | |
| 419 | if (Curr < 0) { |
| 420 | return trace(-1); |
| 421 | } |
| 422 | Count += Curr; |
| 423 | } |
| 424 | return trace(Count); |
Eric Holk | 67c7c41 | 2016-04-15 13:05:37 -0700 | [diff] [blame] | 425 | } |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 426 | |
| 427 | /// sys_mmap_pgoff |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 428 | int env$$__syscall192(int Which, WasmArray<int> VarArgs) { |
| 429 | TRACE_ENTRY(); |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 430 | (void)Which; |
| 431 | (void)VarArgs; |
| 432 | |
| 433 | // TODO (eholk): figure out how to implement this. |
| 434 | |
Eric Holk | 87def2c | 2016-04-29 14:42:17 -0700 | [diff] [blame] | 435 | return trace(-ENOMEM); |
Eric Holk | 4aae81a | 2016-04-25 12:52:49 -0700 | [diff] [blame] | 436 | } |
Eric Holk | 29acb57 | 2016-04-22 09:34:41 -0700 | [diff] [blame] | 437 | } // end of extern "C" |