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

Cross-Language Wire-Key Consistency & the *Gen Base Classes

All symbols and addresses on this page apply to neuronx_cc 2.24.5133.0+58f8de22, cp310. The C++ side is libBIR.so (md5 12bb979f7ca41248252abb0f16b2da98, 9.5 MB, .symtab stripped, 9 572 dynamic symbols); the Python side is the Cython *.so modules under neuronxcc/. Every address is version-pinned; other wheels differ.

Abstract

The neuronx-cc IR exists in two languages at once. The Python front-end (penguin / birpy) emits BIR; the C++ back-end (libwalrus.solibBIR.so) consumes it. For an XLA HLO program to compile, the JSON a Python InstActivation.toJson produces must parse 1:1 into the C++ bir::InstActivation::readFieldsFromJson and re-emit byte-stable. There is no hand-written serializer on either side to keep in sync — instead a single generator (neuronxcc/instabrew/brewer.py) reads one ISA datamodel spec and projects it into both a Python class and a C++ bir::Inst* class, so the wire-key set, field order, and enum spelling are structurally identical. This page proves that parity at the byte level for two ops (InstActivation, 11 keys; InstMatmultBase, 13 keys), pins the C++↔Python *Gen class parallel, maps the toJson/createFromJson factory path against the Python static factories, and reconciles the five different "instruction count" denominators (121 vs 113 vs 112 vs 110 vs 105) that sibling pages report — they count different things, and conflating them is a real correctness hazard for anyone re-deriving the class roster.

This is the cross-language counterpart to the single-spec → *OpGen Python contract and the 110-opcode InstructionType enum. Read those first if you have not: this page assumes you know the bir::Instruction base struct and the opcode taxonomy.

C++ producer of bir::Inst*libBIR.so (defines every bir::Inst* class)
C++ consumerlibwalrus.so (64 MB; imports bir::Inst* as undefined U)
Python BIR wire layerneuronxcc/starfish/birpy/InstructionOpcodes.cpython-310-*.so
Python front-end op…/penguin/targets/generated/{Activation,ActivationOpGen,MatMulOpGen}.so
Shared generatorneuronxcc/instabrew/brewer.py (provenance string only; not shipped)
Shared specneuronxcc/include/isa/activate2_info.cpython-310-*.so
JSON librarynlohmann::json_abi_v3_11_3 (ordered_map, so key insertion order is stable)

1. One generator, two languages

The decisive artifact is a build-path provenance string that appears, byte-identical, in both language back-ends. In libBIR.so:

/opt/workspace/KaenaCompilerNativeBuild-310/build/private/src-3.10.16/
    neuronxcc/instabrew/brewer.py

(strings -n6 libBIR.so — one occurrence; the same string is also present in libwalrus.so and libBIRSimulator.so.) In the C++ libraries this path is the __FILE__ argument of generated assert() macros: the string lives in .rodata and is loaded into RSI immediately before call __assert_fail@plt (the glibc ABI is __assert_fail(expr, FILE, line, func), so RSI = __FILE__). The companion func-name arguments at those call sites are generated per-op bodies such as bool bir::InstNKIKLIRKernel::sameInst(bir::Instruction*) and bool bir::InstCall::sameInst(bir::Instruction*), with the brewer default 'false && "Not Implemented"' / 'Unknown opcode' fall-throughs. The translation unit that holds those bodies was therefore emitted by brewer.py.

On the Python side, the same generator file is recorded as the provenance of the generated *OpGen modules — ActivationOpGen.so carries the literal string "Generated by brewer … neuronxcc/instabrew/brewer.py at line 3384" (detail). One brewer.py, two outputs. The generator body itself is not shipped in the wheel, so its template text is [INFERRED]; what survives is the provenance string and the uniform shape of its two outputs.

The consequence is that the Python emitter and the C++ consumer are two projections of one spec, not two hand-written implementations. The classic two-implementation drift bugs — a field added on one side only, an enum spelled differently, key-name or field-order skew, a dtype-tag mismatch — are structurally impossible because both sides regenerate from the same param list, the same enum 2string tables, and the same template.


2. The bir::Inst* class family and the 121 / 113 / 112 / 110 / 105 reconciliation

This is the single most error-prone fact on the page, because sibling passes report five different "instruction class counts" and they are five different denominators. They are all correct; they count different sets. Treating any one as "the leaf count" is wrong. Every number below is re-grounded against nm/readelf on the pinned libBIR.so.

