xref: /aosp_15_r20/external/mesa3d/src/amd/compiler/tests/main.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2020 Valve Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  */
6*61046927SAndroid Build Coastguard Worker #include "aco_ir.h"
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include <llvm-c/Target.h>
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker #include "framework.h"
11*61046927SAndroid Build Coastguard Worker #include <getopt.h>
12*61046927SAndroid Build Coastguard Worker #include <map>
13*61046927SAndroid Build Coastguard Worker #include <set>
14*61046927SAndroid Build Coastguard Worker #include <stdarg.h>
15*61046927SAndroid Build Coastguard Worker #include <stdio.h>
16*61046927SAndroid Build Coastguard Worker #include <string.h>
17*61046927SAndroid Build Coastguard Worker #include <string>
18*61046927SAndroid Build Coastguard Worker #include <unistd.h>
19*61046927SAndroid Build Coastguard Worker #include <vector>
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker static const char* help_message =
22*61046927SAndroid Build Coastguard Worker    "Usage: %s [-h] [-l --list] [--no-check] [TEST [TEST ...]]\n"
23*61046927SAndroid Build Coastguard Worker    "\n"
24*61046927SAndroid Build Coastguard Worker    "Run ACO unit test(s). If TEST is not provided, all tests are run.\n"
25*61046927SAndroid Build Coastguard Worker    "\n"
26*61046927SAndroid Build Coastguard Worker    "positional arguments:\n"
27*61046927SAndroid Build Coastguard Worker    "  TEST        Run TEST. If TEST ends with a '.', run tests with names\n"
28*61046927SAndroid Build Coastguard Worker    "              starting with TEST. The test variant (after the '/') can\n"
29*61046927SAndroid Build Coastguard Worker    "              be omitted to run all variants\n"
30*61046927SAndroid Build Coastguard Worker    "\n"
31*61046927SAndroid Build Coastguard Worker    "optional arguments:\n"
32*61046927SAndroid Build Coastguard Worker    "  -h, --help  Show this help message and exit.\n"
33*61046927SAndroid Build Coastguard Worker    "  -l --list   List unit tests.\n"
34*61046927SAndroid Build Coastguard Worker    "  --no-check  Print test output instead of checking it.\n";
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker std::map<std::string, TestDef> *tests = NULL;
37*61046927SAndroid Build Coastguard Worker FILE* output = NULL;
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker static TestDef current_test;
40*61046927SAndroid Build Coastguard Worker static unsigned tests_written = 0;
41*61046927SAndroid Build Coastguard Worker static FILE* checker_stdin = NULL;
42*61046927SAndroid Build Coastguard Worker static char* checker_stdin_data = NULL;
43*61046927SAndroid Build Coastguard Worker static size_t checker_stdin_size = 0;
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker static char* output_data = NULL;
46*61046927SAndroid Build Coastguard Worker static size_t output_size = 0;
47*61046927SAndroid Build Coastguard Worker static size_t output_offset = 0;
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker static char current_variant[64] = {0};
50*61046927SAndroid Build Coastguard Worker static std::set<std::string>* variant_filter = NULL;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker bool test_failed = false;
53*61046927SAndroid Build Coastguard Worker bool test_skipped = false;
54*61046927SAndroid Build Coastguard Worker static char fail_message[256] = {0};
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker void
write_test()57*61046927SAndroid Build Coastguard Worker write_test()
58*61046927SAndroid Build Coastguard Worker {
59*61046927SAndroid Build Coastguard Worker    if (!checker_stdin) {
60*61046927SAndroid Build Coastguard Worker       /* not entirely correct, but shouldn't matter */
61*61046927SAndroid Build Coastguard Worker       tests_written++;
62*61046927SAndroid Build Coastguard Worker       return;
63*61046927SAndroid Build Coastguard Worker    }
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    fflush(output);
66*61046927SAndroid Build Coastguard Worker    if (output_offset == output_size && !test_skipped && !test_failed)
67*61046927SAndroid Build Coastguard Worker       return;
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker    char* data = output_data + output_offset;
70*61046927SAndroid Build Coastguard Worker    uint32_t size = output_size - output_offset;
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker    fwrite("test", 1, 4, checker_stdin);
73*61046927SAndroid Build Coastguard Worker    fwrite(current_test.name, 1, strlen(current_test.name) + 1, checker_stdin);
74*61046927SAndroid Build Coastguard Worker    fwrite(current_variant, 1, strlen(current_variant) + 1, checker_stdin);
75*61046927SAndroid Build Coastguard Worker    fwrite(current_test.source_file, 1, strlen(current_test.source_file) + 1, checker_stdin);
76*61046927SAndroid Build Coastguard Worker    if (test_failed || test_skipped) {
77*61046927SAndroid Build Coastguard Worker       const char* res = test_failed ? "failed" : "skipped";
78*61046927SAndroid Build Coastguard Worker       fwrite("\x01", 1, 1, checker_stdin);
79*61046927SAndroid Build Coastguard Worker       fwrite(res, 1, strlen(res) + 1, checker_stdin);
80*61046927SAndroid Build Coastguard Worker       fwrite(fail_message, 1, strlen(fail_message) + 1, checker_stdin);
81*61046927SAndroid Build Coastguard Worker    } else {
82*61046927SAndroid Build Coastguard Worker       fwrite("\x00", 1, 1, checker_stdin);
83*61046927SAndroid Build Coastguard Worker    }
84*61046927SAndroid Build Coastguard Worker    fwrite(&size, 4, 1, checker_stdin);
85*61046927SAndroid Build Coastguard Worker    fwrite(data, 1, size, checker_stdin);
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    tests_written++;
88*61046927SAndroid Build Coastguard Worker    output_offset += size;
89*61046927SAndroid Build Coastguard Worker }
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker bool
set_variant(const char * name)92*61046927SAndroid Build Coastguard Worker set_variant(const char* name)
93*61046927SAndroid Build Coastguard Worker {
94*61046927SAndroid Build Coastguard Worker    if (variant_filter && !variant_filter->count(name))
95*61046927SAndroid Build Coastguard Worker       return false;
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    write_test();
98*61046927SAndroid Build Coastguard Worker    test_failed = false;
99*61046927SAndroid Build Coastguard Worker    test_skipped = false;
100*61046927SAndroid Build Coastguard Worker    strncpy(current_variant, name, sizeof(current_variant) - 1);
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    printf("Running '%s/%s'\n", current_test.name, name);
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    return true;
105*61046927SAndroid Build Coastguard Worker }
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker void
fail_test(const char * fmt,...)108*61046927SAndroid Build Coastguard Worker fail_test(const char* fmt, ...)
109*61046927SAndroid Build Coastguard Worker {
110*61046927SAndroid Build Coastguard Worker    va_list args;
111*61046927SAndroid Build Coastguard Worker    va_start(args, fmt);
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    test_failed = true;
114*61046927SAndroid Build Coastguard Worker    vsnprintf(fail_message, sizeof(fail_message), fmt, args);
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    va_end(args);
117*61046927SAndroid Build Coastguard Worker }
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker void
skip_test(const char * fmt,...)120*61046927SAndroid Build Coastguard Worker skip_test(const char* fmt, ...)
121*61046927SAndroid Build Coastguard Worker {
122*61046927SAndroid Build Coastguard Worker    va_list args;
123*61046927SAndroid Build Coastguard Worker    va_start(args, fmt);
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker    test_skipped = true;
126*61046927SAndroid Build Coastguard Worker    vsnprintf(fail_message, sizeof(fail_message), fmt, args);
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    va_end(args);
129*61046927SAndroid Build Coastguard Worker }
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker void
run_test(TestDef def)132*61046927SAndroid Build Coastguard Worker run_test(TestDef def)
133*61046927SAndroid Build Coastguard Worker {
134*61046927SAndroid Build Coastguard Worker    current_test = def;
135*61046927SAndroid Build Coastguard Worker    output_data = NULL;
136*61046927SAndroid Build Coastguard Worker    output_size = 0;
137*61046927SAndroid Build Coastguard Worker    output_offset = 0;
138*61046927SAndroid Build Coastguard Worker    test_failed = false;
139*61046927SAndroid Build Coastguard Worker    test_skipped = false;
140*61046927SAndroid Build Coastguard Worker    memset(current_variant, 0, sizeof(current_variant));
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker    if (checker_stdin)
143*61046927SAndroid Build Coastguard Worker       output = open_memstream(&output_data, &output_size);
144*61046927SAndroid Build Coastguard Worker    else
145*61046927SAndroid Build Coastguard Worker       output = stdout;
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker    current_test.func();
148*61046927SAndroid Build Coastguard Worker    write_test();
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker    if (checker_stdin)
151*61046927SAndroid Build Coastguard Worker       fclose(output);
152*61046927SAndroid Build Coastguard Worker    free(output_data);
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker int
check_output(char ** argv)156*61046927SAndroid Build Coastguard Worker check_output(char** argv)
157*61046927SAndroid Build Coastguard Worker {
158*61046927SAndroid Build Coastguard Worker    fflush(stdout);
159*61046927SAndroid Build Coastguard Worker    fflush(stderr);
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    fclose(checker_stdin);
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker    int stdin_pipe[2];
164*61046927SAndroid Build Coastguard Worker    pipe(stdin_pipe);
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    pid_t child_pid = fork();
167*61046927SAndroid Build Coastguard Worker    if (child_pid == -1) {
168*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "%s: fork() failed: %s\n", argv[0], strerror(errno));
169*61046927SAndroid Build Coastguard Worker       return 99;
170*61046927SAndroid Build Coastguard Worker    } else if (child_pid != 0) {
171*61046927SAndroid Build Coastguard Worker       /* Evaluate test output externally using Python */
172*61046927SAndroid Build Coastguard Worker       dup2(stdin_pipe[0], STDIN_FILENO);
173*61046927SAndroid Build Coastguard Worker       close(stdin_pipe[0]);
174*61046927SAndroid Build Coastguard Worker       close(stdin_pipe[1]);
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker       execlp(ACO_TEST_PYTHON_BIN, ACO_TEST_PYTHON_BIN, ACO_TEST_SOURCE_DIR "/check_output.py",
177*61046927SAndroid Build Coastguard Worker              NULL);
178*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "%s: execlp() failed: %s\n", argv[0], strerror(errno));
179*61046927SAndroid Build Coastguard Worker       return 99;
180*61046927SAndroid Build Coastguard Worker    } else {
181*61046927SAndroid Build Coastguard Worker       /* Feed input data to the Python process. Writing large streams to
182*61046927SAndroid Build Coastguard Worker        * stdin will block eventually, so this is done in a forked process
183*61046927SAndroid Build Coastguard Worker        * to let the test checker process chunks of data as they arrive */
184*61046927SAndroid Build Coastguard Worker       write(stdin_pipe[1], checker_stdin_data, checker_stdin_size);
185*61046927SAndroid Build Coastguard Worker       close(stdin_pipe[0]);
186*61046927SAndroid Build Coastguard Worker       close(stdin_pipe[1]);
187*61046927SAndroid Build Coastguard Worker       _exit(0);
188*61046927SAndroid Build Coastguard Worker    }
189*61046927SAndroid Build Coastguard Worker }
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker bool
match_test(std::string name,std::string pattern)192*61046927SAndroid Build Coastguard Worker match_test(std::string name, std::string pattern)
193*61046927SAndroid Build Coastguard Worker {
194*61046927SAndroid Build Coastguard Worker    if (name.length() < pattern.length())
195*61046927SAndroid Build Coastguard Worker       return false;
196*61046927SAndroid Build Coastguard Worker    if (pattern.back() == '.')
197*61046927SAndroid Build Coastguard Worker       name.resize(pattern.length());
198*61046927SAndroid Build Coastguard Worker    return name == pattern;
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker int
main(int argc,char ** argv)202*61046927SAndroid Build Coastguard Worker main(int argc, char** argv)
203*61046927SAndroid Build Coastguard Worker {
204*61046927SAndroid Build Coastguard Worker    int print_help = 0;
205*61046927SAndroid Build Coastguard Worker    int do_list = 0;
206*61046927SAndroid Build Coastguard Worker    int do_check = 1;
207*61046927SAndroid Build Coastguard Worker    const struct option opts[] = {{"help", no_argument, &print_help, 1},
208*61046927SAndroid Build Coastguard Worker                                  {"list", no_argument, &do_list, 1},
209*61046927SAndroid Build Coastguard Worker                                  {"no-check", no_argument, &do_check, 0},
210*61046927SAndroid Build Coastguard Worker                                  {NULL, 0, NULL, 0}};
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker    int c;
213*61046927SAndroid Build Coastguard Worker    while ((c = getopt_long(argc, argv, "hl", opts, NULL)) != -1) {
214*61046927SAndroid Build Coastguard Worker       switch (c) {
215*61046927SAndroid Build Coastguard Worker       case 'h': print_help = 1; break;
216*61046927SAndroid Build Coastguard Worker       case 'l': do_list = 1; break;
217*61046927SAndroid Build Coastguard Worker       case 0: break;
218*61046927SAndroid Build Coastguard Worker       case '?':
219*61046927SAndroid Build Coastguard Worker       default: fprintf(stderr, "%s: Invalid argument\n", argv[0]); return 99;
220*61046927SAndroid Build Coastguard Worker       }
221*61046927SAndroid Build Coastguard Worker    }
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker    if (print_help) {
224*61046927SAndroid Build Coastguard Worker       fprintf(stderr, help_message, argv[0]);
225*61046927SAndroid Build Coastguard Worker       return 99;
226*61046927SAndroid Build Coastguard Worker    }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    if (!tests)
229*61046927SAndroid Build Coastguard Worker       tests = new std::map<std::string, TestDef>;
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    if (do_list) {
232*61046927SAndroid Build Coastguard Worker       for (auto test : *tests)
233*61046927SAndroid Build Coastguard Worker          printf("%s\n", test.first.c_str());
234*61046927SAndroid Build Coastguard Worker       return 99;
235*61046927SAndroid Build Coastguard Worker    }
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker    std::vector<std::pair<std::string, std::string>> names;
238*61046927SAndroid Build Coastguard Worker    for (int i = optind; i < argc; i++) {
239*61046927SAndroid Build Coastguard Worker       std::string name = argv[i];
240*61046927SAndroid Build Coastguard Worker       std::string variant;
241*61046927SAndroid Build Coastguard Worker       size_t pos = name.find('/');
242*61046927SAndroid Build Coastguard Worker       if (pos != std::string::npos) {
243*61046927SAndroid Build Coastguard Worker          variant = name.substr(pos + 1);
244*61046927SAndroid Build Coastguard Worker          name = name.substr(0, pos);
245*61046927SAndroid Build Coastguard Worker       }
246*61046927SAndroid Build Coastguard Worker       names.emplace_back(std::pair<std::string, std::string>(name, variant));
247*61046927SAndroid Build Coastguard Worker    }
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    if (do_check)
250*61046927SAndroid Build Coastguard Worker       checker_stdin = open_memstream(&checker_stdin_data, &checker_stdin_size);
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker    LLVMInitializeAMDGPUTargetInfo();
253*61046927SAndroid Build Coastguard Worker    LLVMInitializeAMDGPUTarget();
254*61046927SAndroid Build Coastguard Worker    LLVMInitializeAMDGPUTargetMC();
255*61046927SAndroid Build Coastguard Worker    LLVMInitializeAMDGPUDisassembler();
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker    aco::init();
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    for (auto pair : *tests) {
260*61046927SAndroid Build Coastguard Worker       bool found = names.empty();
261*61046927SAndroid Build Coastguard Worker       bool all_variants = names.empty();
262*61046927SAndroid Build Coastguard Worker       std::set<std::string> variants;
263*61046927SAndroid Build Coastguard Worker       for (const std::pair<std::string, std::string>& name : names) {
264*61046927SAndroid Build Coastguard Worker          if (match_test(pair.first, name.first)) {
265*61046927SAndroid Build Coastguard Worker             found = true;
266*61046927SAndroid Build Coastguard Worker             if (name.second.empty())
267*61046927SAndroid Build Coastguard Worker                all_variants = true;
268*61046927SAndroid Build Coastguard Worker             else
269*61046927SAndroid Build Coastguard Worker                variants.insert(name.second);
270*61046927SAndroid Build Coastguard Worker          }
271*61046927SAndroid Build Coastguard Worker       }
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker       if (found) {
274*61046927SAndroid Build Coastguard Worker          variant_filter = all_variants ? NULL : &variants;
275*61046927SAndroid Build Coastguard Worker          printf("Running '%s'\n", pair.first.c_str());
276*61046927SAndroid Build Coastguard Worker          run_test(pair.second);
277*61046927SAndroid Build Coastguard Worker       }
278*61046927SAndroid Build Coastguard Worker    }
279*61046927SAndroid Build Coastguard Worker    if (!tests_written) {
280*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "%s: No matching tests\n", argv[0]);
281*61046927SAndroid Build Coastguard Worker       return 99;
282*61046927SAndroid Build Coastguard Worker    }
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker    if (checker_stdin) {
285*61046927SAndroid Build Coastguard Worker       printf("\n");
286*61046927SAndroid Build Coastguard Worker       return check_output(argv);
287*61046927SAndroid Build Coastguard Worker    } else {
288*61046927SAndroid Build Coastguard Worker       printf("Tests ran\n");
289*61046927SAndroid Build Coastguard Worker       return 99;
290*61046927SAndroid Build Coastguard Worker    }
291*61046927SAndroid Build Coastguard Worker }
292