1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for
3 // full license information.
4 
5 /*
6  * Exercise lots of different kinds of C++ EH frames.  Compile this with
7  * every combination of opts you can to stress the C++ EH frame code in the
8  * backend.
9  */
10 
11 #include <stdio.h>
12 #include <malloc.h>
13 #include <stdarg.h>
14 #include <memory.h>
15 
16 #ifndef ALIGN
17 #define ALIGN 64
18 #endif
19 
20 #define ARG(x) &x, sizeof(x)
21 #define ARG2(x) ARG(x), ARG(x)
22 #define ARG5(x) ARG(x), ARG(x), ARG(x), ARG(x), ARG(x)
23 
24 extern int TestFunc(int, ...);
25 
26 int failures;
27 
28 int one = 1;
29 int zero = 0;
30 
31 size_t global = 16;
32 volatile bool TestFuncThrows;
33 
34 struct SmallObj {
35   int x;
36 };
37 
38 struct BigObj {
39   char x[1024];
40 };
41 
42 int Simple(int arg) {
43   puts(__FUNCTION__);
44   int res = 0;
45   SmallObj f;
46   __try { TestFunc(1, ARG(f), ARG(res), ARG(arg), NULL); }
47   __finally { res = TestFunc(1, ARG(f), ARG(res), ARG(arg), NULL); }
48   return res;
49 }
50 
51 int Try(int arg) {
52   puts(__FUNCTION__);
53   int res = 0;
54   SmallObj f;
55   __try { res = TestFunc(1, ARG(f), ARG(res), ARG(arg), NULL); }
56   __except(TestFunc(2, ARG(f), ARG(res), ARG(arg), NULL), zero) {
57     res = TestFunc(2, ARG(f), ARG(res), ARG(arg), NULL);
58   }
59   return res;
60 }
61 
62 int GSCookie(int arg) {
63   puts(__FUNCTION__);
64   int res = 0;
65   char buf[16];
66   SmallObj f;
67   __try { TestFunc(1, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL); }
68   __finally { res = TestFunc(1, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL); }
69   return res;
70 }
71 
72 int TryAndGSCookie(int arg) {
73   puts(__FUNCTION__);
74   int res = 0;
75   char buf[16];
76   SmallObj f;
77   __try { res = TestFunc(1, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL); }
78   __except(TestFunc(2, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL), zero) {
79     res = TestFunc(2, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL);
80   }
81   return res;
82 }
83 
84 int Align(int arg) {
85   puts(__FUNCTION__);
86   int res = 0;
87   __declspec(align(ALIGN)) double d[4];
88   SmallObj f;
89   __try { TestFunc(1, ARG(d), ARG(f), ARG(res), ARG(arg), NULL); }
90   __finally { res = TestFunc(1, ARG(d), ARG(f), ARG(res), ARG(arg), NULL); }
91   return res;
92 }
93 
94 int TryAndAlign(int arg) {
95   puts(__FUNCTION__);
96   int res = 0;
97   __declspec(align(ALIGN)) double d[4];
98   SmallObj f;
99   __try { res = TestFunc(1, ARG(d), ARG(f), ARG(res), ARG(arg), NULL); }
100   __except(TestFunc(2, ARG(d), ARG(f), ARG(res), ARG(arg), NULL), zero) {
101     res = TestFunc(2, ARG(d), ARG(f), ARG(res), ARG(arg), NULL);
102   }
103   return res;
104 }
105 
106 int GSCookieAndAlign(int arg) {
107   puts(__FUNCTION__);
108   int res = 0;
109   char buf[16];
110   __declspec(align(ALIGN)) double d[4];
111   SmallObj f;
112   __try { TestFunc(1, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL); }
113   __finally {
114     res = TestFunc(1, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL);
115   }
116   return res;
117 }
118 
119 int TryAndGSCookieAndAlign(int arg) {
120   puts(__FUNCTION__);
121   int res = 0;
122   char buf[16];
123   __declspec(align(ALIGN)) double d[4];
124   SmallObj f;
125   __try {
126     res = TestFunc(1, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL);
127   }
128   __except(TestFunc(2, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL),
129            zero) {
130     res = TestFunc(2, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL);
131   }
132   return res;
133 }
134 
135 int Alloca(int arg) {
136   puts(__FUNCTION__);
137   int res = 0;
138   SmallObj f;
139   __try {
140     TestFunc(1, _alloca(global), global, ARG(f), ARG(res), ARG(arg), NULL);
141   }
142   __finally { res = TestFunc(1, ARG(f), ARG(res), ARG(arg), NULL); }
143   return res;
144 }
145 
146 int TryAndAlloca(int arg) {
147   puts(__FUNCTION__);
148   int res = 0;
149   SmallObj f;
150   __try {
151     res =
152         TestFunc(1, _alloca(global), global, ARG(f), ARG(res), ARG(arg), NULL);
153   }
154   __except(TestFunc(2, ARG(f), ARG(res), ARG(arg), NULL), zero) {
155     res = TestFunc(2, ARG(f), ARG(res), ARG(arg), NULL);
156   }
157   return res;
158 }
159 
160 int GSCookieAndAlloca(int arg) {
161   puts(__FUNCTION__);
162   int res = 0;
163   char buf[16];
164   SmallObj f;
165   __try {
166     TestFunc(1, ARG(buf), _alloca(global), global, ARG(f), ARG(res), ARG(arg),
167              NULL);
168   }
169   __finally { res = TestFunc(1, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL); }
170   return res;
171 }
172 
173 int TryAndGSCookieAndAlloca(int arg) {
174   puts(__FUNCTION__);
175   int res = 0;
176   char buf[16];
177   SmallObj f;
178   __try {
179     res = TestFunc(1, ARG(buf), _alloca(global), global, ARG(f), ARG(res),
180                    ARG(arg), NULL);
181   }
182   __except(TestFunc(2, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL), zero) {
183     res = TestFunc(2, ARG(buf), ARG(f), ARG(res), ARG(arg), NULL);
184   }
185   return res;
186 }
187 
188 int AlignAndAlloca(int arg) {
189   puts(__FUNCTION__);
190   int res = 0;
191   __declspec(align(ALIGN)) double d[4];
192   SmallObj f;
193   __try {
194     TestFunc(1, ARG(d), _alloca(global), global, ARG(f), ARG(res), ARG(arg),
195              NULL);
196   }
197   __finally { res = TestFunc(1, ARG(d), ARG(f), ARG(res), ARG(arg), NULL); }
198   return res;
199 }
200 
201 int TryAndAlignAndAlloca(int arg) {
202   puts(__FUNCTION__);
203   int res = 0;
204   __declspec(align(ALIGN)) double d[4];
205   SmallObj f;
206   __try {
207     res = TestFunc(1, ARG(d), _alloca(global), global, ARG(f), ARG(res),
208                    ARG(arg), NULL);
209   }
210   __except(TestFunc(2, ARG(d), ARG(f), ARG(res), ARG(arg), NULL), zero) {
211     res = TestFunc(2, ARG(d), ARG(f), ARG(res), ARG(arg), NULL);
212   }
213   return res;
214 }
215 
216 int GSCookieAndAlignAndAlloca(int arg) {
217   puts(__FUNCTION__);
218   int res = 0;
219   char buf[16];
220   __declspec(align(ALIGN)) double d[4];
221   SmallObj f;
222   __try {
223     TestFunc(1, ARG(buf), ARG(d), _alloca(global), global, ARG(f), ARG(res),
224              ARG(arg), NULL);
225   }
226   __finally {
227     res = TestFunc(1, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL);
228   }
229   return res;
230 }
231 
232 int TryAndGSCookieAndAlignAndAlloca(int arg) {
233   puts(__FUNCTION__);
234   int res = 0;
235   char buf[16];
236   __declspec(align(ALIGN)) double d[4];
237   SmallObj f;
238   __try {
239     res = TestFunc(1, ARG(buf), ARG(d), _alloca(global), global, ARG(f),
240                    ARG(res), ARG(arg), NULL);
241   }
242   __except(TestFunc(2, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL),
243            zero) {
244     res = TestFunc(2, ARG(buf), ARG(d), ARG(f), ARG(res), ARG(arg), NULL);
245   }
246   return res;
247 }
248 
249 /*
250  * The BigLocals variants try to trigger EBP adjustment, and generally do in
251  * the /O1 case for the non-aligned stacks.
252  */
253 
254 int BigLocals(int arg) {
255   puts(__FUNCTION__);
256   int res = 0;
257   BigObj f1;
258   __try { TestFunc(1, ARG(f1), ARG5(res), ARG(arg), NULL); }
259   __finally { res = TestFunc(1, ARG(f1), ARG5(res), ARG(arg), NULL); }
260   return res;
261 }
262 
263 int TryAndBigLocals(int arg) {
264   puts(__FUNCTION__);
265   int res = 0;
266   BigObj f1;
267   __try { res = TestFunc(1, ARG(f1), ARG5(res), ARG(arg), NULL); }
268   __except(TestFunc(2, ARG(f1), ARG5(res), ARG(arg), NULL), zero) {
269     res = TestFunc(2, ARG(f1), ARG5(res), ARG(arg), NULL);
270   }
271   return res;
272 }
273 
274 int GSCookieAndBigLocals(int arg) {
275   puts(__FUNCTION__);
276   int res = 0;
277   char buf[16];
278   BigObj f1;
279   __try { TestFunc(1, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL); }
280   __finally { res = TestFunc(1, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL); }
281   return res;
282 }
283 
284 int TryAndGSCookieAndBigLocals(int arg) {
285   puts(__FUNCTION__);
286   int res = 0;
287   char buf[16];
288   BigObj f1;
289   __try { res = TestFunc(1, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL); }
290   __except(TestFunc(2, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL), zero) {
291     res = TestFunc(2, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL);
292   }
293   return res;
294 }
295 
296 int AlignAndBigLocals(int arg) {
297   puts(__FUNCTION__);
298   int res = 0;
299   __declspec(align(ALIGN)) double d[4];
300   BigObj f1;
301   __try { TestFunc(1, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL); }
302   __finally { res = TestFunc(1, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL); }
303   return res;
304 }
305 
306 int TryAndAlignAndBigLocals(int arg) {
307   puts(__FUNCTION__);
308   int res = 0;
309   __declspec(align(ALIGN)) double d[4];
310   BigObj f1;
311   __try { res = TestFunc(1, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL); }
312   __except(TestFunc(2, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL), zero) {
313     res = TestFunc(2, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL);
314   }
315   return res;
316 }
317 
318 int GSCookieAndAlignAndBigLocals(int arg) {
319   puts(__FUNCTION__);
320   int res = 0;
321   char buf[16];
322   __declspec(align(ALIGN)) double d[4];
323   BigObj f1;
324   __try { TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL); }
325   __finally {
326     res = TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL);
327   }
328   return res;
329 }
330 
331 int TryAndGSCookieAndAlignAndBigLocals(int arg) {
332   puts(__FUNCTION__);
333   int res = 0;
334   char buf[16];
335   __declspec(align(ALIGN)) double d[4];
336   BigObj f1;
337   __try {
338     res = TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL);
339   }
340   __except(TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL),
341            zero) {
342     res = TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL);
343   }
344   return res;
345 }
346 
347 int AllocaAndBigLocals(int arg) {
348   puts(__FUNCTION__);
349   int res = 0;
350   BigObj f1;
351   __try {
352     TestFunc(1, _alloca(global), global, ARG(f1), ARG5(res), ARG(arg), NULL);
353   }
354   __finally { res = TestFunc(1, ARG(f1), ARG5(res), ARG(arg), NULL); }
355   return res;
356 }
357 
358 int TryAndAllocaAndBigLocals(int arg) {
359   puts(__FUNCTION__);
360   int res = 0;
361   BigObj f1;
362   __try {
363     res = TestFunc(1, _alloca(global), global, ARG(f1), ARG5(res), ARG(arg),
364                    NULL);
365   }
366   __except(TestFunc(2, ARG(f1), ARG5(res), ARG(arg), NULL), zero) {
367     res = TestFunc(2, ARG(f1), ARG5(res), ARG(arg), NULL);
368   }
369   return res;
370 }
371 
372 int GSCookieAndAllocaAndBigLocals(int arg) {
373   puts(__FUNCTION__);
374   int res = 0;
375   char buf[16];
376   BigObj f1;
377   __try {
378     TestFunc(1, ARG(buf), _alloca(global), global, ARG(f1), ARG5(res), ARG(arg),
379              NULL);
380   }
381   __finally { res = TestFunc(1, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL); }
382   return res;
383 }
384 
385 int TryAndGSCookieAndAllocaAndBigLocals(int arg) {
386   puts(__FUNCTION__);
387   int res = 0;
388   char buf[16];
389   BigObj f1;
390   __try {
391     res = TestFunc(1, ARG(buf), _alloca(global), global, ARG(f1), ARG5(res),
392                    ARG(arg), NULL);
393   }
394   __except(TestFunc(2, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL), zero) {
395     res = TestFunc(2, ARG(buf), ARG(f1), ARG5(res), ARG(arg), NULL);
396   }
397   return res;
398 }
399 
400 int AlignAndAllocaAndBigLocals(int arg) {
401   puts(__FUNCTION__);
402   int res = 0;
403   __declspec(align(ALIGN)) double d[4];
404   BigObj f1;
405   __try {
406     TestFunc(1, ARG(d), _alloca(global), global, ARG(f1), ARG5(res), ARG(arg),
407              NULL);
408   }
409   __finally { res = TestFunc(1, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL); }
410   return res;
411 }
412 
413 int TryAndAlignAndAllocaAndBigLocals(int arg) {
414   puts(__FUNCTION__);
415   int res = 0;
416   __declspec(align(ALIGN)) double d[4];
417   BigObj f1;
418   __try {
419     res = TestFunc(1, ARG(d), _alloca(global), global, ARG(f1), ARG5(res),
420                    ARG(arg), NULL);
421   }
422   __except(TestFunc(2, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL), zero) {
423     res = TestFunc(2, ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL);
424   }
425   return res;
426 }
427 
428 int GSCookieAndAlignAndAllocaAndBigLocals(int arg) {
429   puts(__FUNCTION__);
430   int res = 0;
431   char buf[16];
432   __declspec(align(ALIGN)) double d[4];
433   BigObj f1;
434   __try {
435     TestFunc(1, ARG(buf), ARG(d), _alloca(global), global, ARG(f1), ARG5(res),
436              ARG(arg), NULL);
437   }
438   __finally {
439     res = TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL);
440   }
441   return res;
442 }
443 
444 int TryAndGSCookieAndAlignAndAllocaAndBigLocals(int arg) {
445   puts(__FUNCTION__);
446   int res = 0;
447   char buf[16];
448   __declspec(align(ALIGN)) double d[4];
449   BigObj f1;
450   __try {
451     res = TestFunc(1, ARG(buf), ARG(d), _alloca(global), global, ARG(f1),
452                    ARG5(res), ARG(arg), NULL);
453   }
454   __except(TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL),
455            zero) {
456     res = TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG5(res), ARG(arg), NULL);
457   }
458   return res;
459 }
460 
461 /*
462  * The EbpAdj variants try to trigger EBP adjustment, and generally do in
463  * the /O1 case for the non-aligned stacks.  They add a non-GS-protected
464  * buffer so the EH node is far from both sides of the local variable
465  * allocation.  Doesn't seem to add any testing over what the BigLocals cases
466  * already do.
467  */
468 
469 int EbpAdj(int arg) {
470   puts(__FUNCTION__);
471   int res = 0;
472   int a[512];
473   BigObj f1;
474   __try { TestFunc(1, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL); }
475   __finally { res = TestFunc(1, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL); }
476   return res;
477 }
478 
479 int TryAndEbpAdj(int arg) {
480   puts(__FUNCTION__);
481   int res = 0;
482   int a[512];
483   BigObj f1;
484   __try { res = TestFunc(1, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL); }
485   __except(TestFunc(2, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL), zero) {
486     res = TestFunc(2, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
487   }
488   return res;
489 }
490 
491 int GSCookieAndEbpAdj(int arg) {
492   puts(__FUNCTION__);
493   int res = 0;
494   int a[512];
495   char buf[16];
496   BigObj f1;
497   __try { TestFunc(1, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL); }
498   __finally {
499     res = TestFunc(1, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
500   }
501   return res;
502 }
503 
504 int TryAndGSCookieAndEbpAdj(int arg) {
505   puts(__FUNCTION__);
506   int res = 0;
507   int a[512];
508   char buf[16];
509   BigObj f1;
510   __try {
511     res = TestFunc(1, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
512   }
513   __except(TestFunc(2, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL),
514            zero) {
515     res = TestFunc(2, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
516   }
517   return res;
518 }
519 
520 int AlignAndEbpAdj(int arg) {
521   puts(__FUNCTION__);
522   int res = 0;
523   int a[512];
524   __declspec(align(ALIGN)) double d[4];
525   BigObj f1;
526   __try { TestFunc(1, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL); }
527   __finally {
528     res = TestFunc(1, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
529   }
530   return res;
531 }
532 
533 int TryAndAlignAndEbpAdj(int arg) {
534   puts(__FUNCTION__);
535   int res = 0;
536   int a[512];
537   __declspec(align(ALIGN)) double d[4];
538   BigObj f1;
539   __try {
540     res = TestFunc(1, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
541   }
542   __except(TestFunc(2, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL),
543            zero) {
544     res = TestFunc(2, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
545   }
546   return res;
547 }
548 
549 int GSCookieAndAlignAndEbpAdj(int arg) {
550   puts(__FUNCTION__);
551   int res = 0;
552   int a[512];
553   char buf[16];
554   __declspec(align(ALIGN)) double d[4];
555   BigObj f1;
556   __try {
557     TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
558   }
559   __finally {
560     res = TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg),
561                    NULL);
562   }
563   return res;
564 }
565 
566 int TryAndGSCookieAndAlignAndEbpAdj(int arg) {
567   puts(__FUNCTION__);
568   int res = 0;
569   int a[512];
570   char buf[16];
571   __declspec(align(ALIGN)) double d[4];
572   BigObj f1;
573   __try {
574     res = TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg),
575                    NULL);
576   }
577   __except(TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg),
578                     NULL),
579            zero) {
580     res = TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg),
581                    NULL);
582   }
583   return res;
584 }
585 
586 int AllocaAndEbpAdj(int arg) {
587   puts(__FUNCTION__);
588   int res = 0;
589   int a[512];
590   BigObj f1;
591   __try {
592     TestFunc(1, _alloca(global), global, ARG(f1), ARG2(a), ARG5(res), ARG(arg),
593              NULL);
594   }
595   __finally { res = TestFunc(1, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL); }
596   return res;
597 }
598 
599 int TryAndAllocaAndEbpAdj(int arg) {
600   puts(__FUNCTION__);
601   int res = 0;
602   int a[512];
603   BigObj f1;
604   __try {
605     res = TestFunc(1, _alloca(global), global, ARG(f1), ARG2(a), ARG5(res),
606                    ARG(arg), NULL);
607   }
608   __except(TestFunc(2, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL), zero) {
609     res = TestFunc(2, ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
610   }
611   return res;
612 }
613 
614 int GSCookieAndAllocaAndEbpAdj(int arg) {
615   puts(__FUNCTION__);
616   int res = 0;
617   int a[512];
618   char buf[16];
619   BigObj f1;
620   __try {
621     TestFunc(1, ARG(buf), _alloca(global), global, ARG(f1), ARG2(a), ARG5(res),
622              ARG(arg), NULL);
623   }
624   __finally {
625     res = TestFunc(1, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
626   }
627   return res;
628 }
629 
630 int TryAndGSCookieAndAllocaAndEbpAdj(int arg) {
631   puts(__FUNCTION__);
632   int res = 0;
633   int a[512];
634   char buf[16];
635   BigObj f1;
636   __try {
637     res = TestFunc(1, ARG(buf), _alloca(global), global, ARG(f1), ARG2(a),
638                    ARG5(res), ARG(arg), NULL);
639   }
640   __except(TestFunc(2, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL),
641            zero) {
642     res = TestFunc(2, ARG(buf), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
643   }
644   return res;
645 }
646 
647 int AlignAndAllocaAndEbpAdj(int arg) {
648   puts(__FUNCTION__);
649   int res = 0;
650   int a[512];
651   __declspec(align(ALIGN)) double d[4];
652   BigObj f1;
653   __try {
654     TestFunc(1, ARG(d), _alloca(global), global, ARG(f1), ARG2(a), ARG5(res),
655              ARG(arg), NULL);
656   }
657   __finally {
658     res = TestFunc(1, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
659   }
660   return res;
661 }
662 
663 int TryAndAlignAndAllocaAndEbpAdj(int arg) {
664   puts(__FUNCTION__);
665   int res = 0;
666   int a[512];
667   __declspec(align(ALIGN)) double d[4];
668   BigObj f1;
669   __try {
670     res = TestFunc(1, ARG(d), _alloca(global), global, ARG(f1), ARG2(a),
671                    ARG5(res), ARG(arg), NULL);
672   }
673   __except(TestFunc(2, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL),
674            zero) {
675     res = TestFunc(2, ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg), NULL);
676   }
677   return res;
678 }
679 
680 int GSCookieAndAlignAndAllocaAndEbpAdj(int arg) {
681   puts(__FUNCTION__);
682   int res = 0;
683   int a[512];
684   char buf[16];
685   __declspec(align(ALIGN)) double d[4];
686   BigObj f1;
687   __try {
688     TestFunc(1, ARG(buf), ARG(d), _alloca(global), global, ARG(f1), ARG2(a),
689              ARG5(res), ARG(arg), NULL);
690   }
691   __finally {
692     res = TestFunc(1, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg),
693                    NULL);
694   }
695   return res;
696 }
697 
698 int TryAndGSCookieAndAlignAndAllocaAndEbpAdj(int arg) {
699   puts(__FUNCTION__);
700   int res = 0;
701   int a[512];
702   char buf[16];
703   __declspec(align(ALIGN)) double d[4];
704   BigObj f1;
705   __try {
706     res = TestFunc(1, ARG(buf), ARG(d), _alloca(global), global, ARG(f1),
707                    ARG2(a), ARG5(res), ARG(arg), NULL);
708   }
709   __except(TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg),
710                     NULL),
711            zero) {
712     res = TestFunc(2, ARG(buf), ARG(d), ARG(f1), ARG2(a), ARG5(res), ARG(arg),
713                    NULL);
714   }
715   return res;
716 }
717 
718 __declspec(noinline) int TestFunc(int x, ...) {
719   va_list ap;
720   va_start(ap, x);
721 
722   for (;;) {
723     void *pbuf = va_arg(ap, void *);
724     if (pbuf == NULL) {
725       break;
726     }
727     size_t len = va_arg(ap, size_t);
728     memset(pbuf, 0, len);
729   }
730 
731   if (TestFuncThrows) {
732     TestFuncThrows = false;
733     *(volatile int *)0;
734   }
735 
736   return static_cast<int>(global);
737 }
738 
739 void RunTests() {
740   puts("Test pass 1 - no exceptions");
741 
742   __try {
743     Simple(1);
744     Try(1);
745     GSCookie(1);
746     TryAndGSCookie(1);
747     Align(1);
748     TryAndAlign(1);
749     GSCookieAndAlign(1);
750     TryAndGSCookieAndAlign(1);
751     Alloca(1);
752     TryAndAlloca(1);
753     GSCookieAndAlloca(1);
754     TryAndGSCookieAndAlloca(1);
755     AlignAndAlloca(1);
756     TryAndAlignAndAlloca(1);
757     GSCookieAndAlignAndAlloca(1);
758     TryAndGSCookieAndAlignAndAlloca(1);
759     BigLocals(1);
760     TryAndBigLocals(1);
761     GSCookieAndBigLocals(1);
762     TryAndGSCookieAndBigLocals(1);
763     AlignAndBigLocals(1);
764     TryAndAlignAndBigLocals(1);
765     GSCookieAndAlignAndBigLocals(1);
766     TryAndGSCookieAndAlignAndBigLocals(1);
767     AllocaAndBigLocals(1);
768     TryAndAllocaAndBigLocals(1);
769     GSCookieAndAllocaAndBigLocals(1);
770     TryAndGSCookieAndAllocaAndBigLocals(1);
771     AlignAndAllocaAndBigLocals(1);
772     TryAndAlignAndAllocaAndBigLocals(1);
773     GSCookieAndAlignAndAllocaAndBigLocals(1);
774     TryAndGSCookieAndAlignAndAllocaAndBigLocals(1);
775     EbpAdj(1);
776     TryAndEbpAdj(1);
777     GSCookieAndEbpAdj(1);
778     TryAndGSCookieAndEbpAdj(1);
779     AlignAndEbpAdj(1);
780     TryAndAlignAndEbpAdj(1);
781     GSCookieAndAlignAndEbpAdj(1);
782     TryAndGSCookieAndAlignAndEbpAdj(1);
783     AllocaAndEbpAdj(1);
784     TryAndAllocaAndEbpAdj(1);
785     GSCookieAndAllocaAndEbpAdj(1);
786     TryAndGSCookieAndAllocaAndEbpAdj(1);
787     AlignAndAllocaAndEbpAdj(1);
788     TryAndAlignAndAllocaAndEbpAdj(1);
789     GSCookieAndAlignAndAllocaAndEbpAdj(1);
790     TryAndGSCookieAndAlignAndAllocaAndEbpAdj(1);
791   }
792   __except(one) {
793     puts("ERROR - exception not expected");
794     ++failures;
795   }
796 
797   puts("Test pass 2 - exceptions");
798 
799   for (int i = 0; i < 48; ++i) {
800     TestFuncThrows = true;
801     bool caught = false;
802     __try {
803       switch (i) {
804       case 0:
805         Simple(1);
806         break;
807       case 1:
808         Try(1);
809         break;
810       case 2:
811         GSCookie(1);
812         break;
813       case 3:
814         TryAndGSCookie(1);
815         break;
816       case 4:
817         Align(1);
818         break;
819       case 5:
820         TryAndAlign(1);
821         break;
822       case 6:
823         GSCookieAndAlign(1);
824         break;
825       case 7:
826         TryAndGSCookieAndAlign(1);
827         break;
828       case 8:
829         Alloca(1);
830         break;
831       case 9:
832         TryAndAlloca(1);
833         break;
834       case 10:
835         GSCookieAndAlloca(1);
836         break;
837       case 11:
838         TryAndGSCookieAndAlloca(1);
839         break;
840       case 12:
841         AlignAndAlloca(1);
842         break;
843       case 13:
844         TryAndAlignAndAlloca(1);
845         break;
846       case 14:
847         GSCookieAndAlignAndAlloca(1);
848         break;
849       case 15:
850         TryAndGSCookieAndAlignAndAlloca(1);
851         break;
852       case 16:
853         BigLocals(1);
854         break;
855       case 17:
856         TryAndBigLocals(1);
857         break;
858       case 18:
859         GSCookieAndBigLocals(1);
860         break;
861       case 19:
862         TryAndGSCookieAndBigLocals(1);
863         break;
864       case 20:
865         AlignAndBigLocals(1);
866         break;
867       case 21:
868         TryAndAlignAndBigLocals(1);
869         break;
870       case 22:
871         GSCookieAndAlignAndBigLocals(1);
872         break;
873       case 23:
874         TryAndGSCookieAndAlignAndBigLocals(1);
875         break;
876       case 24:
877         AllocaAndBigLocals(1);
878         break;
879       case 25:
880         TryAndAllocaAndBigLocals(1);
881         break;
882       case 26:
883         GSCookieAndAllocaAndBigLocals(1);
884         break;
885       case 27:
886         TryAndGSCookieAndAllocaAndBigLocals(1);
887         break;
888       case 28:
889         AlignAndAllocaAndBigLocals(1);
890         break;
891       case 29:
892         TryAndAlignAndAllocaAndBigLocals(1);
893         break;
894       case 30:
895         GSCookieAndAlignAndAllocaAndBigLocals(1);
896         break;
897       case 31:
898         TryAndGSCookieAndAlignAndAllocaAndBigLocals(1);
899         break;
900       case 32:
901         EbpAdj(1);
902         break;
903       case 33:
904         TryAndEbpAdj(1);
905         break;
906       case 34:
907         GSCookieAndEbpAdj(1);
908         break;
909       case 35:
910         TryAndGSCookieAndEbpAdj(1);
911         break;
912       case 36:
913         AlignAndEbpAdj(1);
914         break;
915       case 37:
916         TryAndAlignAndEbpAdj(1);
917         break;
918       case 38:
919         GSCookieAndAlignAndEbpAdj(1);
920         break;
921       case 39:
922         TryAndGSCookieAndAlignAndEbpAdj(1);
923         break;
924       case 40:
925         AllocaAndEbpAdj(1);
926         break;
927       case 41:
928         TryAndAllocaAndEbpAdj(1);
929         break;
930       case 42:
931         GSCookieAndAllocaAndEbpAdj(1);
932         break;
933       case 43:
934         TryAndGSCookieAndAllocaAndEbpAdj(1);
935         break;
936       case 44:
937         AlignAndAllocaAndEbpAdj(1);
938         break;
939       case 45:
940         TryAndAlignAndAllocaAndEbpAdj(1);
941         break;
942       case 46:
943         GSCookieAndAlignAndAllocaAndEbpAdj(1);
944         break;
945       case 47:
946         TryAndGSCookieAndAlignAndAllocaAndEbpAdj(1);
947         break;
948       }
949     }
950     __except(one) { caught = true; }
951 
952     if (!caught) {
953       puts("ERROR - did not see expected exception");
954       ++failures;
955     }
956   }
957 }
958 
959 int main() {
960   __try { RunTests(); }
961   __except(1) {
962     puts("ERROR - Unexpectedly caught an exception");
963     ++failures;
964   }
965 
966   if (failures) {
967     printf("Test failed with %d failure%s\n", failures,
968            failures == 1 ? "" : "s");
969   } else {
970     puts("Test passed");
971   }
972 
973   return failures;
974 }
975