Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

DenseMap, Symbol Table, and EDG Frontend Structures

The EDG 6.6 frontend layered on LLVM's DenseMap maintains its own declaration nodes, type nodes, and scope stack for C/C++/CUDA semantic analysis. This page documents the EDG-level structures that ride on top of the DenseMap. For the DenseMap implementation itself -- layout, hash function, probing, sentinel values, and growth policy -- see Hash Table and Collection Infrastructure.

The EDG symbol tables in this subsystem use the NVVM-layer sentinel pair (-8 / -16) and the pointer hash (ptr >> 9) ^ (ptr >> 4). See the sentinel reference table for other subsystems.


EDG Declaration Node Layout

The EDG 6.6 frontend represents every C/C++ declaration as a variable-length structure. The canonical declaration node layout was recovered from the top-level declarator parser sub_662DE0 and the declaration-specifier resolver sub_7C0F00.

Declaration Node (a_decl_node) -- 456+ bytes

OffsetSizeTypeFieldEvidence
+08Bptrdecl_id / entity pointer*v31 in sub_662DE0
+88Buint64_tdecl_flags bitfield (see below)v31[1]
+168Buint64_tdecl_extra_flagsv31[2]
+2416Bname / identifier infov31[3..4]
+408Bname string for "main" checkstrcmp target
+724Buint32_tsaved_specifier_word1v239 in sub_662DE0
+762Buint16_tsaved_specifier_word2v240
+801Buint8_tentity_kind (for scope dispatch)checked in sub_860B80
+1201Buint8_taccessibility (bits 0-6, bit 7 reserved)v241 = *(a1+120) & 0x7F
+1241Buint8_tcontext_flags_124bit 5=explicit_spec, bit 6=class_member
+1251Buint8_tcontext_flags_125bit 5=was_friend, bit 6=in_class_body, bit 7=template_decl_head
+1261Buint8_tstate_flags (see below)mask tests throughout sub_662DE0
+1271Buint8_textra_statebit 0=class_scope_pushed, bit 1=needs_deferred_parse
+1288Bptrentity_ptr / scope pointercompared early in sub_739430
+1301Buint8_tmodifier_flagsbit 5=deferred_parse, bit 6=virtual_specifier
+1311Buint8_tinline/constexpr flagbit 4
+1321Buint8_tneeds_semicolon_checkbit 1
+1401Buint8_ttype_kind (for type_def nodes)switch discriminant in sub_766570 case 6
+1608Bptrunderlying_type (for typedef)typedef unwrap chain
+1688Bptrflags_ptrbit 3 checked for fn-pointer
+1731Buint8_telaborate_kindprimary switch in sub_739430
+176varelaborate_sub_kind / secondarysub-switch in case 12
+1848Bptrparm_listv31[23] via sub_5CC190(1)
+2244Buint32_tinit_kindbit 0 = brace-init
+2564Buint32_tadditional_flags
+2681Buint8_tdecl_kind_enum0=variable, 4=function, 6=namespace
+2691Buint8_tstorage_class_kind0=none, 1=extern, 2=static
+2728Bptrdecl_typev31[34]
+2808Bptrresult_typev31[35]
+2888Bptrentity_type / return_typev31[36]
+3048Bptrtemplate_info
+3528Bptrbody_ptrv31[44]
+3608Bptrscope_or_contextv31[45]
+3688Bptrforward_decl_chainlinked list
+4168Bptrpending_listv31[52]
+4568Bptrextra_entityv31[57]

decl_flags (+8) Bit Definitions

BitMaskMeaning
00x1is_definition / linkage related
10x2has_initializer / needs init check
40x10is_typedef
50x20is_template_decl / friend declaration
60x40is_inline
70x80is_extern
140x4000structured_binding / decomposition decl

state_flags (+126) Bit Definitions

BitMaskMeaning
00x1has_saved_tokens
10x2abstract_declarator_mode
20x4has_leading_attributes
30x8no_declarator_needed (typedef etc.)
40x10suppress_error_recovery
50x20in_declarator_parsing (set on entry)
60x40in_multi_declarator_loop
70x80scope_pushed

entity_kind (+80) Dispatch Values

Used by sub_860B80 and sub_7C0F00 phase 3:

