Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / glsl / nir / glsl_to_nir.cpp
index 6b90da5481c0a8bc91b6272735dd2cc942c66b2b..27dabd3b8f2869fd77836e6298bd100eaf52446e 100644 (file)
@@ -43,7 +43,7 @@ namespace {
 class nir_visitor : public ir_visitor
 {
 public:
-   nir_visitor(nir_shader *shader, bool supports_ints);
+   nir_visitor(nir_shader *shader, struct gl_shader *sh, gl_shader_stage stage);
    ~nir_visitor();
 
    virtual void visit(ir_variable *);
@@ -65,6 +65,7 @@ public:
    virtual void visit(ir_dereference_variable *);
    virtual void visit(ir_dereference_record *);
    virtual void visit(ir_dereference_array *);
+   virtual void visit(ir_barrier *);
 
    void create_function(ir_function *ir);
 
@@ -82,11 +83,16 @@ private:
 
    bool supports_ints;
 
+   struct gl_shader *sh;
+
    nir_shader *shader;
+   gl_shader_stage stage;
    nir_function_impl *impl;
    exec_list *cf_node_list;
    nir_instr *result; /* result of the expression tree last visited */
 
+   nir_deref_var *evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir);
+
    /* the head of the dereference chain we're creating */
    nir_deref_var *deref_head;
    /* the tail of the dereference chain we're creating */
@@ -125,34 +131,25 @@ private:
 }; /* end of anonymous namespace */
 
 nir_shader *
-glsl_to_nir(exec_list *ir, _mesa_glsl_parse_state *state,
-            bool native_integers)
+glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
 {
-   nir_shader *shader = nir_shader_create(NULL);
-
-   if (state) {
-      shader->num_user_structures = state->num_user_structures;
-      shader->user_structures = ralloc_array(shader, glsl_type *,
-                                             shader->num_user_structures);
-      memcpy(shader->user_structures, state->user_structures,
-            shader->num_user_structures * sizeof(glsl_type *));
-   } else {
-      shader->num_user_structures = 0;
-      shader->user_structures = NULL;
-   }
+   nir_shader *shader = nir_shader_create(NULL, options);
 
-   nir_visitor v1(shader, native_integers);
+   nir_visitor v1(shader, sh, sh->Stage);
    nir_function_visitor v2(&v1);
-   v2.run(ir);
-   visit_exec_list(ir, &v1);
+   v2.run(sh->ir);
+   visit_exec_list(sh->ir, &v1);
 
    return shader;
 }
 
-nir_visitor::nir_visitor(nir_shader *shader, bool supports_ints)
+nir_visitor::nir_visitor(nir_shader *shader, struct gl_shader *sh,
+                         gl_shader_stage stage)
 {
-   this->supports_ints = supports_ints;
+   this->supports_ints = shader->options->native_integers;
    this->shader = shader;
+   this->sh = sh;
+   this->stage = stage;
    this->is_global = true;
    this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
                                              _mesa_key_pointer_equal);
@@ -166,6 +163,14 @@ nir_visitor::~nir_visitor()
    _mesa_hash_table_destroy(this->overload_table, NULL);
 }
 
+nir_deref_var *
+nir_visitor::evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir)
+{
+   ir->accept(this);
+   ralloc_steal(mem_ctx, this->deref_head);
+   return this->deref_head;
+}
+
 static nir_constant *
 constant_copy(ir_constant *ir, void *mem_ctx)
 {
@@ -216,8 +221,7 @@ constant_copy(ir_constant *ir, void *mem_ctx)
       break;
 
    default:
-      assert(0);
-      break;
+      unreachable("not reached");
    }
 
    return ret;
@@ -243,6 +247,7 @@ nir_visitor::visit(ir_variable *ir)
    var->data.centroid = ir->data.centroid;
    var->data.sample = ir->data.sample;
    var->data.invariant = ir->data.invariant;
+   var->data.location = ir->data.location;
 
    switch(ir->data.mode) {
    case ir_var_auto:
@@ -261,7 +266,14 @@ nir_visitor::visit(ir_variable *ir)
       break;
 
    case ir_var_shader_in:
-      var->data.mode = nir_var_shader_in;
+      if (stage == MESA_SHADER_FRAGMENT &&
+          ir->data.location == VARYING_SLOT_FACE) {
+         /* For whatever reason, GLSL IR makes gl_FrontFacing an input */
+         var->data.location = SYSTEM_VALUE_FRONT_FACE;
+         var->data.mode = nir_var_system_value;
+      } else {
+         var->data.mode = nir_var_shader_in;
+      }
       break;
 
    case ir_var_shader_out:
@@ -272,14 +284,16 @@ nir_visitor::visit(ir_variable *ir)
       var->data.mode = nir_var_uniform;
       break;
 
+   case ir_var_shader_storage:
+      var->data.mode = nir_var_shader_storage;
+      break;
 
    case ir_var_system_value:
       var->data.mode = nir_var_system_value;
       break;
 
    default:
-      assert(0);
-      break;
+      unreachable("not reached");
    }
 
    var->data.interpolation = ir->data.interpolation;
@@ -311,12 +325,11 @@ nir_visitor::visit(ir_variable *ir)
       var->data.depth_layout = nir_depth_layout_unchanged;
       break;
    default:
-      assert(0);
-      break;
+      unreachable("not reached");
    }
 
-   var->data.location = ir->data.location;
    var->data.index = ir->data.index;
+   var->data.descriptor_set = ir->data.set;
    var->data.binding = ir->data.binding;
    /* XXX Get rid of buffer_index */
    var->data.atomic.buffer_index = ir->data.binding;
@@ -330,15 +343,20 @@ nir_visitor::visit(ir_variable *ir)
    var->data.max_array_access = ir->data.max_array_access;
 
    var->num_state_slots = ir->get_num_state_slots();
