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