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 |