-   var->state_slots = ralloc_array(var, nir_state_slot, var->num_state_slots);
-   ir_state_slot *state_slots = ir->get_state_slots();
-   for (unsigned i = 0; i < var->num_state_slots; i++) {
-      for (unsigned j = 0; j < 5; j++)
-         var->state_slots[i].tokens[j] = state_slots[i].tokens[j];
-      var->state_slots[i].swizzle = state_slots[i].swizzle;
+   if (var->num_state_slots > 0) {
+      var->state_slots = ralloc_array(var, nir_state_slot,
+                                      var->num_state_slots);
+
+      ir_state_slot *state_slots = ir->get_state_slots();
+      for (unsigned i = 0; i < var->num_state_slots; i++) {
+         for (unsigned j = 0; j < 5; j++)
+            var->state_slots[i].tokens[j] = state_slots[i].tokens[j];
+         var->state_slots[i].swizzle = state_slots[i].swizzle;
+      }
+   } else {
+      var->state_slots = NULL;
    }
 
-   var->constant_value = constant_copy(ir->constant_value, var);
    var->constant_initializer = constant_copy(ir->constant_initializer, var);
 
    var->interface_type = ir->get_interface_type();
@@ -353,15 +371,16 @@ nir_visitor::visit(ir_variable *ir)
       break;
 
    case nir_var_shader_in:
-      _mesa_hash_table_insert(shader->inputs, var->name, var);
+      exec_list_push_tail(&shader->inputs, &var->node);
       break;
 
    case nir_var_shader_out:
-      _mesa_hash_table_insert(shader->outputs, var->name, var);
+      exec_list_push_tail(&shader->outputs, &var->node);
       break;
 
    case nir_var_uniform:
-      _mesa_hash_table_insert(shader->uniforms, var->name, var);
+   case nir_var_shader_storage:
+      exec_list_push_tail(&shader->uniforms, &var->node);
       break;
 
    case nir_var_system_value:
@@ -369,8 +388,7 @@ nir_visitor::visit(ir_variable *ir)
       break;
 
    default:
-      assert(0);
-      break;
+      unreachable("not reached");
    }
 
    _mesa_hash_table_insert(var_table, ir, var);
@@ -424,8 +442,7 @@ nir_visitor::create_overload(ir_function_signature *ir, nir_function *function)
          break;
 
       default:
-         assert(0);
-         break;
+         unreachable("not reached");
       }
 
       overload->params[i].type = param->type;
@@ -533,8 +550,14 @@ nir_visitor::visit(ir_discard *ir)
     * discards will be immediately followed by a return.
     */
 
-   nir_intrinsic_instr *discard =
-      nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard);
+   nir_intrinsic_instr *discard;
+   if (ir->condition) {
+      discard = nir_intrinsic_instr_create(this->shader,
+                                           nir_intrinsic_discard_if);
+      discard->src[0] = evaluate_rvalue(ir->condition);
+   } else {
+      discard = nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard);
+   }
    nir_instr_insert_after_cf_list(this->cf_node_list, &discard->instr);
 }
 
@@ -568,8 +591,7 @@ nir_visitor::visit(ir_loop_jump *ir)
       type = nir_jump_continue;
       break;
    default:
-      assert(0);
-      break;
+      unreachable("not reached");
    }
 
    nir_jump_instr *instr = nir_jump_instr_create(this->shader, type);
@@ -580,13 +602,11 @@ void
 nir_visitor::visit(ir_return *ir)
 {
    if (ir->value != NULL) {
-      ir->value->accept(this);
       nir_intrinsic_instr *copy =
          nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
 
-      copy->variables[0] = nir_deref_var_create(this->shader,
-                                                this->impl->return_var);
-      copy->variables[1] = this->deref_head;
+      copy->variables[0] = nir_deref_var_create(copy, this->impl->return_var);
+      copy->variables[1] = evaluate_deref(&copy->instr, ir->value);
    }
 
    nir_jump_instr *instr = nir_jump_instr_create(this->shader, nir_jump_return);
@@ -604,30 +624,135 @@ nir_visitor::visit(ir_call *ir)
          op = nir_intrinsic_atomic_counter_inc_var;
       } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_predecrement") == 0) {
          op = nir_intrinsic_atomic_counter_dec_var;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_load") == 0) {
+         op = nir_intrinsic_image_load;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_store") == 0) {
+         op = nir_intrinsic_image_store;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_add") == 0) {
+         op = nir_intrinsic_image_atomic_add;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_min") == 0) {
+         op = nir_intrinsic_image_atomic_min;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_max") == 0) {
+         op = nir_intrinsic_image_atomic_max;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_and") == 0) {
+         op = nir_intrinsic_image_atomic_and;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_or") == 0) {
+         op = nir_intrinsic_image_atomic_or;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_xor") == 0) {
+         op = nir_intrinsic_image_atomic_xor;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_exchange") == 0) {
+         op = nir_intrinsic_image_atomic_exchange;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_comp_swap") == 0) {
+         op = nir_intrinsic_image_atomic_comp_swap;
+      } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier") == 0) {
+         op = nir_intrinsic_memory_barrier;
       } else {
-         assert(0);
+         unreachable("not reached");
       }
 
-      nir_register *reg = nir_local_reg_create(impl);
-      reg->num_components = 1;
-
       nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op);
-      ir_dereference *param =
-         (ir_dereference *) ir->actual_parameters.get_head();
-      param->accept(this);
-      instr->variables[0] = this->deref_head;
-      instr->dest.reg.reg = reg;
+
+      switch (op) {
+      case nir_intrinsic_atomic_counter_read_var:
+      case nir_intrinsic_atomic_counter_inc_var:
+      case nir_intrinsic_atomic_counter_dec_var: {
+         ir_dereference *param =
+            (ir_dereference *) ir->actual_parameters.get_head();
+         instr->variables[0] = evaluate_deref(&instr->instr, param);
+         nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
+         break;
+      }
+      case nir_intrinsic_image_load:
+      case nir_intrinsic_image_store:
+      case nir_intrinsic_image_atomic_add:
+      case nir_intrinsic_image_atomic_min:
+      case nir_intrinsic_image_atomic_max:
+      case nir_intrinsic_image_atomic_and:
+      case nir_intrinsic_image_atomic_or:
+      case nir_intrinsic_image_atomic_xor:
+      case nir_intrinsic_image_atomic_exchange:
+      case nir_intrinsic_image_atomic_comp_swap: {
+         nir_ssa_undef_instr *instr_undef =
+            nir_ssa_undef_instr_create(shader, 1);
+         nir_instr_insert_after_cf_list(this->cf_node_list,
+                                        &instr_undef->instr);
+
+         /* Set the image variable dereference. */
+         exec_node *param = ir->actual_parameters.get_head();
+         ir_dereference *image = (ir_dereference *)param;
+         const glsl_type *type =
+            image->variable_referenced()->type->without_array();
+
+         instr->variables[0] = evaluate_deref(&instr->instr, image);
+         param = param->get_next();
+
+         /* Set the address argument, extending the coordinate vector to four
+          * components.
+          */
+         const nir_src src_addr = evaluate_rvalue((ir_dereference *)param);
+         nir_alu_instr *instr_addr = nir_alu_instr_create(shader, nir_op_vec4);
+         nir_ssa_dest_init(&instr_addr->instr, &instr_addr->dest.dest, 4, NULL);
+
+         for (int i = 0; i < 4; i++) {
+            if (i < type->coordinate_components()) {
+               instr_addr->src[i].src = src_addr;
+               instr_addr->src[i].swizzle[0] = i;
+            } else {
+               instr_addr->src[i].src = nir_src_for_ssa(&instr_undef->def);
+            }
+         }
+
+         nir_instr_insert_after_cf_list(cf_node_list, &instr_addr->instr);
+         instr->src[0] = nir_src_for_ssa(&instr_addr->dest.dest.ssa);
+         param = param->get_next();
+
+         /* Set the sample argument, which is undefined for single-sample
+          * images.
+          */
+         if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) {
+            instr->src[1] = evaluate_rvalue((ir_dereference *)param);
+            param = param->get_next();
+         } else {
+            instr->src[1] = nir_src_for_ssa(&instr_undef->def);
+         }
+
+         /* Set the intrinsic parameters. */
+         if (!param->is_tail_sentinel()) {
+            instr->src[2] = evaluate_rvalue((ir_dereference *)param);
+            param = param->get_next();
+         }
+
+         if (!param->is_tail_sentinel()) {
+            instr->src[3] = evaluate_rvalue((ir_dereference *)param);
+            param = param->get_next();
+         }
+
+         /* Set the intrinsic destination. */
+         if (ir->return_deref)
+            nir_ssa_dest_init(&instr->instr, &instr->dest,
+                              ir->return_deref->type->vector_elements, NULL);
+         break;
+      }
+      case nir_intrinsic_memory_barrier:
+         break;
+      default:
+         unreachable("not reached");
+      }
 
       nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
 
