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