1111
1212#include "upb/mem/alloc.h"
1313#include "upb/mem/arena.h"
14+ #include "upb/mini_table/extension.h"
1415#include "upb/mini_table/extension_registry.h"
1516#include "upb/mini_table/internal/generated_registry.h" // IWYU pragma: keep
1617#include "upb/port/atomic.h"
2223#include <sched.h>
2324#endif // UPB_TSAN
2425
26+ const UPB_PRIVATE (upb_GeneratedExtensionListEntry ) *
27+ UPB_PRIVATE (upb_generated_extension_list ) = NULL ;
28+
2529typedef struct upb_GeneratedRegistry {
2630 UPB_ATOMIC (upb_GeneratedRegistryRef * ) ref ;
2731 UPB_ATOMIC (int32_t ) ref_count ;
@@ -32,6 +36,40 @@ static upb_GeneratedRegistry* _upb_generated_registry(void) {
3236 return & r ;
3337}
3438
39+ static bool _upb_GeneratedRegistry_AddAllLinkedExtensions (
40+ upb_ExtensionRegistry * r ) {
41+ const UPB_PRIVATE (upb_GeneratedExtensionListEntry )* entry =
42+ UPB_PRIVATE (upb_generated_extension_list );
43+ while (entry != NULL ) {
44+ // Comparing pointers to different objects is undefined behavior, so we
45+ // convert them to uintptr_t and compare their values.
46+ uintptr_t begin = (uintptr_t )entry -> start ;
47+ uintptr_t end = (uintptr_t )entry -> stop ;
48+ uintptr_t current = begin ;
49+ while (current < end ) {
50+ const upb_MiniTableExtension * ext =
51+ (const upb_MiniTableExtension * )current ;
52+ // Sentinels and padding introduced by the linker can result in zeroed
53+ // entries, so simply skip them.
54+ if (upb_MiniTableExtension_Number (ext ) == 0 ) {
55+ // MSVC introduces padding that might not be sized exactly the same as
56+ // upb_MiniTableExtension, so we can't iterate by sizeof. This is a
57+ // valid thing for any linker to do, so it's safer to just always do it.
58+ current += UPB_ALIGN_OF (upb_MiniTableExtension );
59+ continue ;
60+ }
61+
62+ if (upb_ExtensionRegistry_Add (r , ext ) !=
63+ kUpb_ExtensionRegistryStatus_Ok ) {
64+ return false;
65+ }
66+ current += sizeof (upb_MiniTableExtension );
67+ }
68+ entry = entry -> next ;
69+ }
70+ return true;
71+ }
72+
3573// Constructs a new GeneratedRegistryRef, adding all linked extensions to the
3674// registry or returning NULL on failure.
3775static upb_GeneratedRegistryRef * _upb_GeneratedRegistry_New (void ) {
@@ -47,7 +85,7 @@ static upb_GeneratedRegistryRef* _upb_GeneratedRegistry_New(void) {
4785 ref -> arena = arena ;
4886 ref -> registry = extreg ;
4987
50- if (!upb_ExtensionRegistry_AddAllLinkedExtensions (extreg )) goto err ;
88+ if (!_upb_GeneratedRegistry_AddAllLinkedExtensions (extreg )) goto err ;
5189
5290 return ref ;
5391
@@ -138,3 +176,9 @@ void upb_GeneratedRegistry_Release(const upb_GeneratedRegistryRef* r) {
138176 }
139177 }
140178}
179+
180+ const upb_ExtensionRegistry * upb_GeneratedRegistry_Get (
181+ const upb_GeneratedRegistryRef * r ) {
182+ if (r == NULL ) return NULL ;
183+ return r -> registry ;
184+ }
0 commit comments