-      nir_intrinsic_instr *store_instr =
-         nir_intrinsic_instr_create(shader, nir_intrinsic_store_var_vec1);
+      if (ir->return_deref) {
+         nir_intrinsic_instr *store_instr =
+            nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
+         store_instr->num_components = ir->return_deref->type->vector_elements;
 
-      ir->return_deref->accept(this);
-      store_instr->variables[0] = this->deref_head;
-      store_instr->src[0].reg.reg = reg;
+         store_instr->variables[0] =
+            evaluate_deref(&store_instr->instr, ir->return_deref);
+         store_instr->src[0] = nir_src_for_ssa(&instr->dest.ssa);
 
-      nir_instr_insert_after_cf_list(this->cf_node_list, &store_instr->instr);
+         nir_instr_insert_after_cf_list(this->cf_node_list,
+                                        &store_instr->instr);
+      }
 
       return;
    }
@@ -641,134 +766,112 @@ nir_visitor::visit(ir_call *ir)
 
    unsigned i = 0;
    foreach_in_list(ir_dereference, param, &ir->actual_parameters) {
-      param->accept(this);
-      instr->params[i] = this->deref_head;
+      instr->params[i] = evaluate_deref(&instr->instr, param);
       i++;
    }
 
-   ir->return_deref->accept(this);
-   instr->return_deref = this->deref_head;
+   instr->return_deref = evaluate_deref(&instr->instr, ir->return_deref);
    nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
 }
 
 void
 nir_visitor::visit(ir_assignment *ir)
 {
-   if (ir->write_mask != (1 << ir->lhs->type->vector_elements) - 1 &&
-       ir->write_mask != 0) {
-      /*
-       * We have no good way to update only part of a variable, so just load
-       * the LHS into a register, do a writemasked move, and then store it
-       * back into the LHS. Copy propagation should get rid of the mess.
-       */
+   unsigned num_components = ir->lhs->type->vector_elements;
 
-      ir->lhs->accept(this);
-      nir_deref_var *lhs_deref = this->deref_head;
-      nir_register *reg = nir_local_reg_create(this->impl);
-      reg->num_components = ir->lhs->type->vector_elements;
+   if ((ir->rhs->as_dereference() || ir->rhs->as_constant()) &&
+       (ir->write_mask == (1 << num_components) - 1 || ir->write_mask == 0)) {
+      /* We're doing a plain-as-can-be copy, so emit a copy_var */
+      nir_intrinsic_instr *copy =
+         nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
 
-      nir_intrinsic_op op;
-      switch (ir->lhs->type->vector_elements) {
-         case 1: op = nir_intrinsic_load_var_vec1; break;
-         case 2: op = nir_intrinsic_load_var_vec2; break;
-         case 3: op = nir_intrinsic_load_var_vec3; break;
-         case 4: op = nir_intrinsic_load_var_vec4; break;
-         default: assert(0); break;
+      copy->variables[0] = evaluate_deref(&copy->instr, ir->lhs);
+      copy->variables[1] = evaluate_deref(&copy->instr, ir->rhs);
+
+      if (ir->condition) {
+         nir_if *if_stmt = nir_if_create(this->shader);
+         if_stmt->condition = evaluate_rvalue(ir->condition);
+         nir_cf_node_insert_end(this->cf_node_list, &if_stmt->cf_node);
+         nir_instr_insert_after_cf_list(&if_stmt->then_list, &copy->instr);
+      } else {
+         nir_instr_insert_after_cf_list(this->cf_node_list, &copy->instr);
       }
+      return;
+   }
 
-      nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op);
-      load->dest.reg.reg = reg;
-      load->variables[0] = lhs_deref;
-      nir_instr_insert_after_cf_list(this->cf_node_list, &load->instr);
+   assert(ir->rhs->type->is_scalar() || ir->rhs->type->is_vector());
 
-      nir_alu_instr *move =
-         nir_alu_instr_create(this->shader,
-                              supports_ints ? nir_op_fmov : nir_op_imov);
-      move->dest.dest.reg.reg = reg;
-      move->dest.write_mask = ir->write_mask;
-      move->src[0].src = evaluate_rvalue(ir->rhs);
+   ir->lhs->accept(this);
+   nir_deref_var *lhs_deref = this->deref_head;
+   nir_src src = evaluate_rvalue(ir->rhs);
 
+   if (ir->write_mask != (1 << num_components) - 1 && ir->write_mask != 0) {
       /*
-       * GLSL IR will give us the input to the write-masked assignment in a
-       * single packed vector, whereas we expect each input component to be in
-       * the same channel as the writemask. So, for example, if the writemask
-       * is xzw, then we have to swizzle x -> x, y -> z, and z -> w.
+       * We have no good way to update only part of a variable, so just load
+       * the LHS and do a vec operation to combine the old with the new, and
+       * then store it
+       * back into the LHS. Copy propagation should get rid of the mess.
        */
 
-      unsigned component = 0;
-      for (unsigned i = 0; i < 4; i++) {
-         if ((ir->write_mask >> i) & 1) {
-            move->src[0].swizzle[i] = component++;
-         } else {
-            move->src[0].swizzle[i] = 0;
-         }
-      }
-
-      if (ir->condition != NULL) {
-         move->has_predicate = true;
-         move->predicate = evaluate_rvalue(ir->condition);
-      }
-
-      nir_instr_insert_after_cf_list(this->cf_node_list, &move->instr);
+      nir_intrinsic_instr *load =
+         nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var);
+      load->num_components = ir->lhs->type->vector_elements;
+      nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL);
+      load->variables[0] = lhs_deref;
+      ralloc_steal(load, load->variables[0]);
+      nir_instr_insert_after_cf_list(this->cf_node_list, &load->instr);
 
+      nir_op vec_op;
       switch (ir->lhs->type->vector_elements) {
-         case 1: op = nir_intrinsic_store_var_vec1; break;
-         case 2: op = nir_intrinsic_store_var_vec2; break;
-         case 3: op = nir_intrinsic_store_var_vec3; break;
-         case 4: op = nir_intrinsic_store_var_vec4; break;
-         default: assert(0); break;
+         case 1: vec_op = nir_op_imov; break;
+         case 2: vec_op = nir_op_vec2; break;
+         case 3: vec_op = nir_op_vec3; break;
+         case 4: vec_op = nir_op_vec4; break;
+         default: unreachable("Invalid number of components"); break;
       }
+      nir_alu_instr *vec = nir_alu_instr_create(this->shader, vec_op);
+      nir_ssa_dest_init(&vec->instr, &vec->dest.dest, num_components, NULL);
+      vec->dest.write_mask = (1 << num_components) - 1;
 
-      nir_intrinsic_instr *store = nir_intrinsic_instr_create(this->shader, op);
-      nir_deref *store_deref = nir_copy_deref(this->shader, &lhs_deref->deref);
-      store->variables[0] = nir_deref_as_var(store_deref);
-      store->src[0].reg.reg = reg;
-      nir_instr_insert_after_cf_list(this->cf_node_list, &store->instr);
-      return;
-   }
-
-   if (ir->rhs->as_dereference() || ir->rhs->as_constant()) {
-      /* we're copying structs or arrays, so emit a copy_var */
-      nir_intrinsic_instr *copy =
-         nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
-
-      ir->lhs->accept(this);
-      copy->variables[0] = this->deref_head;
-
-      ir->rhs->accept(this);
-      copy->variables[1] = this->deref_head;
-
-      if (ir->condition != NULL) {
-         copy->has_predicate = true;
-         copy->predicate = evaluate_rvalue(ir->condition);
+      unsigned component = 0;
+      for (unsigned i = 0; i < ir->lhs->type->vector_elements; i++) {
+         if (ir->write_mask & (1 << i)) {
+            vec->src[i].src = src;
+
+            /* GLSL IR will give us the input to the write-masked assignment
+             * in a single packed vector.  So, for example, if the
+             * writemask is xzw, then we have to swizzle x -> x, y -> z,
+             * and z -> w and get the y component from the load.
+             */
+            vec->src[i].swizzle[0] = component++;
+         } else {
+            vec->src[i].src.is_ssa = true;
+            vec->src[i].src.ssa = &load->dest.ssa;
+            vec->src[i].swizzle[0] = i;
+         }
       }
-      nir_instr_insert_after_cf_list(this->cf_node_list, &copy->instr);
-      return;
-   }
 
-   assert(ir->rhs->type->is_scalar() || ir->rhs->type->is_vector());
+      nir_instr_insert_after_cf_list(this->cf_node_list, &vec->instr);
 
-   nir_intrinsic_op op;
-   switch (ir->lhs->type->vector_elements) {
-      case 1: op = nir_intrinsic_store_var_vec1; break;
-      case 2: op = nir_intrinsic_store_var_vec2; break;
-      case 3: op = nir_intrinsic_store_var_vec3; break;
-      case 4: op = nir_intrinsic_store_var_vec4; break;
-      default: assert(0); break;
+      src.is_ssa = true;
+      src.ssa = &vec->dest.dest.ssa;
    }
 
-   nir_intrinsic_instr *store = nir_intrinsic_instr_create(this->shader, op);
-
-   ir->lhs->accept(this);
-   store->variables[0] = this->deref_head;
-   store->src[0] = evaluate_rvalue(ir->rhs);
-
-   if (ir->condition != NULL) {
-      store->has_predicate = true;
-      store->predicate = evaluate_rvalue(ir->condition);
+   nir_intrinsic_instr *store =
+      nir_intrinsic_instr_create(this->shader, nir_intrinsic_store_var);
+   store->num_components = ir->lhs->type->vector_elements;
+   nir_deref *store_deref = nir_copy_deref(store, &lhs_deref->deref);
+   store->variables[0] = nir_deref_as_var(store_deref);
+   store->src[0] = src;
+
+   if (ir->condition) {
+      nir_if *if_stmt = nir_if_create(this->shader);
+      if_stmt->condition = evaluate_rvalue(ir->condition);
+      nir_cf_node_insert_end(this->cf_node_list, &if_stmt->cf_node);
+      nir_instr_insert_after_cf_list(&if_stmt->then_list, &store->instr);
+   } else {
+      nir_instr_insert_after_cf_list(this->cf_node_list, &store->instr);
    }
-
-   nir_instr_insert_after_cf_list(this->cf_node_list, &store->instr);
 }
 
 /*
@@ -783,7 +886,6 @@ get_instr_dest(nir_instr *instr)
    nir_alu_instr *alu_instr;
    nir_intrinsic_instr *intrinsic_instr;
    nir_tex_instr *tex_instr;
-   nir_load_const_instr *load_const_instr;
 
    switch (instr->type) {
       case nir_instr_type_alu:
@@ -797,17 +899,12 @@ get_instr_dest(nir_instr *instr)
          else
             return NULL;
 
-      case nir_instr_type_texture:
-         tex_instr = nir_instr_as_texture(instr);
+      case nir_instr_type_tex:
+         tex_instr = nir_instr_as_tex(instr);
          return &tex_instr->dest;
 
-      case nir_instr_type_load_const:
-         load_const_instr = nir_instr_as_load_const(instr);
-         return &load_const_instr->dest;
-
       default:
-         assert(0);
-         break;
+         unreachable("not reached");
    }
 
    return NULL;
@@ -818,8 +915,7 @@ nir_visitor::add_instr(nir_instr *instr, unsigned num_components)
 {
    nir_dest *dest = get_instr_dest(instr);
 
-   dest->reg.reg = nir_local_reg_create(this->impl);
-   dest->reg.reg->num_components = num_components;
+   nir_ssa_dest_init(instr, dest, num_components, NULL);
 
    nir_instr_insert_after_cf_list(this->cf_node_list, instr);
    this->result = instr;
@@ -835,45 +931,18 @@ nir_visitor::evaluate_rvalue(ir_rvalue* ir)
        * must emit a variable load.
        */
 
-      nir_intrinsic_op op;
-      switch (ir->type->vector_elements) {
-         case 1:
-            op = nir_intrinsic_load_var_vec1;
-            break;
-         case 2:
-            op = nir_intrinsic_load_var_vec2;
-            break;
-         case 3:
-            op = nir_intrinsic_load_var_vec3;
-            break;
-         case 4:
-            op = nir_intrinsic_load_var_vec4;
-            break;
-      }
-
       nir_intrinsic_instr *load_instr =
-         nir_intrinsic_instr_create(this->shader, op);
+         nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var);
+      load_instr->num_components = ir->type->vector_elements;
       load_instr->variables[0] = this->deref_head;
