diff --git a/upbc/protoc-gen-upb.cc b/upbc/protoc-gen-upb.cc index 159a8ecc45..e809fa66c2 100644 --- a/upbc/protoc-gen-upb.cc +++ b/upbc/protoc-gen-upb.cc @@ -243,7 +243,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output MessageLayout layout(message); output("/* $0 */\n\n", message->full_name()); - std::string msgname = ToCIdent(message->full_name()); + std::string msg_name = ToCIdent(message->full_name()); if (!message->options().map_entry()) { output( @@ -285,7 +285,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output "UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) { " "return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t); }\n" "\n", - fullname, msgname, oneof->name(), + fullname, msg_name, oneof->name(), GetSizeInit(layout.GetOneofCaseOffset(oneof))); } @@ -297,12 +297,12 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE bool $0_has_$1(const $0 *msg) { " "return _upb_hasbit(msg, $2); }\n", - msgname, field->name(), layout.GetHasbitIndex(field)); + msg_name, field->name(), layout.GetHasbitIndex(field)); } else if (field->real_containing_oneof()) { output( "UPB_INLINE bool $0_has_$1(const $0 *msg) { " "return _upb_getoneofcase(msg, $2) == $3; }\n", - msgname, field->name(), + msg_name, field->name(), GetSizeInit( layout.GetOneofCaseOffset(field->real_containing_oneof())), field->number()); @@ -310,7 +310,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE bool $0_has_$1(const $0 *msg) { " "return _upb_has_submsg_nohasbit(msg, $2); }\n", - msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field))); + msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); } // Generate getter. @@ -321,11 +321,11 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE size_t $0_$1_size(const $0 *msg) {" "return _upb_msg_map_size(msg, $2); }\n", - msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field))); + msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); output( "UPB_INLINE bool $0_$1_get(const $0 *msg, $2 key, $3 *val) { " "return _upb_msg_map_get(msg, $4, &key, $5, val, $6); }\n", - msgname, field->name(), CType(key), CType(val), + msg_name, field->name(), CType(key), CType(val), GetSizeInit(layout.GetFieldOffset(field)), key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING ? "0" @@ -336,7 +336,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE $0 $1_$2_next(const $1 *msg, size_t* iter) { " "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", - CTypeConst(field), msgname, field->name(), + CTypeConst(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); } else if (message->options().map_entry()) { output( @@ -345,7 +345,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output " _upb_msg_map_$2(msg, &ret, $4);\n" " return ret;\n" "}\n", - CTypeConst(field), msgname, field->name(), CType(field), + CTypeConst(field), msg_name, field->name(), CType(field), field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING ? "0" : "sizeof(ret)"); @@ -353,13 +353,13 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE $0 const* $1_$2(const $1 *msg, size_t *len) { " "return ($0 const*)_upb_array_accessor(msg, $3, len); }\n", - CTypeConst(field), msgname, field->name(), + CTypeConst(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); } else if (field->real_containing_oneof()) { output( "UPB_INLINE $0 $1_$2(const $1 *msg) { " "return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6); }\n", - CTypeConst(field), msgname, field->name(), + CTypeConst(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)), GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())), field->number(), FieldDefault(field)); @@ -367,7 +367,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE $0 $1_$2(const $1 *msg) { " "return *UPB_PTR_AT(msg, $3, $0); }\n", - CTypeConst(field), msgname, field->name(), + CTypeConst(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); } } @@ -384,12 +384,12 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); output( "UPB_INLINE void $0_$1_clear($0 *msg) { _upb_msg_map_clear(msg, $2); }\n", - msgname, field->name(), + msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); output( "UPB_INLINE bool $0_$1_set($0 *msg, $2 key, $3 val, upb_arena *a) { " "return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a); }\n", - msgname, field->name(), CType(key), CType(val), + msg_name, field->name(), CType(key), CType(val), GetSizeInit(layout.GetFieldOffset(field)), key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING ? "0" @@ -400,7 +400,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE bool $0_$1_delete($0 *msg, $2 key) { " "return _upb_msg_map_delete(msg, $3, &key, $4); }\n", - msgname, field->name(), CType(key), + msg_name, field->name(), CType(key), GetSizeInit(layout.GetFieldOffset(field)), key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING ? "0" @@ -408,21 +408,21 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE $0 $1_$2_nextmutable($1 *msg, size_t* iter) { " "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", - CType(field), msgname, field->name(), + CType(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); } else if (field->is_repeated()) { output( "UPB_INLINE $0* $1_mutable_$2($1 *msg, size_t *len) {\n" " return ($0*)_upb_array_mutable_accessor(msg, $3, len);\n" "}\n", - CType(field), msgname, field->name(), + CType(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field))); output( "UPB_INLINE $0* $1_resize_$2($1 *msg, size_t len, " "upb_arena *arena) {\n" " return ($0*)_upb_array_resize_accessor2(msg, $3, len, $4, arena);\n" "}\n", - CType(field), msgname, field->name(), + CType(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { @@ -434,7 +434,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output " if (!ok) return NULL;\n" " return sub;\n" "}\n", - MessageName(field->message_type()), msgname, field->name(), + MessageName(field->message_type()), msg_name, field->name(), MessageInit(field->message_type()), GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); @@ -444,7 +444,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output " return _upb_array_append_accessor2(msg, $3, $4, &val,\n" " arena);\n" "}\n", - CType(field), msgname, field->name(), + CType(field), msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field)); } @@ -457,7 +457,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output // The common function signature for all setters. Varying implementations // follow. - output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msgname, + output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name, field->name(), CType(field)); if (message->options().map_entry()) { @@ -497,7 +497,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output " }\n" " return sub;\n" "}\n", - MessageName(field->message_type()), msgname, field->name(), + MessageName(field->message_type()), msg_name, field->name(), MessageInit(field->message_type())); } } @@ -536,7 +536,7 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) { "#endif\n" "\n"); - std::vector this_file_messages = + const std::vector this_file_messages = SortedMessages(file); // Forward-declare types defined in this file. @@ -554,7 +554,7 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) { // Order by full name for consistent ordering. std::map forward_messages; - for (auto message : SortedMessages(file)) { + for (auto* message : this_file_messages) { for (int i = 0; i < message->field_count(); i++) { const protobuf::FieldDescriptor* field = message->field(i); if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE && @@ -843,139 +843,163 @@ std::vector FastDecodeTable(const protobuf::Descriptor* message, return table; } -void WriteSource(const protobuf::FileDescriptor* file, Output& output, - bool fasttable_enabled) { - EmitFileWarning(file, output); +void WriteField(const protobuf::FieldDescriptor* field, + absl::string_view offset, absl::string_view presence, + int submsg_index, Output& output) { - output( - "#include \n" - "#include \"upb/msg_internal.h\"\n" - "#include \"$0\"\n", - HeaderFilename(file->name())); + std::string label; + if (field->is_map()) { + label = "_UPB_LABEL_MAP"; + } else if (field->is_packed()) { + label = "_UPB_LABEL_PACKED"; + } else { + label = absl::StrCat(field->label()); + } - for (int i = 0; i < file->dependency_count(); i++) { - output("#include \"$0\"\n", HeaderFilename(file->dependency(i)->name())); + output("{$0, $1, $2, $3, $4, $5}", field->number(), offset, presence, + submsg_index, TableDescriptorType(field), label); +} + +// Writes a single field into a .upb.c source file. +void WriteMessageField(const protobuf::FieldDescriptor* field, + const MessageLayout& layout, int submsg_index, + Output& output) { + std::string presence = "0"; + + if (MessageLayout::HasHasbit(field)) { + int index = layout.GetHasbitIndex(field); + assert(index != 0); + presence = absl::StrCat(index); + } else if (field->real_containing_oneof()) { + MessageLayout::Size case_offset = + layout.GetOneofCaseOffset(field->real_containing_oneof()); + + // We encode as negative to distinguish from hasbits. + case_offset.size32 = ~case_offset.size32; + case_offset.size64 = ~case_offset.size64; + assert(case_offset.size32 < 0); + assert(case_offset.size64 < 0); + presence = GetSizeInit(case_offset); } - output( - "\n" - "#include \"upb/port_def.inc\"\n" - "\n"); + output(" "); + WriteField(field, GetSizeInit(layout.GetFieldOffset(field)), presence, + submsg_index, output); + output(",\n"); +} +// Writes a single message into a .upb.c source file. +void WriteMessage(const protobuf::Descriptor* message, Output& output, + bool fasttable_enabled) { + std::string msg_name = ToCIdent(message->full_name()); + std::string fields_array_ref = "NULL"; + std::string submsgs_array_ref = "NULL"; + uint8_t dense_below = 0; + const int dense_below_max = std::numeric_limits::max(); + MessageLayout layout(message); + SubmsgArray submsg_array(message); + + if (!submsg_array.submsgs().empty()) { + // TODO(haberman): could save a little bit of space by only generating a + // "submsgs" array for every strongly-connected component. + std::string submsgs_array_name = msg_name + "_submsgs"; + submsgs_array_ref = "&" + submsgs_array_name + "[0]"; + output("static const upb_msglayout *const $0[$1] = {\n", + submsgs_array_name, submsg_array.submsgs().size()); + + for (auto submsg : submsg_array.submsgs()) { + output(" &$0,\n", MessageInit(submsg)); + } - for (auto message : SortedMessages(file)) { - std::string msgname = ToCIdent(message->full_name()); - std::string fields_array_ref = "NULL"; - std::string submsgs_array_ref = "NULL"; - uint8_t dense_below = 0; - int dense_below_max = std::numeric_limits::max(); - MessageLayout layout(message); - SubmsgArray submsg_array(message); + output("};\n\n"); + } - if (!submsg_array.submsgs().empty()) { - // TODO(haberman): could save a little bit of space by only generating a - // "submsgs" array for every strongly-connected component. - std::string submsgs_array_name = msgname + "_submsgs"; - submsgs_array_ref = "&" + submsgs_array_name + "[0]"; - output("static const upb_msglayout *const $0[$1] = {\n", - submsgs_array_name, submsg_array.submsgs().size()); + std::vector field_number_order = + FieldNumberOrder(message); + if (!field_number_order.empty()) { + std::string fields_array_name = msg_name + "__fields"; + fields_array_ref = "&" + fields_array_name + "[0]"; + output("static const upb_msglayout_field $0[$1] = {\n", + fields_array_name, field_number_order.size()); + for (int i = 0; i < static_cast(field_number_order.size()); i++) { + auto field = field_number_order[i]; + int submsg_index = 0; + + if (i < dense_below_max && field->number() == i + 1 && + (i == 0 || field_number_order[i - 1]->number() == i)) { + dense_below = i + 1; + } - for (auto submsg : submsg_array.submsgs()) { - output(" &$0,\n", MessageInit(submsg)); + if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + submsg_index = submsg_array.GetIndex(field); } - output("};\n\n"); + WriteMessageField(field, layout, submsg_index, output); } + output("};\n\n"); + } - std::vector field_number_order = - FieldNumberOrder(message); - if (!field_number_order.empty()) { - std::string fields_array_name = msgname + "__fields"; - fields_array_ref = "&" + fields_array_name + "[0]"; - output("static const upb_msglayout_field $0[$1] = {\n", - fields_array_name, field_number_order.size()); - for (int i = 0; i < static_cast(field_number_order.size()); i++) { - auto field = field_number_order[i]; - int submsg_index = 0; - std::string presence = "0"; - - if (i < dense_below_max && field->number() == i + 1 && - (i == 0 || field_number_order[i - 1]->number() == i)) { - dense_below = i + 1; - } - - if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - submsg_index = submsg_array.GetIndex(field); - } + std::vector table; + uint8_t table_mask = -1; - if (MessageLayout::HasHasbit(field)) { - int index = layout.GetHasbitIndex(field); - assert(index != 0); - presence = absl::StrCat(index); - } else if (field->real_containing_oneof()) { - MessageLayout::Size case_offset = - layout.GetOneofCaseOffset(field->real_containing_oneof()); - - // We encode as negative to distinguish from hasbits. - case_offset.size32 = ~case_offset.size32; - case_offset.size64 = ~case_offset.size64; - assert(case_offset.size32 < 0); - assert(case_offset.size64 < 0); - presence = GetSizeInit(case_offset); - } + if (fasttable_enabled) { + table = FastDecodeTable(message, layout); + } - std::string label; - if (field->is_map()) { - label = "_UPB_LABEL_MAP"; - } else if (field->is_packed()) { - label = "_UPB_LABEL_PACKED"; - } else { - label = absl::StrCat(field->label()); - } + if (table.size() > 1) { + assert((table.size() & (table.size() - 1)) == 0); + table_mask = (table.size() - 1) << 3; + } - output(" {$0, $1, $2, $3, $4, $5},\n", - field->number(), - GetSizeInit(layout.GetFieldOffset(field)), - presence, - submsg_index, - TableDescriptorType(field), - label); - } - output("};\n\n"); + output("const upb_msglayout $0 = {\n", MessageInit(message)); + output(" $0,\n", submsgs_array_ref); + output(" $0,\n", fields_array_ref); + output(" $0, $1, $2, $3, $4,\n", GetSizeInit(layout.message_size()), + field_number_order.size(), + "false", // TODO: extendable + dense_below, + table_mask + ); + if (!table.empty()) { + output(" UPB_FASTTABLE_INIT({\n"); + for (const auto& ent : table) { + output(" {0x$1, &$0},\n", ent.first, + absl::StrCat(absl::Hex(ent.second, absl::kZeroPad16))); } + output(" }),\n"); + } + output("};\n\n"); +} - std::vector table; - uint8_t table_mask = -1; +void WriteMessages(const protobuf::FileDescriptor* file, Output& output, + bool fasttable_enabled) { + for (auto* message : SortedMessages(file)) { + WriteMessage(message, output, fasttable_enabled); + } +} - if (fasttable_enabled) { - table = FastDecodeTable(message, layout); - } +// Writes a .upb.c source file. +void WriteSource(const protobuf::FileDescriptor* file, Output& output, + bool fasttable_enabled) { + EmitFileWarning(file, output); - if (table.size() > 1) { - assert((table.size() & (table.size() - 1)) == 0); - table_mask = (table.size() - 1) << 3; - } + output( + "#include \n" + "#include \"upb/msg_internal.h\"\n" + "#include \"$0\"\n", + HeaderFilename(file->name())); - output("const upb_msglayout $0 = {\n", MessageInit(message)); - output(" $0,\n", submsgs_array_ref); - output(" $0,\n", fields_array_ref); - output(" $0, $1, $2, $3, $4,\n", GetSizeInit(layout.message_size()), - field_number_order.size(), - "false", // TODO: extendable - dense_below, - table_mask - ); - if (!table.empty()) { - output(" UPB_FASTTABLE_INIT({\n"); - for (const auto& ent : table) { - output(" {0x$1, &$0},\n", ent.first, - absl::StrCat(absl::Hex(ent.second, absl::kZeroPad16))); - } - output(" }),\n"); - } - output("};\n\n"); + for (int i = 0; i < file->dependency_count(); i++) { + output("#include \"$0\"\n", HeaderFilename(file->dependency(i)->name())); } + output( + "\n" + "#include \"upb/port_def.inc\"\n" + "\n"); + + WriteMessages(file, output, fasttable_enabled); + output("#include \"upb/port_undef.inc\"\n"); output("\n"); }