FigureWhat it actually countsHow to reproduceConfidence
121Distinct bir::Inst* name tokens across all demangled dynamic symbols (methods + RTTI), incl. non-IR-node helpersnm -DC libBIR.so | rg -o 'bir::(Inst[A-Za-z0-9_]+)' | sort -u | wc -l → 121CERTAIN (number); HIGH (denotation)
113bir::*Inst* typeinfo-name hits from a loose Inst-substring grep — includes template names (NamedObject<…Instruction…>, BasicBlock)nm -D | rg ' _ZTSN3bir' | rg Inst | c++filt | sort -u | wc -l → 113CERTAIN
112Distinct bir::Inst* polymorphic classes with a full RTTI triplet (_ZTS/_ZTI/_ZTV), strict mangling regexnm -D | rg -o '_ZTSN3bir[0-9]+Inst[A-Za-z0-9_]+E' | sort -u | wc -l → 112 (same for _ZTI, _ZTV)CERTAIN
110InstructionType opcode enum members {0..109} — one per opcodeinstruction-type.md; InstructionType2string tableCERTAIN
105 / 106Concrete leaves with a distinct getValidEngines engine map (105 maps / 106 overrides)getValidEngines vtable slot vt+0x60, static init at sub_1D71A0CERTAIN

Why 121 > 112. The naive bir::Inst* regex over nm -DC over-counts the RTTI/typeinfo population by nine name tokens that are not IR-node classes at all:

InstructionType   InstructionType2string          # the opcode ENUM + its to-string
InstSyncType      InstSyncType2string             # the sync-type ENUM + to-string
InstructionArgumentType   InstructionArgumentType2string   # arg-kind ENUM + to-string
InstArg            # a by-value builder argument struct, not an IR node
InstBuilder        # bir::InstBuilder — the imperative IR-construction helper
InstProfiler       # bir::InstProfiler — a counting/limit helper (getTotalCount, instCountFitsLimit)

bir::InstProfiler, bir::InstBuilder, and bir::InstArg carry method symbols (e.g. bir::InstProfiler::getTotalCount() @ 0x4a6480, bir::InstBuilder::addMatmult @ 0x2b46c0) but have no _ZTS typeinfo — they are not polymorphic IR instructions. The three *Type tokens are enums; their 2string helpers (bir::InstructionType2string @ 0x2d5bf0, bir::InstSyncType2string @ 0x2d63c0, bir::InstructionArgumentType2string @ 0x2e4a80) are free functions. So 121 = the symbol-name token count, ~9 of which are not bir::Inst<Op> IR classes. State it exactly that way; do not call 121 "the number of instruction classes."

