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