[clang] [Clang][TableGen] Support specifying address space in clang builtin prototypes (PR #108497)
Vikram Hegde via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 27 02:22:02 PDT 2024
https://github.com/vikramRH updated https://github.com/llvm/llvm-project/pull/108497
>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 1/2] [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 {
>From 5ab4003804653cdf3d87048c43bd839ef84b18a9 Mon Sep 17 00:00:00 2001
From: vikhegde <vikhegde at amd.com>
Date: Tue, 24 Sep 2024 10:39:31 +0000
Subject: [PATCH 2/2] design changes according to review comments
---
clang/include/clang/Basic/BuiltinsBase.td | 7 +++
.../target-builtins-prototype-parser.td | 57 ++++-------------
clang/utils/TableGen/ClangBuiltinsEmitter.cpp | 63 +++++++++----------
3 files changed, 51 insertions(+), 76 deletions(-)
diff --git a/clang/include/clang/Basic/BuiltinsBase.td b/clang/include/clang/Basic/BuiltinsBase.td
index 58dee22fc0a450..e7629e944c143c 100644
--- a/clang/include/clang/Basic/BuiltinsBase.td
+++ b/clang/include/clang/Basic/BuiltinsBase.td
@@ -73,6 +73,13 @@ def Constexpr : Attribute<"E">;
// Builtin is immediate and must be constant evaluated. Implies Constexpr, and will only be supported in C++20 mode.
def Consteval : Attribute<"EG">;
+// Address space attribute, only valid for pointer or reference arguments.
+// ArgIdx - argument to which the attribute refers. value 0 is for return type.
+// AddrSpaceNum - Address space number for the argument.
+class AddressSpace<int ArgIdx, int AddrSpaceNum> : IndexedAttribute<"", ArgIdx> {
+ int SpaceNum = AddrSpaceNum;
+}
+
// Builtin kinds
// =============
diff --git a/clang/test/TableGen/target-builtins-prototype-parser.td b/clang/test/TableGen/target-builtins-prototype-parser.td
index dcff11046603ef..0c4494a02b546c 100644
--- a/clang/test/TableGen/target-builtins-prototype-parser.td
+++ b/clang/test/TableGen/target-builtins-prototype-parser.td
@@ -8,10 +8,6 @@
// 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"
@@ -121,66 +117,39 @@ def : Builtin {
def : Builtin {
// CHECK: BUILTIN(__builtin_test_addrspace_attribute_01, "di*3", "")
- let Prototype = "double( [[addrspace[3]]] int*)";
+ let Prototype = "double(int*)";
let Spellings = ["__builtin_test_addrspace_attribute_01"];
+ let Attributes = [AddressSpace<1, 3>];
}
def : Builtin {
-// CHECK: BUILTIN(__builtin_test_addrspace_attribute_02, "Ii*5i*d", "")
- let Prototype = "_Constant [[addrspace[5]]] int* (int*, double)";
+// CHECK: BUILTIN(__builtin_test_addrspace_attribute_02, "Ii*5i*d", "n")
+ let Prototype = "_Constant int* (int*, double)";
let Spellings = ["__builtin_test_addrspace_attribute_02"];
+ let Attributes = [AddressSpace<0, 5>, NoThrow];
}
def : Builtin {
-// CHECK: BUILTIN(__builtin_test_addrspace_attribute_04, "Ii&4id*7", "")
- let Prototype = "_Constant [[addrspace[4]]] int& (int , [[addrspace[7]]] double*)";
+// CHECK: BUILTIN(__builtin_test_addrspace_attribute_04, "Ii&4id*7", "En")
+ let Prototype = "_Constant int& (int , double*)";
let Spellings = ["__builtin_test_addrspace_attribute_04"];
+ let Attributes = [AddressSpace<0, 4>, Constexpr, AddressSpace<2, 7>, NoThrow];
}
#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*)";
+// ERROR_EXPECTED_E: :[[# @LINE + 1]]:7: error: Address space attribute for argument 2 repeated
+ let Prototype = "_Constant int& (int , double*)";
let Spellings = ["__builtin_test_addrspace_attribute_04"];
+ let Attributes = [AddressSpace<2, 4>, AddressSpace<2, 7>];
}
#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 Prototype = "_Constant int (int , double*)";
let Spellings = ["__builtin_test_addrspace_attribute_04"];
+ let Attributes = [AddressSpace<1, 7>];
}
#endif
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index c088806795079c..3d5a6f7adc7a09 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -31,6 +31,7 @@ class PrototypeParser {
public:
PrototypeParser(StringRef Substitution, const Record *Builtin)
: Loc(Builtin->getFieldLoc("Prototype")), Substitution(Substitution) {
+ populateAddrSpaceAttrMap(Builtin);
ParsePrototype(Builtin->getValueAsString("Prototype"));
}
@@ -40,31 +41,22 @@ 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 populateAddrSpaceAttrMap(const Record *Builtin) {
+ for (const auto *Attr : Builtin->getValueAsListOfDefs("Attributes")) {
+ if (Attr->isSubClassOf("AddressSpace")) {
+ uint32_t ArgIdx = Attr->getValueAsInt("Index");
+ uint32_t ASpaceNum = Attr->getValueAsInt("SpaceNum");
+ if (ArgToAddrSpaceMap.find(ArgIdx) != ArgToAddrSpaceMap.end())
+ PrintFatalError(Loc, "Address space attribute for argument " +
+ std::to_string(ArgIdx) + " repeated");
+ ArgToAddrSpaceMap[ArgIdx] = ASpaceNum;
+ }
+ }
}
void ParseTypes(StringRef &Prototype) {
auto ReturnType = Prototype.take_until([](char c) { return c == '('; });
- ParseTypeAndValidateAttributes(ReturnType);
+ ParseTypeAndValidateAttributes(ReturnType, /*Return type ID*/ 0);
Prototype = Prototype.drop_front(ReturnType.size() + 1);
if (!Prototype.ends_with(")"))
PrintFatalError(Loc, "Expected closing brace at end of prototype");
@@ -72,7 +64,7 @@ class PrototypeParser {
// Look through the input parameters.
const size_t end = Prototype.size();
- for (size_t I = 0; I != end;) {
+ for (size_t I = 0, CurArgIdx = 1; I != end;) {
const StringRef Current = Prototype.substr(I, end);
// Skip any leading space or commas
if (Current.starts_with(" ") || Current.starts_with(",")) {
@@ -88,9 +80,11 @@ class PrototypeParser {
// we cannot have nested _ExtVector.
if (Current.starts_with("_ExtVector<")) {
const size_t EndTemplate = Current.find('>', 0);
- ParseTypeAndValidateAttributes(Current.substr(0, EndTemplate + 1));
+ ParseTypeAndValidateAttributes(Current.substr(0, EndTemplate + 1),
+ CurArgIdx);
// Move the prototype beyond _ExtVector<...>
I += EndTemplate + 1;
+ CurArgIdx++;
continue;
}
@@ -99,28 +93,31 @@ class PrototypeParser {
if (size_t CommaPos = Current.find(',', 0)) {
if (CommaPos != StringRef::npos) {
StringRef T = Current.substr(0, CommaPos);
- ParseTypeAndValidateAttributes(T);
+ ParseTypeAndValidateAttributes(T, CurArgIdx);
// Move the prototype beyond the comma.
I += CommaPos + 1;
+ CurArgIdx++;
continue;
}
}
// No more commas, parse final parameter.
- ParseTypeAndValidateAttributes(Current);
+ ParseTypeAndValidateAttributes(Current, CurArgIdx);
I = end;
}
}
- void ParseTypeAndValidateAttributes(StringRef T) {
+ void ParseTypeAndValidateAttributes(StringRef T, uint32_t ArgIdx) {
+ if (ArgToAddrSpaceMap.find(ArgIdx) != ArgToAddrSpaceMap.end())
+ AddrSpace = ArgToAddrSpaceMap[ArgIdx];
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;
+ IsPointerOrReference = false;
}
void ParseType(StringRef T) {
@@ -146,9 +143,6 @@ class PrototypeParser {
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);
@@ -235,7 +229,8 @@ class PrototypeParser {
SMLoc Loc;
StringRef Substitution;
std::string Type;
- std::optional<unsigned long long> AddrSpace;
+ std::unordered_map<uint32_t, uint32_t> ArgToAddrSpaceMap;
+ std::optional<uint32_t> AddrSpace;
bool IsPointerOrReference = false;
};
@@ -279,8 +274,12 @@ void PrintAttributes(const Record *Builtin, BuiltinType BT,
for (const auto *Attr : Builtin->getValueAsListOfDefs("Attributes")) {
OS << Attr->getValueAsString("Mangling");
- if (Attr->isSubClassOf("IndexedAttribute"))
+ if (Attr->isSubClassOf("IndexedAttribute")) {
+ // Address space attributes are already processed
+ if (Attr->isSubClassOf("AddressSpace"))
+ continue;
OS << ':' << Attr->getValueAsInt("Index") << ':';
+ }
}
OS << '\"';
}
More information about the cfe-commits
mailing list