| {{- /* |
| -------------------------------------------------------------------------------- |
| Template file for use with tools/intrinsic-gen to generate intrinsic_table.inl |
| Used by IntrinsicTable.cc for intrinsic overload resolution. |
| |
| See: |
| * tools/cmd/intrinsic-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 IntrinsicTable -}} |
| {{- 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 IntrinsicInfo kIntrinsics[] = { |
| {{- 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_{{.Name}}(ty{{range .TemplateParams}}, {{.GetName}}{{end}})) { |
| return nullptr; |
| } |
| {{- range .TemplateParams }} |
| {{.Name}} = {{ template "MatchTemplateParam" .}}({{.Name}}); |
| if ({{ template "IsTemplateParamInvalid" .}}) { |
| return nullptr; |
| } |
| {{- end }} |
| return build_{{.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 -}} |