Skip to content

Latest commit

 

History

History
1135 lines (898 loc) · 39.6 KB

File metadata and controls

1135 lines (898 loc) · 39.6 KB

Synth Architecture Overview

Project: Synth - WebAssembly Component Synthesizer for Embedded Systems Version: 0.2.0 Last Updated: 2026-02-09 Status: Active Development


0. Current Implementation Status

This section reflects what is actually implemented as of February 2026. The remaining sections describe the full architectural vision.

What Works End-to-End

Command Description
synth compile input.wat -o output.elf --cortex-m Single-function WASM to ARM Cortex-M ELF
synth compile input.wat --all-exports --cortex-m -o out.elf Multi-function compilation
synth compile --demo add --verify Compile + Z3 formal verification
synth verify input.wat output.elf Standalone translation validation
synth backends List available backends with capabilities
synth compile --backend arm|w2c2 Backend selection (ARM functional, others stub)
synth disasm output.elf Disassemble generated ELF

Multi-Backend Architecture (Completed)

                          synth-core
                     ┌────────┴────────┐
                     │  Backend trait   │
                     │  BackendRegistry │
                     └────────┬────────┘
                              │
              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
         synth-backend   backend-awsm    backend-wasker
         (ARM, active)   (stub)          (stub)

All backends implement Backend::compile_function() and Backend::compile_module(). The ARM backend is fully functional; aWsm and wasker are stubs.

Verification Tiers

  1. Rule-level (ASIL D): Z3 SMT proves each synthesis rule (WASM op → ARM sequence) is semantically equivalent. 151/151 core ops have rules + unit tests; comparison ops (CMP+SetCond) verified via ArmSequence patterns.
  2. Binary-level (ASIL B): synth verify disassembles generated ELF and validates against WASM source.

Key Metrics

  • 18 crates, ~45K lines of Rust
  • 496+ tests (unit + Z3 verification + WAST integration + Renode emulation)
  • 55+ Renode emulation tests pass (ARM Cortex-M4, via Bazel rules_renode)
  • 151/151 WASM Core 1.0 ops have synthesis rules

Testing Infrastructure

                    ┌─────────────┐
                    │ tests/wast/ │   22 WAST files
                    └──────┬──────┘
                           │  synth-test generate
                           ▼
                    ┌─────────────┐
                    │ .robot files│   Robot Framework
                    └──────┬──────┘
                           │  bazel test (rules_renode)
                           ▼
                    ┌─────────────┐
                    │   Renode    │   ARM Cortex-M4 emulation
                    └─────────────┘

1. Architectural Vision

1.1 Core Concept: Synthesis vs. Compilation

Synth is a synthesizer, not just a compiler. The distinction is critical:

Traditional Compiler:

Source → Parse → Optimize → Generate → Machine Code
(deterministic transformations)

Synth Synthesizer:

WebAssembly Components → Analyze → Synthesize Optimal Implementation → Verify → Native Code
(explores space of equivalent programs, proves correctness)

1.2 Architectural Principles

  1. Synthesis-First: Explore optimization space, extract provably optimal code
  2. Component-Aware: Whole-program view of component compositions
  3. Hardware-Integrated: Leverage target-specific features (MPU/PMP, SIMD, XIP)
  4. Formally-Verified: Mechanically prove synthesis correctness
  5. Safety-Qualified: Generate certification artifacts for safety-critical use

1.3 Analogy: VHDL Synthesis

VHDL Synthesis:
  High-Level Description (VHDL)
  → Synthesis Tool (optimizes for area/power/timing)
  → Gate-Level Netlist
  → Place & Route
  → Physical Layout (FPGA/ASIC)
  → Formal Equivalence Checking

Synth (Software Synthesis):
  High-Level Description (WebAssembly Components + WIT)
  → Synthesis Tool (optimizes for size/speed/power)
  → Intermediate Representation (optimized)
  → Target-Specific Lowering
  → Native Code (ARM/RISC-V)
  → Formal Translation Validation

2. High-Level Architecture

2.1 System Context

