writer/msl: Emulate scalar length and distance

Fixed: tint:921
Change-Id: I90fe01fa854d64cfff9453898153a38b360b52de
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58822
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 05768ae..16b0a21 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -432,6 +432,33 @@
       return true;
     }
 
+    case sem::IntrinsicType::kLength: {
+      auto* sem = builder_.Sem().Get(expr->params()[0]);
+      if (sem->Type()->UnwrapRef()->is_scalar()) {
+        // Emulate scalar overload using fabs(x).
+        name = "fabs";
+      }
+      break;
+    }
+
+    case sem::IntrinsicType::kDistance: {
+      auto* sem = builder_.Sem().Get(expr->params()[0]);
+      if (sem->Type()->UnwrapRef()->is_scalar()) {
+        // Emulate scalar overload using fabs(x - y);
+        out << "fabs";
+        ScopedParen sp(out);
+        if (!EmitExpression(out, expr->params()[0])) {
+          return false;
+        }
+        out << " - ";
+        if (!EmitExpression(out, expr->params()[1])) {
+          return false;
+        }
+        return true;
+      }
+      break;
+    }
+
     default:
       break;
   }
diff --git a/src/writer/msl/generator_impl_import_test.cc b/src/writer/msl/generator_impl_import_test.cc
index 9535cce..84b9536 100644
--- a/src/writer/msl/generator_impl_import_test.cc
+++ b/src/writer/msl/generator_impl_import_test.cc
@@ -86,6 +86,17 @@
   EXPECT_EQ(out.str(), R"(abs(1))");
 }
 
+TEST_F(MslGeneratorImplTest, MslImportData_SingleParamTest_ScalarLength) {
+  auto* expr = Call("length", 2.f);
+  WrapInFunction(expr);
+
+  GeneratorImpl& gen = Build();
+
+  std::stringstream out;
+  ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
+  EXPECT_EQ(out.str(), R"(fabs(2.0f))");
+}
+
 using MslImportData_DualParam_ScalarTest = TestParamHelper<MslImportData>;
 TEST_P(MslImportData_DualParam_ScalarTest, Float) {
   auto param = GetParam();
@@ -102,12 +113,22 @@
 INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
                          MslImportData_DualParam_ScalarTest,
                          testing::Values(MslImportData{"atan2", "atan2"},
-                                         MslImportData{"distance", "distance"},
                                          MslImportData{"max", "fmax"},
                                          MslImportData{"min", "fmin"},
                                          MslImportData{"pow", "pow"},
                                          MslImportData{"step", "step"}));
 
+TEST_F(MslGeneratorImplTest, MslImportData_DualParam_ScalarDistance) {
+  auto* expr = Call("distance", 2.f, 3.f);
+  WrapInFunction(expr);
+
+  GeneratorImpl& gen = Build();
+
+  std::stringstream out;
+  ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
+  EXPECT_EQ(out.str(), R"(fabs(2.0f - 3.0f))");
+}
+
 using MslImportData_DualParam_VectorTest = TestParamHelper<MslImportData>;
 TEST_P(MslImportData_DualParam_VectorTest, Float) {
   auto param = GetParam();
diff --git a/test/intrinsics/gen/distance/cfed73.wgsl.expected.msl b/test/intrinsics/gen/distance/cfed73.wgsl.expected.msl
index 401e6d8..d06dfb2 100644
--- a/test/intrinsics/gen/distance/cfed73.wgsl.expected.msl
+++ b/test/intrinsics/gen/distance/cfed73.wgsl.expected.msl
@@ -1,18 +1,18 @@
-SKIP: FAILED
-
-
-
-Validation Failure:
 #include <metal_stdlib>
 
 using namespace metal;
+struct tint_symbol {
+  float4 value [[position]];
+};
+
 void distance_cfed73() {
-  float res =   distance(1.0f, 1.0f);
+  float res = fabs(1.0f - 1.0f);
 }
 
-vertex void vertex_main() {
+vertex tint_symbol vertex_main() {
   distance_cfed73();
-  return;
+  tint_symbol const tint_symbol_1 = {.value=float4()};
+  return tint_symbol_1;
 }
 
 fragment void fragment_main() {
@@ -25,26 +25,3 @@
   return;
 }
 
-
-tint_1oo4q6.metal:5:17: error: call to 'distance' is ambiguous
-  float res =   distance(1.0f, 1.0f);
-                ^~~~~~~~
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:303:17: note: candidate function
-METAL_FUNC half distance(half2 x, half2 y)
-                ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:334:17: note: candidate function
-METAL_FUNC half distance(half3 x, half3 y)
-                ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:365:17: note: candidate function
-METAL_FUNC half distance(half4 x, half4 y)
-                ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:404:18: note: candidate function
-METAL_FUNC float distance(float2 x, float2 y)
-                 ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:447:18: note: candidate function
-METAL_FUNC float distance(float3 x, float3 y)
-                 ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:490:18: note: candidate function
-METAL_FUNC float distance(float4 x, float4 y)
-                 ^
-1 error generated.
diff --git a/test/intrinsics/gen/length/602a17.wgsl.expected.msl b/test/intrinsics/gen/length/602a17.wgsl.expected.msl
index 38e7b33..4116991 100644
--- a/test/intrinsics/gen/length/602a17.wgsl.expected.msl
+++ b/test/intrinsics/gen/length/602a17.wgsl.expected.msl
@@ -1,18 +1,18 @@
-SKIP: FAILED
-
-
-
-Validation Failure:
 #include <metal_stdlib>
 
 using namespace metal;
+struct tint_symbol {
+  float4 value [[position]];
+};
+
 void length_602a17() {
-  float res =   length(1.0f);
+  float res = fabs(1.0f);
 }
 
-vertex void vertex_main() {
+vertex tint_symbol vertex_main() {
   length_602a17();
-  return;
+  tint_symbol const tint_symbol_1 = {.value=float4()};
+  return tint_symbol_1;
 }
 
 fragment void fragment_main() {
@@ -25,26 +25,3 @@
   return;
 }
 
-
-tint_bg8DxD.metal:5:17: error: call to 'length' is ambiguous
-  float res =   length(1.0f);
-                ^~~~~~
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:295:17: note: candidate function
-METAL_FUNC half length(half2 x)
-                ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:326:17: note: candidate function
-METAL_FUNC half length(half3 x)
-                ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:357:17: note: candidate function
-METAL_FUNC half length(half4 x)
-                ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:388:18: note: candidate function
-METAL_FUNC float length(float2 x)
-                 ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:431:18: note: candidate function
-METAL_FUNC float length(float3 x)
-                 ^
-/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/macos/lib/clang/902.14/include/metal/metal_geometric:474:18: note: candidate function
-METAL_FUNC float length(float4 x)
-                 ^
-1 error generated.