• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
13 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
14 
15 #include <cstddef>
16 #include <cstdint>
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "absl/container/flat_hash_map.h"
23 #include "absl/strings/string_view.h"
24 #include "google/protobuf/compiler/cpp/enum.h"
25 #include "google/protobuf/compiler/cpp/extension.h"
26 #include "google/protobuf/compiler/cpp/field.h"
27 #include "google/protobuf/compiler/cpp/helpers.h"
28 #include "google/protobuf/compiler/cpp/message_layout_helper.h"
29 #include "google/protobuf/compiler/cpp/options.h"
30 #include "google/protobuf/compiler/cpp/parse_function_generator.h"
31 #include "google/protobuf/descriptor.h"
32 #include "google/protobuf/io/printer.h"
33 
34 namespace google {
35 namespace protobuf {
36 namespace compiler {
37 namespace cpp {
38 class MessageGenerator {
39  public:
40   MessageGenerator(
41       const Descriptor* descriptor,
42       const absl::flat_hash_map<absl::string_view, std::string>& ignored,
43       int index_in_file_messages, const Options& options,
44       MessageSCCAnalyzer* scc_analyzer);
45 
46   MessageGenerator(const MessageGenerator&) = delete;
47   MessageGenerator& operator=(const MessageGenerator&) = delete;
48 
49   ~MessageGenerator() = default;
50 
index_in_file_messages()51   int index_in_file_messages() const { return index_in_file_messages_; }
52 
53   // Append the two types of nested generators to the corresponding vector.
54   void AddGenerators(
55       std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
56       std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
57 
58   // Generate definitions for this class and all its nested types.
59   void GenerateClassDefinition(io::Printer* p);
60 
61   // Generate definitions of inline methods (placed at the end of the header
62   // file).
63   void GenerateInlineMethods(io::Printer* p);
64 
65   // Generate all non-inline methods for this class.
66   void GenerateClassMethods(io::Printer* p);
67 
68   // Generate source file code that should go outside any namespace.
69   void GenerateSourceInProto2Namespace(io::Printer* p);
70 
71 
72   void GenerateInitDefaultSplitInstance(io::Printer* p);
73 
74   // Generate the constexpr constructor for constant initialization of the
75   // default instance.
76   void GenerateConstexprConstructor(io::Printer* p);
77 
78   void GenerateSchema(io::Printer* p, int offset, int has_offset);
79 
80   // Generate the field offsets array.  Returns the a pair of the total number
81   // of entries generated and the index of the first has_bit entry.
82   std::pair<size_t, size_t> GenerateOffsets(io::Printer* p);
83 
descriptor()84   const Descriptor* descriptor() const { return descriptor_; }
85 
86  private:
87   using GeneratorFunction = FieldGeneratorBase::GeneratorFunction;
88   enum class InitType { kConstexpr, kArena, kArenaCopy };
89 
90   // Generate declarations and definitions of accessors for fields.
91   void GenerateFieldAccessorDeclarations(io::Printer* p);
92   void GenerateFieldAccessorDefinitions(io::Printer* p);
93 
94   // Generate constructors and destructor.
95   void GenerateStructors(io::Printer* p);
96 
97   void GenerateZeroInitFields(io::Printer* p) const;
98   void GenerateCopyInitFields(io::Printer* p) const;
99 
100   void GenerateImplMemberInit(io::Printer* p, InitType init_type);
101 
102   void GenerateArenaEnabledCopyConstructor(io::Printer* p);
103 
104   // The compiler typically generates multiple copies of each constructor and
105   // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
106   // Placing common code in a separate method reduces the generated code size.
107   //
108   // Generate the shared constructor code.
109   void GenerateSharedConstructorCode(io::Printer* p);
110 
111   // Generate the shared destructor code.
112   void GenerateSharedDestructorCode(io::Printer* p);
113   // Generate the arena-specific destructor code.
114   void GenerateArenaDestructorCode(io::Printer* p);
115 
116   // Generate standard Message methods.
117   void GenerateClear(io::Printer* p);
118   void GenerateOneofClear(io::Printer* p);
119   void GenerateVerifyDecl(io::Printer* p);
120   void GenerateVerify(io::Printer* p);
121   void GenerateAnnotationDecl(io::Printer* p);
122   void GenerateSerializeWithCachedSizes(io::Printer* p);
123   void GenerateSerializeWithCachedSizesToArray(io::Printer* p);
124   void GenerateSerializeWithCachedSizesBody(io::Printer* p);
125   void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* p);
126   void GenerateByteSize(io::Printer* p);
127   void GenerateClassData(io::Printer* p);
128   void GenerateMapEntryClassDefinition(io::Printer* p);
129   void GenerateAnyMethodDefinition(io::Printer* p);
130   void GenerateImplDefinition(io::Printer* p);
131   void GenerateClassSpecificMergeImpl(io::Printer* p);
132   void GenerateCopyFrom(io::Printer* p);
133   void GenerateSwap(io::Printer* p);
134   void GenerateIsInitialized(io::Printer* p);
135   bool NeedsIsInitialized();
136 
137   struct NewOpRequirements {
138     // Some field is initialized to non-zero values. Eg string fields pointing
139     // to default string.
140     bool needs_memcpy = false;
141     // Some field has a copy of the arena.
142     bool needs_arena_seeding = false;
143     // Some field has logic that needs to run.
144     bool needs_to_run_constructor = false;
145   };
146   NewOpRequirements GetNewOp(io::Printer* arena_emitter) const;
147 
148   // Helpers for GenerateSerializeWithCachedSizes().
149   //
150   // cached_has_bit_index maintains that:
151   //   cached_has_bits = _has_bits_[cached_has_bit_index]
152   // for cached_has_bit_index >= 0
153   void GenerateSerializeOneField(io::Printer* p, const FieldDescriptor* field,
154                                  int cached_has_bits_index);
155   // Generate a switch statement to serialize 2+ fields from the same oneof.
156   // Or, if fields.size() == 1, just call GenerateSerializeOneField().
157   void GenerateSerializeOneofFields(
158       io::Printer* p, const std::vector<const FieldDescriptor*>& fields);
159   void GenerateSerializeOneExtensionRange(io::Printer* p, int start, int end);
160 
161   // Generates has_foo() functions and variables for singular field has-bits.
162   void GenerateSingularFieldHasBits(const FieldDescriptor* field,
163                                     io::Printer* p);
164   // Generates has_foo() functions and variables for oneof field has-bits.
165   void GenerateOneofHasBits(io::Printer* p);
166   // Generates has_foo_bar() functions for oneof members.
167   void GenerateOneofMemberHasBits(const FieldDescriptor* field, io::Printer* p);
168   // Generates the clear_foo() method for a field.
169   void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
170                           io::Printer* p);
171 
172   // Returns true if any of the fields needs an `arena` variable containing
173   // the current message's arena, reducing `GetArena()` call churn.
174   bool RequiresArena(GeneratorFunction function) const;
175 
176   // Returns whether impl_ has a copy ctor.
177   bool ImplHasCopyCtor() const;
178 
179   // Returns the level that this message needs ArenaDtor. If the message has
180   // a field that is not arena-exclusive, it needs an ArenaDtor
181   // (go/proto-destructor).
182   //
183   // - Returning kNone means we don't need to generate ArenaDtor.
184   // - Returning kOnDemand means we need to generate ArenaDtor, but don't need
185   //   to register ArenaDtor at construction. Such as when the message's
186   //   ArenaDtor code is only for destructing inlined string.
187   // - Returning kRequired means we meed to generate ArenaDtor and register it
188   //   at construction.
189   ArenaDtorNeeds NeedsArenaDestructor() const;
190 
191   size_t HasBitsSize() const;
192   size_t InlinedStringDonatedSize() const;
193   absl::flat_hash_map<absl::string_view, std::string> HasBitVars(
194       const FieldDescriptor* field) const;
195   int HasBitIndex(const FieldDescriptor* field) const;
196   int HasByteIndex(const FieldDescriptor* field) const;
197   int HasWordIndex(const FieldDescriptor* field) const;
198   std::vector<uint32_t> RequiredFieldsBitMask() const;
199 
200   // Helper functions to reduce nesting levels of deep Emit calls.
201   void EmitCheckAndUpdateByteSizeForField(const FieldDescriptor* field,
202                                           io::Printer* p) const;
203   void EmitUpdateByteSizeForField(const FieldDescriptor* field, io::Printer* p,
204                                   int& cached_has_word_index) const;
205 
206   const Descriptor* descriptor_;
207   int index_in_file_messages_;
208   Options options_;
209   FieldGeneratorTable field_generators_;
210   // optimized_order_ is the order we layout the message's fields in the
211   // class. This is reused to initialize the fields in-order for cache
212   // efficiency.
213   //
214   // optimized_order_ excludes oneof fields and weak fields.
215   std::vector<const FieldDescriptor*> optimized_order_;
216   std::vector<int> has_bit_indices_;
217   int max_has_bit_index_ = 0;
218 
219   // A map from field index to inlined_string index. For non-inlined-string
220   // fields, the element is -1. If there is no inlined string in the message,
221   // this is empty.
222   std::vector<int> inlined_string_indices_;
223   // The count of inlined_string fields in the message.
224   int max_inlined_string_index_ = 0;
225 
226   std::vector<const EnumGenerator*> enum_generators_;
227   std::vector<const ExtensionGenerator*> extension_generators_;
228   int num_required_fields_ = 0;
229   int num_weak_fields_ = 0;
230 
231   std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
232   std::unique_ptr<ParseFunctionGenerator> parse_function_generator_;
233 
234   MessageSCCAnalyzer* scc_analyzer_;
235 
236   absl::flat_hash_map<absl::string_view, std::string> variables_;
237 
238 };
239 
240 }  // namespace cpp
241 }  // namespace compiler
242 }  // namespace protobuf
243 }  // namespace google
244 
245 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
246