mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-16 10:05:55 +00:00
tint: Split tables for unary and binary operators
Do the partitioning of unary and binary operators in the intrinsic table generators, instead of searching all operators at runtime. Will allow code to be simplified. Bug: tint:1504 Change-Id: I67246b954e530e0542b1b67c99fb34a756cf532a Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/90240 Commit-Queue: Ben Clayton <bclayton@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
62bfd318ae
commit
77473b4699
@ -956,21 +956,20 @@ IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
|
|||||||
auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<uint32_t, const char*> {
|
auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<uint32_t, const char*> {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case ast::UnaryOp::kComplement:
|
case ast::UnaryOp::kComplement:
|
||||||
return {kOperatorComplement, "operator ~ "};
|
return {kUnaryOperatorComplement, "operator ~ "};
|
||||||
case ast::UnaryOp::kNegation:
|
case ast::UnaryOp::kNegation:
|
||||||
return {kOperatorMinus, "operator - "};
|
return {kUnaryOperatorMinus, "operator - "};
|
||||||
case ast::UnaryOp::kNot:
|
case ast::UnaryOp::kNot:
|
||||||
return {kOperatorNot, "operator ! "};
|
return {kUnaryOperatorNot, "operator ! "};
|
||||||
default:
|
default:
|
||||||
return {0, "<unknown>"};
|
return {0, "<unknown>"};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
auto& builtin = kOperators[intrinsic_index];
|
auto& builtin = kUnaryOperators[intrinsic_index];
|
||||||
for (uint32_t o = 0; o < builtin.num_overloads; o++) {
|
for (uint32_t o = 0; o < builtin.num_overloads; o++) {
|
||||||
int match_score = 1000;
|
int match_score = 1000;
|
||||||
auto& overload = builtin.overloads[o];
|
auto& overload = builtin.overloads[o];
|
||||||
if (overload.num_parameters == 1) {
|
|
||||||
auto match = Match(intrinsic_name, intrinsic_index, overload, {arg}, match_score);
|
auto match = Match(intrinsic_name, intrinsic_index, overload, {arg}, match_score);
|
||||||
if (match.return_type) {
|
if (match.return_type) {
|
||||||
return UnaryOperator{match.return_type, match.parameters[0].type};
|
return UnaryOperator{match.return_type, match.parameters[0].type};
|
||||||
@ -979,7 +978,6 @@ IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
|
|||||||
candidates.emplace_back(Candidate{&overload, match_score});
|
candidates.emplace_back(Candidate{&overload, match_score});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the candidates with the most promising first
|
// Sort the candidates with the most promising first
|
||||||
std::stable_sort(candidates.begin(), candidates.end(),
|
std::stable_sort(candidates.begin(), candidates.end(),
|
||||||
@ -1013,51 +1011,50 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
|||||||
auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<uint32_t, const char*> {
|
auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<uint32_t, const char*> {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case ast::BinaryOp::kAnd:
|
case ast::BinaryOp::kAnd:
|
||||||
return {kOperatorAnd, is_compound ? "operator &= " : "operator & "};
|
return {kBinaryOperatorAnd, is_compound ? "operator &= " : "operator & "};
|
||||||
case ast::BinaryOp::kOr:
|
case ast::BinaryOp::kOr:
|
||||||
return {kOperatorOr, is_compound ? "operator |= " : "operator | "};
|
return {kBinaryOperatorOr, is_compound ? "operator |= " : "operator | "};
|
||||||
case ast::BinaryOp::kXor:
|
case ast::BinaryOp::kXor:
|
||||||
return {kOperatorXor, is_compound ? "operator ^= " : "operator ^ "};
|
return {kBinaryOperatorXor, is_compound ? "operator ^= " : "operator ^ "};
|
||||||
case ast::BinaryOp::kLogicalAnd:
|
case ast::BinaryOp::kLogicalAnd:
|
||||||
return {kOperatorLogicalAnd, "operator && "};
|
return {kBinaryOperatorLogicalAnd, "operator && "};
|
||||||
case ast::BinaryOp::kLogicalOr:
|
case ast::BinaryOp::kLogicalOr:
|
||||||
return {kOperatorLogicalOr, "operator || "};
|
return {kBinaryOperatorLogicalOr, "operator || "};
|
||||||
case ast::BinaryOp::kEqual:
|
case ast::BinaryOp::kEqual:
|
||||||
return {kOperatorEqual, "operator == "};
|
return {kBinaryOperatorEqual, "operator == "};
|
||||||
case ast::BinaryOp::kNotEqual:
|
case ast::BinaryOp::kNotEqual:
|
||||||
return {kOperatorNotEqual, "operator != "};
|
return {kBinaryOperatorNotEqual, "operator != "};
|
||||||
case ast::BinaryOp::kLessThan:
|
case ast::BinaryOp::kLessThan:
|
||||||
return {kOperatorLessThan, "operator < "};
|
return {kBinaryOperatorLessThan, "operator < "};
|
||||||
case ast::BinaryOp::kGreaterThan:
|
case ast::BinaryOp::kGreaterThan:
|
||||||
return {kOperatorGreaterThan, "operator > "};
|
return {kBinaryOperatorGreaterThan, "operator > "};
|
||||||
case ast::BinaryOp::kLessThanEqual:
|
case ast::BinaryOp::kLessThanEqual:
|
||||||
return {kOperatorLessThanEqual, "operator <= "};
|
return {kBinaryOperatorLessThanEqual, "operator <= "};
|
||||||
case ast::BinaryOp::kGreaterThanEqual:
|
case ast::BinaryOp::kGreaterThanEqual:
|
||||||
return {kOperatorGreaterThanEqual, "operator >= "};
|
return {kBinaryOperatorGreaterThanEqual, "operator >= "};
|
||||||
case ast::BinaryOp::kShiftLeft:
|
case ast::BinaryOp::kShiftLeft:
|
||||||
return {kOperatorShiftLeft, is_compound ? "operator <<= " : "operator << "};
|
return {kBinaryOperatorShiftLeft, is_compound ? "operator <<= " : "operator << "};
|
||||||
case ast::BinaryOp::kShiftRight:
|
case ast::BinaryOp::kShiftRight:
|
||||||
return {kOperatorShiftRight, is_compound ? "operator >>= " : "operator >> "};
|
return {kBinaryOperatorShiftRight, is_compound ? "operator >>= " : "operator >> "};
|
||||||
case ast::BinaryOp::kAdd:
|
case ast::BinaryOp::kAdd:
|
||||||
return {kOperatorPlus, is_compound ? "operator += " : "operator + "};
|
return {kBinaryOperatorPlus, is_compound ? "operator += " : "operator + "};
|
||||||
case ast::BinaryOp::kSubtract:
|
case ast::BinaryOp::kSubtract:
|
||||||
return {kOperatorMinus, is_compound ? "operator -= " : "operator - "};
|
return {kBinaryOperatorMinus, is_compound ? "operator -= " : "operator - "};
|
||||||
case ast::BinaryOp::kMultiply:
|
case ast::BinaryOp::kMultiply:
|
||||||
return {kOperatorStar, is_compound ? "operator *= " : "operator * "};
|
return {kBinaryOperatorStar, is_compound ? "operator *= " : "operator * "};
|
||||||
case ast::BinaryOp::kDivide:
|
case ast::BinaryOp::kDivide:
|
||||||
return {kOperatorDivide, is_compound ? "operator /= " : "operator / "};
|
return {kBinaryOperatorDivide, is_compound ? "operator /= " : "operator / "};
|
||||||
case ast::BinaryOp::kModulo:
|
case ast::BinaryOp::kModulo:
|
||||||
return {kOperatorModulo, is_compound ? "operator %= " : "operator % "};
|
return {kBinaryOperatorModulo, is_compound ? "operator %= " : "operator % "};
|
||||||
default:
|
default:
|
||||||
return {0, "<unknown>"};
|
return {0, "<unknown>"};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
auto& builtin = kOperators[intrinsic_index];
|
auto& builtin = kBinaryOperators[intrinsic_index];
|
||||||
for (uint32_t o = 0; o < builtin.num_overloads; o++) {
|
for (uint32_t o = 0; o < builtin.num_overloads; o++) {
|
||||||
int match_score = 1000;
|
int match_score = 1000;
|
||||||
auto& overload = builtin.overloads[o];
|
auto& overload = builtin.overloads[o];
|
||||||
if (overload.num_parameters == 2) {
|
|
||||||
auto match = Match(intrinsic_name, intrinsic_index, overload, {lhs, rhs}, match_score);
|
auto match = Match(intrinsic_name, intrinsic_index, overload, {lhs, rhs}, match_score);
|
||||||
if (match.return_type) {
|
if (match.return_type) {
|
||||||
return BinaryOperator{match.return_type, match.parameters[0].type,
|
return BinaryOperator{match.return_type, match.parameters[0].type,
|
||||||
@ -1067,7 +1064,6 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
|||||||
candidates.emplace_back(Candidate{&overload, match_score});
|
candidates.emplace_back(Candidate{&overload, match_score});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the candidates with the most promising first
|
// Sort the candidates with the most promising first
|
||||||
std::stable_sort(candidates.begin(), candidates.end(),
|
std::stable_sort(candidates.begin(), candidates.end(),
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -119,8 +119,8 @@ constexpr IntrinsicInfo kBuiltins[] = {
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr IntrinsicInfo kOperators[] = {
|
constexpr IntrinsicInfo kUnaryOperators[] = {
|
||||||
{{- range $i, $o := .Operators }}
|
{{- range $i, $o := .UnaryOperators }}
|
||||||
{
|
{
|
||||||
/* [{{$i}}] */
|
/* [{{$i}}] */
|
||||||
{{- range $o.OverloadDescriptions }}
|
{{- range $o.OverloadDescriptions }}
|
||||||
@ -132,8 +132,25 @@ constexpr IntrinsicInfo kOperators[] = {
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
|
||||||
{{- range $i, $o := .Operators }}
|
{{- range $i, $o := .UnaryOperators }}
|
||||||
constexpr uint8_t kOperator{{template "OperatorName" $o.Name}} = {{$i}};
|
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 }}
|
{{- end }}
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
@ -107,7 +107,11 @@ func (m MatcherDecl) Format(w fmt.State, verb rune) {
|
|||||||
type IntrinsicKind string
|
type IntrinsicKind string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// Builtin is a builtin function (max, fract, etc).
|
||||||
|
// Declared with 'fn'.
|
||||||
Builtin IntrinsicKind = "builtin"
|
Builtin IntrinsicKind = "builtin"
|
||||||
|
// Operator is a unary or binary operator.
|
||||||
|
// Declared with 'op'.
|
||||||
Operator IntrinsicKind = "operator"
|
Operator IntrinsicKind = "operator"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,7 +43,8 @@ type IntrinsicTable struct {
|
|||||||
Parameters []Parameter // kParameters table content
|
Parameters []Parameter // kParameters table content
|
||||||
Overloads []Overload // kOverloads table content
|
Overloads []Overload // kOverloads table content
|
||||||
Builtins []Intrinsic // kBuiltins table content
|
Builtins []Intrinsic // kBuiltins table content
|
||||||
Operators []Intrinsic // kOperators table content
|
UnaryOperators []Intrinsic // kUnaryOperators table content
|
||||||
|
BinaryOperators []Intrinsic // kBinaryOperators table content
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenType is used to create the C++ OpenTypeInfo structure
|
// OpenType is used to create the C++ OpenTypeInfo structure
|
||||||
@ -361,9 +362,16 @@ func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
|
|||||||
|
|
||||||
b.layoutMatchers(s)
|
b.layoutMatchers(s)
|
||||||
|
|
||||||
buildIntrinsics := func(in []*sem.Intrinsic) ([]Intrinsic, error) {
|
for _, intrinsics := range []struct {
|
||||||
out := make([]Intrinsic, len(in))
|
in []*sem.Intrinsic
|
||||||
for i, f := range in {
|
out *[]Intrinsic
|
||||||
|
}{
|
||||||
|
{s.Builtins, &b.Builtins},
|
||||||
|
{s.UnaryOperators, &b.UnaryOperators},
|
||||||
|
{s.BinaryOperators, &b.BinaryOperators},
|
||||||
|
} {
|
||||||
|
out := make([]Intrinsic, len(intrinsics.in))
|
||||||
|
for i, f := range intrinsics.in {
|
||||||
overloads := make([]Overload, len(f.Overloads))
|
overloads := make([]Overload, len(f.Overloads))
|
||||||
overloadDescriptions := make([]string, len(f.Overloads))
|
overloadDescriptions := make([]string, len(f.Overloads))
|
||||||
for i, o := range f.Overloads {
|
for i, o := range f.Overloads {
|
||||||
@ -380,15 +388,7 @@ func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
|
|||||||
OverloadsOffset: b.lut.overloads.Add(overloads),
|
OverloadsOffset: b.lut.overloads.Add(overloads),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out, nil
|
*intrinsics.out = out
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if b.Builtins, err = buildIntrinsics(s.Builtins); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if b.Operators, err = buildIntrinsics(s.Operators); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.lut.matcherIndices.Compact()
|
b.lut.matcherIndices.Compact()
|
||||||
|
@ -29,7 +29,8 @@ type resolver struct {
|
|||||||
|
|
||||||
globals scope
|
globals scope
|
||||||
builtins map[string]*sem.Intrinsic
|
builtins map[string]*sem.Intrinsic
|
||||||
operators map[string]*sem.Intrinsic
|
unaryOperators map[string]*sem.Intrinsic
|
||||||
|
binaryOperators map[string]*sem.Intrinsic
|
||||||
enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher
|
enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +41,8 @@ func Resolve(a *ast.AST) (*sem.Sem, error) {
|
|||||||
s: sem.New(),
|
s: sem.New(),
|
||||||
globals: newScope(nil),
|
globals: newScope(nil),
|
||||||
builtins: map[string]*sem.Intrinsic{},
|
builtins: map[string]*sem.Intrinsic{},
|
||||||
operators: map[string]*sem.Intrinsic{},
|
unaryOperators: map[string]*sem.Intrinsic{},
|
||||||
|
binaryOperators: map[string]*sem.Intrinsic{},
|
||||||
enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{},
|
enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{},
|
||||||
}
|
}
|
||||||
// Declare and resolve all the enumerators
|
// Declare and resolve all the enumerators
|
||||||
@ -67,11 +69,20 @@ func Resolve(a *ast.AST) (*sem.Sem, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Declare and resolve the operators
|
// Declare and resolve the unary and binary operators
|
||||||
for _, o := range a.Operators {
|
for _, o := range a.Operators {
|
||||||
if err := r.intrinsic(o, r.operators, &r.s.Operators); err != nil {
|
switch len(o.Parameters) {
|
||||||
|
case 1:
|
||||||
|
if err := r.intrinsic(o, r.unaryOperators, &r.s.UnaryOperators); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case 2:
|
||||||
|
if err := r.intrinsic(o, r.binaryOperators, &r.s.BinaryOperators); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("%v operators must have either 1 or 2 parameters", o.Source)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the unique parameter names
|
// Calculate the unique parameter names
|
||||||
@ -318,10 +329,6 @@ func (r *resolver) intrinsic(
|
|||||||
r.s.MaxOpenNumbers = len(overload.OpenNumbers)
|
r.s.MaxOpenNumbers = len(overload.OpenNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Kind == ast.Operator && (len(a.Parameters) < 1 || len(a.Parameters) > 2) {
|
|
||||||
return fmt.Errorf("%v operators must have either 1 or 2 parameters", a.Source)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve the parameters
|
// Resolve the parameters
|
||||||
for i, p := range a.Parameters {
|
for i, p := range a.Parameters {
|
||||||
usage, err := r.fullyQualifiedName(&s, p.Type)
|
usage, err := r.fullyQualifiedName(&s, p.Type)
|
||||||
@ -514,8 +521,13 @@ func (r *resolver) lookupNamed(s *scope, a ast.TemplatedName) (sem.Named, error)
|
|||||||
func (r *resolver) calculateUniqueParameterNames() []string {
|
func (r *resolver) calculateUniqueParameterNames() []string {
|
||||||
set := map[string]struct{}{"": {}}
|
set := map[string]struct{}{"": {}}
|
||||||
names := []string{}
|
names := []string{}
|
||||||
for _, f := range r.s.Builtins {
|
for _, intrinsics := range [][]*sem.Intrinsic{
|
||||||
for _, o := range f.Overloads {
|
r.s.Builtins,
|
||||||
|
r.s.UnaryOperators,
|
||||||
|
r.s.BinaryOperators,
|
||||||
|
} {
|
||||||
|
for _, i := range intrinsics {
|
||||||
|
for _, o := range i.Overloads {
|
||||||
for _, p := range o.Parameters {
|
for _, p := range o.Parameters {
|
||||||
if _, dup := set[p.Name]; !dup {
|
if _, dup := set[p.Name]; !dup {
|
||||||
set[p.Name] = struct{}{}
|
set[p.Name] = struct{}{}
|
||||||
@ -524,6 +536,7 @@ func (r *resolver) calculateUniqueParameterNames() []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sort.Strings(names)
|
sort.Strings(names)
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ type Sem struct {
|
|||||||
TypeMatchers []*TypeMatcher
|
TypeMatchers []*TypeMatcher
|
||||||
EnumMatchers []*EnumMatcher
|
EnumMatchers []*EnumMatcher
|
||||||
Builtins []*Intrinsic
|
Builtins []*Intrinsic
|
||||||
Operators []*Intrinsic
|
UnaryOperators []*Intrinsic
|
||||||
|
BinaryOperators []*Intrinsic
|
||||||
// Maximum number of open-types used across all builtins
|
// Maximum number of open-types used across all builtins
|
||||||
MaxOpenTypes int
|
MaxOpenTypes int
|
||||||
// Maximum number of open-numbers used across all builtins
|
// Maximum number of open-numbers used across all builtins
|
||||||
@ -44,7 +45,8 @@ func New() *Sem {
|
|||||||
TypeMatchers: []*TypeMatcher{},
|
TypeMatchers: []*TypeMatcher{},
|
||||||
EnumMatchers: []*EnumMatcher{},
|
EnumMatchers: []*EnumMatcher{},
|
||||||
Builtins: []*Intrinsic{},
|
Builtins: []*Intrinsic{},
|
||||||
Operators: []*Intrinsic{},
|
UnaryOperators: []*Intrinsic{},
|
||||||
|
BinaryOperators: []*Intrinsic{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user