ValueEntity Kind
3class
4enum (variant A)
5enum (variant B)
6namespace
10function
11variable
16typedef
17template
19class template
22dependent name
23using-declaration
24injected-class-name

Declaration Node Allocation

sub_84DCB0 allocates 152-byte declaration entries from a free-list at qword_4D03C68, with fallback to the global allocator sub_823970(152). The full node size table at qword_4B6D500 provides per-tag sizes for all 87 IL node types; the declaration tag (6) indexes into this table for memcpy during template instantiation.


EDG Type Node Layout

Type nodes are the central representation for C/C++ types throughout the EDG frontend. Two distinct layouts exist: the IL-level type node used by the tree walker (sub_7506E0) and the semantic type node used by the type comparison engine (sub_7386E0). The type translation system (sub_91AED0) bridges between these and LLVM types.

IL-Level Type Node (from sub_7506E0 tree walker)

The IL tree walker addresses fields as a1[N] (8-byte indexed), with byte-level sub-kind tags at specific offsets:

OffsetSizeTypeFieldEvidence
-168Bptrparent_ptr / ownershared-node check path
-81Buint8_tflags_bytebit 0=shared, bit 2=visit-mark
+0..+N*8varptr[]child pointers (typed per kind)a1[0]..a1[N]
+241Buint8_texpression sub-kind (case 13)switch discriminant
+281Buint8_tscope sub-kind (case 23)18 sub-kinds
+401Buint8_tdeclaration sub-kind (case 21)25 sub-kinds
+481Buint8_ttemplate_arg sub-kind (case 30)9 sub-kinds
+1401Buint8_ttype_def_sub_kind (case 6)17 sub-kinds
+1611Buint8_ttype_def_flags
+168-177vartype sub-kind / sub-sub-kind
+1731Buint8_ttype_main_kind (case 2)14 sub-kinds by +173
+1761Buint8_ttype_sub_sub_kindcase 6 elaborated

Semantic Type Node (from sub_7386E0 comparison engine)

OffsetSizeTypeFieldEvidence
+08Bptrassociated_decl*v10 == *v14 comparison
+241Buint8_ttype_kind (0..37)primary switch discriminant
+251Buint8_tcv_qualifiersbits 0-1 = const/volatile, bit 6 = restrict
+261Buint8_ttype_flags_1bit 2 compared
+271Buint8_ttype_flags_2bit 1 compared (case 1)
+568Btype_payload / sub_kindcase 1: char at +56 = base_type_kind
+581Buint8_ttype_extra_flagscase 1: bits 0x3A compared
+648Bvaries per kindcase 30: word at +64
+728Bptrtype_child / pointercase 1 integer path
+808Bptrlinkage_chaincase 33: namespace list +80 = next

EDG-to-LLVM Type Translation Node (from sub_918E50)

The type translation system reads a third view of the type node with offsets optimized for LLVM type construction:

OffsetSizeTypeFieldEvidence
-728Bptrgrandparent_typenested lookups
-488Bptrparent_type_A
-248Bptrparent_type_B / first child
-88Bptrindirect_child_arrayif flag 0x40 at +23
+08Bptrllvm_type_descriptor*node -> LLVM type info
+88Bptrmember_chain_headlinked list of class members
+161Buint8_ttype_kindsee kind table below
+182Buint16_tqualifier_wordbits 0-14: qualifier ID, bit 15: negation
+204Buint32_tchild_countlow 28 bits masked & 0xFFFFFFF
+231Buint8_tflagsbit 6 (0x40) = indirect children
+248Btype-specific datavaries by kind
+328Bbitwidthenum/integer types
+331Buint8_tadditional_flagsbit 5 (0x20) = special treatment
+364Buint32_tsub_kind_discriminatornested types
+408Bptrscope_linkage_ptr
+488Bptrmember_list_headlinked list

type_kind Enumeration (semantic type comparison)

The full enumeration recovered from sub_7386E0:

