@typecad/cuttlefish 1.0.0-alpha.13 → 1.0.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -79
- package/assets/editor-extensions/typecad-debug/README.md +141 -0
- package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
- package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
- package/assets/editor-extensions/typecad-debug/package.json +76 -0
- package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
- package/assets/editor-extensions/typecad-ui/README.md +52 -0
- package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
- package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
- package/assets/editor-extensions/typecad-ui/icon.png +0 -0
- package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
- package/assets/editor-extensions/typecad-ui/package.json +54 -0
- package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
- package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
- package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
- package/dist/api/config.d.ts +30 -27
- package/dist/api/schema/types.d.ts +20 -3
- package/dist/api/shared/async-runtime-static.d.ts +1 -1
- package/dist/api/shared/async-runtime-static.js +5 -5
- package/dist/api/shared/async-types.d.ts +3 -2
- package/dist/api/shared/board-catalog.d.ts +2 -0
- package/dist/api/shared/board-catalog.js +6 -0
- package/dist/api/shared/board-resolver.d.ts +4 -7
- package/dist/api/shared/board-resolver.js +2 -1
- package/dist/api/shared/coop-scheduler.d.ts +1 -1
- package/dist/api/shared/coop-scheduler.js +1 -1
- package/dist/api/shared/cpp-type-ir.d.ts +1 -1
- package/dist/api/shared/cpp-type-ir.js +1 -1
- package/dist/api/shared/display-profile.d.ts +1 -1
- package/dist/api/shared/display-profile.js +3 -5
- package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
- package/dist/api/shared/framework-manifest-registry.js +0 -1
- package/dist/api/shared/framework-manifest.d.ts +65 -507
- package/dist/api/shared/framework-manifest.js +6 -11
- package/dist/api/shared/hal-op-ir.d.ts +294 -685
- package/dist/api/shared/hal-op-ir.js +31 -65
- package/dist/api/shared/index.d.ts +0 -4
- package/dist/api/shared/index.js +1 -7
- package/dist/api/shared/ir-core.d.ts +6 -0
- package/dist/api/shared/ir-declarations.d.ts +4 -0
- package/dist/api/shared/ir.d.ts +1 -3
- package/dist/api/shared/platform-strategy.d.ts +14 -37
- package/dist/api/shared/polyfill-helper-registry.js +0 -5
- package/dist/api/shared/polyfill-types.js +0 -27
- package/dist/api/shared/promise-runtime.js +3 -3
- package/dist/api/shared/spdx-licenses.d.ts +12 -10
- package/dist/api/shared/spdx-licenses.js +1 -1
- package/dist/api/shared/toolchain-types.d.ts +1 -1
- package/dist/api/shared/toolchain-types.js +3 -3
- package/dist/api/shared/types.d.ts +0 -3
- package/dist/api/shared/validate-framework-manifest.js +13 -33
- package/dist/board-catalog/dts-reader.d.ts +220 -0
- package/dist/board-catalog/dts-reader.js +1052 -0
- package/dist/board-catalog/index.d.ts +11 -0
- package/dist/board-catalog/index.js +12 -0
- package/dist/board-catalog/pinconfig.d.ts +48 -0
- package/dist/board-catalog/pinconfig.js +263 -0
- package/dist/board-catalog/sdk.d.ts +82 -0
- package/dist/board-catalog/sdk.js +180 -0
- package/dist/board-catalog/store.d.ts +196 -0
- package/dist/board-catalog/store.js +363 -0
- package/dist/board-catalog/types.d.ts +233 -0
- package/dist/board-catalog/types.js +7 -0
- package/dist/board-catalog/walker.d.ts +112 -0
- package/dist/board-catalog/walker.js +1101 -0
- package/dist/cli-utils.d.ts +2 -2
- package/dist/cli-utils.js +5 -5
- package/dist/cli.js +227 -244
- package/dist/config-loader.d.ts +14 -19
- package/dist/config-loader.js +242 -78
- package/dist/config-schema.d.ts +19 -227
- package/dist/config-schema.js +9 -8
- package/dist/contract/board-generator.d.ts +4 -4
- package/dist/contract/board-generator.js +16 -5
- package/dist/contract/contract-parser.d.ts +36 -127
- package/dist/contract/contract-parser.js +76 -0
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.js +70 -21
- package/dist/create/active-board-catalog.d.ts +9 -0
- package/dist/create/active-board-catalog.js +94 -0
- package/dist/create/board-catalog.generated.d.ts +96 -0
- package/dist/create/board-catalog.generated.js +128737 -0
- package/dist/create/board-search.d.ts +23 -0
- package/dist/create/board-search.js +88 -0
- package/dist/create/editor-integration.d.ts +32 -0
- package/dist/create/editor-integration.js +257 -0
- package/dist/create/eslint-rules-template.d.ts +2 -2
- package/dist/create/framework-catalog.d.ts +48 -8
- package/dist/create/framework-catalog.js +58 -44
- package/dist/create/index.d.ts +8 -13
- package/dist/create/index.js +5 -9
- package/dist/create/mcu-target.d.ts +39 -0
- package/dist/create/mcu-target.js +80 -0
- package/dist/create/pack-targets.d.ts +19 -0
- package/dist/create/pack-targets.js +56 -0
- package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +8 -11
- package/dist/create/{init-scaffold.js → scaffold.js} +28 -87
- package/dist/create/templates.d.ts +51 -0
- package/dist/create/{init-templates.js → templates.js} +135 -116
- package/dist/create/wizard.d.ts +19 -0
- package/dist/create/wizard.js +314 -0
- package/dist/debug/preprocessor.d.ts +5 -0
- package/dist/debug/preprocessor.js +31 -7
- package/dist/diagnostics/diagnostics-report.d.ts +1 -1
- package/dist/diagnostics/diagnostics-report.js +3 -11
- package/dist/diagnostics/json-schema.d.ts +1 -1
- package/dist/diagnostics/md-writer.js +2 -2
- package/dist/diagnostics/mermaid-builder.d.ts +1 -1
- package/dist/diagnostics/mermaid-builder.js +1 -1
- package/dist/emit/cpp-emitter.js +4 -1
- package/dist/emit/emitters/class-emitter.js +32 -4
- package/dist/emit/emitters/emitter-context.d.ts +11 -0
- package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
- package/dist/emit/emitters/function-emitter-impl.js +33 -17
- package/dist/emit/emitters/output-finalizer.d.ts +7 -0
- package/dist/emit/emitters/output-finalizer.js +31 -23
- package/dist/emit/emitters/setup.js +147 -63
- package/dist/emit/emitters/top-level-prep.js +1 -1
- package/dist/emit/emitters/type-decl-emitter.js +13 -8
- package/dist/emit/emitters/ui-emitter.js +1 -1
- package/dist/emit/expression-renderer.d.ts +3 -3
- package/dist/emit/expression-renderer.js +17 -7
- package/dist/emit/route-hal-op.js +17 -48
- package/dist/emit/snprintf-helpers.d.ts +1 -3
- package/dist/emit/snprintf-helpers.js +1 -39
- package/dist/emit/statement-renderer.d.ts +0 -4
- package/dist/emit/statement-renderer.js +54 -45
- package/dist/emit/utils/async-state-machine.d.ts +16 -9
- package/dist/emit/utils/async-state-machine.js +56 -54
- package/dist/emit/utils/comment-helpers.d.ts +0 -8
- package/dist/emit/utils/comment-helpers.js +1 -1
- package/dist/emit/utils/cpp-helpers.d.ts +2 -2
- package/dist/emit/utils/cpp-helpers.js +2 -2
- package/dist/emit/utils/hal-op-cpp-type.js +4 -6
- package/dist/emit/utils/index.d.ts +3 -3
- package/dist/emit/utils/index.js +3 -3
- package/dist/emit/utils/type-inference.d.ts +1 -29
- package/dist/emit/utils/type-inference.js +0 -75
- package/dist/framework-package.d.ts +3 -0
- package/dist/framework-package.js +23 -6
- package/dist/framework-registry.d.ts +5 -5
- package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
- package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
- package/dist/frameworks/native/index.d.ts +3 -0
- package/dist/frameworks/native/index.js +15 -0
- package/dist/frameworks/native/native-compile.d.ts +17 -0
- package/dist/frameworks/native/native-compile.js +170 -0
- package/dist/frameworks/native/native-config.d.ts +41 -0
- package/dist/frameworks/native/native-config.js +7 -0
- package/dist/frameworks/native/strategy.d.ts +97 -0
- package/dist/frameworks/native/strategy.js +664 -0
- package/dist/ir/board-resolver.d.ts +18 -23
- package/dist/ir/board-resolver.js +43 -401
- package/dist/ir/build-ir-state.d.ts +3 -0
- package/dist/ir/build-ir-state.js +42 -0
- package/dist/ir/build-ir.d.ts +1 -1
- package/dist/ir/build-ir.js +64 -45
- package/dist/ir/declaration-builders.js +1 -0
- package/dist/ir/expression-to-ir.js +17 -10
- package/dist/ir/hal/hal-emitter.d.ts +0 -2
- package/dist/ir/hal/hal-emitter.js +92 -41
- package/dist/ir/hal/hal-parser.d.ts +5 -5
- package/dist/ir/hal/hal-parser.js +128 -36
- package/dist/ir/hal/hal-plugins.d.ts +0 -1
- package/dist/ir/hal/hal-plugins.js +425 -716
- package/dist/ir/heap-analysis.js +2 -41
- package/dist/ir/identifier-collector.js +32 -20
- package/dist/ir/network-validation.js +7 -11
- package/dist/ir/ownership-analysis.js +75 -13
- package/dist/ir/peripheral-usage.d.ts +8 -2
- package/dist/ir/peripheral-usage.js +78 -149
- package/dist/ir/peripheral-validation.js +23 -3
- package/dist/ir/pin-capability-validation.d.ts +12 -0
- package/dist/ir/pin-capability-validation.js +61 -97
- package/dist/ir/pin-mode-validation.js +5 -5
- package/dist/ir/program-analysis.d.ts +8 -15
- package/dist/ir/program-analysis.js +140 -323
- package/dist/ir/pulldown-validation.js +11 -4
- package/dist/ir/resource-analysis.js +15 -3
- package/dist/ir/statement-to-ir.js +0 -6
- package/dist/ir/timing-validation.js +1 -1
- package/dist/ir/transformers/array-methods.js +11 -5
- package/dist/ir/transformers/call-statement.js +20 -87
- package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
- package/dist/ir/transformers/callback-context-registry.js +8 -16
- package/dist/ir/transformers/control-flow.js +0 -13
- package/dist/ir/transformers/expressions.js +10 -9
- package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
- package/dist/ir/transformers/hal-call-resolver.js +24 -10
- package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
- package/dist/ir/transformers/hal-emit-helpers.js +2 -2
- package/dist/ir/transformers/namespace-methods.js +1 -1
- package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
- package/dist/ir/transformers/ui-callback-lowering.js +0 -24
- package/dist/ir/transformers/variables.js +338 -42
- package/dist/ir/try-catch-validation.js +4 -3
- package/dist/ir/type-resolution.js +15 -4
- package/dist/ir/validation-orchestrator.js +0 -9
- package/dist/libdef/cpp-to-decl.d.ts +0 -9
- package/dist/libdef/cpp-to-decl.js +0 -72
- package/dist/libdef/registry.d.ts +0 -1
- package/dist/libdef/registry.js +1 -24
- package/dist/library/catalog.d.ts +35 -0
- package/dist/library/catalog.js +67 -0
- package/dist/library/cli.d.ts +2 -0
- package/dist/library/cli.js +168 -0
- package/dist/library/init.d.ts +25 -0
- package/dist/library/init.js +397 -0
- package/dist/library/install.d.ts +9 -0
- package/dist/library/install.js +80 -0
- package/dist/library/registry-search.d.ts +34 -0
- package/dist/library/registry-search.js +50 -0
- package/dist/library/validate.d.ts +17 -0
- package/dist/library/validate.js +175 -0
- package/dist/library-packages.d.ts +95 -0
- package/dist/library-packages.js +275 -0
- package/dist/mapping/peripheral-names.js +9 -4
- package/dist/mapping/source-map.d.ts +3 -4
- package/dist/mapping/source-map.js +12 -18
- package/dist/orchestrator/graph-builder.d.ts +3 -3
- package/dist/orchestrator/graph-builder.js +29 -12
- package/dist/orchestrator/type-checker.d.ts +3 -3
- package/dist/orchestrator/type-checker.js +3 -3
- package/dist/platform/async-runtime.js +1 -1
- package/dist/platform/coop-scheduler-runtime.js +2 -2
- package/dist/platform/generic-debug-codegen.d.ts +36 -0
- package/dist/platform/generic-debug-codegen.js +185 -0
- package/dist/platform/generic-strategy.d.ts +3 -4
- package/dist/platform/generic-strategy.js +5 -80
- package/dist/platform/index.js +1 -1
- package/dist/platform/registry.d.ts +2 -2
- package/dist/platform/registry.js +2 -2
- package/dist/preview/client.js +17 -3
- package/dist/safety/asil-decorators.d.ts +32 -0
- package/dist/safety/asil-decorators.js +32 -0
- package/dist/safety/authoring.d.ts +85 -0
- package/dist/safety/authoring.js +61 -0
- package/dist/safety/engine.d.ts +3 -0
- package/dist/safety/engine.js +83 -0
- package/dist/safety/hal/ops.d.ts +48 -0
- package/dist/safety/hal/ops.js +46 -0
- package/dist/safety/iso26262/analyze.d.ts +13 -0
- package/dist/safety/iso26262/analyze.js +29 -0
- package/dist/safety/iso26262/asil.d.ts +10 -0
- package/dist/safety/iso26262/asil.js +22 -0
- package/dist/safety/iso26262/collect.d.ts +14 -0
- package/dist/safety/iso26262/collect.js +137 -0
- package/dist/safety/iso26262/goto-checker.d.ts +10 -0
- package/dist/safety/iso26262/goto-checker.js +72 -0
- package/dist/safety/iso26262/heap-checker.d.ts +7 -0
- package/dist/safety/iso26262/heap-checker.js +57 -0
- package/dist/safety/iso26262/init-checker.d.ts +13 -0
- package/dist/safety/iso26262/init-checker.js +127 -0
- package/dist/safety/iso26262/loop-checker.d.ts +7 -0
- package/dist/safety/iso26262/loop-checker.js +86 -0
- package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
- package/dist/safety/iso26262/recursion-checker.js +134 -0
- package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
- package/dist/safety/iso26262/sidecar-writer.js +13 -0
- package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
- package/dist/safety/passes/pinMode-intercept.js +60 -0
- package/dist/safety/runtime/mode-table.d.ts +5 -0
- package/dist/safety/runtime/mode-table.js +55 -0
- package/dist/safety/runtime/polyfills.d.ts +6 -0
- package/dist/safety/runtime/polyfills.js +12 -0
- package/dist/safety/runtime/result-struct.d.ts +11 -0
- package/dist/safety/runtime/result-struct.js +98 -0
- package/dist/safety/runtime/safe-int.d.ts +33 -0
- package/dist/safety/runtime/safe-int.js +170 -0
- package/dist/safety/runtime/safe-traits.d.ts +4 -0
- package/dist/safety/runtime/safe-traits.js +95 -0
- package/dist/safety/runtime/safe-variable.d.ts +39 -0
- package/dist/safety/runtime/safe-variable.js +226 -0
- package/dist/safety/runtime/vote.d.ts +8 -0
- package/dist/safety/runtime/vote.js +92 -0
- package/dist/safety/runtime/write-verify.d.ts +8 -0
- package/dist/safety/runtime/write-verify.js +71 -0
- package/dist/safety/safe-int-types.d.ts +45 -0
- package/dist/safety/safe-int-types.js +25 -0
- package/dist/safety/safe-variable-types.d.ts +29 -0
- package/dist/safety/safe-variable-types.js +19 -0
- package/dist/safety/safety-bridge.d.ts +5 -6
- package/dist/safety/safety-bridge.js +15 -28
- package/dist/safety/sidecar-bridge.d.ts +1 -3
- package/dist/safety/sidecar-bridge.js +3 -20
- package/dist/safety/specifiers.d.ts +6 -0
- package/dist/safety/specifiers.js +14 -0
- package/dist/safety-hook.d.ts +8 -7
- package/dist/safety-hook.js +12 -13
- package/dist/testing.d.ts +5 -6
- package/dist/testing.js +5 -5
- package/dist/transpile/resolution.d.ts +1 -1
- package/dist/transpile/resolution.js +18 -9
- package/dist/transpile/test-pins.d.ts +18 -0
- package/dist/transpile/test-pins.js +142 -0
- package/dist/transpile.d.ts +1 -2
- package/dist/transpile.js +90 -29
- package/dist/types.d.ts +45 -26
- package/dist/ui-hook.d.ts +1 -1
- package/dist/utils/cli.d.ts +2 -2
- package/dist/utils/cli.js +160 -157
- package/dist/utils/fs.d.ts +3 -4
- package/dist/utils/fs.js +4 -5
- package/dist/utils/strings.d.ts +0 -1
- package/dist/utils/strings.js +0 -8
- package/dist/utils/ui.d.ts +5 -2
- package/dist/utils/ui.js +13 -3
- package/package.json +158 -149
- package/dist/add-preset.d.ts +0 -4
- package/dist/add-preset.js +0 -74
- package/dist/api/shared/async-symbol-detector.d.ts +0 -11
- package/dist/api/shared/async-symbol-detector.js +0 -140
- package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
- package/dist/api/shared/native-display-op-resolver.js +0 -64
- package/dist/create/board-checklist.d.ts +0 -2
- package/dist/create/board-checklist.js +0 -52
- package/dist/create/board-codegen.d.ts +0 -9
- package/dist/create/board-codegen.js +0 -238
- package/dist/create/board-generators.d.ts +0 -12
- package/dist/create/board-generators.js +0 -651
- package/dist/create/board-spec.d.ts +0 -637
- package/dist/create/board-spec.js +0 -214
- package/dist/create/init-templates.d.ts +0 -28
- package/dist/create/init-wizard.d.ts +0 -8
- package/dist/create/init-wizard.js +0 -182
- package/dist/install/framework-catalog.d.ts +0 -53
- package/dist/install/framework-catalog.js +0 -107
- package/dist/install/handle-install.d.ts +0 -35
- package/dist/install/handle-install.js +0 -177
- package/dist/install/index.d.ts +0 -4
- package/dist/install/index.js +0 -3
- package/dist/ir/pin-state-tracking.d.ts +0 -58
- package/dist/ir/pin-state-tracking.js +0 -182
- package/dist/ir/pwm-timer-sharing.d.ts +0 -4
- package/dist/ir/pwm-timer-sharing.js +0 -94
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
- package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
- package/dist/libdef/component-decls.d.ts +0 -2
- package/dist/libdef/component-decls.js +0 -6
- package/dist/libdef/component-discovery.d.ts +0 -43
- package/dist/libdef/component-discovery.js +0 -83
- package/dist/theme-tokens.d.ts +0 -22
- package/dist/theme-tokens.js +0 -172
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { emitResultStructs } from "./result-struct.js";
|
|
2
|
+
/** The pin-mode tracking table + accessors. Tree-shaken out unless
|
|
3
|
+
* __tc_safety_record_pin_mode appears in the program (registered in
|
|
4
|
+
* POLYFILL_HELPER_MAP). */
|
|
5
|
+
export function modeTablePolyfill() {
|
|
6
|
+
return {
|
|
7
|
+
kind: "polyfill",
|
|
8
|
+
id: "safety_mode_table",
|
|
9
|
+
domain: "embedded",
|
|
10
|
+
requiredIncludes: [],
|
|
11
|
+
forwardDeclarations: [],
|
|
12
|
+
helperStructs: [],
|
|
13
|
+
helperFunctions: [
|
|
14
|
+
emitResultStructs(),
|
|
15
|
+
`
|
|
16
|
+
namespace __tc_safety {
|
|
17
|
+
constexpr uint32_t TC_SAFETY_PIN_TABLE_SIZE = 255U;
|
|
18
|
+
|
|
19
|
+
enum class TrackedMode : uint32_t {
|
|
20
|
+
Unknown = 0x00000000U,
|
|
21
|
+
Input = 0x5A5A5A5AU,
|
|
22
|
+
Output = 0xA5A5A5A5U,
|
|
23
|
+
InputPullup = 0x3C3C3C3CU,
|
|
24
|
+
InputPulldown = 0xC3C3C3C3U,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Raw array: unavoidable for O(1) pin-indexed lookup in an embedded shim.
|
|
28
|
+
// Zero-initialized namespace-scope static storage (Unknown = 0U) satisfies
|
|
29
|
+
// M3-2-1 (const-init) and M3-2-4 (trivial static init); no knownPatterns
|
|
30
|
+
// deviation needed (verified in Part A v1).
|
|
31
|
+
TrackedMode g_pin_mode_table[TC_SAFETY_PIN_TABLE_SIZE];
|
|
32
|
+
|
|
33
|
+
inline void record_pin_mode(uint32_t pin, uint32_t mode) {
|
|
34
|
+
if (pin < TC_SAFETY_PIN_TABLE_SIZE) {
|
|
35
|
+
g_pin_mode_table[pin] = static_cast<TrackedMode>(mode);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
inline TrackedMode get_pin_mode(uint32_t pin) {
|
|
40
|
+
if (pin < TC_SAFETY_PIN_TABLE_SIZE) {
|
|
41
|
+
return g_pin_mode_table[pin];
|
|
42
|
+
}
|
|
43
|
+
return TrackedMode::Unknown;
|
|
44
|
+
}
|
|
45
|
+
} // namespace __tc_safety
|
|
46
|
+
|
|
47
|
+
inline void __tc_safety_record_pin_mode(uint32_t pin, uint32_t mode) {
|
|
48
|
+
__tc_safety::record_pin_mode(pin, mode);
|
|
49
|
+
}
|
|
50
|
+
`.trim(),
|
|
51
|
+
],
|
|
52
|
+
shimMacros: [],
|
|
53
|
+
dependencies: [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RuntimePolyfillIR } from "../../api/index.js";
|
|
2
|
+
/** All safety runtime polyfills, in dependency order (mode table before voter
|
|
3
|
+
* and write-verify, safe variable and safe int are standalone). Returned by
|
|
4
|
+
* the safety hook's buildPolyfills(); called from buildEmitterContext so each
|
|
5
|
+
* polyfill participates in usage-based tree-shaking via filterPolyfillHelpers. */
|
|
6
|
+
export declare function buildSafetyPolyfills(): RuntimePolyfillIR[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { modeTablePolyfill } from "./mode-table.js";
|
|
2
|
+
import { voterPolyfill } from "./vote.js";
|
|
3
|
+
import { safeVariablePolyfill } from "./safe-variable.js";
|
|
4
|
+
import { safeIntPolyfill } from "./safe-int.js";
|
|
5
|
+
import { writeVerifyPolyfill } from "./write-verify.js";
|
|
6
|
+
/** All safety runtime polyfills, in dependency order (mode table before voter
|
|
7
|
+
* and write-verify, safe variable and safe int are standalone). Returned by
|
|
8
|
+
* the safety hook's buildPolyfills(); called from buildEmitterContext so each
|
|
9
|
+
* polyfill participates in usage-based tree-shaking via filterPolyfillHelpers. */
|
|
10
|
+
export function buildSafetyPolyfills() {
|
|
11
|
+
return [modeTablePolyfill(), voterPolyfill(), writeVerifyPolyfill(), safeVariablePolyfill(), safeIntPolyfill()];
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Returns the C++ enum + struct definitions for the safety runtime.
|
|
2
|
+
*
|
|
3
|
+
* These are emitted by the polyfill as the SINGLE canonical source.
|
|
4
|
+
* @typecad/safety is skipped by the graph-builder (like @typecad/ui), so
|
|
5
|
+
* its TypeScript source is never parsed into the user program's IR — the
|
|
6
|
+
* type-decl emitter never sees the enums. The polyfill provides the
|
|
7
|
+
* definitions that both the voter and the user's switch statements
|
|
8
|
+
* reference. Works in both single-file and split-file emit modes because
|
|
9
|
+
* the polyfill is inlined into the entry file's source, visible to all
|
|
10
|
+
* functions in that translation unit. */
|
|
11
|
+
export declare function emitResultStructs(): string;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// C++ source strings for the safety result struct + fault enums. Emitted by
|
|
2
|
+
// the mode-table polyfill (Task 9) BEFORE the voter, so the voter can return
|
|
3
|
+
// a SafeReadResult.
|
|
4
|
+
//
|
|
5
|
+
// AUTOSAR C++14 compliance:
|
|
6
|
+
// - enum class (A7-2-1)
|
|
7
|
+
// - fixed-width types (A3-9-1): uint8_t
|
|
8
|
+
// - no C-style casts (M5-0-7), no malloc (A18-5-10)
|
|
9
|
+
// - the raw pin table in mode-table.ts is zero-initialized namespace-scope
|
|
10
|
+
// static storage, satisfying M3-2-1/M3-2-4. No knownPatterns deviation is
|
|
11
|
+
// expected; if a rule fires anyway, add one (see
|
|
12
|
+
// docs/superpowers/plans/2026-07-27-safety-package-part-a.md Task 17).
|
|
13
|
+
/** Returns the C++ enum + struct definitions for the safety runtime.
|
|
14
|
+
*
|
|
15
|
+
* These are emitted by the polyfill as the SINGLE canonical source.
|
|
16
|
+
* @typecad/safety is skipped by the graph-builder (like @typecad/ui), so
|
|
17
|
+
* its TypeScript source is never parsed into the user program's IR — the
|
|
18
|
+
* type-decl emitter never sees the enums. The polyfill provides the
|
|
19
|
+
* definitions that both the voter and the user's switch statements
|
|
20
|
+
* reference. Works in both single-file and split-file emit modes because
|
|
21
|
+
* the polyfill is inlined into the entry file's source, visible to all
|
|
22
|
+
* functions in that translation unit. */
|
|
23
|
+
export function emitResultStructs() {
|
|
24
|
+
return `
|
|
25
|
+
enum class SafetyStatus : uint32_t {
|
|
26
|
+
Ok = 0x5A5A5A5AU,
|
|
27
|
+
Fault = 0xA5A5A5A5U,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
enum class SafetyFaultCategory : uint32_t {
|
|
31
|
+
Ok = 0x3C3C3C3CU,
|
|
32
|
+
Signal = 0x5A5A5A5AU,
|
|
33
|
+
Integrity = 0xA5A5A5A5U,
|
|
34
|
+
Timing = 0xC3C3C3C3U,
|
|
35
|
+
System = 0x55AA55AAU,
|
|
36
|
+
Configuration = 0xAA55AA55U,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
enum class SafetyFaultCode : uint32_t {
|
|
40
|
+
Ok = 0x3C3C3C3CU,
|
|
41
|
+
VoteDisagreement = 0x5A5A5A5AU,
|
|
42
|
+
StuckHigh = 0xA5A5A5A5U,
|
|
43
|
+
StuckLow = 0xC3C3C3C3U,
|
|
44
|
+
PinModeMismatch = 0x55AA55AAU,
|
|
45
|
+
PinModeUnknown = 0xAA55AA55U,
|
|
46
|
+
WriteMismatch = 0x3C5AA5C3U,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
struct SafeReadResult {
|
|
50
|
+
SafetyStatus status;
|
|
51
|
+
uint32_t value;
|
|
52
|
+
SafetyFaultCategory category;
|
|
53
|
+
SafetyFaultCode code;
|
|
54
|
+
|
|
55
|
+
// Chainable result handlers. Each calls the handler at runtime when its
|
|
56
|
+
// condition matches, then returns *this so chains compose and the result
|
|
57
|
+
// stays inspectable afterward. Template F&& accepts the inline C++ lambdas
|
|
58
|
+
// cuttlefish renders — no std::function, no heap allocation.
|
|
59
|
+
template <typename F>
|
|
60
|
+
SafeReadResult& ok(F&& handler) noexcept {
|
|
61
|
+
if (status == SafetyStatus::Ok) { handler(*this); }
|
|
62
|
+
return *this;
|
|
63
|
+
}
|
|
64
|
+
template <typename F>
|
|
65
|
+
SafeReadResult& fail(F&& handler) noexcept {
|
|
66
|
+
if (status != SafetyStatus::Ok) { handler(*this); }
|
|
67
|
+
return *this;
|
|
68
|
+
}
|
|
69
|
+
// fault is an alias of fail (no std::forward — avoids the <utility> header
|
|
70
|
+
// AVR lacks; the handler is called once immediately, so perfect forwarding
|
|
71
|
+
// is not load-bearing).
|
|
72
|
+
template <typename F>
|
|
73
|
+
SafeReadResult& fault(F&& handler) noexcept { return fail(handler); }
|
|
74
|
+
template <typename F>
|
|
75
|
+
SafeReadResult& always(F&& handler) noexcept { handler(*this); return *this; }
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
struct SafeWriteResult {
|
|
79
|
+
SafetyStatus status;
|
|
80
|
+
SafetyFaultCode code;
|
|
81
|
+
|
|
82
|
+
template <typename F>
|
|
83
|
+
SafeWriteResult& ok(F&& handler) noexcept {
|
|
84
|
+
if (status == SafetyStatus::Ok) { handler(*this); }
|
|
85
|
+
return *this;
|
|
86
|
+
}
|
|
87
|
+
template <typename F>
|
|
88
|
+
SafeWriteResult& fail(F&& handler) noexcept {
|
|
89
|
+
if (status != SafetyStatus::Ok) { handler(*this); }
|
|
90
|
+
return *this;
|
|
91
|
+
}
|
|
92
|
+
template <typename F>
|
|
93
|
+
SafeWriteResult& fault(F&& handler) noexcept { return fail(handler); }
|
|
94
|
+
template <typename F>
|
|
95
|
+
SafeWriteResult& always(F&& handler) noexcept { handler(*this); return *this; }
|
|
96
|
+
};
|
|
97
|
+
`.trim();
|
|
98
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RuntimePolyfillIR } from "../../api/index.js";
|
|
2
|
+
/** SafeInt<T> polyfill: chainable bounds-checked signed-integer arithmetic.
|
|
3
|
+
*
|
|
4
|
+
* Mutating chain — every math op returns SafeInt<T>& so calls compose:
|
|
5
|
+
* x.add(5).mul(2).get()
|
|
6
|
+
*
|
|
7
|
+
* Sticky-fault overflow policy: on overflow or division error, set fault_
|
|
8
|
+
* and stop computing. Subsequent ops are no-ops returning *this. get()
|
|
9
|
+
* returns the last good value. hasFault()/valid() inspect the flag;
|
|
10
|
+
* reset() clears it.
|
|
11
|
+
*
|
|
12
|
+
* Overflow detection uses portable pure-C++14 PRE-CHECKS (bounds tests
|
|
13
|
+
* before the assignment). The reconstruction trick would compute first
|
|
14
|
+
* then check, but the initial computation is signed-overflow UB. Pre-checks
|
|
15
|
+
* avoid the UB, work at every width including int64_t (no wider promotion
|
|
16
|
+
* type needed), and need no __builtin_*_overflow (a GCC/clang extension
|
|
17
|
+
* that would require an AUTOSAR deviation).
|
|
18
|
+
*
|
|
19
|
+
* NO <type_traits> / <limits> includes: AVR's toolchain ships neither
|
|
20
|
+
* header. The type constraint (static_assert) and the per-width bounds come
|
|
21
|
+
* from the shared hand-rolled __tc_safe_traits block (safe-traits.ts), which
|
|
22
|
+
* uses only core-language features (template specialization, static_cast,
|
|
23
|
+
* constexpr) that every supported target — including AVR's avr-gcc — has.
|
|
24
|
+
*
|
|
25
|
+
* AUTOSAR C++14 compliance:
|
|
26
|
+
* - static_assert on T (rejects unsigned, bool, float, non-integer)
|
|
27
|
+
* - noexcept on all methods (A15-0-2)
|
|
28
|
+
* - [[nodiscard]] on get/hasFault/valid (A0-1-1)
|
|
29
|
+
* - constexpr constructor
|
|
30
|
+
* - static_cast throughout (no C-casts M5-0-7, no builtins M5-0-10,
|
|
31
|
+
* no malloc A18-5-10). Zero deviations required.
|
|
32
|
+
*/
|
|
33
|
+
export declare function safeIntPolyfill(): RuntimePolyfillIR;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { emitSafeTraits } from "./safe-traits.js";
|
|
2
|
+
/** SafeInt<T> polyfill: chainable bounds-checked signed-integer arithmetic.
|
|
3
|
+
*
|
|
4
|
+
* Mutating chain — every math op returns SafeInt<T>& so calls compose:
|
|
5
|
+
* x.add(5).mul(2).get()
|
|
6
|
+
*
|
|
7
|
+
* Sticky-fault overflow policy: on overflow or division error, set fault_
|
|
8
|
+
* and stop computing. Subsequent ops are no-ops returning *this. get()
|
|
9
|
+
* returns the last good value. hasFault()/valid() inspect the flag;
|
|
10
|
+
* reset() clears it.
|
|
11
|
+
*
|
|
12
|
+
* Overflow detection uses portable pure-C++14 PRE-CHECKS (bounds tests
|
|
13
|
+
* before the assignment). The reconstruction trick would compute first
|
|
14
|
+
* then check, but the initial computation is signed-overflow UB. Pre-checks
|
|
15
|
+
* avoid the UB, work at every width including int64_t (no wider promotion
|
|
16
|
+
* type needed), and need no __builtin_*_overflow (a GCC/clang extension
|
|
17
|
+
* that would require an AUTOSAR deviation).
|
|
18
|
+
*
|
|
19
|
+
* NO <type_traits> / <limits> includes: AVR's toolchain ships neither
|
|
20
|
+
* header. The type constraint (static_assert) and the per-width bounds come
|
|
21
|
+
* from the shared hand-rolled __tc_safe_traits block (safe-traits.ts), which
|
|
22
|
+
* uses only core-language features (template specialization, static_cast,
|
|
23
|
+
* constexpr) that every supported target — including AVR's avr-gcc — has.
|
|
24
|
+
*
|
|
25
|
+
* AUTOSAR C++14 compliance:
|
|
26
|
+
* - static_assert on T (rejects unsigned, bool, float, non-integer)
|
|
27
|
+
* - noexcept on all methods (A15-0-2)
|
|
28
|
+
* - [[nodiscard]] on get/hasFault/valid (A0-1-1)
|
|
29
|
+
* - constexpr constructor
|
|
30
|
+
* - static_cast throughout (no C-casts M5-0-7, no builtins M5-0-10,
|
|
31
|
+
* no malloc A18-5-10). Zero deviations required.
|
|
32
|
+
*/
|
|
33
|
+
export function safeIntPolyfill() {
|
|
34
|
+
return {
|
|
35
|
+
kind: "polyfill",
|
|
36
|
+
id: "safety_safe_int",
|
|
37
|
+
domain: "embedded",
|
|
38
|
+
requiredIncludes: [],
|
|
39
|
+
forwardDeclarations: [],
|
|
40
|
+
helperStructs: [],
|
|
41
|
+
helperFunctions: [`
|
|
42
|
+
${emitSafeTraits()}
|
|
43
|
+
|
|
44
|
+
#ifndef __TC_SAFE_INT_DEFINED
|
|
45
|
+
#define __TC_SAFE_INT_DEFINED
|
|
46
|
+
|
|
47
|
+
// No #include here: the fixed-width integer types come transitively from
|
|
48
|
+
// <Arduino.h> on embedded targets (which pulls <stdint.h>), mirroring the
|
|
49
|
+
// other safety polyfills (mode-table, vote). The shared __tc_safe_traits
|
|
50
|
+
// block (emitted above) is also header-free.
|
|
51
|
+
|
|
52
|
+
template <typename T>
|
|
53
|
+
struct SafeInt {
|
|
54
|
+
static_assert(__tc_safe_traits::is_integral<T>::value
|
|
55
|
+
&& __tc_safe_traits::is_signed<T>::value
|
|
56
|
+
&& !__tc_safe_traits::is_same<T, bool>::value,
|
|
57
|
+
"SafeInt<T> requires a signed integer T (int8_t/int16_t/int32_t/int64_t). "
|
|
58
|
+
"Unsigned, bool, floating-point, and non-integer types are rejected.");
|
|
59
|
+
|
|
60
|
+
private:
|
|
61
|
+
T value_;
|
|
62
|
+
bool fault_;
|
|
63
|
+
|
|
64
|
+
static constexpr T kMax = __tc_safe_traits::bounds<T>::kMax;
|
|
65
|
+
static constexpr T kMin = __tc_safe_traits::bounds<T>::kMin;
|
|
66
|
+
|
|
67
|
+
public:
|
|
68
|
+
// Default constructor: zero-initialized, no fault. Required because promoted
|
|
69
|
+
// top-level variables default-construct via '= {}' before their real
|
|
70
|
+
// initializer is assigned inside the entrypoint. Mirrors SafeVariable's
|
|
71
|
+
// default ctor.
|
|
72
|
+
constexpr SafeInt() noexcept : value_(0), fault_(false) {}
|
|
73
|
+
constexpr SafeInt(T initial) noexcept : value_(initial), fault_(false) {}
|
|
74
|
+
|
|
75
|
+
SafeInt<T>& add(T delta) noexcept {
|
|
76
|
+
if (fault_) { return *this; }
|
|
77
|
+
// Pre-check: overflow iff (delta>0 && value>Max-delta) || (delta<0 && value<Min-delta).
|
|
78
|
+
// (Max-delta) and (Min-delta) are safe because delta has the opposite sign
|
|
79
|
+
// of the bound being approached, so the subtraction cannot itself overflow.
|
|
80
|
+
if ((delta > 0 && value_ > kMax - delta) || (delta < 0 && value_ < kMin - delta)) {
|
|
81
|
+
fault_ = true;
|
|
82
|
+
return *this;
|
|
83
|
+
}
|
|
84
|
+
value_ = static_cast<T>(value_ + delta);
|
|
85
|
+
return *this;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
SafeInt<T>& sub(T delta) noexcept {
|
|
89
|
+
if (fault_) { return *this; }
|
|
90
|
+
// Direct pre-check (NOT add(-delta), since -delta is UB when delta==Min):
|
|
91
|
+
// value - delta > Max iff value > Max + delta (when delta < 0)
|
|
92
|
+
// value - delta < Min iff value < Min + delta (when delta > 0)
|
|
93
|
+
// (Max+delta)/(Min+delta) are safe — delta has the opposite sign of the bound.
|
|
94
|
+
if ((delta < 0 && value_ > kMax + delta) || (delta > 0 && value_ < kMin + delta)) {
|
|
95
|
+
fault_ = true;
|
|
96
|
+
return *this;
|
|
97
|
+
}
|
|
98
|
+
value_ = static_cast<T>(value_ - delta);
|
|
99
|
+
return *this;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
SafeInt<T>& mul(T factor) noexcept {
|
|
103
|
+
if (fault_) { return *this; }
|
|
104
|
+
if (factor == 0 || value_ == 0) { value_ = 0; return *this; }
|
|
105
|
+
// Pre-check via absolute bounds. |value| > Max / |factor| => overflow.
|
|
106
|
+
// (Also catches the value==Min && factor==-1 case since |Min| > Max.)
|
|
107
|
+
// absWithoutUB: -(kMin) is UB, so compute |kMin| as -(kMin+1) + (-1) = kMax... no,
|
|
108
|
+
// |kMin| is kMax+1 which is NOT representable. The check absValue > kMax/absFactor
|
|
109
|
+
// still fires for value==kMin because absValue (computed without UB) exceeds any
|
|
110
|
+
// representable positive value when factor==-1. We compute |x| without UB below.
|
|
111
|
+
const T absValue = (value_ < 0) ? static_cast<T>(-(value_ + 1)) + (-1) : value_;
|
|
112
|
+
const T absFactor = (factor < 0) ? static_cast<T>(-(factor + 1)) + (-1) : factor;
|
|
113
|
+
if (absValue > kMax / absFactor) {
|
|
114
|
+
fault_ = true;
|
|
115
|
+
return *this;
|
|
116
|
+
}
|
|
117
|
+
value_ = static_cast<T>(value_ * factor);
|
|
118
|
+
return *this;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Named divide (not div) to avoid the cuttlefish reserved-name escaper
|
|
122
|
+
// renaming .div( to .div_( because div() is a C stdlib (<cstdlib>) name.
|
|
123
|
+
SafeInt<T>& divide(T d) noexcept {
|
|
124
|
+
if (fault_) { return *this; }
|
|
125
|
+
if (d == 0) { fault_ = true; return *this; }
|
|
126
|
+
// INT_MIN / -1 overflows.
|
|
127
|
+
if (value_ == kMin && d == static_cast<T>(-1)) { fault_ = true; return *this; }
|
|
128
|
+
value_ = static_cast<T>(value_ / d);
|
|
129
|
+
return *this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
SafeInt<T>& mod(T d) noexcept {
|
|
133
|
+
if (fault_) { return *this; }
|
|
134
|
+
if (d == 0) { fault_ = true; return *this; }
|
|
135
|
+
if (value_ == kMin && d == static_cast<T>(-1)) { value_ = 0; return *this; }
|
|
136
|
+
value_ = static_cast<T>(value_ % d);
|
|
137
|
+
return *this;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
SafeInt<T>& negate() noexcept {
|
|
141
|
+
if (fault_) { return *this; }
|
|
142
|
+
if (value_ == kMin) { fault_ = true; return *this; }
|
|
143
|
+
value_ = static_cast<T>(-value_);
|
|
144
|
+
return *this;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Named absValue (not abs) to avoid colliding with Arduino's abs() macro
|
|
148
|
+
// (Arduino.h #defines abs(x)), which would mangle the method declaration on
|
|
149
|
+
// AVR. Same caution for any future method whose name matches an Arduino core
|
|
150
|
+
// macro (min/max/round/...).
|
|
151
|
+
SafeInt<T>& absValue() noexcept {
|
|
152
|
+
if (fault_) { return *this; }
|
|
153
|
+
if (value_ == kMin) { fault_ = true; return *this; }
|
|
154
|
+
if (value_ < 0) { value_ = static_cast<T>(-value_); }
|
|
155
|
+
return *this;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
[[nodiscard]] constexpr T get() const noexcept { return value_; }
|
|
159
|
+
[[nodiscard]] bool hasFault() const noexcept { return fault_; }
|
|
160
|
+
[[nodiscard]] bool valid() const noexcept { return !fault_; }
|
|
161
|
+
|
|
162
|
+
void reset(T newValue) noexcept { value_ = newValue; fault_ = false; }
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
#endif // __TC_SAFE_INT_DEFINED
|
|
166
|
+
`.trim()],
|
|
167
|
+
shimMacros: [],
|
|
168
|
+
dependencies: [],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Returns the C++ source for the __tc_safe_traits block. Idempotent via the
|
|
2
|
+
* __TC_SAFE_TRAITS_DEFINED guard, so emitting it from both the SafeInt and
|
|
3
|
+
* SafeVariable polyfills is harmless (the second include is a no-op). */
|
|
4
|
+
export declare function emitSafeTraits(): string;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Hand-rolled C++ type traits for the safety polyfills.
|
|
2
|
+
//
|
|
3
|
+
// AVR's avr-gcc ships neither <type_traits> nor <limits>. The SafeInt and
|
|
4
|
+
// SafeVariable polyfills need is_integral / is_signed / is_same for their
|
|
5
|
+
// static_asserts, but must not include <type_traits>. This helper returns a
|
|
6
|
+
// self-contained C++14 block (no includes) that defines a __tc_safe_traits
|
|
7
|
+
// namespace with exactly the traits the polyfills use.
|
|
8
|
+
//
|
|
9
|
+
// SPECIALIZATION DISCIPLINE (avoids redefinition errors):
|
|
10
|
+
// On AVR, the fixed-width typedefs alias the built-ins: int8_t == signed char,
|
|
11
|
+
// int16_t == short, int32_t == long (int is 16-bit on AVR). Specializing for
|
|
12
|
+
// BOTH a typedef and its underlying built-in is a redefinition error. So:
|
|
13
|
+
// - is_integral / is_signed specialize the BUILT-IN types only (signed char,
|
|
14
|
+
// short, int, long, long long, unsigned variants, char, bool). A lookup
|
|
15
|
+
// via a typedef (is_integral<int32_t>) resolves to the built-in
|
|
16
|
+
// specialization automatically because the typedef names the same type.
|
|
17
|
+
// - bounds specializes the FIXED-WIDTH typedefs only (int8_t/int16_t/
|
|
18
|
+
// int32_t/int64_t). Each typedef maps to exactly one specialization, and
|
|
19
|
+
// the bounds values match the typedef's width (not the host 'int' width).
|
|
20
|
+
/** Returns the C++ source for the __tc_safe_traits block. Idempotent via the
|
|
21
|
+
* __TC_SAFE_TRAITS_DEFINED guard, so emitting it from both the SafeInt and
|
|
22
|
+
* SafeVariable polyfills is harmless (the second include is a no-op). */
|
|
23
|
+
export function emitSafeTraits() {
|
|
24
|
+
return `
|
|
25
|
+
#ifndef __TC_SAFE_TRAITS_DEFINED
|
|
26
|
+
#define __TC_SAFE_TRAITS_DEFINED
|
|
27
|
+
|
|
28
|
+
// No #include here: the integer types come transitively from <Arduino.h> on
|
|
29
|
+
// embedded targets (which pulls <stdint.h>) and from the test harness's own
|
|
30
|
+
// includes on native. This mirrors the other safety polyfills (mode-table,
|
|
31
|
+
// vote) which use uint32_t with no explicit include.
|
|
32
|
+
|
|
33
|
+
namespace __tc_safe_traits {
|
|
34
|
+
|
|
35
|
+
// is_integral<T>: specialized on canonical built-in integer types only.
|
|
36
|
+
// Lookups via fixed-width typedefs (int8_t/int32_t/etc.) resolve to these
|
|
37
|
+
// because each typedef names the same type as its underlying built-in.
|
|
38
|
+
template <typename T> struct is_integral { static constexpr bool value = false; };
|
|
39
|
+
template <> struct is_integral<bool> { static constexpr bool value = true; };
|
|
40
|
+
template <> struct is_integral<char> { static constexpr bool value = true; };
|
|
41
|
+
template <> struct is_integral<signed char> { static constexpr bool value = true; };
|
|
42
|
+
template <> struct is_integral<unsigned char> { static constexpr bool value = true; };
|
|
43
|
+
template <> struct is_integral<short> { static constexpr bool value = true; };
|
|
44
|
+
template <> struct is_integral<unsigned short> { static constexpr bool value = true; };
|
|
45
|
+
template <> struct is_integral<int> { static constexpr bool value = true; };
|
|
46
|
+
template <> struct is_integral<unsigned int> { static constexpr bool value = true; };
|
|
47
|
+
template <> struct is_integral<long> { static constexpr bool value = true; };
|
|
48
|
+
template <> struct is_integral<unsigned long> { static constexpr bool value = true; };
|
|
49
|
+
template <> struct is_integral<long long> { static constexpr bool value = true; };
|
|
50
|
+
template <> struct is_integral<unsigned long long> { static constexpr bool value = true; };
|
|
51
|
+
|
|
52
|
+
// is_signed<T>: specialized on canonical signed built-in integer types only.
|
|
53
|
+
template <typename T> struct is_signed { static constexpr bool value = false; };
|
|
54
|
+
template <> struct is_signed<signed char> { static constexpr bool value = true; };
|
|
55
|
+
template <> struct is_signed<short> { static constexpr bool value = true; };
|
|
56
|
+
template <> struct is_signed<int> { static constexpr bool value = true; };
|
|
57
|
+
template <> struct is_signed<long> { static constexpr bool value = true; };
|
|
58
|
+
template <> struct is_signed<long long> { static constexpr bool value = true; };
|
|
59
|
+
|
|
60
|
+
// is_same<T,U>: standard two-type trait.
|
|
61
|
+
template <typename T, typename U> struct is_same { static constexpr bool value = false; };
|
|
62
|
+
template <typename T> struct is_same<T, T> { static constexpr bool value = true; };
|
|
63
|
+
|
|
64
|
+
// bounds<T>: per-fixed-width min/max via literals + static_cast (no <limits>).
|
|
65
|
+
// Specialized on the FIXED-WIDTH typedefs only. Each typedef has a unique
|
|
66
|
+
// specialization whose bounds match that typedef's width (independent of the
|
|
67
|
+
// host 'int' width — critical because AVR's int is 16-bit while ESP32/native
|
|
68
|
+
// is 32-bit). int64_t is guarded because some freestanding toolchains lack it.
|
|
69
|
+
template <typename T> struct bounds;
|
|
70
|
+
template <> struct bounds<int8_t> {
|
|
71
|
+
static constexpr int8_t kMin = static_cast<int8_t>(static_cast<uint8_t>(0x80u));
|
|
72
|
+
static constexpr int8_t kMax = static_cast<int8_t>(0x7Fu);
|
|
73
|
+
};
|
|
74
|
+
template <> struct bounds<int16_t> {
|
|
75
|
+
static constexpr int16_t kMin = static_cast<int16_t>(static_cast<uint16_t>(0x8000u));
|
|
76
|
+
static constexpr int16_t kMax = static_cast<int16_t>(0x7FFFu);
|
|
77
|
+
};
|
|
78
|
+
template <> struct bounds<int32_t> {
|
|
79
|
+
static constexpr int32_t kMin = static_cast<int32_t>(static_cast<uint32_t>(0x80000000u));
|
|
80
|
+
static constexpr int32_t kMax = static_cast<int32_t>(0x7FFFFFFFu);
|
|
81
|
+
};
|
|
82
|
+
#if defined(__INT64_TYPE__)
|
|
83
|
+
template <> struct bounds<__INT64_TYPE__> {
|
|
84
|
+
// Use unsigned-long-long literals (standard 'ull' suffix) and cast — the
|
|
85
|
+
// 'ill' signed suffix is a GNU extension needing -fext-numeric-literals.
|
|
86
|
+
static constexpr __INT64_TYPE__ kMin = static_cast<__INT64_TYPE__>(static_cast<unsigned long long>(0x8000000000000000ull));
|
|
87
|
+
static constexpr __INT64_TYPE__ kMax = static_cast<__INT64_TYPE__>(static_cast<unsigned long long>(0x7FFFFFFFFFFFFFFFull));
|
|
88
|
+
};
|
|
89
|
+
#endif
|
|
90
|
+
|
|
91
|
+
} // namespace __tc_safe_traits
|
|
92
|
+
|
|
93
|
+
#endif // __TC_SAFE_TRAITS_DEFINED
|
|
94
|
+
`.trim();
|
|
95
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { RuntimePolyfillIR } from "../../api/index.js";
|
|
2
|
+
/** SafeVariable polyfill: 3-replica TMR with per-replica inversion for
|
|
3
|
+
* integral types, and plain 3-copy TMR for float/double.
|
|
4
|
+
*
|
|
5
|
+
* Combines TMR (triple modular redundancy) with inverted-redundancy for
|
|
6
|
+
* integral types: three replicas of the value, each stored alongside its
|
|
7
|
+
* bitwise inverse. On read, each replica is individually validated (XOR
|
|
8
|
+
* check), then the valid replicas are majority-voted. This gives both
|
|
9
|
+
* detection AND correction:
|
|
10
|
+
*
|
|
11
|
+
* - A single-bit SEU in any replica's value or inverse breaks that
|
|
12
|
+
* replica's XOR invariant → the corrupted replica is excluded from
|
|
13
|
+
* the vote, and the good replicas correct it.
|
|
14
|
+
* - If two replicas agree (majority), the value is returned with
|
|
15
|
+
* confidence. The corrupted replica is silently repaired on the next
|
|
16
|
+
* set().
|
|
17
|
+
* - For float/double, replicas are stored as plain copies (no inversion
|
|
18
|
+
* possible), and majority vote still corrects single-replica corruption.
|
|
19
|
+
*
|
|
20
|
+
* Fault signaling: hasFault() returns true iff the last get() found ZERO
|
|
21
|
+
* valid replicas (triple corruption). Callers should check hasFault() after
|
|
22
|
+
* get() on safety-critical paths. set() clears the fault flag.
|
|
23
|
+
*
|
|
24
|
+
* Memory cost: 3× T (same as plain TMR). The inversion is per-replica and
|
|
25
|
+
* does not add copies beyond the three TMR replicas.
|
|
26
|
+
*
|
|
27
|
+
* Arithmetic T only — a static_assert rejects non-arithmetic types (notably
|
|
28
|
+
* std::string) and bool (for which bitwise inversion is ill-defined) at
|
|
29
|
+
* compile time. float and double have explicit specializations.
|
|
30
|
+
*
|
|
31
|
+
* AUTOSAR C++14 compliance:
|
|
32
|
+
* - noexcept on all methods (A15-0-2)
|
|
33
|
+
* - [[nodiscard]] on get/valid/hasFault (A0-1-1)
|
|
34
|
+
* - constexpr constructors/methods
|
|
35
|
+
* - no malloc/new (A18-5-8/A18-5-10)
|
|
36
|
+
* - no C-style casts (M5-0-7)
|
|
37
|
+
* - fixed-width types via template parameter (A3-9-1)
|
|
38
|
+
*/
|
|
39
|
+
export declare function safeVariablePolyfill(): RuntimePolyfillIR;
|