[clang] [Clang][TableGen] Support specifying address space in clang builtin prototypes (PR #108497)
Vikram Hegde via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 12 22:44:53 PDT 2024
https://github.com/vikramRH created https://github.com/llvm/llvm-project/pull/108497
this is a follow up from the discussion in https://github.com/llvm/llvm-project/pull/86801 (apologies for the long delay...).
This PR proposes a way to specify address spaces in builtin prototypes. The idea is to specify address space numbers using CXX11 attribute list syntax ([[<attr_list>]]) with following limitations,
1. The attribute [[addrspace[n]]] is strictly a "prefix" to the builtin type, i.e something as follows is not accepted,
int* const [[addrspace[3]]] ;
2. I really wanted the syntax to be like [[addrspace(n)]] but '(' token conflicts with function signature. so current approach is to use "[[addrspace[n]]]"
3. The attribute is only valid with pointer and reference types (as per the restriction imposed by .def files)
I would like some views on this approach and alternate suggestions if any. Also please let me know if there are any parallel efforts towards this which I might not be aware of.
>From 6afc2e91d8877cc330f6e317a404a74990d9c607 Mon Sep 17 00:00:00 2001
From: vikhegde <vikhegde at amd.com>
Date: Wed, 4 Sep 2024 10:34:54 +0000
Subject: [PATCH] [clang][TableGen] Support specifying address space in clang
builtin prototypes
---
.../target-builtins-prototype-parser.td | 71 +++++++++++++++++++
clang/utils/TableGen/ClangBuiltinsEmitter.cpp | 52 ++++++++++++--
2 files changed, 119 insertions(+), 4 deletions(-)
diff --git a/clang/test/TableGen/target-builtins-prototype-parser.td b/clang/test/TableGen/target-builtins-prototype-parser.td
index 555aebb3ccfb1f..dcff11046603ef 100644
--- a/clang/test/TableGen/target-builtins-prototype-parser.td
+++ b/clang/test/TableGen/target-builtins-prototype-parser.td
@@ -6,6 +6,12 @@
// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_B 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_B
// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_C 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_C
// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_D 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_D
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_E 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_E
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_F 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_F
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_G 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_G
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_H 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_H
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_I 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_I
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_J 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_J
include "clang/Basic/BuiltinsBase.td"
@@ -113,3 +119,68 @@ def : Builtin {
}
#endif
+def : Builtin {
+// CHECK: BUILTIN(__builtin_test_addrspace_attribute_01, "di*3", "")
+ let Prototype = "double( [[addrspace[3]]] int*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_01"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_test_addrspace_attribute_02, "Ii*5i*d", "")
+ let Prototype = "_Constant [[addrspace[5]]] int* (int*, double)";
+ let Spellings = ["__builtin_test_addrspace_attribute_02"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_test_addrspace_attribute_04, "Ii&4id*7", "")
+ let Prototype = "_Constant [[addrspace[4]]] int& (int , [[addrspace[7]]] double*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_04"];
+}
+
+#ifdef ERROR_EXPECTED_E
+def : Builtin {
+// ERROR_EXPECTED_E: :[[# @LINE + 1]]:7: error: Expected opening bracket '[' after 'addrspace'
+ let Prototype = "_Constant [[addrspace]] int& (int , double*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_04"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_F
+def : Builtin {
+// ERROR_EXPECTED_F: :[[# @LINE + 1]]:7: error: Address space attribute can only be specified with a pointer or reference type
+ let Prototype = "_Constant [[addrspace[4]]] int (int , double*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_04"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_G
+def : Builtin {
+// ERROR_EXPECTED_G: :[[# @LINE + 1]]:7: error: Expecetd valid integer for 'addrspace' attribute
+ let Prototype = "_Constant [[addrspace[k]]] int* (int , double*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_04"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_H
+def : Builtin {
+// ERROR_EXPECTED_H: :[[# @LINE + 1]]:7: error: Expected closing bracket ']' after address space specification
+ let Prototype = "_Constant [[addrspace[6 int* (int , double*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_04"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_I
+def : Builtin {
+// ERROR_EXPECTED_I: :[[# @LINE + 1]]:7: error: Expected closing brackets ']]' for attribute list
+ let Prototype = "_Constant [[addrspace[6] int* (int , double*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_04"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_J
+def : Builtin {
+// ERROR_EXPECTED_J: :[[# @LINE + 1]]:7: error: Unknown attribute name specified
+ let Prototype = "_Constant [[invalid]] int* (int , double*)";
+ let Spellings = ["__builtin_test_addrspace_attribute_04"];
+}
+#endif
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 4ae7600a392b8f..c088806795079c 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -40,9 +40,31 @@ class PrototypeParser {
ParseTypes(Prototype);
}
+ void ParseTypeAttributeList(StringRef &T, SMLoc Loc) {
+ if (T.consume_front("addrspace")) {
+ unsigned long long AS = 0;
+ if (!T.consume_front("["))
+ PrintFatalError(Loc, "Expected opening bracket '[' after 'addrspace'");
+
+ if (llvm::consumeUnsignedInteger(T, 10, AS))
+ PrintFatalError(Loc,
+ "Expecetd valid integer for 'addrspace' attribute");
+
+ if (!T.consume_front("]"))
+ PrintFatalError(
+ Loc,
+ "Expected closing bracket ']' after address space specification");
+ AddrSpace = AS;
+ } else
+ PrintFatalError(Loc, "Unknown attribute name specified");
+
+ if (!T.consume_front("]]"))
+ PrintFatalError(Loc, "Expected closing brackets ']]' for attribute list");
+ }
+
void ParseTypes(StringRef &Prototype) {
auto ReturnType = Prototype.take_until([](char c) { return c == '('; });
- ParseType(ReturnType);
+ ParseTypeAndValidateAttributes(ReturnType);
Prototype = Prototype.drop_front(ReturnType.size() + 1);
if (!Prototype.ends_with(")"))
PrintFatalError(Loc, "Expected closing brace at end of prototype");
@@ -66,7 +88,7 @@ class PrototypeParser {
// we cannot have nested _ExtVector.
if (Current.starts_with("_ExtVector<")) {
const size_t EndTemplate = Current.find('>', 0);
- ParseType(Current.substr(0, EndTemplate + 1));
+ ParseTypeAndValidateAttributes(Current.substr(0, EndTemplate + 1));
// Move the prototype beyond _ExtVector<...>
I += EndTemplate + 1;
continue;
@@ -77,7 +99,7 @@ class PrototypeParser {
if (size_t CommaPos = Current.find(',', 0)) {
if (CommaPos != StringRef::npos) {
StringRef T = Current.substr(0, CommaPos);
- ParseType(T);
+ ParseTypeAndValidateAttributes(T);
// Move the prototype beyond the comma.
I += CommaPos + 1;
continue;
@@ -85,16 +107,30 @@ class PrototypeParser {
}
// No more commas, parse final parameter.
- ParseType(Current);
+ ParseTypeAndValidateAttributes(Current);
I = end;
}
}
+ void ParseTypeAndValidateAttributes(StringRef T) {
+ ParseType(T);
+ if (!IsPointerOrReference && AddrSpace)
+ PrintFatalError(
+ Loc, "Address space attribute can only be specified with a pointer"
+ " or reference type");
+
+ IsPointerOrReference = false;
+ AddrSpace = std::nullopt;
+ }
+
void ParseType(StringRef T) {
T = T.trim();
if (T.consume_back("*")) {
ParseType(T);
Type += "*";
+ IsPointerOrReference = true;
+ if (AddrSpace)
+ Type += std::to_string(*AddrSpace);
} else if (T.consume_back("const")) {
ParseType(T);
Type += "C";
@@ -107,6 +143,12 @@ class PrototypeParser {
} else if (T.consume_back("&")) {
ParseType(T);
Type += "&";
+ IsPointerOrReference = true;
+ if (AddrSpace)
+ Type += std::to_string(*AddrSpace);
+ } else if (T.consume_front("[[")) {
+ ParseTypeAttributeList(T, Loc);
+ ParseType(T);
} else if (T.consume_front("long")) {
Type += "L";
ParseType(T);
@@ -193,6 +235,8 @@ class PrototypeParser {
SMLoc Loc;
StringRef Substitution;
std::string Type;
+ std::optional<unsigned long long> AddrSpace;
+ bool IsPointerOrReference = false;
};
class HeaderNameParser {
More information about the cfe-commits
mailing list