All files / transpiler/output/codegen/generators/statements CriticalGenerator.ts

100% Statements 8/8
100% Branches 0/0
100% Functions 1/1
100% Lines 8/8

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68                                                                    13x           17x     17x       17x     17x     17x     17x             17x        
/**
 * Critical Statement Generator (ADR-053 A3)
 *
 * Generates C code for critical sections (ADR-050):
 * - Wraps block with PRIMASK save/restore for interrupt safety
 * - Ensures atomic execution of multi-variable operations
 */
import { CriticalStatementContext } from "../../../../logic/parser/grammar/CNextParser";
import IGeneratorOutput from "../IGeneratorOutput";
import TGeneratorEffect from "../TGeneratorEffect";
import IGeneratorInput from "../IGeneratorInput";
import IGeneratorState from "../IGeneratorState";
import IOrchestrator from "../IOrchestrator";
 
/**
 * Generate C code for a critical statement (ADR-050).
 *
 * Generates a PRIMASK-based interrupt disable wrapper using __cnx_ prefixed
 * wrappers to avoid macro collisions with platform headers (e.g., Teensy's imxrt.h):
 * ```c
 * {
 *     uint32_t __primask = __cnx_get_PRIMASK();
 *     __cnx_disable_irq();
 *     // ... block contents ...
 *     __cnx_set_PRIMASK(__primask);
 * }
 * ```
 *
 * @param node - The CriticalStatementContext AST node
 * @param _input - Read-only context (unused)
 * @param _state - Current generation state (unused)
 * @param orchestrator - For delegating to generateBlock and validation
 * @returns Generated code and effects (irq_wrappers)
 */
const generateCriticalStatement = (
  node: CriticalStatementContext,
  _input: IGeneratorInput,
  _state: IGeneratorState,
  orchestrator: IOrchestrator,
): IGeneratorOutput => {
  const effects: TGeneratorEffect[] = [];
 
  // Validate no early exits inside critical block
  orchestrator.validateNoEarlyExits(node.block());
 
  // Mark that we need IRQ wrapper functions (not cmsis_gcc.h include)
  // This avoids macro collisions with platform headers like Teensy's imxrt.h
  effects.push({ type: "include", header: "irq_wrappers" });
 
  // Generate the block contents
  const blockCode = orchestrator.generateBlock(node.block());
 
  // Remove outer braces from block since we're wrapping
  const innerCode = blockCode.slice(1, -1).trim();
 
  // Generate PRIMASK save/restore wrapper using __cnx_ prefixed functions
  const code = `{
    uint32_t __primask = __cnx_get_PRIMASK();
    __cnx_disable_irq();
    ${innerCode}
    __cnx_set_PRIMASK(__primask);
}`;
 
  return { code, effects };
};
 
export default generateCriticalStatement;