| {{- /* |
| -------------------------------------------------------------------------------- |
| Template file for use with tools/builtin-gen to generate builtin_table.inl |
| Used by BuiltinTable.cc for builtin 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 TemplateTypeInfo kTemplateTypes[] = { |
| {{- range $i, $o := .TemplateTypes }} |
| { |
| /* [{{$i}}] */ |
| /* name */ "{{$o.Name}}", |
| /* matcher index */ |
| {{- if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}} |
| {{- else }} kNoMatcher |
| {{- end }}, |
| }, |
| {{- end }} |
| }; |
| |
| constexpr TemplateNumberInfo kTemplateNumbers[] = { |
| {{- range $i, $o := .TemplateNumbers }} |
| { |
| /* [{{$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 template types */ {{$o.NumTemplateTypes}}, |
| /* num template numbers */ {{$o.NumTemplateNumbers}}, |
| /* template types */ |
| {{- if $o.TemplateTypesOffset }} &kTemplateTypes[{{$o.TemplateTypesOffset}}], |
| {{- else }} nullptr, |
| {{- end }} |
| /* template numbers */ |
| {{- if $o.TemplateNumbersOffset }} &kTemplateNumbers[{{$o.TemplateNumbersOffset}}] |
| {{- else }} nullptr |
| {{- end }}, |
| /* parameters */ &kParameters[{{$o.ParametersOffset}}], |
| /* return matcher indices */ |
| {{- if $o.ReturnMatcherIndicesOffset }} &kMatcherIndices[{{$o.ReturnMatcherIndicesOffset}}] |
| {{- else }} nullptr |
| {{- end }}, |
| /* flags */ OverloadFlags(OverloadFlag::kIs{{Title $o.Kind}} |
| {{- range $i, $u := $o.CanBeUsedInStage.List -}} |
| , OverloadFlag::kSupports{{Title $u}}Pipeline |
| {{- end }} |
| {{- if $o.IsDeprecated}}, OverloadFlag::kIsDeprecated{{end }}), |
| /* const eval */ |
| {{- if $o.ConstEvalFunction }} const_eval::{{$o.ConstEvalFunction}}, |
| {{- else }} nullptr, |
| {{- end }} |
| }, |
| {{- end }} |
| }; |
| |
| constexpr IntrinsicInfo kBuiltins[] = { |
| {{- range $i, $b := .Builtins }} |
| { |
| /* [{{$i}}] */ |
| {{- range $b.OverloadDescriptions }} |
| /* {{.}} */ |
| {{- end }} |
| /* num overloads */ {{$b.NumOverloads}}, |
| /* overloads */ &kOverloads[{{$b.OverloadsOffset}}], |
| }, |
| {{- end }} |
| }; |
| |
| constexpr IntrinsicInfo kUnaryOperators[] = { |
| {{- range $i, $o := .UnaryOperators }} |
| { |
| /* [{{$i}}] */ |
| {{- range $o.OverloadDescriptions }} |
| /* {{.}} */ |
| {{- end }} |
| /* num overloads */ {{$o.NumOverloads}}, |
| /* overloads */ &kOverloads[{{$o.OverloadsOffset}}], |
| }, |
| {{- end }} |
| }; |
| |
| {{- range $i, $o := .UnaryOperators }} |
| constexpr uint8_t kUnaryOperator{{template "OperatorName" $o.Name}} = {{$i}}; |
| {{- end }} |
| |
| constexpr IntrinsicInfo kBinaryOperators[] = { |
| {{- range $i, $o := .BinaryOperators }} |
| { |
| /* [{{$i}}] */ |
| {{- range $o.OverloadDescriptions }} |
| /* {{.}} */ |
| {{- end }} |
| /* num overloads */ {{$o.NumOverloads}}, |
| /* overloads */ &kOverloads[{{$o.OverloadsOffset}}], |
| }, |
| {{- end }} |
| }; |
| |
| {{- range $i, $o := .BinaryOperators }} |
| constexpr uint8_t kBinaryOperator{{template "OperatorName" $o.Name}} = {{$i}}; |
| {{- end }} |
| |
| constexpr IntrinsicInfo kConstructorsAndConverters[] = { |
| {{- range $i, $o := .ConstructorsAndConverters }} |
| { |
| /* [{{$i}}] */ |
| {{- range $o.OverloadDescriptions }} |
| /* {{.}} */ |
| {{- end }} |
| /* num overloads */ {{$o.NumOverloads}}, |
| /* overloads */ &kOverloads[{{$o.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 define and refine the template 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 define and refine the template 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 .PrecedenceSortedTypes }} |
| if (match_{{.Name}}(ty)) { |
| return build_{{.Name}}(state); |
| } |
| {{- end }} |
| return nullptr; |
| } |
| |
| std::string {{$class}}::String(MatchState*) const { |
| std::stringstream ss; |
| // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support |
| // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. |
| ss |
| {{- range .Types -}} |
| {{- if IsFirstIn . $.Types }} << {{PascalCase .Name}}().String(nullptr) |
| {{- else if IsLastIn . $.Types }} << " or " << {{PascalCase .Name}}().String(nullptr) |
| {{- else }} << ", " << {{PascalCase .Name}}().String(nullptr) |
| {{- end -}} |
| {{- end -}}; |
| return ss.str(); |
| } |
| {{ 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 define template 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.MaxTemplateTypes -}} |
| {{- $name := printf "template_type_%v" . -}} |
| {{- $t_names.Put . $name }} |
| TemplateTypeMatcher {{$name}}_{ {{- . -}} }; |
| {{- end }} |
| {{- range Iterate .Sem.MaxTemplateNumbers -}} |
| {{- $name := printf "template_number_%v" . -}} |
| {{- $n_names.Put . $name }} |
| TemplateNumberMatcher {{$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 template 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 template 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 -}} |
| |
| {{- /* ------------------------------------------------------------------ */ -}} |
| {{- define "OperatorName" -}} |
| {{- /* ------------------------------------------------------------------ */ -}} |
| {{- if eq . "<<" -}}ShiftLeft |
| {{- else if eq . "&" -}}And |
| {{- else if eq . "|" -}}Or |
| {{- else if eq . "^" -}}Xor |
| {{- else if eq . "&&" -}}LogicalAnd |
| {{- else if eq . "||" -}}LogicalOr |
| {{- else if eq . "==" -}}Equal |
| {{- else if eq . "!" -}}Not |
| {{- else if eq . "!=" -}}NotEqual |
| {{- else if eq . "~" -}}Complement |
| {{- else if eq . "<" -}}LessThan |
| {{- else if eq . ">" -}}GreaterThan |
| {{- else if eq . "<=" -}}LessThanEqual |
| {{- else if eq . ">=" -}}GreaterThanEqual |
| {{- else if eq . "<<" -}}ShiftLeft |
| {{- else if eq . ">>" -}}ShiftRight |
| {{- else if eq . "+" -}}Plus |
| {{- else if eq . "-" -}}Minus |
| {{- else if eq . "*" -}}Star |
| {{- else if eq . "/" -}}Divide |
| {{- else if eq . "%" -}}Modulo |
| {{- else -}}<unknown-{{.}}> |
| {{- end -}} |
| {{- end -}} |