Move type card printing to standalone function for reuse.
PiperOrigin-RevId: 579966858
diff --git a/src/google/protobuf/compiler/cpp/parse_function_generator.cc b/src/google/protobuf/compiler/cpp/parse_function_generator.cc
index a8074df..25bfbbe 100644
--- a/src/google/protobuf/compiler/cpp/parse_function_generator.cc
+++ b/src/google/protobuf/compiler/cpp/parse_function_generator.cc
@@ -621,141 +621,6 @@
}
}
-static void FormatFieldKind(Formatter& format,
- const TailCallTableInfo::FieldEntryInfo& entry) {
- // In here we convert the runtime value of entry.type_card back into a
- // sequence of literal enum labels. We use the mnenonic labels for nicer
- // codegen.
- namespace fl = internal::field_layout;
- const uint16_t type_card = entry.type_card;
- const int rep_index = (type_card & fl::kRepMask) >> fl::kRepShift;
- const int tv_index = (type_card & fl::kTvMask) >> fl::kTvShift;
-
- // Use `0|` prefix to eagerly convert the enums to int to avoid enum-enum
- // operations. They are deprecated in C++20.
- format("(0 | ");
- static constexpr const char* kFieldCardNames[] = {"Singular", "Optional",
- "Repeated", "Oneof"};
- static_assert((fl::kFcSingular >> fl::kFcShift) == 0, "");
- static_assert((fl::kFcOptional >> fl::kFcShift) == 1, "");
- static_assert((fl::kFcRepeated >> fl::kFcShift) == 2, "");
- static_assert((fl::kFcOneof >> fl::kFcShift) == 3, "");
-
- format("::_fl::kFc$1$",
- kFieldCardNames[(type_card & fl::kFcMask) >> fl::kFcShift]);
-
-#define PROTOBUF_INTERNAL_TYPE_CARD_CASE(x) \
- case fl::k##x: \
- format(" | ::_fl::k" #x); \
- break
-
- switch (type_card & fl::kFkMask) {
- case fl::kFkString: {
- switch (type_card & ~fl::kFcMask & ~fl::kRepMask & ~fl::kSplitMask) {
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bytes);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(RawString);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Utf8String);
- default:
- ABSL_LOG(FATAL) << "Unknown type_card: 0x" << type_card;
- }
-
- static constexpr const char* kRepNames[] = {"AString", "IString", "Cord",
- "SPiece", "SString"};
- static_assert((fl::kRepAString >> fl::kRepShift) == 0, "");
- static_assert((fl::kRepIString >> fl::kRepShift) == 1, "");
- static_assert((fl::kRepCord >> fl::kRepShift) == 2, "");
- static_assert((fl::kRepSPiece >> fl::kRepShift) == 3, "");
- static_assert((fl::kRepSString >> fl::kRepShift) == 4, "");
-
- format(" | ::_fl::kRep$1$", kRepNames[rep_index]);
- break;
- }
-
- case fl::kFkMessage: {
- format(" | ::_fl::kMessage");
-
- static constexpr const char* kRepNames[] = {nullptr, "Group", "Lazy"};
- static_assert((fl::kRepGroup >> fl::kRepShift) == 1, "");
- static_assert((fl::kRepLazy >> fl::kRepShift) == 2, "");
-
- if (auto* rep = kRepNames[rep_index]) {
- format(" | ::_fl::kRep$1$", rep);
- }
-
- static constexpr const char* kXFormNames[2][4] = {
- {nullptr, "Default", "Table", "WeakPtr"}, {nullptr, "Eager", "Lazy"}};
-
- static_assert((fl::kTvDefault >> fl::kTvShift) == 1, "");
- static_assert((fl::kTvTable >> fl::kTvShift) == 2, "");
- static_assert((fl::kTvWeakPtr >> fl::kTvShift) == 3, "");
- static_assert((fl::kTvEager >> fl::kTvShift) == 1, "");
- static_assert((fl::kTvLazy >> fl::kTvShift) == 2, "");
-
- if (auto* xform = kXFormNames[rep_index == 2][tv_index]) {
- format(" | ::_fl::kTv$1$", xform);
- }
- break;
- }
-
- case fl::kFkMap:
- format(" | ::_fl::kMap");
- break;
-
- case fl::kFkNone:
- break;
-
- case fl::kFkVarint:
- case fl::kFkPackedVarint:
- case fl::kFkFixed:
- case fl::kFkPackedFixed: {
- switch (type_card & ~fl::kFcMask & ~fl::kSplitMask) {
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bool);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Float);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Enum);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(EnumRange);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(OpenEnum);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(Double);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedBool);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt32);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFloat);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnum);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnumRange);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedOpenEnum);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt64);
- PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedDouble);
- default:
- ABSL_LOG(FATAL) << "Unknown type_card: 0x" << type_card;
- }
- }
- }
-
- if (type_card & fl::kSplitMask) {
- format(" | ::_fl::kSplitTrue");
- }
-
-#undef PROTOBUF_INTERNAL_TYPE_CARD_CASE
-
- format(")");
-}
-
void ParseFunctionGenerator::GenerateFieldEntries(Formatter& format) {
for (const auto& entry : tc_table_info_->field_entries) {
const FieldDescriptor* field = entry.field;
@@ -787,7 +652,9 @@
format("0, ");
}
format("$1$,\n ", entry.aux_idx);
- FormatFieldKind(format, entry);
+ // Use `0|` prefix to eagerly convert the enums to int to avoid enum-enum
+ // operations. They are deprecated in C++20.
+ format("(0 | $1$)", internal::TypeCardToString(entry.type_card));
}
format("},\n");
}
diff --git a/src/google/protobuf/generated_message_tctable_decl.h b/src/google/protobuf/generated_message_tctable_decl.h
index 629cfb7..22aa54b 100644
--- a/src/google/protobuf/generated_message_tctable_decl.h
+++ b/src/google/protobuf/generated_message_tctable_decl.h
@@ -18,6 +18,7 @@
#include <cstdint>
#include <type_traits>
+#include "absl/types/span.h"
#include "google/protobuf/message_lite.h"
#include "google/protobuf/parse_context.h"
@@ -375,6 +376,9 @@
return reinterpret_cast<const FieldEntry*>(
reinterpret_cast<uintptr_t>(this) + field_entries_offset);
}
+ absl::Span<const FieldEntry> field_entries() const {
+ return {field_entries_begin(), num_field_entries};
+ }
FieldEntry* field_entries_begin() {
return reinterpret_cast<FieldEntry*>(reinterpret_cast<uintptr_t>(this) +
field_entries_offset);
diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h
index 42a5608..fb111e3 100644
--- a/src/google/protobuf/generated_message_tctable_impl.h
+++ b/src/google/protobuf/generated_message_tctable_impl.h
@@ -943,6 +943,10 @@
return ptr;
}
+// Prints the type card as or of labels, using known higher level labels.
+// Used for code generation, but also useful for debugging.
+PROTOBUF_EXPORT std::string TypeCardToString(uint16_t type_card);
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc
index 104a22a..e37a208 100644
--- a/src/google/protobuf/generated_message_tctable_lite.cc
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
@@ -18,6 +18,7 @@
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/numeric/bits.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/generated_message_tctable_decl.h"
#include "google/protobuf/generated_message_tctable_impl.h"
@@ -2800,6 +2801,138 @@
PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS);
}
+std::string TypeCardToString(uint16_t type_card) {
+ // In here we convert the runtime value of entry.type_card back into a
+ // sequence of literal enum labels. We use the mnenonic labels for nicer
+ // codegen.
+ namespace fl = internal::field_layout;
+ const int rep_index = (type_card & fl::kRepMask) >> fl::kRepShift;
+ const int tv_index = (type_card & fl::kTvMask) >> fl::kTvShift;
+
+ static constexpr const char* kFieldCardNames[] = {"Singular", "Optional",
+ "Repeated", "Oneof"};
+ static_assert((fl::kFcSingular >> fl::kFcShift) == 0, "");
+ static_assert((fl::kFcOptional >> fl::kFcShift) == 1, "");
+ static_assert((fl::kFcRepeated >> fl::kFcShift) == 2, "");
+ static_assert((fl::kFcOneof >> fl::kFcShift) == 3, "");
+
+ std::string out;
+
+ absl::StrAppend(&out, "::_fl::kFc",
+ kFieldCardNames[(type_card & fl::kFcMask) >> fl::kFcShift]);
+
+#define PROTOBUF_INTERNAL_TYPE_CARD_CASE(x) \
+ case fl::k##x: \
+ absl::StrAppend(&out, " | ::_fl::k" #x); \
+ break
+
+ switch (type_card & fl::kFkMask) {
+ case fl::kFkString: {
+ switch (type_card & ~fl::kFcMask & ~fl::kRepMask & ~fl::kSplitMask) {
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bytes);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(RawString);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Utf8String);
+ default:
+ ABSL_LOG(FATAL) << "Unknown type_card: 0x" << type_card;
+ }
+
+ static constexpr const char* kRepNames[] = {"AString", "IString", "Cord",
+ "SPiece", "SString"};
+ static_assert((fl::kRepAString >> fl::kRepShift) == 0, "");
+ static_assert((fl::kRepIString >> fl::kRepShift) == 1, "");
+ static_assert((fl::kRepCord >> fl::kRepShift) == 2, "");
+ static_assert((fl::kRepSPiece >> fl::kRepShift) == 3, "");
+ static_assert((fl::kRepSString >> fl::kRepShift) == 4, "");
+
+ absl::StrAppend(&out, " | ::_fl::kRep", kRepNames[rep_index]);
+ break;
+ }
+
+ case fl::kFkMessage: {
+ absl::StrAppend(&out, " | ::_fl::kMessage");
+
+ static constexpr const char* kRepNames[] = {nullptr, "Group", "Lazy"};
+ static_assert((fl::kRepGroup >> fl::kRepShift) == 1, "");
+ static_assert((fl::kRepLazy >> fl::kRepShift) == 2, "");
+
+ if (auto* rep = kRepNames[rep_index]) {
+ absl::StrAppend(&out, " | ::_fl::kRep", rep);
+ }
+
+ static constexpr const char* kXFormNames[2][4] = {
+ {nullptr, "Default", "Table", "WeakPtr"}, {nullptr, "Eager", "Lazy"}};
+
+ static_assert((fl::kTvDefault >> fl::kTvShift) == 1, "");
+ static_assert((fl::kTvTable >> fl::kTvShift) == 2, "");
+ static_assert((fl::kTvWeakPtr >> fl::kTvShift) == 3, "");
+ static_assert((fl::kTvEager >> fl::kTvShift) == 1, "");
+ static_assert((fl::kTvLazy >> fl::kTvShift) == 2, "");
+
+ if (auto* xform = kXFormNames[rep_index == 2][tv_index]) {
+ absl::StrAppend(&out, " | ::_fl::kTv", xform);
+ }
+ break;
+ }
+
+ case fl::kFkMap:
+ absl::StrAppend(&out, " | ::_fl::kMap");
+ break;
+
+ case fl::kFkNone:
+ break;
+
+ case fl::kFkVarint:
+ case fl::kFkPackedVarint:
+ case fl::kFkFixed:
+ case fl::kFkPackedFixed: {
+ switch (type_card & ~fl::kFcMask & ~fl::kSplitMask) {
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bool);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Float);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Enum);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(EnumRange);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(OpenEnum);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(Double);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedBool);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt32);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFloat);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnum);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnumRange);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedOpenEnum);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt64);
+ PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedDouble);
+ default:
+ ABSL_LOG(FATAL) << "Unknown type_card: 0x" << type_card;
+ }
+ }
+ }
+
+ if (type_card & fl::kSplitMask) {
+ absl::StrAppend(&out, " | ::_fl::kSplitTrue");
+ }
+
+#undef PROTOBUF_INTERNAL_TYPE_CARD_CASE
+
+ return out;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/generated_message_tctable_lite_test.cc b/src/google/protobuf/generated_message_tctable_lite_test.cc
index d037852..8648712 100644
--- a/src/google/protobuf/generated_message_tctable_lite_test.cc
+++ b/src/google/protobuf/generated_message_tctable_lite_test.cc
@@ -20,6 +20,7 @@
namespace {
+using ::testing::ElementsAreArray;
using ::testing::Eq;
using ::testing::Not;
using ::testing::Optional;
@@ -899,6 +900,7 @@
EXPECT_LE(proto.vals().Capacity(), 2048);
}
+
} // namespace internal
} // namespace protobuf
} // namespace google