+      ralloc_steal(load_instr, load_instr->variables[0]);
       add_instr(&load_instr->instr, ir->type->vector_elements);
    }
 
-   /*
-    * instr doesn't have a destination right now, give it one and then set up
-    * the source so that it points to it.
-    *
-    * TODO: once we support SSA plumb through a use_ssa boolean and use SSA
-    * here instead of creating a register.
-    */
    nir_dest *dest = get_instr_dest(this->result);
-   assert(dest->reg.reg);
-   nir_src src;
-
-   src.is_ssa = false;
-   src.reg.base_offset = 0;
-   src.reg.indirect = NULL;
-   src.reg.reg = dest->reg.reg;
+   assert(dest->is_ssa);
 
-   return src;
+   return nir_src_for_ssa(&dest->ssa);
 }
 
 nir_alu_instr *
@@ -915,33 +984,34 @@ nir_visitor::emit(nir_op op, unsigned dest_size, nir_src src1,
 void
 nir_visitor::visit(ir_expression *ir)
 {
-   if (ir->operation == ir_binop_ubo_load) {
+   /* Some special cases */
+   switch (ir->operation) {
+   case ir_binop_ubo_load: {
       ir_constant *const_index = ir->operands[1]->as_constant();
 
       nir_intrinsic_op op;
       if (const_index) {
-         switch (ir->type->vector_elements) {
-            case 1: op = nir_intrinsic_load_ubo_vec1; break;
-            case 2: op = nir_intrinsic_load_ubo_vec2; break;
-            case 3: op = nir_intrinsic_load_ubo_vec3; break;
-            case 4: op = nir_intrinsic_load_ubo_vec4; break;
-            default: assert(0); break;
-         }
+         op = nir_intrinsic_load_ubo;
       } else {
-         switch (ir->type->vector_elements) {
-            case 1: op = nir_intrinsic_load_ubo_vec1_indirect; break;
-            case 2: op = nir_intrinsic_load_ubo_vec2_indirect; break;
-            case 3: op = nir_intrinsic_load_ubo_vec3_indirect; break;
-            case 4: op = nir_intrinsic_load_ubo_vec4_indirect; break;
-            default: assert(0); break;
-         }
+         op = nir_intrinsic_load_ubo_indirect;
       }
+
+      ir_constant *const_block = ir->operands[0]->as_constant();
+      assert(const_block && "can't figure out descriptor set index");
+      unsigned index = const_block->value.u[0];
+      unsigned set = sh->UniformBlocks[index].Set;
+      unsigned binding = sh->UniformBlocks[index].Binding;
+
       nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op);
-      load->const_index[0] = ir->operands[0]->as_constant()->value.u[0];
+      load->num_components = ir->type->vector_elements;
+      load->const_index[0] = set;
       load->const_index[1] = const_index ? const_index->value.u[0] : 0; /* base offset */
-      load->const_index[2] = 1; /* number of vec4's */
+      nir_load_const_instr *load_binding = nir_load_const_instr_create(shader, 1);
+      load_binding->value.u[0] = binding;
+      nir_instr_insert_after_cf_list(this->cf_node_list, &load_binding->instr);
+      load->src[0] = nir_src_for_ssa(&load_binding->def);
       if (!const_index)
-         load->src[0] = evaluate_rvalue(ir->operands[1]);
+         load->src[1] = evaluate_rvalue(ir->operands[1]);
       add_instr(&load->instr, ir->type->vector_elements);
 
       /*
@@ -950,16 +1020,15 @@ nir_visitor::visit(ir_expression *ir)
        */
 
       if (ir->type->base_type == GLSL_TYPE_BOOL) {
-         nir_load_const_instr *const_zero = nir_load_const_instr_create(shader);
-         const_zero->num_components = 1;
+         nir_load_const_instr *const_zero = nir_load_const_instr_create(shader, 1);
          const_zero->value.u[0] = 0;
-         const_zero->dest.reg.reg = nir_local_reg_create(this->impl);
-         const_zero->dest.reg.reg->num_components = 1;
          nir_instr_insert_after_cf_list(this->cf_node_list, &const_zero->instr);
 
          nir_alu_instr *compare = nir_alu_instr_create(shader, nir_op_ine);
-         compare->src[0].src.reg.reg = load->dest.reg.reg;
-         compare->src[1].src.reg.reg = const_zero->dest.reg.reg;
+         compare->src[0].src.is_ssa = true;
+         compare->src[0].src.ssa = &load->dest.ssa;
+         compare->src[1].src.is_ssa = true;
+         compare->src[1].src.ssa = &const_zero->def;
          for (unsigned i = 0; i < ir->type->vector_elements; i++)
             compare->src[1].swizzle[i] = 0;
          compare->dest.write_mask = (1 << ir->type->vector_elements) - 1;
@@ -970,6 +1039,83 @@ nir_visitor::visit(ir_expression *ir)
       return;
    }
 
+   case ir_unop_interpolate_at_centroid:
+   case ir_binop_interpolate_at_offset:
+   case ir_binop_interpolate_at_sample: {
+      ir_dereference *deref = ir->operands[0]->as_dereference();
+      ir_swizzle *swizzle = NULL;
+      if (!deref) {
+         /* the api does not allow a swizzle here, but the varying packing code
+          * may have pushed one into here.
+          */
+         swizzle = ir->operands[0]->as_swizzle();
+         assert(swizzle);
+         deref = swizzle->val->as_dereference();
+         assert(deref);
+      }
+
+      deref->accept(this);
+
+      nir_intrinsic_op op;
+      if (this->deref_head->var->data.mode == nir_var_shader_in) {
+         switch (ir->operation) {
+         case ir_unop_interpolate_at_centroid:
+            op = nir_intrinsic_interp_var_at_centroid;
+            break;
+         case ir_binop_interpolate_at_offset:
+            op = nir_intrinsic_interp_var_at_offset;
+            break;
+         case ir_binop_interpolate_at_sample:
+            op = nir_intrinsic_interp_var_at_sample;
+            break;
+         default:
+            unreachable("Invalid interpolation intrinsic");
+         }
+      } else {
+         /* This case can happen if the vertex shader does not write the
+          * given varying.  In this case, the linker will lower it to a
+          * global variable.  Since interpolating a variable makes no
+          * sense, we'll just turn it into a load which will probably
+          * eventually end up as an SSA definition.
+          */
+         assert(this->deref_head->var->data.mode == nir_var_global);
+         op = nir_intrinsic_load_var;
+      }
+
+      nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(shader, op);
+      intrin->num_components = deref->type->vector_elements;
+      intrin->variables[0] = this->deref_head;
+      ralloc_steal(intrin, intrin->variables[0]);
+
+      if (intrin->intrinsic == nir_intrinsic_interp_var_at_offset ||
+          intrin->intrinsic == nir_intrinsic_interp_var_at_sample)
+         intrin->src[0] = evaluate_rvalue(ir->operands[1]);
+
+      add_instr(&intrin->instr, deref->type->vector_elements);
+
+      if (swizzle) {
+         nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_imov);
+         mov->dest.write_mask = (1 << swizzle->type->vector_elements) - 1;
+         mov->src[0].src.is_ssa = true;
+         mov->src[0].src.ssa = &intrin->dest.ssa;
+
+         mov->src[0].swizzle[0] = swizzle->mask.x;
+         mov->src[0].swizzle[1] = swizzle->mask.y;
+         mov->src[0].swizzle[2] = swizzle->mask.z;
+         mov->src[0].swizzle[3] = swizzle->mask.w;
+         for (unsigned i = deref->type->vector_elements; i < 4; i++)
+            mov->src[0].swizzle[i] = 0;
+
+         add_instr(&mov->instr, swizzle->type->vector_elements);
+      }
+
+      return;
+   }
+
+   default:
+      break;
+   }
+
    nir_src srcs[4];
    for (unsigned i = 0; i < ir->get_num_operands(); i++)
       srcs[i] = evaluate_rvalue(ir->operands[i]);
@@ -998,19 +1144,16 @@ nir_visitor::visit(ir_expression *ir)
       emit(supports_ints ? nir_op_inot : nir_op_fnot, dest_size, srcs);
       break;
    case ir_unop_neg:
-      instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fmov : nir_op_imov,
+      instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fneg : nir_op_ineg,
                    dest_size, srcs);
-      instr->src[0].negate = true;
       break;
    case ir_unop_abs:
-      instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fmov : nir_op_imov,
+      instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fabs : nir_op_iabs,
                    dest_size, srcs);
