Software Architecture#

This chapter describes the software architecture of the WRT system. The architecture is designed to meet the requirements specified in the Requirements section.

System Overview#

WRT is a WebAssembly runtime implementation with a focus on bounded execution, bare-metal support, and component model capabilities. The architecture is organized into several key subsystems:

Specification: System Component Diagram SPEC_001
links outgoing: REQ_001, REQ_003, REQ_014, REQ_018

WRT System Components

The WRT system is comprised of the following main components:

  1. Core Runtime - The foundational WebAssembly execution engine

  2. Component Model - The implementation of WebAssembly Component Model Preview 2

  3. WASI Interfaces - Platform-specific implementations of WASI APIs

  4. CLI (WRTD) - Command-line interface for running WebAssembly modules

Core Runtime Architecture#

The core runtime is responsible for executing WebAssembly instructions and managing the WebAssembly execution environment.

Specification: Core Runtime Execution Flow SPEC_006
links outgoing: REQ_001, REQ_003, REQ_007

WRT Execution Flow

The execution flow demonstrates the bounded execution model, showing how the WRTD CLI interacts with the Engine and how the fuel-based execution can be paused when fuel is exhausted.

Specification: Core Runtime Architecture SPEC_002
links outgoing: REQ_001, REQ_003, REQ_005, REQ_006, REQ_007
links incoming: IMPL_001, IMPL_002, IMPL_003, IMPL_004

The core runtime follows a stackless interpreter design that enables:

  • Bounded execution through fuel metering

  • Resumability after execution pauses

  • No-std compatibility for bare-metal environments

  • State serialization for migration between systems

Implementation: Engine Implementation IMPL_001
status: implemented
links outgoing: SPEC_002, REQ_001, REQ_003, REQ_007

The Engine struct is the central execution component that:

  1. Manages the WebAssembly state

  2. Tracks fuel consumption

  3. Provides execution control

  4. Contains statistics gathering capabilities

Key methods include: - set_fuel(amount) - Sets the fuel limit for bounded execution - execute(instance_idx, func_idx, args) - Executes a WebAssembly function - remaining_fuel() - Returns the remaining fuel after execution - stats() - Returns execution statistics

Implementation: Module Implementation IMPL_002
status: partial
links outgoing: SPEC_002, REQ_018

The Module struct encapsulates a WebAssembly module and provides:

  1. Binary parsing and validation

  2. Type checking

  3. Function table management

  4. Memory management

Key methods include: - load_from_binary(bytes) - Loads a WebAssembly binary - validate() - Validates the module structure and types - instantiate(engine) - Creates a new module instance

Implementation: Memory Implementation IMPL_003
status: implemented
links outgoing: SPEC_002, REQ_018

The Memory struct manages WebAssembly linear memory:

  1. Handles memory allocations and resizing

  2. Enforces memory access boundaries

  3. Provides safe read/write operations

Key methods include: - grow(pages) - Grows memory by the specified number of pages - size() - Returns the current memory size in pages - read/write(addr, data) - Safely reads/writes memory with bounds checking

Implementation: Stack Implementation IMPL_004
status: partial
links outgoing: SPEC_002, REQ_005

The Stack struct implements a stackless interpreter model:

  1. Stores the WebAssembly value stack

  2. Tracks control flow with labels

  3. Enables pausing and resuming execution at any point

This implementation enables bounded execution and future state migration.

Component Model Architecture#

The Component Model subsystem implements the WebAssembly Component Model Preview 2 specification.

Specification: Component Model Architecture SPEC_003
links outgoing: REQ_014, REQ_019, REQ_020
links incoming: IMPL_005, IMPL_006

The Component Model implementation provides:

  1. Component instantiation and linking

  2. Interface type conversion

  3. Resource type management

  4. Host function binding

Implementation: Component Implementation IMPL_005
status: partial
links outgoing: SPEC_003, REQ_014, REQ_019

The Component struct represents a WebAssembly component:

  1. Parses component binary format

  2. Manages component instances

  3. Handles interface binding

  4. Orchestrates resource lifetime

Key methods include: - load_from_binary(bytes) - Loads a component binary - instantiate(engine, imports) - Creates a new component instance - link(other_component) - Links two components together

Implementation: Interface Type Handling IMPL_006
status: partial
links outgoing: SPEC_003, REQ_014, REQ_019

Interface types are managed through:

  1. Type adapters for each interface type

  2. Conversion between host and component types

  3. Validation of type compatibility

The implementation handles all standard interface types including records, variants, enums, flags, and resources.

Logging Subsystem#

The logging subsystem implements the WASI logging API and provides platform-specific backends.

Specification: Logging Architecture SPEC_004
links outgoing: REQ_015, REQ_016
links incoming: IMPL_007