┌─────────────────────────────────────────────────────────────┐
│                   Development Environment                    │
│                                                               │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │  Rust    │  │    C     │  │   C++    │  │ Other... │   │
│  │ Compiler │  │ Compiler │  │ Compiler │  │ Language │   │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘   │
│       │             │              │             │          │
│       └─────────────┴──────────────┴─────────────┘          │
│                          │                                   │
│                    WebAssembly                               │
│                     Components                               │
│                          ↓                                   │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                                                        │  │
│  │               SYNTH SYNTHESIZER                        │  │
│  │                                                        │  │
│  │  Component Analysis → Optimization → Synthesis →      │  │
│  │  Target Lowering → Verification                       │  │
│  │                                                        │  │
│  └────────────────────┬───────────────────────────────────┘  │
│                       │                                       │
│                 Native Binary                                 │
│                       ↓                                       │
└─────────────────────────────────────────────────────────────┘
                        │
       ┌────────────────┴────────────────┐
       │                                  │
┌──────▼────────┐              ┌─────────▼────────┐
│  ARM Cortex-M │              │     RISC-V       │
│  Embedded     │              │   Embedded       │
│  Devices      │              │   Devices        │
└───────────────┘              └──────────────────┘

2.2 Major Components

┌──────────────────────────────────────────────────────────────┐
│                         SYNTH CORE                            │
├──────────────────────────────────────────────────────────────┤
│                                                               │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  FRONTEND: Component Model Parser & Validator          │  │
│  │  - Parse WebAssembly Component binaries                │  │
│  │  - Validate component structure                        │  │
│  │  - WIT interface processing                            │  │
│  │  - Build component dependency graph                    │  │
│  └───────────────────────┬────────────────────────────────┘  │
│                          │                                    │
│                          ↓                                    │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  ANALYSIS: Whole-Program Analysis                      │  │
│  │  - Component composition analysis                      │  │
│  │  - Memory layout analysis (multi-memory)               │  │
│  │  - Call graph construction                             │  │
│  │  - Data flow analysis                                  │  │
│  │  - Hardware capability detection                       │  │
│  └───────────────────────┬────────────────────────────────┘  │
│                          │                                    │
│                          ↓                                    │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  OPTIMIZATION: Synthesis Engine                        │  │
│  │  - E-graph construction (equality saturation)          │  │
│  │  - ISLE-based rewrite rules                            │  │
│  │  - Cross-component optimization                        │  │
│  │  - Memory layout optimization                          │  │
│  │  - Bounds check optimization                           │  │
│  └───────────────────────┬────────────────────────────────┘  │
│                          │                                    │
│                          ↓                                    │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  SYNTHESIS: Target-Specific Code Generation            │  │
│  │  - ISLE instruction selection                          │  │
│  │  - Register allocation (regalloc2)                     │  │
│  │  - Hardware protection mapping (MPU/PMP)               │  │
│  │  - XIP binary generation                               │  │
│  └───────────────────────┬────────────────────────────────┘  │
│                          │                                    │
│                          ↓                                    │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  VERIFICATION: Formal Proof & Validation               │  │
│  │  - Translation validation (SMT)                        │  │
│  │  - Memory safety proofs                                │  │
│  │  - CFI verification                                    │  │
│  │  - Component isolation proofs                          │  │
│  └───────────────────────┬────────────────────────────────┘  │
│                          │                                    │
│                          ↓                                    │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  BACKEND: Target Emission                              │  │
│  │  - ELF generation                                      │  │
│  │  - Raw binary generation                               │  │
│  │  - Debug info (DWARF)                                  │  │
│  │  - Certification artifacts                             │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                               │
└──────────────────────────────────────────────────────────────┘

3. Detailed Component Design

3.1 Frontend: Component Model Parser

Responsibilities:

  • Parse WebAssembly Component Model binary format
  • Validate component structure and types
  • Process WIT interface definitions
  • Build Abstract Syntax Tree (AST) representation

Architecture:

pub mod frontend {
    pub struct ComponentParser {
        wasm_parser: wasmparser::Parser,
        wit_parser: wit_parser::Interface,
    }