-      instr->src[0].abs = true;
       break;
    case ir_unop_saturate:
       assert(types[0] == GLSL_TYPE_FLOAT);
-      instr = emit(nir_op_fmov, dest_size, srcs);
-      instr->dest.saturate = true;
+      instr = emit(nir_op_fsat, dest_size, srcs);
       break;
    case ir_unop_sign:
       emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fsign : nir_op_isign,
@@ -1019,8 +1162,8 @@ nir_visitor::visit(ir_expression *ir)
    case ir_unop_rcp:  emit(nir_op_frcp, dest_size, srcs);  break;
    case ir_unop_rsq:  emit(nir_op_frsq, dest_size, srcs);  break;
    case ir_unop_sqrt: emit(nir_op_fsqrt, dest_size, srcs); break;
-   case ir_unop_exp:  emit(nir_op_fexp, dest_size, srcs);  break;
-   case ir_unop_log:  emit(nir_op_flog, dest_size, srcs);  break;
+   case ir_unop_exp:  unreachable("ir_unop_exp should have been lowered");
+   case ir_unop_log:  unreachable("ir_unop_log should have been lowered");
    case ir_unop_exp2: emit(nir_op_fexp2, dest_size, srcs); break;
    case ir_unop_log2: emit(nir_op_flog2, dest_size, srcs); break;
    case ir_unop_i2f:
