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 
bufAsString(const char Buf[BUF_SIZE])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 
testCaller(size_t & TotalTests,size_t & Passes,size_t & Failures)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 
testCallee(size_t & TotalTests,size_t & Passes,size_t & Failures)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 
main(int argc,char * argv[])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