Update builtin methods.

This CL removes the import mechanism, the identifier paths and updates
all of the standard library methods to be builtins.

Bug: tint:242
Change-Id: If09b98a155ae49ced3986ba2c9b517a060693006
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28720
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 7dbfaf1..0c31e5a 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -17,7 +17,6 @@
 #include <memory>
 #include <vector>
 
-#include "spirv/unified1/GLSL.std.450.h"
 #include "src/ast/array_accessor_expression.h"
 #include "src/ast/as_expression.h"
 #include "src/ast/assignment_statement.h"
@@ -56,104 +55,6 @@
 #include "src/ast/variable_decl_statement.h"
 
 namespace tint {
-namespace {
-
-// Most of these are floating-point general except the below which are only
-// FP16 and FP32. We only have FP32 at this point so the below works, if we
-// get FP64 support or otherwise we'll need to differentiate.
-//   * radians
-//   * degrees
-//   * sin, cos, tan
-//   * asin, acos, atan
-//   * sinh, cosh, tanh
-//   * asinh, acosh, atanh
-//   * exp, exp2
-//   * log, log2
-enum class GlslDataType {
-  kFloatScalarOrVector,
-  kIntScalarOrVector,
-  kFloatVector,
-  kMatrix
-};
-struct GlslData {
-  const char* name;
-  uint8_t param_count;
-  uint32_t op_id;
-  GlslDataType type;
-  uint8_t vector_count;
-};
-
-constexpr const GlslData kGlslData[] = {
-    {"acos", 1, GLSLstd450Acos, GlslDataType::kFloatScalarOrVector, 0},
-    {"acosh", 1, GLSLstd450Acosh, GlslDataType::kFloatScalarOrVector, 0},
-    {"asin", 1, GLSLstd450Asin, GlslDataType::kFloatScalarOrVector, 0},
-    {"asinh", 1, GLSLstd450Asinh, GlslDataType::kFloatScalarOrVector, 0},
-    {"atan", 1, GLSLstd450Atan, GlslDataType::kFloatScalarOrVector, 0},
-    {"atan2", 2, GLSLstd450Atan2, GlslDataType::kFloatScalarOrVector, 0},
-    {"atanh", 1, GLSLstd450Atanh, GlslDataType::kFloatScalarOrVector, 0},
-    {"ceil", 1, GLSLstd450Ceil, GlslDataType::kFloatScalarOrVector, 0},
-    {"cos", 1, GLSLstd450Cos, GlslDataType::kFloatScalarOrVector, 0},
-    {"cosh", 1, GLSLstd450Cosh, GlslDataType::kFloatScalarOrVector, 0},
-    {"cross", 2, GLSLstd450Cross, GlslDataType::kFloatVector, 3},
-    {"degrees", 1, GLSLstd450Degrees, GlslDataType::kFloatScalarOrVector, 0},
-    {"determinant", 1, GLSLstd450Determinant, GlslDataType::kMatrix, 0},
-    {"distance", 2, GLSLstd450Distance, GlslDataType::kFloatScalarOrVector, 0},
-    {"exp", 1, GLSLstd450Exp, GlslDataType::kFloatScalarOrVector, 0},
-    {"exp2", 1, GLSLstd450Exp2, GlslDataType::kFloatScalarOrVector, 0},
-    {"fabs", 1, GLSLstd450FAbs, GlslDataType::kFloatScalarOrVector, 0},
-    {"faceforward", 3, GLSLstd450FaceForward,
-     GlslDataType::kFloatScalarOrVector, 0},
-    {"fclamp", 3, GLSLstd450FClamp, GlslDataType::kFloatScalarOrVector, 0},
-    {"findilsb", 1, GLSLstd450FindILsb, GlslDataType::kIntScalarOrVector, 0},
-    {"findumsb", 1, GLSLstd450FindUMsb, GlslDataType::kIntScalarOrVector, 0},
-    {"findsmsb", 1, GLSLstd450FindSMsb, GlslDataType::kIntScalarOrVector, 0},
-    {"floor", 1, GLSLstd450Floor, GlslDataType::kFloatScalarOrVector, 0},
-    {"fma", 3, GLSLstd450Fma, GlslDataType::kFloatScalarOrVector, 0},
-    {"fmax", 2, GLSLstd450FMax, GlslDataType::kFloatScalarOrVector, 0},
-    {"fmin", 2, GLSLstd450FMin, GlslDataType::kFloatScalarOrVector, 0},
-    {"fmix", 3, GLSLstd450FMix, GlslDataType::kFloatScalarOrVector, 0},
-    {"fract", 1, GLSLstd450Fract, GlslDataType::kFloatScalarOrVector, 0},
-    {"fsign", 1, GLSLstd450FSign, GlslDataType::kFloatScalarOrVector, 0},
-    {"interpolateatcentroid", 1, GLSLstd450InterpolateAtCentroid,
-     GlslDataType::kFloatScalarOrVector, 0},
-    {"inversesqrt", 1, GLSLstd450InverseSqrt,
-     GlslDataType::kFloatScalarOrVector, 0},
-    {"length", 1, GLSLstd450Length, GlslDataType::kFloatScalarOrVector, 0},
-    {"log", 1, GLSLstd450Log, GlslDataType::kFloatScalarOrVector, 0},
-    {"log2", 1, GLSLstd450Log2, GlslDataType::kFloatScalarOrVector, 0},
-    {"matrixinverse", 1, GLSLstd450MatrixInverse, GlslDataType::kMatrix, 0},
-    {"nclamp", 3, GLSLstd450NClamp, GlslDataType::kFloatScalarOrVector, 0},
-    {"nmax", 2, GLSLstd450NMax, GlslDataType::kFloatScalarOrVector, 0},
-    {"nmin", 2, GLSLstd450NMin, GlslDataType::kFloatScalarOrVector, 0},
-    {"normalize", 1, GLSLstd450Normalize, GlslDataType::kFloatScalarOrVector,
-     0},
-    {"pow", 2, GLSLstd450Pow, GlslDataType::kFloatScalarOrVector, 0},
-    {"radians", 1, GLSLstd450Radians, GlslDataType::kFloatScalarOrVector, 0},
-    {"reflect", 2, GLSLstd450Reflect, GlslDataType::kFloatScalarOrVector, 0},
-    {"round", 1, GLSLstd450Round, GlslDataType::kFloatScalarOrVector, 0},
-    {"roundeven", 1, GLSLstd450RoundEven, GlslDataType::kFloatScalarOrVector,
-     0},
-    {"sabs", 1, GLSLstd450SAbs, GlslDataType::kIntScalarOrVector, 0},
-    {"sclamp", 3, GLSLstd450SClamp, GlslDataType::kIntScalarOrVector, 0},
-    {"sin", 1, GLSLstd450Sin, GlslDataType::kFloatScalarOrVector, 0},
-    {"sinh", 1, GLSLstd450Sinh, GlslDataType::kFloatScalarOrVector, 0},
-    {"smax", 2, GLSLstd450SMax, GlslDataType::kIntScalarOrVector, 0},
-    {"smin", 2, GLSLstd450SMin, GlslDataType::kIntScalarOrVector, 0},
-    {"smoothstep", 3, GLSLstd450SmoothStep, GlslDataType::kFloatScalarOrVector,
-     0},
-    {"sqrt", 1, GLSLstd450Sqrt, GlslDataType::kFloatScalarOrVector, 0},
-    {"ssign", 1, GLSLstd450SSign, GlslDataType::kIntScalarOrVector, 0},
-    {"step", 2, GLSLstd450Step, GlslDataType::kFloatScalarOrVector, 0},
-    {"tan", 1, GLSLstd450Tan, GlslDataType::kFloatScalarOrVector, 0},
-    {"tanh", 1, GLSLstd450Tanh, GlslDataType::kFloatScalarOrVector, 0},
-    {"trunc", 1, GLSLstd450Trunc, GlslDataType::kFloatScalarOrVector, 0},
-    {"uclamp", 3, GLSLstd450UClamp, GlslDataType::kIntScalarOrVector, 0},
-    {"umax", 2, GLSLstd450UMax, GlslDataType::kIntScalarOrVector, 0},
-    {"umin", 2, GLSLstd450UMin, GlslDataType::kIntScalarOrVector, 0},
-};
-constexpr const uint32_t kGlslDataCount = sizeof(kGlslData) / sizeof(GlslData);
-
-}  // namespace
 
 TypeDeterminer::TypeDeterminer(Context* ctx, ast::Module* mod)
     : ctx_(*ctx), mod_(mod) {}
@@ -471,6 +372,9 @@
 }
 
 bool TypeDeterminer::DetermineCall(ast::CallExpression* expr) {
+  if (!DetermineResultType(expr->func())) {
+    return false;
+  }
   if (!DetermineResultType(expr->params())) {
     return false;
   }
@@ -481,31 +385,10 @@
   if (expr->func()->IsIdentifier()) {
     auto* ident = expr->func()->AsIdentifier();
 
-    if (ast::intrinsic::IsIntrinsic(ident->name())) {
-      if (!DetermineIntrinsic(ident->name(), expr))
-        return false;
-
-    } else if (ident->has_path()) {
-      auto* imp = mod_->FindImportByName(ident->path());
-      if (imp == nullptr) {
-        set_error(expr->source(), "Unable to find import for " + ident->name());
+    if (ident->IsIntrinsic()) {
+      if (!DetermineIntrinsic(ident, expr)) {
         return false;
       }
-
-      uint32_t ext_id = 0;
-      auto* result_type = GetImportData(expr->source(), imp->path(),
-                                        ident->name(), expr->params(), &ext_id);
-      if (result_type == nullptr) {
-        if (error_.empty()) {
-          set_error(expr->source(),
-                    "Unable to determine result type for GLSL expression " +
-                        ident->name());
-        }
-        return false;
-      }
-
-      imp->AddMethodId(ident->name(), ext_id);
-      expr->func()->set_result_type(result_type);
     } else {
       if (current_function_) {
         caller_to_callee_[current_function_->name()].push_back(ident->name());
@@ -547,41 +430,111 @@
   return true;
 }
 
-bool TypeDeterminer::DetermineIntrinsic(const std::string& name,
+namespace {
+
+enum class IntrinsicDataType {
+  kFloatOrIntScalarOrVector,
+  kFloatScalarOrVector,
+  kIntScalarOrVector,
+  kFloatVector,
+  kMatrix,
+};
+struct IntrinsicData {
+  ast::Intrinsic intrinsic;
+  uint8_t param_count;
+  IntrinsicDataType data_type;
+  uint8_t vector_size;
+};
+
+// Note, this isn't all the intrinsics. Some are handled specially before
+// we get to the generic code. See the DetermineIntrinsic code below.
+constexpr const IntrinsicData kIntrinsicData[] = {
+    {ast::Intrinsic::kAbs, 1, IntrinsicDataType::kFloatOrIntScalarOrVector, 0},
+    {ast::Intrinsic::kAcos, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kAsin, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kAtan, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kAtan2, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kCeil, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kClamp, 3, IntrinsicDataType::kFloatOrIntScalarOrVector,
+     0},
+    {ast::Intrinsic::kCos, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kCosh, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kCountOneBits, 1, IntrinsicDataType::kIntScalarOrVector,
+     0},
+    {ast::Intrinsic::kCross, 2, IntrinsicDataType::kFloatVector, 3},
+    {ast::Intrinsic::kDeterminant, 1, IntrinsicDataType::kMatrix, 0},
+    {ast::Intrinsic::kDistance, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kExp, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kExp2, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kFaceForward, 3, IntrinsicDataType::kFloatScalarOrVector,
+     0},
+    {ast::Intrinsic::kFloor, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kFma, 3, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kFract, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kFrexp, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kInverseSqrt, 1, IntrinsicDataType::kFloatScalarOrVector,
+     0},
+    {ast::Intrinsic::kLdexp, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kLength, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kLog, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kLog2, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kMax, 2, IntrinsicDataType::kFloatOrIntScalarOrVector, 0},
+    {ast::Intrinsic::kMin, 2, IntrinsicDataType::kFloatOrIntScalarOrVector, 0},
+    {ast::Intrinsic::kMix, 3, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kModf, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kNormalize, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kPow, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kReflect, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kReverseBits, 1, IntrinsicDataType::kIntScalarOrVector, 0},
+    {ast::Intrinsic::kRound, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kSign, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kSin, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kSinh, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kSmoothStep, 3, IntrinsicDataType::kFloatScalarOrVector,
+     0},
+    {ast::Intrinsic::kSqrt, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kStep, 2, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kTan, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kTanh, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+    {ast::Intrinsic::kTrunc, 1, IntrinsicDataType::kFloatScalarOrVector, 0},
+};
+
+constexpr const uint32_t kIntrinsicDataCount =
+    sizeof(kIntrinsicData) / sizeof(IntrinsicData);
+
+}  // namespace
+
+bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
                                         ast::CallExpression* expr) {
-  if (ast::intrinsic::IsDerivative(name)) {
+  if (ast::intrinsic::IsDerivative(ident->intrinsic())) {
     if (expr->params().size() != 1) {
-      set_error(expr->source(), "incorrect number of parameters for " + name);
+      set_error(expr->source(),
+                "incorrect number of parameters for " + ident->name());
       return false;
     }
 
     // The result type must be the same as the type of the parameter.
-    auto& param = expr->params()[0];
-    if (!DetermineResultType(param.get())) {
-      return false;
-    }
-    expr->func()->set_result_type(param->result_type()->UnwrapPtrIfNeeded());
+    auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
+    expr->func()->set_result_type(param_type);
     return true;
   }
-  if (name == "any" || name == "all") {
+  if (ident->intrinsic() == ast::Intrinsic::kAny ||
+      ident->intrinsic() == ast::Intrinsic::kAll) {
     expr->func()->set_result_type(
         ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>()));
     return true;
   }
-  if (ast::intrinsic::IsFloatClassificationIntrinsic(name)) {
+  if (ast::intrinsic::IsFloatClassificationIntrinsic(ident->intrinsic())) {
     if (expr->params().size() != 1) {
-      set_error(expr->source(), "incorrect number of parameters for " + name);
+      set_error(expr->source(),
+                "incorrect number of parameters for " + ident->name());
       return false;
     }
 
     auto* bool_type =
         ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
 
-    auto& param = expr->params()[0];
-    if (!DetermineResultType(param.get())) {
-      return false;
-    }
-    auto* param_type = param->result_type()->UnwrapPtrIfNeeded();
+    auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
     if (param_type->IsVector()) {
       expr->func()->set_result_type(
           ctx_.type_mgr().Get(std::make_unique<ast::type::VectorType>(
@@ -591,31 +544,31 @@
     }
     return true;
   }
-  if (ast::intrinsic::IsTextureOperationIntrinsic(name)) {
+  if (ast::intrinsic::IsTextureIntrinsic(ident->intrinsic())) {
     // TODO: Remove the LOD param from textureLoad on storage textures when
     // https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
     uint32_t num_of_params =
-        (name == "textureLoad" || name == "textureSample") ? 3 : 4;
+        (ident->intrinsic() == ast::Intrinsic::kTextureLoad ||
+         ident->intrinsic() == ast::Intrinsic::kTextureSample)
+            ? 3
+            : 4;
     if (expr->params().size() != num_of_params) {
       set_error(expr->source(),
-                "incorrect number of parameters for " + name + ", got " +
-                    std::to_string(expr->params().size()) + " and expected " +
-                    std::to_string(num_of_params));
+                "incorrect number of parameters for " + ident->name() +
+                    ", got " + std::to_string(expr->params().size()) +
+                    " and expected " + std::to_string(num_of_params));
       return false;
     }
 
-    if (name == "textureSampleCompare") {
+    if (ident->intrinsic() == ast::Intrinsic::kTextureSampleCompare) {
       expr->func()->set_result_type(
           ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
       return true;
     }
 
     auto& texture_param = expr->params()[0];
-    if (!DetermineResultType(texture_param.get())) {
-      return false;
-    }
     if (!texture_param->result_type()->UnwrapPtrIfNeeded()->IsTexture()) {
-      set_error(expr->source(), "invalid first argument for " + name);
+      set_error(expr->source(), "invalid first argument for " + ident->name());
       return false;
     }
     ast::type::TextureType* texture =
@@ -623,7 +576,7 @@
 
     if (!texture->IsStorage() &&
         !(texture->IsSampled() || texture->IsMultisampled())) {
-      set_error(expr->source(), "invalid texture for " + name);
+      set_error(expr->source(), "invalid texture for " + ident->name());
       return false;
     }
 
@@ -642,29 +595,22 @@
         ctx_.type_mgr().Get(std::make_unique<ast::type::VectorType>(type, 4)));
     return true;
   }
-  if (name == "dot") {
+  if (ident->intrinsic() == ast::Intrinsic::kDot) {
     expr->func()->set_result_type(
         ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
     return true;
   }
-  if (name == "outerProduct") {
+  if (ident->intrinsic() == ast::Intrinsic::kOuterProduct) {
     if (expr->params().size() != 2) {
       set_error(expr->source(),
-                "incorrect number of parameters for outer_product");
+                "incorrect number of parameters for " + ident->name());
       return false;
     }
 
-    auto& param0 = expr->params()[0];
-    auto& param1 = expr->params()[1];
-    if (!DetermineResultType(param0.get()) ||
-        !DetermineResultType(param1.get())) {
-      return false;
-    }
-
-    auto* param0_type = param0->result_type()->UnwrapPtrIfNeeded();
-    auto* param1_type = param1->result_type()->UnwrapPtrIfNeeded();
+    auto* param0_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
+    auto* param1_type = expr->params()[1]->result_type()->UnwrapPtrIfNeeded();
     if (!param0_type->IsVector() || !param1_type->IsVector()) {
-      set_error(expr->source(), "invalid parameter type for outer_product");
+      set_error(expr->source(), "invalid parameter type for " + ident->name());
       return false;
     }
 
@@ -674,24 +620,121 @@
             param0_type->AsVector()->size(), param1_type->AsVector()->size())));
     return true;
   }
-  if (name == "select") {
+  if (ident->intrinsic() == ast::Intrinsic::kSelect) {
     if (expr->params().size() != 3) {
-      set_error(expr->source(),
-                "incorrect number of parameters for select expected 3 got " +
-                    std::to_string(expr->params().size()));
+      set_error(expr->source(), "incorrect number of parameters for " +
+                                    ident->name() + " expected 3 got " +
+                                    std::to_string(expr->params().size()));
       return false;
     }
 
     // The result type must be the same as the type of the parameter.
-    auto& param = expr->params()[0];
-    if (!DetermineResultType(param.get())) {
-      return false;
-    }
-    expr->func()->set_result_type(param->result_type()->UnwrapPtrIfNeeded());
+    auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
+    expr->func()->set_result_type(param_type);
     return true;
   }
 
-  return false;
+  const IntrinsicData* data = nullptr;
+  for (uint32_t i = 0; i < kIntrinsicDataCount; ++i) {
+    if (ident->intrinsic() == kIntrinsicData[i].intrinsic) {
+      data = &kIntrinsicData[i];
+      break;
+    }
+  }
+  if (data == nullptr) {
+    return false;
+  }
+
+  if (expr->params().size() != data->param_count) {
+    set_error(expr->source(), "incorrect number of parameters for " +
+                                  ident->name() + ". Expected " +
+                                  std::to_string(data->param_count) + " got " +
+                                  std::to_string(expr->params().size()));
+    return false;
+  }
+
+  std::vector<ast::type::Type*> result_types;
+  for (uint32_t i = 0; i < data->param_count; ++i) {
+    result_types.push_back(
+        expr->params()[i]->result_type()->UnwrapPtrIfNeeded());
+
+    switch (data->data_type) {
+      case IntrinsicDataType::kFloatOrIntScalarOrVector:
+        if (!result_types.back()->is_float_scalar_or_vector() &&
+            !result_types.back()->is_integer_scalar_or_vector()) {
+          set_error(expr->source(),
+                    "incorrect type for " + ident->name() + ". " +
+                        "Requires float or int, scalar or vector values");
+          return false;
+        }
+        break;
+      case IntrinsicDataType::kFloatScalarOrVector:
+        if (!result_types.back()->is_float_scalar_or_vector()) {
+          set_error(expr->source(),
+                    "incorrect type for " + ident->name() + ". " +
+                        "Requires float scalar or float vector values");
+          return false;
+        }
+
+        break;
+      case IntrinsicDataType::kIntScalarOrVector:
+        if (!result_types.back()->is_integer_scalar_or_vector()) {
+          set_error(expr->source(),
+                    "incorrect type for " + ident->name() + ". " +
+                        "Requires integer scalar or integer vector values");
+          return false;
+        }
+        break;
+      case IntrinsicDataType::kFloatVector:
+        if (!result_types.back()->is_float_vector()) {
+          set_error(expr->source(), "incorrect type for " + ident->name() +
+                                        ". " + "Requires float vector values");
+          return false;
+        }
+        if (data->vector_size > 0 &&
+            result_types.back()->AsVector()->size() != data->vector_size) {
+          set_error(expr->source(), "incorrect vector size for " +
+                                        ident->name() + ". " + "Requires " +
+                                        std::to_string(data->vector_size) +
+                                        " elements");
+          return false;
+        }
+        break;
+      case IntrinsicDataType::kMatrix:
+        if (!result_types.back()->IsMatrix()) {
+          set_error(expr->source(), "incorrect type for " + ident->name() +
+                                        ". Requires matrix value");
+          return false;
+        }
+        break;
+    }
+  }
+
+  // Verify all the parameter types match
+  for (size_t i = 1; i < data->param_count; ++i) {
+    if (result_types[0] != result_types[i]) {
+      set_error(expr->source(),
+                "mismatched parameter types for " + ident->name());
+      return false;
+    }
+  }
+
+  // Handle functions which aways return the type, even if a vector is
+  // provided.
+  if (ident->intrinsic() == ast::Intrinsic::kLength ||
+      ident->intrinsic() == ast::Intrinsic::kDistance) {
+    expr->func()->set_result_type(result_types[0]->is_float_scalar()
+                                      ? result_types[0]
+                                      : result_types[0]->AsVector()->type());
+    return true;
+  }
+  // The determinant returns the component type of the columns
+  if (ident->intrinsic() == ast::Intrinsic::kDeterminant) {
+    expr->func()->set_result_type(result_types[0]->AsMatrix()->type());
+    return true;
+  }
+  expr->func()->set_result_type(result_types[0]);
+  return true;
 }
 
 bool TypeDeterminer::DetermineCast(ast::CastExpression* expr) {
@@ -719,12 +762,6 @@
 }
 
 bool TypeDeterminer::DetermineIdentifier(ast::IdentifierExpression* expr) {
-  if (expr->has_path()) {
-    set_error(expr->source(),
-              "determine identifier should not be called with imports");
-    return false;
-  }
-
   auto name = expr->name();
   ast::Variable* var;
   if (variable_stack_.get(name, &var)) {
@@ -750,9 +787,147 @@
     return true;
   }
 
+  SetIntrinsicIfNeeded(expr);
+
   return true;
 }
 
+void TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
+  if (ident->name() == "abs") {
+    ident->set_intrinsic(ast::Intrinsic::kAbs);
+  } else if (ident->name() == "acos") {
+    ident->set_intrinsic(ast::Intrinsic::kAcos);
+  } else if (ident->name() == "all") {
+    ident->set_intrinsic(ast::Intrinsic::kAll);
+  } else if (ident->name() == "any") {
+    ident->set_intrinsic(ast::Intrinsic::kAny);
+  } else if (ident->name() == "asin") {
+    ident->set_intrinsic(ast::Intrinsic::kAsin);
+  } else if (ident->name() == "atan") {
+    ident->set_intrinsic(ast::Intrinsic::kAtan);
+  } else if (ident->name() == "atan2") {
+    ident->set_intrinsic(ast::Intrinsic::kAtan2);
+  } else if (ident->name() == "ceil") {
+    ident->set_intrinsic(ast::Intrinsic::kCeil);
+  } else if (ident->name() == "clamp") {
+    ident->set_intrinsic(ast::Intrinsic::kClamp);
+  } else if (ident->name() == "cos") {
+    ident->set_intrinsic(ast::Intrinsic::kCos);
+  } else if (ident->name() == "cosh") {
+    ident->set_intrinsic(ast::Intrinsic::kCosh);
+  } else if (ident->name() == "countOneBits") {
+    ident->set_intrinsic(ast::Intrinsic::kCountOneBits);
+  } else if (ident->name() == "cross") {
+    ident->set_intrinsic(ast::Intrinsic::kCross);
+  } else if (ident->name() == "determinant") {
+    ident->set_intrinsic(ast::Intrinsic::kDeterminant);
+  } else if (ident->name() == "distance") {
+    ident->set_intrinsic(ast::Intrinsic::kDistance);
+  } else if (ident->name() == "dot") {
+    ident->set_intrinsic(ast::Intrinsic::kDot);
+  } else if (ident->name() == "dpdx") {
+    ident->set_intrinsic(ast::Intrinsic::kDpdx);
+  } else if (ident->name() == "dpdxCoarse") {
+    ident->set_intrinsic(ast::Intrinsic::kDpdxCoarse);
+  } else if (ident->name() == "dpdxFine") {
+    ident->set_intrinsic(ast::Intrinsic::kDpdxFine);
+  } else if (ident->name() == "dpdy") {
+    ident->set_intrinsic(ast::Intrinsic::kDpdy);
+  } else if (ident->name() == "dpdyCoarse") {
+    ident->set_intrinsic(ast::Intrinsic::kDpdyCoarse);
+  } else if (ident->name() == "dpdyFine") {
+    ident->set_intrinsic(ast::Intrinsic::kDpdyFine);
+  } else if (ident->name() == "exp") {
+    ident->set_intrinsic(ast::Intrinsic::kExp);
+  } else if (ident->name() == "exp2") {
+    ident->set_intrinsic(ast::Intrinsic::kExp2);
+  } else if (ident->name() == "faceForward") {
+    ident->set_intrinsic(ast::Intrinsic::kFaceForward);
+  } else if (ident->name() == "floor") {
+    ident->set_intrinsic(ast::Intrinsic::kFloor);
+  } else if (ident->name() == "fma") {
+    ident->set_intrinsic(ast::Intrinsic::kFma);
+  } else if (ident->name() == "fract") {
+    ident->set_intrinsic(ast::Intrinsic::kFract);
+  } else if (ident->name() == "frexp") {
+    ident->set_intrinsic(ast::Intrinsic::kFrexp);
+  } else if (ident->name() == "fwidth") {
+    ident->set_intrinsic(ast::Intrinsic::kFwidth);
+  } else if (ident->name() == "fwidthCoarse") {
+    ident->set_intrinsic(ast::Intrinsic::kFwidthCoarse);
+  } else if (ident->name() == "fwidthFine") {
+    ident->set_intrinsic(ast::Intrinsic::kFwidthFine);
+  } else if (ident->name() == "inverseSqrt") {
+    ident->set_intrinsic(ast::Intrinsic::kInverseSqrt);
+  } else if (ident->name() == "isFinite") {
+    ident->set_intrinsic(ast::Intrinsic::kIsFinite);
+  } else if (ident->name() == "isInf") {
+    ident->set_intrinsic(ast::Intrinsic::kIsInf);
+  } else if (ident->name() == "isNan") {
+    ident->set_intrinsic(ast::Intrinsic::kIsNan);
+  } else if (ident->name() == "isNormal") {
+    ident->set_intrinsic(ast::Intrinsic::kIsNormal);
+  } else if (ident->name() == "ldexp") {
+    ident->set_intrinsic(ast::Intrinsic::kLdexp);
+  } else if (ident->name() == "length") {
+    ident->set_intrinsic(ast::Intrinsic::kLength);
+  } else if (ident->name() == "log") {
+    ident->set_intrinsic(ast::Intrinsic::kLog);
+  } else if (ident->name() == "log2") {
+    ident->set_intrinsic(ast::Intrinsic::kLog2);
+  } else if (ident->name() == "max") {
+    ident->set_intrinsic(ast::Intrinsic::kMax);
+  } else if (ident->name() == "min") {
+    ident->set_intrinsic(ast::Intrinsic::kMin);
+  } else if (ident->name() == "mix") {
+    ident->set_intrinsic(ast::Intrinsic::kMix);
+  } else if (ident->name() == "modf") {
+    ident->set_intrinsic(ast::Intrinsic::kModf);
+  } else if (ident->name() == "normalize") {
+    ident->set_intrinsic(ast::Intrinsic::kNormalize);
+  } else if (ident->name() == "outerProduct") {
+    ident->set_intrinsic(ast::Intrinsic::kOuterProduct);
+  } else if (ident->name() == "pow") {
+    ident->set_intrinsic(ast::Intrinsic::kPow);
+  } else if (ident->name() == "reflect") {
+    ident->set_intrinsic(ast::Intrinsic::kReflect);
+  } else if (ident->name() == "reverseBits") {
+    ident->set_intrinsic(ast::Intrinsic::kReverseBits);
+  } else if (ident->name() == "round") {
+    ident->set_intrinsic(ast::Intrinsic::kRound);
+  } else if (ident->name() == "select") {
+    ident->set_intrinsic(ast::Intrinsic::kSelect);
+  } else if (ident->name() == "sign") {
+    ident->set_intrinsic(ast::Intrinsic::kSign);
+  } else if (ident->name() == "sin") {
+    ident->set_intrinsic(ast::Intrinsic::kSin);
+  } else if (ident->name() == "sinh") {
+    ident->set_intrinsic(ast::Intrinsic::kSinh);
+  } else if (ident->name() == "smoothStep") {
+    ident->set_intrinsic(ast::Intrinsic::kSmoothStep);
+  } else if (ident->name() == "sqrt") {
+    ident->set_intrinsic(ast::Intrinsic::kSqrt);
+  } else if (ident->name() == "step") {
+    ident->set_intrinsic(ast::Intrinsic::kStep);
+  } else if (ident->name() == "tan") {
+    ident->set_intrinsic(ast::Intrinsic::kTan);
+  } else if (ident->name() == "tanh") {
+    ident->set_intrinsic(ast::Intrinsic::kTanh);
+  } else if (ident->name() == "textureLoad") {
+    ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
+  } else if (ident->name() == "textureSample") {
+    ident->set_intrinsic(ast::Intrinsic::kTextureSample);
+  } else if (ident->name() == "textureSampleBias") {
+    ident->set_intrinsic(ast::Intrinsic::kTextureSampleBias);
+  } else if (ident->name() == "textureSampleCompare") {
+    ident->set_intrinsic(ast::Intrinsic::kTextureSampleCompare);
+  } else if (ident->name() == "textureSampleLevel") {
+    ident->set_intrinsic(ast::Intrinsic::kTextureSampleLevel);
+  } else if (ident->name() == "trunc") {
+    ident->set_intrinsic(ast::Intrinsic::kTrunc);
+  }
+}
+
 bool TypeDeterminer::DetermineMemberAccessor(
     ast::MemberAccessorExpression* expr) {
   if (!DetermineResultType(expr->structure())) {
@@ -962,101 +1137,4 @@
   return false;
 }
 
-ast::type::Type* TypeDeterminer::GetImportData(
-    const Source& source,
-    const std::string& path,
-    const std::string& name,
-    const ast::ExpressionList& params,
-    uint32_t* id) {
-  if (path != "GLSL.std.450") {
-    set_error(source, "unknown import path " + path);
-    return nullptr;
-  }
-
-  const GlslData* data = nullptr;
-  for (uint32_t i = 0; i < kGlslDataCount; ++i) {
-    if (name == kGlslData[i].name) {
-      data = &kGlslData[i];
-      break;
-    }
-  }
-  if (data == nullptr) {
-    return nullptr;
-  }
-
-  if (params.size() != data->param_count) {
-    set_error(source, "incorrect number of parameters for " + name +
-                          ". Expected " + std::to_string(data->param_count) +
-                          " got " + std::to_string(params.size()));
-    return nullptr;
-  }
-
-  std::vector<ast::type::Type*> result_types;
-  for (uint32_t i = 0; i < data->param_count; ++i) {
-    result_types.push_back(params[i]->result_type()->UnwrapPtrIfNeeded());
-
-    switch (data->type) {
-      case GlslDataType::kFloatScalarOrVector:
-        if (!result_types.back()->is_float_scalar_or_vector()) {
-          set_error(source, "incorrect type for " + name + ". " +
-                                "Requires float scalar or float vector values");
-          return nullptr;
-        }
-
-        break;
-      case GlslDataType::kIntScalarOrVector:
-        if (!result_types.back()->is_integer_scalar_or_vector()) {
-          set_error(source,
-                    "incorrect type for " + name + ". " +
-                        "Requires integer scalar or integer vector values");
-          return nullptr;
-        }
-        break;
-      case GlslDataType::kFloatVector:
-        if (!result_types.back()->is_float_vector()) {
-          set_error(source, "incorrect type for " + name + ". " +
-                                "Requires float vector values");
-          return nullptr;
-        }
-        if (data->vector_count > 0 &&
-            result_types.back()->AsVector()->size() != data->vector_count) {
-          set_error(source,
-                    "incorrect vector size for " + name + ". " + "Requires " +
-                        std::to_string(data->vector_count) + " elements");
-          return nullptr;
-        }
-        break;
-      case GlslDataType::kMatrix:
-        if (!result_types.back()->IsMatrix()) {
-          set_error(source,
-                    "incorrect type for " + name + ". Requires matrix value");
-          return nullptr;
-        }
-        break;
-    }
-  }
-
-  // Verify all the parameter types match
-  for (size_t i = 1; i < data->param_count; ++i) {
-    if (result_types[0] != result_types[i]) {
-      error_ = "mismatched parameter types for " + name;
-      return nullptr;
-    }
-  }
-
-  *id = data->op_id;
-
-  // Handle functions which aways return the type, even if a vector is provided.
-  if (name == "length" || name == "distance") {
-    return result_types[0]->is_float_scalar()
-               ? result_types[0]
-               : result_types[0]->AsVector()->type();
-  }
-  // The determinant returns the component type of the columns
-  if (name == "determinant") {
-    return result_types[0]->AsMatrix()->type();
-  }
-  return result_types[0];
-}
-
 }  // namespace tint