161d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick/*
261d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * Copyright © 2008, 2009 Intel Corporation
361d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick *
461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * Permission is hereby granted, free of charge, to any person obtaining a
561d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * copy of this software and associated documentation files (the "Software"),
661d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * to deal in the Software without restriction, including without limitation
761d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * the rights to use, copy, modify, merge, publish, distribute, sublicense,
861d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * and/or sell copies of the Software, and to permit persons to whom the
961d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * Software is furnished to do so, subject to the following conditions:
1061d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick *
1161d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * The above copyright notice and this permission notice (including the next
1261d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * paragraph) shall be included in all copies or substantial portions of the
1361d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * Software.
1461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick *
1561d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1661d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1761d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1861d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1961d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2061d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2161d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick * DEALINGS IN THE SOFTWARE.
2261d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick */
237babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick#include <getopt.h>
2461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
256a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt/** @file main.cpp
266a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt *
276a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt * This file is the main() routine and scaffolding for producing
286a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt * builtin_compiler (which doesn't include builtins itself and is used
296a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt * to generate the profile information for builtin_function.cpp), and
306a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt * for glsl_compiler (which does include builtins and can be used to
316a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt * offline compile GLSL code and examine the resulting GLSL IR.
326a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt */
336a6cb03507da75a30224020c9193464ca5b81c5fEric Anholt
3461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick#include "ast.h"
3561d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick#include "glsl_parser_extras.h"
3661d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick#include "ir_optimization.h"
3761d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick#include "ir_print_visitor.h"
388ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick#include "program.h"
398df2dbf91ddfd0c1590e33015e85470b67e69319Ian Romanick#include "loop_analysis.h"
40f129f618fe8a5397774484f1b7afb42d4be809a0Paul Berry#include "standalone_scaffolding.h"
413fb878722ed53d79eedb9fe68972ef32b79575d4Ian Romanick
42dc754586ca84741b4df5b72fd235c4134816854cChia-I Wustatic void
43f9995b30756140724f41daf963fa06167912be7fKristian Høgsberginitialize_context(struct gl_context *ctx, gl_api api)
44dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu{
45f129f618fe8a5397774484f1b7afb42d4be809a0Paul Berry   initialize_context_to_defaults(ctx, api);
46dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu
47497aab39f0dea48707f9414f318365839132ed75Eric Anholt   /* The standalone compiler needs to claim support for almost
48497aab39f0dea48707f9414f318365839132ed75Eric Anholt    * everything in order to compile the built-in functions.
49e5e34ab18eeaffa465094f6281dfe293b84376dbIan Romanick    */
50497aab39f0dea48707f9414f318365839132ed75Eric Anholt   ctx->Const.GLSLVersion = 140;
51e5e34ab18eeaffa465094f6281dfe293b84376dbIan Romanick
52dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu   ctx->Const.MaxClipPlanes = 8;
53f129f618fe8a5397774484f1b7afb42d4be809a0Paul Berry   ctx->Const.MaxDrawBuffers = 2;
54dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu
55dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu   /* More than the 1.10 minimum to appease parser tests taken from
56dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu    * apps that (hopefully) already checked the number of coords.
57dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu    */
58dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu   ctx->Const.MaxTextureCoordUnits = 4;
59dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu
60dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu   ctx->Driver.NewShader = _mesa_new_shader;
61dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu}
62dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu
63d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke/* Returned string will have 'ctx' as its ralloc owner. */
6461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanickstatic char *
6516b68b1952d0da14b9ce8306efa64988ce46b4b7Eric Anholtload_text_file(void *ctx, const char *file_name)
6661d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick{
6761d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick	char *text = NULL;
680035d1d902f34a88ec745925284fe3b768fac261José Fonseca	size_t size;
690035d1d902f34a88ec745925284fe3b768fac261José Fonseca	size_t total_read = 0;
700035d1d902f34a88ec745925284fe3b768fac261José Fonseca	FILE *fp = fopen(file_name, "rb");
7161d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
720035d1d902f34a88ec745925284fe3b768fac261José Fonseca	if (!fp) {
7361d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick		return NULL;
7461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick	}
7561d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
760035d1d902f34a88ec745925284fe3b768fac261José Fonseca	fseek(fp, 0L, SEEK_END);
770035d1d902f34a88ec745925284fe3b768fac261José Fonseca	size = ftell(fp);
780035d1d902f34a88ec745925284fe3b768fac261José Fonseca	fseek(fp, 0L, SEEK_SET);
790035d1d902f34a88ec745925284fe3b768fac261José Fonseca
80d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke	text = (char *) ralloc_size(ctx, size + 1);
810035d1d902f34a88ec745925284fe3b768fac261José Fonseca	if (text != NULL) {
820035d1d902f34a88ec745925284fe3b768fac261José Fonseca		do {
830035d1d902f34a88ec745925284fe3b768fac261José Fonseca			size_t bytes = fread(text + total_read,
840035d1d902f34a88ec745925284fe3b768fac261José Fonseca					     1, size - total_read, fp);
850035d1d902f34a88ec745925284fe3b768fac261José Fonseca			if (bytes < size - total_read) {
860035d1d902f34a88ec745925284fe3b768fac261José Fonseca				free(text);
870035d1d902f34a88ec745925284fe3b768fac261José Fonseca				text = NULL;
880035d1d902f34a88ec745925284fe3b768fac261José Fonseca				break;
890035d1d902f34a88ec745925284fe3b768fac261José Fonseca			}
900035d1d902f34a88ec745925284fe3b768fac261José Fonseca
910035d1d902f34a88ec745925284fe3b768fac261José Fonseca			if (bytes == 0) {
920035d1d902f34a88ec745925284fe3b768fac261José Fonseca				break;
930035d1d902f34a88ec745925284fe3b768fac261José Fonseca			}
940035d1d902f34a88ec745925284fe3b768fac261José Fonseca
950035d1d902f34a88ec745925284fe3b768fac261José Fonseca			total_read += bytes;
960035d1d902f34a88ec745925284fe3b768fac261José Fonseca		} while (total_read < size);
970035d1d902f34a88ec745925284fe3b768fac261José Fonseca
980035d1d902f34a88ec745925284fe3b768fac261José Fonseca		text[total_read] = '\0';
9961d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick	}
10061d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
1010035d1d902f34a88ec745925284fe3b768fac261José Fonseca	fclose(fp);
10261d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
10361d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick	return text;
10461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick}
10561d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
1061a5b32ca0198488e7d616c8cd968471166a97ef3Chia-I Wuint glsl_es = 0;
1077babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanickint dump_ast = 0;
10822c23dedad4e7f362ffbd990f1c2d5caf4cae75aIan Romanickint dump_hir = 0;
10981e1747ac5206948893876b7da6fdb27bff26e0fIan Romanickint dump_lir = 0;
110c648a124b20c5e37cf4041062333fc177a65f997Ian Romanickint do_link = 0;
1117babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick
1127babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanickconst struct option compiler_opts[] = {
1131a5b32ca0198488e7d616c8cd968471166a97ef3Chia-I Wu   { "glsl-es",  0, &glsl_es,  1 },
1147babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick   { "dump-ast", 0, &dump_ast, 1 },
11522c23dedad4e7f362ffbd990f1c2d5caf4cae75aIan Romanick   { "dump-hir", 0, &dump_hir, 1 },
11681e1747ac5206948893876b7da6fdb27bff26e0fIan Romanick   { "dump-lir", 0, &dump_lir, 1 },
117c648a124b20c5e37cf4041062333fc177a65f997Ian Romanick   { "link",     0, &do_link,  1 },
1187babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick   { NULL, 0, NULL, 0 }
1197babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick};
1207babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick
1217819435f2ef484696560547fbc1325cb97c7174bChad Versace/**
1227819435f2ef484696560547fbc1325cb97c7174bChad Versace * \brief Print proper usage and exit with failure.
1237819435f2ef484696560547fbc1325cb97c7174bChad Versace */
1247819435f2ef484696560547fbc1325cb97c7174bChad Versacevoid
1257819435f2ef484696560547fbc1325cb97c7174bChad Versaceusage_fail(const char *name)
1267819435f2ef484696560547fbc1325cb97c7174bChad Versace{
1277819435f2ef484696560547fbc1325cb97c7174bChad Versace
1287819435f2ef484696560547fbc1325cb97c7174bChad Versace   const char *header =
1297819435f2ef484696560547fbc1325cb97c7174bChad Versace      "usage: %s [options] <file.vert | file.geom | file.frag>\n"
1307819435f2ef484696560547fbc1325cb97c7174bChad Versace      "\n"
1317819435f2ef484696560547fbc1325cb97c7174bChad Versace      "Possible options are:\n";
1327819435f2ef484696560547fbc1325cb97c7174bChad Versace   printf(header, name, name);
1337819435f2ef484696560547fbc1325cb97c7174bChad Versace   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
1347819435f2ef484696560547fbc1325cb97c7174bChad Versace      printf("    --%s\n", o->name);
1357819435f2ef484696560547fbc1325cb97c7174bChad Versace   }
1367819435f2ef484696560547fbc1325cb97c7174bChad Versace   exit(EXIT_FAILURE);
1377819435f2ef484696560547fbc1325cb97c7174bChad Versace}
1387819435f2ef484696560547fbc1325cb97c7174bChad Versace
1397819435f2ef484696560547fbc1325cb97c7174bChad Versace
1408ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanickvoid
141f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergcompile_shader(struct gl_context *ctx, struct gl_shader *shader)
14261d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick{
143aa9f86ae8b3bb2172092ff9b50751677c509e6b4Kenneth Graunke   struct _mesa_glsl_parse_state *state =
144dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
145f8946699ecfa5bc6566821fb855072bbdbd716b2Eric Anholt
14604ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke   const char *source = shader->Source;
1477cfd42cefe1949af51ecced9891f415eca2c0e66Dave Airlie   state->error = glcpp_preprocess(state, &source, &state->info_log,
148d42acef139740a54fe571f99b62cba7720734d8cBrian Paul			     state->extensions, ctx->API) != 0;
14904ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke
1502d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth   if (!state->error) {
1512d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth      _mesa_glsl_lexer_ctor(state, source);
1522d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth      _mesa_glsl_parse(state);
1532d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth      _mesa_glsl_lexer_dtor(state);
15404ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke   }
15554992c30b00b13232641b5d2b6479f005a60abfdIan Romanick
1567babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick   if (dump_ast) {
1572d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth      foreach_list_const(n, &state->translation_unit) {
1587babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick	 ast_node *ast = exec_node_data(ast_node, n, link);
1597babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick	 ast->print();
1607babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick      }
1617babbdbd82701147e50a5296dd215376b7ec7da8Ian Romanick      printf("\n\n");
16261d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick   }
16361d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
16416b68b1952d0da14b9ce8306efa64988ce46b4b7Eric Anholt   shader->ir = new(shader) exec_list;
1652d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth   if (!state->error && !state->translation_unit.is_empty())
16616b68b1952d0da14b9ce8306efa64988ce46b4b7Eric Anholt      _mesa_ast_to_hir(shader->ir, state);
16754992c30b00b13232641b5d2b6479f005a60abfdIan Romanick
16822c23dedad4e7f362ffbd990f1c2d5caf4cae75aIan Romanick   /* Print out the unoptimized IR. */
16922c23dedad4e7f362ffbd990f1c2d5caf4cae75aIan Romanick   if (!state->error && dump_hir) {
1705a2e0b8ce59a3d9f8fa7510546137aff40016c74Ian Romanick      validate_ir_tree(shader->ir);
17116b68b1952d0da14b9ce8306efa64988ce46b4b7Eric Anholt      _mesa_print_ir(shader->ir, state);
17222c23dedad4e7f362ffbd990f1c2d5caf4cae75aIan Romanick   }
17322c23dedad4e7f362ffbd990f1c2d5caf4cae75aIan Romanick
17461d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick   /* Optimization passes */
17516b68b1952d0da14b9ce8306efa64988ce46b4b7Eric Anholt   if (!state->error && !shader->ir->is_empty()) {
17661d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick      bool progress;
17761d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick      do {
1781d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick	 progress = do_common_optimization(shader->ir, false, false, 32);
17961d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick      } while (progress);
1805a2e0b8ce59a3d9f8fa7510546137aff40016c74Ian Romanick
1815a2e0b8ce59a3d9f8fa7510546137aff40016c74Ian Romanick      validate_ir_tree(shader->ir);
18261d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick   }
18361d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
18453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
18561d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick   /* Print out the resulting IR */
1862d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth   if (!state->error && dump_lir) {
18716b68b1952d0da14b9ce8306efa64988ce46b4b7Eric Anholt      _mesa_print_ir(shader->ir, state);
18861d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick   }
18961d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
1902d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth   shader->symbols = state->symbols;
1912d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth   shader->CompileStatus = !state->error;
19225f51d3b9b8c36c41cd23d2797b6a06f6e27ff86Ian Romanick   shader->Version = state->language_version;
193d5be2acae379783c4aa31243e0a88a9e67e6ca7eIan Romanick   memcpy(shader->builtins_to_link, state->builtins_to_link,
194d5be2acae379783c4aa31243e0a88a9e67e6ca7eIan Romanick	  sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
195d5be2acae379783c4aa31243e0a88a9e67e6ca7eIan Romanick   shader->num_builtins_to_link = state->num_builtins_to_link;
196ca97bd395f476ad2b5a009f92edef4656aab3650Ian Romanick
197ca97bd395f476ad2b5a009f92edef4656aab3650Ian Romanick   if (shader->InfoLog)
198d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      ralloc_free(shader->InfoLog);
199ca97bd395f476ad2b5a009f92edef4656aab3650Ian Romanick
2002d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth   shader->InfoLog = state->info_log;
2012d2561ef9696aa5ff0c1a85e3a4a95475f927935Carl Worth
202116f1d4f95d8eb0a82b272016590549632c865b3Kenneth Graunke   /* Retain any live IR, but trash the rest. */
20360e2d06d1ccc66ad00cd7ab81c418853f21be291Ian Romanick   reparent_ir(shader->ir, shader);
204116f1d4f95d8eb0a82b272016590549632c865b3Kenneth Graunke
205d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   ralloc_free(state);
206ca97bd395f476ad2b5a009f92edef4656aab3650Ian Romanick
2078ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick   return;
2088ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick}
2098ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
2108ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanickint
2118ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanickmain(int argc, char **argv)
2128ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick{
2136fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick   int status = EXIT_SUCCESS;
214f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context local_ctx;
215f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = &local_ctx;
2165d0f430e8ed01db29d11d22e4b6c3760d8c39f8fEric Anholt
2178ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick   int c;
2188ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick   int idx = 0;
2198ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
2208ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick      /* empty */ ;
2218ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
2228ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
2238ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick   if (argc <= optind)
2248ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick      usage_fail(argv[0]);
2258ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
2261a5b32ca0198488e7d616c8cd968471166a97ef3Chia-I Wu   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL);
227dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu
228849e18153cd91d812f694b806a84008498860bc3Eric Anholt   struct gl_shader_program *whole_program;
229be83eb8671e7789cbe5ca1fc8d3f5d133e2e7014Carl Worth
230d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   whole_program = rzalloc (NULL, struct gl_shader_program);
231be83eb8671e7789cbe5ca1fc8d3f5d133e2e7014Carl Worth   assert(whole_program != NULL);
23289193933cbd322cd08fb54232411a8a9221fcca8Ian Romanick   whole_program->InfoLog = ralloc_strdup(whole_program, "");
2338ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
2346fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick   for (/* empty */; argc > optind; optind++) {
235d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      whole_program->Shaders =
236d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke	 reralloc(whole_program, whole_program->Shaders,
237d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke		  struct gl_shader *, whole_program->NumShaders + 1);
238be83eb8671e7789cbe5ca1fc8d3f5d133e2e7014Carl Worth      assert(whole_program->Shaders != NULL);
2398ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
240d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      struct gl_shader *shader = rzalloc(whole_program, gl_shader);
2416fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick
242be83eb8671e7789cbe5ca1fc8d3f5d133e2e7014Carl Worth      whole_program->Shaders[whole_program->NumShaders] = shader;
243be83eb8671e7789cbe5ca1fc8d3f5d133e2e7014Carl Worth      whole_program->NumShaders++;
2446fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick
2456fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick      const unsigned len = strlen(argv[optind]);
2466fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick      if (len < 6)
2476fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick	 usage_fail(argv[0]);
2488ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
2496fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick      const char *const ext = & argv[optind][len - 5];
2507e35d97a02cf139746ce9e85b78fe0c651139074Kenneth Graunke      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
25129e60874812ae323780cfab67b8b1365059ff4b2Kenneth Graunke	 shader->Type = GL_VERTEX_SHADER;
2526fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick      else if (strncmp(".geom", ext, 5) == 0)
25329e60874812ae323780cfab67b8b1365059ff4b2Kenneth Graunke	 shader->Type = GL_GEOMETRY_SHADER;
2546fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick      else if (strncmp(".frag", ext, 5) == 0)
25529e60874812ae323780cfab67b8b1365059ff4b2Kenneth Graunke	 shader->Type = GL_FRAGMENT_SHADER;
2566fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick      else
2576fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick	 usage_fail(argv[0]);
2588ce55dbd9207ff4338588dcba155f1a754dc8f19Ian Romanick
25916b68b1952d0da14b9ce8306efa64988ce46b4b7Eric Anholt      shader->Source = load_text_file(whole_program, argv[optind]);
2602848c4c183ea0aaca2ca0a23a13196c786403a5cKenneth Graunke      if (shader->Source == NULL) {
2612848c4c183ea0aaca2ca0a23a13196c786403a5cKenneth Graunke	 printf("File \"%s\" does not exist.\n", argv[optind]);
2622848c4c183ea0aaca2ca0a23a13196c786403a5cKenneth Graunke	 exit(EXIT_FAILURE);
2632848c4c183ea0aaca2ca0a23a13196c786403a5cKenneth Graunke      }
2646fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick
265dc754586ca84741b4df5b72fd235c4134816854cChia-I Wu      compile_shader(ctx, shader);
2666fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick
26729e60874812ae323780cfab67b8b1365059ff4b2Kenneth Graunke      if (!shader->CompileStatus) {
268f3eb42d200bb78afae64af6862e2b12396226707Kenneth Graunke	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
2696fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick	 status = EXIT_FAILURE;
2706fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick	 break;
2716fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick      }
2726fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick   }
27361d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick
274c648a124b20c5e37cf4041062333fc177a65f997Ian Romanick   if ((status == EXIT_SUCCESS) && do_link)  {
2755d0f430e8ed01db29d11d22e4b6c3760d8c39f8fEric Anholt      link_shaders(ctx, whole_program);
276be83eb8671e7789cbe5ca1fc8d3f5d133e2e7014Carl Worth      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
2774d962e66e319191d5b94291b6f55d720df71130aIan Romanick
2784d962e66e319191d5b94291b6f55d720df71130aIan Romanick      if (strlen(whole_program->InfoLog) > 0)
2794d962e66e319191d5b94291b6f55d720df71130aIan Romanick	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
280832dfa58b2070d60111bc1997aea86228f630e75Ian Romanick   }
281832dfa58b2070d60111bc1997aea86228f630e75Ian Romanick
2823322fbaf3b5e305ce00c1d08c26965bb98e0cef0Ian Romanick   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
283d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      ralloc_free(whole_program->_LinkedShaders[i]);
2843fb878722ed53d79eedb9fe68972ef32b79575d4Ian Romanick
285d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   ralloc_free(whole_program);
286efc15f862b08a9f035c06a79bc43848cca740372Ian Romanick   _mesa_glsl_release_types();
287d5be2acae379783c4aa31243e0a88a9e67e6ca7eIan Romanick   _mesa_glsl_release_functions();
288be83eb8671e7789cbe5ca1fc8d3f5d133e2e7014Carl Worth
2896fd9fb23de908ec52089fdc6e24af9e2ebbe126eIan Romanick   return status;
29061d4aa041f800429127aab3263c50cbc6e69ae50Ian Romanick}
291