The logging architecture consists of:

  1. WASI logging component interface

  2. Host logging handler registration

  3. Platform-specific backends (planned)

  4. Log level filtering and routing

Logging Flow Sequence

The following sequence diagram illustrates how logging flows from a WebAssembly module through the runtime:

WRT Logging Flow

When a WebAssembly module calls a logging function, the following steps occur:

  1. WebAssembly module calls the WASI logging interface function (log, logTrace, etc.)

  2. The WASI logging interface implementation in WRT converts the call to an engine operation

  3. The StacklessEngine creates a LogOperation object with level, message, and optional component ID

  4. The operation is passed to the CallbackRegistry via handle_log()

  5. The CallbackRegistry invokes the registered log handler (if any)

  6. The host logging system (terminal, file, syslog, etc.) processes the log message

Implementation: Logging Implementation IMPL_007
status: implemented
links outgoing: SPEC_004, REQ_015

The logging implementation provides:

  1. Standard log levels (Trace, Debug, Info, Warn, Error, Critical)

  2. Registration of custom log handlers

  3. Default stderr fallback

  4. Component-specific context tracking

Key components:

  • LogLevel - Enum with standard log levels (Trace, Debug, Info, Warn, Error, Critical)

  • LogOperation - Struct containing level, message, and optional component ID

  • CallbackRegistry - Central registry for handling WebAssembly component operations

Key methods include: - register_log_handler(handler) - Registers a custom log handler - handle_log(operation) - Internal method to process log messages - LogOperation::with_component(level, message, component_id) - Creates a log operation with component context

CLI (WRTD) Architecture#

The WRTD command-line interface provides a user-friendly way to execute WebAssembly modules and components.

Specification: CLI Architecture SPEC_005
links outgoing: REQ_003, REQ_015
links incoming: IMPL_008

The CLI architecture includes:

  1. Command-line argument parsing

  2. Module loading and instantiation

  3. Execution control with fuel limits

  4. Statistics reporting

  5. Logging configuration

Implementation: CLI Implementation IMPL_008
status: implemented
links outgoing: SPEC_005, REQ_003, REQ_015

The WRTD CLI provides:

  1. WebAssembly file loading

  2. Optional function calling

  3. Fuel-bounded execution

  4. Execution statistics reporting

  5. Logging configuration and output

Command-line options include: - --call <function> - Function to call - --fuel <amount> - Fuel limit for bounded execution - --stats - Show execution statistics

Development Status#

The current implementation status of the WRT architecture is as follows:

ID

Title

Status

Links

IMPL_001

Engine Implementation

implemented

IMPL_002

Module Implementation

partial

IMPL_003

Memory Implementation

implemented

IMPL_004

Stack Implementation

partial

IMPL_005

Component Implementation

partial

IMPL_006

Interface Type Handling

partial

IMPL_007

Logging Implementation

implemented

IMPL_008

CLI Implementation

implemented

Architecture-Requirement Mapping#

The following diagram shows how the architectural components map to requirements:

@startuml

' Nodes definition 

