OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * Tests if the ABI for passing structures by value matches. | 8 * Tests if the ABI for passing structures by value matches. |
9 * | 9 * |
10 * We have 4 modules, two compiled by one compiler and two by the other. | 10 * We have 4 modules, two compiled by one compiler and two by the other. |
(...skipping 27 matching lines...) Expand all Loading... |
38 * separate native .o files, but... just in case the build changes. | 38 * separate native .o files, but... just in case the build changes. |
39 * Also tag each function as noinline... just in case. | 39 * Also tag each function as noinline... just in case. |
40 */ | 40 */ |
41 #if defined(MODULE0) | 41 #if defined(MODULE0) |
42 int should_be_true; | 42 int should_be_true; |
43 #else | 43 #else |
44 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ | 44 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ |
45 extern int should_be_true; | 45 extern int should_be_true; |
46 #endif | 46 #endif |
47 | 47 |
48 /* This could have less duplication, but let's duplicate the bodies to | 48 /**********************************************************************/ |
49 * be clear about what functions are generated and how they call each other. | 49 |
| 50 /* We test the pnaclcall attribute several ways. |
| 51 * (1) Commandline flag (or nothing at all if there is 100% compatibility). |
| 52 * (2) Declaring the callee as having the "pnaclcall" attribute. |
| 53 * (3) Not declaring the callee to have the attribute, but by making a |
| 54 * call through a temporary function pointer that has the attribute. |
| 55 * |
| 56 * Module 2 is the only one that calls from nacl-gcc to pnacl, so |
| 57 * this is the only one that varies this way. |
| 58 * |
| 59 * Module 0 to Module 1 is where we transition from pnacl to nacl-gcc. |
| 60 * For this, we either use the commandline flag (1), or we use the |
| 61 * declaration (2), since pnacl itself cannot turn on/off the pnaclcall |
| 62 * convention. |
50 */ | 63 */ |
| 64 #if defined(TEST_ATTRIBUTE_VIA_DECL) |
| 65 |
| 66 #define MOD3_DECL(TYPE) \ |
| 67 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
| 68 extern __attribute__((noinline,pnaclcall)) void mod3_##TYPE(TYPE z) |
| 69 #define MOD2_TO_3_CALL(TYPE, arg) \ |
| 70 mod3_##TYPE(arg) |
| 71 #define MOD1_DECL(TYPE) \ |
| 72 __attribute__((pnaclcall,noinline)) void mod1_##TYPE(TYPE z) |
| 73 |
| 74 #elif defined(TEST_ATTRIBUTE_VIA_FP) |
| 75 |
| 76 #define MOD3_DECL(TYPE) \ |
| 77 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
| 78 extern __attribute__((noinline)) void mod3_##TYPE(TYPE z) |
| 79 #define MOD2_TO_3_CALL(TYPE, arg) \ |
| 80 do { \ |
| 81 void (__attribute__((pnaclcall)) *temp_fp)(TYPE z) = \ |
| 82 (void (__attribute__((pnaclcall)) *)(TYPE)) &mod3_##TYPE; \ |
| 83 (*temp_fp)(arg); \ |
| 84 } while(0) |
| 85 #define MOD1_DECL(TYPE) \ |
| 86 __attribute__((pnaclcall,noinline)) void mod1_##TYPE(TYPE z) |
| 87 |
| 88 #else /* Testing with just the commandline flag / or nothing at all. */ |
| 89 |
| 90 #define MOD3_DECL(TYPE) \ |
| 91 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
| 92 extern __attribute__((noinline)) void mod3_##TYPE(TYPE z) |
| 93 #define MOD2_TO_3_CALL(TYPE, arg) \ |
| 94 mod3_##TYPE(arg) |
| 95 #define MOD1_DECL(TYPE) \ |
| 96 __attribute__((noinline)) void mod1_##TYPE(TYPE z) |
| 97 |
| 98 #endif /* TEST_ATTRIBUTE_VIA_... */ |
| 99 |
| 100 /**********************************************************************/ |
| 101 /* The actual test code structure (which is divided into 4 modules). */ |
| 102 |
51 #define GENERATE_FOR_MODULE3(TYPE) \ | 103 #define GENERATE_FOR_MODULE3(TYPE) \ |
52 void mod3_##TYPE(TYPE z) __attribute__((noinline)); \ | 104 __attribute__((noinline)) void mod3_##TYPE(TYPE z); \ |
53 void mod3_##TYPE(TYPE z) { \ | 105 void mod3_##TYPE(TYPE z) { \ |
54 CHECK_##TYPE(z); \ | 106 CHECK_##TYPE(z); \ |
55 if (should_be_true) { \ | 107 if (should_be_true) { \ |
56 printf("Made it to mod3_" #TYPE "\n"); \ | 108 printf("Made it to mod3_" #TYPE "\n"); \ |
57 memset((void*)&z, 0, sizeof z); \ | 109 memset((void*)&z, 0, sizeof z); \ |
58 } else { \ | 110 } else { \ |
59 printf("should_be_true is not true for mod3_" #TYPE "\n"); \ | 111 printf("should_be_true is not true for mod3_" #TYPE "\n"); \ |
60 memset((void*)&z, 1, sizeof z); \ | 112 memset((void*)&z, 1, sizeof z); \ |
61 } \ | 113 } \ |
62 } | 114 } |
63 | 115 |
64 #define GENERATE_FOR_MODULE2(TYPE) \ | 116 #define GENERATE_FOR_MODULE2(TYPE) \ |
65 /* @IGNORE_LINES_FOR_CODE_HYGIENE[2] */ \ | 117 MOD3_DECL(TYPE); \ |
66 extern void mod3_##TYPE(TYPE z) __attribute__((noinline)); \ | 118 __attribute__((noinline)) void mod2_##TYPE(TYPE z); \ |
67 void mod2_##TYPE(TYPE z) __attribute__((noinline)); \ | |
68 void mod2_##TYPE(TYPE z) { \ | 119 void mod2_##TYPE(TYPE z) { \ |
69 CHECK_##TYPE(z); \ | 120 CHECK_##TYPE(z); \ |
70 if (should_be_true) { \ | 121 if (should_be_true) { \ |
71 mod3_##TYPE(z); \ | 122 MOD2_TO_3_CALL(TYPE, z); \ |
72 CHECK_##TYPE(z); \ | 123 CHECK_##TYPE(z); \ |
73 printf("Made it to mod2_" #TYPE "\n"); \ | 124 printf("Made it to mod2_" #TYPE "\n"); \ |
74 memset((void*)&z, 0, sizeof z); \ | 125 memset((void*)&z, 0, sizeof z); \ |
75 } else { \ | 126 } else { \ |
76 memset((void*)&z, 0, sizeof z); \ | 127 memset((void*)&z, 0, sizeof z); \ |
77 printf("should_be_true is not true for mod2_" #TYPE "\n"); \ | 128 printf("should_be_true is not true for mod2_" #TYPE "\n"); \ |
78 mod3_##TYPE(z); \ | 129 mod3_##TYPE(z); \ |
79 } \ | 130 } \ |
80 } | 131 } |
81 | 132 |
82 #define GENERATE_FOR_MODULE1(TYPE) \ | 133 #define GENERATE_FOR_MODULE1(TYPE) \ |
83 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ | 134 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
84 extern void mod2_##TYPE(TYPE z) __attribute__((noinline)); \ | 135 extern __attribute__((noinline)) void mod2_##TYPE(TYPE z); \ |
85 void mod1_##TYPE(TYPE z) __attribute__((noinline)); \ | 136 MOD1_DECL(TYPE); \ |
86 void mod1_##TYPE(TYPE z) { \ | 137 void mod1_##TYPE(TYPE z) { \ |
87 CHECK_##TYPE(z); \ | 138 CHECK_##TYPE(z); \ |
88 if (should_be_true) { \ | 139 if (should_be_true) { \ |
89 mod2_##TYPE(z); \ | 140 mod2_##TYPE(z); \ |
90 CHECK_##TYPE(z); \ | 141 CHECK_##TYPE(z); \ |
91 printf("Made it to mod1_" #TYPE "\n"); \ | 142 printf("Made it to mod1_" #TYPE "\n"); \ |
92 memset((void*)&z, 0, sizeof z); \ | 143 memset((void*)&z, 0, sizeof z); \ |
93 } else { \ | 144 } else { \ |
94 memset((void*)&z, 0, sizeof z); \ | 145 memset((void*)&z, 0, sizeof z); \ |
95 printf("should_be_true is not true for mod1_" #TYPE "\n"); \ | 146 printf("should_be_true is not true for mod1_" #TYPE "\n"); \ |
96 mod2_##TYPE(z); \ | 147 mod2_##TYPE(z); \ |
97 } \ | 148 } \ |
98 } | 149 } |
99 | 150 |
100 #define GENERATE_FOR_MODULE0(TYPE) \ | 151 #define GENERATE_FOR_MODULE0(TYPE) \ |
101 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ | 152 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
102 extern void mod1_##TYPE(TYPE z) __attribute__((noinline)); \ | 153 extern __attribute__((noinline)) void mod1_##TYPE(TYPE z) ; \ |
103 void mod0_##TYPE(TYPE z) __attribute__((noinline)); \ | 154 void __attribute__((noinline)) mod0_##TYPE(TYPE z) ; \ |
104 void mod0_##TYPE(TYPE z) { \ | 155 void mod0_##TYPE(TYPE z) { \ |
105 CHECK_##TYPE(z); \ | 156 CHECK_##TYPE(z); \ |
106 if (should_be_true) { \ | 157 if (should_be_true) { \ |
107 mod1_##TYPE(z); \ | 158 mod1_##TYPE(z); \ |
108 CHECK_##TYPE(z); \ | 159 CHECK_##TYPE(z); \ |
109 printf("Made it to mod0_" #TYPE "\n"); \ | 160 printf("Made it to mod0_" #TYPE "\n"); \ |
110 memset((void*)&z, 0, sizeof z); \ | 161 memset((void*)&z, 0, sizeof z); \ |
111 } else { \ | 162 } else { \ |
112 memset((void*)&z, 0, sizeof z); \ | 163 memset((void*)&z, 0, sizeof z); \ |
113 printf("should_be_true is not true for mod0_" #TYPE "\n"); \ | 164 printf("should_be_true is not true for mod0_" #TYPE "\n"); \ |
114 mod1_##TYPE(z); \ | 165 mod1_##TYPE(z); \ |
115 } \ | 166 } \ |
116 } \ | 167 } \ |
117 void test_##TYPE(void) __attribute__((noinline)); \ | 168 void __attribute__((noinline)) test_##TYPE(void); \ |
118 void test_##TYPE(void) { \ | 169 void test_##TYPE(void) { \ |
119 TYPE z = k##TYPE; \ | 170 TYPE z = k##TYPE; \ |
120 CHECK_##TYPE(z); \ | 171 CHECK_##TYPE(z); \ |
121 if (should_be_true) { \ | 172 if (should_be_true) { \ |
122 mod0_##TYPE(z); \ | 173 mod0_##TYPE(z); \ |
123 CHECK_##TYPE(z); \ | 174 CHECK_##TYPE(z); \ |
124 printf("Made it through test_" #TYPE "\n"); \ | 175 printf("Made it through test_" #TYPE "\n"); \ |
125 } else { \ | 176 } else { \ |
126 memset((void*)&z, 0, sizeof z); \ | 177 memset((void*)&z, 0, sizeof z); \ |
127 printf("should_be_true is not true for test_" #TYPE "\n"); \ | 178 printf("should_be_true is not true for test_" #TYPE "\n"); \ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 test_##TYPE(); | 218 test_##TYPE(); |
168 | 219 |
169 #define DO_FOR_TYPE CALL_TEST | 220 #define DO_FOR_TYPE CALL_TEST |
170 #include "native_client/tests/callingconv_case_by_case/for_each_type.h" | 221 #include "native_client/tests/callingconv_case_by_case/for_each_type.h" |
171 #undef DO_FOR_TYPE | 222 #undef DO_FOR_TYPE |
172 #undef NOT_DECLARING_DEFINING | 223 #undef NOT_DECLARING_DEFINING |
173 | 224 |
174 return 0; | 225 return 0; |
175 } | 226 } |
176 #endif /* defined(MODULE0) */ | 227 #endif /* defined(MODULE0) */ |
OLD | NEW |