@@ -1043,6 +1186,7 @@ nir_visitor::visit(ir_expression *ir)
    case ir_unop_bitcast_f2i:
    case ir_unop_bitcast_u2f:
    case ir_unop_bitcast_f2u:
+   case ir_unop_subroutine_to_int:
       /* no-op */
       emit(nir_op_imov, dest_size, srcs);
       break;
@@ -1061,8 +1205,7 @@ nir_visitor::visit(ir_expression *ir)
               dest_size, srcs);
          break;
       default:
-         assert(0);
-         break;
+         unreachable("not reached");
       }
       break;
    case ir_unop_trunc: emit(nir_op_ftrunc, dest_size, srcs); break;
@@ -1072,12 +1215,6 @@ nir_visitor::visit(ir_expression *ir)
    case ir_unop_round_even: emit(nir_op_fround_even, dest_size, srcs); break;
    case ir_unop_sin:   emit(nir_op_fsin,   dest_size, srcs); break;
    case ir_unop_cos:   emit(nir_op_fcos,   dest_size, srcs); break;
-   case ir_unop_sin_reduced:
-      emit(nir_op_fsin_reduced, dest_size, srcs);
-      break;
-   case ir_unop_cos_reduced:
-      emit(nir_op_fcos_reduced, dest_size, srcs);
-      break;
    case ir_unop_dFdx:        emit(nir_op_fddx,        dest_size, srcs); break;
    case ir_unop_dFdy:        emit(nir_op_fddy,        dest_size, srcs); break;
    case ir_unop_dFdx_fine:   emit(nir_op_fddx_fine,   dest_size, srcs); break;
@@ -1150,7 +1287,7 @@ nir_visitor::visit(ir_expression *ir)
             case 2: emit(nir_op_fnoise1_2, dest_size, srcs); break;
             case 3: emit(nir_op_fnoise1_3, dest_size, srcs); break;
             case 4: emit(nir_op_fnoise1_4, dest_size, srcs); break;
