Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: runtime/wasm-runtime.cpp

Issue 1918213003: Subzero, Wasm: Dynamically reallocate read buffer. Runtime improvements. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Formatting Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
OLDNEW
« no previous file with comments | « pydir/wasm-run-torture-tests.py ('k') | src/IceCompiler.cpp » ('j') | src/IceCompiler.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698