Home | History | Annotate | Download | only in crosstest
      1 //===- subzero/crosstest/test_calling_conv_main.cpp - Driver for tests ----===//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the driver for cross testing the compatibility of
     11 // calling conventions.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 /* crosstest.py --test=test_calling_conv.cpp               \
     16    --driver=test_calling_conv_main.cpp --prefix=Subzero_   \
     17    --output=test_calling_conv */
     18 
     19 #include <cstring>
     20 #include <iostream>
     21 #include <sstream>
     22 
     23 #include "test_calling_conv.h"
     24 
     25 namespace Subzero_ {
     26 #include "test_calling_conv.h"
     27 }
     28 
     29 // The crosstest code consists of caller / callee function pairs.
     30 //
     31 // The caller function initializes a list of arguments and calls the
     32 // function located at Callee.
     33 //
     34 // The callee function writes the argument numbered ArgNum into the
     35 // location pointed to by Buf.
     36 //
     37 // testCaller() tests that caller functions, as compiled by Subzero and
     38 // llc, pass arguments to the callee in the same way.  The Caller() and
     39 // Subzero_Caller() functions both call the same callee (which has been
     40 // compiled by llc).  The result in the global buffer is compared to
     41 // check that it is the same value after the calls by both callers.
     42 //
     43 // testCallee() runs the same kind of test, except that the functions
     44 // Callee() and Subzero_Callee() are being tested to ensure that both
     45 // functions receive arguments from the caller in the same way.  The
     46 // caller is compiled by llc.
     47 
     48 size_t ArgNum;
     49 CalleePtrTy Callee;
     50 char *Buf;
     51 
     52 const static size_t BUF_SIZE = 16;
     53 
     54 std::string bufAsString(const char Buf[BUF_SIZE]) {
     55   std::ostringstream OS;
     56   for (size_t i = 0; i < BUF_SIZE; ++i) {
     57     if (i > 0)
     58       OS << " ";
     59     OS << (unsigned)Buf[i];
     60   }
     61   return OS.str();
     62 }
     63 
     64 void testCaller(size_t &TotalTests, size_t &Passes, size_t &Failures) {
     65   static struct {
     66     const char *CallerName, *CalleeName;
     67     size_t Args;
     68     void (*Caller)(void);
     69     void (*Subzero_Caller)(void);
     70     CalleePtrTy Callee;
     71   } Funcs[] = {
     72 #ifdef MIPS32
     73 #define X(caller, callee, argc)                                                \
     74   {                                                                            \
     75     STR(caller), STR(callee), argc, &caller, &Subzero_::caller,                \
     76         reinterpret_cast<CalleePtrTy>(&Subzero_::callee),                      \
     77   }                                                                            \
     78   ,
     79       TEST_FUNC_TABLE
     80 #undef X
     81 #else
     82 #define X(caller, callee, argc)                                                \
     83   {                                                                            \
     84     STR(caller), STR(callee), argc, &caller, &Subzero_::caller,                \
     85         reinterpret_cast<CalleePtrTy>(&callee),                                \
     86   }                                                                            \
     87   ,
     88       TEST_FUNC_TABLE
     89 #undef X
     90 #endif
     91   };
     92 
     93   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
     94 
     95   for (size_t f = 0; f < NumFuncs; ++f) {
     96     char BufLlc[BUF_SIZE], BufSz[BUF_SIZE];
     97     Callee = Funcs[f].Callee;
     98 
     99     for (size_t i = 0; i < Funcs[f].Args; ++i) {
    100       memset(BufLlc, 0xff, sizeof(BufLlc));
    101       memset(BufSz, 0xff, sizeof(BufSz));
    102 
    103       ArgNum = i;
    104 
    105       Buf = BufLlc;
    106       Funcs[f].Caller();
    107 
    108       Buf = BufSz;
    109       Funcs[f].Subzero_Caller();
    110 
    111       ++TotalTests;
    112       if (!memcmp(BufLlc, BufSz, sizeof(BufLlc))) {
    113         ++Passes;
    114       } else {
    115         ++Failures;
    116         std::cout << "testCaller(Caller=" << Funcs[f].CallerName
    117                   << ", Callee=" << Funcs[f].CalleeName << ", ArgNum=" << ArgNum
    118                   << ")\nsz =" << bufAsString(BufSz)
    119                   << "\nllc=" << bufAsString(BufLlc) << "\n";
    120       }
    121     }
    122   }
    123 }
    124 
    125 void testCallee(size_t &TotalTests, size_t &Passes, size_t &Failures) {
    126   static struct {
    127     const char *CallerName, *CalleeName;
    128     size_t Args;
    129     void (*Caller)(void);
    130     CalleePtrTy Callee, Subzero_Callee;
    131   } Funcs[] = {
    132 #define X(caller, callee, argc)                                                \
    133   {                                                                            \
    134     STR(caller), STR(callee), argc, &caller,                                   \
    135         reinterpret_cast<CalleePtrTy>(&callee),                                \
    136         reinterpret_cast<CalleePtrTy>(&Subzero_::callee)                       \
    137   }                                                                            \
    138   ,
    139       TEST_FUNC_TABLE
    140 #undef X
    141   };
    142 
    143   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
    144 
    145   for (size_t f = 0; f < NumFuncs; ++f) {
    146     char BufLlc[BUF_SIZE], BufSz[BUF_SIZE];
    147 
    148     for (size_t i = 0; i < Funcs[f].Args; ++i) {
    149       memset(BufLlc, 0xff, sizeof(BufLlc));
    150       memset(BufSz, 0xff, sizeof(BufSz));
    151 
    152       ArgNum = i;
    153 
    154       Buf = BufLlc;
    155       Callee = Funcs[f].Callee;
    156       Funcs[f].Caller();
    157 
    158       Buf = BufSz;
    159       Callee = Funcs[f].Subzero_Callee;
    160       Funcs[f].Caller();
    161 
    162       ++TotalTests;
    163       if (!memcmp(BufLlc, BufSz, sizeof(BufLlc))) {
    164         ++Passes;
    165       } else {
    166         ++Failures;
    167         std::cout << "testCallee(Caller=" << Funcs[f].CallerName
    168                   << ", Callee=" << Funcs[f].CalleeName << ", ArgNum=" << ArgNum
    169                   << ")\nsz =" << bufAsString(BufSz)
    170                   << "\nllc=" << bufAsString(BufLlc) << "\n";
    171       }
    172     }
    173   }
    174 }
    175 
    176 int main(int argc, char *argv[]) {
    177   size_t TotalTests = 0;
    178   size_t Passes = 0;
    179   size_t Failures = 0;
    180 
    181   testCaller(TotalTests, Passes, Failures);
    182   testCallee(TotalTests, Passes, Failures);
    183 
    184   std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
    185             << " Failures=" << Failures << "\n";
    186 
    187   return Failures;
    188 }
    189