summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2010-04-09 17:40:51 -0700
committerIan Romanick <[email protected]>2010-04-28 18:14:54 -0700
commitd1d2ada3c6bdf5a99c07147c157da75f07100847 (patch)
treef90399306caeac36b2996843b6f275b87e45b7e1
parentf955649af3f23367d5e70f33a2bf958b11c2e127 (diff)
ir_reader: Add support for reading variable declarations.
It also now reads a list of instructions, as it should, rather than a single rvalue.
-rw-r--r--ir_reader.cpp119
1 files changed, 114 insertions, 5 deletions
diff --git a/ir_reader.cpp b/ir_reader.cpp
index 4890cf8da9e..00fcc9475cc 100644
--- a/ir_reader.cpp
+++ b/ir_reader.cpp
@@ -29,6 +29,11 @@
static void ir_read_error(s_expression *expr, const char *fmt, ...);
static glsl_type *read_type(_mesa_glsl_parse_state *, s_expression *);
+
+static ir_instruction *read_instruction(_mesa_glsl_parse_state *,
+ s_expression *);
+static ir_variable *read_declaration(_mesa_glsl_parse_state *, s_list *);
+
static ir_rvalue *read_rvalue(_mesa_glsl_parse_state *, s_expression *);
static ir_assignment *read_assignment(_mesa_glsl_parse_state *, s_list *);
static ir_expression *read_expression(_mesa_glsl_parse_state *, s_list *);
@@ -54,14 +59,24 @@ _mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
_mesa_glsl_initialize_constructors(instructions, state);
_mesa_glsl_initialize_functions(instructions, state);
- // FINISHME: Only reading rvalues...for testing.
- ir_instruction *ir = read_rvalue(state, SX_AS_LIST(expr));
- if (ir == NULL) {
- ir_read_error(NULL, "No IR\n");
+ // Read in a list of instructions
+ s_list *list = SX_AS_LIST(expr);
+ if (list == NULL) {
+ ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
state->error = true;
return;
}
- instructions->push_tail(ir);
+
+ foreach_iter(exec_list_iterator, it, list->subexpressions) {
+ s_expression *sub = (s_expression*) it.get();
+ ir_instruction *ir = read_instruction(state, sub);
+ if (ir == NULL) {
+ ir_read_error(sub, "Invalid instruction.\n");
+ state->error = true;
+ return;
+ }
+ instructions->push_tail(ir);
+ }
}
static void
@@ -111,6 +126,100 @@ read_type(_mesa_glsl_parse_state *st, s_expression *expr)
return type;
}
+
+static ir_instruction *
+read_instruction(_mesa_glsl_parse_state *st, s_expression *expr)
+{
+ s_list *list = SX_AS_LIST(expr);
+ if (list == NULL || list->subexpressions.is_empty())
+ return NULL;
+
+ s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
+ if (tag == NULL) {
+ ir_read_error(expr, "expected instruction tag");
+ return NULL;
+ }
+
+ ir_instruction *inst = NULL;
+ if (strcmp(tag->value(), "declare") == 0)
+ inst = read_declaration(st, list);
+ else
+ ir_read_error(expr, "unrecognized instruction tag: %s", tag->value());
+
+ return inst;
+}
+
+
+static ir_variable *
+read_declaration(_mesa_glsl_parse_state *st, s_list *list)
+{
+ if (list->length() != 4) {
+ ir_read_error(list, "expected (declare (<qualifiers>) <type> <name>)");
+ return NULL;
+ }
+
+ s_list *quals = SX_AS_LIST(list->subexpressions.head->next);
+ if (quals == NULL) {
+ ir_read_error(list, "expected a list of variable qualifiers");
+ return NULL;
+ }
+
+ s_expression *type_expr = (s_expression*) quals->next;
+ glsl_type *type = read_type(st, type_expr);
+ if (type == NULL)
+ return NULL;
+
+ s_symbol *var_name = SX_AS_SYMBOL(type_expr->next);
+ if (var_name == NULL) {
+ ir_read_error(list, "expected variable name, found non-symbol");
+ return NULL;
+ }
+
+ ir_variable *var = new ir_variable(type, var_name->value());
+
+ foreach_iter(exec_list_iterator, it, quals->subexpressions) {
+ s_symbol *qualifier = SX_AS_SYMBOL(it.get());
+ if (qualifier == NULL) {
+ ir_read_error(list, "qualifier list must contain only symbols");
+ delete var;
+ return NULL;
+ }
+
+ // FINISHME: Check for duplicate/conflicting qualifiers.
+ if (strcmp(qualifier->value(), "centroid") == 0) {
+ var->centroid = 1;
+ } else if (strcmp(qualifier->value(), "invariant") == 0) {
+ var->invariant = 1;
+ } else if (strcmp(qualifier->value(), "uniform") == 0) {
+ var->mode = ir_var_uniform;
+ } else if (strcmp(qualifier->value(), "auto") == 0) {
+ var->mode = ir_var_auto;
+ } else if (strcmp(qualifier->value(), "in") == 0) {
+ var->mode = ir_var_in;
+ } else if (strcmp(qualifier->value(), "out") == 0) {
+ var->mode = ir_var_out;
+ } else if (strcmp(qualifier->value(), "inout") == 0) {
+ var->mode = ir_var_inout;
+ } else if (strcmp(qualifier->value(), "smooth") == 0) {
+ var->interpolation = ir_var_smooth;
+ } else if (strcmp(qualifier->value(), "flat") == 0) {
+ var->interpolation = ir_var_flat;
+ } else if (strcmp(qualifier->value(), "noperspective") == 0) {
+ var->interpolation = ir_var_noperspective;
+ } else {
+ ir_read_error(list, "unknown qualifier: %s", qualifier->value());
+ delete var;
+ return NULL;
+ }
+ }
+
+ // Add the variable to the symbol table
+ st->symbols->add_variable(var_name->value(), var);
+
+ return var;
+}
+
+
static ir_rvalue *
read_rvalue(_mesa_glsl_parse_state *st, s_expression *expr)
{