1  /* This header file should be included for the purpose of parameter passing
       2     testing and va_arg code gen testing.
       3  
       4     To test va_arg code gen, #define AAPCS64_TEST_STDARG in the test case.
       5  
       6     The parameter passing test is done by passing variables/constants to
       7     'myfunc', which pushes its incoming arguments to a memory block on the
       8     stack and then passes the memory block address to 'testfunc'.  It is inside
       9     'testfunc' that the real parameter passing check is carried out.
      10  
      11     The function body of 'myfunc' is in abitest.S.  The declaration of 'myfunc'
      12     is constructed during the pre-processing stage.
      13  
      14     The va_arg code gen test has a similar workflow, apart from an extra set-up
      15     step before calling 'myfunc'.  All arguments are passed to 'stdarg_func'
      16     first, which assigned these arguments to its local variables via either
      17     direct assignment or va_arg macro, depending on whether an argument is named
      18     or not.  Afterwards, 'stdarg_func' calls 'myfunc' with the aforementioned
      19     local variables as the arguments to finish the remaining steps.  */
      20  
      21  #include "abitest-common.h"
      22  #include "validate_memory.h"
      23  
      24  #ifdef AAPCS64_TEST_STDARG
      25  /* Generate va_start (ap, last_named_arg).  Note that this requires
      26     LAST_NAMED_ARG_ID to be defined/used correctly in the test file.  */
      27  #ifndef LAST_NAMED_ARG_ID
      28  #define LAST_NAMED_ARG_ID 65535
      29  #endif
      30  #ifndef VA_START
      31  #undef VA_START_1
      32  #define VA_START_1(ap, id) va_start (ap, _f##id);
      33  #define VA_START(ap, id) VA_START_1 (ap, id);
      34  #endif
      35  #endif /* AAPCS64_TEST_STDARG */
      36  
      37  /* Some debugging facility.  */
      38  #undef DUMP_ARG
      39  #ifdef DUMP_ENABLED
      40  #define DUMP_ARG(type,val) printf ("### Checking ARG "#type" "#val"\n")
      41  #else
      42  #define DUMP_ARG(type,val)
      43  #endif
      44  
      45  
      46  /* Function called from myfunc (defined in abitest.S) to check the arguments
      47     passed to myfunc.  myfunc has pushed all the arguments into the memory
      48     block pointed by STACK.  */
      49  void testfunc(char* stack)
      50  {
      51  #define AARCH64_MACRO_DEF_CHECK_INCOMING_ARGS
      52  #include "macro-def.h"
      53  #include TESTFILE
      54  #undef AARCH64_MACRO_DEF_CHECK_INCOMING_ARGS
      55    return;
      56  }
      57  
      58  
      59  #ifndef AAPCS64_TEST_STDARG
      60  /* Test parameter passing.  */
      61  
      62  /* Function declaration of myfunc.  */
      63  MYFUNCTYPE myfunc(
      64  #define AARCH64_MACRO_DEF_GEN_PARAM_TYPE_LIST
      65  #include "macro-def.h"
      66  #include TESTFILE
      67  #undef AARCH64_MACRO_DEF_GEN_PARAM_TYPE_LIST
      68  ) PCSATTR;
      69  
      70  #else /* AAPCS64_TEST_STDARG */
      71  /* Test stdarg macros, e.g. va_arg.  */
      72  #include <stdarg.h>
      73  
      74  /* Dummy function to help reset parameter passing registers, i.e. X0-X7
      75     and V0-V7 (by being passed 0 in W0-W7 and 0.f in S0-S7).  */
      76  __attribute__ ((noipa)) void
      77  dummy_func (int w0, int w1, int w2, int w3, int w4, int w5, int w6, int w7,
      78  	    float s0, float s1, float s2, float s3, float s4, float s5,
      79  	    float s6, float s7)
      80  {
      81    asm (""); /* Prevent function from getting optimized away */
      82    return;
      83  }
      84  
      85  /* Function declaration of myfunc.  */
      86  MYFUNCTYPE myfunc(
      87  #define AARCH64_VARIADIC_MACRO_DEF_GEN_PARAM_TYPE_LIST
      88  #include "macro-def.h"
      89  #include TESTFILE
      90  #undef AARCH64_VARIADIC_MACRO_DEF_GEN_PARAM_TYPE_LIST
      91  ) PCSATTR;
      92  
      93  /* Function definition of stdarg_func.
      94     stdarg_func is a variadic function; it retrieves all of its arguments,
      95     both named and unnamed, and passes them to myfunc in the identical
      96     order.  myfunc will carry out the check on the passed values.  Remember
      97     that myfunc is not a variadic function.  */
      98  MYFUNCTYPE stdarg_func(
      99  #define AARCH64_VARIADIC_MACRO_DEF_GEN_PARAM_TYPE_LIST_WITH_IDENT
     100  #include "macro-def.h"
     101  #include TESTFILE
     102  #undef AARCH64_VARIADIC_MACRO_DEF_GEN_PARAM_TYPE_LIST_WITH_IDENT
     103  ) PCSATTR
     104  {
     105    /* Start of the function body of stdarg_func.  */
     106    va_list ap;
     107  
     108    VA_START (ap, LAST_NAMED_ARG_ID)
     109    /* Zeroize the content of X0-X7 and V0-V7 to make sure that any va_arg
     110       failure will not be hidden by the old data being in these registers.  */
     111    dummy_func (0, 0, 0, 0, 0, 0, 0, 0, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
     112    /* A full memory barrier to ensure that compiler won't optimize away
     113       va_arg code gen.  */
     114    __sync_synchronize ();
     115      {
     116        /* Assign all the function incoming arguments to local variables. */
     117  #define AARCH64_VARIADIC_MACRO_DEF_ASSIGN_LOCAL_VARS_WITH_ARGS
     118  #include "macro-def.h"
     119  #include TESTFILE
     120  #undef AARCH64_VARIADIC_MACRO_DEF_ASSIGN_LOCAL_VARS_WITH_ARGS
     121  
     122        /* Call myfunc and pass in the local variables prepared above.  */
     123        myfunc (
     124  #define AARCH64_VARIADIC_MACRO_DEF_GEN_ARGUMENT_LIST
     125  #include "macro-def.h"
     126  #include TESTFILE
     127  #undef AARCH64_VARIADIC_MACRO_DEF_GEN_ARGUMENT_LIST
     128  );
     129      }
     130    va_end (ap);
     131  }
     132  
     133  #endif /* AAPCS64_TEST_STDARG */
     134  
     135  
     136  int main()
     137  {
     138  #ifdef RUNTIME_ENDIANNESS_CHECK
     139    rt_endian_check();
     140  #endif
     141  #ifdef HAS_DATA_INIT_FUNC
     142    init_data ();
     143  #endif
     144  
     145  #ifndef AAPCS64_TEST_STDARG
     146    which_kind_of_test = TK_PARAM;
     147    myfunc(
     148  #else
     149    which_kind_of_test = TK_VA_ARG;
     150    stdarg_func(
     151  #endif
     152  #define AARCH64_MACRO_DEF_GEN_ARGUMENT_LIST
     153  #include "macro-def.h"
     154  #include TESTFILE
     155  #undef AARCH64_MACRO_DEF_GEN_ARGUMENT_LIST
     156  );
     157    return 0;
     158  }
     159