    pub struct ComponentAST {
        modules: Vec<CoreModule>,
        components: Vec<Component>,
        instances: Vec<ComponentInstance>,
        interfaces: HashMap<String, WITInterface>,
    }

    pub struct ValidationContext {
        type_checker: TypeChecker,
        capability_checker: CapabilityChecker,
    }
}

Key Dependencies:

  • wasmparser (Bytecode Alliance)
  • wit-parser (Bytecode Alliance)
  • wasm-tools (validation)

Input: WebAssembly Component binaries (.wasm), WIT files (.wit) Output: Validated ComponentAST

3.2 Analysis: Whole-Program Analysis

Responsibilities:

  • Construct component dependency graph
  • Analyze memory usage across components
  • Build call graph (with devirtualization opportunities)
  • Perform data flow analysis
  • Detect hardware capabilities

Architecture:

pub mod analysis {
    pub struct DependencyGraph {
        components: Vec<ComponentNode>,
        edges: Vec<DependencyEdge>,
    }

    pub struct MemoryLayout {
        linear_memories: Vec<MemoryRegion>,
        mpu_regions: Vec<MPURegion>,  // ARM
        pmp_entries: Vec<PMPEntry>,    // RISC-V
    }

    pub struct CallGraph {
        functions: HashMap<FunctionID, FunctionNode>,
        direct_calls: Vec<CallEdge>,
        indirect_calls: Vec<IndirectCallSite>,
        devirtualization_opportunities: Vec<DevirtualizationHint>,
    }

    pub struct HardwareCapabilities {
        target: TargetArch,
        has_mpu: bool,
        mpu_regions: u8,
        has_fpu: bool,
        simd_support: SIMDLevel,
        xip_capable: bool,
    }
}

Analyses Performed:

  1. Component Dependency Analysis

    • Shared-everything vs shared-nothing linking
    • Identify optimization boundaries
  2. Memory Layout Analysis

    • Total memory requirements
    • Multi-memory mapping to hardware regions
    • Stack size estimation
  3. Call Graph Construction

    • Direct calls (statically known targets)
    • Indirect calls (tables, dynamic dispatch)
    • Devirtualization opportunities
  4. Data Flow Analysis

    • Constant propagation candidates
    • Dead code identification
    • Inlining candidates

Output: AnalysisResults containing all analysis data

3.3 Optimization: Synthesis Engine

Responsibilities:

  • Construct e-graph of equivalent programs
  • Apply synthesis/rewrite rules (ISLE-based)
  • Explore optimization space via equality saturation
  • Extract optimal program from e-graph

Architecture:

pub mod optimization {
    use egg::{EGraph, Rewrite, Extractor};

    pub struct SynthesisEngine {
        egraph: EGraph<ComponentIR, ComponentAnalysis>,
        rules: Vec<Rewrite<ComponentIR, ComponentAnalysis>>,
    }

    pub struct ComponentIR {
        // E-graph representation of components
        nodes: Vec<ENode>,
        classes: Vec<EClass>,
    }

    pub struct ISLERules {
        optimization_rules: Vec<ISLERule>,
        target_lowering_rules: Vec<ISLERule>,
    }
}

Optimization Strategies:

1. Equality Saturation (E-Graphs):

Component IR → E-Graph Construction
             → Apply All Rewrite Rules
             → Saturation (fixed point)
             → Cost Model Extraction
             → Optimal Program

2. ISLE-Based Rewrites:

;; Example: Memory layout optimization
(rule (component_memory (mem_size s1) (mem_size s2))
  (if (and (aligned s1) (aligned s2))
    (merged_memory (+ s1 s2))))

;; Example: Devirtualization
(rule (indirect_call (known_target f) args)
  (direct_call f args))

;; Example: Bounds check optimization
(rule (bounds_check addr (static_mem size))
  (if (provably_in_bounds addr size)
    (checked_access addr)))  ;; Hardware check only

3. Cross-Component Optimization:

  • Inline across component boundaries (shared-everything)
  • Constant propagation through Canonical ABI
  • Dead code elimination of unused exports

4. Memory Optimization:

  • Merge compatible memories
  • Optimize for MPU/PMP alignment
  • Minimize total memory footprint