Why 113 vs 112. The loose substring grep additionally catches template/aggregate names whose mangling mentions Instruction (bir::NamedObject<bir::Instruction, …>, bir::BasicBlock's Instruction-parameterised members). The strict _ZTSN3bir[0-9]+Inst…E regex collapses to 112 distinct polymorphic bir::Inst* classes, each with all three RTTI symbols.

What the 112 RTTI classes are. They decompose (cross-checked against the InstructionType table and the inheritance graph) as:

  112 RTTI classes
   =   1   root bir::Instruction
   +   1   bir::InstructionBasicBlockHolder   (a container node, not an opcode leaf)
   +   6   abstract intermediate bases  (InstGeneric, InstMatmultBase, InstDMA,
   |                                      InstCollective, InstDMADescriptor, InstTerminator)
   + 104   concrete opcode leaves        (of the 110 opcodes: the 6 abstract bases
                                          above ARE 6 of the 110 IT slots and never
                                          materialise as leaves)

So 110 opcodes − 6 abstract-base ITs = 104 concrete leaves, and 104 leaves + 6 bases + the root + the BB-holder = 112 RTTI classes. The getValidEngines evidence (105 concrete engine maps) is the independent corroboration that there are ~104–105 concrete leaves and no hidden polymorphic intermediate bases beyond the six (each opcode owns exactly one engine map; there is no extra map for a phantom base).

GOTCHA — the counts are NOT interchangeable. 121 (symbol-name tokens, ~9 of them non-IR), 113 (loose typeinfo grep, includes templates), 112 (strict RTTI triplet — the true polymorphic class population), 110 (opcodes), 104–105 (concrete leaves), and the ~401 figure sometimes quoted (RTTI triplet × classes plus template/Hwm::getLatency overload name-hits — ~117 × 3 + ~50, not 401 classes) are six views of the same ~112-class population through six lenses. Quoting "121 bir::Inst* classes" is fine only if you name the lens. For the polymorphic-class population use 112; for opcodes 110; for concrete leaves with engine maps ~104–105.

The uniform generated member skeleton

Every bir::Inst* exhibits the same brewer-emitted shape (taken from bir::InstActivation, nm -DC). The headings name the Python counterpart from the *OpGen contract:

ctor / dtor                 InstActivation(std::string const&, bir::BasicBlock*) / ~…
field accessors (=props)    getIfmap()/const  getDst()/const  getBiases()/const
                            getSummation()/hasSummation()  getIfmapOffsets()…ValidDtypes()…
spec-flag eval helpers      get<Flag>EvalIfNeeded(DenseMap&) const   (one per bool/derived field)
wire format (= .toJson/.fromJson)
                            toJson(json&) const                       SERIALIZE
                            readFieldsFromJson(InstActivation&, json const&)   DESERIALIZE
                            createFromJson(std::string const&, BasicBlock*, json const&)  FACTORY
IR plumbing (= NeuronInst)  clone()  sameInst()  evalFieldsInto()  updateAffineExprs()  isSymbolic()
perf model (= spec perf_est)getLatency()/getLatencyExec()/getLatencyReadInit()/getLatencyWriteDrain()
engine binding (= spec)     getDefaultEngine() const   getValidEngines() const   validEngines
RTTI                        _ZTV / _ZTI / _ZTS  (polymorphic triplet)

There is no separate <Op>Gen C++ symbol the way Python ships a distinct *OpGen.so. The C++ generator folds generated base + behaviour into one bir::Inst<Op> class (with an Inst<Op>Base : Instruction / Inst<Op> : Inst<Op>Base split only where a shared base is genuinely needed, e.g. matmul). The Python two-module split (<Op>OpGen + <Op>) is a Cython packaging choice; the C++ side is one translation unit.

The Python name-for-name mirror

birpy/InstructionOpcodes.so defines Python classes named exactly Inst<Name> — a subset of the C++ catalog (the front-end-emittable op set), with byte-identical class names. A token sweep of its Cython string pool (strings | rg '^Inst[A-Z]…') surfaces InstActivation, InstMatmult, InstMatmultMx, InstMatmultSparse, InstAbstractCopy, InstCollectiveCompute/Recv/Send, InstCopyPredicated, InstCustomOp, InstDMA(Copy), InstDropout, InstIota, InstGather, InstCall, … The C++ catalog is the superset: it adds back-end-only ops the front-end never emits directly (InstDMADescriptor*, InstTensorScalarCache, InstSwitchQueueInstance, …). The producer/consumer split is reloc-clean: libwalrus.so references bir::InstActivation::getIfmap(), …::getDst…, and the ctor as undefined imports (nm -DC libwalrus.so shows U bir::InstActivation::…), i.e. libBIR.so defines, libwalrus.so consumes.


3. InstActivation: 11 wire keys, byte-identical across languages

The C++ serializer is bir::InstActivation::toJson @ 0x435450; the parser is readFieldsFromJson @ 0x417f00; the factory is createFromJson @ 0x425b10. (All three addresses come from nm -DC; ABI json_abi_v3_11_3.)

Disassembling toJson (objdump -d -M intel, RIP-relative lea rsi,[rip+…] targets resolved against the .rodata map — .rodata VMA 0x7080000x7a118c is file-offset-equal) lands the key-name lea loads at these .rodata strings (the pool concatenates interned tokens; each key is the prefix up to the next token):

.rodata addrstring at addrwire key
0x70a6f1funcremote_writer_funcfunc
0x70c22fop0compare_op1…op0
0x70c23bop1fill_value…op1
0x70c156reverse0const1…reverse0
0x70c166reverse1is_64bit…reverse1
0x70c1a7reduce_opis_tensor…reduce_op
0x70b38ascaleFloorDivKind…scale
0x70c196accis_activate2…acc
0x70a0ffalphablankcntrl…alpha
0x70c19ais_activate2reduce_op…is_activate2
0x70c0ffcan_read_uninitis_reset…can_read_uninit

readFieldsFromJson @ 0x417f00 loads the same eleven .rodata addresses (verified by the same disassembly+resolve method): func@0x70a6f1, scale@0x70b38a, reduce_op@0x70c1a7, reverse1@0x70c166, reverse0@0x70c156, op1@0x70c23b, op0@0x70c22f, is_activate2@0x70c19a, acc@0x70c196, can_read_uninit@0x70c0ff, alpha@0x70a0ff. The emit side and the parse side reference the identical literal addresses — that is a direct, address-level proof that the C++ JSON round-trip is symmetric and lossless: toJson key-set ≡ readFieldsFromJson key-set.

The Python side carries 10 of the 11 keys verbatim. strings birpy/InstructionOpcodes.so | rg -x '<key>' returns exactly: func, op0, op1, reverse0, reverse1, reduce_op, scale, acc, alpha, is_activate2present, exact, 10/11. can_read_uninit is absent as a plain interned key (rg -c '^can_read_uninit$' → 0); it is carried via the eval-flag / set-prefixed-setter path, not a standalone interned name. The Python InstActivation class also exports .toJson, .fromJson, and .setAcc (the setter for the acc wire key).

These 11 keys are the brewer projection of the shared activate2_info ISA spec (the s2d2_ac_struct Activate2 entry). The mapping spec-param → wire-key:

  wire key          spec param / concept (activate2_info)
  ----------        -------------------------------------------------------------
  func           <- activation_func   (ActivationFunctionType)
  op0 / op1      <- op0 / op1          (AluOpType tensor-scalar ops)
  reverse0/1     <- reverse0/reverse1  ("reverse operand order for first/second op")
  reduce_op      <- reduce_op          (AluOpType reduction)
  alpha          <- relu_param         ("scalar/vector for Parametric ReLU")
  scale          <- the (Mult,Add) scale&bias tensor-scalar combo
  acc            <- accumulation / read-accumulator flag
  is_activate2   <- activate2 variant discriminator
  can_read_uninit<- uninitialised-read permission flag

THREE LAYERS, ONE SPEC. Do not confuse the penguin L1 op (ActivationOpGen, fields tensor/bias/scale/dtype/scale_ptr — the pre-lowering high-level op, different key vocabulary) with the wire layers that must byte-agree: L2 = Python birpy InstActivation.toJson/fromJson (these 11 keys) and L3 = C++ bir::InstActivation::toJson/readFieldsFromJson (these 11 keys). L1 lowers into L2/L3 at BirCodeGenLoop; L2 and L3 are the cross-language pair that exchanges the same on-disk BIR JSON, and they DO agree.


4. InstMatmult: the two-layer base + 13 wire keys

Matmul shows the C++ two-layer split byte-for-byte. From readelf -rW libBIR.so (the __si_class_type_info base-pointer reloc at typeinfo+0x10):

typeinfo bir::InstActivation   @0x900400 → base reloc @0x900410 → _ZTIN3bir11InstructionE     (0x8fcd78)
typeinfo bir::InstMatmultBase  @0x900448 → base reloc @0x900458 → _ZTIN3bir11InstructionE     (0x8fcd78)
typeinfo bir::InstMatmult      @0x8fd9a8 → base reloc @0x8fd9b8 → _ZTIN3bir15InstMatmultBaseE (0x900448)

So InstActivation : bir::Instruction, InstMatmultBase : bir::Instruction, and InstMatmult : InstMatmultBase — proven from relocations, not naming. This is the exact C++ image of the Python two-layer split (MatMul : MatMulOpBase : NeuronInst): the generated base owns the spec fields + serialize, the subclass/Base split mirrors the brewer base-vs-public emission, and bir::Instruction is the NeuronInst plumbing root.

The scalar wire keys live on the base. bir::InstMatmultBase::toJson @ 0x4358b0 emits 13 keys; readFieldsFromJson @ 0x41f600 reads the same 13. Resolving the toJson .rodata lea targets directly:

0x70c2cd accumulation_flag       0x70c2df psum_zero_region        0x70c2f0 replication_resolution
0x70c307 replication_shift_amnt  0x70c31e replication_num_rows    0x70c333 is_transpose
0x70c340 is_fmap_onezero         0x70c350 is_weight_onezero       0x70c362 tile_size
0x70c36c tile_position           0x70c37a perf_mode               0x70c384 ifmap_quant_offset
0x70c397 weights_quant_offset

InstMatmult::toJson @ 0x435e00 (the leaf) adds 0 scalar keys: its data fields (ifmap/weights/dst) serialize as operands via the base Instruction operand list, not as JSON scalars — the getIfmap/getWeights/getDst accessors index the operand list. The InstMatmult::readFieldsFromJson @ 0x420720 tail-jumps into the base body.

The Python side carries all 13 keys verbatim. strings birpy/InstructionOpcodes.so | rg -x '<key>' returns all of accumulation_flag, psum_zero_region, replication_resolution, replication_shift_amnt, replication_num_rows, is_transpose, is_fmap_onezero, is_weight_onezero, tile_size, tile_position, ifmap_quant_offset, weights_quant_offset, perf_mode13/13 EXACT. birpy also carries the set-prefixed setter setaccumulation_flag and the EngineAccumulationType enum used for accumulation_flag, matching C++ getAccumulationFlag + bir::EngineAccumulationType.


5. Enum wire vocabulary: strings, not integers

The brewer spec declares each field's enum domain (EnumSchema(enum_class)). That one enum becomes both a C++ bir::<Enum> (with <Enum>2string / string2<Enum> / to_json / from_json) and a Python enum. Critically, enums serialize by string name, not integer — so the spellings must agree across languages. The C++ JSON enum serializers each call <Enum>2string then build a JSON string node (bir::to_json(json&, ActivationFunctionType const&) @ 0x41b8d0 calls ActivationFunctionType2string; adl_serializer<bir::Dtype>::to_json @ 0x484cc0 calls Dtype2string); the inverse from_json calls string2<Enum> (bir::string2Dtype @ 0x265fb0, string2AluOpType @ 0x40db60, …). The Python emitter must therefore produce the identical spelling for the round-trip to parse.

EnumC++ 2string @membersPython home
bir::Dtype0x2641e020, ordinals 0..19 (see Dtype tables)penguin.dtypesimported by birpy/InstructionOpcodes.so (neuronxcc.starfish.penguin.dtypes in its import table)
bir::AluOpType0x40060033birpy (24/33 verbatim) + penguin Opcodes.ALUOpcode
bir::ActivationFunctionType0x4002a030birpy + penguin Opcodes
bir::ReduceCmdType0x402480Idle/Reduce/Reset/ResetReducebirpy
bir::EngineAccumulationType0x400990Idle/Zero/Accumulate/AddAccumulate/LoadAccumulate/ZeroAccumulatebirpy (accumulation_flag enum)

penguin.dtypes additionally exposes numpy-style aliases (float8_e4m3, float8_e5m2) for the front-end L1; the L2/L3 canonical wire spelling (float8e3/e4/e5, *_fn) is what Dtype2string emits, mapped at the lowering boundary. Same enum, one ordinal table, byte-verified on the C++ side and imported by the Python BIR layer (Dtype master table).


6. The factory path: createFromJson vtable-slot ↔ Python static factory

Construction cannot be virtual-dispatched (you have no object yet), so neither language uses a vtable slot for the factory — both use a static, opcode-keyed factory that news the concrete node, then calls the per-leaf field reader. The C++ cascade, read from the disassembly of bir::InstActivation::createFromJson @ 0x425b10, whose call targets are insertElement<InstActivation> then readFieldsFromJson:

walrus loads a module at the Function level — libwalrus imports exactly 4 createFromJson:
    bir::Function::createFromJson              (+ Function::createFromJsonPass2 — two-pass)
    bir::MemoryLocationSet::createFromJson
    bir::Register::createFromJson
        │
        ▼  (versioned top-level dispatch — the wire format is versioned)
  fromJsonv1 @0x3bbe90 / fromJsonv2 @0x3bc8c0  (v2 string-compares op/version tags, routes)
        │
        ▼  (per-BB, two pass)
  bir::Function::createFromJson → BasicBlock::createFromJson (+ …Pass2)
        │
        ▼  (per-op static factory, opcode-keyed)
  bir::Inst<Op>::createFromJson(name, BB, json):
      InstActivation& a = container.insertElement<InstActivation>(it, name);  // news the node in the BB
      InstActivation::readFieldsFromJson(a, json);                            // parses the 11 keys
      return a;

The Python parallel is the same shape on the emit side: birpy InstActivation exports the static methods .toJson (emit) / .fromJson (parse), keyed by op name, with no virtual dispatch — .toJson builds the dict, .fromJson is the static reconstructor. The annotated correspondence:

  C++ (libBIR)                                    Python (birpy)
  --------------------------------------------    -------------------------------------------
  toJson(json&) const            [vtable slot]    InstActivation.toJson()        [static-ish]
  readFieldsFromJson(self, json) [non-virtual]    (folded into) InstActivation.fromJson()
  createFromJson(name, BB, json) [STATIC factory] InstActivation.fromJson(...)   [static factory]
  enum field  → <Enum>2string / string2<Enum>     enum field  → same name string  (penguin.dtypes)

Two virtuals are per-leaf vtable slots and matter to this story: toJson (so a bir::Inst* polymorphically serialises itself) and getValidEngines (reloc-proven at vt+0x60; bir::InstActivation::getValidEngines is the weak inline stub @ 0x43ef50). But createFromJson/readFieldsFromJson are deliberately static, and sameInst/verify/the visitor accept are opcode-switch on Instruction+0x58, not vtable slots (see the vtable-layout analysis). The bottom line for cross-language parity: serialization is virtual (polymorphic emit), reconstruction is a static op-name-keyed factory, and both sides key on the same op-name strings and the same field-key strings, so a Python-emitted node and a C++-reconstructed node cannot disagree on which keys to write or read.


7. Round-trip safety guarantee

Because both sides are projections of one brewer.py spec, the field set, field-order intent, enum string domain, and wire keys are identical, so:

  • Python birpy InstActivation.toJson(...) produces {func, op0, op1, reverse0, reverse1, reduce_op, scale, acc, alpha, is_activate2, …} with enum values spelled per the shared 2string domain.
  • C++ bir::InstActivation::createFromJson → readFieldsFromJson consumes exactly those keys (the address-level proof of §3) and parses each enum via string2<Enum> over the same domain.

No key is dropped, renamed, or numerically mis-encoded across the boundary. A BIR emitted by Python parses losslessly in C++ and re-emits byte-stable (toJson key-set ≡ readFieldsFromJson key-set, proven for Activation = 11 and Matmult = 13). The nlohmann::json_abi_v3_11_3 config uses ordered_map, so key insertion order is preserved on the wire — the brewer template's per-field emit order is itself part of the contract. This is the round-trip safety that single-spec generation guarantees: the spec is the one source of truth; both languages are projections of it; the IR (Python-emitted) and BIR (C++-consumed) cannot disagree on field encoding. The guarantee is byte-proven for Activation and Matmult; extending it to the rest of the family rests on the shared generator rather than on a per-op check.


8. Evidence Anchors and Limits

Read byte-exact from libBIR.so / libwalrus.so / birpy: the 121/113/112/110/104-105 count decomposition, with all nine non-IR tokens enumerated by nm; the InstActivation 11 wire keys, resolved to identical .rodata addresses on both toJson (0x435450) and readFieldsFromJson (0x417f00); the InstMatmultBase 13 wire keys (toJson 0x4358b0); the __si_class_type_info base relocations placing InstActivation and InstMatmultBase under Instruction and InstMatmult under InstMatmultBase; the brewer.py provenance string in all three C++ libraries; the producer/consumer U-import split; the four container createFromJson imports plus the fromJsonv1/v2 dispatchers; and on the Python side the birpy class names, 10-of-11 and 13-of-13 key coverage, the penguin.dtypes import, and toJson/fromJson/setAcc.

Resting on one anchor plus corroboration: that the 112-class population hides no polymorphic intermediate base beyond the six — this leans on the 105-engine-map count rather than on reading every _ZTI base pointer; the L1/L2/L3 three-layer model; and the generalisation of round-trip safety from the two proven ops to the whole family.

[INFERRED] or open: the exact brewer.py C++ template text, since the generator .py is not in the wheel and only its uniform output and provenance survive; the exact L1→L3 dtype-name remap site inside BirCodeGenLoop; and the precise per-field statement bodies of toJson/readFieldsFromJson, which are heavily inlined nlohmann template instantiations — only the key-string literals and the enum 2string calls survive as recoverable evidence. The Python .fromJson internal folding is likewise inlined by Cython, so the call chain is pinned but its interior is not.


Cross-references