node "<size:12>Specification</size>\n**System**\n**Component**\n**Diagram**\n<size:10>SPEC_001</size>" as SPEC_001 [[../architecture.html#SPEC_001]] #FEDCD2
node "<size:12>Specification</size>\n**Core Runtime**\n**Architecture**\n<size:10>SPEC_002</size>" as SPEC_002 [[../architecture.html#SPEC_002]] #FEDCD2
node "<size:12>Specification</size>\n**Component Model**\n**Architecture**\n<size:10>SPEC_003</size>" as SPEC_003 [[../architecture.html#SPEC_003]] #FEDCD2
node "<size:12>Specification</size>\n**Logging**\n**Architecture**\n<size:10>SPEC_004</size>" as SPEC_004 [[../architecture.html#SPEC_004]] #FEDCD2
node "<size:12>Specification</size>\n**CLI**\n**Architecture**\n<size:10>SPEC_005</size>" as SPEC_005 [[../architecture.html#SPEC_005]] #FEDCD2
node "<size:12>Specification</size>\n**Core Runtime**\n**Execution Flow**\n<size:10>SPEC_006</size>" as SPEC_006 [[../architecture.html#SPEC_006]] #FEDCD2
node "<size:12>Implementation</size>\n**Engine**\n**Implementation**\n<size:10>IMPL_001</size>" as IMPL_001 [[../architecture.html#IMPL_001]] #DF744A
node "<size:12>Implementation</size>\n**Module**\n**Implementation**\n<size:10>IMPL_002</size>" as IMPL_002 [[../architecture.html#IMPL_002]] #DF744A
node "<size:12>Implementation</size>\n**Memory**\n**Implementation**\n<size:10>IMPL_003</size>" as IMPL_003 [[../architecture.html#IMPL_003]] #DF744A
node "<size:12>Implementation</size>\n**Stack**\n**Implementation**\n<size:10>IMPL_004</size>" as IMPL_004 [[../architecture.html#IMPL_004]] #DF744A
node "<size:12>Implementation</size>\n**Component**\n**Implementation**\n<size:10>IMPL_005</size>" as IMPL_005 [[../architecture.html#IMPL_005]] #DF744A
node "<size:12>Implementation</size>\n**Interface Type**\n**Handling**\n<size:10>IMPL_006</size>" as IMPL_006 [[../architecture.html#IMPL_006]] #DF744A
node "<size:12>Implementation</size>\n**Logging**\n**Implementation**\n<size:10>IMPL_007</size>" as IMPL_007 [[../architecture.html#IMPL_007]] #DF744A
node "<size:12>Implementation</size>\n**CLI**\n**Implementation**\n<size:10>IMPL_008</size>" as IMPL_008 [[../architecture.html#IMPL_008]] #DF744A
node "<size:12>Requirement</size>\n**Resumable**\n**Interpreter**\n<size:10>REQ_001</size>" as REQ_001 [[../requirements.html#REQ_001]] #BFD8D2
node "<size:12>Requirement</size>\n**Bounded**\n**Execution**\n<size:10>REQ_003</size>" as REQ_003 [[../requirements.html#REQ_003]] #BFD8D2
node "<size:12>Requirement</size>\n**Stackless**\n**Implementation**\n<size:10>REQ_005</size>" as REQ_005 [[../requirements.html#REQ_005]] #BFD8D2
node "<size:12>Requirement</size>\n**No Standard**\n**Library**\n<size:10>REQ_006</size>" as REQ_006 [[../requirements.html#REQ_006]] #BFD8D2
node "<size:12>Requirement</size>\n**Fuel Mechanism**\n<size:10>REQ_007</size>" as REQ_007 [[../requirements.html#REQ_007]] #BFD8D2
node "<size:12>Requirement</size>\n**WebAssembly**\n**Component Model**\n**Support**\n<size:10>REQ_014</size>" as REQ_014 [[../requirements.html#REQ_014]] #BFD8D2
node "<size:12>Requirement</size>\n**WASI Logging**\n**Support**\n<size:10>REQ_015</size>" as REQ_015 [[../requirements.html#REQ_015]] #BFD8D2
node "<size:12>Requirement</size>\n**Platform-**\n**Specific**\n**Logging**\n<size:10>REQ_016</size>" as REQ_016 [[../requirements.html#REQ_016]] #BFD8D2
node "<size:12>Requirement</size>\n**WebAssembly**\n**Core**\n**Implementation**\n<size:10>REQ_018</size>" as REQ_018 [[../requirements.html#REQ_018]] #BFD8D2
node "<size:12>Requirement</size>\n**Component Model**\n**Implementation**\n<size:10>REQ_019</size>" as REQ_019 [[../requirements.html#REQ_019]] #BFD8D2
node "<size:12>Requirement</size>\n**Component Model**\n**Tools**\n<size:10>REQ_020</size>" as REQ_020 [[../requirements.html#REQ_020]] #BFD8D2

' Connection definition 

SPEC_001 --> REQ_001
SPEC_001 --> REQ_003
SPEC_001 --> REQ_014
SPEC_001 --> REQ_018
SPEC_002 --> REQ_001
SPEC_002 --> REQ_003
SPEC_002 --> REQ_005
SPEC_002 --> REQ_006
SPEC_002 --> REQ_007
SPEC_003 --> REQ_014
SPEC_003 --> REQ_019
SPEC_003 --> REQ_020
SPEC_004 --> REQ_015
SPEC_004 --> REQ_016
SPEC_005 --> REQ_003
SPEC_005 --> REQ_015
SPEC_006 --> REQ_001
SPEC_006 --> REQ_003
SPEC_006 --> REQ_007
IMPL_001 --> SPEC_002
IMPL_001 --> REQ_001
IMPL_001 --> REQ_003
IMPL_001 --> REQ_007
IMPL_002 --> SPEC_002
IMPL_002 --> REQ_018
IMPL_003 --> SPEC_002
IMPL_003 --> REQ_018
IMPL_004 --> SPEC_002
IMPL_004 --> REQ_005
IMPL_005 --> SPEC_003
IMPL_005 --> REQ_014
IMPL_005 --> REQ_019
IMPL_006 --> SPEC_003
IMPL_006 --> REQ_014
IMPL_006 --> REQ_019
IMPL_007 --> SPEC_004
IMPL_007 --> REQ_015
IMPL_008 --> SPEC_005
IMPL_008 --> REQ_003
IMPL_008 --> REQ_015
REQ_005 --> REQ_001
REQ_007 --> REQ_003
REQ_016 --> REQ_015
REQ_018 --> REQ_014
REQ_019 --> REQ_014
REQ_020 --> REQ_014

@enduml