| 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 |