2021-06-01 19:06:31 +00:00
|
|
|
{{- /*
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
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
|
|
|
|
|
|
|
|
/// ParameterInfo describes a parameter
|
|
|
|
struct ParameterInfo {
|
|
|
|
/// The parameter usage (parameter name in definition file)
|
|
|
|
ParameterUsage const usage;
|
|
|
|
|
|
|
|
/// Pointer to a list of indices that are used to match the parameter type.
|
|
|
|
/// The matcher indices index on Matchers::type and / or Matchers::number.
|
|
|
|
/// These indices are consumed by the matchers themselves.
|
|
|
|
/// The first index is always a TypeMatcher.
|
|
|
|
MatcherIndex const* const matcher_indices;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// OpenTypeInfo describes an open type
|
|
|
|
struct OpenTypeInfo {
|
|
|
|
/// Name of the open type (e.g. 'T')
|
|
|
|
const char* name;
|
|
|
|
/// Optional type matcher constraint.
|
|
|
|
/// Either an index in Matchers::type, or kNoMatcher
|
|
|
|
MatcherIndex const matcher_index;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// OpenNumberInfo describes an open number
|
|
|
|
struct OpenNumberInfo {
|
|
|
|
/// Name of the open number (e.g. 'N')
|
|
|
|
const char* name;
|
|
|
|
/// Optional number matcher constraint.
|
|
|
|
/// Either an index in Matchers::number, or kNoMatcher
|
|
|
|
MatcherIndex const matcher_index;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// OverloadInfo describes a single function overload
|
|
|
|
struct OverloadInfo {
|
|
|
|
/// Total number of parameters for the overload
|
|
|
|
uint8_t const num_parameters;
|
|
|
|
/// Total number of open types for the overload
|
|
|
|
uint8_t const num_open_types;
|
|
|
|
/// Total number of open numbers for the overload
|
|
|
|
uint8_t const num_open_numbers;
|
|
|
|
/// Pointer to the first open type
|
|
|
|
OpenTypeInfo const* const open_types;
|
|
|
|
/// Pointer to the first open number
|
|
|
|
OpenNumberInfo const* const open_numbers;
|
|
|
|
/// Pointer to the first parameter
|
|
|
|
ParameterInfo const* const parameters;
|
|
|
|
/// Pointer to a list of matcher indices that index on Matchers::type and
|
|
|
|
/// Matchers::number, used to build the return type. If the function has no
|
|
|
|
/// return type then this is null.
|
|
|
|
MatcherIndex const* const return_matcher_indices;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// IntrinsicInfo describes an intrinsic function
|
|
|
|
struct IntrinsicInfo {
|
|
|
|
/// Number of overloads of the intrinsic function
|
|
|
|
uint8_t const num_overloads;
|
|
|
|
/// Pointer to the start of the overloads for the function
|
|
|
|
OverloadInfo const* const overloads;
|
|
|
|
};
|
|
|
|
|
|
|
|
{{ 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 }},
|
|
|
|
},
|
|
|
|
{{- 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}}
|
2021-06-03 08:32:44 +00:00
|
|
|
{{- end -}}
|
2021-06-01 19:06:31 +00:00
|
|
|
{{- 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({{$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 {
|
2021-06-03 08:32:44 +00:00
|
|
|
return "
|
|
|
|
{{- range .Options -}}
|
|
|
|
{{- if IsFirstIn . $.Options }}{{.Name}}
|
|
|
|
{{- else if IsLastIn . $.Options }} or {{.Name}}
|
|
|
|
{{- else }}, {{.Name}}
|
|
|
|
{{- end -}}
|
|
|
|
{{- end -}}
|
|
|
|
";
|
2021-06-01 19:06:31 +00:00
|
|
|
}
|
|
|
|
{{ 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 -}}
|