Output: Optimized ComponentIR ready for lowering

3.4 Synthesis: Target-Specific Code Generation

Responsibilities:

  • Lower optimized IR to target-specific instructions (ISLE)
  • Allocate registers (regalloc2)
  • Map memories to hardware protection regions
  • Generate XIP-capable binaries

Architecture:

pub mod synthesis {
    pub struct TargetSynthesizer {
        target: TargetDescriptor,
        isle_lowering: ISLELowering,
        reg_alloc: RegAllocator,
        hw_mapper: HardwareMapper,
    }

    pub enum TargetDescriptor {
        ARMCortexM {
            variant: CortexMVariant,
            has_fpu: bool,
            has_mve: bool,
            mpu_regions: u8,
        },
        RISCV {
            variant: RISCVVariant,
            extensions: Extensions,
            pmp_entries: u8,
        },
    }

    pub struct ISLELowering {
        rules: Vec<LoweringRule>,
        extractors: HashMap<String, Extractor>,
        constructors: HashMap<String, Constructor>,
    }
}

Synthesis Steps:

1. ISLE Instruction Selection:

;; ARM Cortex-M specific lowering
(rule (lower (iadd x y))
  (if (has_thumb2)
    (add_reg (to_reg x) (to_reg y))
    (add_reg_imm (to_reg x) (to_reg y))))

;; Memory access with MPU check
(rule (lower (load addr))
  (if (has_mpu)
    (load_with_mpu_check (map_to_region addr))
    (load_with_software_check addr)))

;; RISC-V compressed instructions
(rule (lower (iconst n))
  (if (and (has_rvc) (fits_in_ci n))
    (c_li n)        ;; 16-bit compressed
    (li n)))        ;; 32-bit standard

2. Register Allocation:

  • Use regalloc2 from Cranelift
  • Handle target-specific constraints (e.g., ARM R0-R3 for args)
  • Minimize spills for small register files (Cortex-M: 16 regs)

3. Hardware Protection Mapping:

ARM Cortex-M MPU:

pub struct MPUMapper {
    available_regions: u8,  // 8 or 16 depending on variant
}

impl MPUMapper {
    fn allocate_regions(&self, memories: &[Memory]) -> MPUConfig {
        // Map each WebAssembly memory to MPU region
        // Optimize for alignment (must be power-of-2 sized)
        // Generate configuration code
    }
}

RISC-V PMP:

pub struct PMPMapper {
    available_entries: u8,  // Up to 16
}

impl PMPMapper {
    fn allocate_entries(&self, memories: &[Memory]) -> PMPConfig {
        // Map memories to PMP entries
        // Configure for user-mode execution
        // Generate CSR configuration code
    }
}

4. XIP Binary Generation:

  • Position-independent code generation
  • Minimal relocations
  • Flash-friendly memory layout
  • Indirect function calls via tables

Output: Target-specific machine code with hardware configuration

3.5 Verification: Formal Proof & Validation

Responsibilities:

  • Translation validation using SMT solvers
  • Prove memory safety properties
  • Verify control-flow integrity
  • Check component isolation

Architecture:

pub mod verification {
    pub struct TranslationValidator {
        smt_solver: Z3Context,
        wasm_semantics: WasmSemantics,
        native_semantics: NativeSemantics,
    }

    pub struct MemorySafetyProver {
        bounds_checker: BoundsChecker,
        isolation_checker: IsolationChecker,
    }

    pub struct CFIVerifier {
        call_checker: CallTargetChecker,
        return_checker: ReturnChecker,
    }
}

Verification Approach:

1. Translation Validation (Per-Compilation):

For each synthesized function f:
  1. Encode WebAssembly semantics as SMT formula φ_wasm
  2. Encode native code semantics as SMT formula φ_native
  3. Query SMT solver: ∀inputs. φ_wasm ≡ φ_native
  4. If UNSAT: synthesis is correct
  5. If SAT: counterexample found → bug in synthesis

2. Memory Safety Proof:

Theorem (Bounds Safety):
  ∀ memory access addr in synthesized code:
    addr ∈ [memory.base, memory.base + memory.size)

