1 /*
2 * Copyright 2020-2021 Collabora Ltd.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef __AGX_TEST_H
7 #define __AGX_TEST_H
8
9 #include <inttypes.h>
10 #include <stdio.h>
11 #include "agx_builder.h"
12 #include "agx_compiler.h"
13
14 /* Helper to generate a agx_builder suitable for creating test instructions */
15 static inline agx_builder *
agx_test_builder(void * memctx)16 agx_test_builder(void *memctx)
17 {
18 agx_context *ctx = rzalloc(memctx, agx_context);
19 list_inithead(&ctx->blocks);
20
21 agx_block *blk = rzalloc(ctx, agx_block);
22 util_dynarray_init(&blk->predecessors, NULL);
23
24 list_addtail(&blk->link, &ctx->blocks);
25 list_inithead(&blk->instructions);
26
27 agx_builder *b = rzalloc(memctx, agx_builder);
28 b->shader = ctx;
29 b->cursor = agx_after_block(blk);
30
31 return b;
32 }
33
34 /* Helper to compare for logical equality of instructions. Need to compare the
35 * pointers, then compare raw data.
36 */
37 static inline bool
agx_instr_equal(agx_instr * A,agx_instr * B)38 agx_instr_equal(agx_instr *A, agx_instr *B)
39 {
40 unsigned pointers = sizeof(struct list_head) + sizeof(agx_index *) * 2;
41
42 if (A->nr_srcs != B->nr_srcs)
43 return false;
44
45 if (memcmp(A->src, B->src, A->nr_srcs * sizeof(agx_index)))
46 return false;
47
48 if (A->nr_dests != B->nr_dests)
49 return false;
50
51 if (memcmp(A->dest, B->dest, A->nr_dests * sizeof(agx_index)))
52 return false;
53
54 return memcmp((uint8_t *)A + pointers, (uint8_t *)B + pointers,
55 sizeof(agx_instr) - pointers) == 0;
56 }
57
58 static inline bool
agx_block_equal(agx_block * A,agx_block * B)59 agx_block_equal(agx_block *A, agx_block *B)
60 {
61 if (list_length(&A->instructions) != list_length(&B->instructions))
62 return false;
63
64 list_pair_for_each_entry(agx_instr, insA, insB, &A->instructions,
65 &B->instructions, link) {
66 if (!agx_instr_equal(insA, insB))
67 return false;
68 }
69
70 return true;
71 }
72
73 static inline bool
agx_shader_equal(agx_context * A,agx_context * B)74 agx_shader_equal(agx_context *A, agx_context *B)
75 {
76 if (list_length(&A->blocks) != list_length(&B->blocks))
77 return false;
78
79 list_pair_for_each_entry(agx_block, blockA, blockB, &A->blocks, &B->blocks,
80 link) {
81 if (!agx_block_equal(blockA, blockB))
82 return false;
83 }
84
85 return true;
86 }
87
88 #define ASSERT_SHADER_EQUAL(A, B) \
89 if (!agx_shader_equal(A, B)) { \
90 ADD_FAILURE(); \
91 fprintf(stderr, "Pass produced unexpected results"); \
92 fprintf(stderr, " Actual:\n"); \
93 agx_print_shader(A, stderr); \
94 fprintf(stderr, " Expected:\n"); \
95 agx_print_shader(B, stderr); \
96 fprintf(stderr, "\n"); \
97 }
98
99 #define INSTRUCTION_CASE(instr, expected, pass) \
100 do { \
101 agx_builder *A = agx_test_builder(mem_ctx); \
102 agx_builder *B = agx_test_builder(mem_ctx); \
103 { \
104 agx_builder *b = A; \
105 instr; \
106 } \
107 { \
108 agx_builder *b = B; \
109 expected; \
110 } \
111 pass(A->shader); \
112 ASSERT_SHADER_EQUAL(A->shader, B->shader); \
113 } while (0)
114
115 #endif
116