Add well-known identifier caching (#6486)

I'm doing this because I figured it'd be an incremental improvement for
all the operator lookups that we do. Even to the extent that we've
discussed witness caching, I think it'll still apply. It does add one
more step to adding new interfaces (before, you'd just write the string,
now you add it to the def file and reference it).

I'll claim it makes GetClangOperatorKind a lot friendlier to read/edit,
nevermind removing the string comparisons. :)
This commit is contained in:
Jon Ross-Perkins
2025-12-11 21:41:47 +00:00
committed by GitHub
parent a848ae11e4
commit c0b335b87f
19 changed files with 482 additions and 239 deletions
+145 -138
View File
@@ -6,6 +6,7 @@
#include "clang/Sema/Overload.h"
#include "clang/Sema/Sema.h"
#include "toolchain/check/core_identifier.h"
#include "toolchain/check/cpp/import.h"
#include "toolchain/check/cpp/location.h"
#include "toolchain/check/cpp/overload_resolution.h"
@@ -20,147 +21,153 @@ namespace Carbon::Check {
// Maps Carbon operator interface and operator names to Clang operator kinds.
static auto GetClangOperatorKind(Context& context, SemIR::LocId loc_id,
llvm::StringLiteral interface_name,
llvm::StringLiteral op_name)
CoreIdentifier interface_name,
CoreIdentifier op_name)
-> std::optional<clang::OverloadedOperatorKind> {
// Unary operators.
if (interface_name == "Destroy" || interface_name == "As" ||
interface_name == "ImplicitAs" || interface_name == "Copy") {
// TODO: Support destructors and conversions.
return std::nullopt;
}
// Increment and Decrement.
if (interface_name == "Inc") {
CARBON_CHECK(op_name == "Op");
return clang::OO_PlusPlus;
}
if (interface_name == "Dec") {
CARBON_CHECK(op_name == "Op");
return clang::OO_MinusMinus;
}
// Arithmetic.
if (interface_name == "Negate") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Minus;
}
// Binary operators.
// Arithmetic Operators.
if (interface_name == "AddWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Plus;
}
if (interface_name == "SubWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Minus;
}
if (interface_name == "MulWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Star;
}
if (interface_name == "DivWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Slash;
}
if (interface_name == "ModWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Percent;
}
// Bitwise Operators.
if (interface_name == "BitAndWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Amp;
}
if (interface_name == "BitOrWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Pipe;
}
if (interface_name == "BitXorWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_Caret;
}
if (interface_name == "LeftShiftWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_LessLess;
}
if (interface_name == "RightShiftWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_GreaterGreater;
}
// Compound Assignment Arithmetic Operators.
if (interface_name == "AddAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_PlusEqual;
}
if (interface_name == "SubAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_MinusEqual;
}
if (interface_name == "MulAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_StarEqual;
}
if (interface_name == "DivAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_SlashEqual;
}
if (interface_name == "ModAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_PercentEqual;
}
// Compound Assignment Bitwise Operators.
if (interface_name == "BitAndAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_AmpEqual;
}
if (interface_name == "BitOrAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_PipeEqual;
}
if (interface_name == "BitXorAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_CaretEqual;
}
if (interface_name == "LeftShiftAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_LessLessEqual;
}
if (interface_name == "RightShiftAssignWith") {
CARBON_CHECK(op_name == "Op");
return clang::OO_GreaterGreaterEqual;
}
// Relational Operators.
if (interface_name == "EqWith") {
if (op_name == "Equal") {
return clang::OO_EqualEqual;
switch (interface_name) {
// Unary operators.
case CoreIdentifier::Destroy:
case CoreIdentifier::As:
case CoreIdentifier::ImplicitAs:
case CoreIdentifier::Copy: {
// TODO: Support destructors and conversions.
return std::nullopt;
}
CARBON_CHECK(op_name == "NotEqual");
return clang::OO_ExclaimEqual;
}
if (interface_name == "OrderedWith") {
if (op_name == "Less") {
return clang::OO_Less;
}
if (op_name == "Greater") {
return clang::OO_Greater;
}
if (op_name == "LessOrEquivalent") {
return clang::OO_LessEqual;
}
CARBON_CHECK(op_name == "GreaterOrEquivalent");
return clang::OO_GreaterEqual;
}
context.TODO(loc_id, llvm::formatv("Unsupported operator interface `{0}`",
interface_name));
return std::nullopt;
// Increment and decrement.
case CoreIdentifier::Inc: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_PlusPlus;
}
case CoreIdentifier::Dec: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_MinusMinus;
}
// Arithmetic.
case CoreIdentifier::Negate: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Minus;
}
// Binary operators.
// Arithmetic operators.
case CoreIdentifier::AddWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Plus;
}
case CoreIdentifier::SubWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Minus;
}
case CoreIdentifier::MulWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Star;
}
case CoreIdentifier::DivWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Slash;
}
case CoreIdentifier::ModWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Percent;
}
// Bitwise operators.
case CoreIdentifier::BitAndWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Amp;
}
case CoreIdentifier::BitOrWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Pipe;
}
case CoreIdentifier::BitXorWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_Caret;
}
case CoreIdentifier::LeftShiftWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_LessLess;
}
case CoreIdentifier::RightShiftWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_GreaterGreater;
}
// Compound assignment arithmetic operators.
case CoreIdentifier::AddAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_PlusEqual;
}
case CoreIdentifier::SubAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_MinusEqual;
}
case CoreIdentifier::MulAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_StarEqual;
}
case CoreIdentifier::DivAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_SlashEqual;
}
case CoreIdentifier::ModAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_PercentEqual;
}
// Compound assignment bitwise operators.
case CoreIdentifier::BitAndAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_AmpEqual;
}
case CoreIdentifier::BitOrAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_PipeEqual;
}
case CoreIdentifier::BitXorAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_CaretEqual;
}
case CoreIdentifier::LeftShiftAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_LessLessEqual;
}
case CoreIdentifier::RightShiftAssignWith: {
CARBON_CHECK(op_name == CoreIdentifier::Op);
return clang::OO_GreaterGreaterEqual;
}
// Relational operators.
case CoreIdentifier::EqWith: {
if (op_name == CoreIdentifier::Equal) {
return clang::OO_EqualEqual;
}
CARBON_CHECK(op_name == CoreIdentifier::NotEqual);
return clang::OO_ExclaimEqual;
}
case CoreIdentifier::OrderedWith: {
switch (op_name) {
case CoreIdentifier::Less:
return clang::OO_Less;
case CoreIdentifier::Greater:
return clang::OO_Greater;
case CoreIdentifier::LessOrEquivalent:
return clang::OO_LessEqual;
case CoreIdentifier::GreaterOrEquivalent:
return clang::OO_GreaterEqual;
default:
CARBON_FATAL("Unexpected OrderedWith op `{0}`", op_name);
}
}
default:
context.TODO(loc_id, llvm::formatv("Unsupported operator interface `{0}`",
interface_name));
return std::nullopt;
}
}
auto LookupCppOperator(Context& context, SemIR::LocId loc_id, Operator op,