[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:18:35 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/2] [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/2] 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)
More information about the cfe-commits
mailing list