Home | History | Annotate | Download | only in glsl
      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 <stdio.h>
     24 #include <stdarg.h>
     25 #include <string.h>
     26 #include <assert.h>
     27 
     28 extern "C" {
     29 #include <hieralloc.h>
     30 #include "main/core.h" /* for struct gl_context */
     31 }
     32 
     33 #include "ast.h"
     34 #include "glsl_parser_extras.h"
     35 #include "glsl_parser.h"
     36 #include "ir_optimization.h"
     37 #include "loop_analysis.h"
     38 
     39 _mesa_glsl_parse_state::_mesa_glsl_parse_state(const struct gl_context *ctx,
     40 					       GLenum target, void *mem_ctx)
     41 {
     42    switch (target) {
     43    case GL_VERTEX_SHADER:   this->target = vertex_shader; break;
     44    case GL_FRAGMENT_SHADER: this->target = fragment_shader; break;
     45    case GL_GEOMETRY_SHADER: this->target = geometry_shader; break;
     46    }
     47 
     48    this->scanner = NULL;
     49    this->translation_unit.make_empty();
     50    this->symbols = new(mem_ctx) glsl_symbol_table(mem_ctx);
     51    this->info_log = hieralloc_strdup(mem_ctx, "");
     52    this->error = false;
     53    this->loop_or_switch_nesting = NULL;
     54 
     55    /* Set default language version and extensions */
     56    this->language_version = 110;
     57    this->es_shader = false;
     58    this->ARB_texture_rectangle_enable = true;
     59 
     60    /* OpenGL ES 2.0 has different defaults from desktop GL. */
     61    if (ctx->API == API_OPENGLES2) {
     62       this->language_version = 120;
     63       this->es_shader = true;
     64       this->ARB_texture_rectangle_enable = false;
     65    }
     66 
     67    this->extensions = &ctx->Extensions;
     68 
     69    this->Const.MaxLights = ctx->Const.MaxLights;
     70    this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
     71    this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;
     72    this->Const.MaxTextureCoords = ctx->Const.MaxTextureCoordUnits;
     73    this->Const.MaxVertexAttribs = ctx->Const.VertexProgram.MaxAttribs;
     74    this->Const.MaxVertexUniformComponents = ctx->Const.VertexProgram.MaxUniformComponents;
     75    this->Const.MaxVaryingFloats = ctx->Const.MaxVarying * 4;
     76    this->Const.MaxVertexTextureImageUnits = ctx->Const.MaxVertexTextureImageUnits;
     77    this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits;
     78    this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
     79    this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
     80 
     81    this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
     82 }
     83 
     84 const char *
     85 _mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
     86 {
     87    switch (target) {
     88    case vertex_shader:   return "vertex";
     89    case fragment_shader: return "fragment";
     90    case geometry_shader: return "geometry";
     91    }
     92 
     93    assert(!"Should not get here.");
     94    return "unknown";
     95 }
     96 
     97 
     98 void
     99 _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
    100 		 const char *fmt, ...)
    101 {
    102    va_list ap;
    103 
    104    state->error = true;
    105 
    106    assert(state->info_log != NULL);
    107    state->info_log = hieralloc_asprintf_append(state->info_log,
    108 					    "%u:%u(%u): error: ",
    109 					    locp->source,
    110 					    locp->first_line,
    111 					    locp->first_column);
    112    va_start(ap, fmt);
    113    state->info_log = hieralloc_vasprintf_append(state->info_log, fmt, ap);
    114    va_end(ap);
    115    state->info_log = hieralloc_strdup_append(state->info_log, "\n");
    116 }
    117 
    118 
    119 void
    120 _mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
    121 		   const char *fmt, ...)
    122 {
    123    va_list ap;
    124 
    125    assert(state->info_log != NULL);
    126    state->info_log = hieralloc_asprintf_append(state->info_log,
    127 					    "%u:%u(%u): warning: ",
    128 					    locp->source,
    129 					    locp->first_line,
    130 					    locp->first_column);
    131    va_start(ap, fmt);
    132    state->info_log = hieralloc_vasprintf_append(state->info_log, fmt, ap);
    133    va_end(ap);
    134    state->info_log = hieralloc_strdup_append(state->info_log, "\n");
    135 }
    136 
    137 
    138 bool
    139 _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
    140 			     const char *behavior, YYLTYPE *behavior_locp,
    141 			     _mesa_glsl_parse_state *state)
    142 {
    143    enum {
    144       extension_disable,
    145       extension_enable,
    146       extension_require,
    147       extension_warn
    148    } ext_mode;
    149 
    150    if (strcmp(behavior, "warn") == 0) {
    151       ext_mode = extension_warn;
    152    } else if (strcmp(behavior, "require") == 0) {
    153       ext_mode = extension_require;
    154    } else if (strcmp(behavior, "enable") == 0) {
    155       ext_mode = extension_enable;
    156    } else if (strcmp(behavior, "disable") == 0) {
    157       ext_mode = extension_disable;
    158    } else {
    159       _mesa_glsl_error(behavior_locp, state,
    160 		       "Unknown extension behavior `%s'",
    161 		       behavior);
    162       return false;
    163    }
    164 
    165    bool unsupported = false;
    166 
    167    if (strcmp(name, "all") == 0) {
    168       if ((ext_mode == extension_enable) || (ext_mode == extension_require)) {
    169 	 _mesa_glsl_error(name_locp, state, "Cannot %s all extensions",
    170 			  (ext_mode == extension_enable)
    171 			  ? "enable" : "require");
    172 	 return false;
    173       }
    174    } else if (strcmp(name, "GL_ARB_draw_buffers") == 0) {
    175       /* This extension is only supported in fragment shaders.
    176        */
    177       if (state->target != fragment_shader) {
    178 	 unsupported = true;
    179       } else {
    180 	 state->ARB_draw_buffers_enable = (ext_mode != extension_disable);
    181 	 state->ARB_draw_buffers_warn = (ext_mode == extension_warn);
    182       }
    183    } else if (strcmp(name, "GL_ARB_explicit_attrib_location") == 0) {
    184       state->ARB_explicit_attrib_location_enable =
    185 	 (ext_mode != extension_disable);
    186       state->ARB_explicit_attrib_location_warn =
    187 	 (ext_mode == extension_warn);
    188 
    189       unsupported = !state->extensions->ARB_explicit_attrib_location;
    190    } else if (strcmp(name, "GL_ARB_fragment_coord_conventions") == 0) {
    191       state->ARB_fragment_coord_conventions_enable =
    192 	 (ext_mode != extension_disable);
    193       state->ARB_fragment_coord_conventions_warn =
    194 	 (ext_mode == extension_warn);
    195 
    196       unsupported = !state->extensions->ARB_fragment_coord_conventions;
    197    } else if (strcmp(name, "GL_ARB_texture_rectangle") == 0) {
    198       state->ARB_texture_rectangle_enable = (ext_mode != extension_disable);
    199       state->ARB_texture_rectangle_warn = (ext_mode == extension_warn);
    200    } else if (strcmp(name, "GL_EXT_texture_array") == 0) {
    201       state->EXT_texture_array_enable = (ext_mode != extension_disable);
    202       state->EXT_texture_array_warn = (ext_mode == extension_warn);
    203 
    204       unsupported = !state->extensions->EXT_texture_array;
    205    } else if (strcmp(name, "GL_ARB_shader_stencil_export") == 0) {
    206       if (state->target != fragment_shader) {
    207 	 unsupported = true;
    208       } else {
    209 	 state->ARB_shader_stencil_export_enable = (ext_mode != extension_disable);
    210 	 state->ARB_shader_stencil_export_warn = (ext_mode == extension_warn);
    211 	 unsupported = !state->extensions->ARB_shader_stencil_export;
    212       }
    213    } else {
    214       unsupported = true;
    215    }
    216 
    217    if (unsupported) {
    218       static const char *const fmt = "extension `%s' unsupported in %s shader";
    219 
    220       if (ext_mode == extension_require) {
    221 	 _mesa_glsl_error(name_locp, state, fmt,
    222 			  name, _mesa_glsl_shader_target_name(state->target));
    223 	 return false;
    224       } else {
    225 	 _mesa_glsl_warning(name_locp, state, fmt,
    226 			    name, _mesa_glsl_shader_target_name(state->target));
    227       }
    228    }
    229 
    230    return true;
    231 }
    232 
    233 void
    234 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
    235 {
    236    if (q->flags.q.constant)
    237       printf("const ");
    238 
    239    if (q->flags.q.invariant)
    240       printf("invariant ");
    241 
    242    if (q->flags.q.attribute)
    243       printf("attribute ");
    244 
    245    if (q->flags.q.varying)
    246       printf("varying ");
    247 
    248    if (q->flags.q.in && q->flags.q.out)
    249       printf("inout ");
    250    else {
    251       if (q->flags.q.in)
    252 	 printf("in ");
    253 
    254       if (q->flags.q.out)
    255 	 printf("out ");
    256    }
    257 
    258    if (q->flags.q.centroid)
    259       printf("centroid ");
    260    if (q->flags.q.uniform)
    261       printf("uniform ");
    262    if (q->flags.q.smooth)
    263       printf("smooth ");
    264    if (q->flags.q.flat)
    265       printf("flat ");
    266    if (q->flags.q.noperspective)
    267       printf("noperspective ");
    268 }
    269 
    270 
    271 void
    272 ast_node::print(void) const
    273 {
    274    printf("unhandled node ");
    275 }
    276 
    277 
    278 ast_node::ast_node(void)
    279 {
    280    this->location.source = 0;
    281    this->location.line = 0;
    282    this->location.column = 0;
    283 }
    284 
    285 
    286 static void
    287 ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
    288 {
    289    if (is_array) {
    290       printf("[ ");
    291 
    292       if (array_size)
    293 	 array_size->print();
    294 
    295       printf("] ");
    296    }
    297 }
    298 
    299 
    300 void
    301 ast_compound_statement::print(void) const
    302 {
    303    printf("{\n");
    304 
    305    foreach_list_const(n, &this->statements) {
    306       ast_node *ast = exec_node_data(ast_node, n, link);
    307       ast->print();
    308    }
    309 
    310    printf("}\n");
    311 }
    312 
    313 
    314 ast_compound_statement::ast_compound_statement(int new_scope,
    315 					       ast_node *statements)
    316 {
    317    this->new_scope = new_scope;
    318 
    319    if (statements != NULL) {
    320       this->statements.push_degenerate_list_at_head(&statements->link);
    321    }
    322 }
    323 
    324 
    325 void
    326 ast_expression::print(void) const
    327 {
    328    switch (oper) {
    329    case ast_assign:
    330    case ast_mul_assign:
    331    case ast_div_assign:
    332    case ast_mod_assign:
    333    case ast_add_assign:
    334    case ast_sub_assign:
    335    case ast_ls_assign:
    336    case ast_rs_assign:
    337    case ast_and_assign:
    338    case ast_xor_assign:
    339    case ast_or_assign:
    340       subexpressions[0]->print();
    341       printf("%s ", operator_string(oper));
    342       subexpressions[1]->print();
    343       break;
    344 
    345    case ast_field_selection:
    346       subexpressions[0]->print();
    347       printf(". %s ", primary_expression.identifier);
    348       break;
    349 
    350    case ast_plus:
    351    case ast_neg:
    352    case ast_bit_not:
    353    case ast_logic_not:
    354    case ast_pre_inc:
    355    case ast_pre_dec:
    356       printf("%s ", operator_string(oper));
    357       subexpressions[0]->print();
    358       break;
    359 
    360    case ast_post_inc:
    361    case ast_post_dec:
    362       subexpressions[0]->print();
    363       printf("%s ", operator_string(oper));
    364       break;
    365 
    366    case ast_conditional:
    367       subexpressions[0]->print();
    368       printf("? ");
    369       subexpressions[1]->print();
    370       printf(": ");
    371       subexpressions[1]->print();
    372       break;
    373 
    374    case ast_array_index:
    375       subexpressions[0]->print();
    376       printf("[ ");
    377       subexpressions[1]->print();
    378       printf("] ");
    379       break;
    380 
    381    case ast_function_call: {
    382       subexpressions[0]->print();
    383       printf("( ");
    384 
    385       foreach_list_const (n, &this->expressions) {
    386 	 if (n != this->expressions.get_head())
    387 	    printf(", ");
    388 
    389 	 ast_node *ast = exec_node_data(ast_node, n, link);
    390 	 ast->print();
    391       }
    392 
    393       printf(") ");
    394       break;
    395    }
    396 
    397    case ast_identifier:
    398       printf("%s ", primary_expression.identifier);
    399       break;
    400 
    401    case ast_int_constant:
    402       printf("%d ", primary_expression.int_constant);
    403       break;
    404 
    405    case ast_uint_constant:
    406       printf("%u ", primary_expression.uint_constant);
    407       break;
    408 
    409    case ast_float_constant:
    410       printf("%f ", primary_expression.float_constant);
    411       break;
    412 
    413    case ast_bool_constant:
    414       printf("%s ",
    415 	     primary_expression.bool_constant
    416 	     ? "true" : "false");
    417       break;
    418 
    419    case ast_sequence: {
    420       printf("( ");
    421       foreach_list_const(n, & this->expressions) {
    422 	 if (n != this->expressions.get_head())
    423 	    printf(", ");
    424 
    425 	 ast_node *ast = exec_node_data(ast_node, n, link);
    426 	 ast->print();
    427       }
    428       printf(") ");
    429       break;
    430    }
    431 
    432    default:
    433       assert(0);
    434       break;
    435    }
    436 }
    437 
    438 ast_expression::ast_expression(int oper,
    439 			       ast_expression *ex0,
    440 			       ast_expression *ex1,
    441 			       ast_expression *ex2)
    442 {
    443    this->oper = ast_operators(oper);
    444    this->subexpressions[0] = ex0;
    445    this->subexpressions[1] = ex1;
    446    this->subexpressions[2] = ex2;
    447 }
    448 
    449 
    450 void
    451 ast_expression_statement::print(void) const
    452 {
    453    if (expression)
    454       expression->print();
    455 
    456    printf("; ");
    457 }
    458 
    459 
    460 ast_expression_statement::ast_expression_statement(ast_expression *ex) :
    461    expression(ex)
    462 {
    463    /* empty */
    464 }
    465 
    466 
    467 void
    468 ast_function::print(void) const
    469 {
    470    return_type->print();
    471    printf(" %s (", identifier);
    472 
    473    foreach_list_const(n, & this->parameters) {
    474       ast_node *ast = exec_node_data(ast_node, n, link);
    475       ast->print();
    476    }
    477 
    478    printf(")");
    479 }
    480 
    481 
    482 ast_function::ast_function(void)
    483    : is_definition(false), signature(NULL)
    484 {
    485    /* empty */
    486 }
    487 
    488 
    489 void
    490 ast_fully_specified_type::print(void) const
    491 {
    492    _mesa_ast_type_qualifier_print(& qualifier);
    493    specifier->print();
    494 }
    495 
    496 
    497 void
    498 ast_parameter_declarator::print(void) const
    499 {
    500    type->print();
    501    if (identifier)
    502       printf("%s ", identifier);
    503    ast_opt_array_size_print(is_array, array_size);
    504 }
    505 
    506 
    507 void
    508 ast_function_definition::print(void) const
    509 {
    510    prototype->print();
    511    body->print();
    512 }
    513 
    514 
    515 void
    516 ast_declaration::print(void) const
    517 {
    518    printf("%s ", identifier);
    519    ast_opt_array_size_print(is_array, array_size);
    520 
    521    if (initializer) {
    522       printf("= ");
    523       initializer->print();
    524    }
    525 }
    526 
    527 
    528 ast_declaration::ast_declaration(char *identifier, int is_array,
    529 				 ast_expression *array_size,
    530 				 ast_expression *initializer)
    531 {
    532    this->identifier = identifier;
    533    this->is_array = is_array;
    534    this->array_size = array_size;
    535    this->initializer = initializer;
    536 }
    537 
    538 
    539 void
    540 ast_declarator_list::print(void) const
    541 {
    542    assert(type || invariant);
    543 
    544    if (type)
    545       type->print();
    546    else
    547       printf("invariant ");
    548 
    549    foreach_list_const (ptr, & this->declarations) {
    550       if (ptr != this->declarations.get_head())
    551 	 printf(", ");
    552 
    553       ast_node *ast = exec_node_data(ast_node, ptr, link);
    554       ast->print();
    555    }
    556 
    557    printf("; ");
    558 }
    559 
    560 
    561 ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
    562 {
    563    this->type = type;
    564    this->invariant = false;
    565 }
    566 
    567 void
    568 ast_jump_statement::print(void) const
    569 {
    570    switch (mode) {
    571    case ast_continue:
    572       printf("continue; ");
    573       break;
    574    case ast_break:
    575       printf("break; ");
    576       break;
    577    case ast_return:
    578       printf("return ");
    579       if (opt_return_value)
    580 	 opt_return_value->print();
    581 
    582       printf("; ");
    583       break;
    584    case ast_discard:
    585       printf("discard; ");
    586       break;
    587    }
    588 }
    589 
    590 
    591 ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
    592 {
    593    this->mode = ast_jump_modes(mode);
    594 
    595    if (mode == ast_return)
    596       opt_return_value = return_value;
    597 }
    598 
    599 
    600 void
    601 ast_selection_statement::print(void) const
    602 {
    603    printf("if ( ");
    604    condition->print();
    605    printf(") ");
    606 
    607    then_statement->print();
    608 
    609    if (else_statement) {
    610       printf("else ");
    611       else_statement->print();
    612    }
    613 
    614 }
    615 
    616 
    617 ast_selection_statement::ast_selection_statement(ast_expression *condition,
    618 						 ast_node *then_statement,
    619 						 ast_node *else_statement)
    620 {
    621    this->condition = condition;
    622    this->then_statement = then_statement;
    623    this->else_statement = else_statement;
    624 }
    625 
    626 
    627 void
    628 ast_iteration_statement::print(void) const
    629 {
    630    switch (mode) {
    631    case ast_for:
    632       printf("for( ");
    633       if (init_statement)
    634 	 init_statement->print();
    635       printf("; ");
    636 
    637       if (condition)
    638 	 condition->print();
    639       printf("; ");
    640 
    641       if (rest_expression)
    642 	 rest_expression->print();
    643       printf(") ");
    644 
    645       body->print();
    646       break;
    647 
    648    case ast_while:
    649       printf("while ( ");
    650       if (condition)
    651 	 condition->print();
    652       printf(") ");
    653       body->print();
    654       break;
    655 
    656    case ast_do_while:
    657       printf("do ");
    658       body->print();
    659       printf("while ( ");
    660       if (condition)
    661 	 condition->print();
    662       printf("); ");
    663       break;
    664    }
    665 }
    666 
    667 
    668 ast_iteration_statement::ast_iteration_statement(int mode,
    669 						 ast_node *init,
    670 						 ast_node *condition,
    671 						 ast_expression *rest_expression,
    672 						 ast_node *body)
    673 {
    674    this->mode = ast_iteration_modes(mode);
    675    this->init_statement = init;
    676    this->condition = condition;
    677    this->rest_expression = rest_expression;
    678    this->body = body;
    679 }
    680 
    681 
    682 void
    683 ast_struct_specifier::print(void) const
    684 {
    685    printf("struct %s { ", name);
    686    foreach_list_const(n, &this->declarations) {
    687       ast_node *ast = exec_node_data(ast_node, n, link);
    688       ast->print();
    689    }
    690    printf("} ");
    691 }
    692 
    693 
    694 ast_struct_specifier::ast_struct_specifier(char *identifier,
    695 					   ast_node *declarator_list)
    696 {
    697    if (identifier == NULL) {
    698       static unsigned anon_count = 1;
    699       identifier = hieralloc_asprintf(this, "#anon_struct_%04x", anon_count);
    700       anon_count++;
    701    }
    702    name = identifier;
    703    this->declarations.push_degenerate_list_at_head(&declarator_list->link);
    704 }
    705 
    706 bool
    707 do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations)
    708 {
    709    GLboolean progress = GL_FALSE;
    710 
    711    progress = lower_instructions(ir, SUB_TO_ADD_NEG) || progress;
    712 
    713    if (linked) {
    714       progress = do_function_inlining(ir) || progress;
    715       progress = do_dead_functions(ir) || progress;
    716    }
    717    progress = do_structure_splitting(ir) || progress;
    718    progress = do_if_simplification(ir) || progress;
    719    progress = do_discard_simplification(ir) || progress;
    720    progress = do_copy_propagation(ir) || progress;
    721    if (linked)
    722       progress = do_dead_code(ir) || progress;
    723    else
    724       progress = do_dead_code_unlinked(ir) || progress;
    725    progress = do_dead_code_local(ir) || progress;
    726    progress = do_tree_grafting(ir) || progress;
    727    progress = do_constant_propagation(ir) || progress;
    728    if (linked)
    729       progress = do_constant_variable(ir) || progress;
    730    else
    731       progress = do_constant_variable_unlinked(ir) || progress;
    732    progress = do_constant_folding(ir) || progress;
    733    progress = do_algebraic(ir) || progress;
    734    progress = do_lower_jumps(ir) || progress;
    735    progress = do_vec_index_to_swizzle(ir) || progress;
    736    progress = do_swizzle_swizzle(ir) || progress;
    737    progress = do_noop_swizzle(ir) || progress;
    738 
    739    progress = optimize_redundant_jumps(ir) || progress;
    740 
    741    loop_state *ls = analyze_loop_variables(ir);
    742    progress = set_loop_controls(ir, ls) || progress;
    743    progress = unroll_loops(ir, ls, max_unroll_iterations) || progress;
    744    delete ls;
    745 
    746    return progress;
    747 }
    748 
    749 extern "C" {
    750 
    751 /**
    752  * To be called at GL teardown time, this frees compiler datastructures.
    753  *
    754  * After calling this, any previously compiled shaders and shader
    755  * programs would be invalid.  So this should happen at approximately
    756  * program exit.
    757  */
    758 void
    759 _mesa_destroy_shader_compiler(void)
    760 {
    761    _mesa_destroy_shader_compiler_caches();
    762 
    763    _mesa_glsl_release_types();
    764 }
    765 
    766 /**
    767  * Releases compiler caches to trade off performance for memory.
    768  *
    769  * Intended to be used with glReleaseShaderCompiler().
    770  */
    771 void
    772 _mesa_destroy_shader_compiler_caches(void)
    773 {
    774    _mesa_glsl_release_functions();
    775 }
    776 
    777 }
    778