ValueNameComparison Strategy
0tk_none / voidtrivially equal
1tk_fundamentalsub_kind + base type + class scope
2tk_pointerdelegate to sub_739430 on pointee
3tk_classscope identity, unique_id, template args
4tk_enumscope identity, unique_id
5tk_functionsub_73A280 pair compare
6tk_bitfieldwidth + base compare
7tk_member_pointermulti-field descriptor
8tk_referencereferent descriptor
10tk_arrayelement type recursion
11tk_qualifiedchild + qualifier bit
12tk_elaboratedsub_kind switch (typedef/class/enum)
13tk_pack_expansionsub_kind switch
14tk_typeof_exprsub_kind switch
15tk_decltypesub_kind switch
16tk_nullptrtrivially equal
17tk_autoidentity on entity
18tk_function_altsub_73A280
20tk_dependent_namescope identity + unique_id
22tk_unresolvedsub_8D97D0 decl compare
23tk_attributedattribute kind + child
24tk_decltype_autoidentity on entity
25tk_parenchild list compare
26tk_adjustedchild type recursion
27tk_typeof_declresolve decl -> type, recurse
30tk_complexelement type(s) recursion
32tk_template_template_paramidentity + template args
33tk_using_declchild list + base class hash table
34tk_atomicchild + qualifier bit
35tk_vlaelement type recursion
37tk_concept_constraintidentity on entity

EDG-to-LLVM Type Kind Encoding (byte at node+16)

ValueHexKind
0-160x00-0x10Primitive / scalar types
170x11Void (special)
50x05Qualified type (const/volatile/restrict)
130x0DEnum type
140x0EFunction type
260x1AArray type (subscript form)
270x1BCompound type (struct/union/class)
500x32Union variant A
510x33Union variant B
540x36Typedef / using declaration
550x37Using declaration variant
750x4BPointer type
760x4CReference type (lvalue or rvalue)
770x4DMember pointer type
780x4EDependent / nested type

Qualifier Word Values (node+18 & 0x7FFF)

ValueCUDA Memory Space
1Address space 1 (global memory)
9Address space 9 (generic, gated by sub_5F3280)
14Function / method qualifier
26Array subscript context A
27Array subscript context B
32Address space 32 (shared memory)
33Address space 33 (constant memory)

Type Canonicalization -- sub_72EC50

Before any type comparison, both sides are canonicalized by stripping non-template typedef aliases:

fn edg_canonicalize_type(type) -> type:
    while type.type_kind == 2:               // tk_elaborated
        scope = type.payload_at_56
        if scope.elaborate_kind != 12:       // not typedef_name
            break
        if scope.elaborate_sub_kind != 1:    // not single-member typedef
            break
        if scope.class_flags & 0x10:         // has template specialization
            break
        type = sub_72E9A0(type)              // unwrap one layer
    return type

This peels through chains like typedef int MyInt; typedef MyInt YourInt; down to the fundamental type. Template specialization aliases are never unwrapped.


EDG Scope Stack

The scope stack is a global array of 776-byte entries, indexed by a scope depth counter. It represents the C++ scope nesting at parse time (file scope -> namespace -> class -> function -> block).

Global State

AddressTypeNamePurpose
qword_4F04C68ptrScope stack baseheap-allocated array of 776B entries
dword_4F04C64int32_tCurrent scope indextop of the scope stack
dword_4F04C5Cint32_tPrevious scope indexsaved parent index
dword_4F04C44int32_tNamespace scope indexdeepest enclosing namespace
dword_4F04C34int32_tClass scope indexdeepest enclosing class
dword_4F04C40int32_tAnother scope indexauxiliary scope tracking
dword_4F04C3Cint32_tModule linkage flagC++20 module scope state
unk_4F04C48int32_tParent scope checkused by using-declaration handler

Scope Stack Entry Layout (776 bytes)

Each entry at qword_4F04C68[0] + 776 * index:

OffsetSizeTypeField
+04Buint32_tscope_id
+42Buint16_tscope_kind (see table below)
+61Buint8_tflags_a
+71Buint8_tflags_b
+81Buint8_tflags_c
+91Buint8_tflags_d
+101Buint8_tflags_e
+248Bptrname_list_head
+328Bptrname_list_tail
+2088Bptrclass_type_ptr
+2328Bptrdeferred_list
+3288Bptrtemplate_info
+5524Bint32_tparent_scope_index
+6248Bptrdeclaration_ptr
+6808Bfield used by sub_7C0F00
+6884Buint32_tentity_number_counter (for mangling)
+6964Buint32_tentity_number_counter_2

scope_kind Values

ValueScope Kind
5namespace
6class
7function
8block (compound statement)
9enum
12template parameter

Push / Pop Operations

