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 |