1 /*
2 * Copyright © 2024 Imagination Technologies Ltd.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 /**
8 * \file pco.c
9 *
10 * \brief Main compiler interface.
11 */
12
13 #include "compiler/glsl_types.h"
14 #include "pco.h"
15 #include "pco_internal.h"
16 #include "util/hash_table.h"
17 #include "util/list.h"
18 #include "util/macros.h"
19 #include "util/ralloc.h"
20
21 #include <assert.h>
22 #include <stdbool.h>
23
24 /**
25 * \brief PCO compiler context destructor.
26 *
27 * \param[in,out] ptr PCO compiler context pointer.
28 */
pco_ctx_destructor(UNUSED void * ptr)29 static void pco_ctx_destructor(UNUSED void *ptr)
30 {
31 glsl_type_singleton_decref();
32 }
33
34 /**
35 * \brief Allocates and sets up a PCO compiler context.
36 *
37 * \param[in] dev_info Device info.
38 * \param[in] mem_ctx Ralloc memory allocation context.
39 * \return The PCO compiler context, or NULL on failure.
40 */
pco_ctx_create(const struct pvr_device_info * dev_info,void * mem_ctx)41 pco_ctx *pco_ctx_create(const struct pvr_device_info *dev_info, void *mem_ctx)
42 {
43 pco_ctx *ctx = rzalloc_size(mem_ctx, sizeof(*ctx));
44
45 ctx->dev_info = dev_info;
46
47 pco_debug_init();
48
49 #ifndef NDEBUG
50 /* Ensure NIR debug variables are processed. */
51 nir_process_debug_variable();
52 #endif /* NDEBUG */
53
54 pco_setup_spirv_options(dev_info, &ctx->spirv_options);
55 pco_setup_nir_options(dev_info, &ctx->nir_options);
56
57 glsl_type_singleton_init_or_ref();
58 ralloc_set_destructor(ctx, pco_ctx_destructor);
59
60 return ctx;
61 }
62
63 /**
64 * \brief Returns the device/core-specific SPIR-V to NIR options for a PCO
65 * compiler context.
66 *
67 * \param[in] ctx PCO compiler context.
68 * \return The device/core-specific SPIR-V to NIR options.
69 */
pco_spirv_options(pco_ctx * ctx)70 const struct spirv_to_nir_options *pco_spirv_options(pco_ctx *ctx)
71 {
72 return &ctx->spirv_options;
73 }
74
75 /**
76 * \brief Returns the device/core-specific NIR options for a PCO compiler
77 * context.
78 *
79 * \param[in] ctx PCO compiler context.
80 * \return The device/core-specific NIR options.
81 */
pco_nir_options(pco_ctx * ctx)82 const nir_shader_compiler_options *pco_nir_options(pco_ctx *ctx)
83 {
84 return &ctx->nir_options;
85 }
86
87 /**
88 * \brief Allocates and sets up a PCO shader from a NIR shader.
89 *
90 * \param[in] ctx PCO compiler context.
91 * \param[in] nir The NIR shader.
92 * \return The PCO shader, or NULL on failure.
93 */
pco_shader_create(pco_ctx * ctx,nir_shader * nir,void * mem_ctx)94 pco_shader *pco_shader_create(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
95 {
96 pco_shader *shader = rzalloc_size(mem_ctx, sizeof(*shader));
97
98 shader->ctx = ctx;
99 shader->nir = nir;
100 shader->stage = nir->info.stage;
101 shader->name = ralloc_strdup(shader, nir->info.name);
102 shader->is_internal = nir->info.internal;
103 shader->is_grouped = false;
104 list_inithead(&shader->funcs);
105
106 return shader;
107 }
108
109 /**
110 * \brief Sets up a PCO cf node.
111 *
112 * \param[in,out] cf_node PCO cf node.
113 * \param[in] type CF node type.
114 */
init_cf_node(pco_cf_node * cf_node,enum pco_cf_node_type type)115 static inline void init_cf_node(pco_cf_node *cf_node,
116 enum pco_cf_node_type type)
117 {
118 cf_node->type = type;
119 cf_node->parent = NULL;
120 }
121
122 /**
123 * \brief Allocates and sets up a PCO function.
124 *
125 * \param[in,out] shader PCO shader.
126 * \param[in] type The function type.
127 * \param[in] num_params The number of parameters.
128 * \return The PCO function, or NULL on failure.
129 */
pco_func_create(pco_shader * shader,enum pco_func_type type,unsigned num_params)130 pco_func *pco_func_create(pco_shader *shader,
131 enum pco_func_type type,
132 unsigned num_params)
133 {
134 pco_func *func = rzalloc_size(shader, sizeof(*func));
135 pco_func *preamble = pco_preamble(shader);
136
137 /* Add the function to the shader; preamble goes first, then entrypoint.
138 * The rest of the functions will get appended.
139 */
140 if (type == PCO_FUNC_TYPE_PREAMBLE) {
141 assert(!preamble);
142 list_add(&func->link, &shader->funcs);
143 } else if (type == PCO_FUNC_TYPE_ENTRYPOINT) {
144 assert(!pco_entrypoint(shader));
145 list_add(&func->link, !preamble ? &shader->funcs : &preamble->link);
146 } else {
147 list_addtail(&func->link, &shader->funcs);
148 }
149
150 init_cf_node(&func->cf_node, PCO_CF_NODE_TYPE_FUNC);
151 func->parent_shader = shader;
152 func->type = type;
153 func->index = shader->next_func++;
154
155 list_inithead(&func->body);
156
157 func->num_params = num_params;
158 if (num_params) {
159 func->params =
160 rzalloc_array_size(func, sizeof(*func->params), num_params);
161 }
162
163 func->vec_infos = _mesa_hash_table_u64_create(func);
164
165 func->enc_offset = ~0U;
166
167 return func;
168 }
169
170 /**
171 * \brief Allocates and sets up a PCO block.
172 *
173 * \param[in,out] func Parent function.
174 * \return The PCO block, or NULL on failure.
175 */
pco_block_create(pco_func * func)176 pco_block *pco_block_create(pco_func *func)
177 {
178 pco_block *block = rzalloc_size(func, sizeof(*block));
179
180 init_cf_node(&block->cf_node, PCO_CF_NODE_TYPE_BLOCK);
181 block->parent_func = func;
182 list_inithead(&block->instrs);
183 block->index = func->next_block++;
184
185 return block;
186 }
187
188 /**
189 * \brief Allocates and sets up a PCO if construct.
190 *
191 * \param[in,out] func Parent function.
192 * \return The PCO if construct, or NULL on failure.
193 */
pco_if_create(pco_func * func)194 pco_if *pco_if_create(pco_func *func)
195 {
196 pco_if *pif = rzalloc_size(func, sizeof(*pif));
197
198 init_cf_node(&pif->cf_node, PCO_CF_NODE_TYPE_IF);
199 pif->parent_func = func;
200 list_inithead(&pif->then_body);
201 list_inithead(&pif->else_body);
202 pif->index = func->next_if++;
203
204 return pif;
205 }
206
207 /**
208 * \brief Allocates and sets up a PCO loop.
209 *
210 * \param[in,out] func Parent function.
211 * \return The PCO loop, or NULL on failure.
212 */
pco_loop_create(pco_func * func)213 pco_loop *pco_loop_create(pco_func *func)
214 {
215 pco_loop *loop = rzalloc_size(func, sizeof(*loop));
216
217 init_cf_node(&loop->cf_node, PCO_CF_NODE_TYPE_LOOP);
218 loop->parent_func = func;
219 list_inithead(&loop->body);
220 loop->index = func->next_loop++;
221
222 return loop;
223 }
224
225 /**
226 * \brief Allocates and sets up a PCO instruction.
227 *
228 * \param[in,out] func Parent function.
229 * \param[in] op Instruction op.
230 * \param[in] num_dests Number of destinations.
231 * \param[in] num_srcs Number of sources.
232 * \return The PCO instruction, or NULL on failure.
233 */
pco_instr_create(pco_func * func,enum pco_op op,unsigned num_dests,unsigned num_srcs)234 pco_instr *pco_instr_create(pco_func *func,
235 enum pco_op op,
236 unsigned num_dests,
237 unsigned num_srcs)
238 {
239 pco_instr *instr;
240 unsigned size = sizeof(*instr);
241 size += num_dests * sizeof(*instr->dest);
242 size += num_srcs * sizeof(*instr->src);
243
244 instr = rzalloc_size(func, size);
245
246 instr->parent_func = func;
247
248 instr->op = op;
249
250 instr->num_dests = num_dests;
251 instr->dest = (pco_ref *)(instr + 1);
252
253 instr->num_srcs = num_srcs;
254 instr->src = instr->dest + num_dests;
255
256 list_inithead(&instr->phi_srcs);
257
258 instr->index = func->next_instr++;
259
260 return instr;
261 }
262
263 /**
264 * \brief Allocates and sets up a PCO instruction group.
265 *
266 * \param[in,out] func Parent function.
267 * \return The PCO instruction group, or NULL on failure.
268 */
pco_igrp_create(pco_func * func)269 pco_igrp *pco_igrp_create(pco_func *func)
270 {
271 pco_igrp *igrp = rzalloc_size(func, sizeof(*igrp));
272
273 igrp->parent_func = func;
274 igrp->index = func->next_igrp++;
275
276 return igrp;
277 }
278
279 /**
280 * \brief Deletes a PCO instruction.
281 *
282 * \param[in,out] instr PCO instruction.
283 */
pco_instr_delete(pco_instr * instr)284 void pco_instr_delete(pco_instr *instr)
285 {
286 list_del(&instr->link);
287 ralloc_free(instr);
288 }
289
290 /**
291 * \brief Returns the shader data.
292 *
293 * \param[in] shader PCO shader.
294 */
pco_shader_data(pco_shader * shader)295 pco_data *pco_shader_data(pco_shader *shader)
296 {
297 return &shader->data;
298 }
299