sem: Add Owner() to sem::Parameter

Change-Id: I3de1e2437b9604378b8368494363e19070443670
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59201
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/intrinsic_table.cc b/src/intrinsic_table.cc
index 4f1fa28..c134f43 100644
--- a/src/intrinsic_table.cc
+++ b/src/intrinsic_table.cc
@@ -960,12 +960,12 @@
 
   // De-duplicate intrinsics that are identical.
   return utils::GetOrCreate(intrinsics, intrinsic, [&] {
-    sem::ParameterList params;
+    std::vector<sem::Parameter*> params;
     params.reserve(intrinsic.parameters.size());
     for (auto& p : intrinsic.parameters) {
       params.emplace_back(builder.create<sem::Parameter>(
-          nullptr, p.type, ast::StorageClass::kNone, ast::Access::kUndefined,
-          p.usage));
+          nullptr, static_cast<uint32_t>(params.size()), p.type,
+          ast::StorageClass::kNone, ast::Access::kUndefined, p.usage));
     }
     return builder.create<sem::Intrinsic>(
         intrinsic.type, const_cast<sem::Type*>(intrinsic.return_type),
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 842b348..2904df8 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -477,7 +477,8 @@
 }
 
 Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
-                                           VariableKind kind) {
+                                           VariableKind kind,
+                                           uint32_t index /* = 0 */) {
   if (variable_to_info_.count(var)) {
     TINT_ICE(Resolver, diagnostics_)
         << "Variable " << builder_->Symbols().NameFor(var->symbol())
@@ -576,8 +577,9 @@
     return nullptr;
   }
 
-  auto* info = variable_infos_.Create(var, const_cast<sem::Type*>(type),
-                                      type_name, storage_class, access, kind);
+  auto* info =
+      variable_infos_.Create(var, const_cast<sem::Type*>(type), type_name,
+                             storage_class, access, kind, index);
   variable_to_info_.emplace(var, info);
 
   return info;
@@ -1716,9 +1718,11 @@
   TINT_SCOPED_ASSIGNMENT(current_function_, info);
 
   variable_stack_.push_scope();
+  uint32_t parameter_index = 0;
   for (auto* param : func->params()) {
     Mark(param);
-    auto* param_info = Variable(param, VariableKind::kParameter);
+    auto* param_info =
+        Variable(param, VariableKind::kParameter, parameter_index++);
     if (!param_info) {
       return false;
     }
@@ -3667,6 +3671,7 @@
   uint16_t next_constant_id = 0;
 
   // Create semantic nodes for all ast::Variables
+  std::unordered_map<const tint::ast::Variable*, sem::Parameter*> sem_params;
   for (auto it : variable_to_info_) {
     auto* var = it.first;
     auto* info = it.second;
@@ -3706,10 +3711,13 @@
           sem_var = builder_->create<sem::LocalVariable>(
               var, info->type, info->storage_class, info->access);
           break;
-        case VariableKind::kParameter:
-          sem_var = builder_->create<sem::Parameter>(
-              var, info->type, info->storage_class, info->access);
+        case VariableKind::kParameter: {
+          auto* param = builder_->create<sem::Parameter>(
+              var, info->index, info->type, info->storage_class, info->access);
+          sem_var = param;
+          sem_params.emplace(var, param);
           break;
+        }
       }
     }
 
@@ -3752,10 +3760,10 @@
     auto* func = it.first;
     auto* info = it.second;
 
-    sem::ParameterList parameters;
+    std::vector<sem::Parameter*> parameters;
     parameters.reserve(info->parameters.size());
     for (auto* p : info->parameters) {
-      parameters.emplace_back(sem.Get<sem::Parameter>(p->declaration));
+      parameters.emplace_back(sem_params.at(p->declaration));
     }
 
     auto* sem_func = builder_->create<sem::Function>(
@@ -4453,13 +4461,15 @@
                                      const std::string& tn,
                                      ast::StorageClass sc,
                                      ast::Access ac,
-                                     VariableKind k)
+                                     VariableKind k,
+                                     uint32_t idx)
     : declaration(decl),
       type(ty),
       type_name(tn),
       storage_class(sc),
       access(ac),
-      kind(k) {}
+      kind(k),
+      index(idx) {}
 
 Resolver::VariableInfo::~VariableInfo() = default;
 
