protoc-gen-upb.cc
Go to the documentation of this file.
1 // Copyright (c) 2009-2021, Google LLC
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of Google LLC nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 // ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
19 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include <memory>
27 
28 #include "absl/container/flat_hash_map.h"
29 #include "absl/container/flat_hash_set.h"
30 #include "absl/strings/ascii.h"
31 #include "absl/strings/substitute.h"
32 #include "google/protobuf/compiler/code_generator.h"
33 #include "google/protobuf/compiler/plugin.h"
34 #include "google/protobuf/descriptor.h"
35 #include "google/protobuf/descriptor.pb.h"
36 #include "google/protobuf/wire_format.h"
37 #include "upb/mini_table.hpp"
38 #include "upb/upb.hpp"
39 #include "upbc/common.h"
40 
41 // Must be last.
42 #include "upb/port_def.inc"
43 
44 namespace upbc {
45 namespace {
46 
47 namespace protoc = ::google::protobuf::compiler;
48 namespace protobuf = ::google::protobuf;
49 
50 // Returns fields in order of "hotness", eg. how frequently they appear in
51 // serialized payloads. Ideally this will use a profile. When we don't have
52 // that, we assume that fields with smaller numbers are used more frequently.
53 inline std::vector<const google::protobuf::FieldDescriptor*> FieldHotnessOrder(
55  std::vector<const google::protobuf::FieldDescriptor*> fields;
56  for (int i = 0; i < message->field_count(); i++) {
57  fields.push_back(message->field(i));
58  }
59  std::sort(fields.begin(), fields.end(),
62  return std::make_pair(!a->is_required(), a->number()) <
63  std::make_pair(!b->is_required(), b->number());
64  });
65  return fields;
66 }
67 
68 std::string SourceFilename(const google::protobuf::FileDescriptor* file) {
69  return StripExtension(file->name()) + ".upb.c";
70 }
71 
72 std::string MessageInit(const protobuf::Descriptor* descriptor) {
73  return MessageName(descriptor) + "_msginit";
74 }
75 
77  return ToCIdent(descriptor->full_name()) + "_enuminit";
78 }
79 
80 std::string ExtensionIdentBase(const protobuf::FieldDescriptor* ext) {
81  assert(ext->is_extension());
82  std::string ext_scope;
83  if (ext->extension_scope()) {
84  return MessageName(ext->extension_scope());
85  } else {
86  return ToCIdent(ext->file()->package());
87  }
88 }
89 
90 std::string ExtensionLayout(const google::protobuf::FieldDescriptor* ext) {
91  return absl::StrCat(ExtensionIdentBase(ext), "_", ext->name(), "_ext");
92 }
93 
94 const char* kEnumsInit = "enums_layout";
95 const char* kExtensionsInit = "extensions_layout";
96 const char* kMessagesInit = "messages_layout";
97 
98 void AddEnums(const protobuf::Descriptor* message,
99  std::vector<const protobuf::EnumDescriptor*>* enums) {
100  enums->reserve(enums->size() + message->enum_type_count());
101  for (int i = 0; i < message->enum_type_count(); i++) {
102  enums->push_back(message->enum_type(i));
103  }
104  for (int i = 0; i < message->nested_type_count(); i++) {
105  AddEnums(message->nested_type(i), enums);
106  }
107 }
108 
109 std::vector<const protobuf::EnumDescriptor*> SortedEnums(
111  std::vector<const protobuf::EnumDescriptor*> enums;
112  enums.reserve(file->enum_type_count());
113  for (int i = 0; i < file->enum_type_count(); i++) {
114  enums.push_back(file->enum_type(i));
115  }
116  for (int i = 0; i < file->message_type_count(); i++) {
117  AddEnums(file->message_type(i), &enums);
118  }
119  return enums;
120 }
121 
122 std::vector<int32_t> SortedUniqueEnumNumbers(
123  const protobuf::EnumDescriptor* e) {
124  std::vector<int32_t> values;
125  values.reserve(e->value_count());
126  for (int i = 0; i < e->value_count(); i++) {
127  values.push_back(e->value(i)->number());
128  }
129  std::sort(values.begin(), values.end());
130  auto last = std::unique(values.begin(), values.end());
131  values.erase(last, values.end());
132  return values;
133 }
134 
135 void AddMessages(const protobuf::Descriptor* message,
136  std::vector<const protobuf::Descriptor*>* messages) {
137  messages->push_back(message);
138  for (int i = 0; i < message->nested_type_count(); i++) {
139  AddMessages(message->nested_type(i), messages);
140  }
141 }
142 
143 // Ordering must match upb/def.c!
144 //
145 // The ordering is significant because each upb_MessageDef* will point at the
146 // corresponding upb_MiniTable and we just iterate through the list without
147 // any search or lookup.
148 std::vector<const protobuf::Descriptor*> SortedMessages(
150  std::vector<const protobuf::Descriptor*> messages;
151  for (int i = 0; i < file->message_type_count(); i++) {
152  AddMessages(file->message_type(i), &messages);
153  }
154  return messages;
155 }
156 
157 void AddExtensionsFromMessage(
159  std::vector<const protobuf::FieldDescriptor*>* exts) {
160  for (int i = 0; i < message->extension_count(); i++) {
161  exts->push_back(message->extension(i));
162  }
163  for (int i = 0; i < message->nested_type_count(); i++) {
164  AddExtensionsFromMessage(message->nested_type(i), exts);
165  }
166 }
167 
168 // Ordering must match upb/def.c!
169 //
170 // The ordering is significant because each upb_FieldDef* will point at the
171 // corresponding upb_MiniTable_Extension and we just iterate through the list
172 // without any search or lookup.
173 std::vector<const protobuf::FieldDescriptor*> SortedExtensions(
175  std::vector<const protobuf::FieldDescriptor*> ret;
176  for (int i = 0; i < file->extension_count(); i++) {
177  ret.push_back(file->extension(i));
178  }
179  for (int i = 0; i < file->message_type_count(); i++) {
180  AddExtensionsFromMessage(file->message_type(i), &ret);
181  }
182  return ret;
183 }
184 
185 std::vector<const protobuf::FieldDescriptor*> FieldNumberOrder(
186  const protobuf::Descriptor* message) {
187  std::vector<const protobuf::FieldDescriptor*> fields;
188  for (int i = 0; i < message->field_count(); i++) {
189  fields.push_back(message->field(i));
190  }
191  std::sort(fields.begin(), fields.end(),
192  [](const protobuf::FieldDescriptor* a,
193  const protobuf::FieldDescriptor* b) {
194  return a->number() < b->number();
195  });
196  return fields;
197 }
198 
199 std::string EnumValueSymbol(const protobuf::EnumValueDescriptor* value) {
200  return ToCIdent(value->full_name());
201 }
202 
203 std::string CTypeInternal(const protobuf::FieldDescriptor* field,
204  bool is_const) {
205  std::string maybe_const = is_const ? "const " : "";
206  switch (field->cpp_type()) {
208  std::string maybe_struct =
209  field->file() != field->message_type()->file() ? "struct " : "";
210  return maybe_const + maybe_struct + MessageName(field->message_type()) +
211  "*";
212  }
214  return "bool";
216  return "float";
219  return "int32_t";
221  return "uint32_t";
223  return "double";
225  return "int64_t";
227  return "uint64_t";
229  return "upb_StringView";
230  default:
231  fprintf(stderr, "Unexpected type");
232  abort();
233  }
234 }
235 
237  switch (field->cpp_type()) {
239  return "UPB_SIZE(2, 3)";
241  return std::to_string(2);
243  return std::to_string(1);
245  return std::to_string(2);
247  return std::to_string(2);
249  return std::to_string(2);
251  return std::to_string(3);
253  return std::to_string(3);
255  return std::to_string(3);
257  return "UPB_SIZE(3, 4)";
258  default:
259  fprintf(stderr, "Unexpected type");
260  abort();
261  }
262 }
263 
264 bool HasNonZeroDefault(const protobuf::FieldDescriptor* field) {
265  switch (field->cpp_type()) {
267  return false;
269  return !field->default_value_string().empty();
271  return field->default_value_int32() != 0;
273  return field->default_value_int64() != 0;
275  return field->default_value_uint32() != 0;
277  return field->default_value_uint64() != 0;
279  return field->default_value_float() != 0;
281  return field->default_value_double() != 0;
283  return field->default_value_bool() != false;
285  // Use a number instead of a symbolic name so that we don't require
286  // this enum's header to be included.
287  return field->default_value_enum()->number() != 0;
288  }
289  ABSL_ASSERT(false);
290  return false;
291 }
292 
293 std::string FieldDefault(const protobuf::FieldDescriptor* field) {
294  switch (field->cpp_type()) {
296  return "NULL";
298  return absl::Substitute("upb_StringView_FromString(\"$0\")",
299  absl::CEscape(field->default_value_string()));
301  return absl::Substitute("_upb_Int32_FromI($0)",
302  field->default_value_int32());
304  return absl::Substitute("_upb_Int64_FromLL($0ll)",
305  field->default_value_int64());
307  return absl::Substitute("_upb_UInt32_FromU($0u)",
308  field->default_value_uint32());
310  return absl::Substitute("_upb_UInt64_FromULL($0ull)",
311  field->default_value_uint64());
313  return absl::StrCat(field->default_value_float());
315  return absl::StrCat(field->default_value_double());
317  return field->default_value_bool() ? "true" : "false";
319  // Use a number instead of a symbolic name so that we don't require
320  // this enum's header to be included.
321  return absl::StrCat(field->default_value_enum()->number());
322  }
323  ABSL_ASSERT(false);
324  return "XXX";
325 }
326 
328  return CTypeInternal(field, false);
329 }
330 
331 std::string CTypeConst(const protobuf::FieldDescriptor* field) {
332  return CTypeInternal(field, true);
333 }
334 
336 // FilePlatformLayout
338 
339 // FilePlatformLayout builds and vends upb MiniTables for a given platform (32
340 // or 64 bit).
341 class FilePlatformLayout {
342  public:
343  FilePlatformLayout(const protobuf::FileDescriptor* fd,
345  : platform_(platform) {
346  BuildMiniTables(fd);
347  BuildExtensions(fd);
348  }
349 
350  // Retrieves a upb MiniTable or Extension given a protobuf descriptor. The
351  // descriptor must be from this layout's file.
352  upb_MiniTable* GetMiniTable(const protobuf::Descriptor* m) const;
353  const upb_MiniTable_Extension* GetExtension(
354  const protobuf::FieldDescriptor* fd) const;
355 
356  // Get the initializer for the given sub-message/sub-enum link.
357  static std::string GetSub(upb_MiniTable_Sub sub);
358 
359  private:
360  // Functions to build mini-tables for this file's messages and extensions.
361  void BuildMiniTables(const protobuf::FileDescriptor* fd);
362  void BuildExtensions(const protobuf::FileDescriptor* fd);
363  upb_MiniTable* MakeMiniTable(const protobuf::Descriptor* m);
364  upb_MiniTable* MakeRegularMiniTable(const protobuf::Descriptor* m);
365  uint64_t GetMessageModifiers(const protobuf::Descriptor* m);
366  uint64_t GetFieldModifiers(const protobuf::FieldDescriptor* f);
367  void ResolveIntraFileReferences();
368 
369  // When we are generating code, tables are linked to sub-tables via name (ie.
370  // a string) rather than by pointer. We need to emit an initializer like
371  // `&foo_sub_table`. To do this, we store `const char*` strings in all the
372  // links that would normally be pointers:
373  // field -> sub-message
374  // field -> enum table (proto2 only)
375  // extension -> extendee
376  //
377  // This requires a bit of reinterpret_cast<>(), but it's confined to a few
378  // functions. We tag the pointer so we know which member of the union to
379  // initialize.
380  enum SubTag {
381  kNull = 0,
382  kMessage = 1,
383  kEnum = 2,
384  kMask = 3,
385  };
386 
387  static upb_MiniTable_Sub PackSub(const char* data, SubTag tag);
388  static bool IsNull(upb_MiniTable_Sub sub);
389  void SetSubTableStrings();
390  upb_MiniTable_Sub PackSubForField(const protobuf::FieldDescriptor* f,
391  const upb_MiniTable_Field* mt_f);
392  const char* AllocStr(absl::string_view str);
393 
394  private:
395  using TableMap =
397  using ExtensionMap = absl::flat_hash_map<const protobuf::FieldDescriptor*,
400  TableMap table_map_;
401  ExtensionMap extension_map_;
402  upb_MiniTablePlatform platform_;
403 };
404 
405 upb_MiniTable* FilePlatformLayout::GetMiniTable(
406  const protobuf::Descriptor* m) const {
407  auto it = table_map_.find(m);
408  assert(it != table_map_.end());
409  return it->second;
410 }
411 
412 const upb_MiniTable_Extension* FilePlatformLayout::GetExtension(
413  const protobuf::FieldDescriptor* fd) const {
414  auto it = extension_map_.find(fd);
415  assert(it != extension_map_.end());
416  return &it->second;
417 }
418 
419 void FilePlatformLayout::ResolveIntraFileReferences() {
420  // This properly resolves references within a file, in order to set any
421  // necessary flags (eg. is a map).
422  for (const auto& pair : table_map_) {
423  upb_MiniTable* mt = pair.second;
424  // First we properly resolve for defs within the file.
425  for (const auto* f : FieldNumberOrder(pair.first)) {
426  if (f->message_type() && f->message_type()->file() == f->file()) {
427  // const_cast is safe because the mini-table is owned exclusively
428  // by us, and was allocated from an arena (known-writable memory).
429  upb_MiniTable_Field* mt_f = const_cast<upb_MiniTable_Field*>(
430  upb_MiniTable_FindFieldByNumber(mt, f->number()));
431  upb_MiniTable* sub_mt = GetMiniTable(f->message_type());
432  upb_MiniTable_SetSubMessage(mt, mt_f, sub_mt);
433  }
434  // We don't worry about enums here, because resolving an enum will
435  // never alter the mini-table.
436  }
437  }
438 }
439 
440 upb_MiniTable_Sub FilePlatformLayout::PackSub(const char* data, SubTag tag) {
441  uintptr_t val = reinterpret_cast<uintptr_t>(data);
442  assert((val & kMask) == 0);
443  upb_MiniTable_Sub sub;
444  sub.submsg = reinterpret_cast<upb_MiniTable*>(val | tag);
445  return sub;
446 }
447 
449  return reinterpret_cast<uintptr_t>(sub.subenum) == 0;
450 }
451 
452 std::string FilePlatformLayout::GetSub(upb_MiniTable_Sub sub) {
453  uintptr_t as_int = reinterpret_cast<uintptr_t>(sub.submsg);
454  const char* str = reinterpret_cast<const char*>(as_int & ~SubTag::kMask);
455  switch (as_int & SubTag::kMask) {
456  case SubTag::kMessage:
457  return absl::Substitute("{.submsg = &$0}", str);
458  case SubTag::kEnum:
459  return absl::Substitute("{.subenum = &$0}", str);
460  default:
461  return std::string("{.submsg = NULL}");
462  }
463  return std::string("ERROR in GetSub");
464 }
465 
466 void FilePlatformLayout::SetSubTableStrings() {
467  for (const auto& pair : table_map_) {
468  upb_MiniTable* mt = pair.second;
469  for (const auto* f : FieldNumberOrder(pair.first)) {
470  upb_MiniTable_Field* mt_f = const_cast<upb_MiniTable_Field*>(
471  upb_MiniTable_FindFieldByNumber(mt, f->number()));
472  assert(mt_f);
473  upb_MiniTable_Sub sub = PackSubForField(f, mt_f);
474  if (IsNull(sub)) continue;
475  // const_cast is safe because the mini-table is owned exclusively
476  // by us, and was allocated from an arena (known-writable memory).
477  *const_cast<upb_MiniTable_Sub*>(&mt->subs[mt_f->submsg_index]) = sub;
478  }
479  }
480 }
481 
482 upb_MiniTable_Sub FilePlatformLayout::PackSubForField(
483  const protobuf::FieldDescriptor* f, const upb_MiniTable_Field* mt_f) {
484  if (mt_f->submsg_index == kUpb_NoSub) {
485  return PackSub(nullptr, SubTag::kNull);
486  } else if (f->message_type()) {
487  return PackSub(AllocStr(MessageInit(f->message_type())), SubTag::kMessage);
488  } else {
489  ABSL_ASSERT(f->enum_type());
490  return PackSub(AllocStr(EnumInit(f->enum_type())), SubTag::kEnum);
491  }
492 }
493 
494 const char* FilePlatformLayout::AllocStr(absl::string_view str) {
495  char* ret =
496  static_cast<char*>(upb_Arena_Malloc(arena_.ptr(), str.size() + 1));
497  memcpy(ret, str.data(), str.size());
498  ret[str.size()] = '\0';
499  return ret;
500 }
501 
502 void FilePlatformLayout::BuildMiniTables(const protobuf::FileDescriptor* fd) {
503  for (const auto& m : SortedMessages(fd)) {
504  table_map_[m] = MakeMiniTable(m);
505  }
506  ResolveIntraFileReferences();
507  SetSubTableStrings();
508 }
509 
510 void FilePlatformLayout::BuildExtensions(const protobuf::FileDescriptor* fd) {
511  std::vector<const protobuf::FieldDescriptor*> sorted = SortedExtensions(fd);
513  for (const auto* f : sorted) {
515  e.StartMessage(0);
516  e.PutField(static_cast<upb_FieldType>(f->type()), f->number(),
517  GetFieldModifiers(f));
518  upb_MiniTable_Extension& ext = extension_map_[f];
519  upb_MiniTable_Sub sub;
520  bool ok = upb_MiniTable_BuildExtension(e.data().data(), e.data().size(),
521  &ext, sub, status.ptr());
522  if (!ok) {
523  // TODO(haberman): Use ABSL CHECK() when it is available.
524  fprintf(stderr, "Error building mini-table: %s\n",
525  status.error_message());
526  }
527  ABSL_ASSERT(ok);
528  ext.extendee = reinterpret_cast<const upb_MiniTable*>(
529  AllocStr(MessageInit(f->containing_type())));
530  ext.sub = PackSubForField(f, &ext.field);
531  }
532 }
533 
534 upb_MiniTable* FilePlatformLayout::MakeMiniTable(
535  const protobuf::Descriptor* m) {
536  if (m->options().message_set_wire_format()) {
537  return upb_MiniTable_BuildMessageSet(platform_, arena_.ptr());
538  } else if (m->options().map_entry()) {
540  static_cast<upb_FieldType>(m->map_key()->type()),
541  static_cast<upb_FieldType>(m->map_value()->type()),
542  m->map_value()->enum_type() &&
543  m->map_value()->enum_type()->file()->syntax() ==
545  platform_, arena_.ptr());
546  } else {
547  return MakeRegularMiniTable(m);
548  }
549 }
550 
551 upb_MiniTable* FilePlatformLayout::MakeRegularMiniTable(
552  const protobuf::Descriptor* m) {
554  e.StartMessage(GetMessageModifiers(m));
555  for (const auto* f : FieldNumberOrder(m)) {
556  e.PutField(static_cast<upb_FieldType>(f->type()), f->number(),
557  GetFieldModifiers(f));
558  }
559  for (int i = 0; i < m->real_oneof_decl_count(); i++) {
560  const protobuf::OneofDescriptor* oneof = m->oneof_decl(i);
561  e.StartOneof();
562  for (int j = 0; j < oneof->field_count(); j++) {
563  const protobuf::FieldDescriptor* f = oneof->field(j);
564  e.PutOneofField(f->number());
565  }
566  }
567  const std::string& str = e.data();
569  upb_MiniTable* ret = upb_MiniTable_Build(str.data(), str.size(), platform_,
570  arena_.ptr(), status.ptr());
571  if (!ret) {
572  fprintf(stderr, "Error building mini-table: %s\n", status.error_message());
573  }
574  assert(ret);
575  return ret;
576 }
577 
578 uint64_t FilePlatformLayout::GetMessageModifiers(
579  const protobuf::Descriptor* m) {
580  uint64_t ret = 0;
581 
582  if (m->file()->syntax() == protobuf::FileDescriptor::SYNTAX_PROTO3) {
585  }
586 
587  if (m->extension_range_count() > 0) {
589  }
590 
591  assert(!m->options().map_entry());
592  return ret;
593 }
594 
595 uint64_t FilePlatformLayout::GetFieldModifiers(
596  const protobuf::FieldDescriptor* f) {
597  uint64_t ret = 0;
598 
599  if (f->is_repeated()) ret |= kUpb_FieldModifier_IsRepeated;
600  if (f->is_required()) ret |= kUpb_FieldModifier_IsRequired;
601  if (f->is_packed()) ret |= kUpb_FieldModifier_IsPacked;
602  if (f->enum_type() && f->enum_type()->file()->syntax() ==
605  }
606  if (f->is_optional() && !f->has_presence()) {
608  }
609 
610  return ret;
611 }
612 
614 // FileLayout
616 
617 // FileLayout is a pair of platform layouts: one for 32-bit and one for 64-bit.
618 class FileLayout {
619  public:
620  FileLayout(const protobuf::FileDescriptor* fd)
621  : descriptor_(fd),
622  layout32_(fd, kUpb_MiniTablePlatform_32Bit),
623  layout64_(fd, kUpb_MiniTablePlatform_64Bit) {}
624 
625  const protobuf::FileDescriptor* descriptor() const { return descriptor_; }
626 
627  const upb_MiniTable* GetMiniTable32(const protobuf::Descriptor* m) const {
628  return layout32_.GetMiniTable(m);
629  }
630 
631  const upb_MiniTable* GetMiniTable64(const protobuf::Descriptor* m) const {
632  return layout64_.GetMiniTable(m);
633  }
634 
635  std::string GetFieldOffset(const protobuf::FieldDescriptor* f) const {
637  GetMiniTable32(f->containing_type()), f->number());
639  GetMiniTable64(f->containing_type()), f->number());
640  return absl::Substitute("UPB_SIZE($0, $1)", f_32->offset, f_64->offset);
641  }
642 
643  std::string GetOneofCaseOffset(const protobuf::OneofDescriptor* o) const {
644  const protobuf::FieldDescriptor* f = o->field(0);
646  GetMiniTable32(f->containing_type()), f->number());
648  GetMiniTable64(f->containing_type()), f->number());
649  return absl::Substitute("UPB_SIZE($0, $1)", ~f_32->presence,
650  ~f_64->presence);
651  }
652 
653  std::string GetMessageSize(const protobuf::Descriptor* d) const {
654  return absl::Substitute("UPB_SIZE($0, $1)", GetMiniTable32(d)->size,
655  GetMiniTable64(d)->size);
656  }
657 
658  int GetHasbitIndex(const protobuf::FieldDescriptor* f) const {
660  GetMiniTable64(f->containing_type()), f->number());
661  return f_64->presence;
662  }
663 
664  bool HasHasbit(const protobuf::FieldDescriptor* f) const {
665  return GetHasbitIndex(f) > 0;
666  }
667 
668  const upb_MiniTable_Extension* GetExtension(
669  const protobuf::FieldDescriptor* f) const {
670  return layout64_.GetExtension(f);
671  }
672 
673  private:
675  FilePlatformLayout layout32_;
676  FilePlatformLayout layout64_;
677 };
678 
679 void DumpEnumValues(const protobuf::EnumDescriptor* desc, Output& output) {
680  std::vector<const protobuf::EnumValueDescriptor*> values;
681  for (int i = 0; i < desc->value_count(); i++) {
682  values.push_back(desc->value(i));
683  }
684  std::sort(values.begin(), values.end(),
685  [](const protobuf::EnumValueDescriptor* a,
687  return a->number() < b->number();
688  });
689 
690  for (size_t i = 0; i < values.size(); i++) {
691  auto value = values[i];
692  output(" $0 = $1", EnumValueSymbol(value), value->number());
693  if (i != values.size() - 1) {
694  output(",");
695  }
696  output("\n");
697  }
698 }
699 
700 void GenerateExtensionInHeader(const protobuf::FieldDescriptor* ext,
701  Output& output) {
702  output(
703  R"cc(
704  UPB_INLINE bool $0_has_$1(const struct $2* msg) {
705  return _upb_Message_Getext(msg, &$3) != NULL;
706  }
707  )cc",
708  ExtensionIdentBase(ext), ext->name(), MessageName(ext->containing_type()),
709  ExtensionLayout(ext));
710 
711  output(
712  R"cc(
713  UPB_INLINE void $0_clear_$1(struct $2* msg) {
714  _upb_Message_Clearext(msg, &$3);
715  }
716  )cc",
717  ExtensionIdentBase(ext), ext->name(), MessageName(ext->containing_type()),
718  ExtensionLayout(ext));
719 
720  if (ext->is_repeated()) {
721  } else if (ext->message_type()) {
722  output(
723  R"cc(
724  UPB_INLINE $0 $1_$2(const struct $3* msg) {
725  const upb_Message_Extension* ext = _upb_Message_Getext(msg, &$4);
726  UPB_ASSERT(ext);
727  return *UPB_PTR_AT(&ext->data, 0, $0);
728  }
729  )cc",
730  CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
731  MessageName(ext->containing_type()), ExtensionLayout(ext),
732  FieldDefault(ext));
733  output(
734  R"cc(
735  UPB_INLINE void $1_set_$2(struct $3* msg, $0 ext, upb_Arena* arena) {
736  const upb_Message_Extension* msg_ext =
737  _upb_Message_Getorcreateext(msg, &$4, arena);
738  UPB_ASSERT(msg_ext);
739  *UPB_PTR_AT(&msg_ext->data, 0, $0) = ext;
740  }
741  )cc",
742  CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
743  MessageName(ext->containing_type()), ExtensionLayout(ext),
744  FieldDefault(ext));
745  } else {
746  // Returns default if extension field is not a message.
747  output(
748  R"cc(
749  UPB_INLINE $0 $1_$2(const struct $3* msg) {
750  const upb_Message_Extension* ext = _upb_Message_Getext(msg, &$4);
751  return ext ? *UPB_PTR_AT(&ext->data, 0, $0) : $5;
752  }
753  )cc",
754  CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
755  MessageName(ext->containing_type()), ExtensionLayout(ext),
756  FieldDefault(ext));
757  }
758 }
759 
760 void GenerateMessageFunctionsInHeader(const protobuf::Descriptor* message,
761  Output& output) {
762  output(
763  R"cc(
764  UPB_INLINE $0* $0_new(upb_Arena* arena) {
765  return ($0*)_upb_Message_New(&$1, arena);
766  }
767  UPB_INLINE $0* $0_parse(const char* buf, size_t size, upb_Arena* arena) {
768  $0* ret = $0_new(arena);
769  if (!ret) return NULL;
770  if (upb_Decode(buf, size, ret, &$1, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
771  return NULL;
772  }
773  return ret;
774  }
775  UPB_INLINE $0* $0_parse_ex(const char* buf, size_t size,
776  const upb_ExtensionRegistry* extreg,
777  int options, upb_Arena* arena) {
778  $0* ret = $0_new(arena);
779  if (!ret) return NULL;
780  if (upb_Decode(buf, size, ret, &$1, extreg, options, arena) !=
781  kUpb_DecodeStatus_Ok) {
782  return NULL;
783  }
784  return ret;
785  }
786  UPB_INLINE char* $0_serialize(const $0* msg, upb_Arena* arena, size_t* len) {
787  return upb_Encode(msg, &$1, 0, arena, len);
788  }
789  UPB_INLINE char* $0_serialize_ex(const $0* msg, int options,
790  upb_Arena* arena, size_t* len) {
791  return upb_Encode(msg, &$1, options, arena, len);
792  }
793  )cc",
794  MessageName(message), MessageInit(message));
795 }
796 
797 void GenerateOneofInHeader(const protobuf::OneofDescriptor* oneof,
798  const FileLayout& layout, absl::string_view msg_name,
799  Output& output) {
800  std::string fullname = ToCIdent(oneof->full_name());
801  output("typedef enum {\n");
802  for (int j = 0; j < oneof->field_count(); j++) {
803  const protobuf::FieldDescriptor* field = oneof->field(j);
804  output(" $0_$1 = $2,\n", fullname, field->name(), field->number());
805  }
806  output(
807  " $0_NOT_SET = 0\n"
808  "} $0_oneofcases;\n",
809  fullname);
810  output(
811  R"cc(
812  UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) {
813  return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t);
814  }
815  )cc",
816  fullname, msg_name, oneof->name(), layout.GetOneofCaseOffset(oneof));
817 }
818 
819 void GenerateHazzer(const protobuf::FieldDescriptor* field,
820  const FileLayout& layout, absl::string_view msg_name,
821  Output& output) {
822  if (layout.HasHasbit(field)) {
823  output(
824  R"cc(
825  UPB_INLINE bool $0_has_$1(const $0* msg) {
826  return _upb_hasbit(msg, $2);
827  }
828  )cc",
829  msg_name, field->name(), layout.GetHasbitIndex(field));
830  } else if (field->real_containing_oneof()) {
831  output(
832  R"cc(
833  UPB_INLINE bool $0_has_$1(const $0* msg) {
834  return _upb_getoneofcase(msg, $2) == $3;
835  }
836  )cc",
837  msg_name, field->name(),
838  layout.GetOneofCaseOffset(field->real_containing_oneof()),
839  field->number());
840  } else if (field->message_type()) {
841  output(
842  R"cc(
843  UPB_INLINE bool $0_has_$1(const $0* msg) {
844  return _upb_has_submsg_nohasbit(msg, $2);
845  }
846  )cc",
847  msg_name, field->name(), layout.GetFieldOffset(field));
848  }
849 }
850 
851 void GenerateClear(const protobuf::FieldDescriptor* field,
852  const FileLayout& layout, absl::string_view msg_name,
853  Output& output) {
854  if (field == field->containing_type()->map_key() ||
855  field == field->containing_type()->map_value()) {
856  // Cannot be cleared.
857  return;
858  }
859 
860  if (field->real_containing_oneof()) {
861  const protobuf::OneofDescriptor* oneof = field->real_containing_oneof();
862  std::string oneof_fullname = ToCIdent(oneof->full_name());
863  std::string default_value =
865  ? "upb_StringView_FromDataAndSize(NULL, 0)"
866  : "0";
867  output(
868  R"cc(
869  UPB_INLINE void $0_clear_$1(const $0* msg) {
870  UPB_WRITE_ONEOF(msg, $2, $3, $7, $4, $6_NOT_SET);
871  }
872  )cc",
873  msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
874  layout.GetOneofCaseOffset(field->real_containing_oneof()),
875  field->number(), oneof_fullname, default_value);
876  } else {
877  if (field->message_type()) {
878  output(
879  R"cc(
880  UPB_INLINE void $0_clear_$1(const $0* msg) {
881  *UPB_PTR_AT(msg, $2, const upb_Message*) = NULL;
882  }
883  )cc",
884  msg_name, field->name(), layout.GetFieldOffset(field));
885  } else if (layout.HasHasbit(field)) {
887  output(
888  R"cc(
889  UPB_INLINE void $0_clear_$1(const $0* msg) {
890  *UPB_PTR_AT(msg, $3, $2) = upb_StringView_FromDataAndSize(NULL, 0);
891  _upb_clearhas(msg, $4);
892  }
893  )cc",
894  msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
895  layout.GetHasbitIndex(field));
896  } else {
897  output(
898  R"cc(
899  UPB_INLINE void $0_clear_$1(const $0* msg) {
900  *UPB_PTR_AT(msg, $3, $2) = 0;
901  _upb_clearhas(msg, $4);
902  }
903  )cc",
904  msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
905  layout.GetHasbitIndex(field));
906  }
907  } else {
909  output(
910  R"cc(
911  UPB_INLINE void $0_clear_$1(const $0* msg) {
912  *UPB_PTR_AT(msg, $3, $2) = upb_StringView_FromDataAndSize(NULL, 0);
913  }
914  )cc",
915  msg_name, field->name(), CType(field),
916  layout.GetFieldOffset(field));
917  } else {
918  output(
919  R"cc(
920  UPB_INLINE void $0_clear_$1(const $0* msg) {
921  *UPB_PTR_AT(msg, $3, $2) = 0;
922  }
923  )cc",
924  msg_name, field->name(), CType(field), layout.GetFieldOffset(field),
925  layout.GetHasbitIndex(field));
926  }
927  }
928  }
929 }
930 
931 void GenerateRepeatedClear(const protobuf::FieldDescriptor* field,
932  const FileLayout& layout, absl::string_view msg_name,
933  Output& output) {
934  output(
935  R"cc(
936  UPB_INLINE void $0_clear_$1(const $0* msg) {
937  _upb_array_detach(msg, $2);
938  }
939  )cc",
940  msg_name, field->name(), layout.GetFieldOffset(field));
941 }
942 
943 void GenerateMapGetters(const protobuf::FieldDescriptor* field,
944  const FileLayout& layout, absl::string_view msg_name,
945  Output& output) {
946  const protobuf::Descriptor* entry = field->message_type();
948  const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
949  output(
950  R"cc(
951  UPB_INLINE size_t $0_$1_size(const $0* msg) {
952  return _upb_msg_map_size(msg, $2);
953  }
954  )cc",
955  msg_name, field->name(), layout.GetFieldOffset(field));
956  output(
957  R"cc(
958  UPB_INLINE bool $0_$1_get(const $0* msg, $2 key, $3* val) {
959  return _upb_msg_map_get(msg, $4, &key, $5, val, $6);
960  }
961  )cc",
962  msg_name, field->name(), CType(key), CType(val),
963  layout.GetFieldOffset(field),
965  ? "0"
966  : "sizeof(key)",
968  ? "0"
969  : "sizeof(*val)");
970  output(
971  R"cc(
972  UPB_INLINE $0 $1_$2_next(const $1* msg, size_t* iter) {
973  return ($0)_upb_msg_map_next(msg, $3, iter);
974  }
975  )cc",
976  CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field));
977 }
978 
979 void GenerateMapEntryGetters(const protobuf::FieldDescriptor* field,
980  absl::string_view msg_name, Output& output) {
981  output(
982  R"cc(
983  UPB_INLINE $0 $1_$2(const $1* msg) {
984  $3 ret;
985  _upb_msg_map_$2(msg, &ret, $4);
986  return ret;
987  }
988  )cc",
989  CTypeConst(field), msg_name, field->name(), CType(field),
991  ? "0"
992  : "sizeof(ret)");
993 }
994 
995 void GenerateRepeatedGetters(const protobuf::FieldDescriptor* field,
996  const FileLayout& layout,
997  absl::string_view msg_name, Output& output) {
998  output(
999  R"cc(
1000  UPB_INLINE $0 const* $1_$2(const $1* msg, size_t* len) {
1001  return ($0 const*)_upb_array_accessor(msg, $3, len);
1002  }
1003  )cc",
1004  CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field));
1005 }
1006 
1007 void GenerateOneofGetters(const protobuf::FieldDescriptor* field,
1008  const FileLayout& layout, absl::string_view msg_name,
1009  Output& output) {
1010  output(
1011  R"cc(
1012  UPB_INLINE $0 $1_$2(const $1* msg) {
1013  return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6);
1014  }
1015  )cc",
1016  CTypeConst(field), msg_name, field->name(), layout.GetFieldOffset(field),
1017  layout.GetOneofCaseOffset(field->real_containing_oneof()),
1018  field->number(), FieldDefault(field));
1019 }
1020 
1021 void GenerateScalarGetters(const protobuf::FieldDescriptor* field,
1022  const FileLayout& layout, absl::string_view msg_name,
1023  Output& output) {
1024  if (HasNonZeroDefault(field)) {
1025  output(
1026  R"cc(
1027  UPB_INLINE $0 $1_$2(const $1* msg) {
1028  return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4;
1029  }
1030  )cc",
1031  CTypeConst(field), msg_name, field->name(),
1032  layout.GetFieldOffset(field), FieldDefault(field));
1033  } else {
1034  output(
1035  R"cc(
1036  UPB_INLINE $0 $1_$2(const $1* msg) {
1037  return *UPB_PTR_AT(msg, $3, $0);
1038  }
1039  )cc",
1040  CTypeConst(field), msg_name, field->name(),
1041  layout.GetFieldOffset(field));
1042  }
1043 }
1044 
1045 void GenerateGetters(const protobuf::FieldDescriptor* field,
1046  const FileLayout& layout, absl::string_view msg_name,
1047  Output& output) {
1048  if (field->is_map()) {
1049  GenerateMapGetters(field, layout, msg_name, output);
1050  } else if (field->containing_type()->options().map_entry()) {
1051  GenerateMapEntryGetters(field, msg_name, output);
1052  } else if (field->is_repeated()) {
1053  GenerateRepeatedGetters(field, layout, msg_name, output);
1054  } else if (field->real_containing_oneof()) {
1055  GenerateOneofGetters(field, layout, msg_name, output);
1056  } else {
1057  GenerateScalarGetters(field, layout, msg_name, output);
1058  }
1059 }
1060 
1061 void GenerateMapSetters(const protobuf::FieldDescriptor* field,
1062  const FileLayout& layout, absl::string_view msg_name,
1063  Output& output) {
1064  const protobuf::Descriptor* entry = field->message_type();
1065  const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
1066  const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
1067  output(
1068  R"cc(
1069  UPB_INLINE void $0_$1_clear($0* msg) { _upb_msg_map_clear(msg, $2); }
1070  )cc",
1071  msg_name, field->name(), layout.GetFieldOffset(field));
1072  output(
1073  R"cc(
1074  UPB_INLINE bool $0_$1_set($0* msg, $2 key, $3 val, upb_Arena* a) {
1075  return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a);
1076  }
1077  )cc",
1078  msg_name, field->name(), CType(key), CType(val),
1079  layout.GetFieldOffset(field),
1081  ? "0"
1082  : "sizeof(key)",
1084  ? "0"
1085  : "sizeof(val)");
1086  output(
1087  R"cc(
1088  UPB_INLINE bool $0_$1_delete($0* msg, $2 key) {
1089  return _upb_msg_map_delete(msg, $3, &key, $4);
1090  }
1091  )cc",
1092  msg_name, field->name(), CType(key), layout.GetFieldOffset(field),
1094  ? "0"
1095  : "sizeof(key)");
1096  output(
1097  R"cc(
1098  UPB_INLINE $0 $1_$2_nextmutable($1* msg, size_t* iter) {
1099  return ($0)_upb_msg_map_next(msg, $3, iter);
1100  }
1101  )cc",
1102  CType(field), msg_name, field->name(), layout.GetFieldOffset(field));
1103 }
1104 
1105 void GenerateRepeatedSetters(const protobuf::FieldDescriptor* field,
1106  const FileLayout& layout,
1107  absl::string_view msg_name, Output& output) {
1108  output(
1109  R"cc(
1110  UPB_INLINE $0* $1_mutable_$2($1* msg, size_t* len) {
1111  return ($0*)_upb_array_mutable_accessor(msg, $3, len);
1112  }
1113  )cc",
1114  CType(field), msg_name, field->name(), layout.GetFieldOffset(field));
1115  output(
1116  R"cc(
1117  UPB_INLINE $0* $1_resize_$2($1* msg, size_t len, upb_Arena* arena) {
1118  return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, arena);
1119  }
1120  )cc",
1121  CType(field), msg_name, field->name(), layout.GetFieldOffset(field),
1122  SizeLg2(field));
1124  output(
1125  R"cc(
1126  UPB_INLINE struct $0* $1_add_$2($1* msg, upb_Arena* arena) {
1127  struct $0* sub = (struct $0*)_upb_Message_New(&$3, arena);
1128  bool ok = _upb_Array_Append_accessor2(msg, $4, $5, &sub, arena);
1129  if (!ok) return NULL;
1130  return sub;
1131  }
1132  )cc",
1133  MessageName(field->message_type()), msg_name, field->name(),
1134  MessageInit(field->message_type()), layout.GetFieldOffset(field),
1135  SizeLg2(field));
1136  } else {
1137  output(
1138  R"cc(
1139  UPB_INLINE bool $1_add_$2($1* msg, $0 val, upb_Arena* arena) {
1140  return _upb_Array_Append_accessor2(msg, $3, $4, &val, arena);
1141  }
1142  )cc",
1143  CType(field), msg_name, field->name(), layout.GetFieldOffset(field),
1144  SizeLg2(field));
1145  }
1146 }
1147 
1148 void GenerateNonRepeatedSetters(const protobuf::FieldDescriptor* field,
1149  const FileLayout& layout,
1150  absl::string_view msg_name, Output& output) {
1151  if (field == field->containing_type()->map_key()) {
1152  // Key cannot be mutated.
1153  return;
1154  }
1155 
1156  // The common function signature for all setters. Varying
1157  // implementations follow.
1158  output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name,
1159  field->name(), CType(field));
1160 
1161  if (field == field->containing_type()->map_value()) {
1162  output(
1163  " _upb_msg_map_set_value(msg, &value, $0);\n"
1164  "}\n",
1166  ? "0"
1167  : "sizeof(" + CType(field) + ")");
1168  } else if (field->real_containing_oneof()) {
1169  output(
1170  " UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n"
1171  "}\n",
1172  CType(field), layout.GetFieldOffset(field),
1173  layout.GetOneofCaseOffset(field->real_containing_oneof()),
1174  field->number());
1175  } else {
1176  if (layout.HasHasbit(field)) {
1177  output(" _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field));
1178  }
1179  output(
1180  " *UPB_PTR_AT(msg, $1, $0) = value;\n"
1181  "}\n",
1182  CType(field), layout.GetFieldOffset(field));
1183  }
1184 
1185  // Message fields also have a Msg_mutable_foo() accessor that will create
1186  // the sub-message if it doesn't already exist.
1188  !field->containing_type()->options().map_entry()) {
1189  output(
1190  R"cc(
1191  UPB_INLINE struct $0* $1_mutable_$2($1* msg, upb_Arena* arena) {
1192  struct $0* sub = (struct $0*)$1_$2(msg);
1193  if (sub == NULL) {
1194  sub = (struct $0*)_upb_Message_New(&$3, arena);
1195  if (!sub) return NULL;
1196  $1_set_$2(msg, sub);
1197  }
1198  return sub;
1199  }
1200  )cc",
1201  MessageName(field->message_type()), msg_name, field->name(),
1202  MessageInit(field->message_type()));
1203  }
1204 }
1205 
1206 void GenerateSetters(const protobuf::FieldDescriptor* field,
1207  const FileLayout& layout, absl::string_view msg_name,
1208  Output& output) {
1209  if (field->is_map()) {
1210  GenerateMapSetters(field, layout, msg_name, output);
1211  } else if (field->is_repeated()) {
1212  GenerateRepeatedSetters(field, layout, msg_name, output);
1213  } else {
1214  GenerateNonRepeatedSetters(field, layout, msg_name, output);
1215  }
1216 }
1217 
1218 void GenerateMessageInHeader(const protobuf::Descriptor* message,
1219  const FileLayout& layout, Output& output) {
1220  output("/* $0 */\n\n", message->full_name());
1221  std::string msg_name = ToCIdent(message->full_name());
1222 
1223  if (!message->options().map_entry()) {
1224  GenerateMessageFunctionsInHeader(message, output);
1225  }
1226 
1227  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
1228  GenerateOneofInHeader(message->oneof_decl(i), layout, msg_name, output);
1229  }
1230 
1231  for (auto field : FieldNumberOrder(message)) {
1232  GenerateHazzer(field, layout, msg_name, output);
1233  if (field->is_repeated()) {
1234  GenerateRepeatedClear(field, layout, msg_name, output);
1235  } else {
1236  GenerateClear(field, layout, msg_name, output);
1237  }
1238  GenerateGetters(field, layout, msg_name, output);
1239  }
1240 
1241  output("\n");
1242 
1243  for (auto field : FieldNumberOrder(message)) {
1244  GenerateSetters(field, layout, msg_name, output);
1245  }
1246 
1247  output("\n");
1248 }
1249 
1250 void WriteHeader(const FileLayout& layout, Output& output) {
1251  const protobuf::FileDescriptor* file = layout.descriptor();
1253  output(
1254  "#ifndef $0_UPB_H_\n"
1255  "#define $0_UPB_H_\n\n"
1256  "#include \"upb/msg_internal.h\"\n"
1257  "#include \"upb/decode.h\"\n"
1258  "#include \"upb/decode_fast.h\"\n"
1259  "#include \"upb/encode.h\"\n\n",
1260  ToPreproc(file->name()));
1261 
1262  for (int i = 0; i < file->public_dependency_count(); i++) {
1263  if (i == 0) {
1264  output("/* Public Imports. */\n");
1265  }
1266  output("#include \"$0\"\n", HeaderFilename(file));
1267  if (i == file->public_dependency_count() - 1) {
1268  output("\n");
1269  }
1270  }
1271 
1272  output(
1273  "#include \"upb/port_def.inc\"\n"
1274  "\n"
1275  "#ifdef __cplusplus\n"
1276  "extern \"C\" {\n"
1277  "#endif\n"
1278  "\n");
1279 
1280  const std::vector<const protobuf::Descriptor*> this_file_messages =
1281  SortedMessages(file);
1282  const std::vector<const protobuf::FieldDescriptor*> this_file_exts =
1283  SortedExtensions(file);
1284 
1285  // Forward-declare types defined in this file.
1286  for (auto message : this_file_messages) {
1287  output("struct $0;\n", ToCIdent(message->full_name()));
1288  }
1289  for (auto message : this_file_messages) {
1290  output("typedef struct $0 $0;\n", ToCIdent(message->full_name()));
1291  }
1292  for (auto message : this_file_messages) {
1293  output("extern const upb_MiniTable $0;\n", MessageInit(message));
1294  }
1295  for (auto ext : this_file_exts) {
1296  output("extern const upb_MiniTable_Extension $0;\n", ExtensionLayout(ext));
1297  }
1298 
1299  // Forward-declare types not in this file, but used as submessages.
1300  // Order by full name for consistent ordering.
1301  std::map<std::string, const protobuf::Descriptor*> forward_messages;
1302 
1303  for (auto* message : this_file_messages) {
1304  for (int i = 0; i < message->field_count(); i++) {
1305  const protobuf::FieldDescriptor* field = message->field(i);
1307  field->file() != field->message_type()->file()) {
1308  forward_messages[field->message_type()->full_name()] =
1309  field->message_type();
1310  }
1311  }
1312  }
1313  for (auto ext : this_file_exts) {
1314  if (ext->file() != ext->containing_type()->file()) {
1315  forward_messages[ext->containing_type()->full_name()] =
1316  ext->containing_type();
1317  }
1318  }
1319  for (const auto& pair : forward_messages) {
1320  output("struct $0;\n", MessageName(pair.second));
1321  }
1322  for (const auto& pair : forward_messages) {
1323  output("extern const upb_MiniTable $0;\n", MessageInit(pair.second));
1324  }
1325 
1326  if (!this_file_messages.empty()) {
1327  output("\n");
1328  }
1329 
1330  std::vector<const protobuf::EnumDescriptor*> this_file_enums =
1331  SortedEnums(file);
1332  std::sort(
1333  this_file_enums.begin(), this_file_enums.end(),
1334  [](const protobuf::EnumDescriptor* a, const protobuf::EnumDescriptor* b) {
1335  return a->full_name() < b->full_name();
1336  });
1337 
1338  for (auto enumdesc : this_file_enums) {
1339  output("typedef enum {\n");
1340  DumpEnumValues(enumdesc, output);
1341  output("} $0;\n\n", ToCIdent(enumdesc->full_name()));
1342  }
1343 
1344  output("\n");
1345 
1346  if (file->syntax() == protobuf::FileDescriptor::SYNTAX_PROTO2) {
1347  for (const auto* enumdesc : this_file_enums) {
1348  output("extern const upb_MiniTable_Enum $0;\n", EnumInit(enumdesc));
1349  }
1350  }
1351 
1352  output("\n");
1353 
1354  for (auto message : this_file_messages) {
1355  GenerateMessageInHeader(message, layout, output);
1356  }
1357 
1358  for (auto ext : this_file_exts) {
1359  GenerateExtensionInHeader(ext, output);
1360  }
1361 
1362  output("extern const upb_MiniTable_File $0;\n\n", FileLayoutName(file));
1363 
1364  if (file->name() ==
1365  protobuf::FileDescriptorProto::descriptor()->file()->name()) {
1366  // This is gratuitously inefficient with how many times it rebuilds
1367  // MessageLayout objects for the same message. But we only do this for one
1368  // proto (descriptor.proto) so we don't worry about it.
1369  const protobuf::Descriptor* max32_message = nullptr;
1370  const protobuf::Descriptor* max64_message = nullptr;
1371  size_t max32 = 0;
1372  size_t max64 = 0;
1373  for (const auto* message : this_file_messages) {
1374  if (absl::EndsWith(message->name(), "Options")) {
1375  size_t size32 = layout.GetMiniTable32(message)->size;
1376  size_t size64 = layout.GetMiniTable64(message)->size;
1377  if (size32 > max32) {
1378  max32 = size32;
1379  max32_message = message;
1380  }
1381  if (size64 > max64) {
1382  max64 = size64;
1383  max64_message = message;
1384  }
1385  }
1386  }
1387 
1388  output("/* Max size 32 is $0 */\n", max32_message->full_name());
1389  output("/* Max size 64 is $0 */\n", max64_message->full_name());
1390  output("#define _UPB_MAXOPT_SIZE UPB_SIZE($0, $1)\n\n", max32, max64);
1391  }
1392 
1393  output(
1394  "#ifdef __cplusplus\n"
1395  "} /* extern \"C\" */\n"
1396  "#endif\n"
1397  "\n"
1398  "#include \"upb/port_undef.inc\"\n"
1399  "\n"
1400  "#endif /* $0_UPB_H_ */\n",
1401  ToPreproc(file->name()));
1402 }
1403 
1404 typedef std::pair<std::string, uint64_t> TableEntry;
1405 
1406 uint64_t GetEncodedTag(const protobuf::FieldDescriptor* field) {
1407  protobuf::internal::WireFormatLite::WireType wire_type =
1408  protobuf::internal::WireFormat::WireTypeForField(field);
1409  uint32_t unencoded_tag =
1410  protobuf::internal::WireFormatLite::MakeTag(field->number(), wire_type);
1411  uint8_t tag_bytes[10] = {0};
1412  protobuf::io::CodedOutputStream::WriteVarint32ToArray(unencoded_tag,
1413  tag_bytes);
1414  uint64_t encoded_tag = 0;
1415  memcpy(&encoded_tag, tag_bytes, sizeof(encoded_tag));
1416  // TODO: byte-swap for big endian.
1417  return encoded_tag;
1418 }
1419 
1420 int GetTableSlot(const protobuf::FieldDescriptor* field) {
1421  uint64_t tag = GetEncodedTag(field);
1422  if (tag > 0x7fff) {
1423  // Tag must fit within a two-byte varint.
1424  return -1;
1425  }
1426  return (tag & 0xf8) >> 3;
1427 }
1428 
1429 bool TryFillTableEntry(const FileLayout& layout,
1431  TableEntry& ent) {
1432  const upb_MiniTable* mt = layout.GetMiniTable64(field->containing_type());
1433  const upb_MiniTable_Field* mt_f =
1434  upb_MiniTable_FindFieldByNumber(mt, field->number());
1435  std::string type = "";
1436  std::string cardinality = "";
1437  switch (mt_f->descriptortype) {
1438  case kUpb_FieldType_Bool:
1439  type = "b1";
1440  break;
1441  case kUpb_FieldType_Enum:
1442  // We don't have the means to test proto2 enum fields for valid values.
1443  return false;
1444  case kUpb_FieldType_Int32:
1445  case kUpb_FieldType_UInt32:
1446  type = "v4";
1447  break;
1448  case kUpb_FieldType_Int64:
1449  case kUpb_FieldType_UInt64:
1450  type = "v8";
1451  break;
1454  case kUpb_FieldType_Float:
1455  type = "f4";
1456  break;
1459  case kUpb_FieldType_Double:
1460  type = "f8";
1461  break;
1462  case kUpb_FieldType_SInt32:
1463  type = "z4";
1464  break;
1465  case kUpb_FieldType_SInt64:
1466  type = "z8";
1467  break;
1468  case kUpb_FieldType_String:
1469  type = "s";
1470  break;
1471  case kUpb_FieldType_Bytes:
1472  type = "b";
1473  break;
1475  type = "m";
1476  break;
1477  default:
1478  return false; // Not supported yet.
1479  }
1480 
1481  switch (upb_FieldMode_Get(mt_f)) {
1482  case kUpb_FieldMode_Map:
1483  return false; // Not supported yet (ever?).
1484  case kUpb_FieldMode_Array:
1485  if (mt_f->mode & kUpb_LabelFlags_IsPacked) {
1486  cardinality = "p";
1487  } else {
1488  cardinality = "r";
1489  }
1490  break;
1491  case kUpb_FieldMode_Scalar:
1492  if (mt_f->presence < 0) {
1493  cardinality = "o";
1494  } else {
1495  cardinality = "s";
1496  }
1497  break;
1498  }
1499 
1500  uint64_t expected_tag = GetEncodedTag(field);
1501 
1502  // Data is:
1503  //
1504  // 48 32 16 0
1505  // |--------|--------|--------|--------|--------|--------|--------|--------|
1506  // | offset (16) |case offset (16) |presence| submsg | exp. tag (16) |
1507  // |--------|--------|--------|--------|--------|--------|--------|--------|
1508  //
1509  // - |presence| is either hasbit index or field number for oneofs.
1510 
1511  uint64_t data = static_cast<uint64_t>(mt_f->offset) << 48 | expected_tag;
1512 
1513  if (field->is_repeated()) {
1514  // No hasbit/oneof-related fields.
1515  }
1516  if (field->real_containing_oneof()) {
1517  size_t case_offset = ~mt_f->presence;
1518  if (case_offset > 0xffff) return false;
1519  assert(field->number() < 256);
1520  data |= field->number() << 24;
1521  data |= case_offset << 32;
1522  } else {
1523  uint64_t hasbit_index = 63; // No hasbit (set a high, unused bit).
1524  if (mt_f->presence) {
1525  hasbit_index = mt_f->presence;
1526  if (hasbit_index > 31) return false;
1527  }
1528  data |= hasbit_index << 24;
1529  }
1530 
1532  uint64_t idx = mt_f->submsg_index;
1533  if (idx > 255) return false;
1534  data |= idx << 16;
1535 
1536  std::string size_ceil = "max";
1537  size_t size = SIZE_MAX;
1538  if (field->message_type()->file() == field->file()) {
1539  // We can only be guaranteed the size of the sub-message if it is in the
1540  // same file as us. We could relax this to increase the speed of
1541  // cross-file sub-message parsing if we are comfortable requiring that
1542  // users compile all messages at the same time.
1543  const upb_MiniTable* sub_mt =
1544  layout.GetMiniTable64(field->message_type());
1545  size = sub_mt->size + 8;
1546  }
1547  std::vector<size_t> breaks = {64, 128, 192, 256};
1548  for (auto brk : breaks) {
1549  if (size <= brk) {
1550  size_ceil = std::to_string(brk);
1551  break;
1552  }
1553  }
1554  ent.first = absl::Substitute("upb_p$0$1_$2bt_max$3b", cardinality, type,
1555  expected_tag > 0xff ? "2" : "1", size_ceil);
1556 
1557  } else {
1558  ent.first = absl::Substitute("upb_p$0$1_$2bt", cardinality, type,
1559  expected_tag > 0xff ? "2" : "1");
1560  }
1561  ent.second = data;
1562  return true;
1563 }
1564 
1565 std::vector<TableEntry> FastDecodeTable(const protobuf::Descriptor* message,
1566  const FileLayout& layout) {
1567  std::vector<TableEntry> table;
1568  for (const auto field : FieldHotnessOrder(message)) {
1569  TableEntry ent;
1570  int slot = GetTableSlot(field);
1571  // std::cerr << "table slot: " << field->number() << ": " << slot << "\n";
1572  if (slot < 0) {
1573  // Tag can't fit in the table.
1574  continue;
1575  }
1576  if (!TryFillTableEntry(layout, field, ent)) {
1577  // Unsupported field type or offset, hasbit index, etc. doesn't fit.
1578  continue;
1579  }
1580  while ((size_t)slot >= table.size()) {
1581  size_t size = std::max(static_cast<size_t>(1), table.size() * 2);
1582  table.resize(size, TableEntry{"fastdecode_generic", 0});
1583  }
1584  if (table[slot].first != "fastdecode_generic") {
1585  // A hotter field already filled this slot.
1586  continue;
1587  }
1588  table[slot] = ent;
1589  }
1590  return table;
1591 }
1592 
1593 // Returns the field mode as a string initializer.
1594 //
1595 // We could just emit this as a number (and we may yet go in that direction) but
1596 // for now emitting symbolic constants gives this better readability and
1597 // debuggability.
1598 std::string GetModeInit(uint8_t mode) {
1599  std::string ret;
1600  switch (mode & kUpb_FieldMode_Mask) {
1601  case kUpb_FieldMode_Map:
1602  ret = "kUpb_FieldMode_Map";
1603  break;
1604  case kUpb_FieldMode_Array:
1605  ret = "kUpb_FieldMode_Array";
1606  break;
1607  case kUpb_FieldMode_Scalar:
1608  ret = "kUpb_FieldMode_Scalar";
1609  break;
1610  default:
1611  break;
1612  }
1613 
1615  absl::StrAppend(&ret, " | kUpb_LabelFlags_IsPacked");
1616  }
1617 
1619  absl::StrAppend(&ret, " | kUpb_LabelFlags_IsExtension");
1620  }
1621 
1622  std::string rep;
1623  switch (mode >> kUpb_FieldRep_Shift) {
1624  case kUpb_FieldRep_1Byte:
1625  rep = "kUpb_FieldRep_1Byte";
1626  break;
1627  case kUpb_FieldRep_4Byte:
1628  rep = "kUpb_FieldRep_4Byte";
1629  break;
1630  case kUpb_FieldRep_Pointer:
1631  rep = "kUpb_FieldRep_Pointer";
1632  break;
1634  rep = "kUpb_FieldRep_StringView";
1635  break;
1636  case kUpb_FieldRep_8Byte:
1637  rep = "kUpb_FieldRep_8Byte";
1638  break;
1639  }
1640 
1641  absl::StrAppend(&ret, " | (", rep, " << kUpb_FieldRep_Shift)");
1642  return ret;
1643 }
1644 
1645 void WriteField(const upb_MiniTable_Field* field64,
1646  const upb_MiniTable_Field* field32, Output& output) {
1647  output("{$0, UPB_SIZE($1, $2), UPB_SIZE($3, $4), $5, $6, $7}",
1648  field64->number, field32->offset, field64->offset, field32->presence,
1649  field64->presence,
1650  field64->submsg_index == kUpb_NoSub
1651  ? "kUpb_NoSub"
1652  : absl::StrCat(field64->submsg_index).c_str(),
1653  field64->descriptortype, GetModeInit(field64->mode));
1654 }
1655 
1656 // Writes a single field into a .upb.c source file.
1657 void WriteMessageField(const upb_MiniTable_Field* field64,
1658  const upb_MiniTable_Field* field32, Output& output) {
1659  output(" ");
1660  WriteField(field64, field32, output);
1661  output(",\n");
1662 }
1663 
1664 // Writes a single message into a .upb.c source file.
1665 void WriteMessage(const protobuf::Descriptor* message, const FileLayout& layout,
1666  Output& output, bool fasttable_enabled) {
1667  std::string msg_name = ToCIdent(message->full_name());
1668  std::string fields_array_ref = "NULL";
1669  std::string submsgs_array_ref = "NULL";
1670  std::string subenums_array_ref = "NULL";
1671  const upb_MiniTable* mt_32 = layout.GetMiniTable32(message);
1672  const upb_MiniTable* mt_64 = layout.GetMiniTable64(message);
1673  std::vector<std::string> subs;
1674 
1675  for (int i = 0; i < mt_64->field_count; i++) {
1676  const upb_MiniTable_Field* f = &mt_64->fields[i];
1677  if (f->submsg_index != kUpb_NoSub) {
1678  subs.push_back(FilePlatformLayout::GetSub(mt_64->subs[f->submsg_index]));
1679  }
1680  }
1681 
1682  if (!subs.empty()) {
1683  std::string submsgs_array_name = msg_name + "_submsgs";
1684  submsgs_array_ref = "&" + submsgs_array_name + "[0]";
1685  output("static const upb_MiniTable_Sub $0[$1] = {\n", submsgs_array_name,
1686  subs.size());
1687 
1688  for (const auto& sub : subs) {
1689  output(" $0,\n", sub);
1690  }
1691 
1692  output("};\n\n");
1693  }
1694 
1695  if (mt_64->field_count > 0) {
1696  std::string fields_array_name = msg_name + "__fields";
1697  fields_array_ref = "&" + fields_array_name + "[0]";
1698  output("static const upb_MiniTable_Field $0[$1] = {\n", fields_array_name,
1699  mt_64->field_count);
1700  for (int i = 0; i < mt_64->field_count; i++) {
1701  WriteMessageField(&mt_64->fields[i], &mt_32->fields[i], output);
1702  }
1703  output("};\n\n");
1704  }
1705 
1706  std::vector<TableEntry> table;
1707  uint8_t table_mask = -1;
1708 
1709  if (fasttable_enabled) {
1710  table = FastDecodeTable(message, layout);
1711  }
1712 
1713  if (table.size() > 1) {
1714  assert((table.size() & (table.size() - 1)) == 0);
1715  table_mask = (table.size() - 1) << 3;
1716  }
1717 
1718  std::string msgext = "kUpb_ExtMode_NonExtendable";
1719 
1720  if (message->extension_range_count()) {
1721  if (message->options().message_set_wire_format()) {
1722  msgext = "kUpb_ExtMode_IsMessageSet";
1723  } else {
1724  msgext = "kUpb_ExtMode_Extendable";
1725  }
1726  }
1727 
1728  output("const upb_MiniTable $0 = {\n", MessageInit(message));
1729  output(" $0,\n", submsgs_array_ref);
1730  output(" $0,\n", fields_array_ref);
1731  output(" $0, $1, $2, $3, $4, $5,\n", layout.GetMessageSize(message),
1732  mt_64->field_count, msgext, mt_64->dense_below, table_mask,
1733  mt_64->required_count);
1734  if (!table.empty()) {
1735  output(" UPB_FASTTABLE_INIT({\n");
1736  for (const auto& ent : table) {
1737  output(" {0x$1, &$0},\n", ent.first,
1738  absl::StrCat(absl::Hex(ent.second, absl::kZeroPad16)));
1739  }
1740  output(" }),\n");
1741  }
1742  output("};\n\n");
1743 }
1744 
1745 int WriteEnums(const protobuf::FileDescriptor* file, Output& output) {
1746  if (file->syntax() != protobuf::FileDescriptor::SYNTAX_PROTO2) {
1747  return 0;
1748  }
1749 
1750  std::vector<const protobuf::EnumDescriptor*> this_file_enums =
1751  SortedEnums(file);
1752 
1753  std::string values_init = "NULL";
1754 
1755  for (const auto* e : this_file_enums) {
1756  uint64_t mask = 0;
1757  std::vector<int32_t> values;
1758  for (auto number : SortedUniqueEnumNumbers(e)) {
1759  if (static_cast<uint32_t>(number) < 64) {
1760  mask |= 1ULL << number;
1761  } else {
1762  values.push_back(number);
1763  }
1764  }
1765 
1766  if (!values.empty()) {
1767  values_init = EnumInit(e) + "_values";
1768  output("static const int32_t $0[$1] = {\n", values_init, values.size());
1769  for (int32_t value : values) {
1770  output(" $0,\n", value);
1771  }
1772  output("};\n\n");
1773  }
1774 
1775  output("const upb_MiniTable_Enum $0 = {\n", EnumInit(e));
1776  output(" $0,\n", values_init);
1777  output(" 0x$0ULL,\n", absl::Hex(mask));
1778  output(" $0,\n", values.size());
1779 
1780  output("};\n\n");
1781  }
1782 
1783  if (!this_file_enums.empty()) {
1784  output("static const upb_MiniTable_Enum *$0[$1] = {\n", kEnumsInit,
1785  this_file_enums.size());
1786  for (const auto* e : this_file_enums) {
1787  output(" &$0,\n", EnumInit(e));
1788  }
1789  output("};\n");
1790  output("\n");
1791  }
1792 
1793  return this_file_enums.size();
1794 }
1795 
1796 int WriteMessages(const FileLayout& layout, Output& output,
1797  bool fasttable_enabled) {
1798  const protobuf::FileDescriptor* file = layout.descriptor();
1799  std::vector<const protobuf::Descriptor*> file_messages = SortedMessages(file);
1800 
1801  if (file_messages.empty()) return 0;
1802 
1803  for (auto message : file_messages) {
1804  WriteMessage(message, layout, output, fasttable_enabled);
1805  }
1806 
1807  output("static const upb_MiniTable *$0[$1] = {\n", kMessagesInit,
1808  file_messages.size());
1809  for (auto message : file_messages) {
1810  output(" &$0,\n", MessageInit(message));
1811  }
1812  output("};\n");
1813  output("\n");
1814  return file_messages.size();
1815 }
1816 
1817 void WriteExtension(const upb_MiniTable_Extension* ext, Output& output) {
1818  WriteField(&ext->field, &ext->field, output);
1819  output(",\n");
1820  output(" &$0,\n", reinterpret_cast<const char*>(ext->extendee));
1821  output(" $0,\n", FilePlatformLayout::GetSub(ext->sub));
1822 }
1823 
1824 int WriteExtensions(const FileLayout& layout, Output& output) {
1825  auto exts = SortedExtensions(layout.descriptor());
1827 
1828  if (exts.empty()) return 0;
1829 
1830  // Order by full name for consistent ordering.
1831  std::map<std::string, const protobuf::Descriptor*> forward_messages;
1832 
1833  for (auto ext : exts) {
1834  forward_messages[ext->containing_type()->full_name()] =
1835  ext->containing_type();
1836  if (ext->message_type()) {
1837  forward_messages[ext->message_type()->full_name()] = ext->message_type();
1838  }
1839  }
1840 
1841  for (const auto& decl : forward_messages) {
1842  output("extern const upb_MiniTable $0;\n", MessageInit(decl.second));
1843  }
1844 
1845  for (auto ext : exts) {
1846  output("const upb_MiniTable_Extension $0 = {\n ", ExtensionLayout(ext));
1847  WriteExtension(layout.GetExtension(ext), output);
1848  output("\n};\n");
1849  }
1850 
1851  output(
1852  "\n"
1853  "static const upb_MiniTable_Extension *$0[$1] = {\n",
1854  kExtensionsInit, exts.size());
1855 
1856  for (auto ext : exts) {
1857  output(" &$0,\n", ExtensionLayout(ext));
1858  }
1859 
1860  output(
1861  "};\n"
1862  "\n");
1863  return exts.size();
1864 }
1865 
1866 // Writes a .upb.c source file.
1867 void WriteSource(const FileLayout& layout, Output& output,
1868  bool fasttable_enabled) {
1869  const protobuf::FileDescriptor* file = layout.descriptor();
1871 
1872  output(
1873  "#include <stddef.h>\n"
1874  "#include \"upb/msg_internal.h\"\n"
1875  "#include \"$0\"\n",
1876  HeaderFilename(file));
1877 
1878  for (int i = 0; i < file->dependency_count(); i++) {
1879  output("#include \"$0\"\n", HeaderFilename(file->dependency(i)));
1880  }
1881 
1882  output(
1883  "\n"
1884  "#include \"upb/port_def.inc\"\n"
1885  "\n");
1886 
1887  int msg_count = WriteMessages(file, output, fasttable_enabled);
1888  int ext_count = WriteExtensions(layout, output);
1889  int enum_count = WriteEnums(file, output);
1890 
1891  output("const upb_MiniTable_File $0 = {\n", FileLayoutName(file));
1892  output(" $0,\n", msg_count ? kMessagesInit : "NULL");
1893  output(" $0,\n", enum_count ? kEnumsInit : "NULL");
1894  output(" $0,\n", ext_count ? kExtensionsInit : "NULL");
1895  output(" $0,\n", msg_count);
1896  output(" $0,\n", enum_count);
1897  output(" $0,\n", ext_count);
1898  output("};\n\n");
1899 
1900  output("#include \"upb/port_undef.inc\"\n");
1901  output("\n");
1902 }
1903 
1904 class Generator : public protoc::CodeGenerator {
1905  ~Generator() override {}
1906  bool Generate(const protobuf::FileDescriptor* file,
1907  const std::string& parameter, protoc::GeneratorContext* context,
1908  std::string* error) const override;
1909  uint64_t GetSupportedFeatures() const override {
1910  return FEATURE_PROTO3_OPTIONAL;
1911  }
1912 };
1913 
1914 bool Generator::Generate(const protobuf::FileDescriptor* file,
1915  const std::string& parameter,
1917  std::string* error) const {
1918  bool fasttable_enabled = false;
1919  std::vector<std::pair<std::string, std::string>> params;
1921 
1922  for (const auto& pair : params) {
1923  if (pair.first == "fasttable") {
1924  fasttable_enabled = true;
1925  } else {
1926  *error = "Unknown parameter: " + pair.first;
1927  return false;
1928  }
1929  }
1930 
1931  FileLayout layout(file);
1932 
1933  std::unique_ptr<protobuf::io::ZeroCopyOutputStream> h_output_stream(
1934  context->Open(HeaderFilename(file)));
1935  Output h_output(h_output_stream.get());
1936  WriteHeader(layout, h_output);
1937 
1938  std::unique_ptr<protobuf::io::ZeroCopyOutputStream> c_output_stream(
1939  context->Open(SourceFilename(file)));
1940  Output c_output(c_output_stream.get());
1941  WriteSource(layout, c_output, fasttable_enabled);
1942 
1943  return true;
1944 }
1945 
1946 } // namespace
1947 } // namespace upbc
1948 
1949 int main(int argc, char** argv) {
1950  std::unique_ptr<google::protobuf::compiler::CodeGenerator> generator(
1951  new upbc::Generator());
1952  return google::protobuf::compiler::PluginMain(argc, argv, generator.get());
1953 }
google::protobuf::Descriptor::full_name
const std::string & full_name() const
xds_interop_client.str
str
Definition: xds_interop_client.py:487
upb::MtDataEncoder
Definition: mini_table.hpp:39
upbc::EmitFileWarning
void EmitFileWarning(const protobuf::FileDescriptor *file, Output &output)
Definition: upb/upbc/common.cc:53
kUpb_FieldRep_4Byte
@ kUpb_FieldRep_4Byte
Definition: msg_internal.h:101
kUpb_FieldType_SInt64
@ kUpb_FieldType_SInt64
Definition: upb/upb/upb.h:326
upb_FieldType
upb_FieldType
Definition: upb/upb/upb.h:308
descriptor_
string_view descriptor_
Definition: elf.cc:154
kUpb_FieldType_SFixed64
@ kUpb_FieldType_SFixed64
Definition: upb/upb/upb.h:324
MessageLayout::size
size_t size
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:939
regen-readme.it
it
Definition: regen-readme.py:15
upb_MiniTable_Sub
Definition: msg_internal.h:154
google::protobuf::FieldDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:515
kUpb_FieldType_SInt32
@ kUpb_FieldType_SInt32
Definition: upb/upb/upb.h:325
absl::str_format_internal::LengthMod::j
@ j
absl::StrAppend
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: abseil-cpp/absl/strings/str_cat.cc:193
testing::internal::IsNull
AssertionResult IsNull(const char *str)
Definition: bloaty/third_party/googletest/googletest/test/gtest-unittest-api_test.cc:139
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
google::protobuf::FieldDescriptor::CPPTYPE_STRING
@ CPPTYPE_STRING
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:562
google::protobuf::compiler::cpp::HasHasbit
bool HasHasbit(const FieldDescriptor *field)
Definition: protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h:443
upb_MiniTable_Sub::subenum
const upb_MiniTable_Enum * subenum
Definition: msg_internal.h:156
google::protobuf::compiler::CodeGenerator
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/code_generator.h:68
upb_MiniTable::fields
const upb_MiniTable_Field * fields
Definition: msg_internal.h:187
kUpb_FieldMode_Mask
#define kUpb_FieldMode_Mask
Definition: msg_internal.h:90
upb_MiniTable_Field
Definition: msg_internal.h:71
kUpb_FieldType_UInt64
@ kUpb_FieldType_UInt64
Definition: upb/upb/upb.h:312
kUpb_LabelFlags_IsPacked
@ kUpb_LabelFlags_IsPacked
Definition: msg_internal.h:94
kUpb_FieldModifier_IsPacked
@ kUpb_FieldModifier_IsPacked
Definition: mini_table.h:51
google::protobuf::FileDescriptor::SYNTAX_PROTO2
@ SYNTAX_PROTO2
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1393
upb_MiniTable::dense_below
uint8_t dense_below
Definition: msg_internal.h:193
upb_MiniTable_FindFieldByNumber
const upb_MiniTable_Field * upb_MiniTable_FindFieldByNumber(const upb_MiniTable *table, uint32_t number)
Definition: mini_table.c:282
ext
void * ext
Definition: x509v3.h:87
upb_MiniTable_Sub::submsg
const struct upb_MiniTable * submsg
Definition: msg_internal.h:155
kUpb_MiniTablePlatform_64Bit
@ kUpb_MiniTablePlatform_64Bit
Definition: mini_table.h:115
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
upb_MiniTable_Extension
Definition: msg_internal.h:202
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
upb_MiniTable_Field::number
uint32_t number
Definition: msg_internal.h:72
upb_MiniTable_SetSubMessage
void upb_MiniTable_SetSubMessage(upb_MiniTable *table, upb_MiniTable_Field *field, const upb_MiniTable *sub)
Definition: mini_table.c:1049
upbc
Definition: upb/upbc/common.cc:30
google::protobuf::Descriptor::FindFieldByNumber
const FieldDescriptor * FindFieldByNumber(int number) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.cc:1564
google::protobuf::OneofDescriptor::full_name
const std::string & full_name() const
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
status
absl::Status status
Definition: rls.cc:251
kUpb_FieldType_SFixed32
@ kUpb_FieldType_SFixed32
Definition: upb/upb/upb.h:323
common.h
upb_MiniTable
Definition: msg_internal.h:185
mode
const char int mode
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
google::protobuf::OneofDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:843
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
upb_MiniTable_BuildMapEntry
upb_MiniTable * upb_MiniTable_BuildMapEntry(upb_FieldType key_type, upb_FieldType value_type, bool value_is_proto3_enum, upb_MiniTablePlatform platform, upb_Arena *arena)
Definition: mini_table.c:928
absl::CEscape
std::string CEscape(absl::string_view src)
Definition: abseil-cpp/absl/strings/escaping.cc:854
upbc::StripExtension
std::string StripExtension(absl::string_view fname)
Definition: upb/upbc/common.cc:37
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
google::protobuf::OneofDescriptor::name
const std::string & name() const
message
char * message
Definition: libuv/docs/code/tty-gravity/main.c:12
google::protobuf::compiler::PluginMain
int PluginMain(int argc, char *argv[], const CodeGenerator *generator)
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/plugin.cc:147
google::protobuf::OneofDescriptor::field
const FieldDescriptor * field(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:2179
kUpb_FieldModifier_IsRepeated
@ kUpb_FieldModifier_IsRepeated
Definition: mini_table.h:50
upbc::HeaderFilename
std::string HeaderFilename(const google::protobuf::FileDescriptor *file)
Definition: upb/upbc/common.cc:73
mini_table.hpp
kUpb_LabelFlags_IsExtension
@ kUpb_LabelFlags_IsExtension
Definition: msg_internal.h:95
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
absl::kZeroPad16
@ kZeroPad16
Definition: abseil-cpp/absl/strings/str_cat.h:101
google::protobuf::compiler
Definition: bloaty/third_party/protobuf/benchmarks/util/protoc-gen-gogoproto.cc:19
kUpb_FieldType_Double
@ kUpb_FieldType_Double
Definition: upb/upb/upb.h:309
kUpb_FieldType_Bool
@ kUpb_FieldType_Bool
Definition: upb/upb/upb.h:316
o
UnboundConversion o
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:97
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
google::protobuf::FileDescriptor::SYNTAX_PROTO3
@ SYNTAX_PROTO3
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1394
kUpb_FieldType_Float
@ kUpb_FieldType_Float
Definition: upb/upb/upb.h:310
ULL
#define ULL(x)
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc:57
absl::Hex
Definition: abseil-cpp/absl/strings/str_cat.h:134
upb_MiniTable_Field::presence
int16_t presence
Definition: msg_internal.h:74
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
kUpb_FieldType_UInt32
@ kUpb_FieldType_UInt32
Definition: upb/upb/upb.h:321
absl::FormatConversionChar::e
@ e
kUpb_FieldRep_8Byte
@ kUpb_FieldRep_8Byte
Definition: msg_internal.h:104
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
upb_MiniTable::subs
const upb_MiniTable_Sub * subs
Definition: msg_internal.h:186
arena_
Arena * arena_
Definition: client_channel.cc:391
kUpb_FieldType_String
@ kUpb_FieldType_String
Definition: upb/upb/upb.h:317
unique
static int unique
Definition: h2_local_abstract_uds_percent_encoded.cc:25
tag
static void * tag(intptr_t t)
Definition: bad_client.cc:318
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
SIZE_MAX
#define SIZE_MAX
Definition: stdint-msvc2008.h:206
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
upb_MiniTable::field_count
uint16_t field_count
Definition: msg_internal.h:191
kUpb_FieldType_Enum
@ kUpb_FieldType_Enum
Definition: upb/upb/upb.h:322
upb_Arena_Malloc
UPB_INLINE void * upb_Arena_Malloc(upb_Arena *a, size_t size)
Definition: upb/upb/upb.h:222
kUpb_MessageModifier_DefaultIsPacked
@ kUpb_MessageModifier_DefaultIsPacked
Definition: mini_table.h:45
kUpb_FieldType_Fixed32
@ kUpb_FieldType_Fixed32
Definition: upb/upb/upb.h:315
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::flat_hash_set
Definition: abseil-cpp/absl/container/flat_hash_set.h:105
upb_FieldMode_Get
UPB_INLINE upb_FieldMode upb_FieldMode_Get(const upb_MiniTable_Field *field)
Definition: msg_internal.h:110
number
int32_t number
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:850
kUpb_FieldRep_Shift
@ kUpb_FieldRep_Shift
Definition: msg_internal.h:106
kUpb_FieldMode_Map
@ kUpb_FieldMode_Map
Definition: msg_internal.h:84
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
upb_MiniTable_Field::offset
uint16_t offset
Definition: msg_internal.h:73
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
google::protobuf::FieldDescriptor::CPPTYPE_UINT64
@ CPPTYPE_UINT64
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:557
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
layout
MessageLayout * layout
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:809
setup.idx
idx
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:197
kUpb_FieldModifier_IsRequired
@ kUpb_FieldModifier_IsRequired
Definition: mini_table.h:54
kNull
static const int kNull
Definition: stack_test.cc:58
upb_MiniTable_BuildMessageSet
upb_MiniTable * upb_MiniTable_BuildMessageSet(upb_MiniTablePlatform platform, upb_Arena *arena)
Definition: mini_table.c:914
kUpb_NoSub
#define kUpb_NoSub
Definition: msg_internal.h:81
upb_MiniTable_Field::mode
uint8_t mode
Definition: msg_internal.h:77
upb_MiniTable_Field::descriptortype
uint8_t descriptortype
Definition: msg_internal.h:76
value
const char * value
Definition: hpack_parser_table.cc:165
kUpb_FieldType_Fixed64
@ kUpb_FieldType_Fixed64
Definition: upb/upb/upb.h:314
upbc::ToPreproc
std::string ToPreproc(absl::string_view str)
Definition: upb/upbc/common.cc:49
google::protobuf::FieldDescriptor::CPPTYPE_INT64
@ CPPTYPE_INT64
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:555
main
int main(int argc, char **argv)
Definition: protoc-gen-upb.cc:1949
kUpb_MiniTablePlatform_32Bit
@ kUpb_MiniTablePlatform_32Bit
Definition: mini_table.h:114
upb::Arena
Definition: upb.hpp:68
kUpb_FieldMode_Scalar
@ kUpb_FieldMode_Scalar
Definition: msg_internal.h:86
field
const FieldDescriptor * field
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc:2692
upbc::FileLayoutName
std::string FileLayoutName(const google::protobuf::FileDescriptor *file)
Definition: upb/upbc/common.cc:69
key
const char * key
Definition: hpack_parser_table.cc:164
absl::types_internal::Generator
GeneratorType< Fun > Generator(Fun fun, const char *description)
Definition: abseil-cpp/absl/types/internal/conformance_testing.h:96
google::protobuf::FieldDescriptor::CPPTYPE_UINT32
@ CPPTYPE_UINT32
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:556
google::protobuf::FieldDescriptor::CPPTYPE_FLOAT
@ CPPTYPE_FLOAT
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:559
upb_MiniTablePlatform
upb_MiniTablePlatform
Definition: mini_table.h:113
ABSL_ASSERT
#define ABSL_ASSERT(expr)
Definition: abseil-cpp/absl/base/macros.h:97
upb.hpp
kUpb_FieldModifier_IsProto3Singular
@ kUpb_FieldModifier_IsProto3Singular
Definition: mini_table.h:53
google::protobuf::FieldDescriptor::CPPTYPE_BOOL
@ CPPTYPE_BOOL
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:560
google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE
@ CPPTYPE_DOUBLE
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:558
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
upb_MiniTable::size
uint16_t size
Definition: msg_internal.h:190
profile_analyzer.fields
list fields
Definition: profile_analyzer.py:266
absl::flat_hash_map
Definition: abseil-cpp/absl/container/flat_hash_map.h:113
first
StrT first
Definition: cxa_demangle.cpp:4884
google::protobuf::FieldDescriptor::CPPTYPE_ENUM
@ CPPTYPE_ENUM
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:561
values
std::array< int64_t, Size > values
Definition: abseil-cpp/absl/container/btree_benchmark.cc:608
kUpb_MessageModifier_IsExtendable
@ kUpb_MessageModifier_IsExtendable
Definition: mini_table.h:46
rep
const CordRep * rep
Definition: cord_analysis.cc:53
ok
bool ok
Definition: async_end2end_test.cc:197
google::protobuf::EnumValueDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1075
google::protobuf::Descriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:231
desc
#define desc
Definition: bloaty/third_party/protobuf/src/google/protobuf/extension_set.h:338
google::protobuf::compiler::ParseGeneratorParameter
void ParseGeneratorParameter(const std::string &text, std::vector< std::pair< std::string, std::string > > *output)
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/code_generator.cc:101
upbc::MessageName
std::string MessageName(const protobuf::Descriptor *descriptor)
Definition: upb/upbc/common.cc:65
upb_MiniTable_Build
upb_MiniTable * upb_MiniTable_Build(const char *data, size_t len, upb_MiniTablePlatform platform, upb_Arena *arena, upb_Status *status)
Definition: mini_table.c:1038
kUpb_FieldModifier_IsClosedEnum
@ kUpb_FieldModifier_IsClosedEnum
Definition: mini_table.h:52
absl::Substitute
ABSL_MUST_USE_RESULT std::string Substitute(absl::string_view format)
Definition: abseil-cpp/absl/strings/substitute.h:506
kUpb_FieldType_Message
@ kUpb_FieldType_Message
Definition: upb/upb/upb.h:319
upb_MiniTable::required_count
uint8_t required_count
Definition: msg_internal.h:195
google::protobuf::FileDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1320
table
uint8_t table[256]
Definition: hpack_parser.cc:456
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE
@ CPPTYPE_MESSAGE
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:563
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
kUpb_MessageModifier_ValidateUtf8
@ kUpb_MessageModifier_ValidateUtf8
Definition: mini_table.h:44
kUpb_FieldRep_Pointer
@ kUpb_FieldRep_Pointer
Definition: msg_internal.h:103
google::protobuf::OneofDescriptor::field_count
int field_count() const
file::name
char * name
Definition: bloaty/third_party/zlib/examples/gzappend.c:176
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
kUpb_FieldType_Int32
@ kUpb_FieldType_Int32
Definition: upb/upb/upb.h:313
kUpb_FieldRep_1Byte
@ kUpb_FieldRep_1Byte
Definition: msg_internal.h:100
kUpb_FieldRep_StringView
@ kUpb_FieldRep_StringView
Definition: msg_internal.h:102
regress.m
m
Definition: regress/regress.py:25
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
upb_MiniTable_Field::submsg_index
uint16_t submsg_index
Definition: msg_internal.h:75
google::protobuf::EnumDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:918
upb::Status
Definition: upb.hpp:35
google::protobuf::compiler::GeneratorContext
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/code_generator.h:119
kUpb_FieldMode_Array
@ kUpb_FieldMode_Array
Definition: msg_internal.h:85
kUpb_FieldType_Int64
@ kUpb_FieldType_Int64
Definition: upb/upb/upb.h:311
subs
template_param_type subs
Definition: cxa_demangle.cpp:4906
to_string
static bool to_string(zval *from)
Definition: protobuf/php/ext/google/protobuf/convert.c:333
descriptor
static const char descriptor[1336]
Definition: certs.upbdefs.c:16
pair
std::pair< std::string, std::string > pair
Definition: abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc:78
platform
Definition: test_arm_regression.c:18
google::protobuf::FieldDescriptor::cpp_type
CppType cpp_type() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:2139
upb_MiniTable_BuildExtension
bool upb_MiniTable_BuildExtension(const char *data, size_t len, upb_MiniTable_Extension *ext, upb_MiniTable_Sub sub, upb_Status *status)
Definition: mini_table.c:1018
upbc::ToCIdent
std::string ToCIdent(absl::string_view str)
Definition: upb/upbc/common.cc:45
absl::EndsWith
bool EndsWith(absl::string_view text, absl::string_view suffix) noexcept
Definition: third_party/abseil-cpp/absl/strings/match.h:68
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
kUpb_FieldType_Bytes
@ kUpb_FieldType_Bytes
Definition: upb/upb/upb.h:320
google::protobuf::FieldDescriptor::CPPTYPE_INT32
@ CPPTYPE_INT32
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:554


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:47