Proof Strategy:
  - Instrument all memory accesses
  - Check bounds via SMT or runtime assertion
  - If hardware MPU/PMP: prove configuration correct

3. Component Isolation Proof:

Theorem (Isolation):
  ∀ components C1, C2 with separate memories M1, M2:
    Code in C1 cannot access M2 (except via Canonical ABI)

Proof Strategy:
  - Static analysis of memory accesses
  - Verify all accesses go through bounds checks
  - Prove MPU/PMP regions don't overlap

4. Control-Flow Integrity Verification:

Theorem (CFI):
  ∀ indirect call sites:
    target ∈ valid_function_table
    type_signature_matches(target, expected_signature)

Proof Strategy:
  - Verify type check inserted before every indirect call
  - Check table bounds
  - Prove function table immutable after initialization

Output: Verification results, proofs (for Coq), or SMT traces

3.6 Backend: Target Emission

Responsibilities:

  • Generate final binary formats
  • Emit debug information
  • Create certification artifacts

Architecture:

pub mod backend {
    pub struct BinaryEmitter {
        format: BinaryFormat,
        debug_info: DebugInfoGenerator,
    }

    pub enum BinaryFormat {
        ELF { arch: Architecture },
        RawBinary,
        IntelHex,
    }

    pub struct DebugInfoGenerator {
        dwarf_gen: DwarfGenerator,
        source_map: SourceMap,
    }

    pub struct CertificationArtifactGenerator {
        traceability: TraceabilityMatrix,
        verification_evidence: VerificationEvidence,
    }
}

Generated Outputs:

  1. Binary Files:

    • ELF (with sections for text, data, bss)
    • Raw binary (for direct flash programming)
    • Intel HEX or Motorola S-Record
  2. Debug Information:

    • DWARF debug info
    • Source-to-binary mapping
    • Variable locations
  3. Certification Artifacts:

    • Requirements traceability matrix
    • Verification evidence (SMT traces, proofs)
    • Test coverage reports
    • Static analysis results

4. Data Flow Through Architecture

4.1 End-to-End Synthesis Flow

Input: WebAssembly Components (.wasm) + WIT Interfaces (.wit) + Target Config

┌──────────────────────────────────────────────────────────┐
│ 1. FRONTEND: Parse & Validate                            │
│    - Parse component binaries                            │
│    - Validate structure and types                        │
│    - Build ComponentAST                                  │
│    Output: Validated ComponentAST                        │
└────────────────────┬─────────────────────────────────────┘
                     │
                     ↓
┌──────────────────────────────────────────────────────────┐
│ 2. ANALYSIS: Whole-Program Analysis                      │
│    - Build dependency graph                              │
│    - Analyze memory layout                               │
│    - Construct call graph                                │
│    - Detect hardware capabilities                        │
│    Output: AnalysisResults                               │
└────────────────────┬─────────────────────────────────────┘
                     │
                     ↓
┌──────────────────────────────────────────────────────────┐
│ 3. OPTIMIZATION: E-Graph Synthesis                       │
│    - Construct e-graph from ComponentAST                 │
│    - Apply ISLE rewrite rules                            │
│    - Saturate (run until fixed point)                    │
│    - Extract optimal program via cost model              │
│    Output: Optimized ComponentIR                         │
└────────────────────┬─────────────────────────────────────┘
                     │
                     ↓
┌──────────────────────────────────────────────────────────┐
│ 4. SYNTHESIS: Target-Specific Lowering                   │
│    - ISLE instruction selection                          │
│    - Register allocation (regalloc2)                     │
│    - Map memories to MPU/PMP regions                     │
│    - Generate hardware config code                       │
│    Output: Target-specific machine code                  │
└────────────────────┬─────────────────────────────────────┘
                     │
                     ↓
┌──────────────────────────────────────────────────────────┐
│ 5. VERIFICATION: Formal Validation                       │
│    - SMT-based translation validation                    │
│    - Memory safety proofs                                │
│    - CFI verification                                    │
│    - Isolation proofs                                    │
│    Output: Verification results + proofs                 │
└────────────────────┬─────────────────────────────────────┘
                     │
                     ↓