diff --git a/src/resolver/resolver.h b/src/resolver/resolver.h
index 6afb4c7..600ef22 100644
--- a/src/resolver/resolver.h
+++ b/src/resolver/resolver.h
@@ -103,7 +103,8 @@
                  const std::string& type_name,
                  ast::StorageClass storage_class,
                  ast::Access ac,
-                 VariableKind k);
+                 VariableKind k,
+                 uint32_t idx);
     ~VariableInfo();
 
     ast::Variable const* const declaration;
@@ -114,6 +115,7 @@
     std::vector<ast::IdentifierExpression*> users;
     sem::BindingPoint binding_point;
     VariableKind kind;
+    uint32_t index = 0;  // Parameter index, if kind == kParameter
   };
 
   struct IntrinsicCallInfo {
@@ -359,7 +361,10 @@
   /// context-dependent (global, local, parameter)
   /// @param var the variable to create or return the `VariableInfo` for
   /// @param kind what kind of variable we are declaring
-  VariableInfo* Variable(ast::Variable* var, VariableKind kind);
+  /// @param index the index of the parameter, if this variable is a parameter
+  VariableInfo* Variable(ast::Variable* var,
+                         VariableKind kind,
+                         uint32_t index = 0);
 
   /// Records the storage class usage for the given type, and any transient
   /// dependencies of the type. Validates that the type can be used for the
diff --git a/src/sem/function.cc b/src/sem/function.cc
index 21fabf9..454be74 100644
--- a/src/sem/function.cc
+++ b/src/sem/function.cc
@@ -21,6 +21,7 @@
 #include "src/sem/sampled_texture_type.h"
 #include "src/sem/storage_texture_type.h"
 #include "src/sem/variable.h"
+#include "src/utils/to_const_ptr_vec.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::sem::Function);
 
@@ -29,21 +30,25 @@
 
 Function::Function(ast::Function* declaration,
                    Type* return_type,
-                   ParameterList parameters,
+                   std::vector<Parameter*> parameters,
                    std::vector<const Variable*> referenced_module_vars,
                    std::vector<const Variable*> local_referenced_module_vars,
                    std::vector<const ast::ReturnStatement*> return_statements,
                    std::vector<const ast::CallExpression*> callsites,
                    std::vector<Symbol> ancestor_entry_points,
                    std::array<WorkgroupDimension, 3> workgroup_size)
-    : Base(return_type, std::move(parameters)),
+    : Base(return_type, utils::ToConstPtrVec(parameters)),
       declaration_(declaration),
       referenced_module_vars_(std::move(referenced_module_vars)),
       local_referenced_module_vars_(std::move(local_referenced_module_vars)),
       return_statements_(std::move(return_statements)),
       callsites_(callsites),
       ancestor_entry_points_(std::move(ancestor_entry_points)),
-      workgroup_size_(std::move(workgroup_size)) {}
+      workgroup_size_(std::move(workgroup_size)) {
+  for (auto* parameter : parameters) {
+    parameter->SetOwner(this);
+  }
+}
 
 Function::~Function() = default;
 
diff --git a/src/sem/function.h b/src/sem/function.h
index 6ab1d39..ebf6303 100644
--- a/src/sem/function.h
+++ b/src/sem/function.h
@@ -68,7 +68,7 @@
   /// @param workgroup_size the workgroup size
   Function(ast::Function* declaration,
            Type* return_type,
-           ParameterList parameters,
+           std::vector<Parameter*> parameters,
            std::vector<const Variable*> referenced_module_vars,
            std::vector<const Variable*> local_referenced_module_vars,
            std::vector<const ast::ReturnStatement*> return_statements,
diff --git a/src/sem/intrinsic.cc b/src/sem/intrinsic.cc
index b7d57a9..2e38901 100644
--- a/src/sem/intrinsic.cc
+++ b/src/sem/intrinsic.cc
@@ -14,6 +14,10 @@
 
 #include "src/sem/intrinsic.h"
 
+#include <vector>
+
+#include "src/utils/to_const_ptr_vec.h"
+
 TINT_INSTANTIATE_TYPEINFO(tint::sem::Intrinsic);
 
 namespace tint {
@@ -98,13 +102,17 @@
 
 Intrinsic::Intrinsic(IntrinsicType type,
                      sem::Type* return_type,
-                     ParameterList parameters,
+                     std::vector<Parameter*> parameters,
                      PipelineStageSet supported_stages,
                      bool is_deprecated)
-    : Base(return_type, parameters),
+    : Base(return_type, utils::ToConstPtrVec(parameters)),
       type_(type),
       supported_stages_(supported_stages),
-      is_deprecated_(is_deprecated) {}
+      is_deprecated_(is_deprecated) {
+  for (auto* parameter : parameters) {
+    parameter->SetOwner(this);
+  }
+}
 
 Intrinsic::~Intrinsic() = default;
 
diff --git a/src/sem/intrinsic.h b/src/sem/intrinsic.h
index 74f332f..27f3136 100644
--- a/src/sem/intrinsic.h
+++ b/src/sem/intrinsic.h
@@ -16,6 +16,7 @@
 #define SRC_SEM_INTRINSIC_H_
 
 #include <string>
+#include <vector>
 
 #include "src/sem/call_target.h"
 #include "src/sem/intrinsic_type.h"
@@ -88,7 +89,7 @@
   /// deprecated
   Intrinsic(IntrinsicType type,
             sem::Type* return_type,
-            ParameterList parameters,
+            std::vector<Parameter*> parameters,
             PipelineStageSet supported_stages,
             bool is_deprecated);
 
diff --git a/src/sem/variable.cc b/src/sem/variable.cc
index fb6f48f..bc783a1 100644
--- a/src/sem/variable.cc
+++ b/src/sem/variable.cc
@@ -69,11 +69,14 @@
 GlobalVariable::~GlobalVariable() = default;
 
 Parameter::Parameter(const ast::Variable* declaration,
+                     uint32_t index,
                      const sem::Type* type,
                      ast::StorageClass storage_class,
                      ast::Access access,
                      const ParameterUsage usage /* = ParameterUsage::kNone */)
-    : Base(declaration, type, storage_class, access), usage_(usage) {}
+    : Base(declaration, type, storage_class, access),
+      index_(index),
+      usage_(usage) {}
 
 Parameter::~Parameter() = default;
 
diff --git a/src/sem/variable.h b/src/sem/variable.h
index fc8d9be..5bbe3e1 100644
--- a/src/sem/variable.h
+++ b/src/sem/variable.h
@@ -34,6 +34,7 @@
 namespace sem {
 
 // Forward declarations
+class CallTarget;
 class Type;
 class VariableUser;
 
@@ -143,27 +144,37 @@
  public:
   /// Constructor for function parameters
   /// @param declaration the AST declaration node
+  /// @param index the index of the parmeter in the function
   /// @param type the variable type
   /// @param storage_class the variable storage class
   /// @param access the variable access control type
   /// @param usage the semantic usage for the parameter
   Parameter(const ast::Variable* declaration,
+            uint32_t index,
             const sem::Type* type,
             ast::StorageClass storage_class,
             ast::Access access,
             const ParameterUsage usage = ParameterUsage::kNone);
 
-  /// Copy constructor
-  Parameter(const Parameter&);
-
   /// Destructor
   ~Parameter() override;
 
+  /// @return the index of the parmeter in the function
+  uint32_t Index() const { return index_; }
+
   /// @returns the semantic usage for the parameter
   ParameterUsage Usage() const { return usage_; }
 
+  /// @returns the CallTarget owner of this parameter
+  CallTarget const* Owner() const { return owner_; }
+
+  /// @param owner the CallTarget owner of this parameter
+  void SetOwner(CallTarget const* owner) { owner_ = owner; }
+
  private:
+  uint32_t const index_;
   ParameterUsage const usage_;
+  CallTarget const* owner_;
 };
 
 /// ParameterList is a list of Parameter
diff --git a/src/utils/to_const_ptr_vec.h b/src/utils/to_const_ptr_vec.h
new file mode 100644
index 0000000..25e9261
--- /dev/null
+++ b/src/utils/to_const_ptr_vec.h
@@ -0,0 +1,39 @@
+
+// Copyright 2021 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_UTILS_TO_CONST_PTR_VEC_H_
+#define SRC_UTILS_TO_CONST_PTR_VEC_H_
+
+#include <vector>
+
+namespace tint {
+namespace utils {
+
+/// @param in a vector of `T*`
+/// @returns a vector of `const T*` with the content of `in`.
+template <typename T>
+std::vector<const T*> ToConstPtrVec(const std::vector<T*>& in) {
+  std::vector<const T*> out;
+  out.reserve(in.size());
+  for (auto* ptr : in) {
+    out.emplace_back(ptr);
+  }
+  return out;
+}
+
+}  // namespace utils
+}  // namespace tint
+
+#endif  //  SRC_UTILS_TO_CONST_PTR_VEC_H_