sub_854590(0)   // push_scope -- increments dword_4F04C64, initializes new entry
sub_854430()    // pop_scope  -- decrements dword_4F04C64, restores parent
sub_854AB0(...) // pop_declarator_scope (context-specific cleanup)
sub_854B40()    // push_declarator_scope (declarator-specific init)

The scope depth counter at qword_4F061C8 + 64 is bumped independently for declarator nesting depth tracking. Class scope depth lives at qword_4F061C8 + 81.


Scope Chain Traversal Algorithm

The declaration-specifier resolver sub_7C0F00 performs scope chain traversal to resolve qualified names. The algorithm was recovered from Phase 4 (lines 1197-1600) of that function.

Unqualified Name Lookup

fn lookup_unqualified(name, scope_index) -> entity:
    // Phase 2 of sub_7C0F00
    // Try each lookup strategy in priority order:

    result = sub_7D5DD0(name)                    // unqualified lookup in current scope
    if result:
        return result

    result = sub_7D2AC0(name, flags)             // lookup with specific flags
    if result:
        return result

    result = sub_7ACA80(name)                    // ADL / ambiguity resolution
    return result

Qualified Name Lookup (A::B::C)

The scope iteration loop at LABEL_282/283/285/288 walks the scope chain:

fn lookup_qualified(base_entity, remaining_name) -> entity:
    current = base_entity
    while true:
        // Check if "::" follows the current entity
        if current_token != TK_SCOPE_RESOLUTION:  // token 37
            return current

        consume_token()  // sub_7B8B50

        // Classify the current entity
        kind = current.entity_kind  // byte at +80
        switch kind:
            case 6:   // namespace
                result = sub_7D4A40(current, remaining_name)  // namespace lookup
            case 3:   // class
            case 19:  // class template
                result = sub_7D2AC0(current, remaining_name, MEMBER_FLAG)
            case 17:  // template
                result = sub_830940(current, remaining_name)  // class template lookup
            default:
                result = sub_7D4600(current, remaining_name)  // generic qualified lookup

        if !result:
            // Error: member not found in scope
            sub_6851C0(error_code, context)
            return null

        current = result

        // Check member access, visibility, redeclaration
        sub_8841F0(current, scope_entry)  // access check for C++ members

Self-Recursive Qualified Resolution

When the declaration-specifier resolver encounters a :: after resolving a name, it recurses into itself at sub_7C0F00(20, a2) where flags=20 decodes as:

  • bit 2 (0x04) = nested declarator sub-parse context
  • bit 4 (0x10) = restrict parse to type-specifiers only

This handles arbitrarily deep qualified names like A::B::C::D. Recursion depth is bounded by the nesting depth of the qualified name.

Scope Chain Walking for Declaration Resolution

sub_868D90 (ADL / instantiation lookup) walks the scope chain upward:

fn walk_scope_chain(start_index) -> entity:
    index = start_index
    while index >= 0:
        entry = scope_table_base + 776 * index
        // Check if this scope contains the target declaration
        // ... name lookup within the scope's name list ...

        // Move to parent scope
        index = entry.parent_scope_index  // at offset +552

Type Comparison Engine

sub_7386E0 implements structural type comparison for the EDG frontend. It performs a parallel tree walk over two type nodes, comparing them field-by-field with mode-dependent strictness.

Calling Convention

sub_7386E0(packed_pair: __int128, flags: int) -> bool
    packed_pair.low  = type_A pointer
    packed_pair.high = type_B pointer
    flags bits:
        0-1: cv_compare_mode (0=strict, 1=relaxed, 2=overload)
        2:   template_matching_mode
        5:   anonymous_class_structural_compare

Comparison Algorithm