┌──────────────────────────────────────────────────────────┐
│ 6. BACKEND: Binary Emission                              │
│    - Generate ELF/binary                                 │
│    - Emit debug info (DWARF)                             │
│    - Create certification artifacts                      │
│    Output: Native binary + artifacts                     │
└──────────────────────────────────────────────────────────┘

Final Output:
  - Native binary (ELF/raw)
  - Debug information
  - Verification proofs
  - Certification artifacts

4.2 Example: Memory Access Synthesis

WebAssembly: (i32.load offset=4 align=2 (local.get $addr))

↓ FRONTEND: Parse
  Load { offset: 4, align: 2, addr: Local(0) }

↓ ANALYSIS: Memory Layout Analysis
  - Memory 0 mapped to MPU region 2 (0x20000000-0x20010000)
  - Access pattern: sequential reads
  - Alignment: 4-byte aligned

↓ OPTIMIZATION: E-Graph Synthesis
  - Combine offset into addressing mode
  - Recognize sequential pattern (potential for load-multiple)
  - Bounds check optimization: hardware MPU covers this region

↓ SYNTHESIS: ARM Cortex-M Lowering (ISLE)
  Rule: (load (+ base (const 4)))
    → ldr r0, [r1, #4]  ;; Offset in instruction, no bounds check needed

  Hardware config:
    MPU Region 2: 0x20000000, 64KB, Read/Write, User accessible

↓ VERIFICATION: Translation Validation
  SMT query:
    wasm_memory[addr + 4] ≡ native_memory[mpu_region_2_base + addr + 4]
    Result: UNSAT (semantics equivalent)

  Memory safety proof:
    addr + 4 < 0x10000 (within 64KB) → MPU allows access
    Proven correct

↓ BACKEND: Code Emission
  Generated ARM code:
    ldr r0, [r1, #4]  ; Load with offset

  MPU config code:
    MPU->RNR = 2;
    MPU->RBAR = 0x20000000;
    MPU->RASR = (SIZE_64KB | RW | USER);

5. Key Architectural Decisions

AD-001: Use of E-Graphs for Optimization

Decision: Use egg library for equality saturation

Rationale:

  • Solves phase-ordering problems
  • Explores all equivalent programs simultaneously
  • Provably optimal extraction
  • Production-ready Rust implementation

Alternatives Considered:

  • Traditional pass-based optimizer (rejected: phase-ordering issues)
  • Custom rewrite system (rejected: reinventing wheel)

Consequences:

  • Increased compilation time (acceptable for AOT)
  • Requires learning e-graph concepts
  • Better optimization results

AD-002: ISLE for Synthesis Rules

Decision: Use ISLE DSL for instruction lowering and rewrites

Rationale:

  • Declarative specification enables formal verification
  • Proven in Cranelift production use
  • Modular, testable rules
  • VeriISLE provides SMT-based verification

Alternatives Considered:

  • Hand-written Rust code (rejected: hard to verify, error-prone)
  • LLVM backend (rejected: too heavyweight, hard to customize)
  • Custom DSL (rejected: significant development cost)

Consequences:

  • Need to learn ISLE language
  • Dependency on Cranelift's ISLE compiler
  • Clear verification path

AD-003: Hardware-Assisted Bounds Checking

Decision: Map WebAssembly memories to MPU/PMP regions

Rationale:

  • Leverages existing hardware for sandboxing
  • Reduces performance overhead vs software checks
  • Enables formal verification of memory isolation
  • Natural fit for multi-memory proposal

Alternatives Considered:

  • Software-only bounds checks (rejected: performance overhead)
  • Virtual memory guard pages (rejected: not available on Cortex-M)
  • No bounds checking (rejected: loses WebAssembly guarantees)

Consequences:

  • Requires careful region allocation
  • Limited number of regions (8-16)
  • Need fallback for targets without MPU/PMP

AD-004: AOT-Only (No JIT)

Decision: Support AOT compilation only, no JIT

Rationale:

  • Embedded targets often prohibit dynamic code generation
  • Deterministic performance critical for real-time
  • Enables ahead-of-time formal verification
  • Simpler architecture

Alternatives Considered:

  • JIT compilation (rejected: security concerns, determinism issues)
  • Hybrid AOT+JIT (rejected: added complexity)

Consequences:

  • Longer build times acceptable
  • All code known at synthesis time
  • Easier verification

AD-005: Component Model as Primary Abstraction

Decision: Target WebAssembly Component Model, not core modules

Rationale:

  • Component Model provides structured composition
  • Multi-memory support for isolation
  • Canonical ABI for cross-language interop
  • Future-proof for WASI evolution

Alternatives Considered:

  • Core WebAssembly only (rejected: lacks composition features)
  • Custom module system (rejected: not standards-based)

Consequences:

  • Requires Component Model tooling (wasm-tools, etc.)
  • Smaller initial ecosystem vs core Wasm
  • Better long-term architecture

AD-006: Rust as Implementation Language

Decision: Implement Synth in Rust

Rationale:

  • Memory safety without garbage collection
  • Excellent WebAssembly tooling ecosystem (Bytecode Alliance)
  • Strong type system for correctness
  • Good performance

Alternatives Considered:

  • C++ (rejected: memory safety concerns)
  • OCaml (rejected: smaller embedded tooling ecosystem)
  • Zig (rejected: less mature, smaller ecosystem)

Consequences:

  • Learning curve for Rust
  • Compile times can be long
  • Excellent safety and correctness

6. Technology Stack

6.1 Core Dependencies

WebAssembly Tooling:

  • wasmparser 0.222 - Parse WASM binaries
  • wast 222.0 - WAST text format parsing (test infrastructure)
  • wat 1.222 - WAT to WASM binary conversion
  • wasm-tools - Validation and component manipulation
  • wit-parser, wit-component - Component Model support

Code Generation (custom — no LLVM/Cranelift dependency):

  • Custom ArmEncoder - ARM Thumb-2 machine code emission
  • Custom InstructionSelector - WASM→ARM lowering via pattern matching
  • Custom ElfBuilder - ELF32 binary generation
  • Custom VectorTable, ResetHandler - Cortex-M startup code

Verification:

  • z3 0.12 / z3-sys 0.8 - SMT solver for translation validation
  • Custom arm_semantics.rs (~3000 lines) - ARM instruction SMT encoding

6.2 Development Tools

Build Systems:

  • Cargo (primary: cargo test --workspace)
  • Bazel 8.x (Renode integration tests: bazel test //...)
  • rules_renode (PulseEngine fork with macOS support)

Testing Infrastructure:

  • 22 WAST files auto-generate Robot Framework tests
  • synth-test crate: WAST parser → Robot generator → Renode execution
  • Bazel hermetic Renode (no system install needed)

CI/CD:

  • GitHub Actions (cargo test, cargo clippy, Z3 verification)

7. Deployment Architecture

7.1 CLI Tool (Implemented)

synth compile <INPUT.wat> -o <OUTPUT.elf> [OPTIONS]
  --cortex-m              Generate complete Cortex-M binary (vector table + startup)
  --all-exports           Compile all exported functions
  --backend <NAME>        Select backend (arm, w2c2, awsm, wasker)
  --verify                Run Z3 formal verification after compilation
  --no-optimize           Skip optimization passes

synth verify <INPUT.wat> <OUTPUT.elf>
  Standalone translation validation via Z3 SMT

synth disasm <ELF>
  Disassemble and display generated ARM code

synth backends
  List available backends and their capabilities

synth parse <INPUT.wasm>
  Parse and analyze WASM module structure

7.2 Library API

use synth::{Synthesizer, TargetConfig, SynthesisOptions};

let config = TargetConfig::cortex_m4f()
    .with_mpu_regions(8)
    .with_xip(true);

let options = SynthesisOptions::default()
    .optimize_for_size()
    .enable_verification();

let synthesizer = Synthesizer::new(config, options)?;
let binary = synthesizer.synthesize_from_file("app.wasm")?;

binary.write_elf("output.elf")?;
binary.emit_artifacts("artifacts/")?;

7.3 Build System Integration

Cargo Integration (Rust):

[build-dependencies]
synth = "0.1"

[package.metadata.synth]
target = "thumbv7em-none-eabihf"
opt-level = "z"
verify = true

CMake Integration (C/C++):

find_package(Synth REQUIRED)

add_wasm_component(my_app
  SOURCES app.c
  WIT_INTERFACE interface.wit
  TARGET cortex-m4f
  OPTIMIZE_FOR size
)

synth_synthesize(my_app
  OUTPUT my_app.elf
  VERIFY ON
)

8. Scalability and Performance

8.1 Compilation Performance

Expected Performance:

  • Small components (<100KB): <1 second
  • Medium components (100KB-1MB): 1-10 seconds
  • Large components (>1MB): 10-60 seconds
  • With full verification: 2-10x slower

Optimization Strategies:

  • Parallel compilation of independent components
  • Incremental compilation (cache analysis results)
  • Lazy verification (only verify changed components)

8.2 Runtime Performance

Target Performance (vs hand-written native):

  • ≥80% for compute-intensive code
  • ≥85% for memory-intensive code
  • ≥90% for control-flow-heavy code

Key Optimizations:

  • Hardware-assisted bounds checking (near-zero overhead)
  • Devirtualization (eliminate indirect call overhead)
  • SIMD utilization (Helium on M55, RISC-V V extension)
  • XIP (no load-time overhead)

8.3 Memory Footprint

Code Size:

  • Target: <120% of equivalent native code
  • XIP reduces RAM requirements significantly

Runtime Memory:

  • No allocator required for synthesized code
  • Predictable stack usage (static analysis)
  • Minimal metadata overhead

9. Security Architecture

9.1 Input Validation

Threat: Malicious WebAssembly components

Mitigation:

  • Comprehensive validation before synthesis
  • Bounds on resource usage (memory, stack)
  • Reject invalid or malformed components

9.2 Synthesis Integrity

Threat: Bugs in synthesizer leading to unsafe code

Mitigation:

  • Translation validation (SMT-based)
  • Fuzzing with differential testing
  • Formal verification of critical paths
  • Continuous integration testing

9.3 Sandboxing Guarantees

Threat: Component escaping sandbox

Mitigation:

  • Hardware-enforced memory isolation (MPU/PMP)
  • Control-flow integrity verification
  • Component isolation proofs
  • Runtime trap handling

10. Future Extensions

10.1 Phase 2 Features

  • Additional Targets: Xtensa (ESP32), ARMv8-A (Cortex-A)
  • SIMD Optimization: Advanced auto-vectorization
  • Profiling Integration: Profile-guided optimization
  • Incremental Compilation: Faster rebuild times

10.2 Phase 3 Features

  • WebAssembly GC Support: Garbage collection proposal
  • WASI Preview 3: Async/await support
  • End-to-End Verification: Full mechanized proof in Coq
  • Safety Certification: ISO 26262 / IEC 62304 qualified tool

10.3 Phase 4 Features

  • Multi-Core Support: Parallel component execution
  • Dynamic Linking: Runtime component loading (with constraints)
  • Custom Instructions: Target-specific ISA extensions
  • Hardware Accelerators: Offload to DSPs, FPGAs

11. Success Metrics

11.1 Performance Metrics

  • ✓ Synthesis time <10s for typical component
  • ✓ Generated code ≥80% native performance
  • ✓ Code size <120% of native equivalent
  • ✓ Verification time <60s for typical component

11.2 Correctness Metrics

  • ✓ Pass 100% of WebAssembly Component Model test suite
  • ✓ Zero known correctness bugs in stable releases
  • ✓ >90% code coverage in test suite
  • ✓ Translation validation passes for all syntheses

11.3 Usability Metrics

  • ✓ <10 steps to synthesize first component
  • ✓ Clear error messages for all failures
  • ✓ Comprehensive documentation with examples
  • ✓ Integration with popular toolchains (Cargo, CMake)

Document Status: Draft v0.1 Next Steps: Review and refine, begin prototype implementation Approval Required: Technical Lead, Architecture Review Board