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 69 70 71 72 73 74 75 | 47x 19x 19x | /**
* Critical Statement Generator
*
* 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 IGeneratorOutput from "../IGeneratorOutput";
import InterruptMask from "../../helpers/InterruptMask";
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);
* }
* ```
*
* #1445 box 3: takes the two things it read off the node -- the block's
* already-rendered code, and the line the `critical` keyword sits on -- rather
* than the node itself. The delegation inverts: the caller renders the block,
* this wraps it.
*
* `blockCode` MUST be a brace-delimited block, because the wrapper strips the
* outer braces before re-wrapping. That is an invariant the type cannot state,
* so it is stated here.
*
* Effect ordering is unchanged. The `irq_wrappers` effect is pushed onto this
* function's local array and only APPLIED by the caller on return, so whether
* the block renders before or during this call, the block's own effects still
* land first.
*
* @param critical - The rendered block and the source line of the construct
* @param _input - Read-only context (unused)
* @param _state - Current generation state (unused)
* @param _orchestrator - Unused; the block arrives rendered
* @returns Generated code and effects (irq_wrappers)
*/
interface ICriticalStatement {
/** The block's generated C, braces included. */
readonly blockCode: string;
/** Source line of the `critical` construct, for the #1143 deferred emitter. */
readonly line: number | undefined;
}
const generateCriticalStatement = (
critical: ICriticalStatement,
_input: IGeneratorInput,
_state: IGeneratorState,
_orchestrator: IOrchestrator,
): IGeneratorOutput => {
// #1322: the early-exit check that stood here is E0853 in pass 2.1, which
// reaches every statement the grammar can nest inside the block -- including
// `switch`, which the recursion it replaces did not descend into.
// The IRQ wrappers, not cmsis_gcc.h: this avoids macro collisions with
// platform headers like Teensy's imxrt.h. Issue #1143: the line is carried
// so the deferred emitter can tell the user *which* critical block made
// their project depend on CMSIS or avr-libc. The masked region is the one
// an atomic read-modify-write takes too (#1146).
const innerCode = critical.blockCode.slice(1, -1).trim();
return InterruptMask.wrap(innerCode, critical.line);
};
export default generateCriticalStatement;
|