Index: tests/callingconv_case_by_case/call_structs.cc |
diff --git a/tests/callingconv_case_by_case/call_structs.cc b/tests/callingconv_case_by_case/call_structs.cc |
index c98ef3f2dd22e7a9221b4085421d91aff9b4a956..57f3b8fe340ee7b9bde61306a7dbe3c395213146 100644 |
--- a/tests/callingconv_case_by_case/call_structs.cc |
+++ b/tests/callingconv_case_by_case/call_structs.cc |
@@ -45,11 +45,63 @@ int should_be_true; |
extern int should_be_true; |
#endif |
-/* This could have less duplication, but let's duplicate the bodies to |
- * be clear about what functions are generated and how they call each other. |
+/**********************************************************************/ |
+ |
+/* We test the pnaclcall attribute several ways. |
+ * (1) Commandline flag (or nothing at all if there is 100% compatibility). |
+ * (2) Declaring the callee as having the "pnaclcall" attribute. |
+ * (3) Not declaring the callee to have the attribute, but by making a |
+ * call through a temporary function pointer that has the attribute. |
+ * |
+ * Module 2 is the only one that calls from nacl-gcc to pnacl, so |
+ * this is the only one that varies this way. |
+ * |
+ * Module 0 to Module 1 is where we transition from pnacl to nacl-gcc. |
+ * For this, we either use the commandline flag (1), or we use the |
+ * declaration (2), since pnacl itself cannot turn on/off the pnaclcall |
+ * convention. |
*/ |
+#if defined(TEST_ATTRIBUTE_VIA_DECL) |
+ |
+#define MOD3_DECL(TYPE) \ |
+ /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
+ extern __attribute__((noinline,pnaclcall)) void mod3_##TYPE(TYPE z) |
+#define MOD2_TO_3_CALL(TYPE, arg) \ |
+ mod3_##TYPE(arg) |
+#define MOD1_DECL(TYPE) \ |
+ __attribute__((pnaclcall,noinline)) void mod1_##TYPE(TYPE z) |
+ |
+#elif defined(TEST_ATTRIBUTE_VIA_FP) |
+ |
+#define MOD3_DECL(TYPE) \ |
+ /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
+ extern __attribute__((noinline)) void mod3_##TYPE(TYPE z) |
+#define MOD2_TO_3_CALL(TYPE, arg) \ |
+ do { \ |
+ void (__attribute__((pnaclcall)) *temp_fp)(TYPE z) = \ |
+ (void (__attribute__((pnaclcall)) *)(TYPE)) &mod3_##TYPE; \ |
+ (*temp_fp)(arg); \ |
+ } while(0) |
+#define MOD1_DECL(TYPE) \ |
+ __attribute__((pnaclcall,noinline)) void mod1_##TYPE(TYPE z) |
+ |
+#else /* Testing with just the commandline flag / or nothing at all. */ |
+ |
+#define MOD3_DECL(TYPE) \ |
+ /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
+ extern __attribute__((noinline)) void mod3_##TYPE(TYPE z) |
+#define MOD2_TO_3_CALL(TYPE, arg) \ |
+ mod3_##TYPE(arg) |
+#define MOD1_DECL(TYPE) \ |
+ __attribute__((noinline)) void mod1_##TYPE(TYPE z) |
+ |
+#endif /* TEST_ATTRIBUTE_VIA_... */ |
+ |
+/**********************************************************************/ |
+/* The actual test code structure (which is divided into 4 modules). */ |
+ |
#define GENERATE_FOR_MODULE3(TYPE) \ |
- void mod3_##TYPE(TYPE z) __attribute__((noinline)); \ |
+ __attribute__((noinline)) void mod3_##TYPE(TYPE z); \ |
void mod3_##TYPE(TYPE z) { \ |
CHECK_##TYPE(z); \ |
if (should_be_true) { \ |
@@ -62,13 +114,12 @@ extern int should_be_true; |
} |
#define GENERATE_FOR_MODULE2(TYPE) \ |
- /* @IGNORE_LINES_FOR_CODE_HYGIENE[2] */ \ |
- extern void mod3_##TYPE(TYPE z) __attribute__((noinline)); \ |
- void mod2_##TYPE(TYPE z) __attribute__((noinline)); \ |
+ MOD3_DECL(TYPE); \ |
+ __attribute__((noinline)) void mod2_##TYPE(TYPE z); \ |
void mod2_##TYPE(TYPE z) { \ |
CHECK_##TYPE(z); \ |
if (should_be_true) { \ |
- mod3_##TYPE(z); \ |
+ MOD2_TO_3_CALL(TYPE, z); \ |
CHECK_##TYPE(z); \ |
printf("Made it to mod2_" #TYPE "\n"); \ |
memset((void*)&z, 0, sizeof z); \ |
@@ -81,8 +132,8 @@ extern int should_be_true; |
#define GENERATE_FOR_MODULE1(TYPE) \ |
/* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
- extern void mod2_##TYPE(TYPE z) __attribute__((noinline)); \ |
- void mod1_##TYPE(TYPE z) __attribute__((noinline)); \ |
+ extern __attribute__((noinline)) void mod2_##TYPE(TYPE z); \ |
+ MOD1_DECL(TYPE); \ |
void mod1_##TYPE(TYPE z) { \ |
CHECK_##TYPE(z); \ |
if (should_be_true) { \ |
@@ -99,8 +150,8 @@ extern int should_be_true; |
#define GENERATE_FOR_MODULE0(TYPE) \ |
/* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \ |
- extern void mod1_##TYPE(TYPE z) __attribute__((noinline)); \ |
- void mod0_##TYPE(TYPE z) __attribute__((noinline)); \ |
+ extern __attribute__((noinline)) void mod1_##TYPE(TYPE z) ; \ |
+ void __attribute__((noinline)) mod0_##TYPE(TYPE z) ; \ |
void mod0_##TYPE(TYPE z) { \ |
CHECK_##TYPE(z); \ |
if (should_be_true) { \ |
@@ -114,7 +165,7 @@ extern int should_be_true; |
mod1_##TYPE(z); \ |
} \ |
} \ |
- void test_##TYPE(void) __attribute__((noinline)); \ |
+ void __attribute__((noinline)) test_##TYPE(void); \ |
void test_##TYPE(void) { \ |
TYPE z = k##TYPE; \ |
CHECK_##TYPE(z); \ |