Skip to content

Commit 9b672de

Browse files
authored
[clang][Builtins] Parse clang extended vectors types. (#83584)
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>))) or template <unsigned N, class T> using _ExtVector __attribute__((ext_vector_type(N))) = T; For example: typedef double ext_vector_type_4_double __attribute__((ext_vector_type(4)))
1 parent 80f9458 commit 9b672de

File tree

2 files changed

+178
-3
lines changed

2 files changed

+178
-3
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// RUN: clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins | FileCheck %s
2+
// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_LANES 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_LANES
3+
// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_COMMA 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_COMMA
4+
// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_TYPE 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_TYPE
5+
// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_A 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_A
6+
// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_B 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_B
7+
// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_C 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_C
8+
// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_D 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_D
9+
10+
include "clang/Basic/BuiltinsBase.td"
11+
12+
def : Builtin {
13+
// CHECK: BUILTIN(__builtin_01, "E8idE4b", "")
14+
let Prototype = "_ExtVector<8,int>(double, _ExtVector<4, bool>)";
15+
let Spellings = ["__builtin_01"];
16+
}
17+
18+
def : Builtin {
19+
// CHECK: BUILTIN(__builtin_02, "E8UiE4s", "")
20+
let Prototype = "_ExtVector<8,unsigned int>(_ExtVector<4, short>)";
21+
let Spellings = ["__builtin_02"];
22+
}
23+
24+
def : Builtin {
25+
// CHECK: BUILTIN(__builtin_03, "di", "")
26+
let Prototype = "double(int)";
27+
let Spellings = ["__builtin_03"];
28+
}
29+
30+
def : Builtin {
31+
// CHECK: BUILTIN(__builtin_04, "diIUi", "")
32+
let Prototype = "double(int, _Constant unsigned int)";
33+
let Spellings = ["__builtin_04"];
34+
}
35+
36+
def : Builtin {
37+
// CHECK: BUILTIN(__builtin_05, "v&v&", "")
38+
let Prototype = "void&(void&)";
39+
let Spellings = ["__builtin_05"];
40+
}
41+
42+
def : Builtin {
43+
// CHECK: BUILTIN(__builtin_06, "v*v*cC*.", "")
44+
let Prototype = "void*(void*, char const*, ...)";
45+
let Spellings = ["__builtin_06"];
46+
}
47+
48+
def : Builtin {
49+
// CHECK: BUILTIN(__builtin_07, "E8iE4dE4b.", "")
50+
let Prototype = "_ExtVector<8, int>(_ExtVector<4,double>, _ExtVector<4, bool>, ...)";
51+
let Spellings = ["__builtin_07"];
52+
}
53+
54+
def : Builtin {
55+
// CHECK: BUILTIN(__builtin_08, "di*R", "")
56+
let Prototype = "double(int * restrict)";
57+
let Spellings = ["__builtin_08"];
58+
}
59+
60+
#ifdef ERROR_EXPECTED_LANES
61+
def : Builtin {
62+
// ERROR_EXPECTED_LANES: :[[# @LINE + 1]]:7: error: Expected number of lanes after '_ExtVector<'
63+
let Prototype = "_ExtVector<int>(double)";
64+
let Spellings = ["__builtin_test_use_clang_extended_vectors"];
65+
}
66+
#endif
67+
68+
#ifdef ERROR_EXPECTED_COMMA
69+
def : Builtin {
70+
// ERROR_EXPECTED_COMMA: :[[# @LINE + 1]]:7: error: Expected ',' after number of lanes in '_ExtVector<'
71+
let Prototype = "_ExtVector<8 int>(double)";
72+
let Spellings = ["__builtin_test_use_clang_extended_vectors"];
73+
}
74+
#endif
75+
76+
#ifdef ERROR_EXPECTED_TYPE
77+
def : Builtin {
78+
// ERROR_EXPECTED_TYPE: :[[# @LINE + 1]]:7: error: Expected '>' after scalar type in '_ExtVector<N, type>'
79+
let Prototype = "_ExtVector<8, int (double)";
80+
let Spellings = ["__builtin_test_use_clang_extended_vectors"];
81+
}
82+
#endif
83+
84+
#ifdef ERROR_EXPECTED_A
85+
def : Builtin {
86+
// ERROR_EXPECTED_A: :[[# @LINE + 1]]:7: error: Expected '<' after '_ExtVector'
87+
let Prototype = "_ExtVector(8, int) (double)";
88+
let Spellings = ["__builtin_test_use_clang_extended_vectors"];
89+
}
90+
#endif
91+
92+
#ifdef ERROR_EXPECTED_B
93+
def : Builtin {
94+
// ERROR_EXPECTED_B: :[[# @LINE + 1]]:7: error: Expected '<' after '_ExtVector'
95+
let Prototype = "double(_ExtVector(8, int))";
96+
let Spellings = ["__builtin_test_use_clang_extended_vectors"];
97+
}
98+
#endif
99+
100+
#ifdef ERROR_EXPECTED_C
101+
def : Builtin {
102+
// ERROR_EXPECTED_C: :[[# @LINE + 1]]:7: error: Unknown Type: _EtxVector<8, int>
103+
let Prototype = "_EtxVector<8, int>(void)";
104+
let Spellings = ["__builtin_test_use_clang_extended_vectors"];
105+
}
106+
#endif
107+
108+
#ifdef ERROR_EXPECTED_D
109+
def : Builtin {
110+
// ERROR_EXPECTED_D: :[[# @LINE + 1]]:7: error: Expected number of lanes after '_ExtVector<'
111+
let Prototype = "_ExtVector<>(void)";
112+
let Spellings = ["__builtin_test_use_clang_extended_vectors"];
113+
}
114+
#endif
115+

