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), \
76 STR(callee), \
77 argc, \
78 &caller, \
79 &Subzero_::caller, \
80 reinterpret_cast<CalleePtrTy>(&Subzero_::callee), \
81 },
82 TEST_FUNC_TABLE
83 #undef X
84 #else
85 #define X(caller, callee, argc) \
86 { \
87 STR(caller), STR(callee), argc, \
88 &caller, &Subzero_::caller, reinterpret_cast<CalleePtrTy>(&callee), \
89 },
90 TEST_FUNC_TABLE
91 #undef X
92 #endif
93 };
94
95 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
96
97 for (size_t f = 0; f < NumFuncs; ++f) {
98 char BufLlc[BUF_SIZE], BufSz[BUF_SIZE];
99 Callee = Funcs[f].Callee;
100
101 for (size_t i = 0; i < Funcs[f].Args; ++i) {
102 memset(BufLlc, 0xff, sizeof(BufLlc));
103 memset(BufSz, 0xff, sizeof(BufSz));
104
105 ArgNum = i;
106
107 Buf = BufLlc;
108 Funcs[f].Caller();
109
110 Buf = BufSz;
111 Funcs[f].Subzero_Caller();
112
113 ++TotalTests;
114 if (!memcmp(BufLlc, BufSz, sizeof(BufLlc))) {
115 ++Passes;
116 } else {
117 ++Failures;
118 std::cout << "testCaller(Caller=" << Funcs[f].CallerName
119 << ", Callee=" << Funcs[f].CalleeName << ", ArgNum=" << ArgNum
120 << ")\nsz =" << bufAsString(BufSz)
121 << "\nllc=" << bufAsString(BufLlc) << "\n";
122 }
123 }
124 }
125 }
126
testCallee(size_t & TotalTests,size_t & Passes,size_t & Failures)127 void testCallee(size_t &TotalTests, size_t &Passes, size_t &Failures) {
128 static struct {
129 const char *CallerName, *CalleeName;
130 size_t Args;
131 void (*Caller)(void);
132 CalleePtrTy Callee, Subzero_Callee;
133 } Funcs[] = {
134 #define X(caller, callee, argc) \
135 {STR(caller), \
136 STR(callee), \
137 argc, \
138 &caller, \
139 reinterpret_cast<CalleePtrTy>(&callee), \
140 reinterpret_cast<CalleePtrTy>(&Subzero_::callee)},
141 TEST_FUNC_TABLE
142 #undef X
143 };
144
145 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
146
147 for (size_t f = 0; f < NumFuncs; ++f) {
148 char BufLlc[BUF_SIZE], BufSz[BUF_SIZE];
149
150 for (size_t i = 0; i < Funcs[f].Args; ++i) {
151 memset(BufLlc, 0xff, sizeof(BufLlc));
152 memset(BufSz, 0xff, sizeof(BufSz));
153
154 ArgNum = i;
155
156 Buf = BufLlc;
157 Callee = Funcs[f].Callee;
158 Funcs[f].Caller();
159
160 Buf = BufSz;
161 Callee = Funcs[f].Subzero_Callee;
162 Funcs[f].Caller();
163
164 ++TotalTests;
165 if (!memcmp(BufLlc, BufSz, sizeof(BufLlc))) {
166 ++Passes;
167 } else {
168 ++Failures;
169 std::cout << "testCallee(Caller=" << Funcs[f].CallerName
170 << ", Callee=" << Funcs[f].CalleeName << ", ArgNum=" << ArgNum
171 << ")\nsz =" << bufAsString(BufSz)
172 << "\nllc=" << bufAsString(BufLlc) << "\n";
173 }
174 }
175 }
176 }
177
main(int argc,char * argv[])178 int main(int argc, char *argv[]) {
179 size_t TotalTests = 0;
180 size_t Passes = 0;
181 size_t Failures = 0;
182
183 testCaller(TotalTests, Passes, Failures);
184 testCallee(TotalTests, Passes, Failures);
185
186 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
187 << " Failures=" << Failures << "\n";
188
189 return Failures;
190 }
191