blob: 2b491bad16128f2e5f20966b561f3dd179f0a704 [file] [log] [blame]
Ben Claytonb85e6922022-02-02 23:07:11 +00001{{- /*
2--------------------------------------------------------------------------------
3Template file for use with tools/builtin-gen to generate builtin_table.inl
4Used by BuiltinTable.cc for builtin overload resolution.
5
6See:
Ben Claytone1325162022-05-06 15:13:01 +00007* tools/cmd/intrinsic-gen/gen for structures used by this template
Ben Claytonb85e6922022-02-02 23:07:11 +00008* https://golang.org/pkg/text/template/ for documentation on the template syntax
9--------------------------------------------------------------------------------
10*/ -}}
11
12// clang-format off
13
14{{ with .Sem -}}
15{{ range .Types -}}
16{{ template "Type" . }}
17{{ end -}}
18{{ range .TypeMatchers -}}
19{{ template "TypeMatcher" . }}
20{{ end -}}
21{{ range .EnumMatchers -}}
22{{ template "EnumMatcher" . }}
23{{ end -}}
24{{- end -}}
25
Ben Claytone6e96de2022-05-09 18:08:23 +000026{{- with IntrinsicTable -}}
Ben Claytonb85e6922022-02-02 23:07:11 +000027{{- template "Matchers" . }}
28
29constexpr MatcherIndex kMatcherIndices[] = {
30{{- range $i, $idx := .MatcherIndices }}
31 /* [{{$i}}] */ {{$idx}},
32{{- end }}
33};
34
35// Assert that the MatcherIndex is big enough to index all the matchers, plus
36// kNoMatcher.
37static_assert(static_cast<int>(sizeof(kMatcherIndices) / sizeof(kMatcherIndices[0])) <
38 static_cast<int>(std::numeric_limits<MatcherIndex>::max() - 1),
39 "MatcherIndex is not large enough to index kMatcherIndices");
40
41constexpr ParameterInfo kParameters[] = {
42{{- range $i, $p := .Parameters }}
43 {
44 /* [{{$i}}] */
45 /* usage */ ParameterUsage::
46{{- if $p.Usage }}k{{PascalCase $p.Usage}}
47{{- else }}kNone
48{{- end }},
49 /* matcher indices */ &kMatcherIndices[{{$p.MatcherIndicesOffset}}],
50 },
51{{- end }}
52};
53
54constexpr OpenTypeInfo kOpenTypes[] = {
55{{- range $i, $o := .OpenTypes }}
56 {
57 /* [{{$i}}] */
58 /* name */ "{{$o.Name}}",
59 /* matcher index */
60{{- if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
61{{- else }} kNoMatcher
62{{- end }},
63 },
64{{- end }}
65};
66
67constexpr OpenNumberInfo kOpenNumbers[] = {
68{{- range $i, $o := .OpenNumbers }}
69 {
70 /* [{{$i}}] */
71 /* name */ "{{$o.Name}}",
72 /* matcher index */
73{{- if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
74{{- else }} kNoMatcher
75{{- end }},
76 },
77{{- end }}
78};
79
80constexpr OverloadInfo kOverloads[] = {
81{{- range $i, $o := .Overloads }}
82 {
83 /* [{{$i}}] */
84 /* num parameters */ {{$o.NumParameters}},
85 /* num open types */ {{$o.NumOpenTypes}},
86 /* num open numbers */ {{$o.NumOpenNumbers}},
87 /* open types */
88{{- if $o.OpenTypesOffset }} &kOpenTypes[{{$o.OpenTypesOffset}}],
89{{- else }} nullptr,
90{{- end }}
91 /* open numbers */
92{{- if $o.OpenNumbersOffset }} &kOpenNumbers[{{$o.OpenNumbersOffset}}]
93{{- else }} nullptr
94{{- end }},
95 /* parameters */ &kParameters[{{$o.ParametersOffset}}],
96 /* return matcher indices */
97{{- if $o.ReturnMatcherIndicesOffset }} &kMatcherIndices[{{$o.ReturnMatcherIndicesOffset}}]
98{{- else }} nullptr
99{{- end }},
100 /* supported_stages */ PipelineStageSet(
101{{- range $i, $u := $o.CanBeUsedInStage.List -}}
102{{- if $i -}}, {{end}}PipelineStage::k{{Title $u}}
103{{- end }}),
104 /* is_deprecated */ {{$o.IsDeprecated}},
105 },
106{{- end }}
107};
108
Ben Claytone6e96de2022-05-09 18:08:23 +0000109constexpr IntrinsicInfo kBuiltins[] = {
110{{- range $i, $b := .Builtins }}
Ben Claytonb85e6922022-02-02 23:07:11 +0000111 {
112 /* [{{$i}}] */
Ben Claytone6e96de2022-05-09 18:08:23 +0000113{{- range $b.OverloadDescriptions }}
Ben Claytonb85e6922022-02-02 23:07:11 +0000114 /* {{.}} */
115{{- end }}
Ben Claytone6e96de2022-05-09 18:08:23 +0000116 /* num overloads */ {{$b.NumOverloads}},
117 /* overloads */ &kOverloads[{{$b.OverloadsOffset}}],
Ben Claytonb85e6922022-02-02 23:07:11 +0000118 },
119{{- end }}
120};
121
Ben Clayton77473b42022-05-13 14:35:37 +0000122constexpr IntrinsicInfo kUnaryOperators[] = {
123{{- range $i, $o := .UnaryOperators }}
Ben Clayton9fb29a32022-05-09 20:00:13 +0000124 {
125 /* [{{$i}}] */
126{{- range $o.OverloadDescriptions }}
127 /* {{.}} */
128{{- end }}
129 /* num overloads */ {{$o.NumOverloads}},
130 /* overloads */ &kOverloads[{{$o.OverloadsOffset}}],
131 },
132{{- end }}
133};
134
Ben Clayton77473b42022-05-13 14:35:37 +0000135{{- range $i, $o := .UnaryOperators }}
136constexpr uint8_t kUnaryOperator{{template "OperatorName" $o.Name}} = {{$i}};
137{{- end }}
138
139constexpr IntrinsicInfo kBinaryOperators[] = {
140{{- range $i, $o := .BinaryOperators }}
141 {
142 /* [{{$i}}] */
143{{- range $o.OverloadDescriptions }}
144 /* {{.}} */
145{{- end }}
146 /* num overloads */ {{$o.NumOverloads}},
147 /* overloads */ &kOverloads[{{$o.OverloadsOffset}}],
148 },
149{{- end }}
150};
151
152{{- range $i, $o := .BinaryOperators }}
153constexpr uint8_t kBinaryOperator{{template "OperatorName" $o.Name}} = {{$i}};
Ben Clayton9fb29a32022-05-09 20:00:13 +0000154{{- end }}
155
Ben Claytonb85e6922022-02-02 23:07:11 +0000156// clang-format on
157{{ end -}}
158
159{{- /* ------------------------------------------------------------------ */ -}}
160{{- define "Type" -}}
161{{- /* ------------------------------------------------------------------ */ -}}
162{{- $class := PascalCase .Name -}}
163/// TypeMatcher for 'type {{.Name}}'
164{{- if .Decl.Source.S.Filepath }}
165/// @see {{.Decl.Source}}
166{{- end }}
167class {{$class}} : public TypeMatcher {
168 public:
169 /// Checks whether the given type matches the matcher rules.
170 /// Match may close open types and numbers in state.
171 /// @param state the MatchState
172 /// @param type the type to match
173 /// @returns the canonicalized type on match, otherwise nullptr
174 const sem::Type* Match(MatchState& state,
175 const sem::Type* type) const override;
176 /// @param state the MatchState
177 /// @return a string representation of the matcher.
178 std::string String(MatchState& state) const override;
179};
180
181const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
182{{- range .TemplateParams }}
183{{- template "DeclareLocalTemplateParam" . }}
184{{- end }}
185 if (!match_{{TrimLeft .Name "_"}}(ty{{range .TemplateParams}}, {{.GetName}}{{end}})) {
186 return nullptr;
187 }
188{{- range .TemplateParams }}
189 {{.Name}} = {{ template "MatchTemplateParam" .}}({{.Name}});
190 if ({{ template "IsTemplateParamInvalid" .}}) {
191 return nullptr;
192 }
193{{- end }}
194 return build_{{TrimLeft .Name "_"}}(state{{range .TemplateParams}}, {{.GetName}}{{end}});
195}
196
197std::string {{$class}}::String(MatchState&{{if .TemplateParams}} state{{end}}) const {
198{{- range .TemplateParams }}
199{{- template "DeclareLocalTemplateParamName" . }}
200{{- end }}
201
202{{- if .DisplayName }}
203 std::stringstream ss;
204 ss{{range SplitDisplayName .DisplayName}} << {{.}}{{end}};
205 return ss.str();
206{{- else if .TemplateParams }}
207 return "{{.Name}}<"{{template "AppendTemplateParamNames" .TemplateParams}} + ">";
208{{- else }}
209 return "{{.Name}}";
210{{- end }}
211}
212{{ end -}}
213
214{{- /* ------------------------------------------------------------------ */ -}}
215{{- define "TypeMatcher" -}}
216{{- /* ------------------------------------------------------------------ */ -}}
217{{- $class := PascalCase .Name -}}
218/// TypeMatcher for 'match {{.Name}}'
219{{- if .Decl.Source.S.Filepath }}
220/// @see {{.Decl.Source}}
221{{- end }}
222class {{$class}} : public TypeMatcher {
223 public:
224 /// Checks whether the given type matches the matcher rules, and returns the
225 /// expected, canonicalized type on success.
226 /// Match may close open types and numbers in state.
227 /// @param state the MatchState
228 /// @param type the type to match
229 /// @returns the canonicalized type on match, otherwise nullptr
230 const sem::Type* Match(MatchState& state,
231 const sem::Type* type) const override;
232 /// @param state the MatchState
233 /// @return a string representation of the matcher.
234 std::string String(MatchState& state) const override;
235};
236
237const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
238{{- range .Types }}
239 if (match_{{.Name}}(ty)) {
240 return build_{{.Name}}(state);
241 }
242{{- end }}
243 return nullptr;
244}
245
246std::string {{$class}}::String(MatchState&) const {
247 return "
248{{- range .Types -}}
249{{- if IsFirstIn . $.Types }}{{.Name}}
250{{- else if IsLastIn . $.Types }} or {{.Name}}
251{{- else }}, {{.Name}}
252{{- end -}}
253{{- end -}}
254 ";
255}
256{{ end -}}
257
258{{- /* ------------------------------------------------------------------ */ -}}
259{{- define "EnumMatcher" -}}
260{{- /* ------------------------------------------------------------------ */ -}}
261{{- $class := PascalCase .Name -}}
262{{- $enum := PascalCase .Enum.Name -}}
263/// EnumMatcher for 'match {{.Name}}'
264{{- if .Decl.Source.S.Filepath }}
265/// @see {{.Decl.Source}}
266{{- end }}
267class {{$class}} : public NumberMatcher {
268 public:
269 /// Checks whether the given number matches the enum matcher rules.
270 /// Match may close open types and numbers in state.
271 /// @param state the MatchState
272 /// @param number the enum value as a Number
273 /// @return true if the enum value matches the set
274 Number Match(MatchState& state, Number number) const override;
275 /// @param state the MatchState
276 /// @return a string representation of the matcher.
277 std::string String(MatchState& state) const override;
278};
279
280{{ if eq 1 (len .Options) -}}
281{{- $option := index .Options 0 }}
282{{- $entry := printf "k%v" (PascalCase $option.Name) -}}
283Number {{$class}}::Match(MatchState&, Number number) const {
284 if (number.IsAny() || number.Value() == static_cast<uint32_t>({{$enum}}::{{$entry}})) {
285 return Number(static_cast<uint32_t>({{$enum}}::{{$entry}}));
286 }
287 return Number::invalid;
288}
289{{- else -}}
290Number {{$class}}::Match(MatchState&, Number number) const {
291 switch (static_cast<{{$enum}}>(number.Value())) {
292{{- range .Options }}
293 case {{$enum}}::k{{PascalCase .Name}}:
294{{- end }}
295 return number;
296 default:
297 return Number::invalid;
298 }
299}
300{{- end }}
301
302std::string {{$class}}::String(MatchState&) const {
303 return "
304{{- range .Options -}}
305{{- if IsFirstIn . $.Options }}{{.Name}}
306{{- else if IsLastIn . $.Options }} or {{.Name}}
307{{- else }}, {{.Name}}
308{{- end -}}
309{{- end -}}
310";
311}
312{{ end -}}
313
314{{- /* ------------------------------------------------------------------ */ -}}
315{{- define "Matchers" -}}
316{{- /* ------------------------------------------------------------------ */ -}}
317/// Matchers holds type and number matchers
318class Matchers {
319 private:
320{{- $t_names := Map -}}
321{{- $n_names := Map -}}
322{{- range Iterate .Sem.MaxOpenTypes -}}
323{{- $name := printf "open_type_%v" . -}}
324{{- $t_names.Put . $name }}
325 OpenTypeMatcher {{$name}}_{ {{- . -}} };
326{{- end }}
327{{- range Iterate .Sem.MaxOpenNumbers -}}
328{{- $name := printf "open_number_%v" . -}}
329{{- $n_names.Put . $name }}
330 OpenNumberMatcher {{$name}}_{ {{- . -}} };
331{{- end }}
332{{- range .Sem.Types -}}
333{{- $name := PascalCase .Name -}}
334{{- $t_names.Put . $name }}
335 {{$name}} {{$name}}_;
336{{- end }}
337{{- range .Sem.TypeMatchers -}}
338{{- $name := PascalCase .Name -}}
339{{- $t_names.Put . $name }}
340 {{$name}} {{$name}}_;
341{{- end }}
342{{- range .Sem.EnumMatchers -}}
343{{- $name := PascalCase .Name -}}
344{{- $n_names.Put . $name }}
345 {{$name}} {{$name}}_;
346{{- end }}
347
348 public:
349 /// Constructor
350 Matchers();
351 /// Destructor
352 ~Matchers();
353
354 /// The open-types, types, and type matchers
355 TypeMatcher const* const type[{{len .TMatchers}}] = {
356{{- range $i, $m := .TMatchers }}
357 /* [{{$i}}] */
358{{- if $m }} &{{$t_names.Get $m}}_,
359{{- else }} &{{$t_names.Get $i}}_,
360{{- end }}
361{{- end }}
362 };
363
364 /// The open-numbers, and number matchers
365 NumberMatcher const* const number[{{len .NMatchers}}] = {
366{{- range $i, $m := .NMatchers }}
367 /* [{{$i}}] */
368{{- if $m }} &{{$n_names.Get $m}}_,
369{{- else }} &{{$n_names.Get $i}}_,
370{{- end }}
371{{- end }}
372 };
373};
374
375Matchers::Matchers() = default;
376Matchers::~Matchers() = default;
377{{- end -}}
378
379{{- /* ------------------------------------------------------------------ */ -}}
380{{- define "DeclareLocalTemplateParam" -}}
381{{- /* ------------------------------------------------------------------ */ -}}
382{{- if IsTemplateTypeParam . }}
383 const sem::Type* {{.Name}} = nullptr;
384{{- else if IsTemplateNumberParam . }}
385 Number {{.Name}} = Number::invalid;
386{{- else if IsTemplateEnumParam . }}
387 Number {{.Name}} = Number::invalid;
388{{- end -}}
389{{- end -}}
390
391{{- /* ------------------------------------------------------------------ */ -}}
392{{- define "DeclareLocalTemplateParamName" -}}
393{{- /* ------------------------------------------------------------------ */ -}}
394{{- if IsTemplateTypeParam . }}
395 const std::string {{.Name}} = state.TypeName();
396{{- else if IsTemplateNumberParam . }}
397 const std::string {{.Name}} = state.NumName();
398{{- else if IsTemplateEnumParam . }}
399 const std::string {{.Name}} = state.NumName();
400{{- end -}}
401{{- end -}}
402
403{{- /* ------------------------------------------------------------------ */ -}}
404{{- define "MatchTemplateParam" -}}
405{{- /* ------------------------------------------------------------------ */ -}}
406{{- if IsTemplateTypeParam . -}}
407 state.Type
408{{- else if IsTemplateNumberParam . -}}
409 state.Num
410{{- else if IsTemplateEnumParam . -}}
411 state.Num
412{{- end -}}
413{{- end -}}
414
415{{- /* ------------------------------------------------------------------ */ -}}
416{{- define "IsTemplateParamInvalid" -}}
417{{- /* ------------------------------------------------------------------ */ -}}
418{{- if IsTemplateTypeParam . -}}
419 {{.Name}} == nullptr
420{{- else if IsTemplateNumberParam . -}}
421 !{{.Name}}.IsValid()
422{{- else if IsTemplateEnumParam . -}}
423 !{{.Name}}.IsValid()
424{{- end -}}
425{{- end -}}
426
427{{- /* ------------------------------------------------------------------ */ -}}
428{{- define "AppendTemplateParamNames" -}}
429{{- /* ------------------------------------------------------------------ */ -}}
430{{- range $i, $ := . -}}
431{{- if $i }} + ", " + {{.Name}}
432{{- else }} + {{.Name}}
433{{- end -}}
434{{- end -}}
435{{- end -}}
Ben Clayton9fb29a32022-05-09 20:00:13 +0000436
437{{- /* ------------------------------------------------------------------ */ -}}
438{{- define "OperatorName" -}}
439{{- /* ------------------------------------------------------------------ */ -}}
440{{- if eq . "<<" -}}ShiftLeft
441{{- else if eq . "&" -}}And
442{{- else if eq . "|" -}}Or
443{{- else if eq . "^" -}}Xor
444{{- else if eq . "&&" -}}LogicalAnd
445{{- else if eq . "||" -}}LogicalOr
446{{- else if eq . "==" -}}Equal
Ben Claytonb61e0452022-05-09 21:22:24 +0000447{{- else if eq . "!" -}}Not
Ben Clayton9fb29a32022-05-09 20:00:13 +0000448{{- else if eq . "!=" -}}NotEqual
Ben Claytonb61e0452022-05-09 21:22:24 +0000449{{- else if eq . "~" -}}Complement
Ben Clayton9fb29a32022-05-09 20:00:13 +0000450{{- else if eq . "<" -}}LessThan
451{{- else if eq . ">" -}}GreaterThan
452{{- else if eq . "<=" -}}LessThanEqual
453{{- else if eq . ">=" -}}GreaterThanEqual
454{{- else if eq . "<<" -}}ShiftLeft
455{{- else if eq . ">>" -}}ShiftRight
456{{- else if eq . "+" -}}Plus
457{{- else if eq . "-" -}}Minus
458{{- else if eq . "*" -}}Star
459{{- else if eq . "/" -}}Divide
460{{- else if eq . "%" -}}Modulo
461{{- else -}}<unknown-{{.}}>
462{{- end -}}
463{{- end -}}