Move type card printing to standalone function for reuse.

PiperOrigin-RevId: 579966858
pull/14598/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent a2815fa13f
commit 5c4d643a2d
  1. 139
      src/google/protobuf/compiler/cpp/parse_function_generator.cc
  2. 4
      src/google/protobuf/generated_message_tctable_decl.h
  3. 4
      src/google/protobuf/generated_message_tctable_impl.h
  4. 133
      src/google/protobuf/generated_message_tctable_lite.cc
  5. 2
      src/google/protobuf/generated_message_tctable_lite_test.cc

@ -621,141 +621,6 @@ void ParseFunctionGenerator::GenerateFastFieldEntries(Formatter& format) {
}
}
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 @@ void ParseFunctionGenerator::GenerateFieldEntries(Formatter& format) {
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");
}

@ -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 @@ struct alignas(uint64_t) TcParseTableBase {
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);

@ -943,6 +943,10 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop(
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

@ -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_NOINLINE const char* TcParser::MpMap(PROTOBUF_TC_PARAM_DECL) {
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

@ -20,6 +20,7 @@ namespace internal {
namespace {
using ::testing::ElementsAreArray;
using ::testing::Eq;
using ::testing::Not;
using ::testing::Optional;
@ -899,6 +900,7 @@ TEST(GeneratedMessageTctableLiteTest,
EXPECT_LE(proto.vals().Capacity(), 2048);
}
} // namespace internal
} // namespace protobuf
} // namespace google

Loading…
Cancel
Save