Checkpoint new GLSL compiler back-end to produce fp/vp-style assembly instructions.
authorBrian <brian@yutani.localnet.net>
Wed, 13 Dec 2006 21:48:36 +0000 (14:48 -0700)
committerBrian <brian@yutani.localnet.net>
Wed, 13 Dec 2006 21:48:36 +0000 (14:48 -0700)
29 files changed:
src/mesa/shader/slang/slang_assemble.c
src/mesa/shader/slang/slang_assemble.h
src/mesa/shader/slang/slang_assemble_assignment.c
src/mesa/shader/slang/slang_assemble_constructor.c
src/mesa/shader/slang/slang_assemble_typeinfo.c
src/mesa/shader/slang/slang_codegen.c [new file with mode: 0644]
src/mesa/shader/slang/slang_codegen.h [new file with mode: 0644]
src/mesa/shader/slang/slang_compile.c
src/mesa/shader/slang/slang_compile.h
src/mesa/shader/slang/slang_compile_function.c
src/mesa/shader/slang/slang_compile_function.h
src/mesa/shader/slang/slang_compile_operation.c
src/mesa/shader/slang/slang_compile_operation.h
src/mesa/shader/slang/slang_compile_variable.c
src/mesa/shader/slang/slang_compile_variable.h
src/mesa/shader/slang/slang_emit.c [new file with mode: 0644]
src/mesa/shader/slang/slang_emit.h [new file with mode: 0644]
src/mesa/shader/slang/slang_error.c [new file with mode: 0644]
src/mesa/shader/slang/slang_error.h [new file with mode: 0644]
src/mesa/shader/slang/slang_execute.c
src/mesa/shader/slang/slang_ir.h [new file with mode: 0644]
src/mesa/shader/slang/slang_link.h
src/mesa/shader/slang/slang_link2.c [new file with mode: 0644]
src/mesa/shader/slang/slang_print.c [new file with mode: 0644]
src/mesa/shader/slang/slang_print.h [new file with mode: 0644]
src/mesa/shader/slang/slang_simplify.c [new file with mode: 0644]
src/mesa/shader/slang/slang_simplify.h [new file with mode: 0644]
src/mesa/shader/slang/slang_utility.c
src/mesa/shader/slang/slang_utility.h

index 0cba5d5d007f6ecb70a85af2dfddcc78da560c79..617249487f5fb8c588957cddd38fe1b3350a26c5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.2
  *
  * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
  *
 #include "slang_assemble.h"
 #include "slang_compile.h"
 #include "slang_storage.h"
+#include "slang_error.h"
+
+#include "slang_print.h"
+/*#include "assemble2.c"*/
 
 /* slang_assembly */
 
