/*
 * Copyright © 2018 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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
 * THE AUTHORS OR COPYRIGHT HOLDERS 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 "nir.h"
#include "nir_deref.h"

struct split_struct_state {
   void *dead_ctx;

   struct hash_table *var_to_member_map;
};

static nir_variable *
find_var_member(struct nir_variable *var, unsigned member,
                struct hash_table *var_to_member_map)
{
   struct hash_entry *map_entry =
      _mesa_hash_table_search(var_to_member_map, var);
   if (map_entry == NULL)
      return NULL;

   nir_variable **members = map_entry->data;
   assert(member < var->num_members);
   return members[member];
}

static const struct glsl_type *
member_type(const struct glsl_type *type, unsigned index)
{
   if (glsl_type_is_array(type)) {
      const struct glsl_type *elem =
         member_type(glsl_get_array_element(type), index);
      assert(glsl_get_explicit_stride(type) == 0);
      return glsl_array_type(elem, glsl_get_length(type), 0);
   } else {
      assert(glsl_type_is_struct_or_ifc(type));
      assert(index < glsl_get_length(type));
      return glsl_get_struct_field(type, index);
   }
}

static void
split_variable(struct nir_variable *var, nir_shader *shader,
               struct hash_table *var_to_member_map, void *dead_ctx)
{
   assert(var->state_slots == NULL);

   /* Constant initializers are currently not handled */
   assert(var->constant_initializer == NULL);

   nir_variable **members =
      ralloc_array(dead_ctx, nir_variable *, var->num_members);

   for (unsigned i = 0; i < var->num_members; i++) {
      char *member_name = NULL;
      if (var->name) {
         /* Calculate a reasonable variable name */
         member_name = ralloc_strdup(dead_ctx, var->name);
         const struct glsl_type *t = var->type;
         while (glsl_type_is_array(t)) {
            ralloc_strcat(&member_name, "[*]");
            t = glsl_get_array_element(t);
         }
         const char *field_name = glsl_get_struct_elem_name(t, i);
         if (field_name) {
            member_name = ralloc_asprintf(dead_ctx, "%s.%s",
                                          member_name, field_name);
         } else {
            member_name = ralloc_asprintf(dead_ctx, "%s.@%d", member_name, i);
         }
      }

      members[i] =
         nir_variable_create(shader, var->members[i].mode,
                             member_type(var->type, i), member_name);
      if (var->interface_type) {
         members[i]->interface_type =
            glsl_get_struct_field(var->interface_type, i);
      }
      members[i]->data = var->members[i];
   }

   _mesa_hash_table_insert(var_to_member_map, var, members);
}

static bool
split_variables_in_list(struct exec_list *var_list, nir_shader *shader,
                        struct hash_table *var_to_member_map, void *dead_ctx)
{
   bool progress = false;

   nir_foreach_variable_safe(var, var_list) {
      if (var->num_members == 0)
         continue;

      split_variable(var, shader, var_to_member_map, dead_ctx);
      exec_node_remove(&var->node);
      progress = true;
   }

   return progress;
}

static nir_deref_instr *
build_member_deref(nir_builder *b, nir_deref_instr *deref, nir_variable *member)
{
   if (deref->deref_type == nir_deref_type_var) {
      return nir_build_deref_var(b, member);
   } else {
      nir_deref_instr *parent =
         build_member_deref(b, nir_deref_instr_parent(deref), member);
      return nir_build_deref_follower(b, parent, deref);
   }
}

static void
rewrite_deref_instr(nir_builder *b, nir_deref_instr *deref,
                    struct hash_table *var_to_member_map)
{
   /* We must be a struct deref */
   if (deref->deref_type != nir_deref_type_struct)
      return;

   nir_deref_instr *base;
   for (base = nir_deref_instr_parent(deref);
        base && base->deref_type != nir_deref_type_var;
        base = nir_deref_instr_parent(base)) {

      /* If this struct is nested inside another, bail */
      if (base->deref_type == nir_deref_type_struct)
         return;
   }

   /* We must be on a variable with members */
   if (!base || base->var->num_members == 0)
      return;

   nir_variable *member = find_var_member(base->var, deref->strct.index,
                                          var_to_member_map);
   assert(member);

   b->cursor = nir_before_instr(&deref->instr);
   nir_deref_instr *member_deref =
      build_member_deref(b, nir_deref_instr_parent(deref), member);
   nir_ssa_def_rewrite_uses(&deref->dest.ssa,
                            nir_src_for_ssa(&member_deref->dest.ssa));

   /* The referenced variable is no longer valid, clean up the deref */
   nir_deref_instr_remove_if_unused(deref);
}

bool
nir_split_per_member_structs(nir_shader *shader)
{
   bool progress = false;
   void *dead_ctx = ralloc_context(NULL);
   struct hash_table *var_to_member_map =
      _mesa_pointer_hash_table_create(dead_ctx);

   progress |= split_variables_in_list(&shader->inputs, shader,
                                       var_to_member_map, dead_ctx);
   progress |= split_variables_in_list(&shader->outputs, shader,
                                       var_to_member_map, dead_ctx);
   progress |= split_variables_in_list(&shader->system_values, shader,
                                       var_to_member_map, dead_ctx);
   if (!progress) {
      ralloc_free(dead_ctx);
      return false;
   }

   nir_foreach_function(function, shader) {
      if (!function->impl)
         continue;

      nir_builder b;
      nir_builder_init(&b, function->impl);
      nir_foreach_block(block, function->impl) {
         nir_foreach_instr_safe(instr, block) {
            if (instr->type == nir_instr_type_deref) {
               rewrite_deref_instr(&b, nir_instr_as_deref(instr),
                                   var_to_member_map);
            }
         }
      }
   }

   ralloc_free(dead_ctx);

   return progress;
}
