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