@@ -99,6 +103,9 @@ push_gen(slang_assembly_file * file, slang_assembly_type type,
 {
    slang_assembly *assem;
 
+#if 0
+   printf("Gen %s %f %d %d\n", slang_asm_string(type), literal, label, size);
+#endif
    if (!push_new(file))
       return GL_FALSE;
    assem = &file->code[file->count - 1];
@@ -169,7 +176,7 @@ slang_assembly_file_restore_point_load(slang_assembly_file * file,
 /* utility functions */
 
 static GLboolean
-sizeof_variable(slang_assemble_ctx * A, slang_type_specifier * spec,
+sizeof_variable(const slang_assemble_ctx * A, slang_type_specifier * spec,
                 slang_type_qualifier qual, GLuint array_len, GLuint * size)
 {
    slang_storage_aggregate agg;
@@ -177,9 +184,9 @@ sizeof_variable(slang_assemble_ctx * A, slang_type_specifier * spec,
    /* calculate the size of the variable's aggregate */
    if (!slang_storage_aggregate_construct(&agg))
       return GL_FALSE;
-   if (!_slang_aggregate_variable
-       (&agg, spec, array_len, A->space.funcs, A->space.structs,
-        A->space.vars, A->mach, A->file, A->atoms)) {
+   if (!_slang_aggregate_variable(&agg, spec, array_len, A->space.funcs,
+                                  A->space.structs, A->space.vars, A->mach,
+                                  A->file, A->atoms)) {
       slang_storage_aggregate_destruct(&agg);
       return GL_FALSE;
    }
@@ -231,33 +238,39 @@ collect_locals(slang_assemble_ctx * A, slang_operation * op, GLuint * size)
 
 /* _slang_locate_function() */
 
+/**
+ * Locate a function by comparing actual arguments against formal parameters.
+ */
 slang_function *
 _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
-                       const slang_operation * params, GLuint num_params,
+                       const slang_operation * args, GLuint num_args,
                        const slang_assembly_name_space * space,
                        slang_atom_pool * atoms)
 {
    GLuint i;
 
    for (i = 0; i < funcs->num_functions; i++) {
-      GLuint j;
       slang_function *f = &funcs->functions[i];
+      const GLuint haveRetValue = _slang_function_has_return_value(f);
+      GLuint j;
 
       if (a_name != f->header.a_name)
          continue;
-      if (f->param_count != num_params)
+      if (f->param_count - haveRetValue != num_args)
          continue;
-      for (j = 0; j < num_params; j++) {
+
+      /* compare parameter / argument types */
+      for (j = 0; j < num_args; j++) {
          slang_assembly_typeinfo ti;
 
          if (!slang_assembly_typeinfo_construct(&ti))
             return NULL;
-         if (!_slang_typeof_operation_(&params[j], space, &ti, atoms)) {
+         if (!_slang_typeof_operation_(&args[j], space, &ti, atoms)) {
             slang_assembly_typeinfo_destruct(&ti);
             return NULL;
          }
-         if (!slang_type_specifier_equal
-             (&ti.spec, &f->parameters->variables[j].type.specifier)) {
+         if (!slang_type_specifier_equal(&ti.spec,
+             &f->parameters->variables[j/* + haveRetValue*/].type.specifier)) {
             slang_assembly_typeinfo_destruct(&ti);
             break;
          }
@@ -265,26 +278,30 @@ _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
 
          /* "out" and "inout" formal parameter requires the actual parameter to be l-value */
          if (!ti.can_be_referenced &&
-             (f->parameters->variables[j].type.qualifier == slang_qual_out ||
-              f->parameters->variables[j].type.qualifier == slang_qual_inout))
+             (f->parameters->variables[j/* + haveRetValue*/].type.qualifier == slang_qual_out ||
+              f->parameters->variables[j/* + haveRetValue*/].type.qualifier == slang_qual_inout))
             break;
       }
-      if (j == num_params)
+      if (j == num_args)
          return f;
    }
    if (funcs->outer_scope != NULL)
-      return _slang_locate_function(funcs->outer_scope, a_name, params,
-                                    num_params, space, atoms);
+      return _slang_locate_function(funcs->outer_scope, a_name, args,
+                                    num_args, space, atoms);
    return NULL;
 }
 
-/* _slang_assemble_function() */
 
+
+/**
+ * Generate assembly for a parsed function.
+ */
 GLboolean
 _slang_assemble_function(slang_assemble_ctx * A, slang_function * fun)
 {
    GLuint param_size, local_size;
    GLuint skip, cleanup;
+   const GLuint haveRetValue = _slang_function_has_return_value(fun);
 
    fun->address = A->file->count;
 
@@ -293,9 +310,9 @@ _slang_assemble_function(slang_assemble_ctx * A, slang_function * fun)
        * the instruction to fixup table
        */
       if (!slang_fixup_save(&fun->fixups, fun->address))
-         return GL_FALSE;
+         RETURN_NIL();
       if (!PUSH(A->file, slang_asm_jump))
-         return GL_FALSE;
+         RETURN_OUT_OF_MEMORY();
       return GL_TRUE;
    }
    else {
@@ -316,16 +333,18 @@ _slang_assemble_function(slang_assemble_ctx * A, slang_function * fun)
 
    /* calculate return value size */
    param_size = 0;
-   if (fun->header.type.specifier.type != slang_spec_void)
-      if (!sizeof_variable
-          (A, &fun->header.type.specifier, slang_qual_none, 0, &param_size))
-         return GL_FALSE;
+   if (fun->header.type.specifier.type != slang_spec_void) {
+      if (!sizeof_variable(A, &fun->header.type.specifier,
+                           slang_qual_none, 0, &param_size))
+         RETURN_NIL();
+   }
    A->local.ret_size = param_size;
 
    /* calculate formal parameter list size */
-   if (!sizeof_variables
-       (A, fun->parameters, 0, fun->param_count, &param_size))
-      return GL_FALSE;
+   if (!sizeof_variables(A, fun->parameters,
+                         0,
+                         fun->param_count - haveRetValue, &param_size))
+      RETURN_NIL();
 
    /* calculate local variables size - take into account the four-byte
     * return address and temporaries for various tasks (4 for addr and
@@ -335,52 +354,52 @@ _slang_assemble_function(slang_assemble_ctx * A, slang_function * fun)
    A->local.addr_tmp = param_size + 4;
    A->local.swizzle_tmp = param_size + 4 + 4;
    local_size = param_size + 4 + 4 + 16;
-   if (!sizeof_variables
-       (A, fun->parameters, fun->param_count, fun->parameters->num_variables,
-        &local_size))
-      return GL_FALSE;
+   if (!sizeof_variables(A, fun->parameters, fun->param_count,
+                         fun->parameters->num_variables, &local_size)) {
+      RETURN_OUT_OF_MEMORY();
+   }
    if (!collect_locals(A, fun->body, &local_size))
-      return GL_FALSE;
+      RETURN_NIL();
 
    /* allocate local variable storage */
    if (!PLAB(A->file, slang_asm_local_alloc, local_size - param_size - 4))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
 
    /* mark a new frame for function variable storage */
    if (!PLAB(A->file, slang_asm_enter, local_size))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
 
    /* jump directly to the actual code */
    skip = A->file->count;
    if (!push_new(A->file))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
    A->file->code[skip].type = slang_asm_jump;
 
    /* all "return" statements will be directed here */
    A->flow.function_end = A->file->count;
    cleanup = A->file->count;
    if (!push_new(A->file))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
    A->file->code[cleanup].type = slang_asm_jump;
 
    /* execute the function body */
    A->file->code[skip].param[0] = A->file->count;
-   if (!_slang_assemble_operation
-       (A, fun->body, /*slang_ref_freelance */ slang_ref_forbid))
-      return GL_FALSE;
+   if (!_slang_assemble_operation(A, fun->body,
+                                  /*slang_ref_freelance */ slang_ref_forbid))
+      RETURN_NIL();
 
    /* this is the end of the function - restore the old function frame */
    A->file->code[cleanup].param[0] = A->file->count;
    if (!PUSH(A->file, slang_asm_leave))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
 
    /* free local variable storage */
    if (!PLAB(A->file, slang_asm_local_free, local_size - param_size - 4))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
 
    /* return from the function */
    if (!PUSH(A->file, slang_asm_return))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
 
    return GL_TRUE;
 }
@@ -488,23 +507,19 @@ dereference_aggregate(slang_assemble_ctx * A,
 
       for (j = arr->length; j > 0; j--) {
          if (arr->type == slang_stor_aggregate) {
-            if (!dereference_aggregate
-                (A, arr->aggregate, size, swz, is_swizzled))
+            if (!dereference_aggregate(A, arr->aggregate, size,
+                                       swz, is_swizzled))
                return GL_FALSE;
          }
          else {
             if (is_swizzled && arr->type == slang_stor_vec4) {
-               if (!dereference_basic
-                   (A, slang_stor_float, size, swz, is_swizzled))
+               if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
                   return GL_FALSE;
-               if (!dereference_basic
-                   (A, slang_stor_float, size, swz, is_swizzled))
+               if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
                   return GL_FALSE;
-               if (!dereference_basic
-                   (A, slang_stor_float, size, swz, is_swizzled))
+               if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
                   return GL_FALSE;
-               if (!dereference_basic
-                   (A, slang_stor_float, size, swz, is_swizzled))
+               if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
                   return GL_FALSE;
             }
             else {
@@ -535,9 +550,9 @@ _slang_dereference(slang_assemble_ctx * A, slang_operation * op)
    /* construct aggregate from the type info */
    if (!slang_storage_aggregate_construct(&agg))
       goto end1;
-   if (!_slang_aggregate_variable
-       (&agg, &ti.spec, ti.array_len, A->space.funcs, A->space.structs,
-        A->space.vars, A->mach, A->file, A->atoms))
+   if (!_slang_aggregate_variable(&agg, &ti.spec, ti.array_len, A->space.funcs,
+                                  A->space.structs, A->space.vars, A->mach,
+                                  A->file, A->atoms))
       goto end;
 
    /* dereference the resulting aggregate */
@@ -551,6 +566,10 @@ _slang_dereference(slang_assemble_ctx * A, slang_operation * op)
    return result;
 }
 
+
+/**
+ * Assemble a function call, given a pointer to the actual function to call.
+ */
 GLboolean
 _slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
                               slang_operation * params, GLuint param_count,
@@ -559,6 +578,9 @@ _slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
    GLuint i;
    slang_swizzle p_swz[64];
    slang_ref_type p_ref[64];
+   /*
+   const GLuint haveRetValue = _slang_function_has_return_value(fun);
+   */
 
    /* TODO: fix this, allocate dynamically */
    if (param_count > 64)
@@ -568,8 +590,8 @@ _slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
    if (fun->header.type.specifier.type != slang_spec_void) {
       GLuint ret_size = 0;
 
-      if (!sizeof_variable
-          (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size))
+      if (!sizeof_variable(A, &fun->header.type.specifier,
+                           slang_qual_none, 0, &ret_size))
          return GL_FALSE;
       if (!PLAB(A->file, slang_asm_local_alloc, ret_size))
          return GL_FALSE;
@@ -577,8 +599,8 @@ _slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
 
    /* push the actual parameters on the stack */
    for (i = 0; i < param_count; i++) {
-      if (fun->parameters->variables[i].type.qualifier == slang_qual_inout ||
-          fun->parameters->variables[i].type.qualifier == slang_qual_out) {
+      if (fun->parameters->variables[i /*+ haveRetValue*/].type.qualifier == slang_qual_inout ||
+          fun->parameters->variables[i /*+ haveRetValue*/].type.qualifier == slang_qual_out) {
          if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
             return GL_FALSE;
          /* TODO: optimize the "out" parameter case */
@@ -609,6 +631,10 @@ _slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
    }
 
    /* call the function */
+#if 0
+   printf("CALL FUNCTION %s\n", (char*) fun->header.a_name);
+   slang_print_var_scope(fun->parameters, fun->param_count);
+#endif
    if (!PLAB(A->file, slang_asm_call, fun->address))
       return GL_FALSE;
 
@@ -618,8 +644,8 @@ _slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
 
       A->swz = p_swz[j];
       A->ref = p_ref[j];
-      if (fun->parameters->variables[j].type.qualifier == slang_qual_inout ||
-          fun->parameters->variables[j].type.qualifier == slang_qual_out) {
+      if (fun->parameters->variables[j /*+ haveRetValue*/].type.qualifier == slang_qual_inout ||
+          fun->parameters->variables[j/* + haveRetValue*/].type.qualifier == slang_qual_out) {
          /* for output parameter copy the contents of the formal parameter
           * back to the original actual parameter
           */
@@ -639,6 +665,11 @@ _slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
    return GL_TRUE;
 }
 
+
+/**
+ * Assemble a function call, given the name of the function to call and a
+ * list of parameters.
+ */
 GLboolean
 _slang_assemble_function_call_name(slang_assemble_ctx * A, const char *name,
                                    slang_operation * params,
@@ -653,6 +684,12 @@ _slang_assemble_function_call_name(slang_assemble_ctx * A, const char *name,
    fun =
       _slang_locate_function(A->space.funcs, atom, params, param_count,
                              &A->space, A->atoms);
+   {
+      char *s = (char *) name;
+      if (strcmp(name, "vec4") == 0)
+         printf("LLLLLLLLLLLLLLL locate %s %p\n", s, (void*) fun);
+   }
+
    if (fun == NULL)
       return GL_FALSE;
    return _slang_assemble_function_call(A, fun, params, param_count,
@@ -682,18 +719,25 @@ static const struct
 } inst[] = {
    /* core */
    {"float_add", slang_asm_float_add, slang_asm_float_copy},
+   {"float_subtract", slang_asm_float_subtract, slang_asm_float_copy},
    {"float_multiply", slang_asm_float_multiply, slang_asm_float_copy},
    {"float_divide", slang_asm_float_divide, slang_asm_float_copy},
    {"float_negate", slang_asm_float_negate, slang_asm_float_copy},
+   {"float_min", slang_asm_float_min, slang_asm_float_copy},
+   {"float_max", slang_asm_float_max, slang_asm_float_copy},
    {"float_less", slang_asm_float_less, slang_asm_bool_copy},
    {"float_equal", slang_asm_float_equal_exp, slang_asm_bool_copy},
    {"float_to_int", slang_asm_float_to_int, slang_asm_int_copy},
    {"float_sine", slang_asm_float_sine, slang_asm_float_copy},
+   {"float_cosine", slang_asm_float_cosine, slang_asm_float_copy},
    {"float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy},
    {"float_arctan", slang_asm_float_arctan, slang_asm_float_copy},
    {"float_power", slang_asm_float_power, slang_asm_float_copy},
+   {"float_exp", slang_asm_float_exp, slang_asm_float_copy},
+   {"float_exp2", slang_asm_float_exp2, slang_asm_float_copy},
+   {"float_rsq", slang_asm_float_rsq, slang_asm_float_copy},
+   {"float_rcp", slang_asm_float_rcp, slang_asm_float_copy},
    {"float_log2", slang_asm_float_log2, slang_asm_float_copy},
-   {"float_floor", slang_asm_float_floor, slang_asm_float_copy},
    {"float_ceil", slang_asm_float_ceil, slang_asm_float_copy},
    {"float_noise1", slang_asm_float_noise1, slang_asm_float_copy},
    {"float_noise2", slang_asm_float_noise2, slang_asm_float_copy},
@@ -712,12 +756,24 @@ static const struct
    {"bool_print", slang_asm_bool_deref, slang_asm_bool_print},
    /* vec4 */
    {"float_to_vec4", slang_asm_float_to_vec4, slang_asm_none},
-   {"vec4_add", slang_asm_vec4_add, slang_asm_none},
-   {"vec4_subtract", slang_asm_vec4_subtract, slang_asm_none},
-   {"vec4_multiply", slang_asm_vec4_multiply, slang_asm_none},
+   {"vec4_add", slang_asm_vec4_add, slang_asm_float_copy},
+   {"vec4_subtract", slang_asm_vec4_subtract, slang_asm_float_copy},
+   {"vec4_multiply", slang_asm_vec4_multiply, slang_asm_float_copy},
+   {"vec4_min", slang_asm_vec4_min, slang_asm_float_copy},
+   {"vec4_max", slang_asm_vec4_max, slang_asm_float_copy},
+   {"vec4_seq", slang_asm_vec4_seq, slang_asm_float_copy},
+   {"vec4_sne", slang_asm_vec4_sne, slang_asm_float_copy},
+   {"vec4_sge", slang_asm_vec4_sge, slang_asm_float_copy},
+   {"vec4_sgt", slang_asm_vec4_sgt, slang_asm_float_copy},
+   {"vec4_floor", slang_asm_vec4_floor, slang_asm_float_copy},
+   {"vec4_frac", slang_asm_vec4_frac, slang_asm_float_copy},
+   {"vec4_abs", slang_asm_vec4_abs, slang_asm_float_copy},
+
    {"vec4_divide", slang_asm_vec4_divide, slang_asm_none},
    {"vec4_negate", slang_asm_vec4_negate, slang_asm_none},
-   {"vec4_dot", slang_asm_vec4_dot, slang_asm_none},
+   {"vec4_dot", slang_asm_vec4_dot, slang_asm_float_copy},
+   {"vec3_dot", slang_asm_vec3_dot, slang_asm_float_copy},
+   {"vec3_cross", slang_asm_vec3_cross, slang_asm_float_copy},
    {NULL, slang_asm_none, slang_asm_none}
 };
 
@@ -767,15 +823,14 @@ equality_aggregate(slang_assemble_ctx * A,
          else {
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
             if (arr->type == slang_stor_vec4) {
-               if (!PLAB2
-                   (A->file, slang_asm_vec4_equal_int, size + *index, *index))
+               if (!PLAB2(A->file, slang_asm_vec4_equal_int,
+                          size + *index, *index))
                   return GL_FALSE;
             }
             else
 #endif
-            if (!PLAB2
-                   (A->file, slang_asm_float_equal_int, size + *index,
-                       *index))
+            if (!PLAB2(A->file, slang_asm_float_equal_int,
+                       size + *index, *index))
                return GL_FALSE;
 
             *index += _slang_sizeof_type(arr->type);
@@ -799,19 +854,21 @@ equality(slang_assemble_ctx * A, slang_operation * op, GLboolean equal)
 
    /* get type of operation */
    if (!slang_assembly_typeinfo_construct(&ti))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
    if (!_slang_typeof_operation(A, op, &ti))
       goto end1;
 
    /* convert it to an aggregate */
    if (!slang_storage_aggregate_construct(&agg))
       goto end1;
-   if (!_slang_aggregate_variable
-       (&agg, &ti.spec, 0, A->space.funcs, A->space.structs, A->space.vars,
-        A->mach, A->file, A->atoms))
+   if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs,
+                                  A->space.structs, A->space.vars,
+                                  A->mach, A->file, A->atoms))
       goto end;
 
-   /* compute the size of the agregate - there are two such aggregates on the stack */
+   /* compute the size of the agregate - there are two such aggregates
+    * on the stack
+    */
    size = _slang_sizeof_aggregate(&agg);
 
    /* jump to the actual data-comparison code */
@@ -840,10 +897,12 @@ equality(slang_assemble_ctx * A, slang_operation * op, GLboolean equal)
 
    A->file->code[skip_jump].param[0] = A->file->count;
 
-   /* compare the data on stack, it will eventually jump either to true or false label */
+   /* compare the data on stack, it will eventually jump either to
+    * true or false label
+    */
    index = 0;
-   if (!equality_aggregate
-       (A, &agg, &index, size, equal ? false_label : true_label))
+   if (!equality_aggregate(A, &agg, &index, size,
+                           equal ? false_label : true_label))
       goto end;
    if (!PLAB(A->file, slang_asm_jump, equal ? true_label : false_label))
       goto end;
@@ -869,8 +928,8 @@ handle_subscript(slang_assemble_ctx * A, slang_assembly_typeinfo * tie,
    /* get type info of the master expression (matrix, vector or an array */
    if (!_slang_typeof_operation(A, &op->children[0], tia))
       return GL_FALSE;
-   if (!sizeof_variable
-       (A, &tia->spec, slang_qual_none, tia->array_len, &asize))
+   if (!sizeof_variable(A, &tia->spec, slang_qual_none,
+                        tia->array_len, &asize))
       return GL_FALSE;
 
    /* get type info of the result (matrix column, vector row or array element) */
@@ -944,8 +1003,8 @@ handle_subscript(slang_assemble_ctx * A, slang_assembly_typeinfo * tie,
 
       /* move the selected element to the beginning of the master expression */
       for (i = 0; i < esize; i += 4)
-         if (!PLAB2
-             (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4))
+         if (!PLAB2(A->file, slang_asm_float_move,
+                    asize - esize + i + 4, i + 4))
             return GL_FALSE;
       if (!PLAB(A->file, slang_asm_local_free, 4))
          return GL_FALSE;
@@ -965,20 +1024,20 @@ handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia,
 {
    /* get type info of the result (field or swizzle) */
    if (!_slang_typeof_operation(A, op, tia))
-      return GL_FALSE;
+      RETURN_NIL();
 
    /* get type info of the master expression being accessed (struct or vector) */
    if (!_slang_typeof_operation(A, &op->children[0], tib))
-      return GL_FALSE;
+      RETURN_NIL();
 
    /* if swizzling a vector in-place, the swizzle temporary is needed */
    if (ref == slang_ref_forbid && tia->is_swizzled)
       if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
-         return GL_FALSE;
+         RETURN_OUT_OF_MEMORY();
 
    /* assemble the master expression */
    if (!_slang_assemble_operation(A, &op->children[0], ref))
-      return GL_FALSE;
+      RETURN_NIL();
 
    /* assemble the field expression */
    if (tia->is_swizzled) {
@@ -989,9 +1048,9 @@ handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia,
              * the selected component
              */
             if (!PLAB(file, slang_asm_addr_push, tia->swz.swizzle[0] * 4))
-               return 0;
+               RETURN_OUT_OF_MEMORY();
             if (!PUSH(file, slang_asm_addr_add))
-               return 0;
+               RETURN_OUT_OF_MEMORY();
          }
          else
 #endif
@@ -1005,9 +1064,9 @@ handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia,
       }
       else {
          /* swizzle the vector in-place using the swizzle temporary */
-         if (!_slang_assemble_constructor_from_swizzle
-             (A, &tia->swz, &tia->spec, &tib->spec))
-            return GL_FALSE;
+         if (!_slang_assemble_constructor_from_swizzle(A, &tia->swz,
+                                                       &tia->spec, &tib->spec))
+            RETURN_NIL();
       }
    }
    else {
@@ -1023,12 +1082,13 @@ handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia,
 
          field = &tib->spec._struct->fields->variables[i];
          if (!slang_storage_aggregate_construct(&agg))
-            return GL_FALSE;
-         if (!_slang_aggregate_variable
-             (&agg, &field->type.specifier, field->array_len, A->space.funcs,
-              A->space.structs, A->space.vars, A->mach, A->file, A->atoms)) {
+            RETURN_NIL();
+         if (!_slang_aggregate_variable(&agg, &field->type.specifier,
+                                        field->array_len, A->space.funcs,
+                                        A->space.structs, A->space.vars,
+                                        A->mach, A->file, A->atoms)) {
             slang_storage_aggregate_destruct(&agg);
-            return GL_FALSE;
+            RETURN_NIL();
          }
          size = _slang_sizeof_aggregate(&agg);
          slang_storage_aggregate_destruct(&agg);
@@ -1051,9 +1111,9 @@ handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia,
 
          if (shift) {
             if (!PLAB(A->file, slang_asm_addr_push, field_offset))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
             if (!PUSH(A->file, slang_asm_addr_add))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
          }
       }
       else {
@@ -1079,12 +1139,11 @@ handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia,
              * Do it in reverse order to avoid overwriting itself.
              */
             if (!PLAB(A->file, slang_asm_addr_push, field_offset))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
             for (i = field_size; i > 0; i -= 4)
-               if (!PLAB2
-                   (A->file, slang_asm_float_move,
-                    struct_size - field_size + i, i))
-                  return GL_FALSE;
+               if (!PLAB2(A->file, slang_asm_float_move,
+                          struct_size - field_size + i, i))
+                  RETURN_OUT_OF_MEMORY();
             free_b += 4;
          }
 
@@ -1095,7 +1154,7 @@ handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia,
 
          if (free_b) {
             if (!PLAB(A->file, slang_asm_local_free, free_b))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
          }
       }
    }
@@ -1118,12 +1177,11 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
          GLuint i;
 
          for (i = 0; i < op->num_children; i++) {
-            if (!_slang_assemble_operation
-                (A, &op->children[i],
-                 slang_ref_forbid /*slang_ref_freelance */ ))
-               return GL_FALSE;
+            if (!_slang_assemble_operation(A, &op->children[i],
+                                  slang_ref_forbid /*slang_ref_freelance */ ))
+               RETURN_NIL();
             if (!_slang_cleanup_stack(A, &op->children[i]))
-               return GL_FALSE;
+               RETURN_NIL();
          }
       }
       break;
@@ -1135,21 +1193,19 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
 
          /* Construct assignment expression placeholder. */
          if (!slang_operation_construct(&assign))
-            return GL_FALSE;
+            RETURN_NIL();
          assign.type = slang_oper_assign;
-         assign.children =
-            (slang_operation *) slang_alloc_malloc(2 *
-                                                   sizeof(slang_operation));
+         assign.children = slang_operation_new(2);
          if (assign.children == NULL) {
             slang_operation_destruct(&assign);
-            return GL_FALSE;
+            RETURN_NIL();
          }
          for (assign.num_children = 0; assign.num_children < 2;
               assign.num_children++)
-            if (!slang_operation_construct
-                (&assign.children[assign.num_children])) {
+            if (!slang_operation_construct(&assign.children
+                                           [assign.num_children])) {
                slang_operation_destruct(&assign);
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
             }
 
          result = GL_TRUE;
@@ -1177,99 +1233,98 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
          }
          slang_operation_destruct(&assign);
          if (!result)
-            return GL_FALSE;
+            RETURN_NIL();
       }
       break;
    case slang_oper_asm:
       {
          GLuint i;
          if (!_slang_assemble_operation(A, &op->children[0], slang_ref_force))
-            return GL_FALSE;
+            RETURN_NIL();
          for (i = 1; i < op->num_children; i++)
-            if (!_slang_assemble_operation
-                (A, &op->children[i], slang_ref_forbid))
-               return GL_FALSE;
+            if (!_slang_assemble_operation(A, &op->children[i],
+                                           slang_ref_forbid))
+               RETURN_NIL();
          if (!call_asm_instruction(A, op->a_id))
-            return GL_FALSE;
+            RETURN_ERROR2("Unknown __asm call", (char*) op->a_id, 0);
       }
       break;
    case slang_oper_break:
       if (!PLAB(A->file, slang_asm_jump, A->flow.loop_end))
-         return GL_FALSE;
+         RETURN_OUT_OF_MEMORY();
       break;
    case slang_oper_continue:
       if (!PLAB(A->file, slang_asm_jump, A->flow.loop_start))
-         return GL_FALSE;
+         RETURN_OUT_OF_MEMORY();
       break;
    case slang_oper_discard:
       if (!PUSH(A->file, slang_asm_discard))
-         return GL_FALSE;
+         RETURN_OUT_OF_MEMORY();
       if (!PUSH(A->file, slang_asm_exit))
-         return GL_FALSE;
+         RETURN_OUT_OF_MEMORY();
       break;
    case slang_oper_return:
       if (A->local.ret_size != 0) {
          /* push the result's address */
          if (!PLAB2(A->file, slang_asm_local_addr, 0, A->local.ret_size))
-            return GL_FALSE;
-         if (!_slang_assemble_operation
-             (A, &op->children[0], slang_ref_forbid))
-            return GL_FALSE;
+            RETURN_OUT_OF_MEMORY();
+         if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid))
+            RETURN_NIL();
 
          A->swz.num_components = 0;
          /* assign the operation to the function result (it was reserved on the stack) */
          if (!_slang_assemble_assignment(A, op->children))
-            return GL_FALSE;
+            RETURN_NIL();
 
          if (!PLAB(A->file, slang_asm_local_free, 4))
-            return GL_FALSE;
+            RETURN_OUT_OF_MEMORY();
       }
       if (!PLAB(A->file, slang_asm_jump, A->flow.function_end))
-         return GL_FALSE;
+         RETURN_OUT_OF_MEMORY();
       break;
    case slang_oper_expression:
       if (ref == slang_ref_force)
-         return GL_FALSE;
+         RETURN_NIL();
       if (!_slang_assemble_operation(A, &op->children[0], ref))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_if:
       if (!_slang_assemble_if(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_while:
       if (!_slang_assemble_while(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_do:
       if (!_slang_assemble_do(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_for:
       if (!_slang_assemble_for(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_void:
       break;
    case slang_oper_literal_bool:
       if (ref == slang_ref_force)
-         return GL_FALSE;
-      if (!PLIT(A->file, slang_asm_bool_push, op->literal))
-         return GL_FALSE;
+         RETURN_NIL();
+      if (!PLIT(A->file, slang_asm_bool_push, op->literal[0]))
+         RETURN_OUT_OF_MEMORY();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_literal_int:
       if (ref == slang_ref_force)
-         return GL_FALSE;
-      if (!PLIT(A->file, slang_asm_int_push, op->literal))
-         return GL_FALSE;
+         RETURN_NIL();
+      if (!PLIT(A->file, slang_asm_int_push, op->literal[0]))
+         RETURN_OUT_OF_MEMORY();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_literal_float:
       if (ref == slang_ref_force)
-         return GL_FALSE;
-      if (!PLIT(A->file, slang_asm_float_push, op->literal))
-         return GL_FALSE;
+         RETURN_NIL();
+      if (!PLIT(A->file, slang_asm_float_push, op->literal[0]))
+         RETURN_OUT_OF_MEMORY();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_identifier:
@@ -1280,68 +1335,67 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
          /* find the variable and calculate its size */
          var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
          if (var == NULL)
-            return GL_FALSE;
+            RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
          size = 0;
-         if (!sizeof_variable
-             (A, &var->type.specifier, slang_qual_none, var->array_len,
-              &size))
-            return GL_FALSE;
+         if (!sizeof_variable(A, &var->type.specifier, slang_qual_none,
+                              var->array_len, &size))
+            RETURN_OUT_OF_MEMORY();
 
          /* prepare stack for dereferencing */
          if (ref == slang_ref_forbid)
             if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
 
          /* push the variable's address */
          if (var->global) {
             if (!PLAB(A->file, slang_asm_global_addr, var->address))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
          }
          else {
             if (!PLAB2(A->file, slang_asm_local_addr, var->address, size))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
          }
 
          /* perform the dereference */
          if (ref == slang_ref_forbid) {
             if (!PUSH(A->file, slang_asm_addr_copy))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
             if (!PLAB(A->file, slang_asm_local_free, 4))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
             if (!_slang_dereference(A, op))
-               return GL_FALSE;
+               RETURN_NIL();
          }
       }
       break;
    case slang_oper_sequence:
       if (ref == slang_ref_force)
-         return GL_FALSE;
+         RETURN_NIL();
       if (!_slang_assemble_operation(A, &op->children[0],
                                      slang_ref_forbid /*slang_ref_freelance */ ))
-         return GL_FALSE;
+         RETURN_NIL();
       if (!_slang_cleanup_stack(A, &op->children[0]))
-         return GL_FALSE;
+         RETURN_NIL();
       if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_assign:
       if (!_slang_assemble_assign(A, op, "=", ref))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_addassign:
       if (!_slang_assemble_assign(A, op, "+=", ref))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = ref;
       break;
    case slang_oper_subassign:
       if (!_slang_assemble_assign(A, op, "-=", ref))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = ref;
       break;
    case slang_oper_mulassign:
       if (!_slang_assemble_assign(A, op, "*=", ref))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = ref;
       break;
       /*case slang_oper_modassign: */
@@ -1352,27 +1406,27 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
       /*case slang_oper_andassign: */
    case slang_oper_divassign:
       if (!_slang_assemble_assign(A, op, "/=", ref))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = ref;
       break;
    case slang_oper_select:
       if (!_slang_assemble_select(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_logicalor:
       if (!_slang_assemble_logicalor(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_logicaland:
       if (!_slang_assemble_logicaland(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_logicalxor:
       if (!_slang_assemble_function_call_name(A, "^^", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
       /*case slang_oper_bitor: */
@@ -1380,91 +1434,89 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
       /*case slang_oper_bitand: */
    case slang_oper_less:
       if (!_slang_assemble_function_call_name(A, "<", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_greater:
       if (!_slang_assemble_function_call_name(A, ">", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_lessequal:
       if (!_slang_assemble_function_call_name(A, "<=", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_greaterequal:
       if (!_slang_assemble_function_call_name(A, ">=", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
       /*case slang_oper_lshift: */
       /*case slang_oper_rshift: */
    case slang_oper_add:
       if (!_slang_assemble_function_call_name(A, "+", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_subtract:
       if (!_slang_assemble_function_call_name(A, "-", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_multiply:
       if (!_slang_assemble_function_call_name(A, "*", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
       /*case slang_oper_modulus: */
    case slang_oper_divide:
       if (!_slang_assemble_function_call_name(A, "/", op->children, 2, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_equal:
       if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid))
-         return GL_FALSE;
+         RETURN_NIL();
       if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid))
-         return GL_FALSE;
+         RETURN_NIL();
       if (!equality(A, op->children, GL_TRUE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_notequal:
       if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid))
-         return GL_FALSE;
+         RETURN_NIL();
       if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid))
-         return GL_FALSE;
+         RETURN_NIL();
       if (!equality(A, op->children, GL_FALSE))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_preincrement:
       if (!_slang_assemble_assign(A, op, "++", ref))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = ref;
       break;
    case slang_oper_predecrement:
       if (!_slang_assemble_assign(A, op, "--", ref))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = ref;
       break;
    case slang_oper_plus:
       if (!_slang_dereference(A, op))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_minus:
-      if (!_slang_assemble_function_call_name
-          (A, "-", op->children, 1, GL_FALSE))
-         return GL_FALSE;
+      if (!_slang_assemble_function_call_name(A, "-", op->children, 1, GL_FALSE))
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
       /*case slang_oper_complement: */
    case slang_oper_not:
-      if (!_slang_assemble_function_call_name
-          (A, "!", op->children, 1, GL_FALSE))
-         return GL_FALSE;
+      if (!_slang_assemble_function_call_name(A, "!", op->children, 1, GL_FALSE))
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_subscript:
@@ -1472,15 +1524,15 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
          slang_assembly_typeinfo ti_arr, ti_elem;
 
          if (!slang_assembly_typeinfo_construct(&ti_arr))
-            return GL_FALSE;
+            RETURN_OUT_OF_MEMORY();
          if (!slang_assembly_typeinfo_construct(&ti_elem)) {
             slang_assembly_typeinfo_destruct(&ti_arr);
-            return GL_FALSE;
+            RETURN_OUT_OF_MEMORY();
          }
          if (!handle_subscript(A, &ti_elem, &ti_arr, op, ref)) {
             slang_assembly_typeinfo_destruct(&ti_arr);
             slang_assembly_typeinfo_destruct(&ti_elem);
-            return GL_FALSE;
+            RETURN_NIL();
          }
          slang_assembly_typeinfo_destruct(&ti_arr);
          slang_assembly_typeinfo_destruct(&ti_elem);
@@ -1488,19 +1540,17 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
       break;
    case slang_oper_call:
       {
-         slang_function *fun;
-
-         fun =
-            _slang_locate_function(A->space.funcs, op->a_id, op->children,
-                                   op->num_children, &A->space, A->atoms);
+         slang_function *fun
+            = _slang_locate_function(A->space.funcs, op->a_id, op->children,
+                                     op->num_children, &A->space, A->atoms);
          if (fun == NULL) {
             if (!_slang_assemble_constructor(A, op))
-               return GL_FALSE;
+               RETURN_OUT_OF_MEMORY();
          }
          else {
-            if (!_slang_assemble_function_call
-                (A, fun, op->children, op->num_children, GL_FALSE))
-               return GL_FALSE;
+            if (!_slang_assemble_function_call(A, fun, op->children,
+                                               op->num_children, GL_FALSE))
+               RETURN_NIL();
          }
          A->ref = slang_ref_forbid;
       }
@@ -1510,15 +1560,15 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
          slang_assembly_typeinfo ti_after, ti_before;
 
          if (!slang_assembly_typeinfo_construct(&ti_after))
-            return GL_FALSE;
+            RETURN_OUT_OF_MEMORY();
          if (!slang_assembly_typeinfo_construct(&ti_before)) {
             slang_assembly_typeinfo_destruct(&ti_after);
-            return GL_FALSE;
+            RETURN_OUT_OF_MEMORY();
          }
          if (!handle_field(A, &ti_after, &ti_before, op, ref)) {
             slang_assembly_typeinfo_destruct(&ti_after);
             slang_assembly_typeinfo_destruct(&ti_before);
-            return GL_FALSE;
+            RETURN_NIL();
          }
          slang_assembly_typeinfo_destruct(&ti_after);
          slang_assembly_typeinfo_destruct(&ti_before);
@@ -1526,16 +1576,16 @@ _slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op,
       break;
    case slang_oper_postincrement:
       if (!assemble_function_call_name_dummyint(A, "++", op->children))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    case slang_oper_postdecrement:
       if (!assemble_function_call_name_dummyint(A, "--", op->children))
-         return GL_FALSE;
+         RETURN_NIL();
       A->ref = slang_ref_forbid;
       break;
    default:
-      return GL_FALSE;
+      RETURN_NIL();
    }
 
    return GL_TRUE;
index d004e6650035b13e4a43e3d2ffc3bbba60eb34cd..d507fc0161e40ba2f8890fa54514b8698a267b61 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef SLANG_ASSEMBLE_H
 #define SLANG_ASSEMBLE_H
 
+#include "imports.h"
+#include "mtypes.h"
 #include "slang_utility.h"
 
 #if defined __cplusplus
@@ -43,6 +45,7 @@ typedef enum slang_assembly_type_
    slang_asm_float_push,
    slang_asm_float_deref,
    slang_asm_float_add,       /* a = pop(); b = pop(); push(a + b); */
+   slang_asm_float_subtract,
    slang_asm_float_multiply,
    slang_asm_float_divide,
    slang_asm_float_negate,    /* push(-pop()) */
@@ -51,11 +54,17 @@ typedef enum slang_assembly_type_
    slang_asm_float_equal_int,
    slang_asm_float_to_int,    /* push(floatToInt(pop())) */
    slang_asm_float_sine,      /* push(sin(pop()) */
+   slang_asm_float_cosine,
    slang_asm_float_arcsine,
    slang_asm_float_arctan,
    slang_asm_float_power,     /* push(pow(pop(), pop())) */
+   slang_asm_float_exp,
+   slang_asm_float_exp2,
+   slang_asm_float_rsq,
+   slang_asm_float_rcp,
    slang_asm_float_log2,
-   slang_asm_float_floor,
+   slang_asm_float_min,
+   slang_asm_float_max,
    slang_asm_float_ceil,
    slang_asm_float_noise1,    /* push(noise1(pop()) */
    slang_asm_float_noise2,    /* push(noise2(pop(), pop())) */
@@ -114,7 +123,19 @@ typedef enum slang_assembly_type_
    slang_asm_vec4_multiply,
    slang_asm_vec4_divide,
    slang_asm_vec4_negate,
+   slang_asm_vec4_min,
+   slang_asm_vec4_max,
+   slang_asm_vec4_seq,
+   slang_asm_vec4_sne,
+   slang_asm_vec4_sge,
+   slang_asm_vec4_sgt,
    slang_asm_vec4_dot,
+   slang_asm_vec3_dot,
+   slang_asm_vec3_cross,
+   slang_asm_vec4_floor,
+   slang_asm_vec4_frac,
+   slang_asm_vec4_abs,
+
    slang_asm_vec4_copy,
    slang_asm_vec4_deref,
    slang_asm_vec4_equal_int,
@@ -231,6 +252,7 @@ typedef struct slang_assemble_ctx_
    slang_assembly_local_info local;
    slang_ref_type ref;
    slang_swizzle swz;
+   struct gl_program *program;
 } slang_assemble_ctx;
 
 extern struct slang_function_ *
@@ -243,9 +265,6 @@ _slang_locate_function(const struct slang_function_scope_ *funcs,
 extern GLboolean
 _slang_assemble_function(slang_assemble_ctx *, struct slang_function_ *);
 
-extern GLboolean
-_slang_assemble_function2(slang_assemble_ctx * , struct slang_function_ *);
-
 extern GLboolean
 _slang_cleanup_stack(slang_assemble_ctx *, struct slang_operation_ *);
 
index a1038671c41215270b6702985cff767c19b6621e..dbcc4bcf9df92ab7126627af998294e8989b4f20 100644 (file)
@@ -31,6 +31,7 @@
 #include "imports.h"
 #include "slang_assemble.h"
 #include "slang_storage.h"
+#include "slang_error.h"
 
 /*
  * _slang_assemble_assignment()
@@ -95,9 +96,9 @@ assign_basic(slang_assemble_ctx * A, slang_storage_type type, GLuint * index,
     */
    dst_addr_loc = size - *index;
 
-   if (!slang_assembly_file_push_label2
-       (A->file, ty, dst_addr_loc, dst_offset))
-      return GL_FALSE;
+   if (!slang_assembly_file_push_label2(A->file, ty, dst_addr_loc, dst_offset))
+      RETURN_NIL();
+
    *index += _slang_sizeof_type(type);
 
    return GL_TRUE;
@@ -155,7 +156,7 @@ _slang_assemble_assignment(slang_assemble_ctx * A, const slang_operation * op)
    GLuint index, size;
 
    if (!slang_assembly_typeinfo_construct(&ti))
-      return GL_FALSE;
+      RETURN_OUT_OF_MEMORY();
    if (!_slang_typeof_operation(A, op, &ti))
       goto end1;
 
@@ -174,6 +175,8 @@ _slang_assemble_assignment(slang_assemble_ctx * A, const slang_operation * op)
    slang_storage_aggregate_destruct(&agg);
  end:
    slang_assembly_typeinfo_destruct(&ti);
+   if (!result)
+      RETURN_NIL();
    return result;
 }
 
index 6cd320d446626b1f75316fda8088f3bbceaf506f..a41159713036574e5cfc927c484aef8704a17e57 100644 (file)
@@ -46,6 +46,10 @@ _slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
    GLuint i;
    GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
 
+   /* init to default */
+   for (i = 0; i < 4; i++)
+      swz->swizzle[i] = i;
+
    /* the swizzle can be at most 4-component long */
    swz->num_components = slang_string_length(field);
    if (swz->num_components > 4)
@@ -109,6 +113,12 @@ _slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
    if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
       return GL_FALSE;
 
+   if (swz->num_components == 1) {
+      /* smear */
+      swz->swizzle[3] = 
+      swz->swizzle[2] = 
+      swz->swizzle[1] = swz->swizzle[0];
+   }
    return GL_TRUE;
 }
 
@@ -301,6 +311,18 @@ _slang_assemble_constructor(slang_assemble_ctx * A, const slang_operation * op)
    /* check if there are too few arguments */
    if (arg_sums[1] < size) {
       /* TODO: info log: too few arguments in constructor list */
+      /* DEBUG */
+      {
+         if (!slang_storage_aggregate_construct(&agg))
+            goto end1;
+         if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs,
+                                        A->space.structs, A->space.vars,
+                                        A->mach, A->file, A->atoms))
+            goto end2;
+         
+         /* calculate size of the constructor */
+         size = _slang_sizeof_aggregate(&agg);
+      }
       goto end;
    }
 
@@ -316,8 +338,7 @@ _slang_assemble_constructor(slang_assemble_ctx * A, const slang_operation * op)
       else
          garbage_size = 0;
 
-      if (!constructor_aggregate
-          (A, &flat, &op->children[i - 1], garbage_size))
+      if (!constructor_aggregate(A, &flat, &op->children[i - 1], garbage_size))
          goto end;
    }
 
index 265e417dadd0c93888d2ecbc5e2445198e24668a..21b31091ea772b236ee53179a9e56ad9ea2d5fdb 100644 (file)
 #include "imports.h"
 #include "slang_assemble.h"
 #include "slang_compile.h"
+#include "slang_error.h"
 
-/*
- * slang_type_specifier
- */
 
 GLvoid
 slang_type_specifier_ctr(slang_type_specifier * self)
@@ -113,7 +111,6 @@ slang_type_specifier_equal(const slang_type_specifier * x,
    return 1;
 }
 
-/* slang_assembly_typeinfo */
 
 GLboolean
 slang_assembly_typeinfo_construct(slang_assembly_typeinfo * ti)
@@ -129,7 +126,6 @@ slang_assembly_typeinfo_destruct(slang_assembly_typeinfo * ti)
    slang_type_specifier_dtr(&ti->spec);
 }
 
-/* _slang_typeof_operation() */
 
 /**
  * Determine the return type of a function.
@@ -209,7 +205,7 @@ _slang_typeof_operation_(const slang_operation * op,
    case slang_oper_preincrement:
    case slang_oper_predecrement:
       if (!_slang_typeof_operation_(op->children, space, ti, atoms))
-         return 0;
+         return GL_FALSE;
       break;
    case slang_oper_literal_bool:
    case slang_oper_logicalor:
@@ -233,12 +229,11 @@ _slang_typeof_operation_(const slang_operation * op,
    case slang_oper_identifier:
       {
          slang_variable *var;
-
          var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
          if (var == NULL)
-            return GL_FALSE;
+            RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
          if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
-            return GL_FALSE;
+            RETURN_OUT_OF_MEMORY();
          ti->can_be_referenced = GL_TRUE;
          ti->array_len = var->array_len;
       }
@@ -246,7 +241,7 @@ _slang_typeof_operation_(const slang_operation * op,
    case slang_oper_sequence:
       /* TODO: check [0] and [1] if they match */
       if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       ti->can_be_referenced = GL_FALSE;
       ti->is_swizzled = GL_FALSE;
       break;
@@ -259,7 +254,7 @@ _slang_typeof_operation_(const slang_operation * op,
    case slang_oper_select:
       /* TODO: check [1] and [2] if they match */
       if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       ti->can_be_referenced = GL_FALSE;
       ti->is_swizzled = GL_FALSE;
       break;
@@ -271,34 +266,34 @@ _slang_typeof_operation_(const slang_operation * op,
    case slang_oper_add:
       if (!typeof_existing_function("+", op->children, 2, space,
                                     &ti->spec, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_subtract:
       if (!typeof_existing_function("-", op->children, 2, space,
                                     &ti->spec, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_multiply:
       if (!typeof_existing_function("*", op->children, 2, space,
                                     &ti->spec, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
    case slang_oper_divide:
       if (!typeof_existing_function("/", op->children, 2, space,
                                     &ti->spec, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       break;
       /*case slang_oper_modulus: */
    case slang_oper_plus:
       if (!_slang_typeof_operation_(op->children, space, ti, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       ti->can_be_referenced = GL_FALSE;
       ti->is_swizzled = GL_FALSE;
       break;
    case slang_oper_minus:
-      if (!typeof_existing_function
-          ("-", op->children, 1, space, &ti->spec, atoms))
-         return GL_FALSE;
+      if (!typeof_existing_function("-", op->children, 1, space,
+                                    &ti->spec, atoms))
+         RETURN_NIL();
       break;
       /*case slang_oper_complement: */
    case slang_oper_subscript:
@@ -306,23 +301,23 @@ _slang_typeof_operation_(const slang_operation * op,
          slang_assembly_typeinfo _ti;
 
          if (!slang_assembly_typeinfo_construct(&_ti))
-            return GL_FALSE;
+            RETURN_NIL();
          if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
             slang_assembly_typeinfo_destruct(&_ti);
-            return GL_FALSE;
+            RETURN_NIL();
          }
          ti->can_be_referenced = _ti.can_be_referenced;
          if (_ti.spec.type == slang_spec_array) {
             if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
                slang_assembly_typeinfo_destruct(&_ti);
-               return GL_FALSE;
+               RETURN_NIL();
             }
          }
          else {
             if (!_slang_type_is_vector(_ti.spec.type)
                 && !_slang_type_is_matrix(_ti.spec.type)) {
                slang_assembly_typeinfo_destruct(&_ti);
-               return GL_FALSE;
+               RETURN_ERROR("cannot index a non-array type", 0);
             }
             ti->spec.type = _slang_type_base(_ti.spec.type);
          }
@@ -335,7 +330,7 @@ _slang_typeof_operation_(const slang_operation * op,
 
          if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
                                      space, &ti->spec, &exists, atoms))
-            return GL_FALSE;
+            RETURN_NIL();
          if (!exists) {
             slang_struct *s =
                slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
@@ -344,14 +339,14 @@ _slang_typeof_operation_(const slang_operation * op,
                ti->spec._struct =
                   (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
                if (ti->spec._struct == NULL)
-                  return GL_FALSE;
+                  RETURN_NIL();
                if (!slang_struct_construct(ti->spec._struct)) {
                   slang_alloc_free(ti->spec._struct);
                   ti->spec._struct = NULL;
-                  return GL_FALSE;
+                  RETURN_NIL();
                }
                if (!slang_struct_copy(ti->spec._struct, s))
-                  return GL_FALSE;
+                  RETURN_NIL();
             }
             else {
                const char *name;
@@ -360,7 +355,7 @@ _slang_typeof_operation_(const slang_operation * op,
                name = slang_atom_pool_id(atoms, op->a_id);
                type = slang_type_specifier_type_from_string(name);
                if (type == slang_spec_void)
-                  return GL_FALSE;
+                  RETURN_ERROR2("function not found", name, 0);
                ti->spec.type = type;
             }
          }
@@ -371,24 +366,23 @@ _slang_typeof_operation_(const slang_operation * op,
          slang_assembly_typeinfo _ti;
 
          if (!slang_assembly_typeinfo_construct(&_ti))
-            return GL_FALSE;
+            RETURN_NIL();
          if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
             slang_assembly_typeinfo_destruct(&_ti);
-            return GL_FALSE;
+            RETURN_NIL();
          }
          if (_ti.spec.type == slang_spec_struct) {
             slang_variable *field;
 
-            field =
-               _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
-                                      GL_FALSE);
+            field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
+                                           GL_FALSE);
             if (field == NULL) {
                slang_assembly_typeinfo_destruct(&_ti);
-               return GL_FALSE;
+               RETURN_NIL();
             }
             if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
                slang_assembly_typeinfo_destruct(&_ti);
-               return GL_FALSE;
+               RETURN_NIL();
             }
             ti->can_be_referenced = _ti.can_be_referenced;
          }
@@ -398,15 +392,17 @@ _slang_typeof_operation_(const slang_operation * op,
             slang_type_specifier_type base;
 
             /* determine the swizzle of the field expression */
+#if 000
             if (!_slang_type_is_vector(_ti.spec.type)) {
                slang_assembly_typeinfo_destruct(&_ti);
-               return GL_FALSE;
+               RETURN_ERROR("Can't swizzle scalar expression", 0);
             }
+#endif
             rows = _slang_type_dim(_ti.spec.type);
             swizzle = slang_atom_pool_id(atoms, op->a_id);
             if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
                slang_assembly_typeinfo_destruct(&_ti);
-               return GL_FALSE;
+               RETURN_ERROR("Bad swizzle", 0);
             }
             ti->is_swizzled = GL_TRUE;
             ti->can_be_referenced = _ti.can_be_referenced
@@ -478,12 +474,12 @@ _slang_typeof_operation_(const slang_operation * op,
    case slang_oper_postincrement:
    case slang_oper_postdecrement:
       if (!_slang_typeof_operation_(op->children, space, ti, atoms))
-         return GL_FALSE;
+         RETURN_NIL();
       ti->can_be_referenced = GL_FALSE;
       ti->is_swizzled = GL_FALSE;
       break;
    default:
-      return GL_FALSE;
+      RETURN_NIL();
    }
 
    return GL_TRUE;
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
new file mode 100644 (file)
index 0000000..e428209
--- /dev/null
@@ -0,0 +1,1272 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_codegen.c
+ * Mesa GLSL code generator.  Convert AST to IR tree.
+ * \author Brian Paul
+ */
+
+#include "imports.h"
+#include "macros.h"
+#include "slang_assemble.h"
+#include "slang_codegen.h"
+#include "slang_compile.h"
+#include "slang_storage.h"
+#include "slang_error.h"
+#include "slang_simplify.h"
+#include "slang_emit.h"
+#include "slang_ir.h"
+#include "mtypes.h"
+#include "program.h"
+#include "slang_print.h"
+
+
+static slang_function *CurFunction = NULL;
+
+
+static slang_ir_node *
+slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper);
+
+
+
+/**
+ * Allocate storage for given variable, attach it to 'ir'.
+ */
+static GLboolean
+slang_alloc_var_storage(slang_variable *variable, slang_ir_node *ir)
+{
+   slang_ir_storage *store;
+
+   assert(variable);
+
+   /*assert(!variable->aux);*/
+
+   if (variable->aux) {
+      store = (slang_ir_storage *) variable->aux;
+      ir->Store = store;
+      if (store)
+         store->Size = -12;
+   }
+   else {
+      /* alloc storage */
+      store = (slang_ir_storage *) _mesa_calloc(sizeof(*store));
+      store->File = PROGRAM_TEMPORARY;
+      store->Index = -1;
+      store->Size = -10;
+      variable->aux = store;
+      ir->Store = store;
+   }
+   return GL_TRUE;
+}
+
+
+static slang_ir_node *
+new_node(slang_ir_opcode op, slang_ir_node *left, slang_ir_node *right)
+{
+   slang_ir_node *n = (slang_ir_node *) calloc(1, sizeof(slang_ir_node));
+   if (n) {
+      n->Opcode = op;
+      n->Children[0] = left;
+      n->Children[1] = right;
+      n->Swizzle = SWIZZLE_NOOP;
+      n->Writemask = WRITEMASK_XYZW;
+   }
+   return n;
+}
+
+static slang_ir_node *
+new_seq(slang_ir_node *left, slang_ir_node *right)
+{
+   assert(left);
+   assert(right);
+   return new_node(IR_SEQ, left, right);
+}
+
+static slang_ir_node *
+new_label(const char *name)
+{
+   slang_ir_node *n = new_node(IR_LABEL, NULL, NULL);
+   n->Target = _mesa_strdup(name);
+   return n;
+}
+
+static slang_ir_node *
+new_float_literal(float x, float y, float z, float w)
+{
+   slang_ir_node *n = new_node(IR_FLOAT, NULL, NULL);
+   n->Value[0] = x;
+   n->Value[1] = y;
+   n->Value[2] = z;
+   n->Value[3] = w;
+   return n;
+}
+
+static slang_ir_node *
+new_cjump(slang_ir_node *cond, const char *target)
+{
+   slang_ir_node *n = new_node(IR_CJUMP, cond, NULL);
+   n->Target = _mesa_strdup(target);
+   return n;
+}
+
+static slang_ir_node *
+new_jump(const char *target)
+{
+   slang_ir_node *n = new_node(IR_JUMP, NULL, NULL);
+   if (n) {
+      n->Target = _mesa_strdup(target);
+   }
+   return n;
+}
+
+
+/**
+ * New IR_VAR_DECL node - allocate storage for a new variable.
+ */
+static slang_ir_node *
+new_var_decl(slang_assemble_ctx *A, slang_variable *v)
+{
+   slang_ir_node *n = new_node(IR_VAR_DECL, NULL, NULL);
+   if (n) {
+      n->Var = v;
+      v->declared = GL_TRUE;
+   }
+   return n;
+}
+
+
+/**
+ * New IR_VAR node - a reference to a previously declared variable.
+ */
+static slang_ir_node *
+new_var(slang_assemble_ctx *A, slang_operation *oper,
+        slang_atom name, GLuint swizzle)
+{
+   slang_variable *v = _slang_locate_variable(oper->locals, name, GL_TRUE);
+   slang_ir_node *n = new_node(IR_VAR, NULL, NULL);
+   if (!v) {
+      printf("VAR NOT FOUND %s\n", (char *) name);
+      assert(v);
+   }
+   /** 
+   assert(v->declared);
+   **/
+   assert(!oper->var || oper->var == v);
+   v->used = GL_TRUE;
+   oper->var = v;
+   n->Swizzle = swizzle;
+   n->Var = v;
+   slang_resolve_storage(NULL, n, A->program);
+   return n;
+}
+
+
+static GLboolean
+slang_is_writemask(const char *field, GLuint *mask)
+{
+   const GLuint n = 4;
+   GLuint i, bit, c = 0;
+
+   for (i = 0; i < n && field[i]; i++) {
+      switch (field[i]) {
+      case 'x':
+      case 'r':
+         bit = WRITEMASK_X;
+         break;
+      case 'y':
+      case 'g':
+         bit = WRITEMASK_Y;
+         break;
+      case 'z':
+      case 'b':
+         bit = WRITEMASK_Z;
+         break;
+      case 'w':
+      case 'a':
+         bit = WRITEMASK_W;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      if (c & bit)
+         return GL_FALSE;
+      c |= bit;
+   }
+   *mask = c;
+   return GL_TRUE;
+}
+
+
+static slang_ir_node *
+slang_assemble_return(slang_assemble_ctx * A, slang_operation *oper)
+{
+   if (oper->num_children == 0) {
+      /* Convert to:
+       *   goto __endOfFunction;
+       */
+      oper->type = slang_oper_goto;
+      oper->a_id = slang_atom_pool_atom(A->atoms, CurFunction->end_label);
+   }
+   else {
+      /*
+       * Convert from:
+       *   return expr;
+       * To:
+       *   __retVal = expr;
+       *   goto __endOfFunction;
+       */
+      slang_operation *block, *assign, *jump;
+      slang_atom a_retVal;
+
+      a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
+      assert(a_retVal);
+
+#if 1
+      {
+         slang_variable *v
+            = _slang_locate_variable(oper->locals, a_retVal, GL_TRUE);
+         assert(v);
+      }
+#endif
+
+      block = slang_operation_new(1);
+      block->type = slang_oper_block_no_new_scope;
+      block->num_children = 2;
+      block->children = slang_operation_new(2);
+      assert(block->locals);
+      block->locals->outer_scope = oper->locals->outer_scope;
+
+      /* child[0]: __retVal = expr; */
+      assign = &block->children[0];
+      assign->type = slang_oper_assign;
+      assign->locals->outer_scope = block->locals;
+      assign->num_children = 2;
+      assign->children = slang_operation_new(2);
+      /* lhs */
+      assign->children[0].type = slang_oper_identifier;
+      assign->children[0].a_id = a_retVal;
+      assign->children[0].locals->outer_scope = assign->locals;
+      /* rhs */
+#if 0
+      assign->children[1] = oper->children[0]; /* XXX copy */
+#else
+      slang_operation_copy(&assign->children[1], &oper->children[0]);
+#endif
+
+
+      /* child[1]: goto __endOfFunction */
+      jump = &block->children[1];
+      jump->type = slang_oper_goto;
+      assert(CurFunction->end_label);
+      jump->a_id = slang_atom_pool_atom(A->atoms, CurFunction->end_label);
+
+#if 00
+      printf("NEW RETURN:\n");
+      slang_print_tree(block, 0);
+#endif
+
+      slang_operation_copy(oper, block);
+      /* XXX destruct block */
+   }
+
+   /* assemble the new code */
+   return slang_assemble_operation(A, oper);
+}
+
+
+
+/**
+ * Check if the given function is really just a wrapper for an
+ * basic assembly instruction.
+ */
+static GLboolean
+slang_is_asm_function(const slang_function *fun)
+{
+   if (fun->body->type == slang_oper_block_no_new_scope &&
+       fun->body->num_children == 1 &&
+       fun->body->children[0].type == slang_oper_asm) {
+      return GL_TRUE;
+   }
+   return GL_FALSE;
+}
+
+
+/**
+ * Produce inline code for a call to an assembly instruction.
+ */
+static slang_operation *
+slang_inline_asm_function(slang_assemble_ctx *A,
+                          slang_function *fun, slang_operation *oper)
+{
+   const int numArgs = oper->num_children;
+   const slang_operation *args = oper->children;
+   GLuint i;
+   slang_operation *inlined = slang_operation_new(1);
+
+   /*assert(oper->type == slang_oper_call);  or vec4_add, etc */
+
+   inlined->type = fun->body->children[0].type;
+   inlined->a_id = fun->body->children[0].a_id;
+   inlined->num_children = numArgs;
+   inlined->children = slang_operation_new(numArgs);
+#if 0
+   inlined->locals = slang_variable_scope_copy(oper->locals);
+#else
+   assert(inlined->locals);
+   inlined->locals->outer_scope = oper->locals->outer_scope;
+#endif
+
+   for (i = 0; i < numArgs; i++) {
+      slang_operation_copy(inlined->children + i, args + i);
+   }
+
+   return inlined;
+}
+
+
+static void
+slang_resolve_variable(slang_operation *oper)
+{
+   if (oper->type != slang_oper_identifier)
+      return;
+   if (!oper->var) {
+      oper->var = _slang_locate_variable(oper->locals,
+                                         (const slang_atom) oper->a_id,
+                                         GL_TRUE);
+      if (oper->var)
+         oper->var->used = GL_TRUE;
+   }
+}
+
+
+/**
+ * Replace particular variables (slang_oper_identifier) with new expressions.
+ */
+static void
+slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
+                 GLuint substCount, slang_variable **substOld,
+                slang_operation **substNew, GLboolean isLHS)
+{
+   switch (oper->type) {
+   case slang_oper_variable_decl:
+      {
+         slang_variable *v = _slang_locate_variable(oper->locals,
+                                                    oper->a_id, GL_TRUE);
+         assert(v);
+         if (v->initializer && oper->num_children == 0) {
+            /* set child of oper to copy of initializer */
+            oper->num_children = 1;
+            oper->children = slang_operation_new(1);
+            slang_operation_copy(&oper->children[0], v->initializer);
+         }
+         if (oper->num_children == 1) {
+            /* the initializer */
+            slang_substitute(A, &oper->children[0], substCount, substOld, substNew, GL_FALSE);
+         }
+      }
+      break;
+   case slang_oper_identifier:
+      assert(oper->num_children == 0);
+      if (1/**!isLHS XXX FIX */) {
+         slang_atom id = oper->a_id;
+         slang_variable *v;
+        GLuint i;
+         v = _slang_locate_variable(oper->locals, id, GL_TRUE);
+        if (!v) {
+           printf("var %s not found!\n", (char *) oper->a_id);
+           break;
+        }
+
+        /* look for a substitution */
+        for (i = 0; i < substCount; i++) {
+           if (v == substOld[i]) {
+               /* OK, replace this slang_oper_identifier with a new expr */
+              assert(substNew[i]->type == slang_oper_identifier ||
+                      substNew[i]->type == slang_oper_literal_float);
+#if 1 /* DEBUG only */
+              if (substNew[i]->type == slang_oper_identifier) {
+                  assert(substNew[i]->var);
+                  assert(substNew[i]->var->a_name);
+                 printf("Substitute %s with %s in id node %p\n",
+                        (char*)v->a_name, (char*) substNew[i]->var->a_name,
+                        (void*) oper);
+               }
+              else
+                 printf("Substitute %s with %f in id node %p\n",
+                        (char*)v->a_name, substNew[i]->literal[0],
+                        (void*) oper);
+#endif
+              slang_operation_copy(oper, substNew[i]);
+              break;
+           }
+        }
+      }
+      break;
+   case slang_oper_return:
+      /* do return replacement here too */
+      slang_assemble_return(A, oper);
+      slang_substitute(A, oper, substCount, substOld, substNew, GL_FALSE);
+      break;
+   case slang_oper_assign:
+   case slang_oper_subscript:
+      /* special case:
+       * child[0] can't have substitutions but child[1] can.
+       */
+      slang_substitute(A, &oper->children[0], substCount, substOld, substNew, GL_TRUE);
+      slang_substitute(A, &oper->children[1], substCount, substOld, substNew, GL_FALSE);
+      break;
+   case slang_oper_field:
+      /* XXX NEW - test */
+      slang_substitute(A, &oper->children[0], substCount, substOld, substNew, GL_TRUE);
+      break;
+   default:
+      {
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) 
+            slang_substitute(A, &oper->children[i], substCount, substOld, substNew, GL_FALSE);
+      }
+   }
+}
+
+
+
+/**
+ * Inline the given function call operation.
+ * Return a new slang_operation that corresponds to the inlined code.
+ */
+static slang_operation *
+slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
+                          slang_operation *oper, slang_operation *returnOper)
+{
+   typedef enum {
+      SUBST = 1,
+      COPY_IN,
+      COPY_OUT
+   } ParamMode;
+   ParamMode *paramMode;
+   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+   const GLuint numArgs = oper->num_children;
+   const GLuint totalArgs = numArgs + haveRetValue;
+   slang_operation *args = oper->children;
+   slang_operation *inlined, *top;
+   slang_variable **substOld;
+   slang_operation **substNew;
+   GLuint substCount, numCopyIn, i;
+
+   /*assert(oper->type == slang_oper_call); (or (matrix) multiply, etc) */
+   assert(fun->param_count == totalArgs);
+
+   /* allocate temporary arrays */
+   paramMode = (ParamMode *)
+      _mesa_calloc(totalArgs * sizeof(ParamMode));
+   substOld = (slang_variable **)
+      _mesa_calloc(totalArgs * sizeof(slang_variable *));
+   substNew = (slang_operation **)
+      _mesa_calloc(totalArgs * sizeof(slang_operation *));
+
+   printf("\nInline call to %s  (total vars=%d  nparams=%d)\n",
+         (char *) fun->header.a_name,
+         fun->parameters->num_variables, numArgs);
+
+
+   if (haveRetValue && !returnOper) {
+      /* Create comma sequence for inlined code, the left child will be the
+       * function body and the right child will be a variable (__retVal)
+       * that will get the return value.
+       */
+      slang_operation *commaSeq;
+      slang_operation *declOper = NULL;
+      slang_variable *resultVar;
+
+      commaSeq = slang_operation_new(1);
+      commaSeq->type = slang_oper_sequence;
+      assert(commaSeq->locals);
+      commaSeq->locals->outer_scope = oper->locals->outer_scope;
+      commaSeq->num_children = 3;
+      commaSeq->children = slang_operation_new(3);
+      /* allocate the return var */
+      resultVar = slang_variable_scope_grow(commaSeq->locals);
+      /*
+      printf("ALLOC __retVal from scope %p\n", (void*) commaSeq->locals);
+      */
+      printf("Alloc __resultTemp in scope %p for retval of calling %s\n",
+             (void*)commaSeq->locals, (char *) fun->header.a_name);
+
+      resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");
+      resultVar->type = fun->header.type; /* XXX copy? */
+      /*resultVar->type.qualifier = slang_qual_out;*/
+
+      /* child[0] = __resultTmp declaration */
+      declOper = &commaSeq->children[0];
+      declOper->type = slang_oper_variable_decl;
+      declOper->a_id = resultVar->a_name;
+      declOper->locals->outer_scope = commaSeq->locals; /*** ??? **/
+
+      /* child[1] = function body */
+      inlined = &commaSeq->children[1];
+      /* XXXX this may be inappropriate!!!!: */
+      inlined->locals->outer_scope = commaSeq->locals;
+
+      /* child[2] = __resultTmp reference */
+      returnOper = &commaSeq->children[2];
+      returnOper->type = slang_oper_identifier;
+      returnOper->a_id = resultVar->a_name;
+      returnOper->locals->outer_scope = commaSeq->locals;
+      declOper->locals->outer_scope = commaSeq->locals;
+
+      top = commaSeq;
+   }
+   else {
+      top = inlined = slang_operation_new(1);
+      /* XXXX this may be inappropriate!!!! */
+      inlined->locals->outer_scope = oper->locals->outer_scope;
+   }
+
+
+   assert(inlined->locals);
+
+   /* Examine the parameters, look for inout/out params, look for possible
+    * substitutions, etc:
+    *    param type      behaviour
+    *     in             copy actual to local
+    *     const in       substitute param with actual
+    *     out            copy out
+    */
+   substCount = 0;
+   for (i = 0; i < totalArgs; i++) {
+      slang_variable *p = &fun->parameters->variables[i];
+      printf("Param %d: %s %s \n", i,
+             slang_type_qual_string(p->type.qualifier),
+            (char *) p->a_name);
+      if (p->type.qualifier == slang_qual_inout ||
+         p->type.qualifier == slang_qual_out) {
+        /* an output param */
+         slang_operation *arg;
+         if (i < numArgs)
+            arg = &args[i];
+         else
+            arg = returnOper;
+        paramMode[i] = SUBST;
+        assert(arg->type == slang_oper_identifier
+               /*||arg->type == slang_oper_variable_decl*/);
+         slang_resolve_variable(arg);
+         /* replace parameter 'p' with argument 'arg' */
+        substOld[substCount] = p;
+        substNew[substCount] = arg; /* will get copied */
+        substCount++;
+      }
+      else if (p->type.qualifier == slang_qual_const) {
+        /* a constant input param */
+        if (args[i].type == slang_oper_identifier ||
+            args[i].type == slang_oper_literal_float) {
+           /* replace all occurances of this parameter variable with the
+            * actual argument variable or a literal.
+            */
+           paramMode[i] = SUBST;
+            slang_resolve_variable(&args[i]);
+           substOld[substCount] = p;
+           substNew[substCount] = &args[i]; /* will get copied */
+           substCount++;
+        }
+        else {
+           paramMode[i] = COPY_IN;
+        }
+      }
+      else {
+        paramMode[i] = COPY_IN;
+      }
+      assert(paramMode[i]);
+   }
+
+#if 00
+   printf("ABOUT to inline body %p with checksum %d\n",
+          (char *) fun->body, slang_checksum_tree(fun->body));
+#endif
+
+   /* actual code inlining: */
+   slang_operation_copy(inlined, fun->body);
+
+#if 000
+   printf("======================= orig body code ======================\n");
+   printf("=== params scope = %p\n", (void*) fun->parameters);
+   slang_print_tree(fun->body, 8);
+   printf("======================= copied code =========================\n");
+   slang_print_tree(inlined, 8);
+#endif
+
+   /* do parameter substitution in inlined code: */
+   slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
+
+#if 000
+   printf("======================= subst code ==========================\n");
+   slang_print_tree(inlined, 8);
+   printf("=============================================================\n");
+#endif
+
+   /* New prolog statements: (inserted before the inlined code)
+    * Copy the 'in' arguments.
+    */
+   numCopyIn = 0;
+   for (i = 0; i < numArgs; i++) {
+      if (paramMode[i] == COPY_IN) {
+        slang_variable *p = &fun->parameters->variables[i];
+        /* declare parameter 'p' */
+        slang_operation *decl = slang_operation_insert(&inlined->num_children,
+                                                       &inlined->children,
+                                                       numCopyIn);
+         printf("COPY_IN %s from expr\n", (char*)p->a_name);
+        decl->type = slang_oper_variable_decl;
+         assert(decl->locals);
+        decl->locals = fun->parameters;
+        decl->a_id = p->a_name;
+        decl->num_children = 1;
+        decl->children = slang_operation_new(1);
+
+         /* child[0] is the var's initializer */
+         slang_operation_copy(&decl->children[0], args + i);
+
+        numCopyIn++;
+      }
+   }
+
+   /* New epilog statements:
+    * 1. Create end of function label to jump to from return statements.
+    * 2. Copy the 'out' parameter vars
+    */
+   {
+      slang_operation *lab = slang_operation_insert(&inlined->num_children,
+                                                    &inlined->children,
+                                                    inlined->num_children);
+      lab->type = slang_oper_label;
+      lab->a_id = slang_atom_pool_atom(A->atoms, CurFunction->end_label);
+   }
+
+   for (i = 0; i < totalArgs; i++) {
+      if (paramMode[i] == COPY_OUT) {
+        const slang_variable *p = &fun->parameters->variables[i];
+        /* actualCallVar = outParam */
+        /*if (i > 0 || !haveRetValue)*/
+        slang_operation *ass = slang_operation_insert(&inlined->num_children,
+                                                      &inlined->children,
+                                                      inlined->num_children);
+        ass->type = slang_oper_assign;
+        ass->num_children = 2;
+        ass->locals = _slang_variable_scope_new(inlined->locals);
+        assert(ass->locals);
+        ass->children = slang_operation_new(2);
+        ass->children[0] = args[i]; /*XXX copy */
+        ass->children[1].type = slang_oper_identifier;
+        ass->children[1].a_id = p->a_name;
+        ass->children[1].locals = _slang_variable_scope_new(ass->locals);
+      }
+   }
+
+   _mesa_free(paramMode);
+   _mesa_free(substOld);
+   _mesa_free(substNew);
+
+   printf("Done Inline call to %s  (total vars=%d  nparams=%d)\n",
+         (char *) fun->header.a_name,
+         fun->parameters->num_variables, numArgs);
+
+   return top;
+}
+
+
+static slang_ir_node *
+slang_assemble_function_call(slang_assemble_ctx *A, slang_function *fun,
+                            slang_operation *oper, slang_operation *dest)
+{
+   slang_ir_node *n;
+   slang_operation *inlined;
+   slang_function *prevFunc;
+
+   prevFunc = CurFunction;
+   CurFunction = fun;
+
+   if (!CurFunction->end_label) {
+      char name[200];
+      sprintf(name, "__endOfFunc_%s_", (char *) CurFunction->header.a_name);
+      CurFunction->end_label = slang_atom_pool_gen(A->atoms, name);
+   }
+
+   if (slang_is_asm_function(fun) && !dest) {
+      /* assemble assembly function - tree style */
+      inlined = slang_inline_asm_function(A, fun, oper);
+   }
+   else {
+      /* non-assembly function */
+      inlined = slang_inline_function_call(A, fun, oper, dest);
+   }
+
+   /* Replace the function call with the inlined block */
+#if 0
+   slang_operation_construct(oper);
+   slang_operation_copy(oper, inlined);
+#else
+   *oper = *inlined;
+#endif
+
+
+#if 1
+   assert(inlined->locals);
+   printf("*** Inlined code for call to %s:\n",
+          (char*) fun->header.a_name);
+
+   slang_print_tree(oper, 10);
+   printf("\n");
+#endif
+
+   /* assemble what we just made XXX here??? */
+   n = slang_assemble_operation(A, oper);
+
+   CurFunction = prevFunc;
+
+   return n;
+}
+
+
+/**
+ * Map "_asm foo" to IR_FOO, etc.
+ */
+typedef struct
+{
+   const char *Name;
+   slang_ir_opcode Opcode;
+   GLuint HaveRetValue, NumParams;
+} slang_asm_info;
+
+
+static slang_asm_info AsmInfo[] = {
+   /* vec4 binary op */
+   { "vec4_add", IR_ADD, 1, 2 },
+   { "vec4_multiply", IR_MUL, 1, 2 },
+   { "vec4_dot", IR_DOT4, 1, 2 },
+   { "vec3_dot", IR_DOT3, 1, 2 },
+   { "vec3_cross", IR_CROSS, 1, 2 },
+   { "vec4_min", IR_MIN, 1, 2 },
+   { "vec4_max", IR_MAX, 1, 2 },
+   { "vec4_seq", IR_SEQ, 1, 2 },
+   { "vec4_sge", IR_SGE, 1, 2 },
+   { "vec4_sgt", IR_SGT, 1, 2 },
+   /* vec4 unary */
+   { "vec4_floor", IR_FLOOR, 1, 1 },
+   { "vec4_frac", IR_FRAC, 1, 1 },
+   { "vec4_abs", IR_ABS, 1, 1 },
+   /* float binary op */
+   { "float_add", IR_ADD, 1, 2 },
+   { "float_subtract", IR_SUB, 1, 2 },
+   { "float_multiply", IR_MUL, 1, 2 },
+   { "float_divide", IR_DIV, 1, 2 },
+   { "float_power", IR_POW, 1, 2 },
+   /* unary op */
+   { "int_to_float", IR_I_TO_F, 1, 1 },
+   { "float_exp", IR_EXP, 1, 1 },
+   { "float_exp2", IR_EXP2, 1, 1 },
+   { "float_log2", IR_LOG2, 1, 1 },
+   { "float_rsq", IR_RSQ, 1, 1 },
+   { "float_rcp", IR_RCP, 1, 1 },
+   { "float_sine", IR_SIN, 1, 1 },
+   { "float_cosine", IR_COS, 1, 1 },
+   { NULL, IR_NOP, 0, 0 }
+};
+
+
+static slang_asm_info *
+slang_find_asm_info(const char *name)
+{
+   GLuint i;
+   for (i = 0; AsmInfo[i].Name; i++) {
+      if (_mesa_strcmp(AsmInfo[i].Name, name) == 0) {
+         return AsmInfo + i;
+      }
+   }
+   return NULL;
+}
+
+
+static GLuint
+make_writemask(char *field)
+{
+   GLuint mask = 0x0;
+   while (*field) {
+      switch (*field) {
+      case 'x':
+         mask |= WRITEMASK_X;
+         break;
+      case 'y':
+         mask |= WRITEMASK_Y;
+         break;
+      case 'z':
+         mask |= WRITEMASK_Z;
+         break;
+      case 'w':
+         mask |= WRITEMASK_W;
+         break;
+      default:
+         abort();
+      }
+      field++;
+   }
+   if (mask == 0x0)
+      return WRITEMASK_XYZW;
+   else
+      return mask;
+}
+
+
+/**
+ * Generate IR code for an instruction/operation such as:
+ *    __asm vec4_dot __retVal.x, v1, v2;
+ */
+static slang_ir_node *
+slang_assemble_asm(slang_assemble_ctx *A, slang_operation *oper,
+                   slang_operation *dest)
+{
+   const slang_asm_info *info;
+   slang_ir_node *kids[2], *n;
+   GLuint j, firstOperand;
+
+   assert(oper->type == slang_oper_asm);
+
+   info = slang_find_asm_info((char *) oper->a_id);
+   assert(info);
+   assert(info->NumParams <= 2);
+
+   if (info->NumParams == oper->num_children) {
+      /* storage for result not specified */
+      firstOperand = 0;
+   }
+   else {
+      /* storage for result (child[0]) is specified */
+      firstOperand = 1;
+   }
+
+   /* assemble child(ren) */
+   kids[0] = kids[1] = NULL;
+   for (j = 0; j < info->NumParams; j++) {
+      kids[j] = slang_assemble_operation(A, &oper->children[firstOperand + j]);
+   }
+
+   n = new_node(info->Opcode, kids[0], kids[1]);
+
+   if (firstOperand) {
+      /* Setup n->Store to be a particular location.  Otherwise, storage
+       * for the result (a temporary) will be allocated later.
+       */
+      GLuint writemask = WRITEMASK_XYZW;
+      slang_operation *dest_oper;
+      slang_ir_node *n0;
+
+      dest_oper = &oper->children[0];
+      if (dest_oper->type == slang_oper_field) {
+         /* writemask */
+         writemask = make_writemask((char*) dest_oper->a_id);
+         dest_oper = &dest_oper->children[0];
+      }
+
+      assert(dest_oper->type == slang_oper_identifier);
+      n0 = slang_assemble_operation(A, dest_oper);
+      assert(n0->Var);
+      assert(n0->Store);
+      free(n0);
+
+      n->Store = n0->Store;
+      n->Writemask = writemask;
+   }
+
+   return n;
+}
+
+
+
+
+
+/**
+ * Assemble a function call, given a particular function name.
+ * \param name  the function's name (operators like '*' are possible).
+ */
+static slang_ir_node *
+slang_assemble_function_call_name(slang_assemble_ctx *A, const char *name,
+                                 slang_operation *oper, slang_operation *dest)
+{
+   slang_operation *params = oper->children;
+   const GLuint param_count = oper->num_children;
+   slang_atom atom;
+   slang_function *fun;
+
+   atom = slang_atom_pool_atom(A->atoms, name);
+   if (atom == SLANG_ATOM_NULL)
+      return NULL;
+
+   fun = _slang_locate_function(A->space.funcs, atom, params, param_count,
+                               &A->space, A->atoms);
+   if (!fun) {
+      RETURN_ERROR2("Undefined function", name, 0);
+   }
+
+   return slang_assemble_function_call(A, fun, oper, dest);
+}
+
+
+static slang_ir_node *
+slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
+{
+   switch (oper->type) {
+   case slang_oper_block_no_new_scope:
+   case slang_oper_block_new_scope:
+      /* list of operations */
+      assert(oper->num_children > 0);
+      {
+         slang_ir_node *n, *first = NULL;
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            n = slang_assemble_operation(A, &oper->children[i]);
+            first = first ? new_seq(first, n) : n;
+         }
+         return first;
+      }
+      break;
+   case slang_oper_expression:
+      return slang_assemble_operation(A, &oper->children[0]);
+      break;
+   case slang_oper_while:
+      {
+         slang_ir_node *nStartLabel = new_label("while-start");
+         slang_ir_node *nCond = slang_assemble_operation(A, &oper->children[0]);
+         slang_ir_node *nNotCond = new_node(IR_NOT, nCond, NULL);
+         slang_ir_node *nBody = slang_assemble_operation(A, &oper->children[1]);
+         slang_ir_node *nEndLabel = new_label("while-end");
+         slang_ir_node *nCJump = new_cjump(nNotCond, "while-end");
+         slang_ir_node *nJump = new_jump("while-start");
+
+         return new_seq(nStartLabel,
+                        new_seq(nCJump,
+                                new_seq(nBody,
+                                        new_seq(nJump,
+                                                nEndLabel)
+                                        )
+                                )
+                        );
+      }
+      break;
+   case slang_oper_less:
+      return new_node(IR_LESS,
+                      slang_assemble_operation(A, &oper->children[0]),
+                      slang_assemble_operation(A, &oper->children[1]));
+   case slang_oper_add:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = slang_assemble_function_call_name(A, "+", oper, NULL);
+        return n;
+      }
+   case slang_oper_subtract:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = slang_assemble_function_call_name(A, "-", oper, NULL);
+        return n;
+      }
+   case slang_oper_multiply:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+         n = slang_assemble_function_call_name(A, "*", oper, NULL);
+        return n;
+      }
+   case slang_oper_divide:
+      {
+         slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = slang_assemble_function_call_name(A, "/", oper, NULL);
+        return n;
+      }
+
+   case slang_oper_variable_decl:
+      {
+         slang_ir_node *n;
+         slang_ir_node *varDecl;
+         slang_variable *v;
+
+         assert(oper->num_children == 0 || oper->num_children == 1);
+
+         v = _slang_locate_variable(oper->locals,
+                                    oper->a_id, GL_TRUE);
+         assert(v);
+         varDecl = new_var_decl(A, v);
+         slang_alloc_var_storage(v, varDecl);
+
+         if (oper->num_children > 0) {
+            /* child is initializer */
+            slang_ir_node *var, *init, *rhs;
+            assert(oper->num_children == 1);
+            var = new_var(A, oper, oper->a_id, SWIZZLE_NOOP);
+            /* XXX make copy of this initializer? */
+            printf("\n*** ASSEMBLE INITIALIZER %p\n", (void*) v->initializer);
+            rhs = slang_assemble_operation(A, &oper->children[0]);
+            init = new_node(IR_MOVE, var, rhs);
+            n = new_seq(varDecl, init);
+         }
+         else if (v->initializer) {
+            slang_ir_node *var, *init, *rhs;
+            var = new_var(A, oper, oper->a_id, SWIZZLE_NOOP);
+            /* XXX make copy of this initializer? */
+            printf("\n*** ASSEMBLE INITIALIZER %p\n", (void*) v->initializer);
+            rhs = slang_assemble_operation(A, v->initializer);
+            init = new_node(IR_MOVE, var, rhs);
+            n = new_seq(varDecl, init);
+         }
+         else {
+            n = varDecl;
+         }
+         return n;
+      }
+      break;
+   case slang_oper_assign:
+      /* assignment */
+      /* XXX look for special case of:  x = f(a, b)
+       * and replace with f(a, b, x)  (where x == hidden __retVal out param)
+       */
+      if (oper->children[0].type == slang_oper_identifier &&
+          oper->children[1].type == slang_oper_call) {
+         /* special case */
+         slang_ir_node *n;
+         printf(">>>>>>>>>>>>>> Assign function call\n");
+         n = slang_assemble_function_call_name(A,
+                                               (const char *) oper->children[1].a_id,
+                                              &oper->children[1], &oper->children[0]);
+         return n;
+      }
+      else
+      {
+        slang_operation *lhs = &oper->children[0];
+        slang_ir_node *n, *c0, *c1;
+        GLuint mask = WRITEMASK_XYZW;
+        if (lhs->type == slang_oper_field) {
+           /* writemask */
+           if (!slang_is_writemask((char *) lhs->a_id, &mask))
+              mask = WRITEMASK_XYZW;
+           lhs = &lhs->children[0];
+        }
+         c0 = slang_assemble_operation(A, lhs);
+         c1 = slang_assemble_operation(A, &oper->children[1]);
+
+         n = new_node(IR_MOVE, c0, c1);
+        n->Writemask = mask;
+        return n;
+      }
+      break;
+   case slang_oper_asm:
+      return slang_assemble_asm(A, oper, NULL);
+   case slang_oper_call:
+      return slang_assemble_function_call_name(A, (const char *) oper->a_id,
+                                              oper, NULL);
+      break;
+   case slang_oper_return:
+      return slang_assemble_return(A, oper);
+   case slang_oper_goto:
+      return new_jump((char*) oper->a_id);
+   case slang_oper_label:
+      return new_label((char*) oper->a_id);
+   case slang_oper_identifier:
+      {
+         /* If there's a variable associated with this oper (from inlining)
+          * use it.  Otherwise, use the oper's var id.
+          */
+         slang_atom aVar = oper->var ? oper->var->a_name : oper->a_id;
+        slang_ir_node *n = new_var(A, oper, aVar, SWIZZLE_NOOP);
+        assert(oper->var);
+        return n;
+      }
+      break;
+   case slang_oper_field:
+      {
+         slang_assembly_typeinfo ti;
+         slang_assembly_typeinfo_construct(&ti);
+         _slang_typeof_operation(A, &oper->children[0], &ti);
+         if (_slang_type_is_vector(ti.spec.type)) {
+            /* the field should be a swizzle */
+            const GLuint rows = _slang_type_dim(ti.spec.type);
+            slang_swizzle swz;
+            slang_ir_node *n;
+            if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+               RETURN_ERROR("Bad swizzle", 0);
+            }
+            n = slang_assemble_operation(A, &oper->children[0]);
+           n->Swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+                                      swz.swizzle[1],
+                                      swz.swizzle[2],
+                                      swz.swizzle[3]);
+            return n;
+         }
+         else if (ti.spec.type == slang_spec_float) {
+            const GLuint rows = 1;
+            slang_swizzle swz;
+            slang_ir_node *n;
+            if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+               RETURN_ERROR("Bad swizzle", 0);
+            }
+            n = slang_assemble_operation(A, &oper->children[0]);
+           n->Swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+                                      swz.swizzle[1],
+                                      swz.swizzle[2],
+                                      swz.swizzle[3]);
+            return n;
+         }
+         else {
+            /* the field is a structure member */
+            abort();
+         }
+      }
+      break;
+   case slang_oper_subscript:
+      /* array dereference */
+      if (oper->children[1].type == slang_oper_literal_int) {
+         /* compile-time constant index - OK */
+         slang_assembly_typeinfo ti;
+         slang_ir_node *base;
+         slang_ir_storage *store2;
+         GLint index;
+         slang_assembly_typeinfo_construct(&ti);
+         _slang_typeof_operation(A, &oper->children[0], &ti);
+
+         base = slang_assemble_operation(A, &oper->children[0]);
+         assert(base->Opcode == IR_VAR);
+
+         index = (GLint) oper->children[1].literal[0];
+         /*
+         printf("element[%d]\n", index);
+         */
+#if 1
+         store2 = (slang_ir_storage *) _mesa_calloc(sizeof(*store2));
+         *store2 = *base->Store;
+         base->Store = store2;
+         base->Store->Size = -15;
+#endif
+         assert(base->Store);
+         base->Store->Index += index;
+         base->Store->Size = 1;
+         return base;
+      }
+      else {
+         /* run-time index - TBD */
+         abort();
+      }
+      return NULL;
+   case slang_oper_literal_float:
+      return new_float_literal(oper->literal[0], oper->literal[1],
+                               oper->literal[2], oper->literal[3]);
+   case slang_oper_literal_int:
+      return new_float_literal(oper->literal[0], 0, 0, 0);
+   case slang_oper_literal_bool:
+      return new_float_literal(oper->literal[0], 0, 0, 0);
+   case slang_oper_postincrement:
+      /* XXX not 100% about this */
+      {
+        slang_ir_node *var = slang_assemble_operation(A, &oper->children[0]);
+        slang_ir_node *one = new_float_literal(1.0, 1.0, 1.0, 1.0);
+        slang_ir_node *sum = new_node(IR_ADD, var, one);
+        slang_ir_node *assign = new_node(IR_MOVE, var, sum);
+        return assign;
+      }
+      break;
+   case slang_oper_sequence:
+      {
+         slang_ir_node *top = NULL;
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            slang_ir_node *n = slang_assemble_operation(A, &oper->children[i]);
+            top = top ? new_seq(top, n) : n;
+         }
+         return top;
+      }
+      break;
+   case slang_oper_none:
+      return NULL;
+   default:
+      printf("Unhandled node type %d\n", oper->type);
+      abort();
+      return new_node(IR_NOP, NULL, NULL);
+   }
+      abort();
+   return NULL;
+}
+
+
+/**
+ * Produce an IR tree from a function AST.
+ * Then call the code emitter to convert the IR tree into a gl_program.
+ */
+struct slang_ir_node_ *
+_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
+{
+   slang_ir_node *n, *endLabel;
+
+   if (_mesa_strcmp((char *) fun->header.a_name, "main") != 0 &&
+       _mesa_strcmp((char *) fun->header.a_name, "foo") != 0 &&
+       _mesa_strcmp((char *) fun->header.a_name, "bar") != 0)
+     return 0;
+
+   printf("\n*********** Assemble function2(%s)\n", (char*)fun->header.a_name);
+
+   slang_print_function(fun, 1);
+
+   A->program->Parameters = _mesa_new_parameter_list();
+   A->program->Varying = _mesa_new_parameter_list();
+
+   /*printf("** Begin Simplify\n");*/
+   slang_simplify(fun->body, &A->space, A->atoms);
+   /*printf("** End Simplify\n");*/
+
+   CurFunction = fun;
+
+   n = slang_assemble_operation(A, fun->body);
+
+   if (!CurFunction->end_label)
+      CurFunction->end_label = slang_atom_pool_gen(A->atoms, "__endOfFunction_Main");
+
+   endLabel = new_label(fun->end_label);
+   n = new_seq(n, endLabel);
+
+   CurFunction = NULL;
+
+
+   printf("************* New body for %s *****\n", (char*)fun->header.a_name);
+   slang_print_function(fun, 1);
+
+   printf("************* IR for %s *******\n", (char*)fun->header.a_name);
+   slang_print_ir(n, 0);
+
+   if (_mesa_strcmp((char*) fun->header.a_name, "main") == 0) {
+      _slang_emit_code(n, A->program);
+   }
+
+   printf("************* End assemble function2 ************\n\n");
+
+   return n;
+}
+
+
diff --git a/src/mesa/shader/slang/slang_codegen.h b/src/mesa/shader/slang/slang_codegen.h
new file mode 100644 (file)
index 0000000..042737b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef SLANG_CODEGEN_H
+#define SLANG_CODEGEN_H
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_ir.h"
+
+
+extern struct slang_ir_node_ *
+_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun);
+
+
+#endif /* SLANG_CODEGEN_H */
index c49ab4a68dc1c7bc6f563a1fd96d22958be0e758..a9c84abdce019c6fb00769b078ddc950d18501a8 100644 (file)
  */
 
 #include "imports.h"
+#include "context.h"
+#include "program.h"
 #include "grammar_mesa.h"
+#include "slang_codegen.h"
 #include "slang_compile.h"
 #include "slang_preprocess.h"
 #include "slang_storage.h"
+#include "slang_error.h"
+
+#include "slang_print.h"
 
 /*
  * This is a straightforward implementation of the slang front-end
@@ -214,6 +220,7 @@ slang_info_log_memory(slang_info_log * log)
       log->dont_free_text = 1;
       log->text = out_of_memory;
    }
+   abort();
 }
 
 /* slang_parse_ctx */
@@ -237,6 +244,7 @@ typedef struct slang_output_ctx_
    slang_assembly_file *assembly;
    slang_var_pool *global_pool;
    slang_machine *machine;
+   struct gl_program *program;
 } slang_output_ctx;
 
 /* _slang_compile() */
@@ -782,16 +790,17 @@ parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
  * \param C  the parsing context
  * \param O  the output context
  * \param oper  the operation we're parsing
- * \param statment  which child of the operation is being parsed
+ * \param statement  indicates whether parsing a statement, or expression
  * \return 1 if success, 0 if error
  */
 static int
 parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
-                      slang_operation * oper, unsigned int statement)
+                      slang_operation * oper, GLboolean statement)
 {
    slang_operation *ch;
 
    /* grow child array */
+#if 000
    oper->children = (slang_operation *)
       slang_alloc_realloc(oper->children,
                           oper->num_children * sizeof(slang_operation),
@@ -807,7 +816,9 @@ parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
       return 0;
    }
    oper->num_children++;
-   /* XXX I guess the 0th "statement" is not really a statement? */
+#else
+   ch = slang_operation_grow(&oper->num_children, &oper->children);
+#endif
    if (statement)
       return parse_statement(C, O, ch);
    return parse_expression(C, O, ch);
@@ -846,6 +857,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
       /* local variable declaration, individual declarators are stored as
        * children identifiers
        */
+#if 000
       oper->type = slang_oper_variable_decl;
       {
          const unsigned int first_var = O->vars->num_variables;
@@ -881,6 +893,38 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
             }
          }
       }
+#else
+
+      oper->type = slang_oper_block_no_new_scope;
+      {
+         const unsigned int first_var = O->vars->num_variables;
+
+         /* parse the declaration, note that there can be zero or more
+          * than one declarators
+          */
+         if (!parse_declaration(C, O))
+            return 0;
+         if (first_var < O->vars->num_variables) {
+            const unsigned int num_vars = O->vars->num_variables - first_var;
+            unsigned int i;
+
+            oper->num_children = num_vars;
+            oper->children = slang_operation_new(num_vars);
+            if (oper->children == NULL) {
+               slang_info_log_memory(C->L);
+               return 0;
+            }
+            for (i = first_var; i < O->vars->num_variables; i++) {
+               slang_operation *o = &oper->children[i - first_var];
+               o->type = slang_oper_variable_decl;
+               o->locals->outer_scope = O->vars;
+               o->a_id = O->vars->variables[i].a_name;
+            }
+         }
+      }
+
+
+#endif
       break;
    case OP_ASM:
       /* the __asm statement, parse the mnemonic and all its arguments
@@ -888,6 +932,9 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
        */
       oper->type = slang_oper_asm;
       oper->a_id = parse_identifier(C);
+      if (strcmp((char*)oper->a_id, "dot") == 0) {
+         printf("Assemble dot! **************************\n");
+      }
       if (oper->a_id == SLANG_ATOM_NULL)
          return 0;
       while (*C->I != OP_END) {
@@ -1042,18 +1089,27 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
          op->type = slang_oper_literal_bool;
          if (!parse_number(C, &number))
             return 0;
-         op->literal = (GLfloat) number;
+         op->literal[0] =
+         op->literal[1] =
+         op->literal[2] =
+         op->literal[3] = (GLfloat) number;
          break;
       case OP_PUSH_INT:
          op->type = slang_oper_literal_int;
          if (!parse_number(C, &number))
             return 0;
-         op->literal = (GLfloat) number;
+         op->literal[0] =
+         op->literal[1] =
+         op->literal[2] =
+         op->literal[3] = (GLfloat) number;
          break;
       case OP_PUSH_FLOAT:
          op->type = slang_oper_literal_float;
-         if (!parse_float(C, &op->literal))
+         if (!parse_float(C, &op->literal[0]))
             return 0;
+         op->literal[1] =
+         op->literal[2] =
+         op->literal[3] = op->literal[0];
          break;
       case OP_PUSH_IDENTIFIER:
          op->type = slang_oper_identifier;
@@ -1480,6 +1536,20 @@ parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
          return 0;
    }
 
+#if 111
+   /* if the function returns a value, append a hidden __retVal 'out'
+    * parameter that corresponds to the return value.
+    */
+   if (_slang_function_has_return_value(func)) {
+      slang_variable *p = slang_variable_scope_grow(func->parameters);
+      slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
+      assert(a_retVal);
+      p->a_name = a_retVal;
+      p->type = func->header.type;
+      p->type.qualifier = slang_qual_out;
+   }
+#endif
+
    /* function formal parameters and local variables share the same
     * scope, so save the information about param count in a seperate
     * place also link the scope to the global variable scope so when a
@@ -1488,6 +1558,7 @@ parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
     */
    func->param_count = func->parameters->num_variables;
    func->parameters->outer_scope = O->vars;
+
    return 1;
 }
 
@@ -1770,9 +1841,9 @@ parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
  * \param O  output context
  * \param definition if non-zero expect a definition, else a declaration
  * \param parsed_func_ret  returns the parsed function
- * \return 1 if success, 0 if failure
+ * \return GL_TRUE if success, GL_FALSE if failure
  */
-static int
+static GLboolean
 parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
                slang_function ** parsed_func_ret)
 {
@@ -1780,17 +1851,17 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
 
    /* parse function definition/declaration */
    if (!slang_function_construct(&parsed_func))
-      return 0;
+      return GL_FALSE;
    if (definition) {
       if (!parse_function_definition(C, O, &parsed_func)) {
          slang_function_destruct(&parsed_func);
-         return 0;
+         return GL_FALSE;
       }
    }
    else {
       if (!parse_function_prototype(C, O, &parsed_func)) {
          slang_function_destruct(&parsed_func);
-         return 0;
+         return GL_FALSE;
       }
    }
 
@@ -1800,7 +1871,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
     */
    found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
    if (found_func == NULL) {
-      /* add the parsed function to the function list */
+      /* New function, add it to the function list */
       O->funs->functions =
          (slang_function *) slang_alloc_realloc(O->funs->functions,
                                                 O->funs->num_functions *
@@ -1810,7 +1881,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
       if (O->funs->functions == NULL) {
          slang_info_log_memory(C->L);
          slang_function_destruct(&parsed_func);
-         return 0;
+         return GL_FALSE;
       }
       O->funs->functions[O->funs->num_functions] = parsed_func;
       O->funs->num_functions++;
@@ -1819,6 +1890,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
       *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
    }
    else {
+      /* previously defined or declared */
       /* TODO: check function return type qualifiers and specifiers */
       if (definition) {
          if (found_func->body != NULL) {
@@ -1827,7 +1899,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
                                                     parsed_func.header.
                                                     a_name));
             slang_function_destruct(&parsed_func);
-            return 0;
+            return GL_FALSE;
          }
 
          /* destroy the existing function declaration and replace it
@@ -1857,10 +1929,33 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
       A.space.funcs = O->funs;
       A.space.structs = O->structs;
       A.space.vars = O->vars;
-      if (!_slang_assemble_function(&A, *parsed_func_ret))
-         return 0;
+      A.program = O->program;
+
+      _slang_reset_error();
+
+#if 0
+      printf("*************** Assemble function %s ****\n", (char *) (*parsed_func_ret)->header.a_name);
+      slang_print_var_scope((*parsed_func_ret)->parameters,
+                            (*parsed_func_ret)->param_count);
+#endif
+
+
+      if (!_slang_assemble_function(&A, *parsed_func_ret)) {
+         /* propogate the error message back through the info log */
+         C->L->text = _mesa_strdup(_slang_error_text());
+         C->L->dont_free_text = GL_FALSE;
+         return GL_FALSE;
+      }
+
+
+#if 0
+      printf("**************************************\n");
+#endif
+#if 1
+      _slang_codegen_function(&A, *parsed_func_ret);
+#endif
    }
-   return 1;
+   return GL_TRUE;
 }
 
 /* declaration */
@@ -1895,7 +1990,8 @@ parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
 #define EXTERNAL_DECLARATION 2
 
 static GLboolean
-parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit)
+parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
+                struct gl_program *program)
 {
    slang_output_ctx o;
 
@@ -1906,6 +2002,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit)
    o.assembly = &unit->object->assembly;
    o.global_pool = &unit->object->varpool;
    o.machine = &unit->object->machine;
+   o.program = program;
 
    /* parse individual functions and declarations */
    while (*C->I != EXTERNAL_NULL) {
@@ -1915,25 +2012,26 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit)
             slang_function *func;
 
             if (!parse_function(C, &o, 1, &func))
-               return 0;
+               return GL_FALSE;
          }
          break;
       case EXTERNAL_DECLARATION:
          if (!parse_declaration(C, &o))
-            return 0;
+            return GL_FALSE;
          break;
       default:
-         return 0;
+         return GL_FALSE;
       }
    }
    C->I++;
-   return 1;
+   return GL_TRUE;
 }
 
 static GLboolean
 compile_binary(const byte * prod, slang_code_unit * unit,
                slang_unit_type type, slang_info_log * infolog,
-               slang_code_unit * builtin, slang_code_unit * downlink)
+               slang_code_unit * builtin, slang_code_unit * downlink,
+               struct gl_program *program)
 {
    slang_parse_ctx C;
 
@@ -1956,13 +2054,14 @@ compile_binary(const byte * prod, slang_code_unit * unit,
    }
 
    /* parse translation unit */
-   return parse_code_unit(&C, unit);
+   return parse_code_unit(&C, unit, program);
 }
 
 static GLboolean
 compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
                      slang_unit_type type, slang_info_log * infolog,
-                     slang_code_unit * builtin)
+                     slang_code_unit * builtin,
+                     struct gl_program *program)
 {
    byte *prod;
    GLuint size, start, version;
@@ -1987,8 +2086,9 @@ compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
    }
 
    /* Finally check the syntax and generate its binary representation. */
-   if (!grammar_fast_check
-       (id, (const byte *) (slang_string_cstr(&preprocessed)), &prod, &size,
+   if (!grammar_fast_check(id,
+                           (const byte *) (slang_string_cstr(&preprocessed)),
+                           &prod, &size,
         65536)) {
       char buf[1024];
       GLint pos;
@@ -1996,14 +2096,14 @@ compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
       slang_string_free(&preprocessed);
       grammar_get_last_error((byte *) (buf), sizeof(buf), &pos);
       slang_info_log_error(infolog, buf);
-      return GL_FALSE;
+      RETURN_ERROR("syntax error", 0);
    }
    slang_string_free(&preprocessed);
 
    /* Syntax is okay - translate it to internal representation. */
-   if (!compile_binary
-       (prod, unit, type, infolog, builtin,
-        &builtin[SLANG_BUILTIN_TOTAL - 1])) {
+   if (!compile_binary(prod, unit, type, infolog, builtin,
+                       &builtin[SLANG_BUILTIN_TOTAL - 1],
+                       program)) {
       grammar_alloc_free(prod);
       return GL_FALSE;
    }
@@ -2032,6 +2132,7 @@ static const byte slang_vertex_builtin_gc[] = {
 };
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
+foo
 static const byte slang_builtin_vec4_gc[] = {
 #include "library/slang_builtin_vec4_gc.h"
 };
@@ -2039,7 +2140,8 @@ static const byte slang_builtin_vec4_gc[] = {
 
 static GLboolean
 compile_object(grammar * id, const char *source, slang_code_object * object,
-               slang_unit_type type, slang_info_log * infolog)
+               slang_unit_type type, slang_info_log * infolog,
+               struct gl_program *program)
 {
    slang_code_unit *builtins = NULL;
 
@@ -2067,56 +2169,79 @@ compile_object(grammar * id, const char *source, slang_code_object * object,
    /* if parsing user-specified shader, load built-in library */
    if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) {
       /* compile core functionality first */
-      if (!compile_binary(slang_core_gc, &object->builtin[SLANG_BUILTIN_CORE],
-                          slang_unit_fragment_builtin, infolog, NULL, NULL))
+      if (!compile_binary(slang_core_gc,
+                          &object->builtin[SLANG_BUILTIN_CORE],
+                          slang_unit_fragment_builtin, infolog,
+                          NULL, NULL, NULL))
          return GL_FALSE;
 
       /* compile common functions and variables, link to core */
-      if (!compile_binary
-          (slang_common_builtin_gc, &object->builtin[SLANG_BUILTIN_COMMON],
-           slang_unit_fragment_builtin, infolog, NULL,
-           &object->builtin[SLANG_BUILTIN_CORE]))
+      if (!compile_binary(slang_common_builtin_gc,
+                          &object->builtin[SLANG_BUILTIN_COMMON],
+                          slang_unit_fragment_builtin, infolog, NULL,
+                          &object->builtin[SLANG_BUILTIN_CORE], NULL))
          return GL_FALSE;
 
       /* compile target-specific functions and variables, link to common */
       if (type == slang_unit_fragment_shader) {
-         if (!compile_binary
-             (slang_fragment_builtin_gc,
-              &object->builtin[SLANG_BUILTIN_TARGET],
-              slang_unit_fragment_builtin, infolog, NULL,
-              &object->builtin[SLANG_BUILTIN_COMMON]))
+         if (!compile_binary(slang_fragment_builtin_gc,
+                             &object->builtin[SLANG_BUILTIN_TARGET],
+                             slang_unit_fragment_builtin, infolog, NULL,
+                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
             return GL_FALSE;
       }
       else if (type == slang_unit_vertex_shader) {
-         if (!compile_binary
-             (slang_vertex_builtin_gc, &object->builtin[SLANG_BUILTIN_TARGET],
-              slang_unit_vertex_builtin, infolog, NULL,
-              &object->builtin[SLANG_BUILTIN_COMMON]))
+         if (!compile_binary(slang_vertex_builtin_gc,
+                             &object->builtin[SLANG_BUILTIN_TARGET],
+                             slang_unit_vertex_builtin, infolog, NULL,
+                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
             return GL_FALSE;
       }
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
       /* compile x86 4-component vector overrides, link to target */
-      if (!compile_binary
-          (slang_builtin_vec4_gc, &object->builtin[SLANG_BUILTIN_VEC4],
-           slang_unit_fragment_builtin, infolog, NULL,
-           &object->builtin[SLANG_BUILTIN_TARGET]))
+      if (!compile_binary(slang_builtin_vec4_gc,
+                          &object->builtin[SLANG_BUILTIN_VEC4],
+                          slang_unit_fragment_builtin, infolog, NULL,
+                          &object->builtin[SLANG_BUILTIN_TARGET]))
          return GL_FALSE;
 #endif
 
       /* disable language extensions */
+#if NEW_SLANG /* allow-built-ins */
+      grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1);
+#else
       grammar_set_reg8(*id, (const byte *) "parsing_builtin", 0);
+#endif
       builtins = object->builtin;
    }
 
    /* compile the actual shader - pass-in built-in library for external shader */
    return compile_with_grammar(*id, source, &object->unit, type, infolog,
-                               builtins);
+                               builtins, program);
+}
+
+
+static void
+slang_create_uniforms(const slang_export_data_table *exports,
+                      struct gl_program *program)
+{
+   /* XXX only add uniforms that are actually going to get used */
+   GLuint i;
+   for (i = 0; i < exports->count; i++) {
+      if (exports->entries[i].access == slang_exp_uniform) {
+         const char *name = (char *) exports->entries[i].quant.name;
+         GLint j = _mesa_add_uniform(program->Parameters, name, 4);
+         assert(j >= 0);
+      }
+   }
 }
 
+
 GLboolean
 _slang_compile(const char *source, slang_code_object * object,
-               slang_unit_type type, slang_info_log * infolog)
+               slang_unit_type type, slang_info_log * infolog,
+               struct gl_program *program)
 {
    GLboolean success;
    grammar id = 0;
@@ -2124,7 +2249,7 @@ _slang_compile(const char *source, slang_code_object * object,
    _slang_code_object_dtr(object);
    _slang_code_object_ctr(object);
 
-   success = compile_object(&id, source, object, type, infolog);
+   success = compile_object(&id, source, object, type, infolog, program);
    if (id != 0)
       grammar_destroy(id);
    if (!success)
@@ -2132,10 +2257,20 @@ _slang_compile(const char *source, slang_code_object * object,
 
    if (!_slang_build_export_data_table(&object->expdata, &object->unit.vars))
       return GL_FALSE;
-   if (!_slang_build_export_code_table
-       (&object->expcode, &object->unit.funs, &object->unit))
+   if (!_slang_build_export_code_table(&object->expcode, &object->unit.funs,
+                                       &object->unit))
       return GL_FALSE;
 
+#if NEW_SLANG
+   {
+      GET_CURRENT_CONTEXT(ctx);
+      slang_create_uniforms(&object->expdata, program);
+      _mesa_print_program(program);
+      _mesa_print_program_parameters(ctx, program);
+   }
+#endif
+
+
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
    /* XXX: lookup the @main label */
    if (!_slang_x86_codegen
@@ -2146,3 +2281,4 @@ _slang_compile(const char *source, slang_code_object * object,
 
    return GL_TRUE;
 }
+
index 02987f4e1bcf9f02d4beedea74f6078fd3c03bad..a41c00a3f5eaf5c39c2d83e983953384312fbd28 100644 (file)
@@ -25,6 +25,8 @@
 #if !defined SLANG_COMPILE_H
 #define SLANG_COMPILE_H
 
+#include "imports.h"
+#include "mtypes.h"
 #include "slang_export.h"
 #include "slang_execute.h"
 #include "slang_compile_variable.h"
@@ -107,7 +109,7 @@ int slang_info_log_warning (slang_info_log *, const char *, ...);
 void slang_info_log_memory (slang_info_log *);
 
 extern GLboolean
-_slang_compile (const char *, slang_code_object *, slang_unit_type, slang_info_log *);
+_slang_compile (const char *, slang_code_object *, slang_unit_type, slang_info_log *, struct gl_program *program);
 
 #ifdef __cplusplus
 }
index e6e0d89ddb66055ba9c5c049c799d2039e9b575b..58a453d4c23d162cee2410df0cfbee019cb1d47f 100644 (file)
@@ -86,6 +86,7 @@ slang_function_construct(slang_function * func)
    func->param_count = 0;
    func->body = NULL;
    func->address = ~0;
+   func->end_label = 0;
    slang_fixup_table_init(&func->fixups);
    return 1;
 }
@@ -126,6 +127,16 @@ slang_function_scope_destruct(slang_function_scope * scope)
 }
 
 
+/**
+ * Does this function have a non-void return value?
+ */
+GLboolean
+_slang_function_has_return_value(const slang_function *fun)
+{
+   return fun->header.type.specifier.type != slang_spec_void;
+}
+
+
 /**
  * Search a list of functions for a particular function by name.
  * \param funcs  the list of functions to search
@@ -166,21 +177,39 @@ slang_function_scope_find(slang_function_scope * funcs, slang_function * fun,
 
    for (i = 0; i < funcs->num_functions; i++) {
       slang_function *f = &funcs->functions[i];
+      const GLuint haveRetValue = 0;
+#if 0
+         = (f->header.type.specifier.type != slang_spec_void);
+#endif
       unsigned int j;
 
+      /*
+      printf("Compare name %s to %s  (ret %u, %d, %d)\n",
+             (char *) fun->header.a_name, (char *) f->header.a_name,
+             haveRetValue,
+             fun->param_count, f->param_count);
+      */
+
       if (fun->header.a_name != f->header.a_name)
          continue;
       if (fun->param_count != f->param_count)
          continue;
-      for (j = 0; j < fun->param_count; j++) {
+      for (j = haveRetValue; j < fun->param_count; j++) {
          if (!slang_type_specifier_equal
              (&fun->parameters->variables[j].type.specifier,
               &f->parameters->variables[j].type.specifier))
             break;
       }
-      if (j == fun->param_count)
+      if (j == fun->param_count) {
+         /*
+         printf("Found match\n");
+         */
          return f;
+      }
    }
+   /*
+   printf("Not found\n");
+   */
    if (all_scopes && funcs->outer_scope != NULL)
       return slang_function_scope_find(funcs->outer_scope, fun, 1);
    return NULL;
index c05c6f4d850c5dbd192207d432ec895433632b5d..8f0e3b326d43743953112fec7c9b55abcc23e5a6 100644 (file)
@@ -69,6 +69,7 @@ typedef struct slang_function_
    slang_operation *body;      /**< The instruction tree */
    unsigned int address;       /**< Address of this func in memory */
    slang_fixup_table fixups;   /**< Mem locations which need func's address */
+   slang_atom end_label;       /**< The end-of-function label */
 } slang_function;
 
 extern int slang_function_construct(slang_function *);
@@ -92,6 +93,9 @@ _slang_function_scope_ctr(slang_function_scope *);
 extern void
 slang_function_scope_destruct(slang_function_scope *);
 
+extern GLboolean
+_slang_function_has_return_value(const slang_function *fun);
+
 extern int
 slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
 
index 73f57bfb123ce0402dea6f5bf7475d05499b5fe9..192f2b086b604569fae554a71e9dc4cee24f2e63 100644 (file)
@@ -41,14 +41,14 @@ slang_operation_construct(slang_operation * oper)
    oper->type = slang_oper_none;
    oper->children = NULL;
    oper->num_children = 0;
-   oper->literal = (float) 0;
+   oper->literal[0] = 0.0;
    oper->a_id = SLANG_ATOM_NULL;
-   oper->locals =
-      (slang_variable_scope *)
-      slang_alloc_malloc(sizeof(slang_variable_scope));
+   oper->locals = _slang_variable_scope_new(NULL);
    if (oper->locals == NULL)
       return GL_FALSE;
    _slang_variable_scope_ctr(oper->locals);
+   oper->fun = NULL;
+   oper->var = NULL;
    return GL_TRUE;
 }
 
@@ -62,6 +62,9 @@ slang_operation_destruct(slang_operation * oper)
    slang_alloc_free(oper->children);
    slang_variable_scope_destruct(oper->locals);
    slang_alloc_free(oper->locals);
+   oper->children = NULL;
+   oper->num_children = 0;
+   oper->locals = NULL;
 }
 
 /**
@@ -96,12 +99,21 @@ slang_operation_copy(slang_operation * x, const slang_operation * y)
          return GL_FALSE;
       }
    }
-   z.literal = y->literal;
+   z.literal[0] = y->literal[0];
+   z.literal[1] = y->literal[1];
+   z.literal[2] = y->literal[2];
+   z.literal[3] = y->literal[3];
    z.a_id = y->a_id;
-   if (!slang_variable_scope_copy(z.locals, y->locals)) {
-      slang_operation_destruct(&z);
-      return GL_FALSE;
+   if (y->locals) {
+      if (!slang_variable_scope_copy(z.locals, y->locals)) {
+         slang_operation_destruct(&z);
+         return GL_FALSE;
+      }
    }
+#if 0
+   z.var = y->var;
+   z.fun = y->fun;
+#endif
    slang_operation_destruct(x);
    *x = z;
    return GL_TRUE;
@@ -111,5 +123,77 @@ slang_operation_copy(slang_operation * x, const slang_operation * y)
 slang_operation *
 slang_operation_new(GLuint count)
 {
-   return (slang_operation *) _mesa_calloc(count * sizeof(slang_operation));
+   slang_operation *ops
+       = (slang_operation *) _mesa_malloc(count * sizeof(slang_operation));
+   assert(count > 0);
+   if (ops) {
+      GLuint i;
+      for (i = 0; i < count; i++)
+         slang_operation_construct(ops + i);
+   }
+   return ops;
+}
+
+
+slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children)
+{
+   slang_operation *ops;
+
+   ops = (slang_operation *)
+      slang_alloc_realloc(*children,
+                          *numChildren * sizeof(slang_operation),
+                          (*numChildren + 1) * sizeof(slang_operation));
+   if (ops) {
+      slang_operation *newOp = ops + *numChildren;
+      if (!slang_operation_construct(newOp)) {
+         _mesa_free(ops);
+         *children = NULL;
+         return NULL;
+      }
+      *children = ops;
+      (*numChildren)++;
+      return newOp;
+   }
+   return NULL;
+}
+
+/**
+ * Insert a new slang_operation into an array.
+ * \param numChildren  pointer to current number of children (in/out)
+ * \param children  address of array (in/out)
+ * \param pos  position to insert
+ * \return  pointer to the new operation
+ */
+slang_operation *
+slang_operation_insert(GLuint *numChildren, slang_operation **children,
+                       GLuint pos)
+{
+   slang_operation *ops;
+
+   assert(pos <= *numChildren);
+
+   ops = (slang_operation *)
+      _mesa_malloc((*numChildren + 1) * sizeof(slang_operation));
+   if (ops) {
+      slang_operation *newOp;
+      newOp = ops + pos;
+      if (pos > 0)
+         _mesa_memcpy(ops, *children, pos * sizeof(slang_operation));
+      if (pos < *numChildren)
+         _mesa_memcpy(newOp + 1, (*children) + pos,
+                      (*numChildren - pos) * sizeof(slang_operation));
+
+      if (!slang_operation_construct(newOp)) {
+         _mesa_free(ops);
+         *numChildren = 0;
+         *children = NULL;
+         return NULL;
+      }
+      *children = ops;
+      (*numChildren)++;
+      return newOp;
+   }
+   return NULL;
 }
+
index a9376ec945fba93648890ad22199338860472feb..f6d0ba85ba5ed2384e3faedd77845243d944b66b 100644 (file)
@@ -46,6 +46,8 @@ typedef enum slang_operation_type_
    slang_oper_continue,         /* "continue" statement */
    slang_oper_discard,          /* "discard" (kill fragment) statement */
    slang_oper_return,           /* "return" [expr]  */
+   slang_oper_goto,             /* jump to label */
+   slang_oper_label,            /* a jump target */
    slang_oper_expression,       /* [expr] */
    slang_oper_if,               /* "if" [0] then [1] else [2] */
    slang_oper_while,            /* "while" [cond] [body] */
@@ -114,9 +116,13 @@ typedef struct slang_operation_
    slang_operation_type type;
    struct slang_operation_ *children;
    GLuint num_children;
-   GLfloat literal;            /**< Used for float, int and bool values */
-   slang_atom a_id;            /**< type: asm, identifier, call, field */
-   slang_variable_scope *locals;       /**< local vars for scope */
+   GLfloat literal[4];           /**< Used for float, int and bool values */
+   slang_atom a_id;              /**< type: asm, identifier, call, field */
+   slang_variable_scope *locals; /**< local vars for scope */
+   struct slang_function_ *fun;  /**< If type == slang_oper_call */
+   struct slang_variable_ *var;  /**< If type == slang_oper_identier */
+   slang_fully_specified_type *datatype; /**< Type of this operation */
+   slang_assembly_typeinfo ti;
 } slang_operation;
 
 
@@ -132,6 +138,13 @@ slang_operation_copy(slang_operation *, const slang_operation *);
 extern slang_operation *
 slang_operation_new(GLuint count);
 
+extern slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children);
+
+extern slang_operation *
+slang_operation_insert(GLuint *numChildren, slang_operation **children,
+                       GLuint pos);
+
 
 #ifdef __cplusplus
 }
index a8a2d6aa6a0629c245e92dbf43e3635ccf6842e3..f9f02066a3af3c67359d21f089fe4bc32f463040 100644 (file)
@@ -127,6 +127,16 @@ slang_fully_specified_type_copy(slang_fully_specified_type * x,
  * slang_variable_scope
  */
 
+slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent)
+{
+   slang_variable_scope *s;
+   s = (slang_variable_scope *) _mesa_calloc(sizeof(slang_variable_scope));
+   s->outer_scope = parent;
+   return s;
+}
+
+
 GLvoid
 _slang_variable_scope_ctr(slang_variable_scope * self)
 {
@@ -218,9 +228,11 @@ slang_variable_construct(slang_variable * var)
    var->array_len = 0;
    var->initializer = NULL;
    var->address = ~0;
-   var->address2 = 0;
    var->size = 0;
    var->global = GL_FALSE;
+   var->declared = GL_FALSE;
+   var->used = GL_FALSE;
+   var->aux = NULL;
    return 1;
 }
 
@@ -248,8 +260,8 @@ slang_variable_copy(slang_variable * x, const slang_variable * y)
    z.a_name = y->a_name;
    z.array_len = y->array_len;
    if (y->initializer != NULL) {
-      z.initializer =
-         (slang_operation *) slang_alloc_malloc(sizeof(slang_operation));
+      z.initializer
+         (slang_operation *) slang_alloc_malloc(sizeof(slang_operation));
       if (z.initializer == NULL) {
          slang_variable_destruct(&z);
          return 0;
index b0910e855ea3098e9df4938660f4fed6503386b6..d52e2660dc0d2344faec43e313599bce38c5b692 100644 (file)
@@ -78,9 +78,10 @@ typedef struct slang_variable_
    GLuint array_len;                /**< only if type == slang_spec_array */
    struct slang_operation_ *initializer; /**< Optional initializer code */
    GLuint address;                  /**< Storage location */
-   GLuint address2;                 /**< Storage location */
    GLuint size;                     /**< Variable's size in bytes */
    GLboolean global;                /**< A global var? */
+   GLboolean used;                  /**< Ever referenced by code? */
+   GLboolean declared;              /**< Declared by slang_variable_decl? */
    void *aux;                       /**< Used during code gen */
 } slang_variable;
 
@@ -95,6 +96,10 @@ typedef struct slang_variable_scope_
    struct slang_variable_scope_ *outer_scope;
 } slang_variable_scope;
 
+
+extern slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent);
+
 extern GLvoid
 _slang_variable_scope_ctr(slang_variable_scope *);
 
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
new file mode 100644 (file)
index 0000000..0b4ef6d
--- /dev/null
@@ -0,0 +1,1027 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_emit.c
+ * Emit program instructions (PI code) from IR trees.
+ * \author Brian Paul
+ */
+
+#include "imports.h"
+#include "context.h"
+#include "get.h"
+#include "macros.h"
+#include "program.h"
+#include "program_instruction.h"
+#include "slang_emit.h"
+
+
+/**
+ * Assembly and IR info
+ */
+typedef struct
+{
+   slang_ir_opcode IrOpcode;
+   const char *IrName;
+   gl_inst_opcode InstOpcode;
+   GLuint ResultSize, NumParams;
+} slang_ir_info;
+
+
+
+static slang_ir_info IrInfo[] = {
+   /* binary ops */
+   { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
+   { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
+   { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
+   { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
+   { IR_DOT4, "IR_DOT_4", OPCODE_DP4, 1, 2 },
+   { IR_DOT3, "IR_DOT_3", OPCODE_DP3, 1, 2 },
+   { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
+   { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
+   { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
+   { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
+   { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
+   { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
+   { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
+   { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
+   /* unary ops */
+   { IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 },
+   { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
+   { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
+   { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
+   { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
+   { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
+   { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
+   { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
+   { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
+   { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
+   { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
+   /* other */
+   { IR_SEQ, "IR_SEQ", 0, 0, 0 },
+   { IR_LABEL, "IR_LABEL", 0, 0, 0 },
+   { IR_JUMP, "IR_JUMP", 0, 0, 0 },
+   { IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
+   { IR_CALL, "IR_CALL", 0, 0, 0 },
+   { IR_MOVE, "IR_MOVE", 0, 0, 1 },
+   { IR_LESS, "IR_LESS", 0, 1, 2 },
+   { IR_NOT, "IR_NOT", 0, 1, 1 },
+   { IR_VAR, "IR_VAR", 0, 0, 0 },
+   { IR_VAR_DECL, "IR_VAR_DECL", 0, 0, 0 },
+   { IR_FLOAT, "IR_FLOAT", 0, 0, 0 },
+   { IR_FIELD, "IR_FIELD", 0, 0, 0 },
+   { IR_NOP, NULL, OPCODE_NOP, 0, 0 }
+};
+
+
+static slang_ir_info *
+slang_find_ir_info(slang_ir_opcode opcode)
+{
+   GLuint i;
+   for (i = 0; IrInfo[i].IrName; i++) {
+      if (IrInfo[i].IrOpcode == opcode) {
+        return IrInfo + i;
+      }
+   }
+   return NULL;
+}
+
+static const char *
+slang_ir_name(slang_ir_opcode opcode)
+{
+   return slang_find_ir_info(opcode)->IrName;
+}
+
+
+slang_ir_storage *
+_slang_new_ir_storage(enum register_file file, GLint index, GLint size)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _mesa_calloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = file;
+      st->Index = index;
+      st->Size = size;
+   }
+   return st;
+}
+
+
+static const char *
+swizzle_string(GLuint swizzle)
+{
+   static char s[6];
+   GLuint i;
+   s[0] = '.';
+   for (i = 1; i < 5; i++) {
+      s[i] = "xyzw"[GET_SWZ(swizzle, i-1)];
+   }
+   s[i] = 0;
+   return s;
+}
+
+static const char *
+writemask_string(GLuint writemask)
+{
+   static char s[6];
+   GLuint i, j = 0;
+   s[j++] = '.';
+   for (i = 0; i < 4; i++) {
+      if (writemask & (1 << i))
+         s[j++] = "xyzw"[i];
+   }
+   s[j] = 0;
+   return s;
+}
+
+static const char *
+storage_string(const slang_ir_storage *st)
+{
+   static const char *files[] = {
+      "TEMP",
+      "LOCAL_PARAM",
+      "ENV_PARAM",
+      "STATE",
+      "INPUT",
+      "OUTPUT",
+      "NAMED_PARAM",
+      "CONSTANT",
+      "UNIFORM",
+      "WRITE_ONLY",
+      "ADDRESS",
+      "UNDEFINED"
+   };
+   static char s[100];
+#if 0
+   if (st->Size == 1)
+      sprintf(s, "%s[%d]", files[st->File], st->Index);
+   else
+      sprintf(s, "%s[%d..%d]", files[st->File], st->Index,
+              st->Index + st->Size - 1);
+#endif
+   sprintf(s, "%s", files[st->File]);
+   return s;
+}
+
+
+static GLuint
+sizeof_struct(const slang_struct *s)
+{
+   return 0;
+}
+
+
+static GLuint
+sizeof_type(const slang_fully_specified_type *t)
+{
+   switch (t->specifier.type) {
+   case slang_spec_void:
+      abort();
+      return 0;
+   case slang_spec_bool:
+      return 1;
+   case slang_spec_bvec2:
+      return 2;
+   case slang_spec_bvec3:
+      return 3;
+   case slang_spec_bvec4:
+      return 4;
+   case slang_spec_int:
+      return 1;
+   case slang_spec_ivec2:
+      return 2;
+   case slang_spec_ivec3:
+      return 3;
+   case slang_spec_ivec4:
+      return 4;
+   case slang_spec_float:
+      return 1;
+   case slang_spec_vec2:
+      return 2;
+   case slang_spec_vec3:
+      return 3;
+   case slang_spec_vec4:
+      return 4;
+   case slang_spec_mat2:
+      return 2 * 2;
+   case slang_spec_mat3:
+      return 3 * 3;
+   case slang_spec_mat4:
+      return 4 * 4;
+   case slang_spec_sampler1D:
+   case slang_spec_sampler2D:
+   case slang_spec_sampler3D:
+   case slang_spec_samplerCube:
+   case slang_spec_sampler1DShadow:
+   case slang_spec_sampler2DShadow:
+      abort();
+      return 0;
+   case slang_spec_struct:
+      return sizeof_struct(t->specifier._struct);
+   case slang_spec_array:
+      return 1; /* XXX */
+   default:
+      abort();
+      return 0;
+   }
+   return 0;
+}
+
+
+#define IND 0
+void
+slang_print_ir(const slang_ir_node *n, int indent)
+{
+   int i;
+   if (!n)
+      return;
+#if !IND
+   if (n->Opcode != IR_SEQ)
+#else
+      printf("%3d:", indent);
+#endif
+      for (i = 0; i < indent; i++)
+        printf(" ");
+
+   switch (n->Opcode) {
+   case IR_SEQ:
+#if IND
+      printf("SEQ  store %p\n", (void*) n->Store);
+#endif
+      assert(n->Children[0]);
+      assert(n->Children[1]);
+      slang_print_ir(n->Children[0], indent + IND);
+      slang_print_ir(n->Children[1], indent + IND);
+      break;
+   case IR_MOVE:
+      printf("MOVE (writemask = %s)\n", writemask_string(n->Writemask));
+      slang_print_ir(n->Children[0], indent+3);
+      slang_print_ir(n->Children[1], indent+3);
+      break;
+   case IR_LABEL:
+      printf("LABEL: %s\n", n->Target);
+      break;
+   case IR_JUMP:
+      printf("JUMP %s\n", n->Target);
+      break;
+   case IR_CJUMP:
+      printf("CJUMP %s\n", n->Target);
+      slang_print_ir(n->Children[0], indent+3);
+      break;
+   case IR_VAR:
+      printf("VAR %s%s at %s  store %p\n",
+             (char *) n->Var->a_name, swizzle_string(n->Swizzle),
+             storage_string(n->Store), (void*) n->Store);
+      break;
+   case IR_VAR_DECL:
+      printf("VAR_DECL %s (%p) at %s  store %p\n",
+             (char *) n->Var->a_name, (void*) n->Var, storage_string(n->Store),
+             (void*) n->Store);
+      break;
+   case IR_FIELD:
+      printf("FIELD %s of\n", n->Target);
+      slang_print_ir(n->Children[0], indent+3);
+      break;
+   case IR_CALL:
+      printf("ASMCALL %s(%d args)\n", n->Target, n->Swizzle);
+      break;
+   case IR_FLOAT:
+      printf("FLOAT %f %f %f %f\n",
+             n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
+      break;
+   case IR_I_TO_F:
+      printf("INT_TO_FLOAT %d\n", (int) n->Value[0]);
+      break;
+   default:
+      printf("%s (%p, %p)\n", slang_ir_name(n->Opcode),
+             (void*) n->Children[0], (void*) n->Children[1]);
+      slang_print_ir(n->Children[0], indent+3);
+      slang_print_ir(n->Children[1], indent+3);
+   }
+}
+
+
+static GLint
+alloc_temporary(slang_gen_context *gc)
+{
+   GLuint i;
+   for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+      if (!gc->TempUsed[i]) {
+         gc->TempUsed[i] = GL_TRUE;
+         return i;
+      }
+   }
+   return -1;
+}
+
+
+static GLboolean
+is_temporary(const slang_gen_context *gc, const slang_ir_storage *st)
+{
+   if (st->File == PROGRAM_TEMPORARY && gc->TempUsed[st->Index])
+      return gc->TempUsed[st->Index];
+   else
+      return GL_FALSE;
+}
+
+
+static void
+free_temporary(slang_gen_context *gc, GLuint r)
+{
+   if (gc->TempUsed[r])
+      gc->TempUsed[r] = GL_FALSE;
+}
+
+
+
+static GLint
+slang_find_input(GLenum target, const char *name, GLint index)
+{
+   struct input_info {
+      const char *Name;
+      GLuint Attrib;
+   };
+   static const struct input_info vertInputs[] = {
+      { "gl_Vertex", VERT_ATTRIB_POS },
+      { "gl_Normal", VERT_ATTRIB_NORMAL },
+      { "gl_Color", VERT_ATTRIB_COLOR0 },
+      { "gl_SecondaryColor", VERT_ATTRIB_COLOR1 },
+      { NULL, 0 }
+   };
+   static const struct input_info fragInputs[] = {
+      { NULL, 0 }
+   };
+   const struct input_info *inputs;
+   GLuint i;
+
+   if (target == GL_VERTEX_PROGRAM_ARB) {
+      inputs = vertInputs;
+   }
+   else {
+      assert(target == GL_FRAGMENT_PROGRAM_ARB);
+      inputs = fragInputs;
+   }
+
+   for (i = 0; inputs[i].Name; i++) {
+      if (strcmp(inputs[i].Name, name) == 0) {
+         /* found */
+         return inputs[i].Attrib;
+      }
+   }
+   return -1;
+}
+
+
+static GLint
+slang_find_output(GLenum target, const char *name, GLint index)
+{
+   struct output_info {
+      const char *Name;
+      GLuint Attrib;
+   };
+   static const struct output_info vertOutputs[] = {
+      { "gl_Position", VERT_RESULT_HPOS },
+      { "gl_FrontColor", VERT_RESULT_COL0 },
+      { "gl_BackColor", VERT_RESULT_BFC0 },
+      { "gl_FrontSecondaryColor", VERT_RESULT_COL1 },
+      { "gl_BackSecondaryColor", VERT_RESULT_BFC1 },
+      { "gl_TexCoord", VERT_RESULT_TEX0 }, /* XXX indexed */
+      { "gl_FogFragCoord", VERT_RESULT_FOGC },
+      { NULL, 0 }
+   };
+   static const struct output_info fragOutputs[] = {
+      { "gl_FragColor", FRAG_RESULT_COLR },
+      { NULL, 0 }
+   };
+   const struct output_info *outputs;
+   GLuint i;
+
+   if (target == GL_VERTEX_PROGRAM_ARB) {
+      outputs = vertOutputs;
+   }
+   else {
+      assert(target == GL_FRAGMENT_PROGRAM_ARB);
+      outputs = fragOutputs;
+   }
+
+   for (i = 0; outputs[i].Name; i++) {
+      if (strcmp(outputs[i].Name, name) == 0) {
+         /* found */
+         return outputs[i].Attrib;
+      }
+   }
+   return -1;
+}
+
+
+/**
+ * Lookup a named constant and allocate storage for the parameter in
+ * the given parameter list.
+ * \return position of the constant in the paramList.
+ */
+static GLint
+slang_lookup_constant(const char *name, GLint index,
+                      struct gl_program_parameter_list *paramList)
+{
+   struct constant_info {
+      const char *Name;
+      const GLenum Token;
+   };
+   static const struct constant_info info[] = {
+      { "gl_MaxLights", GL_MAX_LIGHTS },
+      { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES },
+      { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS },
+      { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS },
+      { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
+      { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS },
+      { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS },
+      { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
+      { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
+      { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS },
+      { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
+      { NULL, 0 }
+   };
+   GLuint i;
+   GLuint swizzle; /* XXX use this */
+
+   for (i = 0; info[i].Name; i++) {
+      if (strcmp(info[i].Name, name) == 0) {
+         /* found */
+         GLfloat value = -1.0;
+         GLint pos;
+         _mesa_GetFloatv(info[i].Token, &value);
+         ASSERT(value >= 0.0);  /* sanity check that glGetFloatv worked */
+         pos = _mesa_add_unnamed_constant(paramList, &value, 1, &swizzle);
+         return pos;
+      }
+   }
+   return -1;
+}
+
+
+/**
+ * Determine if 'name' is a state variable.  If so, create a new program
+ * parameter for it, and return the param's index.  Else, return -1.
+ */
+static GLint
+slang_lookup_statevar(const char *name, GLint index,
+                      struct gl_program_parameter_list *paramList)
+{
+   struct state_info {
+      const char *Name;
+      const GLuint NumRows;  /** for matrices */
+      const GLuint Swizzle;
+      const GLint Indexes[6];
+   };
+   static const struct state_info state[] = {
+      { "gl_ModelViewMatrix", 4, SWIZZLE_NOOP,
+        { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+      { "gl_NormalMatrix", 3, SWIZZLE_NOOP,
+        { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, STATE_MATRIX_INVTRANS } },
+      { "gl_ProjectionMatrix", 4, SWIZZLE_NOOP,
+        { STATE_MATRIX, STATE_PROJECTION, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+      { "gl_ModelViewProjectionMatrix", 4, SWIZZLE_NOOP,
+        { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+      { "gl_TextureMatrix", 4, SWIZZLE_NOOP,
+        { STATE_MATRIX, STATE_TEXTURE, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+      { NULL, 0, 0, {0, 0, 0, 0, 0, 0} }
+   };
+   GLuint i;
+
+   for (i = 0; state[i].Name; i++) {
+      if (strcmp(state[i].Name, name) == 0) {
+         /* found */
+         if (paramList) {
+            if (state[i].NumRows > 1) {
+               /* a matrix */
+               GLuint j;
+               GLint pos[4], indexesCopy[6];
+               /* make copy of state tokens */
+               for (j = 0; j < 6; j++)
+                  indexesCopy[j] = state[i].Indexes[j];
+               /* load rows */
+               for (j = 0; j < state[i].NumRows; j++) {
+                  indexesCopy[3] = indexesCopy[4] = j; /* jth row of matrix */
+                  pos[j] = _mesa_add_state_reference(paramList, indexesCopy);
+                  assert(pos[j] >= 0);
+               }
+               return pos[0];
+            }
+            else {
+               /* non-matrix state */
+               GLint pos
+                  = _mesa_add_state_reference(paramList, state[i].Indexes);
+               assert(pos >= 0);
+               return pos;
+            }
+         }
+      }
+   }
+   return -1;
+}
+
+
+static GLint
+slang_alloc_uniform(struct gl_program *prog, const char *name)
+{
+   GLint i = _mesa_add_uniform(prog->Parameters, name, 4);
+   return i;
+}
+
+
+static GLint
+slang_alloc_varying(struct gl_program *prog, const char *name)
+{
+   GLint i = _mesa_add_varying(prog->Varying, name, 4); /* XXX fix size */
+   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+      i += VERT_RESULT_VAR0;
+      prog->OutputsWritten |= (1 << i);
+   }
+   else {
+      i += FRAG_ATTRIB_VAR0;
+      prog->InputsRead |= (1 << i);
+   }
+   return i;
+}
+
+
+/**
+ * Allocate temporary storage for an intermediate result (such as for
+ * a multiply or add, etc.
+ */
+static void
+slang_alloc_temp_storage(slang_gen_context *gc, slang_ir_node *n, GLint size)
+{
+   GLint indx;
+   assert(!n->Var);
+   assert(!n->Store);
+   assert(size > 0);
+   indx = alloc_temporary(gc);
+   n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, indx, size);
+}
+
+
+/**
+ * Allocate storage info for an IR node (n->Store).
+ * We may do any of the following:
+ *   1. Compute Store->File/Index for program inputs/outputs/uniforms/etc.
+ *   2. Allocate storage for user-declared variables.
+ *   3. Allocate intermediate/unnamed storage for complex expressions.
+ *   4. other?
+ *
+ * If gc or prog is NULL, we may only be able to determine the Store->File
+ * but not an Index (register).
+ */
+void
+slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
+                      struct gl_program *prog)
+{
+   int k = 0;
+   if (!n->Store) {
+      /**assert(n->Var);**/
+      if (n->Var && n->Var->aux) {
+         /* node storage info = var storage info */
+         n->Store = (slang_ir_storage *) n->Var->aux;
+      }
+      else {
+         /* alloc new storage info */
+         n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -5);
+         k = 1;
+         /*XXX n->Store->Size = sizeof(var's type) */
+         if (n->Var)
+            n->Var->aux = n->Store;
+      }
+   }
+
+   if (n->Opcode == IR_VAR_DECL) {
+      /* allocate storage for a user's variable */
+      assert(n->Var);
+      if (n->Store->Index < 0) {
+         assert(gc);
+         n->Store->File = PROGRAM_TEMPORARY;
+         n->Store->Index = alloc_temporary(gc);
+         n->Store->Size = sizeof_type(&n->Var->type);
+         printf("alloc var %s storage at %d (size %d)\n",
+                (char *) n->Var->a_name,
+                n->Store->Index,
+                n->Store->Size);
+         assert(n->Store->Size > 0);
+         n->Var->declared = GL_TRUE;
+      }
+      return;
+   }
+
+   if (n->Opcode == IR_VAR && n->Store->File == PROGRAM_UNDEFINED) {
+      /* try to determine the storage for this variable */
+      GLint i;
+
+      assert(n->Var);
+      assert(prog);
+
+#if 0
+      assert(n->Var->declared ||
+             n->Var->type.qualifier == slang_qual_uniform ||
+             n->Var->type.qualifier == slang_qual_varying ||
+             n->Var->type.qualifier == slang_qual_fixedoutput ||
+             n->Var->type.qualifier == slang_qual_attribute ||
+             n->Var->type.qualifier == slang_qual_out ||
+             n->Var->type.qualifier == slang_qual_const);
+#endif
+
+      i = slang_find_input(prog->Target, (char *) n->Var->a_name, 0);
+      if (i >= 0) {
+         n->Store->File = PROGRAM_INPUT;
+         n->Store->Index = i;
+         n->Store->Size = sizeof_type(&n->Var->type);
+         assert(n->Store->Size > 0);
+         prog->InputsRead |= (1 << i);
+         return;
+      }
+
+      i = slang_find_output(prog->Target, (char *) n->Var->a_name, 0);
+      if (i >= 0) {
+         n->Store->File = PROGRAM_OUTPUT;
+         n->Store->Index = i;
+         n->Store->Size = sizeof_type(&n->Var->type);
+         prog->OutputsWritten |= (1 << i);
+         return;
+      }
+
+      i = slang_lookup_statevar((char *) n->Var->a_name, 0, prog->Parameters);
+      if (i >= 0) {
+         n->Store->File = PROGRAM_STATE_VAR;
+         n->Store->Index = i;
+         n->Store->Size = sizeof_type(&n->Var->type);
+         return;
+      }
+
+      i = slang_lookup_constant((char *) n->Var->a_name, 0, prog->Parameters);
+      if (i >= 0) {
+         n->Store->File = PROGRAM_CONSTANT;
+         n->Store->Index = i;
+         n->Store->Size = sizeof_type(&n->Var->type);
+         return;
+      }
+
+      /* probably a uniform or varying */
+      if (n->Var->type.qualifier == slang_qual_uniform) {
+         i = slang_alloc_uniform(prog, (char *) n->Var->a_name);
+         if (i >= 0) {
+            n->Store->File = PROGRAM_UNIFORM;
+            n->Store->Index = i;
+            n->Store->Size = sizeof_type(&n->Var->type);
+            return;
+         }
+      }
+      else if (n->Var->type.qualifier == slang_qual_varying) {
+         i = slang_alloc_varying(prog, (char *) n->Var->a_name);
+         if (i >= 0) {
+            if (prog->Target == GL_VERTEX_PROGRAM_ARB)
+               n->Store->File = PROGRAM_OUTPUT;
+            else
+               n->Store->File = PROGRAM_INPUT;
+            n->Store->Size = sizeof_type(&n->Var->type);
+            n->Store->Index = i;
+            return;
+         }
+      }
+
+      /* what is this?!? */
+      /*
+      abort();
+      */
+   }
+
+   if (n->Store->File == PROGRAM_TEMPORARY && n->Store->Index < 0) {
+      /* unnamed intermediate temporary */
+      if (gc)
+         n->Store->Index = alloc_temporary(gc);
+      return;
+   }
+
+   if (gc && n->Store->File == PROGRAM_UNDEFINED && n->Store->Size < 0) {
+      abort();
+   }
+}
+
+
+static slang_ir_storage *
+alloc_constant(const GLfloat v[], GLuint size, struct gl_program *prog)
+{
+   GLuint swizzle;
+   GLint ind = _mesa_add_unnamed_constant(prog->Parameters, v, size, &swizzle);
+   slang_ir_storage *st = _slang_new_ir_storage(PROGRAM_CONSTANT, ind, size);
+   return st;
+}
+
+
+/**
+ * Swizzle a swizzle.
+ */
+static GLuint
+swizzle_compose(GLuint swz1, GLuint swz2)
+{
+   GLuint i, swz, s[4];
+   for (i = 0; i < 4; i++) {
+      GLuint c = GET_SWZ(swz1, i);
+      s[i] = GET_SWZ(swz2, c);
+   }
+   swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
+   return swz;
+}
+
+
+/**
+ * Convert IR storage to an instruction dst register.
+ */
+static void
+storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
+                   GLuint writemask)
+{
+   static const GLuint defaultWritemask[4] = {
+      WRITEMASK_X,
+      WRITEMASK_X | WRITEMASK_Y,
+      WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z,
+      WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z | WRITEMASK_W
+   };
+   dst->File = st->File;
+   dst->Index = st->Index;
+   assert(st->Size >= 1);
+   assert(st->Size <= 4);
+   dst->WriteMask = defaultWritemask[st->Size - 1] & writemask;
+}
+
+
+/**
+ * Convert IR storage to an instruction src register.
+ */
+static void
+storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st,
+                   GLuint swizzle)
+{
+   static const GLuint defaultSwizzle[4] = {
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
+   };
+     
+   src->File = st->File;
+   src->Index = st->Index;
+   assert(st->Size >= 1);
+   assert(st->Size <= 4);
+   /* XXX swizzling logic here may need some work */
+   /*src->Swizzle = swizzle_compose(swizzle, defaultSwizzle[st->Size - 1]);*/
+   if (swizzle != SWIZZLE_NOOP)
+      src->Swizzle = swizzle;
+   else
+      src->Swizzle = defaultSwizzle[st->Size - 1];
+}
+
+
+
+/**
+ * Add new instruction at end of given program.
+ * \param prog  the program to append instruction onto
+ * \param opcode  opcode for the new instruction
+ * \return pointer to the new instruction
+ */
+static struct prog_instruction *
+new_instruction(struct gl_program *prog, gl_inst_opcode opcode)
+{
+   struct prog_instruction *inst;
+   prog->Instructions = _mesa_realloc_instructions(prog->Instructions,
+                                                   prog->NumInstructions,
+                                                   prog->NumInstructions + 1);
+   inst = prog->Instructions + prog->NumInstructions;
+   prog->NumInstructions++;
+   _mesa_init_instructions(inst, 1);
+   inst->Opcode = opcode;
+   return inst;
+}
+
+
+static struct prog_instruction *
+gen(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog);
+
+
+/**
+ * Generate code for a simple binary-op instruction.
+ */
+static struct prog_instruction *
+gen_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+   struct prog_instruction *inst;
+   const slang_ir_info *info = slang_find_ir_info(n->Opcode);
+   assert(info);
+
+   gen(gc, n->Children[0], prog);
+   gen(gc, n->Children[1], prog);
+   inst = new_instruction(prog, info->InstOpcode);
+   /* alloc temp storage for the result: */
+   if (!n->Store || n->Store->File == PROGRAM_UNDEFINED) {
+#if 1
+      slang_alloc_temp_storage(gc, n, info->ResultSize);
+#else
+      slang_resolve_storage(gc, n, prog);
+#endif
+   }
+   storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+   storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+                      n->Children[0]->Swizzle);
+   storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
+                      n->Children[1]->Swizzle);
+   inst->Comment = n->Comment;
+   return inst;
+}
+
+
+static struct prog_instruction *
+gen_unop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+   struct prog_instruction *inst;
+   const slang_ir_info *info = slang_find_ir_info(n->Opcode);
+   assert(info);
+
+   assert(info->NumParams == 1);
+
+   gen(gc, n->Children[0], prog);
+
+   inst = new_instruction(prog, info->InstOpcode);
+   /*slang_resolve_storage(gc, n, prog);*/
+
+   if (!n->Store)
+      slang_alloc_temp_storage(gc, n, info->ResultSize);
+
+   storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+
+   storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+                      n->Children[0]->Swizzle);
+
+   inst->Comment = n->Comment;
+
+   return inst;
+}
+
+
+static struct prog_instruction *
+gen(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+   struct prog_instruction *inst;
+   if (!n)
+      return NULL;
+
+   switch (n->Opcode) {
+   case IR_SEQ:
+      assert(n->Children[0]);
+      assert(n->Children[1]);
+      gen(gc, n->Children[0], prog);
+      inst = gen(gc, n->Children[1], prog);
+      n->Store = n->Children[1]->Store;
+      return inst;
+      break;
+   case IR_VAR_DECL:
+      slang_resolve_storage(gc, n, prog);
+      assert(n->Store->Index >= 0);
+      assert(n->Store->Size > 0);
+      break;
+   case IR_VAR:
+      /*printf("Gen: var ref\n");*/
+      {
+         int b = !n->Store || n->Store->Index < 0;
+         if (b)
+            slang_resolve_storage(gc, n, prog);
+         /*assert(n->Store->Index >= 0);*/
+         assert(n->Store->Size > 0);
+      }
+      break;
+   case IR_MOVE:
+      /* rhs */
+      assert(n->Children[1]);
+      inst = gen(gc, n->Children[1], prog);
+      /* lhs */
+      gen(gc, n->Children[0], prog);
+
+#if 1
+      if (inst && is_temporary(gc, n->Children[1]->Store)) {
+         /* Peephole optimization:
+          * Just modify the RHS to put its result into the dest of this
+          * MOVE operation.  Then, this MOVE is a no-op.
+          */
+         free_temporary(gc, n->Children[1]->Store->Index);
+         *n->Children[1]->Store = *n->Children[0]->Store;
+         /* fixup the prev (RHS) instruction */
+         storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
+         return inst;
+      }
+      else
+#endif
+      {
+         inst = new_instruction(prog, OPCODE_MOV);
+         storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
+         storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
+                            n->Children[1]->Swizzle);
+         if (n->Children[1]->Store->File == PROGRAM_TEMPORARY) {
+            free_temporary(gc, n->Children[1]->Store->Index);
+         }
+         inst->Comment = n->Comment;
+         n->Store = n->Children[0]->Store; /*XXX new */
+         return inst;
+      }
+      break;
+   case IR_ADD:
+   case IR_SUB:
+   case IR_MUL:
+   case IR_DOT4:
+   case IR_DOT3:
+   case IR_CROSS:
+   case IR_MIN:
+   case IR_MAX:
+   case IR_SEQUAL:
+   case IR_SNEQUAL:
+   case IR_SGE:
+   case IR_SGT:
+   case IR_POW:
+   case IR_EXP:
+   case IR_EXP2:
+      return gen_binop(gc, n, prog);
+      break;
+   case IR_RSQ:
+   case IR_RCP:
+   case IR_FLOOR:
+   case IR_FRAC:
+   case IR_ABS:
+   case IR_SIN:
+   case IR_COS:
+      return gen_unop(gc, n, prog);
+      break;
+   case IR_LABEL:
+      /*printf("LAB: %s\n", n->Target);*/
+      break;
+   case IR_JUMP:
+#if 0
+      inst = new_instruction(prog, OPCODE_BRA);
+      inst->Comment = _mesa_strdup(n->Target);
+#endif
+      break;
+   case IR_FLOAT:
+      n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
+      break;
+   default:
+      printf("gen: ?\n");
+      abort();
+   }
+   return NULL;
+}
+
+
+
+GLboolean
+_slang_emit_code(slang_ir_node *n, struct gl_program *prog)
+{
+   slang_gen_context *gc;
+   /*GET_CURRENT_CONTEXT(ctx);*/
+
+   gc = (slang_gen_context *) _mesa_calloc(sizeof(*gc));
+
+   printf("************ Begin generate code\n");
+
+   gen(gc, n, prog);
+
+   {
+      struct prog_instruction *inst;
+      inst = new_instruction(prog, OPCODE_END);
+   }
+
+   printf("************ End generate code (%u inst):\n", prog->NumInstructions);
+
+#if 0
+   _mesa_print_program(prog);
+   _mesa_print_program_parameters(ctx,prog);
+#endif
+
+   _mesa_free(gc);
+
+   return GL_FALSE;
+}
diff --git a/src/mesa/shader/slang/slang_emit.h b/src/mesa/shader/slang/slang_emit.h
new file mode 100644 (file)
index 0000000..1683542
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_EMIT_H
+#define SLANG_EMIT_H
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_ir.h"
+#include "mtypes.h"
+
+
+typedef struct {
+   GLboolean TempUsed[MAX_PROGRAM_TEMPS];
+} slang_gen_context;
+
+
+extern void
+slang_print_ir(const slang_ir_node *n, int indent);
+
+
+extern slang_ir_storage *
+_slang_new_ir_storage(enum register_file file, GLint index, GLint size);
+
+
+extern void
+slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
+                      struct gl_program *prog);
+
+extern GLboolean
+_slang_emit_code(slang_ir_node *n, struct gl_program *prog);
+
+
+#endif /* SLANG_EMIT_H */
diff --git a/src/mesa/shader/slang/slang_error.c b/src/mesa/shader/slang/slang_error.c
new file mode 100644 (file)
index 0000000..2767163
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "imports.h"
+#include "slang_error.h"
+
+
+static char ErrorText[10000];
+static char FormattedErrorText[10000];
+static int ErrorPos;
+
+
+void
+_slang_reset_error(void)
+{
+   ErrorText[0] = 0;
+   ErrorPos = -1;
+}
+
+
+/**
+ * Record an error message, if one hasn't been recorded already.
+ */
+void
+_slang_record_error(const char *msg1, const char *msg2,
+                    GLint pos, const char *file, int line)
+{
+   /* don't overwrite a previously recorded error */
+   if (!ErrorText[0]) {
+      _mesa_sprintf(ErrorText, "%s %s", msg1, msg2);
+      ErrorPos = -1;
+#ifdef DEBUG
+      fprintf(stderr, "Mesa shader compile error: %s %s at %d (%s line %d)\n",
+              msg1, msg2, pos, file, line);
+#endif
+   }
+}
+
+
+/** 
+ * Return formatted error text.
+ */
+const char *
+_slang_error_text(void)
+{
+   /*
+    * NVIDIA formats errors like this:
+    *   (LINE_NUMBER) : error ERROR_CODE: ERROR_TEXT
+    * Example:
+    *   (7) : error C1048: invalid character 'P' in swizzle "P"
+    */
+   _mesa_sprintf(FormattedErrorText,
+                 "(%d) : error: %s", ErrorPos, ErrorText);
+   return FormattedErrorText;
+}
+
diff --git a/src/mesa/shader/slang/slang_error.h b/src/mesa/shader/slang/slang_error.h
new file mode 100644 (file)
index 0000000..d35ae83
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_ERROR_H
+#define SLANG_ERROR_H
+
+
+extern void
+_slang_reset_error(void);
+
+
+extern void
+_slang_record_error(const char *msg1, const char *msg2,
+                    GLint pos, const char *file, int line);
+
+
+extern const char *
+_slang_error_text(void);
+
+
+/**
+ * Record a compilation error, single string message.
+ */
+#define RETURN_ERROR(MSG, POS)                             \
+do {                                                       \
+   _slang_record_error(MSG, "", POS, __FILE__, __LINE__);  \
+   return GL_FALSE;                                        \
+} while (0)
+
+
+/**
+ * Record a compilation error, two-string message.
+ */
+#define RETURN_ERROR2(MSG1, MSG2, POS)                        \
+do {                                                          \
+   _slang_record_error(MSG1, MSG2, POS, __FILE__, __LINE__);  \
+   return GL_FALSE;                                           \
+} while (0)
+
+
+/**
+ * Record a nil error.  Either a real error message or out of memory should
+ * have already been recorded.
+ */
+#define RETURN_NIL()                                            \
+do {                                                            \
+   _slang_record_error("unknown", "", -1, __FILE__, __LINE__);  \
+   return GL_FALSE;                                             \
+} while (0)
+
+
+/**
+ * Used to report an out of memory condition.
+ */
+#define RETURN_OUT_OF_MEMORY()                                        \
+do {                                                                  \
+   _slang_record_error("Out of memory", "", -1, __FILE__, __LINE__);  \
+   return GL_FALSE;                                                   \
+} while (0)
+
+
+
+
+#endif /* SLANG_ERROR_H */
index e469de02075c1531084a14c7ad126f4cc4697d01..09401b8910a2656bab0ca5181c0c8be9c43c7193 100644 (file)
@@ -392,12 +392,16 @@ _slang_execute2(const slang_assembly_file * file, slang_machine * mach)
       case slang_asm_int_copy:
       case slang_asm_bool_copy:
          /* store top value on stack to memory */
+#if 0
          {
             GLuint address
                = (stack[mach->sp + a->param[0] / 4]._addr + a->param[1]) / 4;
             GLfloat value = stack[mach->sp]._float;
             mach->mem[address]._float = value;
          }
+#else
+         mach->mem[(stack[mach->sp + a->param[0] / 4]._addr +a->param[1]) / 4]._float = stack[mach->sp]._float;
+#endif
          mach->sp++;
          break;
       case slang_asm_float_move:
@@ -425,6 +429,10 @@ _slang_execute2(const slang_assembly_file * file, slang_machine * mach)
          stack[mach->sp + 1]._float += stack[mach->sp]._float;
          mach->sp++;
          break;
+      case slang_asm_float_subtract:
+         stack[mach->sp + 1]._float -= stack[mach->sp]._float;
+         mach->sp++;
+         break;
       case slang_asm_float_multiply:
          stack[mach->sp + 1]._float *= stack[mach->sp]._float;
          mach->sp++;
@@ -476,12 +484,14 @@ _slang_execute2(const slang_assembly_file * file, slang_machine * mach)
       case slang_asm_float_log2:
          stack[mach->sp]._float = LOG2(stack[mach->sp]._float);
          break;
+#if 0
       case slang_asm_float_floor:
          stack[mach->sp]._float = FLOORF(stack[mach->sp]._float);
          break;
       case slang_asm_float_ceil:
          stack[mach->sp]._float = CEILF(stack[mach->sp]._float);
          break;
+#endif
       case slang_asm_float_noise1:
          stack[mach->sp]._float =
             _slang_library_noise1(stack[mach->sp]._float);
@@ -718,6 +728,7 @@ _slang_execute2(const slang_assembly_file * file, slang_machine * mach)
                -mach->mem[(da + 12) / 4]._float;
          }
          break;
+#if 0
       case slang_asm_vec4_dot:
          /* [vec4] | vec4 > [float] */
          {
@@ -730,6 +741,7 @@ _slang_execute2(const slang_assembly_file * file, slang_machine * mach)
             mach->sp += 4;
          }
          break;
+#endif
       case slang_asm_vec4_copy:
          /* [vec4] | vec4 > [vec4] */
          {
@@ -768,6 +780,19 @@ _slang_execute2(const slang_assembly_file * file, slang_machine * mach)
             }
          }
          break;
+      case slang_asm_vec4_dot:
+      case slang_asm_vec3_dot:
+         {
+            /* XXX almost certainly wrong */
+            GLuint da = stack[mach->sp + 4]._addr;
+            mach->mem[da / 4]._float =
+               mach->mem[da / 4]._float * stack[mach->sp]._float +
+               mach->mem[(da + 4) / 4]._float * stack[mach->sp + 1]._float +
+               mach->mem[(da + 8) / 4]._float * stack[mach->sp + 2]._float +
+               mach->mem[(da + 12) / 4]._float * stack[mach->sp + 3]._float;
+            mach->sp += 4;
+         }
+         break;
       default:
          _mesa_problem(NULL, "bad slang opcode 0x%x", a->type);
          return GL_FALSE;
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
new file mode 100644 (file)
index 0000000..3c58336
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_ir.h
+ * Mesa GLSL Itermediate Representation tree types and constants.
+ * \author Brian Paul
+ */
+
+
+#ifndef SLANG_IR_H
+#define SLANG_IR_H
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "mtypes.h"
+
+
+/**
+ * Intermediate Representation opcode
+ */
+typedef enum
+{
+   IR_NOP = 0,
+   IR_SEQ,
+   IR_LABEL,   /* target of a jump or cjump */
+   IR_JUMP,    /* unconditional jump */
+   IR_CJUMP,   /* conditional jump */
+   IR_CALL,
+   IR_MOVE,
+   IR_ADD,
+   IR_SUB,
+   IR_MUL,
+   IR_DIV,
+   IR_DOT4,
+   IR_DOT3,
+   IR_CROSS,
+   IR_MIN,
+   IR_MAX,
+   IR_SEQUAL,
+   IR_SNEQUAL,
+   IR_SGE,
+   IR_SGT,
+   IR_POW,
+   IR_EXP,
+   IR_EXP2,
+   IR_LOG2,
+   IR_RSQ,
+   IR_RCP,
+   IR_FLOOR,
+   IR_FRAC,
+   IR_ABS,
+   IR_SIN,
+   IR_COS,
+   IR_LESS,
+   IR_NOT,
+   IR_VAR,
+   IR_VAR_DECL,
+   IR_FLOAT,
+   IR_FIELD,
+   IR_I_TO_F
+} slang_ir_opcode;
+
+
+/**
+ * Describes where data storage is allocated.
+ */
+typedef struct
+{
+   enum register_file File;  /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
+   GLint Index;  /**< -1 means unallocated */
+   GLint Size;  /**< number of floats */
+} slang_ir_storage;
+
+
+/**
+ * Intermediate Representation (IR) tree node
+ */
+typedef struct slang_ir_node_
+{
+   slang_ir_opcode Opcode;
+   struct slang_ir_node_ *Children[2];
+   const char *Comment;
+   const char *Target;
+   GLuint Swizzle;
+   GLuint Writemask;  /**< If Op == IR_MOVE */
+   GLfloat Value[4];    /**< If Op == IR_FLOAT */
+   slang_variable *Var;
+   slang_ir_storage *Store;
+} slang_ir_node;
+
+
+#endif /* SLANG_IR_H */
index 433964223a5772e7ccd82eb6bd57cf3a387a0ff3..af45c6657e4acb6c7497608282fab980590b7d00 100644 (file)
@@ -316,6 +316,9 @@ enum
    SLANG_COMMON_CODE_MAX
 };
 
+/**
+ * XXX promote this to mtypes.h?
+ */
 typedef struct
 {
    slang_active_variables active_uniforms;
@@ -345,6 +348,11 @@ _slang_program_rst (slang_program *);
 extern GLboolean
 _slang_link (slang_program *, slang_code_object **, GLuint);
 
+
+extern void
+_slang_link2(GLcontext *ctx, GLhandleARB h,
+             struct gl_linked_program *linked);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/mesa/shader/slang/slang_link2.c b/src/mesa/shader/slang/slang_link2.c
new file mode 100644 (file)
index 0000000..e62cc01
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.6
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_link.c
+ * slang linker
+ * \author Michal Krol
+ */
+
+#include "imports.h"
+#include "context.h"
+#include "hash.h"
+#include "macros.h"
+#include "program.h"
+#include "shaderobjects.h"
+#include "slang_link.h"
+
+
+
+
+#define RELEASE_GENERIC(x)\
+   (**x)._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+#define RELEASE_CONTAINER(x)\
+   (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+#define RELEASE_PROGRAM(x)\
+   (**x)._container._generic._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+#define RELEASE_SHADER(x)\
+   (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+
+
+static struct gl2_unknown_intf **
+lookup_handle(GLcontext * ctx, GLhandleARB handle, enum gl2_uiid uiid,
+              const char *function)
+{
+   struct gl2_unknown_intf **unk;
+
+   /*
+    * Note: _mesa_HashLookup() requires non-zero input values, so the
+    * passed-in handle value must be checked beforehand.
+    */
+   if (handle == 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, function);
+      return NULL;
+   }
+   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+   unk = (struct gl2_unknown_intf **) _mesa_HashLookup(ctx->Shared->GL2Objects,
+                                                       handle);
+   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+   if (unk == NULL) {
+      _mesa_error(ctx, GL_INVALID_VALUE, function);
+   }
+   else {
+      unk = (**unk).QueryInterface(unk, uiid);
+      if (unk == NULL)
+         _mesa_error(ctx, GL_INVALID_OPERATION, function);
+   }
+   return unk;
+}
+
+#define GET_GENERIC(x, handle, function)\
+   struct gl2_generic_intf **x = (struct gl2_generic_intf **)\
+                                 lookup_handle (ctx, handle, UIID_GENERIC, function);
+
+#define GET_CONTAINER(x, handle, function)\
+   struct gl2_container_intf **x = (struct gl2_container_intf **)\
+                                   lookup_handle (ctx, handle, UIID_CONTAINER, function);
+
+#define GET_PROGRAM(x, handle, function)\
+   struct gl2_program_intf **x = (struct gl2_program_intf **)\
+                                 lookup_handle (ctx, handle, UIID_PROGRAM, function);
+
+#define GET_SHADER(x, handle, function)\
+   struct gl2_shader_intf **x = (struct gl2_shader_intf **)\
+                                lookup_handle (ctx, handle, UIID_SHADER, function);
+
+
+static void
+prelink(GLhandleARB programObj, struct gl_linked_program *linked)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   linked->VertexProgram = NULL;
+   linked->FragmentProgram = NULL;
+
+   if (programObj != 0) {
+      GET_PROGRAM(program, programObj, "glUseProgramObjectARB(program)");
+
+      if (program == NULL)
+         return;
+
+      /* XXX terrible hack to find the real vertex/fragment programs */
+      {
+         GLuint handle;
+         GLsizei cnt, i;
+         cnt = (**program)._container.GetAttachedCount((struct gl2_container_intf **) (program));
+
+         for (i = 0; i < cnt; i++) {
+            struct gl2_generic_intf **x
+               = (**program)._container.GetAttached((struct gl2_container_intf **) program, i);
+            handle = (**x).GetName(x);
+            {
+               struct gl_program *prog;
+               GET_SHADER(sha, handle, "foo");
+               if (sha && (*sha)->Program) {
+                  prog = (*sha)->Program;
+                  if (prog->Target == GL_VERTEX_PROGRAM_ARB)
+                     linked->VertexProgram = (struct gl_vertex_program *) prog;
+                  else if (prog->Target == GL_FRAGMENT_PROGRAM_ARB)
+                     linked->FragmentProgram = (struct gl_fragment_program *) prog;
+               }
+            }
+#if 0
+            if (linked->VertexProgram)
+               printf("Found vert prog %p %d\n",
+                      linked->VertexProgram,
+                      linked->VertexProgram->Base.NumInstructions);
+            if (linked->FragmentProgram)
+               printf("Found frag prog %p %d\n",
+                      linked->FragmentProgram,
+                      linked->FragmentProgram->Base.NumInstructions);
+#endif
+            RELEASE_GENERIC(x);
+         }
+      }
+
+   }
+}
+
+
+
+void
+_slang_link2(GLcontext *ctx,
+             GLhandleARB programObj,
+             struct gl_linked_program *linked)
+{
+   struct gl_vertex_program *vertProg;
+   struct gl_fragment_program *fragProg;
+
+   prelink(programObj, linked);
+
+   vertProg = linked->VertexProgram;
+   fragProg = linked->FragmentProgram;
+
+   /* free old linked data, if any */
+   if (linked->NumUniforms > 0) {
+      GLuint i;
+      for (i = 0; i < linked->NumUniforms; i++) {
+         _mesa_free((char *) linked->Uniforms[i].Name);
+         linked->Uniforms[i].Name = NULL;
+         linked->Uniforms[i].Value = NULL;
+      }
+      linked->NumUniforms = 0;
+   }
+
+   /*
+    * Find uniforms.
+    * XXX what about dups?
+    */
+   if (vertProg) {
+      GLuint i;
+      for (i = 0; i < vertProg->Base.Parameters->NumParameters; i++) {
+         struct gl_program_parameter *p
+            = vertProg->Base.Parameters->Parameters + i;
+         if (p->Name) {
+            struct gl_uniform *u = linked->Uniforms + linked->NumUniforms;
+            u->Name = _mesa_strdup(p->Name);
+            u->Value = &vertProg->Base.Parameters->ParameterValues[i][0];
+            linked->NumUniforms++;
+            assert(linked->NumUniforms < MAX_UNIFORMS);
+         }
+      }
+   }
+   if (fragProg) {
+      GLuint i;
+      for (i = 0; i < fragProg->Base.Parameters->NumParameters; i++) {
+         struct gl_program_parameter *p
+            = fragProg->Base.Parameters->Parameters + i;
+         if (p->Name) {
+            struct gl_uniform *u = linked->Uniforms + linked->NumUniforms;
+            u->Name = _mesa_strdup(p->Name);
+            u->Value = &fragProg->Base.Parameters->ParameterValues[i][0];
+            linked->NumUniforms++;
+            assert(linked->NumUniforms < MAX_UNIFORMS);
+         }
+      }
+   }
+
+   /* For varying:
+    * scan both programs for varyings, rewrite programs so they agree
+    * on locations of varyings.
+    */
+
+   /**
+    * Linking should _copy_ the vertex and fragment shader code,
+    * rewriting varying references as we go along...
+    */
+
+   linked->LinkStatus = (vertProg && fragProg);
+}
+
diff --git a/src/mesa/shader/slang/slang_print.c b/src/mesa/shader/slang/slang_print.c
new file mode 100644 (file)
index 0000000..2ac0629
--- /dev/null
@@ -0,0 +1,1136 @@
+
+/**
+ * Dump/print a slang_operation tree
+ */
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_print.h"
+
+
+static void
+spaces(int n)
+{
+   while (n--)
+      printf(" ");
+}
+
+
+static void
+print_type(const slang_fully_specified_type *t)
+{
+   switch (t->qualifier) {
+   case slang_qual_none:
+      /*printf("");*/
+      break;
+   case slang_qual_const:
+      printf("const ");
+      break;
+   case slang_qual_attribute:
+      printf("attrib ");
+      break;
+   case slang_qual_varying:
+      printf("varying ");
+      break;
+   case slang_qual_uniform:
+      printf("uniform ");
+      break;
+   case slang_qual_out:
+      printf("output ");
+      break;
+   case slang_qual_inout:
+      printf("inout ");
+      break;
+   case slang_qual_fixedoutput:
+      printf("fixedoutput");
+      break;
+   case slang_qual_fixedinput:
+      printf("fixedinput");
+      break;
+   default:
+      printf("unknown qualifer!");
+   }
+
+   switch (t->specifier.type) {
+   case slang_spec_void:
+      printf("void");
+      break;
+   case slang_spec_bool:
+      printf("bool");
+      break;
+   case slang_spec_bvec2:
+      printf("bvec2");
+      break;
+   case slang_spec_bvec3:
+      printf("bvec3");
+      break;
+   case slang_spec_bvec4:
+      printf("bvec4");
+      break;
+   case slang_spec_int:
+      printf("int");
+      break;
+   case slang_spec_ivec2:
+      printf("ivec2");
+      break;
+   case slang_spec_ivec3:
+      printf("ivec3");
+      break;
+   case slang_spec_ivec4:
+      printf("ivec4");
+      break;
+   case slang_spec_float:
+      printf("float");
+      break;
+   case slang_spec_vec2:
+      printf("vec2");
+      break;
+   case slang_spec_vec3:
+      printf("vec3");
+      break;
+   case slang_spec_vec4:
+      printf("vec4");
+      break;
+   case slang_spec_mat2:
+      printf("mat2");
+      break;
+   case slang_spec_mat3:
+      printf("mat3");
+      break;
+   case slang_spec_mat4:
+      printf("mat4");
+      break;
+   case slang_spec_sampler1D:
+      printf("sampler1D");
+      break;
+   case slang_spec_sampler2D:
+      printf("sampler2D");
+      break;
+   case slang_spec_sampler3D:
+      printf("sampler3D");
+      break;
+   case slang_spec_samplerCube:
+      printf("samplerCube");
+      break;
+   case slang_spec_sampler1DShadow:
+      printf("sampler1DShadow");
+      break;
+   case slang_spec_sampler2DShadow:
+      printf("sampler2DShadow");
+      break;
+   case slang_spec_struct:
+      printf("struct");
+      break;
+   case slang_spec_array:
+      printf("array");
+      break;
+   default:
+      printf("unknown type");
+   }
+   /*printf("\n");*/
+}
+
+
+static void
+print_variable(const slang_variable *v, int indent)
+{
+   spaces(indent);
+   printf("VAR ");
+   print_type(&v->type);
+   printf(" %s", (char *) v->a_name);
+   if (v->initializer) {
+      printf(" :=\n");
+      slang_print_tree(v->initializer, indent + 3);
+   }
+   else {
+      printf(";\n");
+   }
+}
+
+
+static void
+print_binary(const slang_operation *op, const char *oper, int indent)
+{
+   assert(op->num_children == 2);
+   slang_print_tree(&op->children[0], indent + 3);
+   spaces(indent);
+   printf("%s\n", oper);
+   slang_print_tree(&op->children[1], indent + 3);
+}
+
+
+static void
+print_generic2(const slang_operation *op, const char *oper,
+               const char *s, int indent)
+{
+   int i;
+   if (oper) {
+      spaces(indent);
+      printf("[%p locals %p] %s %s\n", (void*) op, (void*) op->locals, oper, s);
+   }
+   for (i = 0; i < op->num_children; i++) {
+      spaces(indent);
+      printf("//child %d:\n", i);
+      slang_print_tree(&op->children[i], indent);
+   }
+}
+
+static void
+print_generic(const slang_operation *op, const char *oper, int indent)
+{
+   print_generic2(op, oper, "", indent);
+}
+
+
+static const slang_variable_scope *
+find_scope(const slang_variable_scope *s, slang_atom name)
+{
+   GLuint i;
+   for (i = 0; i < s->num_variables; i++) {
+      if (s->variables[i].a_name == name)
+         return s;
+   }
+   if (s->outer_scope)
+      return find_scope(s->outer_scope, name);
+   else
+      return NULL;
+}
+
+static const slang_variable *
+find_var(const slang_variable_scope *s, slang_atom name)
+{
+   GLuint i;
+   for (i = 0; i < s->num_variables; i++) {
+      if (s->variables[i].a_name == name)
+         return &s->variables[i];
+   }
+   if (s->outer_scope)
+      return find_var(s->outer_scope, name);
+   else
+      return NULL;
+}
+
+
+void
+slang_print_tree(const slang_operation *op, int indent)
+{
+   int i;
+
+   switch (op->type) {
+
+   case slang_oper_none:
+      spaces(indent);
+      printf("slang_oper_none\n");
+      break;
+
+   case slang_oper_block_no_new_scope:
+      spaces(indent);
+      printf("{ locals %p\n", (void*)op->locals);
+      print_generic(op, NULL, indent+3);
+      spaces(indent);
+      printf("}\n");
+      break;
+
+   case slang_oper_block_new_scope:
+      spaces(indent);
+      printf("{{ // new scope  locals %p\n", (void*)op->locals);
+      print_generic(op, NULL, indent+3);
+      spaces(indent);
+      printf("}}\n");
+      break;
+
+   case slang_oper_variable_decl:
+      assert(op->num_children == 0 || op->num_children == 1);
+      {
+         slang_variable *v;
+         v = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
+         if (v) {
+            spaces(indent);
+            printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope);
+            print_type(&v->type);
+            printf(" %s (%p)", (char *) op->a_id,
+                   (void *) find_var(op->locals, op->a_id));
+
+            printf(" (in scope %p) ",
+                   (void *) find_scope(op->locals, op->a_id));
+            if (op->num_children == 1) {
+               printf(" :=\n");
+               slang_print_tree(&op->children[0], indent + 3);
+            }
+            else if (v->initializer) {
+               printf(" := INITIALIZER\n");
+               slang_print_tree(v->initializer, indent + 3);
+            }
+            else {
+               printf(";\n");
+            }
+            /*
+            spaces(indent);
+            printf("TYPE: ");
+            print_type(&v->type);
+            spaces(indent);
+            printf("ADDR: %d  size: %d\n", v->address, v->size);
+            */
+         }
+         else {
+            abort();
+            spaces(indent);
+            printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id);
+            /*abort();*/
+         }
+      }
+      break;
+
+   case slang_oper_asm:
+      spaces(indent);
+      printf("ASM: %s\n", (char*) op->a_id);
+      print_generic(op, NULL, indent+3);
+      break;
+
+   case slang_oper_break:
+      spaces(indent);
+      printf("BREAK\n");
+      break;
+
+   case slang_oper_continue:
+      spaces(indent);
+      printf("CONTINUE\n");
+      break;
+
+   case slang_oper_discard:
+      spaces(indent);
+      printf("DISCARD\n");
+      break;
+
+   case slang_oper_return:
+      spaces(indent);
+      printf("RETURN\n");
+      if (op->num_children > 0)
+         slang_print_tree(&op->children[0], indent + 3);
+      break;
+
+   case slang_oper_goto:
+      spaces(indent);
+      printf("GOTO %s\n", (char *) op->a_id);
+      break;
+
+   case slang_oper_label:
+      spaces(indent);
+      printf("LABEL %s\n", (char *) op->a_id);
+      break;
+
+   case slang_oper_expression:
+      spaces(indent);
+      printf("EXPR:  locals %p\n", (void*) op->locals);
+      /*print_generic(op, "slang_oper_expression", indent);*/
+      slang_print_tree(&op->children[0], indent + 3);
+      break;
+
+   case slang_oper_if:
+      spaces(indent);
+      printf("IF\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("THEN\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      spaces(indent);
+      printf("ELSE\n");
+      slang_print_tree(&op->children[2], indent + 3);
+      spaces(indent);
+      printf("ENDIF\n");
+      break;
+
+   case slang_oper_while:
+      assert(op->num_children == 2);
+      spaces(indent);
+      printf("WHILE cond:\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("WHILE body:\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      break;
+
+   case slang_oper_do:
+      spaces(indent);
+      printf("DO body:\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("DO cond:\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      break;
+
+   case slang_oper_for:
+      spaces(indent);
+      printf("FOR init:\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("FOR while:\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      spaces(indent);
+      printf("FOR step:\n");
+      slang_print_tree(&op->children[2], indent + 3);
+      spaces(indent);
+      printf("FOR body:\n");
+      slang_print_tree(&op->children[3], indent + 3);
+      spaces(indent);
+      printf("ENDFOR\n");
+      /*
+      print_generic(op, "FOR", indent + 3);
+      */
+      break;
+
+   case slang_oper_void:
+      spaces(indent);
+      printf("(oper-void)\n");
+      break;
+
+   case slang_oper_literal_bool:
+      spaces(indent);
+      /*printf("slang_oper_literal_bool\n");*/
+      printf("%s\n", op->literal[0] ? "TRUE" : "FALSE");
+      break;
+
+   case slang_oper_literal_int:
+      spaces(indent);
+      /*printf("slang_oper_literal_int\n");*/
+      printf("(%d %d %d %d)\n", (int) op->literal[0], (int) op->literal[1],
+             (int) op->literal[2], (int) op->literal[3]);
+      break;
+
+   case slang_oper_literal_float:
+      spaces(indent);
+      /*printf("slang_oper_literal_float\n");*/
+      printf("(%f %f %f %f)\n", op->literal[0], op->literal[1], op->literal[2],
+             op->literal[3]);
+      break;
+
+   case slang_oper_identifier:
+      spaces(indent);
+      if (op->var && op->var->a_name)
+         printf("VAR %s  (in scope %p)\n", (char *) op->var->a_name,
+                (void *) find_scope(op->locals, op->a_id));
+      else
+         printf("VAR' %s  (in scope %p)\n", (char *) op->a_id,
+                (void *) find_scope(op->locals, op->a_id));
+      break;
+
+   case slang_oper_sequence:
+      print_generic(op, "COMMA-SEQ", indent+3);
+      break;
+
+   case slang_oper_assign:
+      spaces(indent);
+      printf("ASSIGNMENT  locals %p\n", (void*)op->locals);
+      print_binary(op, ":=", indent);
+      break;
+
+   case slang_oper_addassign:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "+=", indent);
+      break;
+
+   case slang_oper_subassign:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "-=", indent);
+      break;
+
+   case slang_oper_mulassign:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "*=", indent);
+      break;
+
+   case slang_oper_divassign:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "/=", indent);
+      break;
+
+       /*slang_oper_modassign,*/
+       /*slang_oper_lshassign,*/
+       /*slang_oper_rshassign,*/
+       /*slang_oper_orassign,*/
+       /*slang_oper_xorassign,*/
+       /*slang_oper_andassign,*/
+   case slang_oper_select:
+      spaces(indent);
+      printf("slang_oper_select n=%d\n", op->num_children);
+      assert(op->num_children == 3);
+      slang_print_tree(&op->children[0], indent+3);
+      spaces(indent);
+      printf("?\n");
+      slang_print_tree(&op->children[1], indent+3);
+      spaces(indent);
+      printf(":\n");
+      slang_print_tree(&op->children[2], indent+3);
+      break;
+
+   case slang_oper_logicalor:
+      print_binary(op, "||", indent);
+      break;
+
+   case slang_oper_logicalxor:
+      print_binary(op, "^^", indent);
+      break;
+
+   case slang_oper_logicaland:
+      print_binary(op, "&&", indent);
+      break;
+
+   /*slang_oper_bitor*/
+   /*slang_oper_bitxor*/
+   /*slang_oper_bitand*/
+   case slang_oper_equal:
+      print_binary(op, "==", indent);
+      break;
+
+   case slang_oper_notequal:
+      print_binary(op, "!=", indent);
+      break;
+
+   case slang_oper_less:
+      print_binary(op, "<", indent);
+      break;
+
+   case slang_oper_greater:
+      print_binary(op, ">", indent);
+      break;
+
+   case slang_oper_lessequal:
+      print_binary(op, "<=", indent);
+      break;
+
+   case slang_oper_greaterequal:
+      print_binary(op, ">=", indent);
+      break;
+
+   /*slang_oper_lshift*/
+   /*slang_oper_rshift*/
+   case slang_oper_add:
+      print_binary(op, "+", indent);
+      break;
+
+   case slang_oper_subtract:
+      print_binary(op, "-", indent);
+      break;
+
+   case slang_oper_multiply:
+      print_binary(op, "*", indent);
+      break;
+
+   case slang_oper_divide:
+      print_binary(op, "/", indent);
+      break;
+
+   /*slang_oper_modulus*/
+   case slang_oper_preincrement:
+      spaces(indent);
+      printf("PRE++\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case slang_oper_predecrement:
+      spaces(indent);
+      printf("PRE--\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case slang_oper_plus:
+      spaces(indent);
+      printf("slang_oper_plus\n");
+      break;
+
+   case slang_oper_minus:
+      spaces(indent);
+      printf("slang_oper_minus\n");
+      break;
+
+   /*slang_oper_complement*/
+   case slang_oper_not:
+      spaces(indent);
+      printf("NOT\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case slang_oper_subscript:
+      spaces(indent);
+      printf("slang_oper_subscript\n");
+      print_generic(op, NULL, indent+3);
+      break;
+
+   case slang_oper_call:
+#if 0
+         slang_function *fun
+            = _slang_locate_function(A->space.funcs, oper->a_id,
+                                     oper->children,
+                                     oper->num_children, &A->space, A->atoms);
+#endif
+      spaces(indent);
+      printf("CALL %s(\n", (char *) op->a_id);
+      for (i = 0; i < op->num_children; i++) {
+         slang_print_tree(&op->children[i], indent+3);
+         if (i + 1 < op->num_children) {
+            spaces(indent + 3);
+            printf(",\n");
+         }
+      }
+      spaces(indent);
+      printf(")\n");
+      break;
+
+   case slang_oper_field:
+      spaces(indent);
+      printf("FIELD %s of\n", (char*) op->a_id);
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case slang_oper_postincrement:
+      spaces(indent);
+      printf("POST++\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case slang_oper_postdecrement:
+      spaces(indent);
+      printf("POST--\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   default:
+      printf("unknown op->type %d\n", (int) op->type);
+   }
+
+}
+
+
+
+void
+slang_print_function(const slang_function *f, GLboolean body)
+{
+   int i;
+
+#if 0
+   if (_mesa_strcmp((char *) f->header.a_name, "main") != 0)
+     return;
+#endif
+
+   printf("FUNCTION %s (\n",
+          (char *) f->header.a_name);
+
+   for (i = 0; i < f->param_count; i++) {
+      print_variable(&f->parameters->variables[i], 3);
+   }
+
+   printf(")\n");
+   if (body && f->body)
+      slang_print_tree(f->body, 0);
+}
+
+
+
+
+/* operation */
+#define OP_END 0
+#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
+#define OP_BLOCK_BEGIN_NEW_SCOPE 2
+#define OP_DECLARE 3
+#define OP_ASM 4
+#define OP_BREAK 5
+#define OP_CONTINUE 6
+#define OP_DISCARD 7
+#define OP_RETURN 8
+#define OP_EXPRESSION 9
+#define OP_IF 10
+#define OP_WHILE 11
+#define OP_DO 12
+#define OP_FOR 13
+#define OP_PUSH_VOID 14
+#define OP_PUSH_BOOL 15
+#define OP_PUSH_INT 16
+#define OP_PUSH_FLOAT 17
+#define OP_PUSH_IDENTIFIER 18
+#define OP_SEQUENCE 19
+#define OP_ASSIGN 20
+#define OP_ADDASSIGN 21
+#define OP_SUBASSIGN 22
+#define OP_MULASSIGN 23
+#define OP_DIVASSIGN 24
+/*#define OP_MODASSIGN 25*/
+/*#define OP_LSHASSIGN 26*/
+/*#define OP_RSHASSIGN 27*/
+/*#define OP_ORASSIGN 28*/
+/*#define OP_XORASSIGN 29*/
+/*#define OP_ANDASSIGN 30*/
+#define OP_SELECT 31
+#define OP_LOGICALOR 32
+#define OP_LOGICALXOR 33
+#define OP_LOGICALAND 34
+/*#define OP_BITOR 35*/
+/*#define OP_BITXOR 36*/
+/*#define OP_BITAND 37*/
+#define OP_EQUAL 38
+#define OP_NOTEQUAL 39
+#define OP_LESS 40
+#define OP_GREATER 41
+#define OP_LESSEQUAL 42
+#define OP_GREATEREQUAL 43
+/*#define OP_LSHIFT 44*/
+/*#define OP_RSHIFT 45*/
+#define OP_ADD 46
+#define OP_SUBTRACT 47
+#define OP_MULTIPLY 48
+#define OP_DIVIDE 49
+/*#define OP_MODULUS 50*/
+#define OP_PREINCREMENT 51
+#define OP_PREDECREMENT 52
+#define OP_PLUS 53
+#define OP_MINUS 54
+/*#define OP_COMPLEMENT 55*/
+#define OP_NOT 56
+#define OP_SUBSCRIPT 57
+#define OP_CALL 58
+#define OP_FIELD 59
+#define OP_POSTINCREMENT 60
+#define OP_POSTDECREMENT 61
+
+
+void
+slang_print_opcode(unsigned int opcode)
+{
+   switch (opcode) {
+   case OP_PUSH_VOID:
+      printf("OP_PUSH_VOID\n");
+      break;
+   case OP_PUSH_BOOL:
+      printf("OP_PUSH_BOOL\n");
+      break;
+   case OP_PUSH_INT:
+      printf("OP_PUSH_INT\n");
+      break;
+   case OP_PUSH_FLOAT:
+      printf("OP_PUSH_FLOAT\n");
+      break;
+   case OP_PUSH_IDENTIFIER:
+      printf("OP_PUSH_IDENTIFIER\n");
+      break;
+   case OP_SEQUENCE:
+      printf("OP_SEQUENCE\n");
+      break;
+   case OP_ASSIGN:
+      printf("OP_ASSIGN\n");
+      break;
+   case OP_ADDASSIGN:
+      printf("OP_ADDASSIGN\n");
+      break;
+   case OP_SUBASSIGN:
+      printf("OP_SUBASSIGN\n");
+      break;
+   case OP_MULASSIGN:
+      printf("OP_MULASSIGN\n");
+      break;
+   case OP_DIVASSIGN:
+      printf("OP_DIVASSIGN\n");
+      break;
+   /*case OP_MODASSIGN:*/
+   /*case OP_LSHASSIGN:*/
+   /*case OP_RSHASSIGN:*/
+   /*case OP_ORASSIGN:*/
+   /*case OP_XORASSIGN:*/
+   /*case OP_ANDASSIGN:*/
+   case OP_SELECT:
+      printf("OP_SELECT\n");
+      break;
+   case OP_LOGICALOR:
+      printf("OP_LOGICALOR\n");
+      break;
+   case OP_LOGICALXOR:
+      printf("OP_LOGICALXOR\n");
+      break;
+   case OP_LOGICALAND:
+      printf("OP_LOGICALAND\n");
+      break;
+   /*case OP_BITOR:*/
+   /*case OP_BITXOR:*/
+   /*case OP_BITAND:*/
+   case OP_EQUAL:
+      printf("OP_EQUAL\n");
+      break;
+   case OP_NOTEQUAL:
+      printf("OP_NOTEQUAL\n");
+      break;
+   case OP_LESS:
+      printf("OP_LESS\n");
+      break;
+   case OP_GREATER:
+      printf("OP_GREATER\n");
+      break;
+   case OP_LESSEQUAL:
+      printf("OP_LESSEQUAL\n");
+      break;
+   case OP_GREATEREQUAL:
+      printf("OP_GREATEREQUAL\n");
+      break;
+   /*case OP_LSHIFT:*/
+   /*case OP_RSHIFT:*/
+   case OP_ADD:
+      printf("OP_ADD\n");
+      break;
+   case OP_SUBTRACT:
+      printf("OP_SUBTRACT\n");
+      break;
+   case OP_MULTIPLY:
+      printf("OP_MULTIPLY\n");
+      break;
+   case OP_DIVIDE:
+      printf("OP_DIVIDE\n");
+      break;
+   /*case OP_MODULUS:*/
+   case OP_PREINCREMENT:
+      printf("OP_PREINCREMENT\n");
+      break;
+   case OP_PREDECREMENT:
+      printf("OP_PREDECREMENT\n");
+      break;
+   case OP_PLUS:
+      printf("OP_PLUS\n");
+      break;
+   case OP_MINUS:
+      printf("OP_MINUS\n");
+      break;
+   case OP_NOT:
+      printf("OP_NOT\n");
+      break;
+   /*case OP_COMPLEMENT:*/
+   case OP_SUBSCRIPT:
+      printf("OP_SUBSCRIPT\n");
+      break;
+   case OP_CALL:
+      printf("OP_CALL\n");
+      break;
+   case OP_FIELD:
+      printf("OP_FIELD\n");
+      break;
+   case OP_POSTINCREMENT:
+      printf("OP_POSTINCREMENT\n");
+      break;
+   case OP_POSTDECREMENT:
+      printf("OP_POSTDECREMENT\n");
+      break;
+   default:
+      printf("UNKNOWN OP %d\n", opcode);
+   }
+}
+
+
+
+const char *
+slang_asm_string(slang_assembly_type t)
+{
+   switch (t) {
+      /* core */
+   case slang_asm_none:
+      return "none";
+   case slang_asm_float_copy:
+      return "float_copy";
+   case slang_asm_float_move:
+      return "float_move";
+   case slang_asm_float_push:
+      return "float_push";
+   case slang_asm_float_deref:
+      return "float_deref";
+   case slang_asm_float_add:
+      return "float_add";
+   case slang_asm_float_multiply:
+      return "float_multiply";
+   case slang_asm_float_divide:
+      return "float_divide";
+   case slang_asm_float_negate:
+      return "float_negate";
+   case slang_asm_float_less:
+      return "float_less";
+   case slang_asm_float_equal_exp:
+      return "float_equal";
+   case slang_asm_float_equal_int:
+      return "float_equal";
+   case slang_asm_float_to_int:
+      return "float_to_int";
+   case slang_asm_float_sine:
+      return "float_sine";
+   case slang_asm_float_arcsine:
+      return "float_arcsine";
+   case slang_asm_float_arctan:
+      return "float_arctan";
+   case slang_asm_float_power:
+      return "float_power";
+   case slang_asm_float_log2:
+      return "float_log2";
+   case slang_asm_vec4_floor:
+      return "vec4_floor";
+   case slang_asm_float_ceil:
+      return "float_ceil";
+   case slang_asm_float_noise1:
+      return "float_noise1";
+   case slang_asm_float_noise2:
+      return "float_noise2";
+   case slang_asm_float_noise3:
+      return "float_noise3";
+   case slang_asm_float_noise4:
+      return "float_noise4";
+   case slang_asm_int_copy:
+      return "int_copy";
+   case slang_asm_int_move:
+      return "int_move";
+   case slang_asm_int_push:
+      return "int_push";
+   case slang_asm_int_deref:
+      return "int_deref";
+   case slang_asm_int_to_float:
+      return "int_to_float";
+   case slang_asm_int_to_addr:
+      return "int_to_addr";
+   case slang_asm_bool_copy:
+      return "bool_copy";
+   case slang_asm_bool_move:
+      return "bool_move";
+   case slang_asm_bool_push:
+      return "bool_push";
+   case slang_asm_bool_deref:
+      return "bool_deref";
+   case slang_asm_addr_copy:
+      return "addr_copy";
+   case slang_asm_addr_push:
+      return "addr_push";
+   case slang_asm_addr_deref:
+      return "addr_deref";
+   case slang_asm_addr_add:
+      return "addr_add";
+   case slang_asm_addr_multiply:
+      return "addr_multiply";
+   case slang_asm_vec4_tex1d:
+      return "vec4_tex1d";
+   case slang_asm_vec4_tex2d:
+      return "vec4_tex2d";
+   case slang_asm_vec4_tex3d:
+      return "vec4_tex3d";
+   case slang_asm_vec4_texcube:
+      return "vec4_texcube";
+   case slang_asm_vec4_shad1d:
+      return "vec4_shad1d";
+   case slang_asm_vec4_shad2d:
+      return "vec4_shad2d";
+   case slang_asm_jump:
+      return "jump";
+   case slang_asm_jump_if_zero:
+      return "jump_if_zero";
+   case slang_asm_enter:
+      return "enter";
+   case slang_asm_leave:
+      return "leave";
+   case slang_asm_local_alloc:
+      return "local_alloc";
+   case slang_asm_local_free:
+      return "local_free";
+   case slang_asm_local_addr:
+      return "local_addr";
+   case slang_asm_global_addr:
+      return "global_addr";
+   case slang_asm_call:
+      return "call";
+   case slang_asm_return:
+      return "return";
+   case slang_asm_discard:
+      return "discard";
+   case slang_asm_exit:
+      return "exit";
+      /* GL_MESA_shader_debug */
+   case slang_asm_float_print:
+      return "float_print";
+   case slang_asm_int_print:
+      return "int_print";
+   case slang_asm_bool_print:
+      return "bool_print";
+      /* vec4 */
+   case slang_asm_float_to_vec4:
+      return "float_to_vec4";
+   case slang_asm_vec4_add:
+      return "vec4_add";
+   case slang_asm_vec4_subtract:
+      return "vec4_subtract";
+   case slang_asm_vec4_multiply:
+      return "vec4_multiply";
+   case slang_asm_vec4_divide:
+      return "vec4_divide";
+   case slang_asm_vec4_negate:
+      return "vec4_negate";
+   case slang_asm_vec4_dot:
+      return "vec4_dot";
+   case slang_asm_vec4_copy:
+      return "vec4_copy";
+   case slang_asm_vec4_deref:
+      return "vec4_deref";
+   case slang_asm_vec4_equal_int:
+      return "vec4_equal";
+   default:
+      return "??asm??";
+   }
+}
+
+
+const char *
+slang_type_qual_string(slang_type_qualifier q)
+{
+   switch (q) {
+   case slang_qual_none:
+      return "none";
+   case slang_qual_const:
+      return "const";
+   case slang_qual_attribute:
+      return "attribute";
+   case slang_qual_varying:
+      return "varying";
+   case slang_qual_uniform:
+      return "uniform";
+   case slang_qual_out:
+      return "out";
+   case slang_qual_inout:
+      return "inout";
+   case slang_qual_fixedoutput:
+      return "fixedoutput";
+   case slang_qual_fixedinput:
+      return "fixedinputk";
+   default:
+      return "qual?";
+   }
+}
+
+
+static const char *
+slang_type_string(slang_type_specifier_type t)
+{
+   switch (t) {
+   case slang_spec_void:
+      return "void";
+   case slang_spec_bool:
+      return "bool";
+   case slang_spec_bvec2:
+      return "bvec2";
+   case slang_spec_bvec3:
+      return "bvec3";
+   case slang_spec_bvec4:
+      return "bvec4";
+   case slang_spec_int:
+      return "int";
+   case slang_spec_ivec2:
+      return "ivec2";
+   case slang_spec_ivec3:
+      return "ivec3";
+   case slang_spec_ivec4:
+      return "ivec4";
+   case slang_spec_float:
+      return "float";
+   case slang_spec_vec2:
+      return "vec2";
+   case slang_spec_vec3:
+      return "vec3";
+   case slang_spec_vec4:
+      return "vec4";
+   case slang_spec_mat2:
+      return "mat2";
+   case slang_spec_mat3:
+      return "mat3";
+   case slang_spec_mat4:
+      return "mat4";
+   case slang_spec_sampler1D:
+      return "sampler1D";
+   case slang_spec_sampler2D:
+      return "sampler2D";
+   case slang_spec_sampler3D:
+      return "sampler3D";
+   case slang_spec_samplerCube:
+      return "samplerCube";
+   case slang_spec_sampler1DShadow:
+      return "sampler1DShadow";
+   case slang_spec_sampler2DShadow:
+      return "sampler2DShadow";
+   case slang_spec_struct:
+      return "struct";
+   case slang_spec_array:
+      return "array";
+   default:
+      return "type?";
+   }
+}
+
+
+static const char *
+slang_fq_type_string(const slang_fully_specified_type *t)
+{
+   static char str[1000];
+   sprintf(str, "%s %s", slang_type_qual_string(t->qualifier),
+      slang_type_string(t->specifier.type));
+   return str;
+}
+
+
+void
+slang_print_type(const slang_fully_specified_type *t)
+{
+   printf("%s %s", slang_type_qual_string(t->qualifier),
+      slang_type_string(t->specifier.type));
+}
+
+
+static char *
+slang_var_string(const slang_variable *v)
+{
+   static char str[1000];
+   sprintf(str, "%s : %s",
+           (char *) v->a_name,
+           slang_fq_type_string(&v->type));
+   return str;
+}
+
+
+void
+slang_print_variable(const slang_variable *v)
+{
+   printf("Name: %s\n", (char *) v->a_name);
+   printf("Type: %s\n", slang_fq_type_string(&v->type));
+}
+
+
+void
+_slang_print_var_scope(const slang_variable_scope *vars, int indent)
+{
+   GLuint i;
+
+   spaces(indent);
+   printf("Var scope %p  %d vars\n", (void *) vars, vars->num_variables);
+   for (i = 0; i < vars->num_variables; i++) {
+      spaces(indent + 3);
+      printf("%s\n", (char *) vars->variables[i].a_name);
+   }
+
+   if (vars->outer_scope) {
+      spaces(indent + 3);
+      printf("outer_scope = %p\n", (void*) vars->outer_scope);
+      _slang_print_var_scope(vars->outer_scope, indent + 3);
+   }
+}
+
+
+
+int
+slang_checksum_tree(const slang_operation *op)
+{
+   int s = op->num_children;
+   int i;
+
+   for (i = 0; i < op->num_children; i++) {
+      s += slang_checksum_tree(&op->children[i]);
+   }
+   return s;
+}
diff --git a/src/mesa/shader/slang/slang_print.h b/src/mesa/shader/slang/slang_print.h
new file mode 100644 (file)
index 0000000..a98607a
--- /dev/null
@@ -0,0 +1,38 @@
+
+
+#ifndef SLANG_PRINT
+#define SLANG_PRINT
+
+extern void
+slang_print_function(const slang_function *f, GLboolean body);
+
+extern void
+slang_print_tree(const slang_operation *op, int indent);
+
+
+extern void
+slang_print_opcode(unsigned int opcode);
+
+
+extern const char *
+slang_asm_string(slang_assembly_type t);
+
+
+extern const char *
+slang_type_qual_string(slang_type_qualifier q);
+
+extern void
+slang_print_type(const slang_fully_specified_type *t);
+
+extern void
+slang_print_variable(const slang_variable *v);
+
+extern void
+_slang_print_var_scope(const slang_variable_scope *s, int indent);
+
+
+extern int
+slang_checksum_tree(const slang_operation *op);
+
+#endif /* SLANG_PRINT */
+
diff --git a/src/mesa/shader/slang/slang_simplify.c b/src/mesa/shader/slang/slang_simplify.c
new file mode 100644 (file)
index 0000000..94e6e1e
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_assemble_typeinfo.c
+ * slang type info
+ * \author Michal Krol
+ */
+
+#include "imports.h"
+#include "macros.h"
+#include "slang_compile.h"
+#include "slang_simplify.h"
+
+
+/**
+ * Recursively traverse an AST tree, applying simplifications wherever
+ * possible.
+ * At the least, we do constant folding.  We need to do that much so that
+ * compile-time expressions can be evaluated for things like array
+ * declarations.  I.e.:  float foo[3 + 5];
+ */
+void
+slang_simplify(slang_operation *oper,
+               const slang_assembly_name_space * space,
+               slang_atom_pool * atoms)
+{
+   GLboolean isFloat[4];
+   GLboolean isBool[4];
+   GLuint i, n;
+
+   /* first, simplify children */
+   for (i = 0; i < oper->num_children; i++) {
+      slang_simplify(&oper->children[i], space, atoms);
+   }
+
+   /* examine children */
+   n = MIN2(oper->num_children, 4);
+   for (i = 0; i < n; i++) {
+      isFloat[i] = (oper->children[i].type == slang_oper_literal_float ||
+                   oper->children[i].type == slang_oper_literal_int);
+      isBool[i] = (oper->children[i].type == slang_oper_literal_bool);
+   }
+                              
+   if (n == 2 && isFloat[0] && isFloat[1]) {
+      /* probably simple arithmetic */
+      switch (oper->type) {
+      case slang_oper_add:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] + oper->children[1].literal[i];
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_float;
+         break;
+      case slang_oper_subtract:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] - oper->children[1].literal[i];
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_float;
+         break;
+      case slang_oper_multiply:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] * oper->children[1].literal[i];
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_float;
+         break;
+      case slang_oper_divide:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] / oper->children[1].literal[i];
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_float;
+         break;
+      default:
+         ; /* nothing */
+      }
+   }
+   else if (n == 1 && isFloat[0]) {
+      switch (oper->type) {
+      case slang_oper_minus:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i] = -oper->children[0].literal[i];
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_float;
+         break;
+      case slang_oper_plus:
+         COPY_4V(oper->literal, oper->children[0].literal);
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_float;
+         break;
+      default:
+         ; /* nothing */
+      }
+   }
+   else if (n == 2 && isBool[0] && isBool[1]) {
+      /* simple boolean expression */
+      switch (oper->type) {
+      case slang_oper_logicaland:
+         for (i = 0; i < 4; i++) {
+            const GLint a = oper->children[0].literal[i] ? 1 : 0;
+            const GLint b = oper->children[1].literal[i] ? 1 : 0;
+            oper->literal[i] = (GLfloat) (a && b);
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_bool;
+         break;
+      case slang_oper_logicalor:
+         for (i = 0; i < 4; i++) {
+            const GLint a = oper->children[0].literal[i] ? 1 : 0;
+            const GLint b = oper->children[1].literal[i] ? 1 : 0;
+            oper->literal[i] = (GLfloat) (a || b);
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_bool;
+         break;
+      case slang_oper_logicalxor:
+         for (i = 0; i < 4; i++) {
+            const GLint a = oper->children[0].literal[i] ? 1 : 0;
+            const GLint b = oper->children[1].literal[i] ? 1 : 0;
+            oper->literal[i] = (GLfloat) (a ^ b);
+         }
+         slang_operation_destruct(oper);
+         oper->type = slang_oper_literal_bool;
+         break;
+      default:
+         ; /* nothing */
+      }
+   }
+   else if (n == 4 && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
+      if (oper->type == slang_oper_call) {
+         if (strcmp((char *) oper->a_id, "vec4") == 0) {
+            oper->literal[0] = oper->children[0].literal[0];
+            oper->literal[1] = oper->children[1].literal[0];
+            oper->literal[2] = oper->children[2].literal[0];
+            oper->literal[3] = oper->children[3].literal[0];
+            slang_operation_destruct(oper);
+            oper->type = slang_oper_literal_float;
+         }
+      }
+   }
+}
+
diff --git a/src/mesa/shader/slang/slang_simplify.h b/src/mesa/shader/slang/slang_simplify.h
new file mode 100644 (file)
index 0000000..69be309
--- /dev/null
@@ -0,0 +1,12 @@
+
+#ifndef SLANG_SIMPLIFY_H
+#define SLANG_SIMPLIFY_H
+
+extern void
+slang_simplify(slang_operation *oper,
+               const slang_assembly_name_space * space,
+               slang_atom_pool * atoms);
+
+
+
+#endif /* SLANG_SIMPLIFY_H */
index 256d52455db4865b998198c286254bfd5fd9be16..314ecc8d75981a8d6182a692e2d658e69251e25d 100644 (file)
@@ -220,3 +220,16 @@ slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom)
        return (const char *) (atom);
 }
 
+
+/**
+ * Generate a new, unique atom with given prefix.
+ */
+slang_atom
+slang_atom_pool_gen(slang_atom_pool * pool, const char *prefix)
+{
+   char name[1000];
+   static int nextFree = 100;
+   sprintf(name, "%s%d", prefix, nextFree);
+   nextFree++;
+   return slang_atom_pool_atom(pool, name);
+}
index 565de4e4b028ceb5b83e38a92afd0e3958360bb3..c969ffcd2aff67f564123d4e97923e194836ecee 100644 (file)
@@ -102,6 +102,10 @@ GLvoid slang_atom_pool_destruct (slang_atom_pool *);
 slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *);
 const char *slang_atom_pool_id (slang_atom_pool *, slang_atom);
 
+slang_atom
+slang_atom_pool_gen(slang_atom_pool * pool, const char *prefix);
+
+
 #ifdef __cplusplus
 }
 #endif