-            default: assert(0); break;
+            default: unreachable("not reached");
          }
          break;
       case 2:
@@ -1159,7 +1296,7 @@ nir_visitor::visit(ir_expression *ir)
             case 2: emit(nir_op_fnoise2_2, dest_size, srcs); break;
             case 3: emit(nir_op_fnoise2_3, dest_size, srcs); break;
             case 4: emit(nir_op_fnoise2_4, dest_size, srcs); break;
-            default: assert(0); break;
+            default: unreachable("not reached");
          }
          break;
       case 3:
@@ -1168,7 +1305,7 @@ nir_visitor::visit(ir_expression *ir)
             case 2: emit(nir_op_fnoise3_2, dest_size, srcs); break;
             case 3: emit(nir_op_fnoise3_3, dest_size, srcs); break;
             case 4: emit(nir_op_fnoise3_4, dest_size, srcs); break;
-            default: assert(0); break;
+            default: unreachable("not reached");
          }
          break;
       case 4:
@@ -1177,12 +1314,11 @@ nir_visitor::visit(ir_expression *ir)
             case 2: emit(nir_op_fnoise4_2, dest_size, srcs); break;
             case 3: emit(nir_op_fnoise4_3, dest_size, srcs); break;
             case 4: emit(nir_op_fnoise4_4, dest_size, srcs); break;
-            default: assert(0); break;
+            default: unreachable("not reached");
          }
          break;
       default:
-         assert(0);
-         break;
+         unreachable("not reached");
       }
       break;
    case ir_binop_add:
@@ -1196,6 +1332,9 @@ nir_visitor::visit(ir_expression *ir)
    case ir_binop_bit_and:
    case ir_binop_bit_or:
    case ir_binop_bit_xor:
+   case ir_binop_logic_and:
+   case ir_binop_logic_or:
+   case ir_binop_logic_xor:
    case ir_binop_lshift:
    case ir_binop_rshift:
       switch (ir->operation) {
@@ -1256,6 +1395,24 @@ nir_visitor::visit(ir_expression *ir)
       case ir_binop_bit_xor:
          op = nir_op_ixor;
          break;
+      case ir_binop_logic_and:
+         if (supports_ints)
+            op = nir_op_iand;
+         else
+            op = nir_op_fand;
+         break;
+      case ir_binop_logic_or:
+         if (supports_ints)
+            op = nir_op_ior;
+         else
+            op = nir_op_for;
+         break;
+      case ir_binop_logic_xor:
+         if (supports_ints)
+            op = nir_op_ixor;
+         else
+            op = nir_op_fxor;
+         break;
       case ir_binop_lshift:
          op = nir_op_ishl;
          break;
@@ -1270,8 +1427,7 @@ nir_visitor::visit(ir_expression *ir)
          break;
 
       default:
-         assert(0);
-         break;
+         unreachable("not reached");
       }
 
       instr = emit(op, dest_size, srcs);
@@ -1376,8 +1532,7 @@ nir_visitor::visit(ir_expression *ir)
                case 3: emit(nir_op_ball_fequal3, dest_size, srcs); break;
                case 4: emit(nir_op_ball_fequal4, dest_size, srcs); break;
                default:
-                  assert(0);
-                  break;
+                  unreachable("not reached");
             }
          } else {
             switch (ir->operands[0]->type->vector_elements) {
@@ -1386,8 +1541,7 @@ nir_visitor::visit(ir_expression *ir)
                case 3: emit(nir_op_ball_iequal3, dest_size, srcs); break;
                case 4: emit(nir_op_ball_iequal4, dest_size, srcs); break;
                default:
-                  assert(0);
-                  break;
+                  unreachable("not reached");
             }
          }
       } else {
@@ -1397,8 +1551,7 @@ nir_visitor::visit(ir_expression *ir)
             case 3: emit(nir_op_fall_equal3, dest_size, srcs); break;
             case 4: emit(nir_op_fall_equal4, dest_size, srcs); break;
             default:
-               assert(0);
-               break;
+               unreachable("not reached");
          }
       }
       break;
@@ -1411,8 +1564,7 @@ nir_visitor::visit(ir_expression *ir)
                case 3: emit(nir_op_bany_fnequal3, dest_size, srcs); break;
                case 4: emit(nir_op_bany_fnequal4, dest_size, srcs); break;
                default:
-                  assert(0);
-                  break;
+                  unreachable("not reached");
             }
          } else {
             switch (ir->operands[0]->type->vector_elements) {
@@ -1421,8 +1573,7 @@ nir_visitor::visit(ir_expression *ir)
                case 3: emit(nir_op_bany_inequal3, dest_size, srcs); break;
                case 4: emit(nir_op_bany_inequal4, dest_size, srcs); break;
                default:
-                  assert(0);
-                  break;
+                  unreachable("not reached");
             }
          }
       } else {
@@ -1432,37 +1583,17 @@ nir_visitor::visit(ir_expression *ir)
             case 3: emit(nir_op_fany_nequal3, dest_size, srcs); break;
             case 4: emit(nir_op_fany_nequal4, dest_size, srcs); break;
             default:
-               assert(0);
-               break;
+               unreachable("not reached");
          }
       }
       break;
-   case ir_binop_logic_and:
-      if (supports_ints)
-         emit(nir_op_iand, dest_size, srcs);
-      else
-         emit(nir_op_fand, dest_size, srcs);
-      break;
-   case ir_binop_logic_or:
-      if (supports_ints)
-         emit(nir_op_ior, dest_size, srcs);
-      else
-         emit(nir_op_for, dest_size, srcs);
-      break;
-   case ir_binop_logic_xor:
-      if (supports_ints)
-         emit(nir_op_ixor, dest_size, srcs);
-      else
-         emit(nir_op_fxor, dest_size, srcs);
-      break;
    case ir_binop_dot:
       switch (ir->operands[0]->type->vector_elements) {
          case 2: emit(nir_op_fdot2, dest_size, srcs); break;
          case 3: emit(nir_op_fdot3, dest_size, srcs); break;
          case 4: emit(nir_op_fdot4, dest_size, srcs); break;
          default:
-            assert(0);
-            break;
+            unreachable("not reached");
       }
       break;
 
@@ -1514,13 +1645,12 @@ nir_visitor::visit(ir_expression *ir)
          case 2: emit(nir_op_vec2, dest_size, srcs); break;
          case 3: emit(nir_op_vec3, dest_size, srcs); break;
          case 4: emit(nir_op_vec4, dest_size, srcs); break;
