# Cross-Language IR Research for Multi-Language SAST > Generated 2026-05-28. Research on unifying fold's IR across C++, Rust, and Swift. ## Existing Multi-Language IR Approaches **CodeQL**: AST-based with DataFlow and TaintTracking libraries. Language-specific AST nodes with a shared property graph layer. C++, Java, Python, JavaScript, Go, Ruby, Swift all use the same query language but different AST schemas. **Semgrep**: Generic AST with language-specific patterns. The "generic" mode uses tree-sitter grammars — any language with a tree-sitter grammar is supported. Not a true IR — purely syntactic matching. **Infer (Facebook)**: SIL (Smallfoot Intermediate Language) — a simple imperative language with memory operations, function calls, and assume/assert. Clang frontend lowers C++ to SIL, which the analysis engines operate on. Single IR for all languages. **Joern (Code Property Graphs)**: AST + CFG + PDG combined into a graph database. Queries traverse edges across representation layers. Language-specific frontends produce a unified CPG. ## fold's Current IR `expr_json.hpp` defines `RustExprNode` with kinds: - IntegerLiteral, BoolLiteral, NullPtr, DeclRef - BinaryOp, Deref, ArraySubscript, UnaryOp, AddrOf - Cast, Call, Member, HeapNew, HeapDelete, StringLiteral, Conditional **Gap analysis for Swift SIL parity:** | Swift SIL Concept | fold IR Equivalent | Status | |-------------------|-------------------|--------| | `alloc_stack` | HeapNew (close) | Has struct — unused | | `load` / `store` | Deref + assignment | Partial | | `apply` (function call) | Call | Has struct, unused in Swift path | | `switch_enum` | Switch + discriminant | **Missing** | | `unchecked_ref_cast` | Cast (has kind) | **Not wired for Swift** | | `existential` type erasure | **Missing entirely** | Needs new node kind | | `protocol witness` dispatch | Indirect Call | **Not implemented** | | `optional` binding (`switch_enum_addr`) | Conditional + member | **Missing** | ## What's Needed for Swift IR 1. **Add `SwitchEnum` kind** to `json_keys` and `RustExprNode` 2. **Wire `encodeRustIr` → `encodeSwiftIr`**: rename or generalize the encoder to accept language-agnostic node trees 3. **Swift-specific observer hooks**: `onOptionalUnwrap`, `onProtocolDispatch` 4. **Map SWAN-parsed SIL to IR trees**: the SWAN parser produces structured SIL — need to tree-ify it for the encoder ## Recommended Approach **Phase 1**: Generalize `RustExprNode` → `IrExprNode` with a `language` discriminator. Add missing kinds (SwitchEnum, OptionalBind, ProtocolWitness). Wire Swift SWAN output into the same pipeline. **Phase 2**: Add Swift-specific SafetyObserver hooks. The observer interface already has language-agnostic overloads from the architecture expansion. **Phase 3**: Unify the Z3 encoder for all languages. The `encodeRustIr` function becomes `encodeIr` that dispatches by `language` field.