clang/utils/TableGen/ClangBuiltinsEmitter.cpp

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,47 @@ class PrototypeParser {
4747
if (!Prototype.ends_with(")"))
4848
PrintFatalError(Loc, "Expected closing brace at end of prototype");
4949
Prototype = Prototype.drop_back();
50-
for (auto T = Prototype.split(','); !T.first.empty();
51-
Prototype = T.second, T = Prototype.split(','))
52-
ParseType(T.first);
50+
51+
// Look through the input parameters.
52+
const size_t end = Prototype.size();
53+
for (size_t I = 0; I != end;) {
54+
const StringRef Current = Prototype.substr(I, end);
55+
// Skip any leading space or commas
56+
if (Current.starts_with(" ") || Current.starts_with(",")) {
57+
++I;
58+
continue;
59+
}
60+
61+
// Check if we are in _ExtVector. We do this first because
62+
// extended vectors are written in template form with the syntax
63+
// _ExtVector< ..., ...>, so we need to make sure we are not
64+
// detecting the comma of the template class as a separator for
65+
// the parameters of the prototype. Note: the assumption is that
66+
// we cannot have nested _ExtVector.
67+
if (Current.starts_with("_ExtVector<")) {
68+
const size_t EndTemplate = Current.find('>', 0);
69+
ParseType(Current.substr(0, EndTemplate + 1));
70+
// Move the prototype beyond _ExtVector<...>
71+
I += EndTemplate + 1;
72+
continue;
73+
}
74+
75+
// We know that we are past _ExtVector, therefore the first seen
76+
// comma is the boundary of a parameter in the prototype.
77+
if (size_t CommaPos = Current.find(',', 0)) {
78+
if (CommaPos != StringRef::npos) {
79+
StringRef T = Current.substr(0, CommaPos);
80+
ParseType(T);
81+
// Move the prototype beyond the comma.
82+
I += CommaPos + 1;
83+
continue;
84+
}
85+
}
86+
87+
// No more commas, parse final parameter.
88+
ParseType(Current);
89+
I = end;
90+
}
5391
}
5492

5593
void ParseType(StringRef T) {
@@ -85,6 +123,28 @@ class PrototypeParser {
85123
if (Substitution.empty())
86124
PrintFatalError(Loc, "Not a template");
87125
ParseType(Substitution);
126+
} else if (T.consume_front("_ExtVector")) {
127+
// Clang extended vector types are mangled as follows:
128+
//
129+
// '_ExtVector<' <lanes> ',' <scalar type> '>'
130+
131+
// Before parsing T(=<scalar type>), make sure the syntax of
132+
// `_ExtVector<N, T>` is correct...
133+
if (!T.consume_front("<"))
134+
PrintFatalError(Loc, "Expected '<' after '_ExtVector'");
135+
unsigned long long Lanes;
136+
if (llvm::consumeUnsignedInteger(T, 10, Lanes))
137+
PrintFatalError(Loc, "Expected number of lanes after '_ExtVector<'");
138+
Type += "E" + std::to_string(Lanes);
139+
if (!T.consume_front(","))
140+
PrintFatalError(Loc,
141+
"Expected ',' after number of lanes in '_ExtVector<'");
142+
if (!T.consume_back(">"))
143+
PrintFatalError(
144+
Loc, "Expected '>' after scalar type in '_ExtVector<N, type>'");
145+
146+
// ...all good, we can check if we have a valid `<scalar type>`.
147+
ParseType(T);
88148
} else {
89149
auto ReturnTypeVal = StringSwitch<std::string>(T)
90150
.Case("__builtin_va_list_ref", "A")

0 commit comments

Comments
 (0)