Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:12:21

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
0009 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
0010 
0011 #include <cassert>
0012 #include <cstdint>
0013 #include <cstdlib>
0014 #include <string>
0015 #include <type_traits>
0016 #include <utility>
0017 
0018 #include "absl/base/optimization.h"
0019 #include "absl/log/absl_log.h"
0020 #include "google/protobuf/extension_set.h"
0021 #include "google/protobuf/generated_message_tctable_decl.h"
0022 #include "google/protobuf/map.h"
0023 #include "google/protobuf/message_lite.h"
0024 #include "google/protobuf/metadata_lite.h"
0025 #include "google/protobuf/parse_context.h"
0026 #include "google/protobuf/port.h"
0027 #include "google/protobuf/raw_ptr.h"
0028 #include "google/protobuf/repeated_field.h"
0029 #include "google/protobuf/repeated_ptr_field.h"
0030 #include "google/protobuf/wire_format_lite.h"
0031 
0032 // Must come last:
0033 #include "google/protobuf/port_def.inc"
0034 
0035 namespace google {
0036 namespace protobuf {
0037 
0038 class Message;
0039 class UnknownFieldSet;
0040 
0041 namespace internal {
0042 
0043 enum {
0044   kInlinedStringAuxIdx = 0,
0045   kSplitOffsetAuxIdx = 1,
0046   kSplitSizeAuxIdx = 2,
0047 };
0048 
0049 // Field layout enums.
0050 //
0051 // Structural information about fields is packed into a 16-bit value. The enum
0052 // types below represent bitwise fields, along with their respective widths,
0053 // shifts, and masks.
0054 //
0055 //     Bit:
0056 //     +-----------------------+-----------------------+
0057 //     |15        ..          8|7         ..          0|
0058 //     +-----------------------+-----------------------+
0059 //     :  .  :  .  :  .  :  .  :  .  :  .  : 3|========| [3] FieldType
0060 //     :     :     :     :     :     :  . 4|==|  :     : [1] FieldSplit
0061 //     :     :     :     :     :    6|=====|  .  :     : [2] FieldCardinality
0062 //     :  .  :  .  :  .  : 9|========|  .  :  .  :  .  : [3] FieldRep
0063 //     :     :     :11|=====|  :     :     :     :     : [2] TransformValidation
0064 //     :  .  :13|=====|  :  .  :  .  :  .  :  .  :  .  : [2] FormatDiscriminator
0065 //     +-----------------------+-----------------------+
0066 //     |15        ..          8|7         ..          0|
0067 //     +-----------------------+-----------------------+
0068 //
0069 namespace field_layout {
0070 // clang-format off
0071 
0072 
0073 // Field kind (3 bits):
0074 // These values broadly represent a wire type and an in-memory storage class.
0075 enum FieldKind : uint16_t {
0076   kFkShift = 0,
0077   kFkBits = 3,
0078   kFkMask = ((1 << kFkBits) - 1) << kFkShift,
0079 
0080   kFkNone = 0,
0081   kFkVarint,        // WT=0     rep=8,32,64 bits
0082   kFkPackedVarint,  // WT=2     rep=8,32,64 bits
0083   kFkFixed,         // WT=1,5   rep=32,64 bits
0084   kFkPackedFixed,   // WT=2     rep=32,64 bits
0085   kFkString,        // WT=2     rep=various
0086   kFkMessage,       // WT=2,3,4 rep=MessageLite*
0087   // Maps are a special case of Message, but use different parsing logic.
0088   kFkMap,           // WT=2     rep=Map(Lite)<various, various>
0089 };
0090 
0091 static_assert(kFkMap < (1 << kFkBits), "too many types");
0092 
0093 // Split (1 bit):
0094 enum FieldSplit : uint16_t {
0095   kSplitShift = kFkShift+ kFkBits,
0096   kSplitBits  = 1,
0097   kSplitMask  = ((1 << kSplitBits) - 1) << kSplitShift,
0098 
0099   kSplitFalse = 0,
0100   kSplitTrue  = 1 << kSplitShift,
0101 };
0102 
0103 // Cardinality (2 bits):
0104 // These values determine how many values a field can have and its presence.
0105 // Packed fields are represented in FieldType.
0106 enum Cardinality : uint16_t {
0107   kFcShift    = kSplitShift+ kSplitBits,
0108   kFcBits     = 2,
0109   kFcMask     = ((1 << kFcBits) - 1) << kFcShift,
0110 
0111   kFcSingular = 0,
0112   kFcOptional = 1 << kFcShift,
0113   kFcRepeated = 2 << kFcShift,
0114   kFcOneof    = 3 << kFcShift,
0115 };
0116 
0117 
0118 // Field representation (3 bits):
0119 // These values are the specific refinements of storage classes in FieldType.
0120 enum FieldRep : uint16_t {
0121   kRepShift    = kFcShift + kFcBits,
0122   kRepBits     = 3,
0123   kRepMask     = ((1 << kRepBits) - 1) << kRepShift,
0124 
0125   // Numeric types (used for optional and repeated fields):
0126   kRep8Bits    = 0,
0127   kRep32Bits   = 2 << kRepShift,
0128   kRep64Bits   = 3 << kRepShift,
0129   // String types:
0130   kRepAString  = 0,               // ArenaStringPtr
0131   kRepIString  = 1 << kRepShift,  // InlinedString
0132   kRepCord     = 2 << kRepShift,  // absl::Cord
0133   kRepSPiece   = 3 << kRepShift,  // StringPieceField
0134   kRepSString  = 4 << kRepShift,  // std::string*
0135   // Message types (WT=2 unless otherwise noted):
0136   kRepMessage  = 0,               // MessageLite*
0137   kRepGroup    = 1 << kRepShift,  // MessageLite* (WT=3,4)
0138   kRepLazy     = 2 << kRepShift,  // LazyField*
0139 };
0140 
0141 // Transform/validation (2 bits):
0142 // These values determine transforms or validation to/from wire format.
0143 enum TransformValidation : uint16_t {
0144   kTvShift     = kRepShift + kRepBits,
0145   kTvBits      = 2,
0146   kTvMask      = ((1 << kTvBits) - 1) << kTvShift,
0147 
0148   // Varint fields:
0149   kTvZigZag    = 1 << kTvShift,
0150   kTvEnum      = 2 << kTvShift,  // validate using ValidateEnum()
0151   kTvRange     = 3 << kTvShift,  // validate using FieldAux::enum_range
0152   // String fields:
0153   kTvUtf8Debug = 1 << kTvShift,  // proto2
0154   kTvUtf8      = 2 << kTvShift,  // proto3
0155 
0156   // Message fields:
0157   kTvDefault   = 1 << kTvShift,  // Aux has default_instance*
0158   kTvTable     = 2 << kTvShift,  // Aux has TcParseTableBase*
0159   kTvWeakPtr   = 3 << kTvShift,  // Aux has default_instance** (for weak)
0160 
0161   // Lazy message fields:
0162   kTvEager     = 1 << kTvShift,
0163   kTvLazy      = 2 << kTvShift,
0164 };
0165 
0166 static_assert((kTvEnum & kTvRange) != 0,
0167               "enum validation types must share a bit");
0168 static_assert((kTvEnum & kTvRange & kTvZigZag) == 0,
0169               "zigzag encoding is not enum validation");
0170 
0171 // Format discriminators (2 bits):
0172 enum FormatDiscriminator : uint16_t {
0173   kFmtShift      = kTvShift + kTvBits,
0174   kFmtBits       = 2,
0175   kFmtMask       = ((1 << kFmtBits) - 1) << kFmtShift,
0176 
0177   // Numeric:
0178   kFmtUnsigned   = 1 << kFmtShift,  // fixed, varint
0179   kFmtSigned     = 2 << kFmtShift,  // fixed, varint
0180   kFmtFloating   = 3 << kFmtShift,  // fixed
0181   kFmtEnum       = 3 << kFmtShift,  // varint
0182   // Strings:
0183   kFmtUtf8       = 1 << kFmtShift,  // string (proto3, enforce_utf8=true)
0184   kFmtUtf8Escape = 2 << kFmtShift,  // string (proto2, enforce_utf8=false)
0185   // Bytes:
0186   kFmtArray      = 1 << kFmtShift,  // bytes
0187   // Messages:
0188   kFmtShow       = 1 << kFmtShift,  // message, map
0189 };
0190 
0191 // Update this assertion (and comments above) when adding or removing bits:
0192 static_assert(kFmtShift + kFmtBits == 13, "number of bits changed");
0193 
0194 // This assertion should not change unless the storage width changes:
0195 static_assert(kFmtShift + kFmtBits <= 16, "too many bits");
0196 
0197 // Convenience aliases (16 bits, with format):
0198 enum FieldType : uint16_t {
0199   // Numeric types:
0200   kBool            = 0 | kFkVarint | kRep8Bits,
0201 
0202   kFixed32         = 0 | kFkFixed  | kRep32Bits | kFmtUnsigned,
0203   kUInt32          = 0 | kFkVarint | kRep32Bits | kFmtUnsigned,
0204   kSFixed32        = 0 | kFkFixed  | kRep32Bits | kFmtSigned,
0205   kInt32           = 0 | kFkVarint | kRep32Bits | kFmtSigned,
0206   kSInt32          = 0 | kFkVarint | kRep32Bits | kFmtSigned | kTvZigZag,
0207   kFloat           = 0 | kFkFixed  | kRep32Bits | kFmtFloating,
0208   kEnum            = 0 | kFkVarint | kRep32Bits | kFmtEnum   | kTvEnum,
0209   kEnumRange       = 0 | kFkVarint | kRep32Bits | kFmtEnum   | kTvRange,
0210   kOpenEnum        = 0 | kFkVarint | kRep32Bits | kFmtEnum,
0211 
0212   kFixed64         = 0 | kFkFixed  | kRep64Bits | kFmtUnsigned,
0213   kUInt64          = 0 | kFkVarint | kRep64Bits | kFmtUnsigned,
0214   kSFixed64        = 0 | kFkFixed  | kRep64Bits | kFmtSigned,
0215   kInt64           = 0 | kFkVarint | kRep64Bits | kFmtSigned,
0216   kSInt64          = 0 | kFkVarint | kRep64Bits | kFmtSigned | kTvZigZag,
0217   kDouble          = 0 | kFkFixed  | kRep64Bits | kFmtFloating,
0218 
0219   kPackedBool      = 0 | kFkPackedVarint | kRep8Bits,
0220 
0221   kPackedFixed32   = 0 | kFkPackedFixed  | kRep32Bits | kFmtUnsigned,
0222   kPackedUInt32    = 0 | kFkPackedVarint | kRep32Bits | kFmtUnsigned,
0223   kPackedSFixed32  = 0 | kFkPackedFixed  | kRep32Bits | kFmtSigned,
0224   kPackedInt32     = 0 | kFkPackedVarint | kRep32Bits | kFmtSigned,
0225   kPackedSInt32    = 0 | kFkPackedVarint | kRep32Bits | kFmtSigned | kTvZigZag,
0226   kPackedFloat     = 0 | kFkPackedFixed  | kRep32Bits | kFmtFloating,
0227   kPackedEnum      = 0 | kFkPackedVarint | kRep32Bits | kFmtEnum   | kTvEnum,
0228   kPackedEnumRange = 0 | kFkPackedVarint | kRep32Bits | kFmtEnum   | kTvRange,
0229   kPackedOpenEnum  = 0 | kFkPackedVarint | kRep32Bits | kFmtEnum,
0230 
0231   kPackedFixed64   = 0 | kFkPackedFixed  | kRep64Bits | kFmtUnsigned,
0232   kPackedUInt64    = 0 | kFkPackedVarint | kRep64Bits | kFmtUnsigned,
0233   kPackedSFixed64  = 0 | kFkPackedFixed  | kRep64Bits | kFmtSigned,
0234   kPackedInt64     = 0 | kFkPackedVarint | kRep64Bits | kFmtSigned,
0235   kPackedSInt64    = 0 | kFkPackedVarint | kRep64Bits | kFmtSigned | kTvZigZag,
0236   kPackedDouble    = 0 | kFkPackedFixed  | kRep64Bits | kFmtFloating,
0237 
0238   // String types:
0239   kBytes           = 0 | kFkString | kFmtArray,
0240   kRawString       = 0 | kFkString | kFmtUtf8  | kTvUtf8Debug,
0241   kUtf8String      = 0 | kFkString | kFmtUtf8  | kTvUtf8,
0242 
0243   // Message types:
0244   kMessage         = kFkMessage,
0245 
0246   // Map types:
0247   kMap             = kFkMap,
0248 };
0249 // clang-format on
0250 }  // namespace field_layout
0251 
0252 #ifndef NDEBUG
0253 PROTOBUF_EXPORT void AlignFail(std::integral_constant<size_t, 4>,
0254                                std::uintptr_t address);
0255 PROTOBUF_EXPORT void AlignFail(std::integral_constant<size_t, 8>,
0256                                std::uintptr_t address);
0257 inline void AlignFail(std::integral_constant<size_t, 1>,
0258                       std::uintptr_t address) {}
0259 #endif
0260 
0261 #define PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(fn) \
0262   PROTOBUF_TC_PARSE_FUNCTION_X(fn##S1)             \
0263   PROTOBUF_TC_PARSE_FUNCTION_X(fn##S2)
0264 
0265 #define PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(fn) \
0266   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(fn)         \
0267   PROTOBUF_TC_PARSE_FUNCTION_X(fn##R1)               \
0268   PROTOBUF_TC_PARSE_FUNCTION_X(fn##R2)
0269 
0270 #define PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(fn) \
0271   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(fn)     \
0272   PROTOBUF_TC_PARSE_FUNCTION_X(fn##P1)             \
0273   PROTOBUF_TC_PARSE_FUNCTION_X(fn##P2)
0274 
0275 #define PROTOBUF_TC_PARSE_FUNCTION_LIST_END_GROUP() \
0276   PROTOBUF_TC_PARSE_FUNCTION_X(FastEndG1)           \
0277   PROTOBUF_TC_PARSE_FUNCTION_X(FastEndG2)
0278 
0279 // TcParseFunction defines the set of table driven, tail call optimized parse
0280 // functions. This list currently does not include all types such as maps.
0281 //
0282 // This table identifies the logical set of functions, it does not imply that
0283 // functions of the same name do exist, and some entries may point to thunks or
0284 // generic implementations accepting multiple types of input.
0285 //
0286 // The names are encoded as follows:
0287 //   kFast<type>[<validation>][cardinality][tag_width]
0288 //
0289 //   type:
0290 //     V8  - bool
0291 //     V32 - int32/uint32 varint
0292 //     Z32 - int32/uint32 varint with zigzag encoding
0293 //     V64 - int64/uint64 varint
0294 //     Z64 - int64/uint64 varint with zigzag encoding
0295 //     F32 - int32/uint32/float fixed width value
0296 //     F64 - int64/uint64/double fixed width value
0297 //     E   - enum
0298 //     B   - string (bytes)*
0299 //     S   - utf8 string, verified in debug mode only*
0300 //     U   - utf8 string, strictly verified*
0301 //     Gd  - group
0302 //     Gt  - group width table driven parse tables
0303 //     Md  - message
0304 //     Mt  - message width table driven parse tables
0305 //     End - End group tag
0306 //
0307 // * string types can have a `c` or `i` suffix, indicating the
0308 //   underlying storage type to be cord or inlined respectively.
0309 //
0310 //  validation:
0311 //    For enums:
0312 //      v  - verify
0313 //      r  - verify; enum values are a contiguous range
0314 //      r0 - verify; enum values are a small contiguous range starting at 0
0315 //      r1 - verify; enum values are a small contiguous range starting at 1
0316 //    For strings:
0317 //      u - validate utf8 encoding
0318 //      v - validate utf8 encoding for debug only
0319 //
0320 //  cardinality:
0321 //    S - singular / optional
0322 //    R - repeated
0323 //    P - packed
0324 //    G - group terminated
0325 //
0326 //  tag_width:
0327 //    1: single byte encoded tag
0328 //    2: two byte encoded tag
0329 //
0330 // Examples:
0331 //   FastV8S1, FastZ64S2, FastEr1P2, FastBcS1, FastMtR2, FastEndG1
0332 //
0333 #define PROTOBUF_TC_PARSE_FUNCTION_LIST                           \
0334   /* These functions have the Fast entry ABI */                   \
0335   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastV8)                  \
0336   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastV32)                 \
0337   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastV64)                 \
0338   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastZ32)                 \
0339   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastZ64)                 \
0340   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastF32)                 \
0341   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastF64)                 \
0342   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEv)                  \
0343   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr)                  \
0344   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr0)                 \
0345   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr1)                 \
0346   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastB)                 \
0347   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastS)                 \
0348   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastU)                 \
0349   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastBi)                  \
0350   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastSi)                  \
0351   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastUi)                  \
0352   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastBc)                  \
0353   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastSc)                  \
0354   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastUc)                  \
0355   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastGd)                \
0356   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastGt)                \
0357   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastMd)                \
0358   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastMt)                \
0359   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastMl)                  \
0360   PROTOBUF_TC_PARSE_FUNCTION_LIST_END_GROUP()                     \
0361   PROTOBUF_TC_PARSE_FUNCTION_X(MessageSetWireFormatParseLoopLite) \
0362   PROTOBUF_TC_PARSE_FUNCTION_X(MessageSetWireFormatParseLoop)     \
0363   PROTOBUF_TC_PARSE_FUNCTION_X(ReflectionParseLoop)               \
0364   /* These functions have the fallback ABI */                     \
0365   PROTOBUF_TC_PARSE_FUNCTION_X(GenericFallback)                   \
0366   PROTOBUF_TC_PARSE_FUNCTION_X(GenericFallbackLite)               \
0367   PROTOBUF_TC_PARSE_FUNCTION_X(ReflectionFallback)                \
0368   PROTOBUF_TC_PARSE_FUNCTION_X(DiscardEverythingFallback)
0369 
0370 #define PROTOBUF_TC_PARSE_FUNCTION_X(value) k##value,
0371 enum class TcParseFunction : uint8_t { kNone, PROTOBUF_TC_PARSE_FUNCTION_LIST };
0372 #undef PROTOBUF_TC_PARSE_FUNCTION_X
0373 
0374 // TcParser implements most of the parsing logic for tailcall tables.
0375 class PROTOBUF_EXPORT TcParser final {
0376  public:
0377   template <typename T>
0378   static constexpr auto GetTable() -> decltype(&T::_table_.header) {
0379     return &T::_table_.header;
0380   }
0381 
0382   static PROTOBUF_ALWAYS_INLINE const char* ParseMessage(
0383       MessageLite* msg, const char* ptr, ParseContext* ctx,
0384       const TcParseTableBase* tc_table) {
0385     return ctx->ParseLengthDelimitedInlined(ptr, [&](const char* ptr) {
0386       return ParseLoop(msg, ptr, ctx, tc_table);
0387     });
0388   }
0389 
0390   static PROTOBUF_ALWAYS_INLINE const char* ParseGroup(
0391       MessageLite* msg, const char* ptr, ParseContext* ctx,
0392       const TcParseTableBase* tc_table, uint32_t start_tag) {
0393     return ctx->ParseGroupInlined(ptr, start_tag, [&](const char* ptr) {
0394       return ParseLoop(msg, ptr, ctx, tc_table);
0395     });
0396   }
0397 
0398   // == ABI of the tail call functions ==
0399   // All the tail call functions have the same signature as required by clang's
0400   // `musttail` attribute. However, their ABIs are different.
0401   // See TcFieldData's comments for details on the layouts.
0402   // The ABIs are as follow:
0403   //
0404   //  - The following functions ignore `data`:
0405   //      ToTagDispatch, TagDispatch, MiniParse, ToParseLoop, Error,
0406   //      FastUnknownEnumFallback.
0407   //  - FastXXX functions expect `data` with a fast table entry ABI.
0408   //  - FastEndGX functions expect `data` with a non-field entry ABI.
0409   //  - MpXXX functions expect `data` with a mini table ABI.
0410   //  - The fallback functions (both GenericFallbackXXX and the codegen ones)
0411   //    expect only the tag in `data`. In addition, if a null `ptr` is passed,
0412   //    the function is used as a way to get a UnknownFieldOps vtable, returned
0413   //    via the `const char*` return type. See `GetUnknownFieldOps()`
0414 
0415   PROTOBUF_CC static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL);
0416   PROTOBUF_CC static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL);
0417   PROTOBUF_CC static const char* ReflectionFallback(PROTOBUF_TC_PARAM_DECL);
0418   PROTOBUF_CC static const char* ReflectionParseLoop(PROTOBUF_TC_PARAM_DECL);
0419 
0420   // This fallback will discard any field that reaches there.
0421   // Note that fields parsed via fast/MiniParse are not going to be discarded
0422   // even when this is enabled.
0423   PROTOBUF_CC static const char* DiscardEverythingFallback(
0424       PROTOBUF_TC_PARAM_DECL);
0425 
0426   // These follow the "fast" function ABI but implement the whole loop for
0427   // message_set_wire_format types.
0428   PROTOBUF_CC static const char* MessageSetWireFormatParseLoop(
0429       PROTOBUF_TC_PARAM_NO_DATA_DECL);
0430   PROTOBUF_CC static const char* MessageSetWireFormatParseLoopLite(
0431       PROTOBUF_TC_PARAM_NO_DATA_DECL);
0432 
0433   static const char* ParseLoop(MessageLite* msg, const char* ptr,
0434                                ParseContext* ctx,
0435                                const TcParseTableBase* table);
0436   PROTOBUF_NOINLINE PROTOBUF_CC static const char* ParseLoopPreserveNone(
0437       MessageLite* msg, const char* ptr, ParseContext* ctx,
0438       const TcParseTableBase* table);
0439 
0440   // Functions referenced by generated fast tables (numeric types):
0441   //   F: fixed      V: varint     Z: zigzag
0442   //   8/32/64: storage type width (bits)
0443   //   S: singular   R: repeated   P: packed
0444   //   1/2: tag length (bytes)
0445 
0446   // Fixed:
0447   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32S1(
0448       PROTOBUF_TC_PARAM_DECL);
0449   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32S2(
0450       PROTOBUF_TC_PARAM_DECL);
0451   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32R1(
0452       PROTOBUF_TC_PARAM_DECL);
0453   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32R2(
0454       PROTOBUF_TC_PARAM_DECL);
0455   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32P1(
0456       PROTOBUF_TC_PARAM_DECL);
0457   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32P2(
0458       PROTOBUF_TC_PARAM_DECL);
0459   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64S1(
0460       PROTOBUF_TC_PARAM_DECL);
0461   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64S2(
0462       PROTOBUF_TC_PARAM_DECL);
0463   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64R1(
0464       PROTOBUF_TC_PARAM_DECL);
0465   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64R2(
0466       PROTOBUF_TC_PARAM_DECL);
0467   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64P1(
0468       PROTOBUF_TC_PARAM_DECL);
0469   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64P2(
0470       PROTOBUF_TC_PARAM_DECL);
0471 
0472   // Varint:
0473   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8S1(
0474       PROTOBUF_TC_PARAM_DECL);
0475   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8S2(
0476       PROTOBUF_TC_PARAM_DECL);
0477   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8R1(
0478       PROTOBUF_TC_PARAM_DECL);
0479   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8R2(
0480       PROTOBUF_TC_PARAM_DECL);
0481   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8P1(
0482       PROTOBUF_TC_PARAM_DECL);
0483   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8P2(
0484       PROTOBUF_TC_PARAM_DECL);
0485   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32S1(
0486       PROTOBUF_TC_PARAM_DECL);
0487   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32S2(
0488       PROTOBUF_TC_PARAM_DECL);
0489   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32R1(
0490       PROTOBUF_TC_PARAM_DECL);
0491   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32R2(
0492       PROTOBUF_TC_PARAM_DECL);
0493   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32P1(
0494       PROTOBUF_TC_PARAM_DECL);
0495   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32P2(
0496       PROTOBUF_TC_PARAM_DECL);
0497   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64S1(
0498       PROTOBUF_TC_PARAM_DECL);
0499   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64S2(
0500       PROTOBUF_TC_PARAM_DECL);
0501   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64R1(
0502       PROTOBUF_TC_PARAM_DECL);
0503   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64R2(
0504       PROTOBUF_TC_PARAM_DECL);
0505   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64P1(
0506       PROTOBUF_TC_PARAM_DECL);
0507   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64P2(
0508       PROTOBUF_TC_PARAM_DECL);
0509 
0510   // Varint (with zigzag):
0511   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32S1(
0512       PROTOBUF_TC_PARAM_DECL);
0513   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32S2(
0514       PROTOBUF_TC_PARAM_DECL);
0515   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32R1(
0516       PROTOBUF_TC_PARAM_DECL);
0517   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32R2(
0518       PROTOBUF_TC_PARAM_DECL);
0519   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32P1(
0520       PROTOBUF_TC_PARAM_DECL);
0521   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32P2(
0522       PROTOBUF_TC_PARAM_DECL);
0523   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64S1(
0524       PROTOBUF_TC_PARAM_DECL);
0525   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64S2(
0526       PROTOBUF_TC_PARAM_DECL);
0527   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64R1(
0528       PROTOBUF_TC_PARAM_DECL);
0529   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64R2(
0530       PROTOBUF_TC_PARAM_DECL);
0531   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64P1(
0532       PROTOBUF_TC_PARAM_DECL);
0533   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64P2(
0534       PROTOBUF_TC_PARAM_DECL);
0535 
0536   template <typename FieldType, int unused_data_offset, int unused_hasbit_idx>
0537   static constexpr TailCallParseFunc SingularVarintNoZag1() {
0538     if (sizeof(FieldType) == 1) {
0539       return &FastV8S1;
0540     }
0541     if (sizeof(FieldType) == 4) {
0542       return &FastV32S1;
0543     }
0544     if (sizeof(FieldType) == 8) {
0545       return &FastV64S1;
0546     }
0547     static_assert(sizeof(FieldType) == 1 || sizeof(FieldType) == 4 ||
0548                       sizeof(FieldType) == 8,
0549                   "");
0550     ABSL_LOG(FATAL) << "This should be unreachable";
0551   }
0552 
0553   // Functions referenced by generated fast tables (closed enum):
0554   //   E: closed enum (N.B.: open enums use V32, above)
0555   //   r: enum range  v: enum validator (ValidateEnum function)
0556   //   S: singular   R: repeated   P: packed
0557   //   1/2: tag length (bytes)
0558   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErS1(
0559       PROTOBUF_TC_PARAM_DECL);
0560   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErS2(
0561       PROTOBUF_TC_PARAM_DECL);
0562   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErR1(
0563       PROTOBUF_TC_PARAM_DECL);
0564   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErR2(
0565       PROTOBUF_TC_PARAM_DECL);
0566   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErP1(
0567       PROTOBUF_TC_PARAM_DECL);
0568   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErP2(
0569       PROTOBUF_TC_PARAM_DECL);
0570   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvS1(
0571       PROTOBUF_TC_PARAM_DECL);
0572   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvS2(
0573       PROTOBUF_TC_PARAM_DECL);
0574   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvR1(
0575       PROTOBUF_TC_PARAM_DECL);
0576   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvR2(
0577       PROTOBUF_TC_PARAM_DECL);
0578   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvP1(
0579       PROTOBUF_TC_PARAM_DECL);
0580   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvP2(
0581       PROTOBUF_TC_PARAM_DECL);
0582 
0583   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0S1(
0584       PROTOBUF_TC_PARAM_DECL);
0585   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0S2(
0586       PROTOBUF_TC_PARAM_DECL);
0587   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0R1(
0588       PROTOBUF_TC_PARAM_DECL);
0589   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0R2(
0590       PROTOBUF_TC_PARAM_DECL);
0591   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0P1(
0592       PROTOBUF_TC_PARAM_DECL);
0593   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0P2(
0594       PROTOBUF_TC_PARAM_DECL);
0595   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1S1(
0596       PROTOBUF_TC_PARAM_DECL);
0597   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1S2(
0598       PROTOBUF_TC_PARAM_DECL);
0599   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1R1(
0600       PROTOBUF_TC_PARAM_DECL);
0601   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1R2(
0602       PROTOBUF_TC_PARAM_DECL);
0603   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1P1(
0604       PROTOBUF_TC_PARAM_DECL);
0605   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1P2(
0606       PROTOBUF_TC_PARAM_DECL);
0607 
0608   // Functions referenced by generated fast tables (string types):
0609   //   B: bytes      S: string     U: UTF-8 string
0610   //   (empty): ArenaStringPtr     i: InlinedString
0611   //   S: singular   R: repeated
0612   //   1/2: tag length (bytes)
0613   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBS1(
0614       PROTOBUF_TC_PARAM_DECL);
0615   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBS2(
0616       PROTOBUF_TC_PARAM_DECL);
0617   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBR1(
0618       PROTOBUF_TC_PARAM_DECL);
0619   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBR2(
0620       PROTOBUF_TC_PARAM_DECL);
0621   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSS1(
0622       PROTOBUF_TC_PARAM_DECL);
0623   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSS2(
0624       PROTOBUF_TC_PARAM_DECL);
0625   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSR1(
0626       PROTOBUF_TC_PARAM_DECL);
0627   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSR2(
0628       PROTOBUF_TC_PARAM_DECL);
0629   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUS1(
0630       PROTOBUF_TC_PARAM_DECL);
0631   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUS2(
0632       PROTOBUF_TC_PARAM_DECL);
0633   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUR1(
0634       PROTOBUF_TC_PARAM_DECL);
0635   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUR2(
0636       PROTOBUF_TC_PARAM_DECL);
0637 
0638   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBiS1(
0639       PROTOBUF_TC_PARAM_DECL);
0640   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBiS2(
0641       PROTOBUF_TC_PARAM_DECL);
0642   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSiS1(
0643       PROTOBUF_TC_PARAM_DECL);
0644   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSiS2(
0645       PROTOBUF_TC_PARAM_DECL);
0646   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUiS1(
0647       PROTOBUF_TC_PARAM_DECL);
0648   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUiS2(
0649       PROTOBUF_TC_PARAM_DECL);
0650 
0651   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBcS1(
0652       PROTOBUF_TC_PARAM_DECL);
0653   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBcS2(
0654       PROTOBUF_TC_PARAM_DECL);
0655   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastScS1(
0656       PROTOBUF_TC_PARAM_DECL);
0657   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastScS2(
0658       PROTOBUF_TC_PARAM_DECL);
0659   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUcS1(
0660       PROTOBUF_TC_PARAM_DECL);
0661   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUcS2(
0662       PROTOBUF_TC_PARAM_DECL);
0663 
0664   // Functions referenced by generated fast tables (message types):
0665   //   M: message    G: group
0666   //   d: default*   t: TcParseTable* (the contents of aux)  l: lazy
0667   //   S: singular   R: repeated
0668   //   1/2: tag length (bytes)
0669   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdS1(
0670       PROTOBUF_TC_PARAM_DECL);
0671   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdS2(
0672       PROTOBUF_TC_PARAM_DECL);
0673   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdS1(
0674       PROTOBUF_TC_PARAM_DECL);
0675   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdS2(
0676       PROTOBUF_TC_PARAM_DECL);
0677   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtS1(
0678       PROTOBUF_TC_PARAM_DECL);
0679   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtS2(
0680       PROTOBUF_TC_PARAM_DECL);
0681   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtS1(
0682       PROTOBUF_TC_PARAM_DECL);
0683   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtS2(
0684       PROTOBUF_TC_PARAM_DECL);
0685 
0686   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdR1(
0687       PROTOBUF_TC_PARAM_DECL);
0688   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdR2(
0689       PROTOBUF_TC_PARAM_DECL);
0690   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdR1(
0691       PROTOBUF_TC_PARAM_DECL);
0692   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdR2(
0693       PROTOBUF_TC_PARAM_DECL);
0694   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtR1(
0695       PROTOBUF_TC_PARAM_DECL);
0696   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtR2(
0697       PROTOBUF_TC_PARAM_DECL);
0698   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtR1(
0699       PROTOBUF_TC_PARAM_DECL);
0700   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtR2(
0701       PROTOBUF_TC_PARAM_DECL);
0702 
0703   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMlS1(
0704       PROTOBUF_TC_PARAM_DECL);
0705   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMlS2(
0706       PROTOBUF_TC_PARAM_DECL);
0707 
0708   // NOTE: Do not dedup RefAt by having one call the other with a const_cast. It
0709   // causes ICEs of gcc 7.5.
0710   // https://github.com/protocolbuffers/protobuf/issues/13715
0711   template <typename T>
0712   static inline T& RefAt(void* x, size_t offset) {
0713     T* target = reinterpret_cast<T*>(static_cast<char*>(x) + offset);
0714 #if !defined(NDEBUG) && !(defined(_MSC_VER) && defined(_M_IX86))
0715     // Check the alignment in debug mode, except in 32-bit msvc because it does
0716     // not respect the alignment as expressed by `alignof(T)`
0717     if (PROTOBUF_PREDICT_FALSE(
0718             reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
0719       AlignFail(std::integral_constant<size_t, alignof(T)>(),
0720                 reinterpret_cast<uintptr_t>(target));
0721       // Explicit abort to let compilers know this code-path does not return
0722       abort();
0723     }
0724 #endif
0725     return *target;
0726   }
0727 
0728   template <typename T>
0729   static inline const T& RefAt(const void* x, size_t offset) {
0730     const T* target =
0731         reinterpret_cast<const T*>(static_cast<const char*>(x) + offset);
0732 #if !defined(NDEBUG) && !(defined(_MSC_VER) && defined(_M_IX86))
0733     // Check the alignment in debug mode, except in 32-bit msvc because it does
0734     // not respect the alignment as expressed by `alignof(T)`
0735     if (PROTOBUF_PREDICT_FALSE(
0736             reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
0737       AlignFail(std::integral_constant<size_t, alignof(T)>(),
0738                 reinterpret_cast<uintptr_t>(target));
0739       // Explicit abort to let compilers know this code-path does not return
0740       abort();
0741     }
0742 #endif
0743     return *target;
0744   }
0745 
0746   static const TcParseTableBase* GetTableFromAux(
0747       uint16_t type_card, TcParseTableBase::FieldAux aux);
0748   static MessageLite* NewMessage(const TcParseTableBase* table, Arena* arena);
0749   static MessageLite* AddMessage(const TcParseTableBase* table,
0750                                  RepeatedPtrFieldBase& field);
0751 
0752   template <typename T, bool is_split>
0753   static inline T& MaybeCreateRepeatedRefAt(void* x, size_t offset,
0754                                             MessageLite* msg) {
0755     if (!is_split) return RefAt<T>(x, offset);
0756     void*& ptr = RefAt<void*>(x, offset);
0757     if (ptr == DefaultRawPtr()) {
0758       ptr = Arena::Create<T>(msg->GetArena());
0759     }
0760     return *static_cast<T*>(ptr);
0761   }
0762 
0763   template <typename T, bool is_split>
0764   static inline RepeatedField<T>& MaybeCreateRepeatedFieldRefAt(
0765       void* x, size_t offset, MessageLite* msg) {
0766     return MaybeCreateRepeatedRefAt<RepeatedField<T>, is_split>(x, offset, msg);
0767   }
0768 
0769   template <typename T, bool is_split>
0770   static inline RepeatedPtrField<T>& MaybeCreateRepeatedPtrFieldRefAt(
0771       void* x, size_t offset, MessageLite* msg) {
0772     return MaybeCreateRepeatedRefAt<RepeatedPtrField<T>, is_split>(x, offset,
0773                                                                    msg);
0774   }
0775 
0776   template <typename T>
0777   static inline T ReadAt(const void* x, size_t offset) {
0778     T out;
0779     memcpy(&out, static_cast<const char*>(x) + offset, sizeof(T));
0780     return out;
0781   }
0782 
0783   // Mini parsing:
0784   //
0785   // This function parses a field from incoming data based on metadata stored in
0786   // the message definition. If the field is not defined in the message, it is
0787   // stored in either the ExtensionSet (if applicable) or the UnknownFieldSet.
0788   //
0789   // NOTE: Currently, this function only calls the table-level fallback
0790   // function, so it should only be called as the fallback from fast table
0791   // parsing.
0792   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MiniParse(
0793       PROTOBUF_TC_PARAM_NO_DATA_DECL);
0794 
0795   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEndG1(
0796       PROTOBUF_TC_PARAM_DECL);
0797   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEndG2(
0798       PROTOBUF_TC_PARAM_DECL);
0799 
0800   // For `map` mini parsing generate a type card for the key/value.
0801   template <typename MapField>
0802   static constexpr MapAuxInfo GetMapAuxInfo(bool fail_on_utf8_failure,
0803                                             bool log_debug_utf8_failure,
0804                                             bool validated_enum_value,
0805                                             int key_type, int value_type) {
0806     using MapType = typename MapField::MapType;
0807     using Node = typename MapType::Node;
0808     static_assert(alignof(Node) == alignof(NodeBase), "");
0809     // Verify the assumption made in MpMap, guaranteed by Map<>.
0810     assert(PROTOBUF_FIELD_OFFSET(Node, kv.first) == sizeof(NodeBase));
0811     return {
0812         MakeMapTypeCard(static_cast<WireFormatLite::FieldType>(key_type)),
0813         MakeMapTypeCard(static_cast<WireFormatLite::FieldType>(value_type)),
0814         true,
0815         !std::is_base_of<MapFieldBaseForParse, MapField>::value,
0816         fail_on_utf8_failure,
0817         log_debug_utf8_failure,
0818         validated_enum_value,
0819         Node::size_info(),
0820     };
0821   }
0822 
0823   template <typename T>
0824   static void CreateInArenaStorageCb(Arena* arena, void* p) {
0825     Arena::CreateInArenaStorage(static_cast<T*>(p), arena);
0826   }
0827 
0828  private:
0829   // Optimized small tag varint parser for int32/int64
0830   template <typename FieldType>
0831   PROTOBUF_CC static const char* FastVarintS1(PROTOBUF_TC_PARAM_DECL);
0832 
0833   friend class GeneratedTcTableLiteTest;
0834   static void* MaybeGetSplitBase(MessageLite* msg, bool is_split,
0835                                  const TcParseTableBase* table);
0836 
0837   // Test only access to verify that the right function is being called via
0838   // MiniParse.
0839   struct TestMiniParseResult {
0840     TailCallParseFunc called_func;
0841     uint32_t tag;
0842     const TcParseTableBase::FieldEntry* found_entry;
0843     const char* ptr;
0844   };
0845   PROTOBUF_NOINLINE
0846   static TestMiniParseResult TestMiniParse(PROTOBUF_TC_PARAM_DECL);
0847   template <bool export_called_function>
0848   PROTOBUF_CC static const char* MiniParse(PROTOBUF_TC_PARAM_DECL);
0849 
0850   template <typename TagType, bool group_coding, bool aux_is_table>
0851   PROTOBUF_CC static inline const char* SingularParseMessageAuxImpl(
0852       PROTOBUF_TC_PARAM_DECL);
0853   template <typename TagType, bool group_coding, bool aux_is_table>
0854   PROTOBUF_CC static inline const char* RepeatedParseMessageAuxImpl(
0855       PROTOBUF_TC_PARAM_DECL);
0856   template <typename TagType>
0857   PROTOBUF_CC static inline const char* LazyMessage(PROTOBUF_TC_PARAM_DECL);
0858 
0859   template <typename TagType>
0860   PROTOBUF_CC static const char* FastEndGroupImpl(PROTOBUF_TC_PARAM_DECL);
0861 
0862   static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
0863       MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) {
0864     const uint32_t has_bits_offset = table->has_bits_offset;
0865     if (has_bits_offset) {
0866       // Only the first 32 has-bits are updated. Nothing above those is stored,
0867       // but e.g. messages without has-bits update the upper bits.
0868       RefAt<uint32_t>(msg, has_bits_offset) |= static_cast<uint32_t>(hasbits);
0869     }
0870   }
0871 
0872   PROTOBUF_CC static const char* TagDispatch(PROTOBUF_TC_PARAM_NO_DATA_DECL);
0873   PROTOBUF_CC static const char* ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_DECL);
0874   PROTOBUF_CC static const char* ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_DECL);
0875   PROTOBUF_NOINLINE
0876   PROTOBUF_CC static const char* Error(PROTOBUF_TC_PARAM_NO_DATA_DECL);
0877 
0878   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUnknownEnumFallback(
0879       PROTOBUF_TC_PARAM_DECL);
0880   PROTOBUF_NOINLINE
0881   PROTOBUF_CC static const char* MpUnknownEnumFallback(PROTOBUF_TC_PARAM_DECL);
0882 
0883   class ScopedArenaSwap;
0884 
0885   struct UnknownFieldOps {
0886     void (*write_varint)(MessageLite* msg, int number, int value);
0887     void (*write_length_delimited)(MessageLite* msg, int number,
0888                                    absl::string_view value);
0889   };
0890 
0891   static const UnknownFieldOps& GetUnknownFieldOps(
0892       const TcParseTableBase* table);
0893 
0894   template <typename UnknownFieldsT>
0895   static void WriteVarintToUnknown(MessageLite* msg, int number, int value) {
0896     internal::WriteVarint(
0897         number, value,
0898         msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>());
0899   }
0900   template <typename UnknownFieldsT>
0901   static void WriteLengthDelimitedToUnknown(MessageLite* msg, int number,
0902                                             absl::string_view value) {
0903     internal::WriteLengthDelimited(
0904         number, value,
0905         msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>());
0906   }
0907 
0908   template <class MessageBaseT, class UnknownFieldsT>
0909   PROTOBUF_CC static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) {
0910     if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) {
0911       // This is the ABI used by GetUnknownFieldOps(). Return the vtable.
0912       static constexpr UnknownFieldOps kOps = {
0913           WriteVarintToUnknown<UnknownFieldsT>,
0914           WriteLengthDelimitedToUnknown<UnknownFieldsT>};
0915       return reinterpret_cast<const char*>(&kOps);
0916     }
0917 
0918     SyncHasbits(msg, hasbits, table);
0919     uint32_t tag = data.tag();
0920     if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) {
0921       ctx->SetLastTag(tag);
0922       return ptr;
0923     }
0924 
0925     if (table->extension_offset != 0) {
0926       // We don't need to check the extension ranges. If it is not an extension
0927       // it will be handled just like if it was an unknown extension: sent to
0928       // the unknown field set.
0929       return RefAt<ExtensionSet>(msg, table->extension_offset)
0930           .ParseField(
0931               tag, ptr,
0932               static_cast<const MessageBaseT*>(table->default_instance()),
0933               &msg->_internal_metadata_, ctx);
0934     } else {
0935       // Otherwise, we directly put it on the unknown field set.
0936       return UnknownFieldParse(
0937           tag,
0938           msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(),
0939           ptr, ctx);
0940     }
0941   }
0942 
0943   template <class MessageBaseT>
0944   PROTOBUF_CC static const char* MessageSetWireFormatParseLoopImpl(
0945       PROTOBUF_TC_PARAM_NO_DATA_DECL) {
0946     return RefAt<ExtensionSet>(msg, table->extension_offset)
0947         .ParseMessageSet(
0948             ptr, static_cast<const MessageBaseT*>(table->default_instance()),
0949             &msg->_internal_metadata_, ctx);
0950   }
0951 
0952   // Note: `inline` is needed on template function declarations below to avoid
0953   // -Wattributes diagnostic in GCC.
0954 
0955   // Implementations for fast fixed field parsing functions:
0956   template <typename LayoutType, typename TagType>
0957   PROTOBUF_CC static inline const char* SingularFixed(PROTOBUF_TC_PARAM_DECL);
0958   template <typename LayoutType, typename TagType>
0959   PROTOBUF_CC static inline const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL);
0960   template <typename LayoutType, typename TagType>
0961   PROTOBUF_CC static inline const char* PackedFixed(PROTOBUF_TC_PARAM_DECL);
0962 
0963   // Implementations for fast varint field parsing functions:
0964   template <typename FieldType, typename TagType, bool zigzag = false>
0965   PROTOBUF_CC static inline const char* SingularVarint(PROTOBUF_TC_PARAM_DECL);
0966   template <typename FieldType, typename TagType, bool zigzag = false>
0967   PROTOBUF_CC static inline const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL);
0968   template <typename FieldType, typename TagType, bool zigzag = false>
0969   PROTOBUF_CC static inline const char* PackedVarint(PROTOBUF_TC_PARAM_DECL);
0970 
0971   // Helper for ints > 127:
0972   template <typename FieldType, typename TagType, bool zigzag = false>
0973   PROTOBUF_NOINLINE PROTOBUF_CC static const char* SingularVarBigint(
0974       PROTOBUF_TC_PARAM_DECL);
0975 
0976   // Implementations for fast enum field parsing functions:
0977   template <typename TagType, uint16_t xform_val>
0978   PROTOBUF_CC static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL);
0979   template <typename TagType, uint8_t min>
0980   PROTOBUF_CC static inline const char* SingularEnumSmallRange(
0981       PROTOBUF_TC_PARAM_DECL);
0982   template <typename TagType, uint16_t xform_val>
0983   PROTOBUF_CC static inline const char* RepeatedEnum(PROTOBUF_TC_PARAM_DECL);
0984   template <typename TagType, uint16_t xform_val>
0985   PROTOBUF_CC static inline const char* PackedEnum(PROTOBUF_TC_PARAM_DECL);
0986   template <typename TagType, uint8_t min>
0987   PROTOBUF_CC static inline const char* RepeatedEnumSmallRange(
0988       PROTOBUF_TC_PARAM_DECL);
0989   template <typename TagType, uint8_t min>
0990   PROTOBUF_CC static inline const char* PackedEnumSmallRange(
0991       PROTOBUF_TC_PARAM_DECL);
0992 
0993   // Implementations for fast string field parsing functions:
0994   enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
0995   template <typename TagType, typename FieldType, Utf8Type utf8>
0996   PROTOBUF_CC static inline const char* SingularString(PROTOBUF_TC_PARAM_DECL);
0997   template <typename TagType, typename FieldType, Utf8Type utf8>
0998   PROTOBUF_CC static inline const char* RepeatedString(PROTOBUF_TC_PARAM_DECL);
0999 
1000   static inline const char* ParseRepeatedStringOnce(
1001       const char* ptr, SerialArena* serial_arena, ParseContext* ctx,
1002       RepeatedPtrField<std::string>& field);
1003 
1004   PROTOBUF_NOINLINE
1005   static void AddUnknownEnum(MessageLite* msg, const TcParseTableBase* table,
1006                              uint32_t tag, int32_t enum_value);
1007 
1008   static void WriteMapEntryAsUnknown(MessageLite* msg,
1009                                      const TcParseTableBase* table,
1010                                      uint32_t tag, NodeBase* node,
1011                                      MapAuxInfo map_info);
1012 
1013   static void InitializeMapNodeEntry(void* obj, MapTypeCard type_card,
1014                                      UntypedMapBase& map,
1015                                      const TcParseTableBase::FieldAux* aux,
1016                                      bool is_key);
1017   PROTOBUF_NOINLINE
1018   static void DestroyMapNode(NodeBase* node, MapAuxInfo map_info,
1019                              UntypedMapBase& map);
1020   static const char* ParseOneMapEntry(NodeBase* node, const char* ptr,
1021                                       ParseContext* ctx,
1022                                       const TcParseTableBase::FieldAux* aux,
1023                                       const TcParseTableBase* table,
1024                                       const TcParseTableBase::FieldEntry& entry,
1025                                       Arena* arena);
1026 
1027   // Mini field lookup:
1028   static const TcParseTableBase::FieldEntry* FindFieldEntry(
1029       const TcParseTableBase* table, uint32_t field_num);
1030   static absl::string_view MessageName(const TcParseTableBase* table);
1031   static absl::string_view FieldName(const TcParseTableBase* table,
1032                                      const TcParseTableBase::FieldEntry*);
1033   static bool ChangeOneof(const TcParseTableBase* table,
1034                           const TcParseTableBase::FieldEntry& entry,
1035                           uint32_t field_num, ParseContext* ctx,
1036                           MessageLite* msg);
1037 
1038   // UTF-8 validation:
1039   static void ReportFastUtf8Error(uint32_t decoded_tag,
1040                                   const TcParseTableBase* table);
1041   static bool MpVerifyUtf8(absl::string_view wire_bytes,
1042                            const TcParseTableBase* table,
1043                            const TcParseTableBase::FieldEntry& entry,
1044                            uint16_t xform_val);
1045   static bool MpVerifyUtf8(const absl::Cord& wire_bytes,
1046                            const TcParseTableBase* table,
1047                            const TcParseTableBase::FieldEntry& entry,
1048                            uint16_t xform_val);
1049 
1050   // For FindFieldEntry tests:
1051   friend class FindFieldEntryTest;
1052   friend struct ParseFunctionGeneratorTestPeer;
1053   friend struct FuzzPeer;
1054   static constexpr const uint32_t kMtSmallScanSize = 4;
1055 
1056   // Mini parsing:
1057   template <bool is_split>
1058   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpVarint(
1059       PROTOBUF_TC_PARAM_DECL);
1060   template <bool is_split>
1061   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpRepeatedVarint(
1062       PROTOBUF_TC_PARAM_DECL);
1063   template <bool is_split, typename FieldType, uint16_t xform_val>
1064   PROTOBUF_CC static const char* MpRepeatedVarintT(PROTOBUF_TC_PARAM_DECL);
1065   template <bool is_split>
1066   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpPackedVarint(
1067       PROTOBUF_TC_PARAM_DECL);
1068   template <bool is_split, typename FieldType, uint16_t xform_val>
1069   PROTOBUF_CC static const char* MpPackedVarintT(PROTOBUF_TC_PARAM_DECL);
1070   template <bool is_split>
1071   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpFixed(
1072       PROTOBUF_TC_PARAM_DECL);
1073   template <bool is_split>
1074   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpRepeatedFixed(
1075       PROTOBUF_TC_PARAM_DECL);
1076   template <bool is_split>
1077   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpPackedFixed(
1078       PROTOBUF_TC_PARAM_DECL);
1079   template <bool is_split>
1080   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpString(
1081       PROTOBUF_TC_PARAM_DECL);
1082   template <bool is_split>
1083   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpRepeatedString(
1084       PROTOBUF_TC_PARAM_DECL);
1085   template <bool is_split>
1086   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpMessage(
1087       PROTOBUF_TC_PARAM_DECL);
1088   template <bool is_split, bool is_group>
1089   PROTOBUF_CC static const char* MpRepeatedMessageOrGroup(
1090       PROTOBUF_TC_PARAM_DECL);
1091   PROTOBUF_CC static const char* MpLazyMessage(PROTOBUF_TC_PARAM_DECL);
1092   PROTOBUF_NOINLINE
1093   PROTOBUF_CC static const char* MpFallback(PROTOBUF_TC_PARAM_DECL);
1094   template <bool is_split>
1095   PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpMap(
1096       PROTOBUF_TC_PARAM_DECL);
1097 };
1098 
1099 // Dispatch to the designated parse function
1100 inline PROTOBUF_ALWAYS_INLINE const char* TcParser::TagDispatch(
1101     PROTOBUF_TC_PARAM_NO_DATA_DECL) {
1102   const auto coded_tag = UnalignedLoad<uint16_t>(ptr);
1103   const size_t idx = coded_tag & table->fast_idx_mask;
1104   PROTOBUF_ASSUME((idx & 7) == 0);
1105   auto* fast_entry = table->fast_entry(idx >> 3);
1106   TcFieldData data = fast_entry->bits;
1107   data.data ^= coded_tag;
1108   PROTOBUF_MUSTTAIL return fast_entry->target()(PROTOBUF_TC_PARAM_PASS);
1109 }
1110 
1111 // We can only safely call from field to next field if the call is optimized
1112 // to a proper tail call. Otherwise we blow through stack. Clang and gcc
1113 // reliably do this optimization in opt mode, but do not perform this in debug
1114 // mode. Luckily the structure of the algorithm is such that it's always
1115 // possible to just return and use the enclosing parse loop as a trampoline.
1116 inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToTagDispatch(
1117     PROTOBUF_TC_PARAM_NO_DATA_DECL) {
1118   constexpr bool always_return = !PROTOBUF_TAILCALL;
1119   if (always_return || !ctx->DataAvailable(ptr)) {
1120     PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS);
1121   }
1122   PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS);
1123 }
1124 
1125 inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop(
1126     PROTOBUF_TC_PARAM_NO_DATA_DECL) {
1127   (void)ctx;
1128   SyncHasbits(msg, hasbits, table);
1129   return ptr;
1130 }
1131 
1132 inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoop(
1133     MessageLite* msg, const char* ptr, ParseContext* ctx,
1134     const TcParseTableBase* table) {
1135   // Note: TagDispatch uses a dispatch table at "&table->fast_entries".
1136   // For fast dispatch, we'd like to have a pointer to that, but if we use
1137   // that expression, there's no easy way to get back to "table", which we also
1138   // need during dispatch.  It turns out that "table + 1" points exactly to
1139   // fast_entries, so we just increment table by 1 here, to get the register
1140   // holding the value we want.
1141   table += 1;
1142   while (!ctx->Done(&ptr)) {
1143 #if defined(__GNUC__)
1144     // Note: this asm prevents the compiler (clang, specifically) from
1145     // believing (thanks to CSE) that it needs to dedicate a register both
1146     // to "table" and "&table->fast_entries".
1147     // TODO: remove this asm
1148     asm("" : "+r"(table));
1149 #endif
1150     ptr = TagDispatch(msg, ptr, ctx, TcFieldData::DefaultInit(), table - 1, 0);
1151     if (ptr == nullptr) break;
1152     if (ctx->LastTag() != 1) break;  // Ended on terminating tag
1153   }
1154   table -= 1;
1155   if (ABSL_PREDICT_FALSE(table->has_post_loop_handler)) {
1156     return table->post_loop_handler(msg, ptr, ctx);
1157   }
1158   return ptr;
1159 }
1160 
1161 // Prints the type card as or of labels, using known higher level labels.
1162 // Used for code generation, but also useful for debugging.
1163 PROTOBUF_EXPORT std::string TypeCardToString(uint16_t type_card);
1164 
1165 }  // namespace internal
1166 }  // namespace protobuf
1167 }  // namespace google
1168 
1169 #include "google/protobuf/port_undef.inc"
1170 
1171 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__