fn compare_types(type_A, type_B, flags) -> bool:
    // 1. Null handling
    if both null: return true
    if either null: return false

    // 2. Canonicalize (strip non-template typedefs)
    type_A = sub_72EC50(type_A)
    type_B = sub_72EC50(type_B)

    // 3. Quick-reject on header bytes
    if type_A.type_kind != type_B.type_kind: return false
    if (type_A.cv_quals ^ type_B.cv_quals) & 0x43: return false  // const/volatile/restrict
    if (type_A.flags_1 ^ type_B.flags_1) & 0x04: return false

    // 4. Type-specific structural comparison
    switch type_A.type_kind:
        case 3 (class):
            if type_A.scope == type_B.scope: return true     // identity shortcut
            if unique_id_enabled:
                if scope_A.unique_id == scope_B.unique_id: return true
            if template_mode:
                return sub_89BAF0(...)  // template arg list compare
            if anonymous_mode && both_anonymous:
                return sub_739430(member_list_A, member_list_B)

        case 7 (member_pointer):
            // Compare: flags, class ptr, scope ptr, return type,
            // params, exception spec -- 6 sub-comparisons

        case 33 (using_decl) in overload mode:
            // Hash table lookup at qword_4D03BF8 for base class lists
            // Element-by-element comparison of 24-byte triples

        // ... 35 other cases ...

    // 5. Post-switch: declaration pointer compare
    if type_A.decl != type_B.decl:
        if !sub_8D97D0(type_A.decl, type_B.decl): return false
    return true

Helper Functions

AddressNamePurpose
sub_7386E0edg_compare_type_nodesTop-level structural compare
sub_739370edg_compare_type_listsLinked-list comparator (next at +16)
sub_739430edg_compare_decl_typesDeclaration-level comparator (661 lines)
sub_73A280edg_compare_type_pair_trivTrivial wrapper: null=equal
sub_72EC50edg_canonicalize_typeStrip typedef / elaborated aliases
sub_8D97D0edg_compare_decl_identityName/entity identity comparison
sub_8C7520edg_class_same_templateSame primary class template check
sub_89AB40edg_compare_template_argsTemplate argument list comparison
sub_89BAF0edg_compare_template_arg_lists_fullFull template context compare

Key Global: dword_4F07588 -- unique_id optimization

When set, enables O(1) identity comparison via the unique_id field at scope+32. This avoids recursive structural comparison for named classes and enums. The field is compared as a non-null integer; matching non-null values prove the two types refer to the same entity.


IL Tree Walker and Copier

Tree Walker -- sub_7506E0 (190KB, 7283 lines)

The generic IL tree walker visits every node in the EDG intermediate representation. It dispatches on 83 node kinds (1-86 with gaps at 24-26) using a massive switch statement.

Callback table at .bss 0x4F08014..0x4F08040:

AddressTypeCallbackCall Sites
dword_4F08014boolskip_shared_nodesflag
dword_4F08018boolclear_back_pointers49 sites
qword_4F08020fn(node, kind) -> nodelist_node_rewrite_fn206 sites
qword_4F08028fn(node, kind) -> nodechild_rewrite_fn926 sites
qword_4F08030fn(node, kind) -> boolpre_visit_fn2 sites
qword_4F08038fn(str, kind, len)string_visitor_fn80 sites
qword_4F08040fn(node, kind)post_visit_fn14 sites

Visit-mark protocol: Each node has a flag byte at node[-8]. Bit 2 tracks "visited in current pass" with polarity toggled per walk pass via dword_4D03B64. This avoids clearing visited marks between walks.

Linked-list traversal pattern (60+ lists walked):

for cursor = node.field; cursor; cursor = cursor.next:
    if list_node_rewrite_fn:
        cursor = list_node_rewrite_fn(cursor, child_kind)
    if cursor:
        walk_il_node(cursor, child_kind)
        cursor = node.field  // re-read (rewrite may have changed it)

Next-pointer stride varies by node kind: +0, +16, +24, +32, +56, +112, +120 bytes.

Tree Copier -- sub_766570 (148KB, 5187 lines)

The copier is driven by template instantiation (sub_8C5CD0 -> sub_8C4EC0 -> sub_8C2C50 -> sub_766570). It uses the walker's callback infrastructure:

  • sub_8C38E0 = copy_ref callback: resolves pending copy destinations
  • sub_8C3810 = copy_scope callback: resolves scope-level copies
  • Node sizes from qword_4B6D500[tag] (87+ entries, one per IL node type)

Copy protocol using flag bits at node[-8]:

BitsMeaning
0x1needs copy, not yet started
0x2copy in progress
0x3pending copy (both bits)
0x4copy destination allocated

Copy destination stored at *(node - 24). When both bits 0 and 1 are set, sub_8C3650 forces the copy by allocating qword_4B6D500[tag] bytes and performing memcpy followed by pointer rewriting.


EDG-to-LLVM Type Translation System

Entry: sub_91AED0 -> sub_91AB30. Uses a worklist-driven fixed-point iteration.

