pub fn compile_inner(&mut self, root_block: DslIrBlock<C>) -> RootProgram<C::F> {
        // Prefix an empty basic block to be later filled in by constants.
        let mut program = tracing::debug_span!("compile raw program").in_scope(|| {
            self.compile_raw_program(root_block, vec![SeqBlock::Basic(BasicBlock::default())])
        });
        let total_memory = self.addr_to_mult.len() + self.consts.len();
        tracing::debug_span!("backfill mult").in_scope(|| self.backfill_all(program.iter_mut()));

        // Put in the constants.
        tracing::debug_span!("prepend constants").in_scope(|| {
            let Some(SeqBlock::Basic(BasicBlock { instrs: instrs_consts })) =
                program.seq_blocks.first_mut()
            else {
                unreachable!()
            };
            instrs_consts.extend(self.consts.drain().sorted_by_key(|x| x.1 .0 .0).map(
                |(imm, (addr, mult))| {
                    Instruction::Mem(MemInstr {
                        addrs: MemIo { inner: addr },
                        vals: MemIo { inner: imm.as_block() },
                        mult,
                        kind: MemAccessKind::Write,
                    })
                },
            ));
        });

        RootProgram { inner: program, total_memory, shape: None }
    }
Compile a root `DslIrBlock` that has not necessarily been validated.

Returns a program that may be ill-formed.
crates/recursion/compiler/src/circuit/compiler.rs