Enable tree shaking unused sub-messages for C generated MiniTables.

PiperOrigin-RevId: 642616862
pull/17119/head
Joshua Haberman 6 months ago committed by Copybara-Service
parent 968087eb61
commit 1b451603f6
  1. 11
      upb/mini_table/internal/message.h
  2. 52
      upb_generator/protoc-gen-upb.cc
  3. 25
      upb_generator/protoc-gen-upb_minitable.cc

@ -77,6 +77,17 @@ struct upb_MiniTable {
extern "C" { extern "C" {
#endif #endif
UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(
_upb_MiniTable_StrongReference)(const struct upb_MiniTable* mt) {
#if defined(__GNUC__)
__asm__("" : : "r"(mt));
#else
const struct upb_MiniTable* volatile unused = mt;
(void)&unused; // Use address to avoid an extra load of "unused".
#endif
return mt;
}
UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_Empty)(void) { UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_Empty)(void) {
extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty);

@ -233,6 +233,9 @@ std::string MapValueSize(upb::FieldDefPtr map_field, absl::string_view expr) {
std::string FieldInitializer(const DefPoolPair& pools, upb::FieldDefPtr field, std::string FieldInitializer(const DefPoolPair& pools, upb::FieldDefPtr field,
const Options& options); const Options& options);
std::string FieldInitializerStrong(const DefPoolPair& pools,
upb::FieldDefPtr field,
const Options& options);
void DumpEnumValues(upb::EnumDefPtr desc, Output& output) { void DumpEnumValues(upb::EnumDefPtr desc, Output& output) {
std::vector<upb::EnumValDefPtr> values; std::vector<upb::EnumValDefPtr> values;
@ -466,7 +469,7 @@ void GenerateMapGetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
msg_name, resolved_name, MapKeyCType(field), MapValueCType(field), msg_name, resolved_name, MapKeyCType(field), MapValueCType(field),
FieldInitializer(pools, field, options), MapKeySize(field, "key"), FieldInitializerStrong(pools, field, options), MapKeySize(field, "key"),
MapValueSize(field, "*val")); MapValueSize(field, "*val"));
output( output(
R"cc( R"cc(
@ -478,7 +481,7 @@ void GenerateMapGetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
CTypeConst(field), msg_name, resolved_name, CTypeConst(field), msg_name, resolved_name,
FieldInitializer(pools, field, options)); FieldInitializerStrong(pools, field, options));
// Generate private getter returning a upb_Map or NULL for immutable and // Generate private getter returning a upb_Map or NULL for immutable and
// a upb_Map for mutable. // a upb_Map for mutable.
// //
@ -497,7 +500,7 @@ void GenerateMapGetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
msg_name, resolved_name, kMapGetterPostfix, kMutableMapGetterPostfix, msg_name, resolved_name, kMapGetterPostfix, kMutableMapGetterPostfix,
FieldInitializer(pools, field, options), FieldInitializerStrong(pools, field, options),
MapKeySize(field, MapKeyCType(field)), MapKeySize(field, MapKeyCType(field)),
MapValueSize(field, MapValueCType(field))); MapValueSize(field, MapValueCType(field)));
} }
@ -541,7 +544,7 @@ void GenerateRepeatedGetters(upb::FieldDefPtr field, const DefPoolPair& pools,
CTypeConst(field), // $0 CTypeConst(field), // $0
msg_name, // $1 msg_name, // $1
ResolveFieldName(field, field_names), // $2 ResolveFieldName(field, field_names), // $2
FieldInitializer(pools, field, options) // #3 FieldInitializerStrong(pools, field, options) // #3
); );
// Generate private getter returning array or NULL for immutable and upb_Array // Generate private getter returning array or NULL for immutable and upb_Array
// for mutable. // for mutable.
@ -572,7 +575,7 @@ void GenerateRepeatedGetters(upb::FieldDefPtr field, const DefPoolPair& pools,
CTypeConst(field), // $0 CTypeConst(field), // $0
msg_name, // $1 msg_name, // $1
ResolveFieldName(field, field_names), // $2 ResolveFieldName(field, field_names), // $2
FieldInitializer(pools, field, options), // $3 FieldInitializerStrong(pools, field, options), // $3
kRepeatedFieldArrayGetterPostfix, // $4 kRepeatedFieldArrayGetterPostfix, // $4
kRepeatedFieldMutableArrayGetterPostfix // $5 kRepeatedFieldMutableArrayGetterPostfix // $5
); );
@ -595,7 +598,7 @@ void GenerateScalarGetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
CTypeConst(field), msg_name, field_name, FieldDefault(field), CTypeConst(field), msg_name, field_name, FieldDefault(field),
FieldInitializer(pools, field, Options)); FieldInitializerStrong(pools, field, Options));
} }
void GenerateGetters(upb::FieldDefPtr field, const DefPoolPair& pools, void GenerateGetters(upb::FieldDefPtr field, const DefPoolPair& pools,
@ -640,7 +643,7 @@ void GenerateMapSetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
msg_name, resolved_name, MapKeyCType(field), MapValueCType(field), msg_name, resolved_name, MapKeyCType(field), MapValueCType(field),
FieldInitializer(pools, field, options), MapKeySize(field, "key"), FieldInitializerStrong(pools, field, options), MapKeySize(field, "key"),
MapValueSize(field, "val")); MapValueSize(field, "val"));
output( output(
R"cc( R"cc(
@ -663,7 +666,7 @@ void GenerateMapSetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
CType(field), msg_name, resolved_name, CType(field), msg_name, resolved_name,
FieldInitializer(pools, field, options)); FieldInitializerStrong(pools, field, options));
} }
void GenerateRepeatedSetters(upb::FieldDefPtr field, const DefPoolPair& pools, void GenerateRepeatedSetters(upb::FieldDefPtr field, const DefPoolPair& pools,
@ -686,7 +689,7 @@ void GenerateRepeatedSetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
CType(field), msg_name, resolved_name, CType(field), msg_name, resolved_name,
FieldInitializer(pools, field, options)); FieldInitializerStrong(pools, field, options));
output( output(
R"cc( R"cc(
UPB_INLINE $0* $1_resize_$2($1* msg, size_t size, upb_Arena* arena) { UPB_INLINE $0* $1_resize_$2($1* msg, size_t size, upb_Arena* arena) {
@ -717,7 +720,7 @@ void GenerateRepeatedSetters(upb::FieldDefPtr field, const DefPoolPair& pools,
)cc", )cc",
MessageName(field.message_type()), msg_name, resolved_name, MessageName(field.message_type()), msg_name, resolved_name,
MessageMiniTableRef(field.message_type(), options), MessageMiniTableRef(field.message_type(), options),
FieldInitializer(pools, field, options)); FieldInitializerStrong(pools, field, options));
} else { } else {
output( output(
R"cc( R"cc(
@ -735,7 +738,7 @@ void GenerateRepeatedSetters(upb::FieldDefPtr field, const DefPoolPair& pools,
} }
)cc", )cc",
CType(field), msg_name, resolved_name, CType(field), msg_name, resolved_name,
FieldInitializer(pools, field, options)); FieldInitializerStrong(pools, field, options));
} }
} }
@ -768,7 +771,7 @@ void GenerateNonRepeatedSetters(upb::FieldDefPtr field,
} }
)cc", )cc",
msg_name, field_name, CType(field), msg_name, field_name, CType(field),
FieldInitializer(pools, field, options)); FieldInitializerStrong(pools, field, options));
} }
// Message fields also have a Msg_mutable_foo() accessor that will create // Message fields also have a Msg_mutable_foo() accessor that will create
@ -1007,6 +1010,31 @@ std::string FieldInitializer(upb::FieldDefPtr field,
} }
} }
std::string StrongReferenceSingle(upb::FieldDefPtr field) {
if (!field.message_type()) return "";
return absl::Substitute(" UPB_PRIVATE(_upb_MiniTable_StrongReference)(&$0)",
MessageInitName(field.message_type()));
}
std::string StrongReference(upb::FieldDefPtr field) {
if (field.IsMap() &&
field.message_type().FindFieldByNumber(2).IsSubMessage()) {
return StrongReferenceSingle(field) + ";\n" +
StrongReferenceSingle(field.message_type().FindFieldByNumber(2));
} else {
return StrongReferenceSingle(field);
}
}
std::string FieldInitializerStrong(const DefPoolPair& pools,
upb::FieldDefPtr field,
const Options& options) {
std::string ret = FieldInitializer(pools, field, options);
if (!options.bootstrap && field.IsSubMessage()) {
ret += ";\n" + StrongReference(field);
}
return ret;
}
std::string FieldInitializer(const DefPoolPair& pools, upb::FieldDefPtr field, std::string FieldInitializer(const DefPoolPair& pools, upb::FieldDefPtr field,
const Options& options) { const Options& options) {
return FieldInitializer(field, pools.GetField64(field), return FieldInitializer(field, pools.GetField64(field),

@ -19,6 +19,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "absl/container/flat_hash_set.h"
#include "absl/log/absl_check.h" #include "absl/log/absl_check.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
@ -337,9 +338,13 @@ std::string GetSub(upb::FieldDefPtr field, bool is_extension) {
return std::string("{.UPB_PRIVATE(submsg) = NULL}"); return std::string("{.UPB_PRIVATE(submsg) = NULL}");
} }
bool IsCrossFile(upb::FieldDefPtr field) {
return field.message_type() != field.containing_type();
}
// Writes a single message into a .upb.c source file. // Writes a single message into a .upb.c source file.
void WriteMessage(upb::MessageDefPtr message, const DefPoolPair& pools, void WriteMessage(upb::MessageDefPtr message, const DefPoolPair& pools,
Output& output) { const MiniTableOptions& options, Output& output) {
std::string msg_name = ToCIdent(message.full_name()); std::string msg_name = ToCIdent(message.full_name());
std::string fields_array_ref = "NULL"; std::string fields_array_ref = "NULL";
std::string submsgs_array_ref = "NULL"; std::string submsgs_array_ref = "NULL";
@ -347,6 +352,7 @@ void WriteMessage(upb::MessageDefPtr message, const DefPoolPair& pools,
const upb_MiniTable* mt_32 = pools.GetMiniTable32(message); const upb_MiniTable* mt_32 = pools.GetMiniTable32(message);
const upb_MiniTable* mt_64 = pools.GetMiniTable64(message); const upb_MiniTable* mt_64 = pools.GetMiniTable64(message);
std::map<int, std::string> subs; std::map<int, std::string> subs;
absl::flat_hash_set<const upb_MiniTable*> seen;
// Construct map of sub messages by field number. // Construct map of sub messages by field number.
for (int i = 0; i < mt_64->UPB_PRIVATE(field_count); i++) { for (int i = 0; i < mt_64->UPB_PRIVATE(field_count); i++) {
@ -357,6 +363,15 @@ void WriteMessage(upb::MessageDefPtr message, const DefPoolPair& pools,
upb::FieldDefPtr field = message.FindFieldByNumber(f_number); upb::FieldDefPtr field = message.FindFieldByNumber(f_number);
auto pair = subs.emplace(index, GetSub(field, false)); auto pair = subs.emplace(index, GetSub(field, false));
ABSL_CHECK(pair.second); ABSL_CHECK(pair.second);
if (options.one_output_per_message && field.IsSubMessage() &&
IsCrossFile(field)) {
if (seen.insert(pools.GetMiniTable64(field.message_type())).second) {
output(
"__attribute__((weak)) const upb_MiniTable* $0 = "
"&UPB_PRIVATE(_kUpb_MiniTable_Empty);\n",
MessagePtrName(field.message_type()));
}
}
} }
} }
// Write upb_MiniTableSubInternal table for sub messages referenced from // Write upb_MiniTableSubInternal table for sub messages referenced from
@ -553,6 +568,10 @@ void WriteMiniTableSourceIncludes(upb::FileDefPtr file, Output& output) {
"// Must be last.\n" "// Must be last.\n"
"#include \"upb/port/def.inc\"\n" "#include \"upb/port/def.inc\"\n"
"\n"); "\n");
output(
"extern const struct upb_MiniTable "
"UPB_PRIVATE(_kUpb_MiniTable_Empty);\n");
} }
void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file, void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file,
@ -575,7 +594,7 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file,
} }
} else { } else {
for (auto message : messages) { for (auto message : messages) {
WriteMessage(message, pools, output); WriteMessage(message, pools, options, output);
} }
for (const auto e : enums) { for (const auto e : enums) {
WriteEnum(e, output); WriteEnum(e, output);
@ -655,7 +674,7 @@ void WriteMiniTableMultipleSources(const DefPoolPair& pools,
for (auto message : messages) { for (auto message : messages) {
Output output; Output output;
WriteMiniTableSourceIncludes(file, output); WriteMiniTableSourceIncludes(file, output);
WriteMessage(message, pools, output); WriteMessage(message, pools, options, output);
plugin->AddOutputFile(MultipleSourceFilename(file, message.full_name(), &i), plugin->AddOutputFile(MultipleSourceFilename(file, message.full_name(), &i),
output.output()); output.output());
} }

Loading…
Cancel
Save