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
25namespace 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
48size_t ArgNum;
49CalleePtrTy Callee;
50char *Buf;
51
52const static size_t BUF_SIZE = 16;
53
54std::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
64void 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
125void 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
176int 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