main.cpp revision 127308b4be077e5bdf60f76320307550921e86bb
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright © 2008, 2009 Intel Corporation
359d709d503bab6e2b61931737e662dd293b40578ccornelius *
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Permission is hereby granted, free of charge, to any person obtaining a
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * copy of this software and associated documentation files (the "Software"),
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to deal in the Software without restriction, including without limitation
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and/or sell copies of the Software, and to permit persons to whom the
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Software is furnished to do so, subject to the following conditions:
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The above copyright notice and this permission notice (including the next
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * paragraph) shall be included in all copies or substantial portions of the
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Software.
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * DEALINGS IN THE SOFTWARE.
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <cstdlib>
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <cstdio>
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <getopt.h>
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <sys/types.h>
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <sys/stat.h>
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <fcntl.h>
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <unistd.h>
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ast.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "glsl_parser_extras.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "glsl_parser.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ir_optimization.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ir_print_visitor.h"
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "program.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Returned string will have 'ctx' as its talloc owner. */
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char *
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruload_text_file(void *ctx, const char *file_name)
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	char *text = NULL;
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	struct stat st;
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	ssize_t total_read = 0;
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	int fd = open(file_name, O_RDONLY);
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (fd < 0) {
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		return NULL;
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	}
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (fstat(fd, & st) == 0) {
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	   text = (char *) talloc_size(ctx, st.st_size + 1);
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		if (text != NULL) {
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru			do {
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru				ssize_t bytes = read(fd, text + total_read,
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru						     st.st_size - total_read);
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru				if (bytes < 0) {
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru					free(text);
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru					text = NULL;
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru					break;
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru				}
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru				if (bytes == 0) {
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru					break;
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru				}
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru				total_read += bytes;
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru			} while (total_read < st.st_size);
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru			text[total_read] = '\0';
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		}
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	}
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	close(fd);
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	return text;
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruusage_fail(const char *name)
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      printf("%s <filename.frag|filename.vert>\n", name);
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      exit(EXIT_FAILURE);
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint dump_ast = 0;
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint dump_hir = 0;
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint dump_lir = 0;
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint do_link = 0;
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst struct option compiler_opts[] = {
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   { "dump-ast", 0, &dump_ast, 1 },
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   { "dump-hir", 0, &dump_hir, 1 },
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   { "dump-lir", 0, &dump_lir, 1 },
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   { "link",     0, &do_link,  1 },
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   { NULL, 0, NULL, 0 }
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querusteal_memory(ir_instruction *ir, void *new_ctx)
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   talloc_steal(new_ctx, ir);
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querucompile_shader(struct gl_shader *shader)
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   struct _mesa_glsl_parse_state *state;
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state = talloc_zero(talloc_parent(shader), struct _mesa_glsl_parse_state);
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   switch (shader->Type) {
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   case GL_VERTEX_SHADER:   state->target = vertex_shader; break;
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   case GL_FRAGMENT_SHADER: state->target = fragment_shader; break;
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   case GL_GEOMETRY_SHADER: state->target = geometry_shader; break;
11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho   }
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->scanner = NULL;
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->translation_unit.make_empty();
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->symbols = new(shader) glsl_symbol_table;
12459d709d503bab6e2b61931737e662dd293b40578ccornelius   state->info_log = talloc_strdup(shader, "");
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->error = false;
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->temp_index = 0;
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->loop_or_switch_nesting = NULL;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->ARB_texture_rectangle_enable = true;
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->Const.MaxDrawBuffers = 2;
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->Const.MaxTextureCoords = 4;
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   const char *source = shader->Source;
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   state->error = preprocess(state, &source, &state->info_log);
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   if (!state->error) {
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      _mesa_glsl_lexer_ctor(state, source);
13883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius      _mesa_glsl_parse(state);
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      _mesa_glsl_lexer_dtor(state);
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   }
141
142   if (dump_ast) {
143      foreach_list_const(n, &state->translation_unit) {
144	 ast_node *ast = exec_node_data(ast_node, n, link);
145	 ast->print();
146      }
147      printf("\n\n");
148   }
149
150   shader->ir = new(shader) exec_list;
151   if (!state->error && !state->translation_unit.is_empty())
152      _mesa_ast_to_hir(shader->ir, state);
153
154   validate_ir_tree(shader->ir);
155
156   /* Print out the unoptimized IR. */
157   if (!state->error && dump_hir) {
158      _mesa_print_ir(shader->ir, state);
159   }
160
161   /* Optimization passes */
162   if (!state->error && !shader->ir->is_empty()) {
163      bool progress;
164      do {
165	 progress = false;
166
167	 progress = do_function_inlining(shader->ir) || progress;
168	 progress = do_if_simplification(shader->ir) || progress;
169	 progress = do_copy_propagation(shader->ir) || progress;
170	 progress = do_dead_code_local(shader->ir) || progress;
171	 progress = do_dead_code_unlinked(state, shader->ir) || progress;
172	 progress = do_constant_variable_unlinked(shader->ir) || progress;
173	 progress = do_constant_folding(shader->ir) || progress;
174	 progress = do_vec_index_to_swizzle(shader->ir) || progress;
175	 progress = do_swizzle_swizzle(shader->ir) || progress;
176      } while (progress);
177   }
178
179   validate_ir_tree(shader->ir);
180
181   /* Print out the resulting IR */
182   if (!state->error && dump_lir) {
183      _mesa_print_ir(shader->ir, state);
184   }
185
186   shader->symbols = state->symbols;
187   shader->CompileStatus = !state->error;
188
189   if (shader->InfoLog)
190      talloc_free(shader->InfoLog);
191
192   shader->InfoLog = state->info_log;
193
194   /* Retain any live IR, but trash the rest. */
195   foreach_list(node, shader->ir) {
196      visit_tree((ir_instruction *) node, steal_memory, shader);
197   }
198
199   talloc_free(state);
200
201   return;
202}
203
204int
205main(int argc, char **argv)
206{
207   int status = EXIT_SUCCESS;
208
209   int c;
210   int idx = 0;
211   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
212      /* empty */ ;
213
214
215   if (argc <= optind)
216      usage_fail(argv[0]);
217
218   struct gl_shader_program *whole_program;
219
220   whole_program = talloc_zero (NULL, struct gl_shader_program);
221   assert(whole_program != NULL);
222
223   for (/* empty */; argc > optind; optind++) {
224      whole_program->Shaders = (struct gl_shader **)
225	 talloc_realloc(whole_program, whole_program->Shaders,
226			struct gl_shader *, whole_program->NumShaders + 1);
227      assert(whole_program->Shaders != NULL);
228
229      struct gl_shader *shader = talloc_zero(whole_program, gl_shader);
230
231      whole_program->Shaders[whole_program->NumShaders] = shader;
232      whole_program->NumShaders++;
233
234      const unsigned len = strlen(argv[optind]);
235      if (len < 6)
236	 usage_fail(argv[0]);
237
238      const char *const ext = & argv[optind][len - 5];
239      if (strncmp(".vert", ext, 5) == 0)
240	 shader->Type = GL_VERTEX_SHADER;
241      else if (strncmp(".geom", ext, 5) == 0)
242	 shader->Type = GL_GEOMETRY_SHADER;
243      else if (strncmp(".frag", ext, 5) == 0)
244	 shader->Type = GL_FRAGMENT_SHADER;
245      else
246	 usage_fail(argv[0]);
247
248      shader->Source = load_text_file(whole_program, argv[optind]);
249      if (shader->Source == NULL) {
250	 printf("File \"%s\" does not exist.\n", argv[optind]);
251	 exit(EXIT_FAILURE);
252      }
253
254      compile_shader(shader);
255
256      if (!shader->CompileStatus) {
257	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
258	 status = EXIT_FAILURE;
259	 break;
260      }
261   }
262
263   if ((status == EXIT_SUCCESS) && do_link)  {
264      link_shaders(whole_program);
265      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
266   }
267
268   talloc_free(whole_program);
269   _mesa_glsl_release_types();
270
271   return status;
272}
273