blob: b7604b84a9b8b8476a9bb62c6c063ebdd09b97bd [file] [log] [blame]
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/builtin-gen to generate builtin_table.inl
Used by BuiltinTable.cc for builtin overload resolution.
See:
* tools/cmd/builtin-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
// clang-format off
{{ with .Sem -}}
{{ range .Types -}}
{{ template "Type" . }}
{{ end -}}
{{ range .TypeMatchers -}}
{{ template "TypeMatcher" . }}
{{ end -}}
{{ range .EnumMatchers -}}
{{ template "EnumMatcher" . }}
{{ end -}}
{{- end -}}
{{- with BuiltinTable -}}
{{- template "Matchers" . }}
constexpr MatcherIndex kMatcherIndices[] = {
{{- range $i, $idx := .MatcherIndices }}
/* [{{$i}}] */ {{$idx}},
{{- end }}
};
// Assert that the MatcherIndex is big enough to index all the matchers, plus
// kNoMatcher.
static_assert(static_cast<int>(sizeof(kMatcherIndices) / sizeof(kMatcherIndices[0])) <
static_cast<int>(std::numeric_limits<MatcherIndex>::max() - 1),
"MatcherIndex is not large enough to index kMatcherIndices");
constexpr ParameterInfo kParameters[] = {
{{- range $i, $p := .Parameters }}
{
/* [{{$i}}] */
/* usage */ ParameterUsage::
{{- if $p.Usage }}k{{PascalCase $p.Usage}}
{{- else }}kNone
{{- end }},
/* matcher indices */ &kMatcherIndices[{{$p.MatcherIndicesOffset}}],
},
{{- end }}
};
constexpr OpenTypeInfo kOpenTypes[] = {
{{- range $i, $o := .OpenTypes }}
{
/* [{{$i}}] */
/* name */ "{{$o.Name}}",
/* matcher index */
{{- if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
{{- else }} kNoMatcher
{{- end }},
},
{{- end }}
};
constexpr OpenNumberInfo kOpenNumbers[] = {
{{- range $i, $o := .OpenNumbers }}
{
/* [{{$i}}] */
/* name */ "{{$o.Name}}",
/* matcher index */
{{- if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
{{- else }} kNoMatcher
{{- end }},
},
{{- end }}
};
constexpr OverloadInfo kOverloads[] = {
{{- range $i, $o := .Overloads }}
{
/* [{{$i}}] */
/* num parameters */ {{$o.NumParameters}},
/* num open types */ {{$o.NumOpenTypes}},
/* num open numbers */ {{$o.NumOpenNumbers}},
/* open types */
{{- if $o.OpenTypesOffset }} &kOpenTypes[{{$o.OpenTypesOffset}}],
{{- else }} nullptr,
{{- end }}
/* open numbers */
{{- if $o.OpenNumbersOffset }} &kOpenNumbers[{{$o.OpenNumbersOffset}}]
{{- else }} nullptr
{{- end }},
/* parameters */ &kParameters[{{$o.ParametersOffset}}],
/* return matcher indices */
{{- if $o.ReturnMatcherIndicesOffset }} &kMatcherIndices[{{$o.ReturnMatcherIndicesOffset}}]
{{- else }} nullptr
{{- end }},
/* supported_stages */ PipelineStageSet(
{{- range $i, $u := $o.CanBeUsedInStage.List -}}
{{- if $i -}}, {{end}}PipelineStage::k{{Title $u}}
{{- end }}),
/* is_deprecated */ {{$o.IsDeprecated}},
},
{{- end }}
};
constexpr BuiltinInfo kBuiltins[] = {
{{- range $i, $f := .Functions }}
{
/* [{{$i}}] */
{{- range $f.OverloadDescriptions }}
/* {{.}} */
{{- end }}
/* num overloads */ {{$f.NumOverloads}},
/* overloads */ &kOverloads[{{$f.OverloadsOffset}}],
},
{{- end }}
};
// clang-format on
{{ end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "Type" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $class := PascalCase .Name -}}
/// TypeMatcher for 'type {{.Name}}'
{{- if .Decl.Source.S.Filepath }}
/// @see {{.Decl.Source}}
{{- end }}
class {{$class}} : public TypeMatcher {
public:
/// Checks whether the given type matches the matcher rules.
/// Match may close open types and numbers in state.
/// @param state the MatchState
/// @param type the type to match
/// @returns the canonicalized type on match, otherwise nullptr
const sem::Type* Match(MatchState& state,
const sem::Type* type) const override;
/// @param state the MatchState
/// @return a string representation of the matcher.
std::string String(MatchState& state) const override;
};
const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
{{- range .TemplateParams }}
{{- template "DeclareLocalTemplateParam" . }}
{{- end }}
if (!match_{{TrimLeft .Name "_"}}(ty{{range .TemplateParams}}, {{.GetName}}{{end}})) {
return nullptr;
}
{{- range .TemplateParams }}
{{.Name}} = {{ template "MatchTemplateParam" .}}({{.Name}});
if ({{ template "IsTemplateParamInvalid" .}}) {
return nullptr;
}
{{- end }}
return build_{{TrimLeft .Name "_"}}(state{{range .TemplateParams}}, {{.GetName}}{{end}});
}
std::string {{$class}}::String(MatchState&{{if .TemplateParams}} state{{end}}) const {
{{- range .TemplateParams }}
{{- template "DeclareLocalTemplateParamName" . }}
{{- end }}
{{- if .DisplayName }}
std::stringstream ss;
ss{{range SplitDisplayName .DisplayName}} << {{.}}{{end}};
return ss.str();
{{- else if .TemplateParams }}
return "{{.Name}}<"{{template "AppendTemplateParamNames" .TemplateParams}} + ">";
{{- else }}
return "{{.Name}}";
{{- end }}
}
{{ end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "TypeMatcher" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $class := PascalCase .Name -}}
/// TypeMatcher for 'match {{.Name}}'
{{- if .Decl.Source.S.Filepath }}
/// @see {{.Decl.Source}}
{{- end }}
class {{$class}} : public TypeMatcher {
public:
/// Checks whether the given type matches the matcher rules, and returns the
/// expected, canonicalized type on success.
/// Match may close open types and numbers in state.
/// @param state the MatchState
/// @param type the type to match
/// @returns the canonicalized type on match, otherwise nullptr
const sem::Type* Match(MatchState& state,
const sem::Type* type) const override;
/// @param state the MatchState
/// @return a string representation of the matcher.
std::string String(MatchState& state) const override;
};
const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
{{- range .Types }}
if (match_{{.Name}}(ty)) {
return build_{{.Name}}(state);
}
{{- end }}
return nullptr;
}
std::string {{$class}}::String(MatchState&) const {
return "
{{- range .Types -}}
{{- if IsFirstIn . $.Types }}{{.Name}}
{{- else if IsLastIn . $.Types }} or {{.Name}}
{{- else }}, {{.Name}}
{{- end -}}
{{- end -}}
";
}
{{ end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "EnumMatcher" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $class := PascalCase .Name -}}
{{- $enum := PascalCase .Enum.Name -}}
/// EnumMatcher for 'match {{.Name}}'
{{- if .Decl.Source.S.Filepath }}
/// @see {{.Decl.Source}}
{{- end }}
class {{$class}} : public NumberMatcher {
public:
/// Checks whether the given number matches the enum matcher rules.
/// Match may close open types and numbers in state.
/// @param state the MatchState
/// @param number the enum value as a Number
/// @return true if the enum value matches the set
Number Match(MatchState& state, Number number) const override;
/// @param state the MatchState
/// @return a string representation of the matcher.
std::string String(MatchState& state) const override;
};
{{ if eq 1 (len .Options) -}}
{{- $option := index .Options 0 }}
{{- $entry := printf "k%v" (PascalCase $option.Name) -}}
Number {{$class}}::Match(MatchState&, Number number) const {
if (number.IsAny() || number.Value() == static_cast<uint32_t>({{$enum}}::{{$entry}})) {
return Number(static_cast<uint32_t>({{$enum}}::{{$entry}}));
}
return Number::invalid;
}
{{- else -}}
Number {{$class}}::Match(MatchState&, Number number) const {
switch (static_cast<{{$enum}}>(number.Value())) {
{{- range .Options }}
case {{$enum}}::k{{PascalCase .Name}}:
{{- end }}
return number;
default:
return Number::invalid;
}
}
{{- end }}
std::string {{$class}}::String(MatchState&) const {
return "
{{- range .Options -}}
{{- if IsFirstIn . $.Options }}{{.Name}}
{{- else if IsLastIn . $.Options }} or {{.Name}}
{{- else }}, {{.Name}}
{{- end -}}
{{- end -}}
";
}
{{ end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "Matchers" -}}
{{- /* ------------------------------------------------------------------ */ -}}
/// Matchers holds type and number matchers
class Matchers {
private:
{{- $t_names := Map -}}
{{- $n_names := Map -}}
{{- range Iterate .Sem.MaxOpenTypes -}}
{{- $name := printf "open_type_%v" . -}}
{{- $t_names.Put . $name }}
OpenTypeMatcher {{$name}}_{ {{- . -}} };
{{- end }}
{{- range Iterate .Sem.MaxOpenNumbers -}}
{{- $name := printf "open_number_%v" . -}}
{{- $n_names.Put . $name }}
OpenNumberMatcher {{$name}}_{ {{- . -}} };
{{- end }}
{{- range .Sem.Types -}}
{{- $name := PascalCase .Name -}}
{{- $t_names.Put . $name }}
{{$name}} {{$name}}_;
{{- end }}
{{- range .Sem.TypeMatchers -}}
{{- $name := PascalCase .Name -}}
{{- $t_names.Put . $name }}
{{$name}} {{$name}}_;
{{- end }}
{{- range .Sem.EnumMatchers -}}
{{- $name := PascalCase .Name -}}
{{- $n_names.Put . $name }}
{{$name}} {{$name}}_;
{{- end }}
public:
/// Constructor
Matchers();
/// Destructor
~Matchers();
/// The open-types, types, and type matchers
TypeMatcher const* const type[{{len .TMatchers}}] = {
{{- range $i, $m := .TMatchers }}
/* [{{$i}}] */
{{- if $m }} &{{$t_names.Get $m}}_,
{{- else }} &{{$t_names.Get $i}}_,
{{- end }}
{{- end }}
};
/// The open-numbers, and number matchers
NumberMatcher const* const number[{{len .NMatchers}}] = {
{{- range $i, $m := .NMatchers }}
/* [{{$i}}] */
{{- if $m }} &{{$n_names.Get $m}}_,
{{- else }} &{{$n_names.Get $i}}_,
{{- end }}
{{- end }}
};
};
Matchers::Matchers() = default;
Matchers::~Matchers() = default;
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "DeclareLocalTemplateParam" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- if IsTemplateTypeParam . }}
const sem::Type* {{.Name}} = nullptr;
{{- else if IsTemplateNumberParam . }}
Number {{.Name}} = Number::invalid;
{{- else if IsTemplateEnumParam . }}
Number {{.Name}} = Number::invalid;
{{- end -}}
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "DeclareLocalTemplateParamName" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- if IsTemplateTypeParam . }}
const std::string {{.Name}} = state.TypeName();
{{- else if IsTemplateNumberParam . }}
const std::string {{.Name}} = state.NumName();
{{- else if IsTemplateEnumParam . }}
const std::string {{.Name}} = state.NumName();
{{- end -}}
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "MatchTemplateParam" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- if IsTemplateTypeParam . -}}
state.Type
{{- else if IsTemplateNumberParam . -}}
state.Num
{{- else if IsTemplateEnumParam . -}}
state.Num
{{- end -}}
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "IsTemplateParamInvalid" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- if IsTemplateTypeParam . -}}
{{.Name}} == nullptr
{{- else if IsTemplateNumberParam . -}}
!{{.Name}}.IsValid()
{{- else if IsTemplateEnumParam . -}}
!{{.Name}}.IsValid()
{{- end -}}
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "AppendTemplateParamNames" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- range $i, $ := . -}}
{{- if $i }} + ", " + {{.Name}}
{{- else }} + {{.Name}}
{{- end -}}
{{- end -}}
{{- end -}}