| Index: tests/callingconv_case_by_case/return_structs.cc
|
| diff --git a/tests/callingconv_case_by_case/return_structs.cc b/tests/callingconv_case_by_case/return_structs.cc
|
| index 32015b324f695507c2fa3e5e6f8ba6a981c3e1a6..549b4b6a9366433de0e9206fb19c55d97d3de4d7 100644
|
| --- a/tests/callingconv_case_by_case/return_structs.cc
|
| +++ b/tests/callingconv_case_by_case/return_structs.cc
|
| @@ -42,9 +42,59 @@ 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)) TYPE mod3_##TYPE(void)
|
| +#define MOD2_TO_3_CALL(TYPE, ret) \
|
| + ret = mod3_##TYPE()
|
| +#define MOD1_DECL(TYPE) \
|
| + __attribute__((pnaclcall,noinline)) TYPE mod1_##TYPE(void)
|
| +
|
| +#elif defined(TEST_ATTRIBUTE_VIA_FP)
|
| +
|
| +#define MOD3_DECL(TYPE) \
|
| + /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \
|
| + extern __attribute__((noinline)) TYPE mod3_##TYPE(void)
|
| +#define MOD2_TO_3_CALL(TYPE, ret) \
|
| + do { \
|
| + TYPE (__attribute__((pnaclcall)) *temp_fp)(void) = \
|
| + (TYPE (__attribute__((pnaclcall)) *)(void)) &mod3_##TYPE; \
|
| + ret = (*temp_fp)(); \
|
| + } while(0)
|
| +#define MOD1_DECL(TYPE) \
|
| + __attribute__((pnaclcall,noinline)) TYPE mod1_##TYPE(void)
|
| +
|
| +#else /* Testing with just the commandline flag / or nothing at all. */
|
| +
|
| +#define MOD3_DECL(TYPE) \
|
| + /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \
|
| + extern __attribute__((noinline)) TYPE mod3_##TYPE(void)
|
| +#define MOD2_TO_3_CALL(TYPE, ret) \
|
| + ret = mod3_##TYPE()
|
| +#define MOD1_DECL(TYPE) \
|
| + __attribute__((noinline)) TYPE mod1_##TYPE(void)
|
| +
|
| +#endif /* TEST_ATTRIBUTE_VIA_... */
|
| +
|
| +/**********************************************************************/
|
| +/* The actual test code structure (which is divided into 4 modules). */
|
| +
|
| #define GENERATE_FOR_MODULE3(TYPE) \
|
| TYPE mod3_##TYPE(void) __attribute__((noinline)); \
|
| TYPE mod3_##TYPE(void) { \
|
| @@ -63,11 +113,12 @@ extern int should_be_true;
|
|
|
| #define GENERATE_FOR_MODULE2(TYPE) \
|
| /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \
|
| - extern TYPE mod3_##TYPE(void) __attribute__((noinline)); \
|
| + MOD3_DECL(TYPE); \
|
| TYPE mod2_##TYPE(void) __attribute__((noinline)); \
|
| TYPE mod2_##TYPE(void) { \
|
| if (should_be_true) { \
|
| - TYPE z = mod3_##TYPE(); \
|
| + TYPE z; \
|
| + MOD2_TO_3_CALL(TYPE, z); \
|
| CHECK_##TYPE(z); \
|
| printf("Made it to mod2_" #TYPE "\n"); \
|
| return z; \
|
| @@ -83,7 +134,7 @@ extern int should_be_true;
|
| #define GENERATE_FOR_MODULE1(TYPE) \
|
| /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ \
|
| extern TYPE mod2_##TYPE(void) __attribute__((noinline)); \
|
| - TYPE mod1_##TYPE(void) __attribute__((noinline)); \
|
| + MOD1_DECL(TYPE); \
|
| TYPE mod1_##TYPE(void) { \
|
| if (should_be_true) { \
|
| TYPE z = mod2_##TYPE(); \
|
|
|