1 /* 2 * Copyright 2008, 2009 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 #include <getopt.h> 24 25 /** @file main.cpp 26 * 27 * This file is the main() routine and scaffolding for producing 28 * builtin_compiler (which doesn't include builtins itself and is used 29 * to generate the profile information for builtin_function.cpp), and 30 * for glsl_compiler (which does include builtins and can be used to 31 * offline compile GLSL code and examine the resulting GLSL IR. 32 */ 33 34 #include "ast.h" 35 #include "glsl_parser_extras.h" 36 #include "ir_optimization.h" 37 #include "ir_print_visitor.h" 38 #include "program.h" 39 #include "loop_analysis.h" 40 #include "standalone_scaffolding.h" 41 42 static void 43 initialize_context(struct gl_context *ctx, gl_api api) 44 { 45 initialize_context_to_defaults(ctx, api); 46 47 /* The standalone compiler needs to claim support for almost 48 * everything in order to compile the built-in functions. 49 */ 50 ctx->Const.GLSLVersion = 140; 51 52 ctx->Const.MaxClipPlanes = 8; 53 ctx->Const.MaxDrawBuffers = 2; 54 55 /* More than the 1.10 minimum to appease parser tests taken from 56 * apps that (hopefully) already checked the number of coords. 57 */ 58 ctx->Const.MaxTextureCoordUnits = 4; 59 60 ctx->Driver.NewShader = _mesa_new_shader; 61 } 62 63 /* Returned string will have 'ctx' as its ralloc owner. */ 64 static char * 65 load_text_file(void *ctx, const char *file_name) 66 { 67 char *text = NULL; 68 size_t size; 69 size_t total_read = 0; 70 FILE *fp = fopen(file_name, "rb"); 71 72 if (!fp) { 73 return NULL; 74 } 75 76 fseek(fp, 0L, SEEK_END); 77 size = ftell(fp); 78 fseek(fp, 0L, SEEK_SET); 79 80 text = (char *) ralloc_size(ctx, size + 1); 81 if (text != NULL) { 82 do { 83 size_t bytes = fread(text + total_read, 84 1, size - total_read, fp); 85 if (bytes < size - total_read) { 86 free(text); 87 text = NULL; 88 break; 89 } 90 91 if (bytes == 0) { 92 break; 93 } 94 95 total_read += bytes; 96 } while (total_read < size); 97 98 text[total_read] = '\0'; 99 } 100 101 fclose(fp); 102 103 return text; 104 } 105 106 int glsl_es = 0; 107 int dump_ast = 0; 108 int dump_hir = 0; 109 int dump_lir = 0; 110 int do_link = 0; 111 112 const struct option compiler_opts[] = { 113 { "glsl-es", 0, &glsl_es, 1 }, 114 { "dump-ast", 0, &dump_ast, 1 }, 115 { "dump-hir", 0, &dump_hir, 1 }, 116 { "dump-lir", 0, &dump_lir, 1 }, 117 { "link", 0, &do_link, 1 }, 118 { NULL, 0, NULL, 0 } 119 }; 120 121 /** 122 * \brief Print proper usage and exit with failure. 123 */ 124 void 125 usage_fail(const char *name) 126 { 127 128 const char *header = 129 "usage: %s [options] <file.vert | file.geom | file.frag>\n" 130 "\n" 131 "Possible options are:\n"; 132 printf(header, name, name); 133 for (const struct option *o = compiler_opts; o->name != 0; ++o) { 134 printf(" --%s\n", o->name); 135 } 136 exit(EXIT_FAILURE); 137 } 138 139 140 void 141 compile_shader(struct gl_context *ctx, struct gl_shader *shader) 142 { 143 struct _mesa_glsl_parse_state *state = 144 new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); 145 146 const char *source = shader->Source; 147 state->error = glcpp_preprocess(state, &source, &state->info_log, 148 state->extensions, ctx->API) != 0; 149 150 if (!state->error) { 151 _mesa_glsl_lexer_ctor(state, source); 152 _mesa_glsl_parse(state); 153 _mesa_glsl_lexer_dtor(state); 154 } 155 156 if (dump_ast) { 157 foreach_list_const(n, &state->translation_unit) { 158 ast_node *ast = exec_node_data(ast_node, n, link); 159 ast->print(); 160 } 161 printf("\n\n"); 162 } 163 164 shader->ir = new(shader) exec_list; 165 if (!state->error && !state->translation_unit.is_empty()) 166 _mesa_ast_to_hir(shader->ir, state); 167 168 /* Print out the unoptimized IR. */ 169 if (!state->error && dump_hir) { 170 validate_ir_tree(shader->ir); 171 _mesa_print_ir(shader->ir, state); 172 } 173 174 /* Optimization passes */ 175 if (!state->error && !shader->ir->is_empty()) { 176 bool progress; 177 do { 178 progress = do_common_optimization(shader->ir, false, false, 32); 179 } while (progress); 180 181 validate_ir_tree(shader->ir); 182 } 183 184 185 /* Print out the resulting IR */ 186 if (!state->error && dump_lir) { 187 _mesa_print_ir(shader->ir, state); 188 } 189 190 shader->symbols = state->symbols; 191 shader->CompileStatus = !state->error; 192 shader->Version = state->language_version; 193 memcpy(shader->builtins_to_link, state->builtins_to_link, 194 sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); 195 shader->num_builtins_to_link = state->num_builtins_to_link; 196 197 if (shader->InfoLog) 198 ralloc_free(shader->InfoLog); 199 200 shader->InfoLog = state->info_log; 201 202 /* Retain any live IR, but trash the rest. */ 203 reparent_ir(shader->ir, shader); 204 205 ralloc_free(state); 206 207 return; 208 } 209 210 int 211 main(int argc, char **argv) 212 { 213 int status = EXIT_SUCCESS; 214 struct gl_context local_ctx; 215 struct gl_context *ctx = &local_ctx; 216 217 int c; 218 int idx = 0; 219 while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) 220 /* empty */ ; 221 222 223 if (argc <= optind) 224 usage_fail(argv[0]); 225 226 initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL); 227 228 struct gl_shader_program *whole_program; 229 230 whole_program = rzalloc (NULL, struct gl_shader_program); 231 assert(whole_program != NULL); 232 whole_program->InfoLog = ralloc_strdup(whole_program, ""); 233 234 for (/* empty */; argc > optind; optind++) { 235 whole_program->Shaders = 236 reralloc(whole_program, whole_program->Shaders, 237 struct gl_shader *, whole_program->NumShaders + 1); 238 assert(whole_program->Shaders != NULL); 239 240 struct gl_shader *shader = rzalloc(whole_program, gl_shader); 241 242 whole_program->Shaders[whole_program->NumShaders] = shader; 243 whole_program->NumShaders++; 244 245 const unsigned len = strlen(argv[optind]); 246 if (len < 6) 247 usage_fail(argv[0]); 248 249 const char *const ext = & argv[optind][len - 5]; 250 if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0) 251 shader->Type = GL_VERTEX_SHADER; 252 else if (strncmp(".geom", ext, 5) == 0) 253 shader->Type = GL_GEOMETRY_SHADER; 254 else if (strncmp(".frag", ext, 5) == 0) 255 shader->Type = GL_FRAGMENT_SHADER; 256 else 257 usage_fail(argv[0]); 258 259 shader->Source = load_text_file(whole_program, argv[optind]); 260 if (shader->Source == NULL) { 261 printf("File \"%s\" does not exist.\n", argv[optind]); 262 exit(EXIT_FAILURE); 263 } 264 265 compile_shader(ctx, shader); 266 267 if (!shader->CompileStatus) { 268 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog); 269 status = EXIT_FAILURE; 270 break; 271 } 272 } 273 274 if ((status == EXIT_SUCCESS) && do_link) { 275 link_shaders(ctx, whole_program); 276 status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE; 277 278 if (strlen(whole_program->InfoLog) > 0) 279 printf("Info log for linking:\n%s\n", whole_program->InfoLog); 280 } 281 282 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) 283 ralloc_free(whole_program->_LinkedShaders[i]); 284 285 ralloc_free(whole_program); 286 _mesa_glsl_release_types(); 287 _mesa_glsl_release_functions(); 288 289 return status; 290 } 291