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