- Swift ABI: tagged pointers, garbage-input abort path, ObjC bridging - C++ fuzz: libFuzzer dlopen coverage limits, AFL++ QEMU mode, vtable seeding - Cross-language IR: CodeQL/Infer/Joern patterns, Swift SIL gaps in fold IR - MIR verification: Kani/Prusti/Creusot approaches, BorrowTracker wiring
2.8 KiB
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
- Add
SwitchEnumkind tojson_keysandRustExprNode - Wire
encodeRustIr→encodeSwiftIr: rename or generalize the encoder to accept language-agnostic node trees - Swift-specific observer hooks:
onOptionalUnwrap,onProtocolDispatch - 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.