[clang] [clang][Builtins] Parse clang extended vectors types. (PR #83584)

Francesco Petrogalli via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 4 12:27:44 PST 2024


https://github.com/fpetrogalli updated https://github.com/llvm/llvm-project/pull/83584

>From 53d9fe77500a18884f200c49db57336324305620 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Fri, 1 Mar 2024 16:23:57 +0100
Subject: [PATCH 1/3] [clang][Builtins] Parse clang extended vectors types.

Clang extended vector types are mangled as follows:

   '_ExtVector<' <lanes> ',' <scalar type> '>'

This is used to defetmine the builtins signature for builtins that
use parameters defined as

    typedef <scalar type> ext_vector_type_<lanes>_<scalar type> __attribute__((ext_vector_type(<lanes>)))

For example:

    typedef double ext_vector_type_4_double __attribute__((ext_vector_type(4)))
---
 .../target-builtins-prototype-parser.td       | 79 +++++++++++++++++++
 clang/utils/TableGen/ClangBuiltinsEmitter.cpp | 61 +++++++++++++-
 2 files changed, 137 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/TableGen/target-builtins-prototype-parser.td

diff --git a/clang/test/TableGen/target-builtins-prototype-parser.td b/clang/test/TableGen/target-builtins-prototype-parser.td
new file mode 100644
index 00000000000000..a6d0c98fa8bca2
--- /dev/null
+++ b/clang/test/TableGen/target-builtins-prototype-parser.td
@@ -0,0 +1,79 @@
+// RUN: clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins | FileCheck %s
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_LANES 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_LANES
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_COMMA 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_COMMA
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_TYPE 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_TYPE
+
+include "clang/Basic/BuiltinsBase.td"
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_01, "E8idE4b", "")
+  let Prototype = "_ExtVector<8,int>(double, _ExtVector<4,        bool>)";
+  let Spellings = ["__builtin_01"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_02, "E8UiE4s", "")
+  let Prototype = "_ExtVector<8,unsigned int>(_ExtVector<4, short>)";
+  let Spellings = ["__builtin_02"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_03, "di", "")
+  let Prototype = "double(int)";
+  let Spellings = ["__builtin_03"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_04, "diIUi", "")
+ let Prototype = "double(int, _Constant unsigned int)";
+  let Spellings = ["__builtin_04"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_05, "v&v&", "")
+ let Prototype = "void&(void&)";
+  let Spellings = ["__builtin_05"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_06, "v*v*cC*.", "")
+ let Prototype = "void*(void*, char const*, ...)";
+  let Spellings = ["__builtin_06"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_07, "E8iE4dE4b.", "")
+  let Prototype = "_ExtVector<8, int>(_ExtVector<4,double>, _ExtVector<4, bool>, ...)";
+  let Spellings = ["__builtin_07"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_08, "di*R", "")
+  let Prototype = "double(int * restrict)";
+  let Spellings = ["__builtin_08"];
+}
+
+#ifdef ERROR_EXPECTED_LANES
+def : Builtin {
+// ERROR_EXPECTED_LANES: :[[# @LINE + 1]]:7: error: Expected number of lanes after '_ExtVector<'
+  let Prototype = "_ExtVector<int>(double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_COMMA
+def : Builtin {
+// ERROR_EXPECTED_COMMA: :[[# @LINE + 1]]:7: error: Expected ',' after number of lanes in '_ExtVector<'
+  let Prototype = "_ExtVector<8 int>(double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_TYPE
+def : Builtin {
+// ERROR_EXPECTED_TYPE: :[[# @LINE + 1]]:7: error: Expected '>' after scalar type in '_ExtVector<N, type>'
+  let Prototype = "_ExtVector<8, int (double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 48f55b8af97e4e..8790101c4a44e2 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -47,9 +47,47 @@ class PrototypeParser {
     if (!Prototype.ends_with(")"))
       PrintFatalError(Loc, "Expected closing brace at end of prototype");
     Prototype = Prototype.drop_back();
-    for (auto T = Prototype.split(','); !T.first.empty();
-         Prototype = T.second, T = Prototype.split(','))
-      ParseType(T.first);
+
+    // Look through the input parameters.
+    const size_t end = Prototype.size();
+    for (size_t I = 0; I != end;) {
+      const StringRef Current = Prototype.substr(I, end);
+      // Skip any leading space or commas
+      if (Current.starts_with(" ") || Current.starts_with(",")) {
+        ++I;
+        continue;
+      }
+
+      // Check if we are in _ExtVector. We do this first because
+      // extended vectors are written in template form with the syntax
+      // _ExtVector< ..., ...>, so we need to make sure we are not
+      // detecting the comma of the template class as a separator for
+      // the parameters of the prototype. Note: the assumption is that
+      // we cannot have nested _ExtVector.
+      if (Current.starts_with("_ExtVector<")) {
+        const size_t EndTemplate = Current.find('>', 0);
+        ParseType(Current.substr(0, EndTemplate + 1));
+        // Move the prototype beyond _ExtVector<...>
+        I += EndTemplate + 1;
+        continue;
+      }
+
+      // We know that we are past _ExtVector, therefore the first seen
+      // comma is the boundary of a parameter in the prototype.
+      if (size_t CommaPos = Current.find(',', 0)) {
+        if (CommaPos != StringRef::npos) {
+          StringRef T = Current.substr(0, CommaPos);
+          ParseType(T);
+          // Move the prototype beyond the comma.
+          I += CommaPos + 1;
+          continue;
+        }
+      }
+
+      // No more commas, parse final parameter.
+      ParseType(Current);
+      I = end;
+    }
   }
 
   void ParseType(StringRef T) {
@@ -85,6 +123,23 @@ class PrototypeParser {
       if (Substitution.empty())
         PrintFatalError(Loc, "Not a template");
       ParseType(Substitution);
+    } else if (T.consume_front("_ExtVector")) {
+      // Clang extended vector types are mangled as follows:
+      //
+      // '_ExtVector<' <lanes> ',' <scalar type> '>'
+      if (!T.consume_front("<"))
+        PrintFatalError(Loc, "Expected '<' after '_ExtVector'");
+      unsigned long long Lanes;
+      if (llvm::consumeUnsignedInteger(T, 10, Lanes))
+        PrintFatalError(Loc, "Expected number of lanes after '_ExtVector<'");
+      Type += "E" + std::to_string(Lanes);
+      if (!T.consume_front(","))
+        PrintFatalError(Loc,
+                        "Expected ',' after number of lanes in '_ExtVector<'");
+      if (!T.consume_back(">"))
+        PrintFatalError(
+            Loc, "Expected '>' after scalar type in '_ExtVector<N, type>'");
+      ParseType(T);
     } else {
       auto ReturnTypeVal = StringSwitch<std::string>(T)
                                .Case("__builtin_va_list_ref", "A")

>From 380289e3a36b3523dcc4b98cdc5e11d19dde1ec4 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Mon, 4 Mar 2024 21:15:21 +0100
Subject: [PATCH 2/3] Add comment explaining what we are parsing when invoking
 ParseType on _ExtVector.

---
 clang/utils/TableGen/ClangBuiltinsEmitter.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 8790101c4a44e2..94f12a08164fdc 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -127,6 +127,9 @@ class PrototypeParser {
       // Clang extended vector types are mangled as follows:
       //
       // '_ExtVector<' <lanes> ',' <scalar type> '>'
+
+      // Before parsing T(=<scalar type>), make sure the syntax of
+      // `_ExtVector<N, T>` is correct...
       if (!T.consume_front("<"))
         PrintFatalError(Loc, "Expected '<' after '_ExtVector'");
       unsigned long long Lanes;
@@ -139,6 +142,8 @@ class PrototypeParser {
       if (!T.consume_back(">"))
         PrintFatalError(
             Loc, "Expected '>' after scalar type in '_ExtVector<N, type>'");
+
+      // ...all good, we can check if we have a valid `<scalar type>`.
       ParseType(T);
     } else {
       auto ReturnTypeVal = StringSwitch<std::string>(T)

>From 99bd4e9c41889c0223356e14fad405f40fc0f906 Mon Sep 17 00:00:00 2001
From: Francesco Petrogalli <francesco.petrogalli at apple.com>
Date: Mon, 4 Mar 2024 21:27:15 +0100
Subject: [PATCH 3/3] More test cases. NFC.

---
 .../target-builtins-prototype-parser.td       | 36 +++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/clang/test/TableGen/target-builtins-prototype-parser.td b/clang/test/TableGen/target-builtins-prototype-parser.td
index a6d0c98fa8bca2..3d6c92341ac43f 100644
--- a/clang/test/TableGen/target-builtins-prototype-parser.td
+++ b/clang/test/TableGen/target-builtins-prototype-parser.td
@@ -2,6 +2,10 @@
 // RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_LANES 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_LANES
 // RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_COMMA 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_COMMA
 // RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_TYPE 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_TYPE
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_A 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_A
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_B 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_B
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_C 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_C
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_D 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_D
 
 include "clang/Basic/BuiltinsBase.td"
 
@@ -77,3 +81,35 @@ def : Builtin {
 }
 #endif
 
+#ifdef ERROR_EXPECTED_A
+def : Builtin {
+// ERROR_EXPECTED_A: :[[# @LINE + 1]]:7: error: Expected '<' after '_ExtVector'
+  let Prototype = "_ExtVector(8, int) (double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_B
+def : Builtin {
+// ERROR_EXPECTED_B: :[[# @LINE + 1]]:7: error: Expected '<' after '_ExtVector'
+  let Prototype = "double(_ExtVector(8, int))";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_C
+def : Builtin {
+// ERROR_EXPECTED_C: :[[# @LINE + 1]]:7: error: Unknown Type: _EtxVector<8, int>
+  let Prototype = "_EtxVector<8, int>(void)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_D
+def : Builtin {
+// ERROR_EXPECTED_D: :[[# @LINE + 1]]:7: error: Expected number of lanes after '_ExtVector<'
+  let Prototype = "_ExtVector<>(void)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+



More information about the cfe-commits mailing list