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>
37 #include "glsl_parser_extras.h"
38 #include "glsl_parser.h"
39 #include "ir_optimization.h"
40 #include "ir_print_visitor.h"
45 load_text_file(const char *file_name
, size_t *size
)
49 ssize_t total_read
= 0;
50 int fd
= open(file_name
, O_RDONLY
);
57 if (fstat(fd
, & st
) == 0) {
58 text
= (char *) malloc(st
.st_size
+ 1);
61 ssize_t bytes
= read(fd
, text
+ total_read
,
62 st
.st_size
- total_read
);
74 } while (total_read
< st
.st_size
);
76 text
[total_read
] = '\0';
88 usage_fail(const char *name
)
90 printf("%s <filename.frag|filename.vert>\n", name
);
99 const struct option compiler_opts
[] = {
100 { "dump-ast", 0, &dump_ast
, 1 },
101 { "dump-lir", 0, &dump_lir
, 1 },
102 { "link", 0, &do_link
, 1 },
107 compile_shader(struct glsl_shader
*shader
)
109 struct _mesa_glsl_parse_state state
;
111 memset(& state
, 0, sizeof(state
));
112 switch (shader
->Type
) {
113 case GL_VERTEX_SHADER
: state
.target
= vertex_shader
; break;
114 case GL_FRAGMENT_SHADER
: state
.target
= fragment_shader
; break;
115 case GL_GEOMETRY_SHADER
: state
.target
= geometry_shader
; break;
118 state
.scanner
= NULL
;
119 state
.translation_unit
.make_empty();
120 state
.symbols
= new glsl_symbol_table
;
121 state
.info_log
= talloc_strdup(shader
, "");
123 state
.temp_index
= 0;
124 state
.loop_or_switch_nesting
= NULL
;
125 state
.ARB_texture_rectangle_enable
= true;
127 /* Create a new context for the preprocessor output. Ultimately, this
128 * should probably be the parser context, but there isn't one yet.
130 const char *source
= shader
->Source
;
131 state
.error
= preprocess(shader
, &source
, &state
.info_log
);
134 _mesa_glsl_lexer_ctor(& state
, source
);
135 _mesa_glsl_parse(& state
);
136 _mesa_glsl_lexer_dtor(& state
);
140 foreach_list_const(n
, &state
.translation_unit
) {
141 ast_node
*ast
= exec_node_data(ast_node
, n
, link
);
147 shader
->ir
.make_empty();
148 if (!state
.error
&& !state
.translation_unit
.is_empty())
149 _mesa_ast_to_hir(&shader
->ir
, &state
);
151 validate_ir_tree(&shader
->ir
);
153 /* Optimization passes */
154 if (!state
.error
&& !shader
->ir
.is_empty()) {
159 progress
= do_function_inlining(&shader
->ir
) || progress
;
160 progress
= do_if_simplification(&shader
->ir
) || progress
;
161 progress
= do_copy_propagation(&shader
->ir
) || progress
;
162 progress
= do_dead_code_local(&shader
->ir
) || progress
;
163 progress
= do_dead_code_unlinked(&shader
->ir
) || progress
;
164 progress
= do_constant_variable_unlinked(&shader
->ir
) || progress
;
165 progress
= do_constant_folding(&shader
->ir
) || progress
;
166 progress
= do_vec_index_to_swizzle(&shader
->ir
) || progress
;
167 progress
= do_swizzle_swizzle(&shader
->ir
) || progress
;
171 validate_ir_tree(&shader
->ir
);
173 /* Print out the resulting IR */
174 if (!state
.error
&& dump_lir
) {
175 _mesa_print_ir(&shader
->ir
, &state
);
178 shader
->symbols
= state
.symbols
;
179 shader
->CompileStatus
= !state
.error
;
182 talloc_free(shader
->InfoLog
);
184 shader
->InfoLog
= state
.info_log
;
190 main(int argc
, char **argv
)
192 int status
= EXIT_SUCCESS
;
196 while ((c
= getopt_long(argc
, argv
, "", compiler_opts
, &idx
)) != -1)
203 struct glsl_program whole_program
;
204 memset(&whole_program
, 0, sizeof(whole_program
));
206 for (/* empty */; argc
> optind
; optind
++) {
207 whole_program
.Shaders
= (struct glsl_shader
**)
208 realloc(whole_program
.Shaders
,
209 sizeof(struct glsl_shader
*) * (whole_program
.NumShaders
+ 1));
210 assert(whole_program
.Shaders
!= NULL
);
212 /* talloc context should probably be whole_program */
213 struct glsl_shader
*shader
= talloc_zero(NULL
, 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(argv
[optind
], &shader
->SourceLen
);
233 if (shader
->Source
== NULL
) {
234 printf("File \"%s\" does not exist.\n", argv
[optind
]);
238 compile_shader(shader
);
240 if (!shader
->CompileStatus
) {
241 printf("Info log for %s:\n%s\n", argv
[optind
], shader
->InfoLog
);
242 status
= EXIT_FAILURE
;
247 if ((status
== EXIT_SUCCESS
) && do_link
) {
248 link_shaders(&whole_program
);
249 status
= (whole_program
.LinkStatus
) ? EXIT_SUCCESS
: EXIT_FAILURE
;