Translation Context Object (at a1+160)

OffsetSizeField
+0x0008Bdebug_logger
+0x0088Bpass_list_ptr
+0x0388Bedg_node_map (DenseMap: EDG -> LLVM values)
+0x0588Bvisited_set (DenseSet for dedup)
+0x0604Bvisited_count
+0x0644Bvisited_capacity
+0x0684Bbucket_count
+0x0908Btype_cache (DenseMap: EDG type -> LLVM Type*)
+0x1684Bthreshold
+0x2A08Bpending_replacements
+0x2A84Bpending_count

Fixed-Point Algorithm

fn translate_all_types(ctx, module):
    // Phase 1: iterate module members
    for member in module.member_list:
        sub_AA3700(member)  // gather initial flags

    // Phase 2: fixed-point iteration
    do:
        ordering = sub_919CD0(module)        // topological sort (10-level BFS)
        for type in ordering.reverse():
            sub_913880(ctx, type)            // invalidate stale cache entries
        for type in ordering.reverse():
            changed |= sub_9197C0(ctx, type) // process single declaration
    while changed

    // Phase 3: optional late fixup (byte_3C35480-gated)
    if optimization_enabled:
        do:
            changed = sub_917E30(ctx)
        while changed

    // Phase 4: cleanup
    sub_909590(ctx)

Bitmask for Scope-Tracking Types

The expression 0x100000100003FF >> (kind - 25) selects which type kinds in the range [25..78] require scope tracking during translation. This covers compound types, pointer types, and dependent types that carry CUDA address-space qualifiers.


Usage Across the Compiler

DenseMap instances appear at these known locations:

  • NVVM context object: 8+ tables for IR node uniquing (opcodes 0x10..0x1F), plus sub-function tables for opcodes 0x04..0x15.
  • SelectionDAG builder context: Map A (+120), Map B (+152), Set C (+184) for node deduplication and worklist.
  • Per-node analysis: embedded DenseSet at +72 inside analysis structures created during DAG construction.
  • Instruction constraint table: the global word_3F3E6C0 array is a flat table rather than a DenseMap, but the constraint emission functions use DenseMaps for lookup caching.
  • EDG type translation: 5 distinct caches -- visited set, type cache, type-value map, scope table, and type index table.
  • Base class comparison: qword_4D03BF8 hash table for overload-resolution base class triple lookup.

The consistency of the hash function, sentinel values, and growth policy across all instances is documented in Hash Table and Collection Infrastructure.

Cross-References

Function Map

FunctionAddressSizeRole
edg_parse_declaratorsub_662DE0--Top-level declarator parser
edg_parse_decl_specifiers_coresub_672A20--While/switch token dispatcher
edg_resolve_decl_specifierssub_7C0F00--Scope chain + qualified name resolver
edg_compare_type_nodessub_7386E0--Structural type tree comparison
edg_compare_type_listssub_739370--Linked-list type comparator
edg_compare_decl_typessub_739430--Declaration-level type comparator
edg_canonicalize_typesub_72EC50--Typedef / elaborated alias stripper
edg_type_to_stringsub_74A390--Type-to-string for diagnostics
edg_walk_il_nodesub_7506E0--190KB IL tree walker (297 recursive calls)
edg_copy_il_nodesub_766570--148KB IL tree copier
edg_push_scopesub_854590--Push scope stack entry
edg_pop_scopesub_854430--Pop scope stack entry
edg_emit_scope_chainsub_82BDA0--Scope chain emission
edg_unqualified_lookupsub_7D5DD0--Unqualified name lookup
edg_qualified_lookupsub_7D4600--Qualified name lookup (after ::)
edg_lookup_with_flagssub_7D2AC0--Lookup with specific mode flags
edg_namespace_lookupsub_7D4A40--Lookup in namespace scope
edg_compare_decl_identitysub_8D97D0--Entity identity comparison
edg_type_translation_entrysub_91AED0--Top-level EDG-to-LLVM type translation
edg_type_translation_driversub_91AB30--Fixed-point iteration driver
edg_type_kind_dispatchsub_918E50--Type-kind dispatch for translation
edg_type_pair_comparesub_911D10--Core type-pair comparison + replacement
edg_alloc_decl_nodesub_84DCB0--152-byte declaration node allocator