Bug Summary

File:root/firefox-clang/third_party/rust/glslopt/glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.cpp
Warning:line 1934, column 76
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ir_print_glsl_visitor.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/third_party/rust/glslopt -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/root/firefox-clang/third_party/rust/glslopt -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I glsl-optimizer/include -I glsl-optimizer/src/mesa -I glsl-optimizer/src/mapi -I glsl-optimizer/src/compiler -I glsl-optimizer/src/compiler/glsl -I glsl-optimizer/src/gallium/auxiliary -I glsl-optimizer/src/gallium/include -I glsl-optimizer/src -I glsl-optimizer/src/util -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -D MOZILLA_CONFIG_H -D __STDC_FORMAT_MACROS -D _GNU_SOURCE -D HAVE_ENDIAN_H -D HAVE_PTHREAD -D HAVE_TIMESPEC_GET -D MOZ_INCLUDE_MOZALLOC_H -D mozilla_throw_gcc_h -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c++ glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.cpp
1/*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "ir_print_glsl_visitor.h"
25#include "ir_visitor.h"
26#include "glsl_types.h"
27#include "glsl_parser_extras.h"
28#include "ir_unused_structs.h"
29#include "loop_analysis.h"
30#include "util/hash_table.h"
31#include <math.h>
32#include <limits>
33
34
35static void print_type(string_buffer& buffer, const glsl_type *t, bool arraySize);
36static void print_type_post(string_buffer& buffer, const glsl_type *t, bool arraySize);
37
38// FIXME: precision
39static inline const char* get_precision_string (unsigned p)
40{
41 switch (p) {
42 case GLSL_PRECISION_HIGH:
43 return "highp ";
44 case GLSL_PRECISION_MEDIUM:
45 return "mediump ";
46 case GLSL_PRECISION_LOW:
47 return "lowp ";
48 case GLSL_PRECISION_NONE:
49 return "";
50 }
51 assert(!"Should not get here.")(static_cast <bool> (!"Should not get here.") ? void (0
) : __assert_fail ("!\"Should not get here.\"", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
52 return "";
53}
54
55static const int tex_sampler_type_count = 7;
56// [glsl_sampler_dim]
57static const char* tex_sampler_dim_name[tex_sampler_type_count] = {
58 "1D", "2D", "3D", "Cube", "Rect", "Buf", "2D", /* samplerExternal uses texture2D */
59};
60static int tex_sampler_dim_size[tex_sampler_type_count] = {
61 1, 2, 3, 3, 2, 2, 2,
62};
63
64struct ga_entry : public exec_node
65{
66 ga_entry(ir_instruction* ir)
67 {
68 assert(ir)(static_cast <bool> (ir) ? void (0) : __assert_fail ("ir"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
69 this->ir = ir;
70 }
71 ir_instruction* ir;
72};
73
74
75struct global_print_tracker {
76 global_print_tracker () {
77 mem_ctx = ralloc_context(0);
78 var_counter = 0;
79 var_hash = _mesa_hash_table_create(nullptr, _mesa_hash_pointer, _mesa_key_pointer_equal);
80 main_function_done = false;
81 }
82
83 ~global_print_tracker() {
84 _mesa_hash_table_destroy (var_hash, nullptr);
85 ralloc_free(mem_ctx);
86 }
87
88 unsigned var_counter;
89 hash_table* var_hash;
90 exec_list global_assignements;
91 void* mem_ctx;
92 bool main_function_done;
93};
94
95class ir_print_glsl_visitor : public ir_visitor {
96public:
97 ir_print_glsl_visitor(string_buffer& buf, global_print_tracker* globals_, PrintGlslMode mode_, bool use_precision_, const _mesa_glsl_parse_state* state_)
98 : buffer(buf)
99 , loopstate(NULL__null)
100 , inside_loop_body(false)
101 , skipped_this_ir(false)
102 , previous_skipped(false)
103 , uses_texlod_impl(0)
104 , uses_texlodproj_impl(0)
105 {
106 indentation = 0;
107 expression_depth = 0;
108 globals = globals_;
109 mode = mode_;
110 use_precision = use_precision_;
111 state = state_;
112 }
113
114 virtual ~ir_print_glsl_visitor()
115 {
116 }
117
118
119 void indent(void);
120 void newline_indent();
121 void end_statement_line();
122 void newline_deindent();
123 void print_var_name (ir_variable* v);
124 void print_precision (ir_instruction* ir, const glsl_type* type);
125
126 virtual void visit(ir_variable *);
127 virtual void visit(ir_function_signature *);
128 virtual void visit(ir_function *);
129 virtual void visit(ir_expression *);
130 virtual void visit(ir_texture *);
131 virtual void visit(ir_swizzle *);
132 virtual void visit(ir_dereference_variable *);
133 virtual void visit(ir_dereference_array *);
134 virtual void visit(ir_dereference_record *);
135 virtual void visit(ir_assignment *);
136 virtual void visit(ir_constant *);
137 virtual void visit(ir_call *);
138 virtual void visit(ir_return *);
139 virtual void visit(ir_discard *);
140 virtual void visit(class ir_demote *);
141 virtual void visit(ir_if *);
142 virtual void visit(ir_loop *);
143 virtual void visit(ir_loop_jump *);
144 virtual void visit(ir_precision_statement *);
145 virtual void visit(ir_typedecl_statement *);
146 virtual void visit(ir_emit_vertex *);
147 virtual void visit(ir_end_primitive *);
148 virtual void visit(class ir_barrier *);
149
150 void emit_assignment_part (ir_dereference* lhs, ir_rvalue* rhs, unsigned write_mask, ir_rvalue* dstIndex);
151 bool can_emit_canonical_for (loop_variable_state *ls);
152 bool emit_canonical_for (ir_loop* ir);
153 bool try_print_array_assignment (ir_dereference* lhs, ir_rvalue* rhs);
154
155 int indentation;
156 int expression_depth;
157 string_buffer& buffer;
158 global_print_tracker* globals;
159 const _mesa_glsl_parse_state* state;
160 PrintGlslMode mode;
161 loop_state* loopstate;
162 bool use_precision;
163 bool inside_loop_body;
164 bool skipped_this_ir;
165 bool previous_skipped;
166 int uses_texlod_impl; // 3 bits per tex_dimension, bit set for each precision if any texture sampler needs the GLES2 lod workaround.
167 int uses_texlodproj_impl; // 3 bits per tex_dimension, bit set for each precision if any texture sampler needs the GLES2 lod workaround.
168};
169
170static void print_texlod_workarounds(int usage_bitfield, int usage_proj_bitfield, string_buffer &str)
171{
172 static const char *precStrings[3] = {"lowp", "mediump", "highp"};
173 static const char *precNameStrings[3] = { "low_", "medium_", "high_" };
174 // Print out the texlod workarounds
175 for (int prec = 0; prec < 3; prec++)
176 {
177 const char *precString = precStrings[prec];
178 const char *precName = precNameStrings[prec];
179
180 for (int dim = 0; dim < tex_sampler_type_count; dim++)
181 {
182 int mask = 1 << (dim + (prec * 8));
183 if (usage_bitfield & mask)
184 {
185 str.asprintf_append("%s vec4 impl_%stexture%sLodEXT(%s sampler%s sampler, highp vec%d coord, mediump float lod)\n", precString, precName, tex_sampler_dim_name[dim], precString, tex_sampler_dim_name[dim], tex_sampler_dim_size[dim]);
186 str.asprintf_append("{\n");
187 str.asprintf_append("#if defined(GL_EXT_shader_texture_lod)\n");
188 str.asprintf_append("\treturn texture%sLodEXT(sampler, coord, lod);\n", tex_sampler_dim_name[dim]);
189 str.asprintf_append("#else\n");
190 str.asprintf_append("\treturn texture%s(sampler, coord, lod);\n", tex_sampler_dim_name[dim]);
191 str.asprintf_append("#endif\n");
192 str.asprintf_append("}\n\n");
193 }
194 if (usage_proj_bitfield & mask)
195 {
196 // 2D projected read also has a vec4 UV variant
197 if (dim == GLSL_SAMPLER_DIM_2D)
198 {
199 str.asprintf_append("%s vec4 impl_%stexture2DProjLodEXT(%s sampler2D sampler, highp vec4 coord, mediump float lod)\n", precString, precName, precString);
200 str.asprintf_append("{\n");
201 str.asprintf_append("#if defined(GL_EXT_shader_texture_lod)\n");
202 str.asprintf_append("\treturn texture%sProjLodEXT(sampler, coord, lod);\n", tex_sampler_dim_name[dim]);
203 str.asprintf_append("#else\n");
204 str.asprintf_append("\treturn texture%sProj(sampler, coord, lod);\n", tex_sampler_dim_name[dim]);
205 str.asprintf_append("#endif\n");
206 str.asprintf_append("}\n\n");
207 }
208 str.asprintf_append("%s vec4 impl_%stexture%sProjLodEXT(%s sampler%s sampler, highp vec%d coord, mediump float lod)\n", precString, precName, tex_sampler_dim_name[dim], precString, tex_sampler_dim_name[dim], tex_sampler_dim_size[dim] + 1);
209 str.asprintf_append("{\n");
210 str.asprintf_append("#if defined(GL_EXT_shader_texture_lod)\n");
211 str.asprintf_append("\treturn texture%sProjLodEXT(sampler, coord, lod);\n", tex_sampler_dim_name[dim]);
212 str.asprintf_append("#else\n");
213 str.asprintf_append("\treturn texture%sProj(sampler, coord, lod);\n", tex_sampler_dim_name[dim]);
214 str.asprintf_append("#endif\n");
215 str.asprintf_append("}\n\n");
216 }
217 }
218 }
219}
220
221
222char*
223_mesa_print_ir_glsl(exec_list *instructions,
224 struct _mesa_glsl_parse_state *state,
225 char* buffer, PrintGlslMode mode)
226{
227 string_buffer str(buffer);
228 string_buffer body(buffer);
229
230 // print version & extensions
231 if (state) {
232 if (state->had_version_string)
233 {
234 str.asprintf_append ("#version %i", state->language_version);
235 if (state->es_shader && state->language_version >= 300)
236 str.asprintf_append (" es");
237 str.asprintf_append ("\n");
238 }
239 if (state->ARB_shader_texture_lod_enable)
240 str.asprintf_append ("#extension GL_ARB_shader_texture_lod : enable\n");
241 if (state->ARB_draw_instanced_enable)
242 str.asprintf_append ("#extension GL_ARB_draw_instanced : enable\n");
243 if (state->ARB_explicit_attrib_location_enable)
244 str.asprintf_append ("#extension GL_ARB_explicit_attrib_location : enable\n");
245 if (state->EXT_gpu_shader4_enable)
246 str.asprintf_append ("#extension GL_EXT_gpu_shader4 : enable\n");
247 // FIXME
248 // if (state->EXT_shader_texture_lod_enable)
249 // str.asprintf_append ("#extension GL_EXT_shader_texture_lod : enable\n");
250 if (state->OES_standard_derivatives_enable)
251 str.asprintf_append ("#extension GL_OES_standard_derivatives : enable\n");
252 // FIXME
253 // if (state->EXT_shadow_samplers_enable)
254 // str.asprintf_append ("#extension GL_EXT_shadow_samplers : enable\n");
255 if (state->EXT_frag_depth_enable)
256 str.asprintf_append ("#extension GL_EXT_frag_depth : enable\n");
257 if (state->es_shader && state->language_version < 300)
258 {
259 if (state->EXT_draw_buffers_enable)
260 str.asprintf_append ("#extension GL_EXT_draw_buffers : enable\n");
261 // FIXME
262 // if (state->EXT_draw_instanced_enable)
263 // str.asprintf_append ("#extension GL_EXT_draw_instanced : enable\n");
264 }
265 if (state->EXT_shader_framebuffer_fetch_enable)
266 str.asprintf_append ("#extension GL_EXT_shader_framebuffer_fetch : enable\n");
267 if (state->ARB_shader_bit_encoding_enable)
268 str.asprintf_append("#extension GL_ARB_shader_bit_encoding : enable\n");
269 if (state->EXT_texture_array_enable)
270 str.asprintf_append ("#extension GL_EXT_texture_array : enable\n");
271 if (state->KHR_blend_equation_advanced_enable)
272 str.asprintf_append ("#extension GL_KHR_blend_equation_advanced : enable\n");
273 if (state->EXT_blend_func_extended_enable)
274 str.asprintf_append ("#extension GL_EXT_blend_func_extended : enable\n");
275 if (state->OES_EGL_image_external_enable)
276 str.asprintf_append ("#extension GL_OES_EGL_image_external : enable\n");
277 if (state->OES_EGL_image_external_essl3_enable)
278 str.asprintf_append ("#extension GL_OES_EGL_image_external_essl3 : enable\n");
279 if (state->ARB_shader_storage_buffer_object_enable)
280 str.asprintf_append ("#extension GL_ARB_shader_storage_buffer_object : enable\n");
281
282
283 // TODO: support other blend specifiers besides "all"
284 if (state->fs_blend_support == BLEND_ALL)
285 str.asprintf_append ("layout(blend_support_all_equations) out;\n");
286 }
287
288 // remove unused struct declarations
289 do_remove_unused_typedecls(instructions);
290
291 global_print_tracker gtracker;
292 int uses_texlod_impl = 0;
293 int uses_texlodproj_impl = 0;
294
295 loop_state* ls = analyze_loop_variables(instructions);
296 // FIXME: set_loop_controls has been merged in to unroll_loops
297 // if (ls->loop_found)
298 // set_loop_controls(instructions, ls);
299
300 foreach_in_list(ir_instruction, ir, instructions)for (ir_instruction *ir = (!exec_node_is_tail_sentinel((instructions
)->head_sentinel.next) ? (ir_instruction *) ((instructions
)->head_sentinel.next) : __null); (ir) != __null; (ir) = (
!exec_node_is_tail_sentinel((ir)->next) ? (ir_instruction *
) ((ir)->next) : __null))
301 {
302 if (ir->ir_type == ir_type_variable) {
303 ir_variable *var = static_cast<ir_variable*>(ir);
304 if ((strstr(var->name, "gl_") == var->name)
305 && !var->data.invariant)
306 continue;
307 }
308
309 ir_print_glsl_visitor v (body, &gtracker, mode, state->es_shader, state);
310 v.loopstate = ls;
311
312 ir->accept(&v);
313 if (ir->ir_type != ir_type_function && !v.skipped_this_ir)
314 body.asprintf_append (";\n");
315
316 uses_texlod_impl |= v.uses_texlod_impl;
317 uses_texlodproj_impl |= v.uses_texlodproj_impl;
318 }
319
320 delete ls;
321
322 print_texlod_workarounds(uses_texlod_impl, uses_texlodproj_impl, str);
323
324 // Add the optimized glsl code
325 str.asprintf_append("%s", body.c_str());
326
327 return ralloc_strdup(buffer, str.c_str());
328}
329
330
331void ir_print_glsl_visitor::indent(void)
332{
333 if (previous_skipped)
334 return;
335 previous_skipped = false;
336 for (int i = 0; i < indentation; i++)
337 buffer.asprintf_append (" ");
338}
339
340void ir_print_glsl_visitor::end_statement_line()
341{
342 if (!skipped_this_ir)
343 buffer.asprintf_append(";\n");
344 previous_skipped = skipped_this_ir;
345 skipped_this_ir = false;
346}
347
348void ir_print_glsl_visitor::newline_indent()
349{
350 if (expression_depth % 4 == 0)
351 {
352 ++indentation;
353 buffer.asprintf_append ("\n");
354 indent();
355 }
356}
357void ir_print_glsl_visitor::newline_deindent()
358{
359 if (expression_depth % 4 == 0)
360 {
361 --indentation;
362 buffer.asprintf_append ("\n");
363 indent();
364 }
365}
366
367
368void ir_print_glsl_visitor::print_var_name (ir_variable* v)
369{
370 long id = 0;
371 const hash_entry *entry = _mesa_hash_table_search(globals->var_hash, v);
372 if (entry)
373 {
374 id = (long)entry->data;
375 }
376 else if (v->data.mode == ir_var_temporary)
377 {
378 id = ++globals->var_counter;
379 _mesa_hash_table_insert (globals->var_hash, v, (void*)id);
380 }
381 if (id)
382 {
383 if (v->data.mode == ir_var_temporary)
384 buffer.asprintf_append ("tmpvar_%d", (int)id);
385 else
386 buffer.asprintf_append ("%s_%d", v->name, (int)id);
387 }
388 else
389 {
390 buffer.asprintf_append ("%s", v->name);
391 }
392}
393
394void ir_print_glsl_visitor::print_precision (ir_instruction* ir, const glsl_type* type)
395{
396 if (!this->use_precision)
397 return;
398 if (type &&
399 !type->is_float() &&
400 !type->is_sampler() &&
401 !type->is_integer() &&
402 (!type->is_array() || !type->without_array()->is_float()) &&
403 (!type->is_array() || !type->without_array()->is_integer())
404 )
405 {
406 return;
407 }
408
409 ir_variable* var = ir->as_variable();
410 if (var) {
411 buffer.asprintf_append ("%s", get_precision_string(var->data.precision));
412 }
413
414 // FIXME
415 // glsl_precision prec = precision_from_ir(ir);
416
417 // // In fragment shader, default float precision is undefined.
418 // // We must thus always print it, when there was no default precision
419 // // and for whatever reason our type ended up having undefined precision.
420 // if (prec == glsl_precision_undefined &&
421 // type && type->is_float() &&
422 // this->state->stage == MESA_SHADER_FRAGMENT &&
423 // !this->state->had_float_precision)
424 // {
425 // prec = glsl_precision_high;
426 // }
427 // if (type && type->is_integer())
428 // {
429 // if (prec == glsl_precision_undefined && type && type->is_integer())
430 // {
431 // // Default to highp on integers
432 // prec = glsl_precision_high;
433 // }
434 // }
435
436 // // skip precision for samplers that end up being lowp (default anyway) or undefined;
437 // // except always emit it for shadowmap samplers (some drivers don't implement
438 // // default EXT_shadow_samplers precision) and 3D textures (they always require precision)
439 // if (type && type->is_sampler() && !type->sampler_shadow && !(type->sampler_dimensionality > GLSL_SAMPLER_DIM_2D))
440 // {
441 // if (prec == glsl_precision_low || prec == glsl_precision_undefined)
442 // return;
443 // }
444
445 // if (prec == glsl_precision_high || prec == glsl_precision_undefined)
446 // {
447 // if (ir->ir_type == ir_type_function_signature)
448 // return;
449 // }
450 // buffer.asprintf_append ("%s", get_precision_string(prec));
451}
452
453
454static void print_type(string_buffer& buffer, const glsl_type *t, bool arraySize)
455{
456 if (t->base_type == GLSL_TYPE_ARRAY) {
457 print_type(buffer, t->fields.array, true);
458 if (arraySize)
459 buffer.asprintf_append ("[%u]", t->length);
460 } else if ((t->base_type == GLSL_TYPE_STRUCT)
461 && (strncmp("gl_", t->name, 3) != 0)) {
462 buffer.asprintf_append ("%s", t->name);
463 } else {
464 buffer.asprintf_append ("%s", t->name);
465 }
466}
467
468static void print_type_post(string_buffer& buffer, const glsl_type *t, bool arraySize)
469{
470 if (t->base_type == GLSL_TYPE_ARRAY) {
471 if (!arraySize) {
472 if (t->length) {
473 buffer.asprintf_append ("[%u]", t->length);
474 } else {
475 buffer.asprintf_append ("[]");
476 }
477 }
478 }
479}
480
481
482void ir_print_glsl_visitor::visit(ir_variable *ir)
483{
484 // Variables that are declared as or part of interface blocks will be printed by the block declaration.
485 if (ir->is_in_buffer_block()) {
486 skipped_this_ir = true;
487 return;
488 }
489
490 const char *const cent = (ir->data.centroid) ? "centroid " : "";
491 const char *const inv = (ir->data.invariant) ? "invariant " : "";
492 const char *const mode[3][ir_var_mode_count] =
493 {
494 { "", "uniform ", "", "", "in ", "out ", "in ", "out ", "inout ", "", "", "" },
495 { "", "uniform ", "", "", "attribute ", "varying ", "in ", "out ", "inout ", "", "", "" },
496 { "", "uniform ", "", "", "varying ", "out ", "in ", "out ", "inout ", "", "", "" },
497 };
498
499 const char *const interp[] = { "", "smooth ", "flat ", "noperspective " };
500
501 bool supports_explicit_location = this->state->language_version >= 300 ||
502 this->state->ARB_explicit_attrib_location_enable;
503 if (supports_explicit_location && ir->data.explicit_location)
504 {
505 const int binding_base = (this->state->stage == MESA_SHADER_VERTEX ? (int)VERT_ATTRIB_GENERIC0 : (int)FRAG_RESULT_DATA0);
506 const int location = ir->data.location - binding_base;
507 if (ir->data.explicit_index) {
508 const int index = ir->data.index;
509 buffer.asprintf_append ("layout(location=%d, index=%d) ", location, index);
510 } else {
511 buffer.asprintf_append ("layout(location=%d) ", location);
512 }
513 }
514
515 int decormode = this->mode;
516 // GLSL 1.30 and up use "in" and "out" for everything
517 if (this->state->language_version >= 130)
518 {
519 decormode = 0;
520 }
521
522 // give an id to any variable defined in a function that is not an uniform
523 if ((this->mode == kPrintGlslNone && ir->data.mode != ir_var_uniform))
524 {
525 const hash_entry *entry = _mesa_hash_table_search (globals->var_hash, ir);
526 if (!entry)
527 {
528 long id = ++globals->var_counter;
529 _mesa_hash_table_insert (globals->var_hash, ir, (void*)id);
530 }
531 }
532
533 // if this is a loop induction variable, do not print it
534 // (will be printed inside loop body)
535 if (!inside_loop_body)
536 {
537 // FIXME
538 // loop_variable_state* inductor_state = loopstate->get_for_inductor(ir);
539 // if (inductor_state && inductor_state->private_induction_variable_count == 1 &&
540 // can_emit_canonical_for(inductor_state))
541 // {
542 // skipped_this_ir = true;
543 // return;
544 // }
545 }
546
547 // keep invariant declaration for builtin variables
548 if (strstr(ir->name, "gl_") == ir->name) {
549 buffer.asprintf_append ("%s", inv);
550 print_var_name (ir);
551 return;
552 }
553
554 buffer.asprintf_append ("%s%s%s%s",
555 cent, inv, interp[ir->data.interpolation], mode[decormode][ir->data.mode]);
556 print_precision (ir, ir->type);
557 print_type(buffer, ir->type, false);
558 buffer.asprintf_append (" ");
559 print_var_name (ir);
560 print_type_post(buffer, ir->type, false);
561
562 // FIXME: inout is a metal thing?
563 if (ir->constant_value &&
564 ir->data.mode != ir_var_shader_in &&
565 ir->data.mode != ir_var_shader_out &&
566 // ir->data.mode != ir_var_shader_inout &&
567 ir->data.mode != ir_var_function_in &&
568 ir->data.mode != ir_var_function_out) // &&
569 // ir->data.mode != ir_var_function_inout)
570 {
571 buffer.asprintf_append (" = ");
572 visit (ir->constant_value);
573 }
574}
575
576
577void ir_print_glsl_visitor::visit(ir_function_signature *ir)
578{
579 print_precision (ir, ir->return_type);
580 print_type(buffer, ir->return_type, true);
581 buffer.asprintf_append (" %s (", ir->function_name());
582
583 if (!ir->parameters.is_empty())
584 {
585 buffer.asprintf_append ("\n");
586
587 indentation++; previous_skipped = false;
588 bool first = true;
589 foreach_in_list(ir_variable, inst, &ir->parameters)for (ir_variable *inst = (!exec_node_is_tail_sentinel((&ir
->parameters)->head_sentinel.next) ? (ir_variable *) ((
&ir->parameters)->head_sentinel.next) : __null); (inst
) != __null; (inst) = (!exec_node_is_tail_sentinel((inst)->
next) ? (ir_variable *) ((inst)->next) : __null))
{
590 if (!first)
591 buffer.asprintf_append (",\n");
592 indent();
593 inst->accept(this);
594 first = false;
595 }
596 indentation--;
597
598 buffer.asprintf_append ("\n");
599 indent();
600 }
601
602 if (ir->body.is_empty())
603 {
604 buffer.asprintf_append (");\n");
605 return;
606 }
607
608 buffer.asprintf_append (")\n");
609
610 indent();
611 buffer.asprintf_append ("{\n");
612 indentation++; previous_skipped = false;
613
614 // insert postponed global assigments
615 if (strcmp(ir->function()->name, "main") == 0)
616 {
617 assert (!globals->main_function_done)(static_cast <bool> (!globals->main_function_done) ?
void (0) : __assert_fail ("!globals->main_function_done",
__builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
618 globals->main_function_done = true;
619 foreach_in_list(ga_entry, node, &globals->global_assignements)for (ga_entry *node = (!exec_node_is_tail_sentinel((&globals
->global_assignements)->head_sentinel.next) ? (ga_entry
*) ((&globals->global_assignements)->head_sentinel
.next) : __null); (node) != __null; (node) = (!exec_node_is_tail_sentinel
((node)->next) ? (ga_entry *) ((node)->next) : __null))
620 {
621 ir_instruction* as = node->ir;
622 as->accept(this);
623 buffer.asprintf_append(";\n");
624 }
625 }
626
627 foreach_in_list(ir_instruction, inst, &ir->body)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((&
ir->body)->head_sentinel.next) ? (ir_instruction *) ((&
ir->body)->head_sentinel.next) : __null); (inst) != __null
; (inst) = (!exec_node_is_tail_sentinel((inst)->next) ? (ir_instruction
*) ((inst)->next) : __null))
{
628 indent();
629 inst->accept(this);
630 end_statement_line();
631 }
632 indentation--;
633 indent();
634 buffer.asprintf_append ("}\n");
635}
636
637void ir_print_glsl_visitor::visit(ir_function *ir)
638{
639 bool found_non_builtin_proto = false;
640
641 foreach_in_list(ir_function_signature, sig, &ir->signatures)for (ir_function_signature *sig = (!exec_node_is_tail_sentinel
((&ir->signatures)->head_sentinel.next) ? (ir_function_signature
*) ((&ir->signatures)->head_sentinel.next) : __null
); (sig) != __null; (sig) = (!exec_node_is_tail_sentinel((sig
)->next) ? (ir_function_signature *) ((sig)->next) : __null
))
{
642 if (!sig->is_builtin())
643 found_non_builtin_proto = true;
644 }
645 if (!found_non_builtin_proto)
646 return;
647
648 PrintGlslMode oldMode = this->mode;
649 this->mode = kPrintGlslNone;
650
651 foreach_in_list(ir_function_signature, sig, &ir->signatures)for (ir_function_signature *sig = (!exec_node_is_tail_sentinel
((&ir->signatures)->head_sentinel.next) ? (ir_function_signature
*) ((&ir->signatures)->head_sentinel.next) : __null
); (sig) != __null; (sig) = (!exec_node_is_tail_sentinel((sig
)->next) ? (ir_function_signature *) ((sig)->next) : __null
))
{
652 indent();
653 sig->accept(this);
654 buffer.asprintf_append ("\n");
655 }
656
657 this->mode = oldMode;
658
659 indent();
660}
661
662static const char* operator_glsl_str(ir_expression_operation op, const glsl_type* type) {
663 switch (op) {
664 case ir_unop_bit_not:
665 return "~";
666 case ir_unop_logic_not:
667 return "!";
668 case ir_unop_neg:
669 return "-";
670 case ir_unop_abs:
671 return "abs";
672 case ir_unop_sign:
673 return "sign";
674 case ir_unop_rsq:
675 return "inversesqrt";
676 case ir_unop_sqrt:
677 return "sqrt";
678 case ir_unop_exp:
679 return "exp";
680 case ir_unop_log:
681 return "log";
682 case ir_unop_exp2:
683 return "exp2";
684 case ir_unop_log2:
685 return "log2";
686 case ir_unop_trunc:
687 return "trunc";
688 case ir_unop_ceil:
689 return "ceil";
690 case ir_unop_floor:
691 return "floor";
692 case ir_unop_fract:
693 return "fract";
694 case ir_unop_round_even:
695 return "roundEven";
696 case ir_unop_sin:
697 return "sin";
698 case ir_unop_cos:
699 return "cos";
700 case ir_unop_atan:
701 return "atan";
702 case ir_unop_dFdx:
703 return "dFdx";
704 case ir_unop_dFdx_coarse:
705 return "dFdxCoarse";
706 case ir_unop_dFdx_fine:
707 return "dFdxFine";
708 case ir_unop_dFdy:
709 return "dFdy";
710 case ir_unop_dFdy_coarse:
711 return "dFdyCoarse";
712 case ir_unop_dFdy_fine:
713 return "dFdyFine";
714 case ir_unop_pack_snorm_2x16:
715 return "packSnorm2x16";
716 case ir_unop_pack_snorm_4x8:
717 return "packSnorm4x8";
718 case ir_unop_pack_unorm_2x16:
719 return "packUnorm2x16";
720 case ir_unop_pack_unorm_4x8:
721 return "packUnorm4x8";
722 case ir_unop_pack_half_2x16:
723 return "packHalf2x16";
724 case ir_unop_unpack_snorm_2x16:
725 return "unpackSnorm2x16";
726 case ir_unop_unpack_snorm_4x8:
727 return "unpackSnorm4x8";
728 case ir_unop_unpack_unorm_2x16:
729 return "unpackUnorm2x16";
730 case ir_unop_unpack_unorm_4x8:
731 return "unpackUnorm4x8";
732 case ir_unop_unpack_half_2x16:
733 return "unpackHalf2x16";
734 case ir_unop_bitfield_reverse:
735 return "bitfieldReverse";
736 case ir_unop_bit_count:
737 return "bitCount";
738 case ir_unop_find_msb:
739 return "findMSB";
740 case ir_unop_find_lsb:
741 return "findLSB";
742 case ir_unop_saturate:
743 return "saturate";
744 case ir_unop_pack_double_2x32:
745 return "packDouble2x32";
746 case ir_unop_unpack_double_2x32:
747 return "unpackDouble2x32";
748 case ir_unop_pack_sampler_2x32:
749 return "packSampler2x32";
750 case ir_unop_pack_image_2x32:
751 return "packImage2x32";
752 case ir_unop_unpack_sampler_2x32:
753 return "unpackSampler2x32";
754 case ir_unop_unpack_image_2x32:
755 return "unpackImage2x32";
756 case ir_unop_interpolate_at_centroid:
757 return "interpolateAtCentroid";
758 case ir_unop_pack_int_2x32:
759 return "packInt2x32";
760 case ir_unop_pack_uint_2x32:
761 return "packUint2x32";
762 case ir_unop_unpack_int_2x32:
763 return "unpackInt2x32";
764 case ir_unop_unpack_uint_2x32:
765 return "unpackUint2x32";
766 case ir_binop_add:
767 return "+";
768 case ir_binop_sub:
769 return "-";
770 case ir_binop_mul:
771 return "*";
772 case ir_binop_div:
773 return "/";
774 case ir_binop_mod:
775 if (type->is_integer())
776 return "%";
777 else
778 return "mod";
779 case ir_binop_less:
780 if (type->is_vector())
781 return "lessThan";
782 else
783 return "<";
784 case ir_binop_gequal:
785 if (type->is_vector())
786 return "greaterThanEqual";
787 else
788 return ">=";
789 case ir_binop_equal:
790 if (type->is_vector())
791 return "equal";
792 else
793 return "==";
794 case ir_binop_nequal:
795 if (type->is_vector())
796 return "notEqual";
797 else
798 return "!=";
799 case ir_binop_all_equal:
800 return "==";
801 case ir_binop_any_nequal:
802 return "!=";
803 case ir_binop_lshift:
804 return "<<";
805 case ir_binop_rshift:
806 return ">>";
807 case ir_binop_bit_and:
808 return "&";
809 case ir_binop_bit_xor:
810 return "^";
811 case ir_binop_bit_or:
812 return "|";
813 case ir_binop_logic_and:
814 return "&&";
815 case ir_binop_logic_xor:
816 return "^^";
817 case ir_binop_logic_or:
818 return "||";
819 case ir_binop_dot:
820 return "dot";
821 case ir_binop_min:
822 return "min";
823 case ir_binop_max:
824 return "max";
825 case ir_binop_pow:
826 return "pow";
827 case ir_binop_interpolate_at_offset:
828 return "interpolateAtOffset";
829 case ir_binop_interpolate_at_sample:
830 return "interpolateAtSample";
831 case ir_binop_atan2:
832 return "atan";
833 case ir_triop_fma:
834 return "fma";
835 case ir_triop_lrp:
836 return "mix";
837 default:
838 unreachable("Unexpected operator in operator_glsl_str")do { (static_cast <bool> (!"Unexpected operator in operator_glsl_str"
) ? void (0) : __assert_fail ("!\"Unexpected operator in operator_glsl_str\""
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
)); __builtin_unreachable(); } while (0)
;
839 return "UNIMPLEMENTED";
840 }
841}
842
843static bool is_binop_func_like(ir_expression_operation op, const glsl_type* type)
844{
845 if (op == ir_binop_mod && !type->is_integer()) {
846 return true;
847 } else if ((op >= ir_binop_dot && op <= ir_binop_pow) || op == ir_binop_atan2) {
848 return true;
849 } else if (type->is_vector() && (op >= ir_binop_less && op <= ir_binop_nequal)) {
850 return true;
851 }
852 return false;
853}
854
855void ir_print_glsl_visitor::visit(ir_expression *ir)
856{
857 ++this->expression_depth;
858 newline_indent();
859
860 if (ir->num_operands == 1) {
861 if (ir->operation >= ir_unop_f2i && ir->operation <= ir_unop_u2i) {
862 print_type(buffer, ir->type, true);
863 buffer.asprintf_append ("(");
864 } else if (ir->operation == ir_unop_rcp) {
865 buffer.asprintf_append ("(1.0/(");
866 } else {
867 buffer.asprintf_append ("%s(", operator_glsl_str(ir->operation, ir->type));
868 }
869 if (ir->operands[0])
870 ir->operands[0]->accept(this);
871 buffer.asprintf_append (")");
872 if (ir->operation == ir_unop_rcp) {
873 buffer.asprintf_append (")");
874 }
875 }
876 else if (ir->operation == ir_triop_csel)
877 {
878 buffer.asprintf_append ("mix(");
879 ir->operands[2]->accept(this);
880 buffer.asprintf_append (", ");
881 ir->operands[1]->accept(this);
882 if (ir->operands[1]->type->is_scalar())
883 buffer.asprintf_append (", bool(");
884 else
885 buffer.asprintf_append (", bvec%d(", ir->operands[1]->type->vector_elements);
886 ir->operands[0]->accept(this);
887 buffer.asprintf_append ("))");
888 }
889 else if (ir->operation == ir_binop_vector_extract)
890 {
891 // a[b]
892
893 if (ir->operands[0])
894 ir->operands[0]->accept(this);
895 buffer.asprintf_append ("[");
896 if (ir->operands[1])
897 ir->operands[1]->accept(this);
898 buffer.asprintf_append ("]");
899 }
900 else if (is_binop_func_like(ir->operation, ir->type))
901 {
902 if (ir->operation == ir_binop_mod)
903 {
904 buffer.asprintf_append ("(");
905 print_type(buffer, ir->type, true);
906 buffer.asprintf_append ("(");
907 }
908 buffer.asprintf_append ("%s (", operator_glsl_str(ir->operation, ir->type));
909
910 if (ir->operands[0])
911 ir->operands[0]->accept(this);
912 buffer.asprintf_append (", ");
913 if (ir->operands[1])
914 ir->operands[1]->accept(this);
915 buffer.asprintf_append (")");
916 if (ir->operation == ir_binop_mod)
917 buffer.asprintf_append ("))");
918 }
919 else if (ir->num_operands == 2)
920 {
921 buffer.asprintf_append ("(");
922 if (ir->operands[0])
923 ir->operands[0]->accept(this);
924
925 buffer.asprintf_append (" %s ", operator_glsl_str(ir->operation, ir->type));
926
927 if (ir->operands[1])
928 ir->operands[1]->accept(this);
929 buffer.asprintf_append (")");
930 }
931 else
932 {
933 // ternary op
934 buffer.asprintf_append ("%s (", operator_glsl_str(ir->operation, ir->type));
935 if (ir->operands[0])
936 ir->operands[0]->accept(this);
937 buffer.asprintf_append (", ");
938 if (ir->operands[1])
939 ir->operands[1]->accept(this);
940 buffer.asprintf_append (", ");
941 if (ir->operands[2])
942 ir->operands[2]->accept(this);
943 buffer.asprintf_append (")");
944 }
945
946 newline_deindent();
947 --this->expression_depth;
948}
949
950void ir_print_glsl_visitor::visit(ir_texture *ir)
951{
952 glsl_sampler_dim sampler_dim = (glsl_sampler_dim)ir->sampler->type->sampler_dimensionality;
953 const bool is_shadow = ir->sampler->type->sampler_shadow;
954 const bool is_array = ir->sampler->type->sampler_array;
955
956 if (ir->op == ir_txs)
957 {
958 buffer.asprintf_append("textureSize (");
959 ir->sampler->accept(this);
960 if (ir_texture::has_lod(ir->sampler->type))
961 {
962 buffer.asprintf_append(", ");
963 ir->lod_info.lod->accept(this);
964 }
965 buffer.asprintf_append(")");
966 return;
967 }
968
969 const glsl_type* uv_type = ir->coordinate->type;
970 const int uv_dim = uv_type->vector_elements;
971 int sampler_uv_dim = tex_sampler_dim_size[sampler_dim];
972 if (is_shadow)
973 sampler_uv_dim += 1;
974 if (is_array)
975 sampler_uv_dim += 1;
976 const bool is_proj = ((ir->op == ir_tex || ir->op == ir_txb || ir->op == ir_txl || ir->op == ir_txd) && uv_dim > sampler_uv_dim);
977 const bool is_lod = (ir->op == ir_txl);
978
979 // FIXME precision/lod
980 // if (is_lod && state->es_shader && state->language_version < 300 && state->stage == MESA_SHADER_FRAGMENT)
981 // {
982 // // Special workaround for GLES 2.0 LOD samplers to prevent a lot of debug spew.
983 // const glsl_precision prec = ir->sampler->get_precision();
984 // const char *precString = "";
985 // // Sampler bitfield is 7 bits, so use 0-7 for lowp, 8-15 for mediump and 16-23 for highp.
986 // int position = (int)sampler_dim;
987 // switch (prec)
988 // {
989 // case glsl_precision_high:
990 // position += 16;
991 // precString = "_high_";
992 // break;
993 // case glsl_precision_medium:
994 // position += 8;
995 // precString = "_medium_";
996 // break;
997 // case glsl_precision_low:
998 // default:
999 // precString = "_low_";
1000 // break;
1001 // }
1002 // buffer.asprintf_append("impl%s", precString);
1003 // if (is_proj)
1004 // uses_texlodproj_impl |= (1 << position);
1005 // else
1006 // uses_texlod_impl |= (1 << position);
1007 // }
1008
1009
1010 // texture function name
1011 //ACS: shadow lookups and lookups with dimensionality included in the name were deprecated in 130
1012 if(state->language_version<130)
1013 {
1014 buffer.asprintf_append ("%s", is_shadow ? "shadow" : "texture");
1015 buffer.asprintf_append ("%s", tex_sampler_dim_name[sampler_dim]);
1016 }
1017 else
1018 {
1019 if (ir->op == ir_txf || ir->op == ir_txf_ms)
1020 buffer.asprintf_append ("texelFetch");
1021 else
1022 buffer.asprintf_append ("texture");
1023 }
1024
1025 if (is_array && state->EXT_texture_array_enable)
1026 buffer.asprintf_append ("Array");
1027
1028 if (is_proj)
1029 buffer.asprintf_append ("Proj");
1030 if (ir->op == ir_txl)
1031 buffer.asprintf_append ("Lod");
1032 if (ir->op == ir_txd)
1033 buffer.asprintf_append ("Grad");
1034 if (ir->offset != NULL__null)
1035 buffer.asprintf_append ("Offset");
1036
1037 if (state->es_shader)
1038 {
1039 // FIXME extension
1040 // if ( (is_shadow && state->EXT_shadow_samplers_enable) ||
1041 // (ir->op == ir_txl && state->EXT_shader_texture_lod_enable) )
1042 // {
1043 // buffer.asprintf_append ("EXT");
1044 // }
1045 }
1046
1047 if(ir->op == ir_txd)
1048 {
1049 // FIXME extension
1050 // if(state->es_shader && state->EXT_shader_texture_lod_enable)
1051 // buffer.asprintf_append ("EXT");
1052 // else if(!state->es_shader && state->ARB_shader_texture_lod_enable)
1053 // buffer.asprintf_append ("ARB");
1054 }
1055
1056 buffer.asprintf_append (" (");
1057
1058 // sampler
1059 ir->sampler->accept(this);
1060 buffer.asprintf_append (", ");
1061
1062 // texture coordinate
1063 ir->coordinate->accept(this);
1064
1065 // lod
1066 if (ir->op == ir_txl || ir->op == ir_txf)
1067 {
1068 buffer.asprintf_append (", ");
1069 ir->lod_info.lod->accept(this);
1070 }
1071
1072 // sample index
1073 if (ir->op == ir_txf_ms)
1074 {
1075 buffer.asprintf_append (", ");
1076 ir->lod_info.sample_index->accept(this);
1077 }
1078
1079 // grad
1080 if (ir->op == ir_txd)
1081 {
1082 buffer.asprintf_append (", ");
1083 ir->lod_info.grad.dPdx->accept(this);
1084 buffer.asprintf_append (", ");
1085 ir->lod_info.grad.dPdy->accept(this);
1086 }
1087
1088 // texel offset
1089 if (ir->offset != NULL__null)
1090 {
1091 buffer.asprintf_append (", ");
1092 ir->offset->accept(this);
1093 }
1094
1095 // lod bias
1096 if (ir->op == ir_txb)
1097 {
1098 buffer.asprintf_append (", ");
1099 ir->lod_info.bias->accept(this);
1100 }
1101
1102 /*
1103
1104
1105 if (ir->op != ir_txf) {
1106 if (ir->projector)
1107 ir->projector->accept(this);
1108 else
1109 buffer.asprintf_append ("1");
1110
1111 if (ir->shadow_comparitor) {
1112 buffer.asprintf_append (" ");
1113 ir->shadow_comparitor->accept(this);
1114 } else {
1115 buffer.asprintf_append (" ()");
1116 }
1117 }
1118
1119 buffer.asprintf_append (" ");
1120 switch (ir->op)
1121 {
1122 case ir_tex:
1123 break;
1124 case ir_txb:
1125 ir->lod_info.bias->accept(this);
1126 break;
1127 case ir_txl:
1128 case ir_txf:
1129 ir->lod_info.lod->accept(this);
1130 break;
1131 case ir_txd:
1132 buffer.asprintf_append ("(");
1133 ir->lod_info.grad.dPdx->accept(this);
1134 buffer.asprintf_append (" ");
1135 ir->lod_info.grad.dPdy->accept(this);
1136 buffer.asprintf_append (")");
1137 break;
1138 };
1139 */
1140 buffer.asprintf_append (")");
1141}
1142
1143
1144void ir_print_glsl_visitor::visit(ir_swizzle *ir)
1145{
1146 const unsigned swiz[4] = {
1147 ir->mask.x,
1148 ir->mask.y,
1149 ir->mask.z,
1150 ir->mask.w,
1151 };
1152
1153 if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type || ir->val->type == glsl_type::uint_type)
1154 {
1155 if (ir->mask.num_components != 1)
1156 {
1157 print_type(buffer, ir->type, true);
1158 buffer.asprintf_append ("(");
1159 }
1160 }
1161
1162 ir->val->accept(this);
1163
1164 if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type || ir->val->type == glsl_type::uint_type)
1165 {
1166 if (ir->mask.num_components != 1)
1167 {
1168 buffer.asprintf_append (")");
1169 }
1170 return;
1171 }
1172
1173 // Swizzling scalar types is not allowed so just return now.
1174 if (ir->val->type->vector_elements == 1)
1175 return;
1176
1177 buffer.asprintf_append (".");
1178 for (unsigned i = 0; i < ir->mask.num_components; i++) {
1179 buffer.asprintf_append ("%c", "xyzw"[swiz[i]]);
1180 }
1181}
1182
1183
1184void ir_print_glsl_visitor::visit(ir_dereference_variable *ir)
1185{
1186 ir_variable *var = ir->variable_referenced();
1187 print_var_name (var);
1188}
1189
1190
1191void ir_print_glsl_visitor::visit(ir_dereference_array *ir)
1192{
1193 ir->array->accept(this);
1194 buffer.asprintf_append ("[");
1195 ir->array_index->accept(this);
1196 buffer.asprintf_append ("]");
1197}
1198
1199
1200void ir_print_glsl_visitor::visit(ir_dereference_record *ir)
1201{
1202 ir->record->accept(this);
1203 const char *field_name = ir->record->type->fields.structure[ir->field_idx].name;
1204 buffer.asprintf_append (".%s", field_name);
1205}
1206
1207
1208bool ir_print_glsl_visitor::try_print_array_assignment (ir_dereference* lhs, ir_rvalue* rhs)
1209{
1210 if (this->state->language_version >= 120)
1211 return false;
1212 ir_dereference_variable* rhsarr = rhs->as_dereference_variable();
1213 if (rhsarr == NULL__null)
1214 return false;
1215 const glsl_type* lhstype = lhs->type;
1216 const glsl_type* rhstype = rhsarr->type;
1217 if (!lhstype->is_array() || !rhstype->is_array())
1218 return false;
1219 if (lhstype->array_size() != rhstype->array_size())
1220 return false;
1221 if (lhstype->base_type != rhstype->base_type)
1222 return false;
1223
1224 const unsigned size = rhstype->array_size();
1225 for (unsigned i = 0; i < size; i++)
1226 {
1227 lhs->accept(this);
1228 buffer.asprintf_append ("[%d]=", i);
1229 rhs->accept(this);
1230 buffer.asprintf_append ("[%d]", i);
1231 if (i != size-1)
1232 buffer.asprintf_append (";");
1233 }
1234 return true;
1235}
1236
1237void ir_print_glsl_visitor::emit_assignment_part (ir_dereference* lhs, ir_rvalue* rhs, unsigned write_mask, ir_rvalue* dstIndex)
1238{
1239 lhs->accept(this);
1240
1241 if (dstIndex)
1242 {
1243 // if dst index is a constant, then emit a swizzle
1244 ir_constant* dstConst = dstIndex->as_constant();
1245 if (dstConst)
1246 {
1247 const char* comps = "xyzw";
1248 char comp = comps[dstConst->get_int_component(0)];
1249 buffer.asprintf_append (".%c", comp);
1250 }
1251 else
1252 {
1253 buffer.asprintf_append ("[");
1254 dstIndex->accept(this);
1255 buffer.asprintf_append ("]");
1256 }
1257 }
1258
1259 char mask[5];
1260 unsigned j = 0;
1261 const glsl_type* lhsType = lhs->type;
1262 const glsl_type* rhsType = rhs->type;
1263 if (!dstIndex && lhsType->matrix_columns <= 1 && lhsType->vector_elements > 1 && write_mask != (1<<lhsType->vector_elements)-1)
1264 {
1265 for (unsigned i = 0; i < 4; i++) {
1266 if ((write_mask & (1 << i)) != 0) {
1267 mask[j] = "xyzw"[i];
1268 j++;
1269 }
1270 }
1271 lhsType = glsl_type::get_instance(lhsType->base_type, j, 1);
1272 }
1273 mask[j] = '\0';
1274 bool hasWriteMask = false;
1275 if (mask[0])
1276 {
1277 buffer.asprintf_append (".%s", mask);
1278 hasWriteMask = true;
1279 }
1280
1281 buffer.asprintf_append (" = ");
1282
1283 bool typeMismatch = !dstIndex && (lhsType != rhsType);
1284 const bool addSwizzle = hasWriteMask && typeMismatch;
1285 if (typeMismatch)
1286 {
1287 if (!addSwizzle)
1288 print_type(buffer, lhsType, true);
1289 buffer.asprintf_append ("(");
1290 }
1291
1292 rhs->accept(this);
1293
1294 if (typeMismatch)
1295 {
1296 buffer.asprintf_append (")");
1297 if (addSwizzle)
1298 buffer.asprintf_append (".%s", mask);
1299 }
1300}
1301
1302
1303// Try to print (X = X + const) as (X += const), mostly to satisfy
1304// OpenGL ES 2.0 loop syntax restrictions.
1305static bool try_print_increment (ir_print_glsl_visitor* vis, ir_assignment* ir)
1306{
1307 if (ir->condition)
1308 return false;
1309
1310 // Needs to be + on rhs
1311 ir_expression* rhsOp = ir->rhs->as_expression();
1312 if (!rhsOp || rhsOp->operation != ir_binop_add)
1313 return false;
1314
1315 // Needs to write to whole variable
1316 ir_variable* lhsVar = ir->whole_variable_written();
1317 if (lhsVar == NULL__null)
1318 return false;
1319
1320 // Types must match
1321 if (ir->lhs->type != ir->rhs->type)
1322 return false;
1323
1324 // Type must be scalar
1325 if (!ir->lhs->type->is_scalar())
1326 return false;
1327
1328 // rhs0 must be variable deref, same one as lhs
1329 ir_dereference_variable* rhsDeref = rhsOp->operands[0]->as_dereference_variable();
1330 if (rhsDeref == NULL__null)
1331 return false;
1332 if (lhsVar != rhsDeref->var)
1333 return false;
1334
1335 // rhs1 must be a constant
1336 ir_constant* rhsConst = rhsOp->operands[1]->as_constant();
1337 if (!rhsConst)
1338 return false;
1339
1340 // print variable name
1341 ir->lhs->accept (vis);
1342
1343 // print ++ or +=const
1344 if (ir->lhs->type->base_type <= GLSL_TYPE_INT && rhsConst->is_one())
1345 {
1346 vis->buffer.asprintf_append ("++");
1347 }
1348 else
1349 {
1350 vis->buffer.asprintf_append(" += ");
1351 rhsConst->accept (vis);
1352 }
1353
1354 return true;
1355}
1356
1357
1358void ir_print_glsl_visitor::visit(ir_assignment *ir)
1359{
1360 // if this is a loop induction variable initial assignment, and we aren't inside loop body:
1361 // do not print it (will be printed when inside loop body)
1362 if (!inside_loop_body)
1363 {
1364 ir_variable* whole_var = ir->whole_variable_written();
1365 if (!ir->condition && whole_var)
1366 {
1367 // FIXME
1368 // loop_variable_state* inductor_state = loopstate->get_for_inductor(whole_var);
1369 // if (inductor_state && inductor_state->private_induction_variable_count == 1 &&
1370 // can_emit_canonical_for(inductor_state))
1371 // {
1372 // skipped_this_ir = true;
1373 // return;
1374 // }
1375 }
1376 }
1377
1378 // assignments in global scope are postponed to main function
1379 if (this->mode != kPrintGlslNone)
1380 {
1381 // FIXME: This assertion gets tripped when encountering const variable
1382 // initializations which occur after the main() function definition.
1383 // assert (!this->globals->main_function_done);
1384 this->globals->global_assignements.push_tail (new(this->globals->mem_ctx) ga_entry(ir));
1385 buffer.asprintf_append ("//"); // for the ; that will follow (ugly, I know)
1386 return;
1387 }
1388
1389 // if RHS is ir_triop_vector_insert, then we have to do some special dance. If source expression is:
1390 // dst = vector_insert (a, b, idx)
1391 // then emit it like:
1392 // dst = a;
1393 // dst.idx = b;
1394 ir_expression* rhsOp = ir->rhs->as_expression();
1395 if (rhsOp && rhsOp->operation == ir_triop_vector_insert)
1396 {
1397 // skip assignment if lhs and rhs would be the same
1398 bool skip_assign = false;
1399 ir_dereference_variable* lhsDeref = ir->lhs->as_dereference_variable();
1400 ir_dereference_variable* rhsDeref = rhsOp->operands[0]->as_dereference_variable();
1401 if (lhsDeref && rhsDeref)
1402 {
1403 if (lhsDeref->var == rhsDeref->var)
1404 skip_assign = true;
1405 }
1406
1407 if (!skip_assign)
1408 {
1409 emit_assignment_part(ir->lhs, rhsOp->operands[0], ir->write_mask, NULL__null);
1410 buffer.asprintf_append ("; ");
1411 }
1412 emit_assignment_part(ir->lhs, rhsOp->operands[1], ir->write_mask, rhsOp->operands[2]);
1413 return;
1414 }
1415
1416 if (try_print_increment (this, ir))
1417 return;
1418
1419 if (try_print_array_assignment (ir->lhs, ir->rhs))
1420 return;
1421
1422 if (ir->condition)
1423 {
1424 if (ir->condition)
1425 {
1426 buffer.asprintf_append ("if (");
1427 ir->condition->accept(this);
1428 buffer.asprintf_append (") ");
1429 }
1430 }
1431
1432 emit_assignment_part (ir->lhs, ir->rhs, ir->write_mask, NULL__null);
1433}
1434
1435
1436#ifdef _MSC_VER
1437#define isnan(x) _isnan(x)
1438#define isinf(x) (!_finite(x))
1439#endif
1440
1441#define fpcheck(x)(isnan(x) || isinf(x)) (isnan(x) || isinf(x))
1442
1443void print_float (string_buffer& buffer, float f)
1444{
1445 // Kind of roundabout way, but this is to satisfy two things:
1446 // * MSVC and gcc-based compilers differ a bit in how they treat float
1447 // widht/precision specifiers. Want to match for tests.
1448 // * GLSL (early version at least) require floats to have ".0" or
1449 // exponential notation.
1450 char tmp[64];
1451 snprintf(tmp, 64, "%.7g", f);
1452
1453 char* posE = NULL__null;
1454 posE = strchr(tmp, 'e');
1455 if (!posE)
1456 posE = strchr(tmp, 'E');
1457
1458 // snprintf formats infinity as inf.0 or -inf.0, which isn't useful here.
1459 // GLSL has no infinity constant so print an equivalent expression instead.
1460 if (f == std::numeric_limits<float>::infinity())
1461 strcpy(tmp, "(1.0/0.0)");
1462
1463 if (f == -std::numeric_limits<float>::infinity())
1464 strcpy(tmp, "(-1.0/0.0)");
1465
1466 // Do similar thing for NaN
1467 if (isnan(f))
1468 strcpy(tmp, "(0.0/0.0)");
1469
1470 #if _MSC_VER
1471 // While gcc would print something like 1.0e+07, MSVC will print 1.0e+007 -
1472 // only for exponential notation, it seems, will add one extra useless zero. Let's try to remove
1473 // that so compiler output matches.
1474 if (posE != NULL__null)
1475 {
1476 if((posE[1] == '+' || posE[1] == '-') && posE[2] == '0')
1477 {
1478 char* p = posE+2;
1479 while (p[0])
1480 {
1481 p[0] = p[1];
1482 ++p;
1483 }
1484 }
1485 }
1486 #endif
1487
1488 buffer.asprintf_append ("%s", tmp);
1489
1490 // need to append ".0"?
1491 if (!strchr(tmp,'.') && (posE == NULL__null))
1492 buffer.asprintf_append(".0");
1493}
1494
1495void ir_print_glsl_visitor::visit(ir_constant *ir)
1496{
1497 const glsl_type* type = ir->type;
1498
1499 if (type == glsl_type::float_type)
1500 {
1501 if (fpcheck(ir->value.f[0])(isnan(ir->value.f[0]) || isinf(ir->value.f[0])))
1502 {
1503 // Non-printable float. If we have bit conversions, we're fine. otherwise do hand-wavey things in print_float().
1504 if ((state->es_shader && (state->language_version >= 300))
1505 || (state->language_version >= 330)
1506 || (state->ARB_shader_bit_encoding_enable))
1507 {
1508 buffer.asprintf_append("uintBitsToFloat(%uu)", ir->value.u[0]);
1509 return;
1510 }
1511 }
1512
1513 print_float (buffer, ir->value.f[0]);
1514 return;
1515 }
1516 else if (type == glsl_type::int_type)
1517 {
1518 // Need special handling for INT_MIN
1519 if (ir->value.u[0] == 0x80000000)
1520 buffer.asprintf_append("int(0x%X)", ir->value.i[0]);
1521 else
1522 buffer.asprintf_append ("%d", ir->value.i[0]);
1523 return;
1524 }
1525 else if (type == glsl_type::uint_type)
1526 {
1527 // ES 2.0 doesn't support uints, neither does GLSL < 130
1528 if ((state->es_shader && (state->language_version < 300))
1529 || (state->language_version < 130))
1530 buffer.asprintf_append("%u", ir->value.u[0]);
1531 else
1532 {
1533 // Old Adreno drivers try to be smart with '0u' and treat that as 'const int'. Sigh.
1534 if (ir->value.u[0] == 0)
1535 buffer.asprintf_append("uint(0)");
1536 else
1537 buffer.asprintf_append("%uu", ir->value.u[0]);
1538 }
1539 return;
1540 }
1541
1542 const glsl_type *const base_type = ir->type->get_base_type();
1543
1544 print_type(buffer, type, true);
1545 buffer.asprintf_append ("(");
1546
1547 if (ir->type->is_array()) {
1548 for (unsigned i = 0; i < ir->type->length; i++)
1549 {
1550 if (i != 0)
1551 buffer.asprintf_append (", ");
1552 ir->get_array_element(i)->accept(this);
1553 }
1554 } else if (ir->type->is_struct()) {
1555 for (unsigned i = 0; i < ir->type->length; i++) {
1556 if (i > 0)
1557 buffer.asprintf_append (", ");
1558 ir->const_elements[i]->accept(this);
1559 }
1560
1561 }else {
1562 bool first = true;
1563 for (unsigned i = 0; i < ir->type->components(); i++) {
1564 if (!first)
1565 buffer.asprintf_append (", ");
1566 first = false;
1567 switch (base_type->base_type) {
1568 case GLSL_TYPE_UINT:
1569 {
1570 // ES 2.0 doesn't support uints, neither does GLSL < 130
1571 if ((state->es_shader && (state->language_version < 300))
1572 || (state->language_version < 130))
1573 buffer.asprintf_append("%u", ir->value.u[i]);
1574 else
1575 buffer.asprintf_append("%uu", ir->value.u[i]);
1576 break;
1577 }
1578 case GLSL_TYPE_INT:
1579 {
1580 // Need special handling for INT_MIN
1581 if (ir->value.u[i] == 0x80000000)
1582 buffer.asprintf_append("int(0x%X)", ir->value.i[i]);
1583 else
1584 buffer.asprintf_append("%d", ir->value.i[i]);
1585 break;
1586 }
1587 case GLSL_TYPE_FLOAT: print_float(buffer, ir->value.f[i]); break;
1588 case GLSL_TYPE_BOOL: buffer.asprintf_append ("%d", ir->value.b[i]); break;
1589 default: assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1590 }
1591 }
1592 }
1593 buffer.asprintf_append (")");
1594}
1595
1596
1597void
1598ir_print_glsl_visitor::visit(ir_call *ir)
1599{
1600 // calls in global scope are postponed to main function
1601 if (this->mode != kPrintGlslNone)
1602 {
1603 assert (!this->globals->main_function_done)(static_cast <bool> (!this->globals->main_function_done
) ? void (0) : __assert_fail ("!this->globals->main_function_done"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1604 this->globals->global_assignements.push_tail (new(this->globals->mem_ctx) ga_entry(ir));
1605 buffer.asprintf_append ("//"); // for the ; that will follow (ugly, I know)
1606 return;
1607 }
1608
1609 if (ir->return_deref)
1610 {
1611 visit(ir->return_deref);
1612 buffer.asprintf_append (" = ");
1613 }
1614
1615 buffer.asprintf_append ("%s (", ir->callee_name());
1616 bool first = true;
1617 foreach_in_list(ir_instruction, inst, &ir->actual_parameters)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((&
ir->actual_parameters)->head_sentinel.next) ? (ir_instruction
*) ((&ir->actual_parameters)->head_sentinel.next) :
__null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel
((inst)->next) ? (ir_instruction *) ((inst)->next) : __null
))
{
1618 if (!first)
1619 buffer.asprintf_append (", ");
1620 inst->accept(this);
1621 first = false;
1622 }
1623 buffer.asprintf_append (")");
1624}
1625
1626
1627void
1628ir_print_glsl_visitor::visit(ir_return *ir)
1629{
1630 buffer.asprintf_append ("return");
1631
1632 ir_rvalue *const value = ir->get_value();
1633 if (value) {
1634 buffer.asprintf_append (" ");
1635 value->accept(this);
1636 }
1637}
1638
1639
1640void
1641ir_print_glsl_visitor::visit(ir_discard *ir)
1642{
1643 buffer.asprintf_append ("discard");
1644
1645 if (ir->condition != NULL__null) {
1646 buffer.asprintf_append (" TODO ");
1647 ir->condition->accept(this);
1648 }
1649}
1650
1651void
1652ir_print_glsl_visitor::visit(ir_demote *ir)
1653{
1654 buffer.asprintf_append ("discard-TODO");
1655}
1656
1657void
1658ir_print_glsl_visitor::visit(ir_if *ir)
1659{
1660 buffer.asprintf_append ("if (");
1661 ir->condition->accept(this);
1662
1663 buffer.asprintf_append (") {\n");
1664 indentation++; previous_skipped = false;
1665
1666
1667 foreach_in_list(ir_instruction, inst, &ir->then_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((&
ir->then_instructions)->head_sentinel.next) ? (ir_instruction
*) ((&ir->then_instructions)->head_sentinel.next) :
__null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel
((inst)->next) ? (ir_instruction *) ((inst)->next) : __null
))
{
1668 indent();
1669 inst->accept(this);
1670 end_statement_line();
1671 }
1672
1673 indentation--;
1674 indent();
1675 buffer.asprintf_append ("}");
1676
1677 if (!ir->else_instructions.is_empty())
1678 {
1679 buffer.asprintf_append (" else {\n");
1680 indentation++; previous_skipped = false;
1681
1682 foreach_in_list(ir_instruction, inst, &ir->else_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((&
ir->else_instructions)->head_sentinel.next) ? (ir_instruction
*) ((&ir->else_instructions)->head_sentinel.next) :
__null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel
((inst)->next) ? (ir_instruction *) ((inst)->next) : __null
))
{
1683 indent();
1684 inst->accept(this);
1685 end_statement_line();
1686 }
1687 indentation--;
1688 indent();
1689 buffer.asprintf_append ("}");
1690 }
1691}
1692
1693bool ir_print_glsl_visitor::can_emit_canonical_for (loop_variable_state *ls)
1694{
1695 if (ls == NULL__null)
1696 return false;
1697
1698 if (ls->induction_variables.is_empty())
1699 return false;
1700
1701 if (ls->terminators.is_empty())
1702 return false;
1703
1704 // only support for loops with one terminator condition
1705 int terminatorCount = ls->terminators.length();
1706 if (terminatorCount != 1)
1707 return false;
1708
1709 return true;
1710}
1711
1712bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
1713{
1714 loop_variable_state* const ls = this->loopstate->get(ir);
1715
1716 if (!can_emit_canonical_for(ls))
1717 return false;
1718
1719 hash_table* terminator_hash = _mesa_hash_table_create(nullptr, _mesa_hash_pointer, _mesa_key_pointer_equal);
1720 hash_table* induction_hash = _mesa_hash_table_create(nullptr, _mesa_hash_pointer, _mesa_key_pointer_equal);
1721
1722 buffer.asprintf_append("for (");
1723 inside_loop_body = true;
1724
1725 // emit loop induction variable declarations.
1726 // only for loops with single induction variable, to avoid cases of different types of them
1727 // FIXME
1728 // if (ls->private_induction_variable_count == 1)
1729 // {
1730 // foreach_in_list(loop_variable, indvar, &ls->induction_variables)
1731 // {
1732 // if (!this->loopstate->get_for_inductor(indvar->var))
1733 // continue;
1734
1735 // ir_variable* var = indvar->var;
1736 // print_precision (var, var->type);
1737 // print_type(buffer, var->type, false);
1738 // buffer.asprintf_append (" ");
1739 // print_var_name (var);
1740 // print_type_post(buffer, var->type, false);
1741 // if (indvar->initial_value)
1742 // {
1743 // buffer.asprintf_append (" = ");
1744 // // if the var is an array add the proper initializer
1745 // if(var->type->is_vector())
1746 // {
1747 // print_type(buffer, var->type, false);
1748 // buffer.asprintf_append ("(");
1749 // }
1750 // indvar->initial_value->accept(this);
1751 // if(var->type->is_vector())
1752 // {
1753 // buffer.asprintf_append (")");
1754 // }
1755 // }
1756 // }
1757 // }
1758 buffer.asprintf_append("; ");
1759
1760 // emit loop terminating conditions
1761 foreach_in_list(loop_terminator, term, &ls->terminators)for (loop_terminator *term = (!exec_node_is_tail_sentinel((&
ls->terminators)->head_sentinel.next) ? (loop_terminator
*) ((&ls->terminators)->head_sentinel.next) : __null
); (term) != __null; (term) = (!exec_node_is_tail_sentinel((term
)->next) ? (loop_terminator *) ((term)->next) : __null)
)
1762 {
1763 _mesa_hash_table_insert(terminator_hash, term->ir, term);
1764
1765 // IR has conditions in the form of "if (x) break",
1766 // whereas for loop needs them negated, in the form
1767 // if "while (x) continue the loop".
1768 // See if we can print them using syntax that reads nice.
1769 bool handled = false;
1770 ir_expression* term_expr = term->ir->condition->as_expression();
1771 if (term_expr)
1772 {
1773 // Binary comparison conditions
1774 const char* termOp = NULL__null;
1775 switch (term_expr->operation)
1776 {
1777 case ir_binop_less: termOp = ">="; break;
1778 case ir_binop_gequal: termOp = "<"; break;
1779 case ir_binop_equal: termOp = "!="; break;
1780 case ir_binop_nequal: termOp = "=="; break;
1781 default: break;
1782 }
1783 if (termOp != NULL__null)
1784 {
1785 term_expr->operands[0]->accept(this);
1786 buffer.asprintf_append(" %s ", termOp);
1787 term_expr->operands[1]->accept(this);
1788 handled = true;
1789 }
1790
1791 // Unary logic not
1792 if (!handled && term_expr->operation == ir_unop_logic_not)
1793 {
1794 term_expr->operands[0]->accept(this);
1795 handled = true;
1796 }
1797 }
1798
1799 // More complex condition, print as "!(x)"
1800 if (!handled)
1801 {
1802 buffer.asprintf_append("!(");
1803 term->ir->condition->accept(this);
1804 buffer.asprintf_append(")");
1805 }
1806 }
1807 buffer.asprintf_append("; ");
1808
1809 // emit loop induction variable updates
1810 bool first = true;
1811 foreach_in_list(loop_variable, indvar, &ls->induction_variables)for (loop_variable *indvar = (!exec_node_is_tail_sentinel((&
ls->induction_variables)->head_sentinel.next) ? (loop_variable
*) ((&ls->induction_variables)->head_sentinel.next
) : __null); (indvar) != __null; (indvar) = (!exec_node_is_tail_sentinel
((indvar)->next) ? (loop_variable *) ((indvar)->next) :
__null))
1812 {
1813 _mesa_hash_table_insert(induction_hash, indvar->first_assignment, indvar);
1814 if (!first)
1815 buffer.asprintf_append(", ");
1816 visit(indvar->first_assignment);
1817 first = false;
1818 }
1819 buffer.asprintf_append(") {\n");
1820
1821 inside_loop_body = false;
1822
1823 // emit loop body
1824 indentation++; previous_skipped = false;
1825 foreach_in_list(ir_instruction, inst, &ir->body_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((&
ir->body_instructions)->head_sentinel.next) ? (ir_instruction
*) ((&ir->body_instructions)->head_sentinel.next) :
__null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel
((inst)->next) ? (ir_instruction *) ((inst)->next) : __null
))
{
1826
1827 // skip termination & induction statements,
1828 // they are part of "for" clause
1829 if (_mesa_hash_table_search(terminator_hash, inst))
1830 continue;
1831 if (_mesa_hash_table_search(induction_hash, inst))
1832 continue;
1833
1834 indent();
1835 inst->accept(this);
1836 end_statement_line();
1837 }
1838 indentation--;
1839
1840 indent();
1841 buffer.asprintf_append("}");
1842
1843 _mesa_hash_table_destroy (terminator_hash, nullptr);
1844 _mesa_hash_table_destroy (induction_hash, nullptr);
1845
1846 return true;
1847}
1848
1849
1850void
1851ir_print_glsl_visitor::visit(ir_loop *ir)
1852{
1853 if (emit_canonical_for(ir))
1854 return;
1855
1856 buffer.asprintf_append ("while (true) {\n");
1857 indentation++; previous_skipped = false;
1858 foreach_in_list(ir_instruction, inst, &ir->body_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((&
ir->body_instructions)->head_sentinel.next) ? (ir_instruction
*) ((&ir->body_instructions)->head_sentinel.next) :
__null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel
((inst)->next) ? (ir_instruction *) ((inst)->next) : __null
))
{
1859 indent();
1860 inst->accept(this);
1861 end_statement_line();
1862 }
1863 indentation--;
1864 indent();
1865 buffer.asprintf_append ("}");
1866}
1867
1868
1869void
1870ir_print_glsl_visitor::visit(ir_loop_jump *ir)
1871{
1872 buffer.asprintf_append ("%s", ir->is_break() ? "break" : "continue");
1873}
1874
1875void
1876ir_print_glsl_visitor::visit(ir_precision_statement *ir)
1877{
1878 buffer.asprintf_append ("%s", ir->precision_statement);
1879}
1880
1881static const char*
1882interface_packing_string(enum glsl_interface_packing packing)
1883{
1884 switch (packing) {
1885 case GLSL_INTERFACE_PACKING_STD140:
1886 return "std140";
1887 case GLSL_INTERFACE_PACKING_SHARED:
1888 return "shared";
1889 case GLSL_INTERFACE_PACKING_PACKED:
1890 return "packed";
1891 case GLSL_INTERFACE_PACKING_STD430:
1892 return "std430";
1893 default:
1894 unreachable("Unexpected interface packing")do { (static_cast <bool> (!"Unexpected interface packing"
) ? void (0) : __assert_fail ("!\"Unexpected interface packing\""
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
)); __builtin_unreachable(); } while (0)
;
1895 return "UNKNOWN";
1896 }
1897}
1898
1899static const char*
1900interface_variable_mode_string(enum ir_variable_mode mode)
1901{
1902 switch (mode) {
1903 case ir_var_uniform:
1904 return "uniform";
1905 case ir_var_shader_storage:
1906 return "buffer";
1907 default:
1908 unreachable("Unexpected interface variable mode")do { (static_cast <bool> (!"Unexpected interface variable mode"
) ? void (0) : __assert_fail ("!\"Unexpected interface variable mode\""
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
)); __builtin_unreachable(); } while (0)
;
1909 return "UNKOWN";
1910 }
1911}
1912
1913void
1914ir_print_glsl_visitor::visit(ir_typedecl_statement *ir)
1915{
1916 const glsl_type *const s = ir->type_decl;
1917
1918 ir_variable* interface_var = NULL__null;
1
'interface_var' initialized to a null pointer value
1919
1920 if (s->is_struct()) {
2
Taking false branch
1921 buffer.asprintf_append ("struct %s {\n", s->name);
1922 } else if (s->is_interface()) {
3
Taking true branch
1923 const char* packing = interface_packing_string(s->get_interface_packing());
1924
1925 // Find a variable defined by this interface, as it holds some necessary data.
1926 exec_node* n = ir;
1927 while ((n = n->get_next())) {
4
Loop condition is false. Execution continues on line 1934
1928 ir_variable* v = ((ir_instruction *)n)->as_variable();
1929 if (v != NULL__null && v->get_interface_type() == ir->type_decl) {
1930 interface_var = v;
1931 break;
1932 }
1933 }
1934 const char* mode = interface_variable_mode_string((enum ir_variable_mode)interface_var->data.mode);
5
Dereference of null pointer
1935 if (interface_var->data.explicit_binding) {
1936 uint16_t binding = interface_var->data.binding;
1937 buffer.asprintf_append ("layout(%s, binding=%" PRIu16"u" ") %s %s {\n", packing, binding, mode, s->name);
1938 } else {
1939 buffer.asprintf_append ("layout(%s) %s %s {\n", packing, mode, s->name);
1940 }
1941
1942 }
1943
1944 for (unsigned j = 0; j < s->length; j++) {
1945 buffer.asprintf_append (" ");
1946 // FIXME: precision
1947 // if (state->es_shader)
1948 // buffer.asprintf_append ("%s", get_precision_string(s->fields.structure[j].precision));
1949 print_type(buffer, s->fields.structure[j].type, false);
1950 buffer.asprintf_append (" %s", s->fields.structure[j].name);
1951 print_type_post(buffer, s->fields.structure[j].type, false);
1952 buffer.asprintf_append (";\n");
1953 }
1954 buffer.asprintf_append ("}");
1955
1956 if (interface_var && interface_var->is_interface_instance()) {
1957 buffer.asprintf_append(" ");
1958 print_var_name(interface_var);
1959 }
1960}
1961
1962void
1963ir_print_glsl_visitor::visit(ir_emit_vertex *ir)
1964{
1965 buffer.asprintf_append ("emit-vertex-TODO");
1966}
1967
1968void
1969ir_print_glsl_visitor::visit(ir_end_primitive *ir)
1970{
1971 buffer.asprintf_append ("end-primitive-TODO");
1972}
1973
1974void
1975ir_print_glsl_visitor::visit(ir_barrier *ir)
1976{
1977 buffer.asprintf_append ("discard-TODO");
1978}