101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2010 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2101e04c3fSmrg * DEALINGS IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include "ir_reader.h" 2501e04c3fSmrg#include "glsl_parser_extras.h" 2601e04c3fSmrg#include "compiler/glsl_types.h" 2701e04c3fSmrg#include "s_expression.h" 2801e04c3fSmrg 2901e04c3fSmrgstatic const bool debug = false; 3001e04c3fSmrg 3101e04c3fSmrgnamespace { 3201e04c3fSmrg 3301e04c3fSmrgclass ir_reader { 3401e04c3fSmrgpublic: 3501e04c3fSmrg ir_reader(_mesa_glsl_parse_state *); 3601e04c3fSmrg 3701e04c3fSmrg void read(exec_list *instructions, const char *src, bool scan_for_protos); 3801e04c3fSmrg 3901e04c3fSmrgprivate: 4001e04c3fSmrg void *mem_ctx; 4101e04c3fSmrg _mesa_glsl_parse_state *state; 4201e04c3fSmrg 4301e04c3fSmrg void ir_read_error(s_expression *, const char *fmt, ...); 4401e04c3fSmrg 4501e04c3fSmrg const glsl_type *read_type(s_expression *); 4601e04c3fSmrg 4701e04c3fSmrg void scan_for_prototypes(exec_list *, s_expression *); 4801e04c3fSmrg ir_function *read_function(s_expression *, bool skip_body); 4901e04c3fSmrg void read_function_sig(ir_function *, s_expression *, bool skip_body); 5001e04c3fSmrg 5101e04c3fSmrg void read_instructions(exec_list *, s_expression *, ir_loop *); 5201e04c3fSmrg ir_instruction *read_instruction(s_expression *, ir_loop *); 5301e04c3fSmrg ir_variable *read_declaration(s_expression *); 5401e04c3fSmrg ir_if *read_if(s_expression *, ir_loop *); 5501e04c3fSmrg ir_loop *read_loop(s_expression *); 5601e04c3fSmrg ir_call *read_call(s_expression *); 5701e04c3fSmrg ir_return *read_return(s_expression *); 5801e04c3fSmrg ir_rvalue *read_rvalue(s_expression *); 5901e04c3fSmrg ir_assignment *read_assignment(s_expression *); 6001e04c3fSmrg ir_expression *read_expression(s_expression *); 6101e04c3fSmrg ir_swizzle *read_swizzle(s_expression *); 6201e04c3fSmrg ir_constant *read_constant(s_expression *); 6301e04c3fSmrg ir_texture *read_texture(s_expression *); 6401e04c3fSmrg ir_emit_vertex *read_emit_vertex(s_expression *); 6501e04c3fSmrg ir_end_primitive *read_end_primitive(s_expression *); 6601e04c3fSmrg ir_barrier *read_barrier(s_expression *); 6701e04c3fSmrg 6801e04c3fSmrg ir_dereference *read_dereference(s_expression *); 6901e04c3fSmrg ir_dereference_variable *read_var_ref(s_expression *); 7001e04c3fSmrg}; 7101e04c3fSmrg 7201e04c3fSmrg} /* anonymous namespace */ 7301e04c3fSmrg 7401e04c3fSmrgir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state) 7501e04c3fSmrg{ 7601e04c3fSmrg this->mem_ctx = state; 7701e04c3fSmrg} 7801e04c3fSmrg 7901e04c3fSmrgvoid 8001e04c3fSmrg_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions, 8101e04c3fSmrg const char *src, bool scan_for_protos) 8201e04c3fSmrg{ 8301e04c3fSmrg ir_reader r(state); 8401e04c3fSmrg r.read(instructions, src, scan_for_protos); 8501e04c3fSmrg} 8601e04c3fSmrg 8701e04c3fSmrgvoid 8801e04c3fSmrgir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos) 8901e04c3fSmrg{ 9001e04c3fSmrg void *sx_mem_ctx = ralloc_context(NULL); 9101e04c3fSmrg s_expression *expr = s_expression::read_expression(sx_mem_ctx, src); 9201e04c3fSmrg if (expr == NULL) { 9301e04c3fSmrg ir_read_error(NULL, "couldn't parse S-Expression."); 9401e04c3fSmrg return; 9501e04c3fSmrg } 9601e04c3fSmrg 9701e04c3fSmrg if (scan_for_protos) { 9801e04c3fSmrg scan_for_prototypes(instructions, expr); 9901e04c3fSmrg if (state->error) 10001e04c3fSmrg return; 10101e04c3fSmrg } 10201e04c3fSmrg 10301e04c3fSmrg read_instructions(instructions, expr, NULL); 10401e04c3fSmrg ralloc_free(sx_mem_ctx); 10501e04c3fSmrg 10601e04c3fSmrg if (debug) 10701e04c3fSmrg validate_ir_tree(instructions); 10801e04c3fSmrg} 10901e04c3fSmrg 11001e04c3fSmrgvoid 11101e04c3fSmrgir_reader::ir_read_error(s_expression *expr, const char *fmt, ...) 11201e04c3fSmrg{ 11301e04c3fSmrg va_list ap; 11401e04c3fSmrg 11501e04c3fSmrg state->error = true; 11601e04c3fSmrg 11701e04c3fSmrg if (state->current_function != NULL) 11801e04c3fSmrg ralloc_asprintf_append(&state->info_log, "In function %s:\n", 11901e04c3fSmrg state->current_function->function_name()); 12001e04c3fSmrg ralloc_strcat(&state->info_log, "error: "); 12101e04c3fSmrg 12201e04c3fSmrg va_start(ap, fmt); 12301e04c3fSmrg ralloc_vasprintf_append(&state->info_log, fmt, ap); 12401e04c3fSmrg va_end(ap); 12501e04c3fSmrg ralloc_strcat(&state->info_log, "\n"); 12601e04c3fSmrg 12701e04c3fSmrg if (expr != NULL) { 12801e04c3fSmrg ralloc_strcat(&state->info_log, "...in this context:\n "); 12901e04c3fSmrg expr->print(); 13001e04c3fSmrg ralloc_strcat(&state->info_log, "\n\n"); 13101e04c3fSmrg } 13201e04c3fSmrg} 13301e04c3fSmrg 13401e04c3fSmrgconst glsl_type * 13501e04c3fSmrgir_reader::read_type(s_expression *expr) 13601e04c3fSmrg{ 13701e04c3fSmrg s_expression *s_base_type; 13801e04c3fSmrg s_int *s_size; 13901e04c3fSmrg 14001e04c3fSmrg s_pattern pat[] = { "array", s_base_type, s_size }; 14101e04c3fSmrg if (MATCH(expr, pat)) { 14201e04c3fSmrg const glsl_type *base_type = read_type(s_base_type); 14301e04c3fSmrg if (base_type == NULL) { 14401e04c3fSmrg ir_read_error(NULL, "when reading base type of array type"); 14501e04c3fSmrg return NULL; 14601e04c3fSmrg } 14701e04c3fSmrg 14801e04c3fSmrg return glsl_type::get_array_instance(base_type, s_size->value()); 14901e04c3fSmrg } 15001e04c3fSmrg 15101e04c3fSmrg s_symbol *type_sym = SX_AS_SYMBOL(expr); 15201e04c3fSmrg if (type_sym == NULL) { 15301e04c3fSmrg ir_read_error(expr, "expected <type>"); 15401e04c3fSmrg return NULL; 15501e04c3fSmrg } 15601e04c3fSmrg 15701e04c3fSmrg const glsl_type *type = state->symbols->get_type(type_sym->value()); 15801e04c3fSmrg if (type == NULL) 15901e04c3fSmrg ir_read_error(expr, "invalid type: %s", type_sym->value()); 16001e04c3fSmrg 16101e04c3fSmrg return type; 16201e04c3fSmrg} 16301e04c3fSmrg 16401e04c3fSmrg 16501e04c3fSmrgvoid 16601e04c3fSmrgir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr) 16701e04c3fSmrg{ 16801e04c3fSmrg s_list *list = SX_AS_LIST(expr); 16901e04c3fSmrg if (list == NULL) { 17001e04c3fSmrg ir_read_error(expr, "Expected (<instruction> ...); found an atom."); 17101e04c3fSmrg return; 17201e04c3fSmrg } 17301e04c3fSmrg 17401e04c3fSmrg foreach_in_list(s_list, sub, &list->subexpressions) { 17501e04c3fSmrg if (!sub->is_list()) 17601e04c3fSmrg continue; // not a (function ...); ignore it. 17701e04c3fSmrg 17801e04c3fSmrg s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head()); 17901e04c3fSmrg if (tag == NULL || strcmp(tag->value(), "function") != 0) 18001e04c3fSmrg continue; // not a (function ...); ignore it. 18101e04c3fSmrg 18201e04c3fSmrg ir_function *f = read_function(sub, true); 18301e04c3fSmrg if (f == NULL) 18401e04c3fSmrg return; 18501e04c3fSmrg instructions->push_tail(f); 18601e04c3fSmrg } 18701e04c3fSmrg} 18801e04c3fSmrg 18901e04c3fSmrgir_function * 19001e04c3fSmrgir_reader::read_function(s_expression *expr, bool skip_body) 19101e04c3fSmrg{ 19201e04c3fSmrg bool added = false; 19301e04c3fSmrg s_symbol *name; 19401e04c3fSmrg 19501e04c3fSmrg s_pattern pat[] = { "function", name }; 19601e04c3fSmrg if (!PARTIAL_MATCH(expr, pat)) { 19701e04c3fSmrg ir_read_error(expr, "Expected (function <name> (signature ...) ...)"); 19801e04c3fSmrg return NULL; 19901e04c3fSmrg } 20001e04c3fSmrg 20101e04c3fSmrg ir_function *f = state->symbols->get_function(name->value()); 20201e04c3fSmrg if (f == NULL) { 20301e04c3fSmrg f = new(mem_ctx) ir_function(name->value()); 20401e04c3fSmrg added = state->symbols->add_function(f); 20501e04c3fSmrg assert(added); 20601e04c3fSmrg } 20701e04c3fSmrg 20801e04c3fSmrg /* Skip over "function" tag and function name (which are guaranteed to be 20901e04c3fSmrg * present by the above PARTIAL_MATCH call). 21001e04c3fSmrg */ 21101e04c3fSmrg exec_node *node = ((s_list *) expr)->subexpressions.get_head_raw()->next->next; 21201e04c3fSmrg for (/* nothing */; !node->is_tail_sentinel(); node = node->next) { 21301e04c3fSmrg s_expression *s_sig = (s_expression *) node; 21401e04c3fSmrg read_function_sig(f, s_sig, skip_body); 21501e04c3fSmrg } 21601e04c3fSmrg return added ? f : NULL; 21701e04c3fSmrg} 21801e04c3fSmrg 21901e04c3fSmrgstatic bool 22001e04c3fSmrgalways_available(const _mesa_glsl_parse_state *) 22101e04c3fSmrg{ 22201e04c3fSmrg return true; 22301e04c3fSmrg} 22401e04c3fSmrg 22501e04c3fSmrgvoid 22601e04c3fSmrgir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body) 22701e04c3fSmrg{ 22801e04c3fSmrg s_expression *type_expr; 22901e04c3fSmrg s_list *paramlist; 23001e04c3fSmrg s_list *body_list; 23101e04c3fSmrg 23201e04c3fSmrg s_pattern pat[] = { "signature", type_expr, paramlist, body_list }; 23301e04c3fSmrg if (!MATCH(expr, pat)) { 23401e04c3fSmrg ir_read_error(expr, "Expected (signature <type> (parameters ...) " 23501e04c3fSmrg "(<instruction> ...))"); 23601e04c3fSmrg return; 23701e04c3fSmrg } 23801e04c3fSmrg 23901e04c3fSmrg const glsl_type *return_type = read_type(type_expr); 24001e04c3fSmrg if (return_type == NULL) 24101e04c3fSmrg return; 24201e04c3fSmrg 24301e04c3fSmrg s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head()); 24401e04c3fSmrg if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) { 24501e04c3fSmrg ir_read_error(paramlist, "Expected (parameters ...)"); 24601e04c3fSmrg return; 24701e04c3fSmrg } 24801e04c3fSmrg 24901e04c3fSmrg // Read the parameters list into a temporary place. 25001e04c3fSmrg exec_list hir_parameters; 25101e04c3fSmrg state->symbols->push_scope(); 25201e04c3fSmrg 25301e04c3fSmrg /* Skip over the "parameters" tag. */ 25401e04c3fSmrg exec_node *node = paramlist->subexpressions.get_head_raw()->next; 25501e04c3fSmrg for (/* nothing */; !node->is_tail_sentinel(); node = node->next) { 25601e04c3fSmrg ir_variable *var = read_declaration((s_expression *) node); 25701e04c3fSmrg if (var == NULL) 25801e04c3fSmrg return; 25901e04c3fSmrg 26001e04c3fSmrg hir_parameters.push_tail(var); 26101e04c3fSmrg } 26201e04c3fSmrg 26301e04c3fSmrg ir_function_signature *sig = 26401e04c3fSmrg f->exact_matching_signature(state, &hir_parameters); 26501e04c3fSmrg if (sig == NULL && skip_body) { 26601e04c3fSmrg /* If scanning for prototypes, generate a new signature. */ 26701e04c3fSmrg /* ir_reader doesn't know what languages support a given built-in, so 26801e04c3fSmrg * just say that they're always available. For now, other mechanisms 26901e04c3fSmrg * guarantee the right built-ins are available. 27001e04c3fSmrg */ 27101e04c3fSmrg sig = new(mem_ctx) ir_function_signature(return_type, always_available); 27201e04c3fSmrg f->add_signature(sig); 27301e04c3fSmrg } else if (sig != NULL) { 27401e04c3fSmrg const char *badvar = sig->qualifiers_match(&hir_parameters); 27501e04c3fSmrg if (badvar != NULL) { 27601e04c3fSmrg ir_read_error(expr, "function `%s' parameter `%s' qualifiers " 27701e04c3fSmrg "don't match prototype", f->name, badvar); 27801e04c3fSmrg return; 27901e04c3fSmrg } 28001e04c3fSmrg 28101e04c3fSmrg if (sig->return_type != return_type) { 28201e04c3fSmrg ir_read_error(expr, "function `%s' return type doesn't " 28301e04c3fSmrg "match prototype", f->name); 28401e04c3fSmrg return; 28501e04c3fSmrg } 28601e04c3fSmrg } else { 28701e04c3fSmrg /* No prototype for this body exists - skip it. */ 28801e04c3fSmrg state->symbols->pop_scope(); 28901e04c3fSmrg return; 29001e04c3fSmrg } 29101e04c3fSmrg assert(sig != NULL); 29201e04c3fSmrg 29301e04c3fSmrg sig->replace_parameters(&hir_parameters); 29401e04c3fSmrg 29501e04c3fSmrg if (!skip_body && !body_list->subexpressions.is_empty()) { 29601e04c3fSmrg if (sig->is_defined) { 29701e04c3fSmrg ir_read_error(expr, "function %s redefined", f->name); 29801e04c3fSmrg return; 29901e04c3fSmrg } 30001e04c3fSmrg state->current_function = sig; 30101e04c3fSmrg read_instructions(&sig->body, body_list, NULL); 30201e04c3fSmrg state->current_function = NULL; 30301e04c3fSmrg sig->is_defined = true; 30401e04c3fSmrg } 30501e04c3fSmrg 30601e04c3fSmrg state->symbols->pop_scope(); 30701e04c3fSmrg} 30801e04c3fSmrg 30901e04c3fSmrgvoid 31001e04c3fSmrgir_reader::read_instructions(exec_list *instructions, s_expression *expr, 31101e04c3fSmrg ir_loop *loop_ctx) 31201e04c3fSmrg{ 31301e04c3fSmrg // Read in a list of instructions 31401e04c3fSmrg s_list *list = SX_AS_LIST(expr); 31501e04c3fSmrg if (list == NULL) { 31601e04c3fSmrg ir_read_error(expr, "Expected (<instruction> ...); found an atom."); 31701e04c3fSmrg return; 31801e04c3fSmrg } 31901e04c3fSmrg 32001e04c3fSmrg foreach_in_list(s_expression, sub, &list->subexpressions) { 32101e04c3fSmrg ir_instruction *ir = read_instruction(sub, loop_ctx); 32201e04c3fSmrg if (ir != NULL) { 32301e04c3fSmrg /* Global variable declarations should be moved to the top, before 32401e04c3fSmrg * any functions that might use them. Functions are added to the 32501e04c3fSmrg * instruction stream when scanning for prototypes, so without this 32601e04c3fSmrg * hack, they always appear before variable declarations. 32701e04c3fSmrg */ 32801e04c3fSmrg if (state->current_function == NULL && ir->as_variable() != NULL) 32901e04c3fSmrg instructions->push_head(ir); 33001e04c3fSmrg else 33101e04c3fSmrg instructions->push_tail(ir); 33201e04c3fSmrg } 33301e04c3fSmrg } 33401e04c3fSmrg} 33501e04c3fSmrg 33601e04c3fSmrg 33701e04c3fSmrgir_instruction * 33801e04c3fSmrgir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx) 33901e04c3fSmrg{ 34001e04c3fSmrg s_symbol *symbol = SX_AS_SYMBOL(expr); 34101e04c3fSmrg if (symbol != NULL) { 34201e04c3fSmrg if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL) 34301e04c3fSmrg return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break); 34401e04c3fSmrg if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL) 34501e04c3fSmrg return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); 34601e04c3fSmrg } 34701e04c3fSmrg 34801e04c3fSmrg s_list *list = SX_AS_LIST(expr); 34901e04c3fSmrg if (list == NULL || list->subexpressions.is_empty()) { 35001e04c3fSmrg ir_read_error(expr, "Invalid instruction.\n"); 35101e04c3fSmrg return NULL; 35201e04c3fSmrg } 35301e04c3fSmrg 35401e04c3fSmrg s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); 35501e04c3fSmrg if (tag == NULL) { 35601e04c3fSmrg ir_read_error(expr, "expected instruction tag"); 35701e04c3fSmrg return NULL; 35801e04c3fSmrg } 35901e04c3fSmrg 36001e04c3fSmrg ir_instruction *inst = NULL; 36101e04c3fSmrg if (strcmp(tag->value(), "declare") == 0) { 36201e04c3fSmrg inst = read_declaration(list); 36301e04c3fSmrg } else if (strcmp(tag->value(), "assign") == 0) { 36401e04c3fSmrg inst = read_assignment(list); 36501e04c3fSmrg } else if (strcmp(tag->value(), "if") == 0) { 36601e04c3fSmrg inst = read_if(list, loop_ctx); 36701e04c3fSmrg } else if (strcmp(tag->value(), "loop") == 0) { 36801e04c3fSmrg inst = read_loop(list); 36901e04c3fSmrg } else if (strcmp(tag->value(), "call") == 0) { 37001e04c3fSmrg inst = read_call(list); 37101e04c3fSmrg } else if (strcmp(tag->value(), "return") == 0) { 37201e04c3fSmrg inst = read_return(list); 37301e04c3fSmrg } else if (strcmp(tag->value(), "function") == 0) { 37401e04c3fSmrg inst = read_function(list, false); 37501e04c3fSmrg } else if (strcmp(tag->value(), "emit-vertex") == 0) { 37601e04c3fSmrg inst = read_emit_vertex(list); 37701e04c3fSmrg } else if (strcmp(tag->value(), "end-primitive") == 0) { 37801e04c3fSmrg inst = read_end_primitive(list); 37901e04c3fSmrg } else if (strcmp(tag->value(), "barrier") == 0) { 38001e04c3fSmrg inst = read_barrier(list); 38101e04c3fSmrg } else { 38201e04c3fSmrg inst = read_rvalue(list); 38301e04c3fSmrg if (inst == NULL) 38401e04c3fSmrg ir_read_error(NULL, "when reading instruction"); 38501e04c3fSmrg } 38601e04c3fSmrg return inst; 38701e04c3fSmrg} 38801e04c3fSmrg 38901e04c3fSmrgir_variable * 39001e04c3fSmrgir_reader::read_declaration(s_expression *expr) 39101e04c3fSmrg{ 39201e04c3fSmrg s_list *s_quals; 39301e04c3fSmrg s_expression *s_type; 39401e04c3fSmrg s_symbol *s_name; 39501e04c3fSmrg 39601e04c3fSmrg s_pattern pat[] = { "declare", s_quals, s_type, s_name }; 39701e04c3fSmrg if (!MATCH(expr, pat)) { 39801e04c3fSmrg ir_read_error(expr, "expected (declare (<qualifiers>) <type> <name>)"); 39901e04c3fSmrg return NULL; 40001e04c3fSmrg } 40101e04c3fSmrg 40201e04c3fSmrg const glsl_type *type = read_type(s_type); 40301e04c3fSmrg if (type == NULL) 40401e04c3fSmrg return NULL; 40501e04c3fSmrg 40601e04c3fSmrg ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(), 40701e04c3fSmrg ir_var_auto); 40801e04c3fSmrg 40901e04c3fSmrg foreach_in_list(s_symbol, qualifier, &s_quals->subexpressions) { 41001e04c3fSmrg if (!qualifier->is_symbol()) { 41101e04c3fSmrg ir_read_error(expr, "qualifier list must contain only symbols"); 41201e04c3fSmrg return NULL; 41301e04c3fSmrg } 41401e04c3fSmrg 41501e04c3fSmrg // FINISHME: Check for duplicate/conflicting qualifiers. 41601e04c3fSmrg if (strcmp(qualifier->value(), "centroid") == 0) { 41701e04c3fSmrg var->data.centroid = 1; 41801e04c3fSmrg } else if (strcmp(qualifier->value(), "sample") == 0) { 41901e04c3fSmrg var->data.sample = 1; 42001e04c3fSmrg } else if (strcmp(qualifier->value(), "patch") == 0) { 42101e04c3fSmrg var->data.patch = 1; 422993e1d59Smrg } else if (strcmp(qualifier->value(), "explicit_invariant") == 0) { 423993e1d59Smrg var->data.explicit_invariant = true; 42401e04c3fSmrg } else if (strcmp(qualifier->value(), "invariant") == 0) { 425993e1d59Smrg var->data.invariant = true; 42601e04c3fSmrg } else if (strcmp(qualifier->value(), "uniform") == 0) { 42701e04c3fSmrg var->data.mode = ir_var_uniform; 42801e04c3fSmrg } else if (strcmp(qualifier->value(), "shader_storage") == 0) { 42901e04c3fSmrg var->data.mode = ir_var_shader_storage; 43001e04c3fSmrg } else if (strcmp(qualifier->value(), "auto") == 0) { 43101e04c3fSmrg var->data.mode = ir_var_auto; 43201e04c3fSmrg } else if (strcmp(qualifier->value(), "in") == 0) { 43301e04c3fSmrg var->data.mode = ir_var_function_in; 43401e04c3fSmrg } else if (strcmp(qualifier->value(), "shader_in") == 0) { 43501e04c3fSmrg var->data.mode = ir_var_shader_in; 43601e04c3fSmrg } else if (strcmp(qualifier->value(), "const_in") == 0) { 43701e04c3fSmrg var->data.mode = ir_var_const_in; 43801e04c3fSmrg } else if (strcmp(qualifier->value(), "out") == 0) { 43901e04c3fSmrg var->data.mode = ir_var_function_out; 44001e04c3fSmrg } else if (strcmp(qualifier->value(), "shader_out") == 0) { 44101e04c3fSmrg var->data.mode = ir_var_shader_out; 44201e04c3fSmrg } else if (strcmp(qualifier->value(), "inout") == 0) { 44301e04c3fSmrg var->data.mode = ir_var_function_inout; 44401e04c3fSmrg } else if (strcmp(qualifier->value(), "temporary") == 0) { 44501e04c3fSmrg var->data.mode = ir_var_temporary; 44601e04c3fSmrg } else if (strcmp(qualifier->value(), "stream1") == 0) { 44701e04c3fSmrg var->data.stream = 1; 44801e04c3fSmrg } else if (strcmp(qualifier->value(), "stream2") == 0) { 44901e04c3fSmrg var->data.stream = 2; 45001e04c3fSmrg } else if (strcmp(qualifier->value(), "stream3") == 0) { 45101e04c3fSmrg var->data.stream = 3; 45201e04c3fSmrg } else if (strcmp(qualifier->value(), "smooth") == 0) { 45301e04c3fSmrg var->data.interpolation = INTERP_MODE_SMOOTH; 45401e04c3fSmrg } else if (strcmp(qualifier->value(), "flat") == 0) { 45501e04c3fSmrg var->data.interpolation = INTERP_MODE_FLAT; 45601e04c3fSmrg } else if (strcmp(qualifier->value(), "noperspective") == 0) { 45701e04c3fSmrg var->data.interpolation = INTERP_MODE_NOPERSPECTIVE; 45801e04c3fSmrg } else { 45901e04c3fSmrg ir_read_error(expr, "unknown qualifier: %s", qualifier->value()); 46001e04c3fSmrg return NULL; 46101e04c3fSmrg } 46201e04c3fSmrg } 46301e04c3fSmrg 46401e04c3fSmrg // Add the variable to the symbol table 46501e04c3fSmrg state->symbols->add_variable(var); 46601e04c3fSmrg 46701e04c3fSmrg return var; 46801e04c3fSmrg} 46901e04c3fSmrg 47001e04c3fSmrg 47101e04c3fSmrgir_if * 47201e04c3fSmrgir_reader::read_if(s_expression *expr, ir_loop *loop_ctx) 47301e04c3fSmrg{ 47401e04c3fSmrg s_expression *s_cond; 47501e04c3fSmrg s_expression *s_then; 47601e04c3fSmrg s_expression *s_else; 47701e04c3fSmrg 47801e04c3fSmrg s_pattern pat[] = { "if", s_cond, s_then, s_else }; 47901e04c3fSmrg if (!MATCH(expr, pat)) { 48001e04c3fSmrg ir_read_error(expr, "expected (if <condition> (<then>...) (<else>...))"); 48101e04c3fSmrg return NULL; 48201e04c3fSmrg } 48301e04c3fSmrg 48401e04c3fSmrg ir_rvalue *condition = read_rvalue(s_cond); 48501e04c3fSmrg if (condition == NULL) { 48601e04c3fSmrg ir_read_error(NULL, "when reading condition of (if ...)"); 48701e04c3fSmrg return NULL; 48801e04c3fSmrg } 48901e04c3fSmrg 49001e04c3fSmrg ir_if *iff = new(mem_ctx) ir_if(condition); 49101e04c3fSmrg 49201e04c3fSmrg read_instructions(&iff->then_instructions, s_then, loop_ctx); 49301e04c3fSmrg read_instructions(&iff->else_instructions, s_else, loop_ctx); 49401e04c3fSmrg if (state->error) { 49501e04c3fSmrg delete iff; 49601e04c3fSmrg iff = NULL; 49701e04c3fSmrg } 49801e04c3fSmrg return iff; 49901e04c3fSmrg} 50001e04c3fSmrg 50101e04c3fSmrg 50201e04c3fSmrgir_loop * 50301e04c3fSmrgir_reader::read_loop(s_expression *expr) 50401e04c3fSmrg{ 50501e04c3fSmrg s_expression *s_body; 50601e04c3fSmrg 50701e04c3fSmrg s_pattern loop_pat[] = { "loop", s_body }; 50801e04c3fSmrg if (!MATCH(expr, loop_pat)) { 50901e04c3fSmrg ir_read_error(expr, "expected (loop <body>)"); 51001e04c3fSmrg return NULL; 51101e04c3fSmrg } 51201e04c3fSmrg 51301e04c3fSmrg ir_loop *loop = new(mem_ctx) ir_loop; 51401e04c3fSmrg 51501e04c3fSmrg read_instructions(&loop->body_instructions, s_body, loop); 51601e04c3fSmrg if (state->error) { 51701e04c3fSmrg delete loop; 51801e04c3fSmrg loop = NULL; 51901e04c3fSmrg } 52001e04c3fSmrg return loop; 52101e04c3fSmrg} 52201e04c3fSmrg 52301e04c3fSmrg 52401e04c3fSmrgir_return * 52501e04c3fSmrgir_reader::read_return(s_expression *expr) 52601e04c3fSmrg{ 52701e04c3fSmrg s_expression *s_retval; 52801e04c3fSmrg 52901e04c3fSmrg s_pattern return_value_pat[] = { "return", s_retval}; 53001e04c3fSmrg s_pattern return_void_pat[] = { "return" }; 53101e04c3fSmrg if (MATCH(expr, return_value_pat)) { 53201e04c3fSmrg ir_rvalue *retval = read_rvalue(s_retval); 53301e04c3fSmrg if (retval == NULL) { 53401e04c3fSmrg ir_read_error(NULL, "when reading return value"); 53501e04c3fSmrg return NULL; 53601e04c3fSmrg } 53701e04c3fSmrg return new(mem_ctx) ir_return(retval); 53801e04c3fSmrg } else if (MATCH(expr, return_void_pat)) { 53901e04c3fSmrg return new(mem_ctx) ir_return; 54001e04c3fSmrg } else { 54101e04c3fSmrg ir_read_error(expr, "expected (return <rvalue>) or (return)"); 54201e04c3fSmrg return NULL; 54301e04c3fSmrg } 54401e04c3fSmrg} 54501e04c3fSmrg 54601e04c3fSmrg 54701e04c3fSmrgir_rvalue * 54801e04c3fSmrgir_reader::read_rvalue(s_expression *expr) 54901e04c3fSmrg{ 55001e04c3fSmrg s_list *list = SX_AS_LIST(expr); 55101e04c3fSmrg if (list == NULL || list->subexpressions.is_empty()) 55201e04c3fSmrg return NULL; 55301e04c3fSmrg 55401e04c3fSmrg s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); 55501e04c3fSmrg if (tag == NULL) { 55601e04c3fSmrg ir_read_error(expr, "expected rvalue tag"); 55701e04c3fSmrg return NULL; 55801e04c3fSmrg } 55901e04c3fSmrg 56001e04c3fSmrg ir_rvalue *rvalue = read_dereference(list); 56101e04c3fSmrg if (rvalue != NULL || state->error) 56201e04c3fSmrg return rvalue; 56301e04c3fSmrg else if (strcmp(tag->value(), "swiz") == 0) { 56401e04c3fSmrg rvalue = read_swizzle(list); 56501e04c3fSmrg } else if (strcmp(tag->value(), "expression") == 0) { 56601e04c3fSmrg rvalue = read_expression(list); 56701e04c3fSmrg } else if (strcmp(tag->value(), "constant") == 0) { 56801e04c3fSmrg rvalue = read_constant(list); 56901e04c3fSmrg } else { 57001e04c3fSmrg rvalue = read_texture(list); 57101e04c3fSmrg if (rvalue == NULL && !state->error) 57201e04c3fSmrg ir_read_error(expr, "unrecognized rvalue tag: %s", tag->value()); 57301e04c3fSmrg } 57401e04c3fSmrg 57501e04c3fSmrg return rvalue; 57601e04c3fSmrg} 57701e04c3fSmrg 57801e04c3fSmrgir_assignment * 57901e04c3fSmrgir_reader::read_assignment(s_expression *expr) 58001e04c3fSmrg{ 58101e04c3fSmrg s_expression *cond_expr = NULL; 58201e04c3fSmrg s_expression *lhs_expr, *rhs_expr; 58301e04c3fSmrg s_list *mask_list; 58401e04c3fSmrg 58501e04c3fSmrg s_pattern pat4[] = { "assign", mask_list, lhs_expr, rhs_expr }; 58601e04c3fSmrg s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr }; 58701e04c3fSmrg if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) { 58801e04c3fSmrg ir_read_error(expr, "expected (assign [<condition>] (<write mask>) " 58901e04c3fSmrg "<lhs> <rhs>)"); 59001e04c3fSmrg return NULL; 59101e04c3fSmrg } 59201e04c3fSmrg 59301e04c3fSmrg ir_rvalue *condition = NULL; 59401e04c3fSmrg if (cond_expr != NULL) { 59501e04c3fSmrg condition = read_rvalue(cond_expr); 59601e04c3fSmrg if (condition == NULL) { 59701e04c3fSmrg ir_read_error(NULL, "when reading condition of assignment"); 59801e04c3fSmrg return NULL; 59901e04c3fSmrg } 60001e04c3fSmrg } 60101e04c3fSmrg 60201e04c3fSmrg unsigned mask = 0; 60301e04c3fSmrg 60401e04c3fSmrg s_symbol *mask_symbol; 60501e04c3fSmrg s_pattern mask_pat[] = { mask_symbol }; 60601e04c3fSmrg if (MATCH(mask_list, mask_pat)) { 60701e04c3fSmrg const char *mask_str = mask_symbol->value(); 60801e04c3fSmrg unsigned mask_length = strlen(mask_str); 60901e04c3fSmrg if (mask_length > 4) { 61001e04c3fSmrg ir_read_error(expr, "invalid write mask: %s", mask_str); 61101e04c3fSmrg return NULL; 61201e04c3fSmrg } 61301e04c3fSmrg 61401e04c3fSmrg const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */ 61501e04c3fSmrg 61601e04c3fSmrg for (unsigned i = 0; i < mask_length; i++) { 61701e04c3fSmrg if (mask_str[i] < 'w' || mask_str[i] > 'z') { 61801e04c3fSmrg ir_read_error(expr, "write mask contains invalid character: %c", 61901e04c3fSmrg mask_str[i]); 62001e04c3fSmrg return NULL; 62101e04c3fSmrg } 62201e04c3fSmrg mask |= 1 << idx_map[mask_str[i] - 'w']; 62301e04c3fSmrg } 62401e04c3fSmrg } else if (!mask_list->subexpressions.is_empty()) { 62501e04c3fSmrg ir_read_error(mask_list, "expected () or (<write mask>)"); 62601e04c3fSmrg return NULL; 62701e04c3fSmrg } 62801e04c3fSmrg 62901e04c3fSmrg ir_dereference *lhs = read_dereference(lhs_expr); 63001e04c3fSmrg if (lhs == NULL) { 63101e04c3fSmrg ir_read_error(NULL, "when reading left-hand side of assignment"); 63201e04c3fSmrg return NULL; 63301e04c3fSmrg } 63401e04c3fSmrg 63501e04c3fSmrg ir_rvalue *rhs = read_rvalue(rhs_expr); 63601e04c3fSmrg if (rhs == NULL) { 63701e04c3fSmrg ir_read_error(NULL, "when reading right-hand side of assignment"); 63801e04c3fSmrg return NULL; 63901e04c3fSmrg } 64001e04c3fSmrg 64101e04c3fSmrg if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) { 64201e04c3fSmrg ir_read_error(expr, "non-zero write mask required."); 64301e04c3fSmrg return NULL; 64401e04c3fSmrg } 64501e04c3fSmrg 64601e04c3fSmrg return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask); 64701e04c3fSmrg} 64801e04c3fSmrg 64901e04c3fSmrgir_call * 65001e04c3fSmrgir_reader::read_call(s_expression *expr) 65101e04c3fSmrg{ 65201e04c3fSmrg s_symbol *name; 65301e04c3fSmrg s_list *params; 65401e04c3fSmrg s_list *s_return = NULL; 65501e04c3fSmrg 65601e04c3fSmrg ir_dereference_variable *return_deref = NULL; 65701e04c3fSmrg 65801e04c3fSmrg s_pattern void_pat[] = { "call", name, params }; 65901e04c3fSmrg s_pattern non_void_pat[] = { "call", name, s_return, params }; 66001e04c3fSmrg if (MATCH(expr, non_void_pat)) { 66101e04c3fSmrg return_deref = read_var_ref(s_return); 66201e04c3fSmrg if (return_deref == NULL) { 66301e04c3fSmrg ir_read_error(s_return, "when reading a call's return storage"); 66401e04c3fSmrg return NULL; 66501e04c3fSmrg } 66601e04c3fSmrg } else if (!MATCH(expr, void_pat)) { 66701e04c3fSmrg ir_read_error(expr, "expected (call <name> [<deref>] (<param> ...))"); 66801e04c3fSmrg return NULL; 66901e04c3fSmrg } 67001e04c3fSmrg 67101e04c3fSmrg exec_list parameters; 67201e04c3fSmrg 67301e04c3fSmrg foreach_in_list(s_expression, e, ¶ms->subexpressions) { 67401e04c3fSmrg ir_rvalue *param = read_rvalue(e); 67501e04c3fSmrg if (param == NULL) { 67601e04c3fSmrg ir_read_error(e, "when reading parameter to function call"); 67701e04c3fSmrg return NULL; 67801e04c3fSmrg } 67901e04c3fSmrg parameters.push_tail(param); 68001e04c3fSmrg } 68101e04c3fSmrg 68201e04c3fSmrg ir_function *f = state->symbols->get_function(name->value()); 68301e04c3fSmrg if (f == NULL) { 68401e04c3fSmrg ir_read_error(expr, "found call to undefined function %s", 68501e04c3fSmrg name->value()); 68601e04c3fSmrg return NULL; 68701e04c3fSmrg } 68801e04c3fSmrg 68901e04c3fSmrg ir_function_signature *callee = 69001e04c3fSmrg f->matching_signature(state, ¶meters, true); 69101e04c3fSmrg if (callee == NULL) { 69201e04c3fSmrg ir_read_error(expr, "couldn't find matching signature for function " 69301e04c3fSmrg "%s", name->value()); 69401e04c3fSmrg return NULL; 69501e04c3fSmrg } 69601e04c3fSmrg 69701e04c3fSmrg if (callee->return_type == glsl_type::void_type && return_deref) { 69801e04c3fSmrg ir_read_error(expr, "call has return value storage but void type"); 69901e04c3fSmrg return NULL; 70001e04c3fSmrg } else if (callee->return_type != glsl_type::void_type && !return_deref) { 70101e04c3fSmrg ir_read_error(expr, "call has non-void type but no return value storage"); 70201e04c3fSmrg return NULL; 70301e04c3fSmrg } 70401e04c3fSmrg 70501e04c3fSmrg return new(mem_ctx) ir_call(callee, return_deref, ¶meters); 70601e04c3fSmrg} 70701e04c3fSmrg 70801e04c3fSmrgir_expression * 70901e04c3fSmrgir_reader::read_expression(s_expression *expr) 71001e04c3fSmrg{ 71101e04c3fSmrg s_expression *s_type; 71201e04c3fSmrg s_symbol *s_op; 71301e04c3fSmrg s_expression *s_arg[4] = {NULL}; 71401e04c3fSmrg 71501e04c3fSmrg s_pattern pat[] = { "expression", s_type, s_op, s_arg[0] }; 71601e04c3fSmrg if (!PARTIAL_MATCH(expr, pat)) { 71701e04c3fSmrg ir_read_error(expr, "expected (expression <type> <operator> " 71801e04c3fSmrg "<operand> [<operand>] [<operand>] [<operand>])"); 71901e04c3fSmrg return NULL; 72001e04c3fSmrg } 72101e04c3fSmrg s_arg[1] = (s_expression *) s_arg[0]->next; // may be tail sentinel 72201e04c3fSmrg s_arg[2] = (s_expression *) s_arg[1]->next; // may be tail sentinel or NULL 72301e04c3fSmrg if (s_arg[2]) 72401e04c3fSmrg s_arg[3] = (s_expression *) s_arg[2]->next; // may be tail sentinel or NULL 72501e04c3fSmrg 72601e04c3fSmrg const glsl_type *type = read_type(s_type); 72701e04c3fSmrg if (type == NULL) 72801e04c3fSmrg return NULL; 72901e04c3fSmrg 73001e04c3fSmrg /* Read the operator */ 73101e04c3fSmrg ir_expression_operation op = ir_expression::get_operator(s_op->value()); 73201e04c3fSmrg if (op == (ir_expression_operation) -1) { 73301e04c3fSmrg ir_read_error(expr, "invalid operator: %s", s_op->value()); 73401e04c3fSmrg return NULL; 73501e04c3fSmrg } 73601e04c3fSmrg 73701e04c3fSmrg /* Skip "expression" <type> <operation> by subtracting 3. */ 73801e04c3fSmrg int num_operands = (int) ((s_list *) expr)->subexpressions.length() - 3; 73901e04c3fSmrg 74001e04c3fSmrg int expected_operands = ir_expression::get_num_operands(op); 74101e04c3fSmrg if (num_operands != expected_operands) { 74201e04c3fSmrg ir_read_error(expr, "found %d expression operands, expected %d", 74301e04c3fSmrg num_operands, expected_operands); 74401e04c3fSmrg return NULL; 74501e04c3fSmrg } 74601e04c3fSmrg 74701e04c3fSmrg ir_rvalue *arg[4] = {NULL}; 74801e04c3fSmrg for (int i = 0; i < num_operands; i++) { 74901e04c3fSmrg arg[i] = read_rvalue(s_arg[i]); 75001e04c3fSmrg if (arg[i] == NULL) { 75101e04c3fSmrg ir_read_error(NULL, "when reading operand #%d of %s", i, s_op->value()); 75201e04c3fSmrg return NULL; 75301e04c3fSmrg } 75401e04c3fSmrg } 75501e04c3fSmrg 75601e04c3fSmrg return new(mem_ctx) ir_expression(op, type, arg[0], arg[1], arg[2], arg[3]); 75701e04c3fSmrg} 75801e04c3fSmrg 75901e04c3fSmrgir_swizzle * 76001e04c3fSmrgir_reader::read_swizzle(s_expression *expr) 76101e04c3fSmrg{ 76201e04c3fSmrg s_symbol *swiz; 76301e04c3fSmrg s_expression *sub; 76401e04c3fSmrg 76501e04c3fSmrg s_pattern pat[] = { "swiz", swiz, sub }; 76601e04c3fSmrg if (!MATCH(expr, pat)) { 76701e04c3fSmrg ir_read_error(expr, "expected (swiz <swizzle> <rvalue>)"); 76801e04c3fSmrg return NULL; 76901e04c3fSmrg } 77001e04c3fSmrg 77101e04c3fSmrg if (strlen(swiz->value()) > 4) { 77201e04c3fSmrg ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value()); 77301e04c3fSmrg return NULL; 77401e04c3fSmrg } 77501e04c3fSmrg 77601e04c3fSmrg ir_rvalue *rvalue = read_rvalue(sub); 77701e04c3fSmrg if (rvalue == NULL) 77801e04c3fSmrg return NULL; 77901e04c3fSmrg 78001e04c3fSmrg ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(), 78101e04c3fSmrg rvalue->type->vector_elements); 78201e04c3fSmrg if (ir == NULL) 78301e04c3fSmrg ir_read_error(expr, "invalid swizzle"); 78401e04c3fSmrg 78501e04c3fSmrg return ir; 78601e04c3fSmrg} 78701e04c3fSmrg 78801e04c3fSmrgir_constant * 78901e04c3fSmrgir_reader::read_constant(s_expression *expr) 79001e04c3fSmrg{ 79101e04c3fSmrg s_expression *type_expr; 79201e04c3fSmrg s_list *values; 79301e04c3fSmrg 79401e04c3fSmrg s_pattern pat[] = { "constant", type_expr, values }; 79501e04c3fSmrg if (!MATCH(expr, pat)) { 79601e04c3fSmrg ir_read_error(expr, "expected (constant <type> (...))"); 79701e04c3fSmrg return NULL; 79801e04c3fSmrg } 79901e04c3fSmrg 80001e04c3fSmrg const glsl_type *type = read_type(type_expr); 80101e04c3fSmrg if (type == NULL) 80201e04c3fSmrg return NULL; 80301e04c3fSmrg 80401e04c3fSmrg if (values == NULL) { 80501e04c3fSmrg ir_read_error(expr, "expected (constant <type> (...))"); 80601e04c3fSmrg return NULL; 80701e04c3fSmrg } 80801e04c3fSmrg 80901e04c3fSmrg if (type->is_array()) { 81001e04c3fSmrg unsigned elements_supplied = 0; 81101e04c3fSmrg exec_list elements; 81201e04c3fSmrg foreach_in_list(s_expression, elt, &values->subexpressions) { 81301e04c3fSmrg ir_constant *ir_elt = read_constant(elt); 81401e04c3fSmrg if (ir_elt == NULL) 81501e04c3fSmrg return NULL; 81601e04c3fSmrg elements.push_tail(ir_elt); 81701e04c3fSmrg elements_supplied++; 81801e04c3fSmrg } 81901e04c3fSmrg 82001e04c3fSmrg if (elements_supplied != type->length) { 82101e04c3fSmrg ir_read_error(values, "expected exactly %u array elements, " 82201e04c3fSmrg "given %u", type->length, elements_supplied); 82301e04c3fSmrg return NULL; 82401e04c3fSmrg } 82501e04c3fSmrg return new(mem_ctx) ir_constant(type, &elements); 82601e04c3fSmrg } 82701e04c3fSmrg 82801e04c3fSmrg ir_constant_data data = { { 0 } }; 82901e04c3fSmrg 83001e04c3fSmrg // Read in list of values (at most 16). 83101e04c3fSmrg unsigned k = 0; 83201e04c3fSmrg foreach_in_list(s_expression, expr, &values->subexpressions) { 83301e04c3fSmrg if (k >= 16) { 83401e04c3fSmrg ir_read_error(values, "expected at most 16 numbers"); 83501e04c3fSmrg return NULL; 83601e04c3fSmrg } 83701e04c3fSmrg 83801e04c3fSmrg if (type->is_float()) { 83901e04c3fSmrg s_number *value = SX_AS_NUMBER(expr); 84001e04c3fSmrg if (value == NULL) { 84101e04c3fSmrg ir_read_error(values, "expected numbers"); 84201e04c3fSmrg return NULL; 84301e04c3fSmrg } 84401e04c3fSmrg data.f[k] = value->fvalue(); 84501e04c3fSmrg } else { 84601e04c3fSmrg s_int *value = SX_AS_INT(expr); 84701e04c3fSmrg if (value == NULL) { 84801e04c3fSmrg ir_read_error(values, "expected integers"); 84901e04c3fSmrg return NULL; 85001e04c3fSmrg } 85101e04c3fSmrg 85201e04c3fSmrg switch (type->base_type) { 85301e04c3fSmrg case GLSL_TYPE_UINT: { 85401e04c3fSmrg data.u[k] = value->value(); 85501e04c3fSmrg break; 85601e04c3fSmrg } 85701e04c3fSmrg case GLSL_TYPE_INT: { 85801e04c3fSmrg data.i[k] = value->value(); 85901e04c3fSmrg break; 86001e04c3fSmrg } 86101e04c3fSmrg case GLSL_TYPE_BOOL: { 86201e04c3fSmrg data.b[k] = value->value(); 86301e04c3fSmrg break; 86401e04c3fSmrg } 86501e04c3fSmrg default: 86601e04c3fSmrg ir_read_error(values, "unsupported constant type"); 86701e04c3fSmrg return NULL; 86801e04c3fSmrg } 86901e04c3fSmrg } 87001e04c3fSmrg ++k; 87101e04c3fSmrg } 87201e04c3fSmrg if (k != type->components()) { 87301e04c3fSmrg ir_read_error(values, "expected %u constant values, found %u", 87401e04c3fSmrg type->components(), k); 87501e04c3fSmrg return NULL; 87601e04c3fSmrg } 87701e04c3fSmrg 87801e04c3fSmrg return new(mem_ctx) ir_constant(type, &data); 87901e04c3fSmrg} 88001e04c3fSmrg 88101e04c3fSmrgir_dereference_variable * 88201e04c3fSmrgir_reader::read_var_ref(s_expression *expr) 88301e04c3fSmrg{ 88401e04c3fSmrg s_symbol *s_var; 88501e04c3fSmrg s_pattern var_pat[] = { "var_ref", s_var }; 88601e04c3fSmrg 88701e04c3fSmrg if (MATCH(expr, var_pat)) { 88801e04c3fSmrg ir_variable *var = state->symbols->get_variable(s_var->value()); 88901e04c3fSmrg if (var == NULL) { 89001e04c3fSmrg ir_read_error(expr, "undeclared variable: %s", s_var->value()); 89101e04c3fSmrg return NULL; 89201e04c3fSmrg } 89301e04c3fSmrg return new(mem_ctx) ir_dereference_variable(var); 89401e04c3fSmrg } 89501e04c3fSmrg return NULL; 89601e04c3fSmrg} 89701e04c3fSmrg 89801e04c3fSmrgir_dereference * 89901e04c3fSmrgir_reader::read_dereference(s_expression *expr) 90001e04c3fSmrg{ 90101e04c3fSmrg s_expression *s_subject; 90201e04c3fSmrg s_expression *s_index; 90301e04c3fSmrg s_symbol *s_field; 90401e04c3fSmrg 90501e04c3fSmrg s_pattern array_pat[] = { "array_ref", s_subject, s_index }; 90601e04c3fSmrg s_pattern record_pat[] = { "record_ref", s_subject, s_field }; 90701e04c3fSmrg 90801e04c3fSmrg ir_dereference_variable *var_ref = read_var_ref(expr); 90901e04c3fSmrg if (var_ref != NULL) { 91001e04c3fSmrg return var_ref; 91101e04c3fSmrg } else if (MATCH(expr, array_pat)) { 91201e04c3fSmrg ir_rvalue *subject = read_rvalue(s_subject); 91301e04c3fSmrg if (subject == NULL) { 91401e04c3fSmrg ir_read_error(NULL, "when reading the subject of an array_ref"); 91501e04c3fSmrg return NULL; 91601e04c3fSmrg } 91701e04c3fSmrg 91801e04c3fSmrg ir_rvalue *idx = read_rvalue(s_index); 91901e04c3fSmrg if (idx == NULL) { 92001e04c3fSmrg ir_read_error(NULL, "when reading the index of an array_ref"); 92101e04c3fSmrg return NULL; 92201e04c3fSmrg } 92301e04c3fSmrg return new(mem_ctx) ir_dereference_array(subject, idx); 92401e04c3fSmrg } else if (MATCH(expr, record_pat)) { 92501e04c3fSmrg ir_rvalue *subject = read_rvalue(s_subject); 92601e04c3fSmrg if (subject == NULL) { 92701e04c3fSmrg ir_read_error(NULL, "when reading the subject of a record_ref"); 92801e04c3fSmrg return NULL; 92901e04c3fSmrg } 93001e04c3fSmrg return new(mem_ctx) ir_dereference_record(subject, s_field->value()); 93101e04c3fSmrg } 93201e04c3fSmrg return NULL; 93301e04c3fSmrg} 93401e04c3fSmrg 93501e04c3fSmrgir_texture * 93601e04c3fSmrgir_reader::read_texture(s_expression *expr) 93701e04c3fSmrg{ 93801e04c3fSmrg s_symbol *tag = NULL; 93901e04c3fSmrg s_expression *s_type = NULL; 94001e04c3fSmrg s_expression *s_sampler = NULL; 94101e04c3fSmrg s_expression *s_coord = NULL; 94201e04c3fSmrg s_expression *s_offset = NULL; 94301e04c3fSmrg s_expression *s_proj = NULL; 94401e04c3fSmrg s_list *s_shadow = NULL; 94501e04c3fSmrg s_expression *s_lod = NULL; 94601e04c3fSmrg s_expression *s_sample_index = NULL; 94701e04c3fSmrg s_expression *s_component = NULL; 94801e04c3fSmrg 94901e04c3fSmrg ir_texture_opcode op = ir_tex; /* silence warning */ 95001e04c3fSmrg 95101e04c3fSmrg s_pattern tex_pattern[] = 95201e04c3fSmrg { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow }; 95301e04c3fSmrg s_pattern lod_pattern[] = 95401e04c3fSmrg { "lod", s_type, s_sampler, s_coord }; 95501e04c3fSmrg s_pattern txf_pattern[] = 95601e04c3fSmrg { "txf", s_type, s_sampler, s_coord, s_offset, s_lod }; 95701e04c3fSmrg s_pattern txf_ms_pattern[] = 95801e04c3fSmrg { "txf_ms", s_type, s_sampler, s_coord, s_sample_index }; 95901e04c3fSmrg s_pattern txs_pattern[] = 96001e04c3fSmrg { "txs", s_type, s_sampler, s_lod }; 96101e04c3fSmrg s_pattern tg4_pattern[] = 96201e04c3fSmrg { "tg4", s_type, s_sampler, s_coord, s_offset, s_component }; 96301e04c3fSmrg s_pattern query_levels_pattern[] = 96401e04c3fSmrg { "query_levels", s_type, s_sampler }; 96501e04c3fSmrg s_pattern texture_samples_pattern[] = 96601e04c3fSmrg { "samples", s_type, s_sampler }; 96701e04c3fSmrg s_pattern other_pattern[] = 96801e04c3fSmrg { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod }; 96901e04c3fSmrg 97001e04c3fSmrg if (MATCH(expr, lod_pattern)) { 97101e04c3fSmrg op = ir_lod; 97201e04c3fSmrg } else if (MATCH(expr, tex_pattern)) { 97301e04c3fSmrg op = ir_tex; 97401e04c3fSmrg } else if (MATCH(expr, txf_pattern)) { 97501e04c3fSmrg op = ir_txf; 97601e04c3fSmrg } else if (MATCH(expr, txf_ms_pattern)) { 97701e04c3fSmrg op = ir_txf_ms; 97801e04c3fSmrg } else if (MATCH(expr, txs_pattern)) { 97901e04c3fSmrg op = ir_txs; 98001e04c3fSmrg } else if (MATCH(expr, tg4_pattern)) { 98101e04c3fSmrg op = ir_tg4; 98201e04c3fSmrg } else if (MATCH(expr, query_levels_pattern)) { 98301e04c3fSmrg op = ir_query_levels; 98401e04c3fSmrg } else if (MATCH(expr, texture_samples_pattern)) { 98501e04c3fSmrg op = ir_texture_samples; 98601e04c3fSmrg } else if (MATCH(expr, other_pattern)) { 98701e04c3fSmrg op = ir_texture::get_opcode(tag->value()); 98801e04c3fSmrg if (op == (ir_texture_opcode) -1) 98901e04c3fSmrg return NULL; 99001e04c3fSmrg } else { 99101e04c3fSmrg ir_read_error(NULL, "unexpected texture pattern %s", tag->value()); 99201e04c3fSmrg return NULL; 99301e04c3fSmrg } 99401e04c3fSmrg 99501e04c3fSmrg ir_texture *tex = new(mem_ctx) ir_texture(op); 99601e04c3fSmrg 99701e04c3fSmrg // Read return type 99801e04c3fSmrg const glsl_type *type = read_type(s_type); 99901e04c3fSmrg if (type == NULL) { 100001e04c3fSmrg ir_read_error(NULL, "when reading type in (%s ...)", 100101e04c3fSmrg tex->opcode_string()); 100201e04c3fSmrg return NULL; 100301e04c3fSmrg } 100401e04c3fSmrg 100501e04c3fSmrg // Read sampler (must be a deref) 100601e04c3fSmrg ir_dereference *sampler = read_dereference(s_sampler); 100701e04c3fSmrg if (sampler == NULL) { 100801e04c3fSmrg ir_read_error(NULL, "when reading sampler in (%s ...)", 100901e04c3fSmrg tex->opcode_string()); 101001e04c3fSmrg return NULL; 101101e04c3fSmrg } 101201e04c3fSmrg tex->set_sampler(sampler, type); 101301e04c3fSmrg 101401e04c3fSmrg if (op != ir_txs) { 101501e04c3fSmrg // Read coordinate (any rvalue) 101601e04c3fSmrg tex->coordinate = read_rvalue(s_coord); 101701e04c3fSmrg if (tex->coordinate == NULL) { 101801e04c3fSmrg ir_read_error(NULL, "when reading coordinate in (%s ...)", 101901e04c3fSmrg tex->opcode_string()); 102001e04c3fSmrg return NULL; 102101e04c3fSmrg } 102201e04c3fSmrg 102301e04c3fSmrg if (op != ir_txf_ms && op != ir_lod) { 102401e04c3fSmrg // Read texel offset - either 0 or an rvalue. 102501e04c3fSmrg s_int *si_offset = SX_AS_INT(s_offset); 102601e04c3fSmrg if (si_offset == NULL || si_offset->value() != 0) { 102701e04c3fSmrg tex->offset = read_rvalue(s_offset); 102801e04c3fSmrg if (tex->offset == NULL) { 102901e04c3fSmrg ir_read_error(s_offset, "expected 0 or an expression"); 103001e04c3fSmrg return NULL; 103101e04c3fSmrg } 103201e04c3fSmrg } 103301e04c3fSmrg } 103401e04c3fSmrg } 103501e04c3fSmrg 103601e04c3fSmrg if (op != ir_txf && op != ir_txf_ms && 103701e04c3fSmrg op != ir_txs && op != ir_lod && op != ir_tg4 && 103801e04c3fSmrg op != ir_query_levels && op != ir_texture_samples) { 103901e04c3fSmrg s_int *proj_as_int = SX_AS_INT(s_proj); 104001e04c3fSmrg if (proj_as_int && proj_as_int->value() == 1) { 104101e04c3fSmrg tex->projector = NULL; 104201e04c3fSmrg } else { 104301e04c3fSmrg tex->projector = read_rvalue(s_proj); 104401e04c3fSmrg if (tex->projector == NULL) { 104501e04c3fSmrg ir_read_error(NULL, "when reading projective divide in (%s ..)", 104601e04c3fSmrg tex->opcode_string()); 104701e04c3fSmrg return NULL; 104801e04c3fSmrg } 104901e04c3fSmrg } 105001e04c3fSmrg 105101e04c3fSmrg if (s_shadow->subexpressions.is_empty()) { 105201e04c3fSmrg tex->shadow_comparator = NULL; 105301e04c3fSmrg } else { 105401e04c3fSmrg tex->shadow_comparator = read_rvalue(s_shadow); 105501e04c3fSmrg if (tex->shadow_comparator == NULL) { 105601e04c3fSmrg ir_read_error(NULL, "when reading shadow comparator in (%s ..)", 105701e04c3fSmrg tex->opcode_string()); 105801e04c3fSmrg return NULL; 105901e04c3fSmrg } 106001e04c3fSmrg } 106101e04c3fSmrg } 106201e04c3fSmrg 106301e04c3fSmrg switch (op) { 106401e04c3fSmrg case ir_txb: 106501e04c3fSmrg tex->lod_info.bias = read_rvalue(s_lod); 106601e04c3fSmrg if (tex->lod_info.bias == NULL) { 106701e04c3fSmrg ir_read_error(NULL, "when reading LOD bias in (txb ...)"); 106801e04c3fSmrg return NULL; 106901e04c3fSmrg } 107001e04c3fSmrg break; 107101e04c3fSmrg case ir_txl: 107201e04c3fSmrg case ir_txf: 107301e04c3fSmrg case ir_txs: 107401e04c3fSmrg tex->lod_info.lod = read_rvalue(s_lod); 107501e04c3fSmrg if (tex->lod_info.lod == NULL) { 107601e04c3fSmrg ir_read_error(NULL, "when reading LOD in (%s ...)", 107701e04c3fSmrg tex->opcode_string()); 107801e04c3fSmrg return NULL; 107901e04c3fSmrg } 108001e04c3fSmrg break; 108101e04c3fSmrg case ir_txf_ms: 108201e04c3fSmrg tex->lod_info.sample_index = read_rvalue(s_sample_index); 108301e04c3fSmrg if (tex->lod_info.sample_index == NULL) { 108401e04c3fSmrg ir_read_error(NULL, "when reading sample_index in (txf_ms ...)"); 108501e04c3fSmrg return NULL; 108601e04c3fSmrg } 108701e04c3fSmrg break; 108801e04c3fSmrg case ir_txd: { 108901e04c3fSmrg s_expression *s_dx, *s_dy; 109001e04c3fSmrg s_pattern dxdy_pat[] = { s_dx, s_dy }; 109101e04c3fSmrg if (!MATCH(s_lod, dxdy_pat)) { 109201e04c3fSmrg ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)"); 109301e04c3fSmrg return NULL; 109401e04c3fSmrg } 109501e04c3fSmrg tex->lod_info.grad.dPdx = read_rvalue(s_dx); 109601e04c3fSmrg if (tex->lod_info.grad.dPdx == NULL) { 109701e04c3fSmrg ir_read_error(NULL, "when reading dPdx in (txd ...)"); 109801e04c3fSmrg return NULL; 109901e04c3fSmrg } 110001e04c3fSmrg tex->lod_info.grad.dPdy = read_rvalue(s_dy); 110101e04c3fSmrg if (tex->lod_info.grad.dPdy == NULL) { 110201e04c3fSmrg ir_read_error(NULL, "when reading dPdy in (txd ...)"); 110301e04c3fSmrg return NULL; 110401e04c3fSmrg } 110501e04c3fSmrg break; 110601e04c3fSmrg } 110701e04c3fSmrg case ir_tg4: 110801e04c3fSmrg tex->lod_info.component = read_rvalue(s_component); 110901e04c3fSmrg if (tex->lod_info.component == NULL) { 111001e04c3fSmrg ir_read_error(NULL, "when reading component in (tg4 ...)"); 111101e04c3fSmrg return NULL; 111201e04c3fSmrg } 111301e04c3fSmrg break; 111401e04c3fSmrg default: 111501e04c3fSmrg // tex and lod don't have any extra parameters. 111601e04c3fSmrg break; 111701e04c3fSmrg }; 111801e04c3fSmrg return tex; 111901e04c3fSmrg} 112001e04c3fSmrg 112101e04c3fSmrgir_emit_vertex * 112201e04c3fSmrgir_reader::read_emit_vertex(s_expression *expr) 112301e04c3fSmrg{ 112401e04c3fSmrg s_expression *s_stream = NULL; 112501e04c3fSmrg 112601e04c3fSmrg s_pattern pat[] = { "emit-vertex", s_stream }; 112701e04c3fSmrg 112801e04c3fSmrg if (MATCH(expr, pat)) { 112901e04c3fSmrg ir_rvalue *stream = read_dereference(s_stream); 113001e04c3fSmrg if (stream == NULL) { 113101e04c3fSmrg ir_read_error(NULL, "when reading stream info in emit-vertex"); 113201e04c3fSmrg return NULL; 113301e04c3fSmrg } 113401e04c3fSmrg return new(mem_ctx) ir_emit_vertex(stream); 113501e04c3fSmrg } 113601e04c3fSmrg ir_read_error(NULL, "when reading emit-vertex"); 113701e04c3fSmrg return NULL; 113801e04c3fSmrg} 113901e04c3fSmrg 114001e04c3fSmrgir_end_primitive * 114101e04c3fSmrgir_reader::read_end_primitive(s_expression *expr) 114201e04c3fSmrg{ 114301e04c3fSmrg s_expression *s_stream = NULL; 114401e04c3fSmrg 114501e04c3fSmrg s_pattern pat[] = { "end-primitive", s_stream }; 114601e04c3fSmrg 114701e04c3fSmrg if (MATCH(expr, pat)) { 114801e04c3fSmrg ir_rvalue *stream = read_dereference(s_stream); 114901e04c3fSmrg if (stream == NULL) { 115001e04c3fSmrg ir_read_error(NULL, "when reading stream info in end-primitive"); 115101e04c3fSmrg return NULL; 115201e04c3fSmrg } 115301e04c3fSmrg return new(mem_ctx) ir_end_primitive(stream); 115401e04c3fSmrg } 115501e04c3fSmrg ir_read_error(NULL, "when reading end-primitive"); 115601e04c3fSmrg return NULL; 115701e04c3fSmrg} 115801e04c3fSmrg 115901e04c3fSmrgir_barrier * 116001e04c3fSmrgir_reader::read_barrier(s_expression *expr) 116101e04c3fSmrg{ 116201e04c3fSmrg s_pattern pat[] = { "barrier" }; 116301e04c3fSmrg 116401e04c3fSmrg if (MATCH(expr, pat)) { 116501e04c3fSmrg return new(mem_ctx) ir_barrier(); 116601e04c3fSmrg } 116701e04c3fSmrg ir_read_error(NULL, "when reading barrier"); 116801e04c3fSmrg return NULL; 116901e04c3fSmrg} 1170