-         default: assert(0); break;
+         default: unreachable("not reached");
       }
       break;
 
    default:
-      assert(0);
-      break;
+      unreachable("not reached");
    }
 }
 
@@ -1595,8 +1725,7 @@ nir_visitor::visit(ir_texture *ir)
       break;
 
    default:
-      assert(0);
-      break;
+      unreachable("not reached");
    }
 
    if (ir->projector != NULL)
@@ -1626,30 +1755,29 @@ nir_visitor::visit(ir_texture *ir)
       instr->dest_type = nir_type_unsigned;
       break;
    default:
-      assert(0);
+      unreachable("not reached");
    }
 
-   ir->sampler->accept(this);
-   instr->sampler = this->deref_head;
+   instr->sampler = evaluate_deref(&instr->instr, ir->sampler);
 
    unsigned src_number = 0;
 
    if (ir->coordinate != NULL) {
       instr->coord_components = ir->coordinate->type->vector_elements;
-      instr->src[src_number] = evaluate_rvalue(ir->coordinate);
-      instr->src_type[src_number] = nir_tex_src_coord;
+      instr->src[src_number].src = evaluate_rvalue(ir->coordinate);
+      instr->src[src_number].src_type = nir_tex_src_coord;
       src_number++;
    }
 
    if (ir->projector != NULL) {
-      instr->src[src_number] = evaluate_rvalue(ir->projector);
-      instr->src_type[src_number] = nir_tex_src_projector;
+      instr->src[src_number].src = evaluate_rvalue(ir->projector);
+      instr->src[src_number].src_type = nir_tex_src_projector;
       src_number++;
    }
 
    if (ir->shadow_comparitor != NULL) {
-      instr->src[src_number] = evaluate_rvalue(ir->shadow_comparitor);
-      instr->src_type[src_number] = nir_tex_src_comparitor;
+      instr->src[src_number].src = evaluate_rvalue(ir->shadow_comparitor);
+      instr->src[src_number].src_type = nir_tex_src_comparitor;
       src_number++;
    }
 
@@ -1662,16 +1790,16 @@ nir_visitor::visit(ir_texture *ir)
          for (unsigned i = 0; i < const_offset->type->vector_elements; i++)
             instr->const_offset[i] = const_offset->value.i[i];
       } else {
-         instr->src[src_number] = evaluate_rvalue(ir->offset);
-         instr->src_type[src_number] = nir_tex_src_offset;
+         instr->src[src_number].src = evaluate_rvalue(ir->offset);
+         instr->src[src_number].src_type = nir_tex_src_offset;
          src_number++;
       }
    }
 
    switch (ir->op) {
    case ir_txb:
-      instr->src[src_number] = evaluate_rvalue(ir->lod_info.bias);
-      instr->src_type[src_number] = nir_tex_src_bias;
+      instr->src[src_number].src = evaluate_rvalue(ir->lod_info.bias);
+      instr->src[src_number].src_type = nir_tex_src_bias;
       src_number++;
       break;
 
@@ -1679,24 +1807,24 @@ nir_visitor::visit(ir_texture *ir)
    case ir_txf:
    case ir_txs:
       if (ir->lod_info.lod != NULL) {
-         instr->src[src_number] = evaluate_rvalue(ir->lod_info.lod);
-         instr->src_type[src_number] = nir_tex_src_lod;
+         instr->src[src_number].src = evaluate_rvalue(ir->lod_info.lod);
+         instr->src[src_number].src_type = nir_tex_src_lod;
          src_number++;
       }
       break;
 
    case ir_txd:
-      instr->src[src_number] = evaluate_rvalue(ir->lod_info.grad.dPdx);
-      instr->src_type[src_number] = nir_tex_src_ddx;
+      instr->src[src_number].src = evaluate_rvalue(ir->lod_info.grad.dPdx);
+      instr->src[src_number].src_type = nir_tex_src_ddx;
       src_number++;
-      instr->src[src_number] = evaluate_rvalue(ir->lod_info.grad.dPdy);
-      instr->src_type[src_number] = nir_tex_src_ddy;
+      instr->src[src_number].src = evaluate_rvalue(ir->lod_info.grad.dPdy);
+      instr->src[src_number].src_type = nir_tex_src_ddy;
       src_number++;
       break;
 
    case ir_txf_ms:
-      instr->src[src_number] = evaluate_rvalue(ir->lod_info.sample_index);
-      instr->src_type[src_number] = nir_tex_src_ms_index;
+      instr->src[src_number].src = evaluate_rvalue(ir->lod_info.sample_index);
+      instr->src[src_number].src_type = nir_tex_src_ms_index;
       src_number++;
       break;
 
@@ -1718,8 +1846,8 @@ nir_visitor::visit(ir_constant *ir)
 {
    /*
     * We don't know if this variable is an an array or struct that gets
-    * dereferenced, so do the safe thing an make it a variable and return a
-    * dereference.
+    * dereferenced, so do the safe thing an make it a variable with a
+    * constant initializer and return a dereference.
     */
 
    nir_variable *var = ralloc(this->shader, nir_variable);
@@ -1727,7 +1855,6 @@ nir_visitor::visit(ir_constant *ir)
    var->type = ir->type;
    var->data.mode = nir_var_local;
    var->data.read_only = true;
-   var->constant_value = constant_copy(ir, var);
    var->constant_initializer = constant_copy(ir, var);
    exec_list_push_tail(&this->impl->locals, &var->node);
 
@@ -1753,7 +1880,10 @@ nir_visitor::visit(ir_dereference_record *ir)
 {
    ir->record->accept(this);
 
-   nir_deref_struct *deref = nir_deref_struct_create(this->shader, ir->field);
+   int field_index = this->deref_tail->type->field_index(ir->field);
+   assert(field_index >= 0);
+
+   nir_deref_struct *deref = nir_deref_struct_create(this->deref_tail, field_index);
    deref->deref.type = ir->type;
    this->deref_tail->child = &deref->deref;
    this->deref_tail = &deref->deref;
@@ -1777,5 +1907,14 @@ nir_visitor::visit(ir_dereference_array *ir)
    ir->array->accept(this);
 
    this->deref_tail->child = &deref->deref;
+   ralloc_steal(this->deref_tail, deref);
    this->deref_tail = &deref->deref;
 }
+
+void
+nir_visitor::visit(ir_barrier *ir)
+{
+   nir_intrinsic_instr *instr =
+      nir_intrinsic_instr_create(this->shader, nir_intrinsic_barrier);
+   nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+}