Skip to main content

seqc/codegen/
runtime.rs

1//! Runtime function declarations for LLVM IR.
2//!
3//! The full set of `declare` statements and Seq-word → C-symbol mappings is
4//! split across the sibling `runtime/` sub-modules by category. Each
5//! sub-module exposes two slices — `DECLS` and `SYMBOLS` — and this file
6//! concatenates them into the public `RUNTIME_DECLARATIONS` and
7//! `BUILTIN_SYMBOLS` statics used by the rest of codegen.
8//!
9//! Adding a new runtime entry point is a two-line edit to the appropriate
10//! sub-module: append a `RuntimeDecl { decl, category }` and, if the entry
11//! point is callable from Seq, append a `(seq-word, c-symbol)` pair.
12
13mod adt;
14mod args_exit;
15mod arith;
16mod callable;
17mod closure;
18mod collections;
19mod concurrency;
20mod float;
21mod fs;
22mod misc;
23mod os;
24mod stack;
25mod stdio;
26mod tcp;
27mod test_time;
28mod text;
29mod udp;
30
31use super::error::CodeGenError;
32use std::collections::HashMap;
33use std::fmt::Write as _;
34use std::sync::LazyLock;
35
36/// A runtime function declaration for LLVM IR.
37pub struct RuntimeDecl {
38    /// LLVM declaration string (e.g., "declare ptr @patch_seq_add(ptr)")
39    pub decl: &'static str,
40    /// Optional category comment (e.g., "; Stack operations")
41    pub category: Option<&'static str>,
42}
43
44/// All runtime function declarations, assembled in IR-emission order.
45pub static RUNTIME_DECLARATIONS: LazyLock<Vec<&'static RuntimeDecl>> = LazyLock::new(|| {
46    let slices: &[&[RuntimeDecl]] = &[
47        stdio::DECLS,
48        arith::DECLS,
49        stack::DECLS,
50        callable::DECLS,
51        closure::DECLS,
52        concurrency::DECLS,
53        args_exit::DECLS,
54        fs::DECLS,
55        collections::DECLS,
56        tcp::DECLS,
57        udp::DECLS,
58        os::DECLS,
59        text::DECLS,
60        adt::DECLS,
61        float::DECLS,
62        test_time::DECLS,
63        misc::DECLS,
64    ];
65    slices.iter().flat_map(|s| s.iter()).collect()
66});
67
68/// Mapping from Seq word names to their C runtime symbol names.
69/// This centralizes all the name transformations in one place:
70/// - Symbolic operators (=, <, >) map to descriptive names (eq, lt, gt)
71/// - Hyphens become underscores for C compatibility
72/// - Special characters get escaped (?, +, ->)
73/// - Reserved words get suffixes (drop -> drop_op)
74pub static BUILTIN_SYMBOLS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
75    let slices: &[&[(&str, &str)]] = &[
76        stdio::SYMBOLS,
77        args_exit::SYMBOLS,
78        arith::SYMBOLS,
79        stack::SYMBOLS,
80        concurrency::SYMBOLS,
81        callable::SYMBOLS,
82        closure::SYMBOLS,
83        tcp::SYMBOLS,
84        udp::SYMBOLS,
85        os::SYMBOLS,
86        text::SYMBOLS,
87        misc::SYMBOLS,
88        adt::SYMBOLS,
89        fs::SYMBOLS,
90        collections::SYMBOLS,
91        float::SYMBOLS,
92        test_time::SYMBOLS,
93    ];
94    slices.iter().flat_map(|s| s.iter().copied()).collect()
95});
96
97/// Emit all runtime function declarations to the IR string.
98pub fn emit_runtime_decls(ir: &mut String) -> Result<(), CodeGenError> {
99    for decl in RUNTIME_DECLARATIONS.iter() {
100        if let Some(cat) = decl.category {
101            writeln!(ir, "{}", cat)?;
102        }
103        writeln!(ir, "{}", decl.decl)?;
104    }
105    writeln!(ir)?;
106    Ok(())
107}