2 * Copyright © 2008, 2009 Intel Corporation
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:
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
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.
27 #include <sys/types.h>
33 #include "glsl_parser_extras.h"
34 #include "glsl_parser.h"
35 #include "ir_optimization.h"
36 #include "ir_print_visitor.h"
39 /* Returned string will have 'ctx' as its talloc owner. */
41 load_text_file(void *ctx
, const char *file_name
, size_t *size
)
45 ssize_t total_read
= 0;
46 int fd
= open(file_name
, O_RDONLY
);
53 if (fstat(fd
, & st
) == 0) {
54 text
= (char *) talloc_size(ctx
, st
.st_size
+ 1);
57 ssize_t bytes
= read(fd
, text
+ total_read
,
58 st
.st_size
- total_read
);
70 } while (total_read
< st
.st_size
);
72 text
[total_read
] = '\0';
84 usage_fail(const char *name
)
86 printf("%s <filename.frag|filename.vert>\n", name
);
95 const struct option compiler_opts
[] = {
96 { "dump-ast", 0, &dump_ast
, 1 },
97 { "dump-lir", 0, &dump_lir
, 1 },
98 { "link", 0, &do_link
, 1 },
103 compile_shader(struct glsl_shader
*shader
)
105 struct _mesa_glsl_parse_state
*state
;
107 state
= talloc_zero(talloc_parent(shader
), struct _mesa_glsl_parse_state
);
109 switch (shader
->Type
) {
110 case GL_VERTEX_SHADER
: state
->target
= vertex_shader
; break;
111 case GL_FRAGMENT_SHADER
: state
->target
= fragment_shader
; break;
112 case GL_GEOMETRY_SHADER
: state
->target
= geometry_shader
; break;
115 state
->scanner
= NULL
;
116 state
->translation_unit
.make_empty();
117 state
->symbols
= new(shader
) glsl_symbol_table
;
118 state
->info_log
= talloc_strdup(shader
, "");
119 state
->error
= false;
120 state
->temp_index
= 0;
121 state
->loop_or_switch_nesting
= NULL
;
122 state
->ARB_texture_rectangle_enable
= true;
124 /* Create a new context for the preprocessor output. Ultimately, this
125 * should probably be the parser context, but there isn't one yet.
127 const char *source
= shader
->Source
;
128 state
->error
= preprocess(shader
, &source
, &state
->info_log
);
131 _mesa_glsl_lexer_ctor(state
, source
);
132 _mesa_glsl_parse(state
);
133 _mesa_glsl_lexer_dtor(state
);
137 foreach_list_const(n
, &state
->translation_unit
) {
138 ast_node
*ast
= exec_node_data(ast_node
, n
, link
);
144 shader
->ir
.make_empty();
145 if (!state
->error
&& !state
->translation_unit
.is_empty())
146 _mesa_ast_to_hir(&shader
->ir
, state
);
148 validate_ir_tree(&shader
->ir
);
150 /* Optimization passes */
151 if (!state
->error
&& !shader
->ir
.is_empty()) {
156 progress
= do_function_inlining(&shader
->ir
) || progress
;
157 progress
= do_if_simplification(&shader
->ir
) || progress
;
158 progress
= do_copy_propagation(&shader
->ir
) || progress
;
159 progress
= do_dead_code_local(&shader
->ir
) || progress
;
160 progress
= do_dead_code_unlinked(&shader
->ir
) || progress
;
161 progress
= do_constant_variable_unlinked(&shader
->ir
) || progress
;
162 progress
= do_constant_folding(&shader
->ir
) || progress
;
163 progress
= do_vec_index_to_swizzle(&shader
->ir
) || progress
;
164 progress
= do_swizzle_swizzle(&shader
->ir
) || progress
;
168 validate_ir_tree(&shader
->ir
);
170 /* Print out the resulting IR */
171 if (!state
->error
&& dump_lir
) {
172 _mesa_print_ir(&shader
->ir
, state
);
175 shader
->symbols
= state
->symbols
;
176 shader
->CompileStatus
= !state
->error
;
179 talloc_free(shader
->InfoLog
);
181 shader
->InfoLog
= state
->info_log
;
189 main(int argc
, char **argv
)
191 int status
= EXIT_SUCCESS
;
195 while ((c
= getopt_long(argc
, argv
, "", compiler_opts
, &idx
)) != -1)
202 struct glsl_program
*whole_program
;
204 whole_program
= talloc_zero (NULL
, struct glsl_program
);
205 assert(whole_program
!= NULL
);
207 for (/* empty */; argc
> optind
; optind
++) {
208 whole_program
->Shaders
= (struct glsl_shader
**)
209 talloc_realloc(whole_program
, whole_program
->Shaders
,
210 struct glsl_shader
*, whole_program
->NumShaders
+ 1);
211 assert(whole_program
->Shaders
!= NULL
);
213 struct glsl_shader
*shader
= talloc_zero(whole_program
, glsl_shader
);
215 whole_program
->Shaders
[whole_program
->NumShaders
] = shader
;
216 whole_program
->NumShaders
++;
218 const unsigned len
= strlen(argv
[optind
]);
222 const char *const ext
= & argv
[optind
][len
- 5];
223 if (strncmp(".vert", ext
, 5) == 0)
224 shader
->Type
= GL_VERTEX_SHADER
;
225 else if (strncmp(".geom", ext
, 5) == 0)
226 shader
->Type
= GL_GEOMETRY_SHADER
;
227 else if (strncmp(".frag", ext
, 5) == 0)
228 shader
->Type
= GL_FRAGMENT_SHADER
;
232 shader
->Source
= load_text_file(whole_program
,
233 argv
[optind
], &shader
->SourceLen
);
234 if (shader
->Source
== NULL
) {
235 printf("File \"%s\" does not exist.\n", argv
[optind
]);
239 compile_shader(shader
);
241 if (!shader
->CompileStatus
) {
242 printf("Info log for %s:\n%s\n", argv
[optind
], shader
->InfoLog
);
243 status
= EXIT_FAILURE
;
248 if ((status
== EXIT_SUCCESS
) && do_link
) {
249 link_shaders(whole_program
);
250 status
= (whole_program
->LinkStatus
) ? EXIT_SUCCESS
: EXIT_FAILURE
;
253 talloc_free(whole_program
);