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;
29
30use super::error::CodeGenError;
31use std::collections::HashMap;
32use std::fmt::Write as _;
33use std::sync::LazyLock;
34
35/// A runtime function declaration for LLVM IR.
36pub struct RuntimeDecl {
37    /// LLVM declaration string (e.g., "declare ptr @patch_seq_add(ptr)")
38    pub decl: &'static str,
39    /// Optional category comment (e.g., "; Stack operations")
40    pub category: Option<&'static str>,
41}
42
43/// All runtime function declarations, assembled in IR-emission order.
44pub static RUNTIME_DECLARATIONS: LazyLock<Vec<&'static RuntimeDecl>> = LazyLock::new(|| {
45    let slices: &[&[RuntimeDecl]] = &[
46        stdio::DECLS,
47        arith::DECLS,
48        stack::DECLS,
49        callable::DECLS,
50        closure::DECLS,
51        concurrency::DECLS,
52        args_exit::DECLS,
53        fs::DECLS,
54        collections::DECLS,
55        tcp::DECLS,
56        os::DECLS,
57        text::DECLS,
58        adt::DECLS,
59        float::DECLS,
60        test_time::DECLS,
61        misc::DECLS,
62    ];
63    slices.iter().flat_map(|s| s.iter()).collect()
64});
65
66/// Mapping from Seq word names to their C runtime symbol names.
67/// This centralizes all the name transformations in one place:
68/// - Symbolic operators (=, <, >) map to descriptive names (eq, lt, gt)
69/// - Hyphens become underscores for C compatibility
70/// - Special characters get escaped (?, +, ->)
71/// - Reserved words get suffixes (drop -> drop_op)
72pub static BUILTIN_SYMBOLS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
73    let slices: &[&[(&str, &str)]] = &[
74        stdio::SYMBOLS,
75        args_exit::SYMBOLS,
76        arith::SYMBOLS,
77        stack::SYMBOLS,
78        concurrency::SYMBOLS,
79        callable::SYMBOLS,
80        closure::SYMBOLS,
81        tcp::SYMBOLS,
82        os::SYMBOLS,
83        text::SYMBOLS,
84        misc::SYMBOLS,
85        adt::SYMBOLS,
86        fs::SYMBOLS,
87        collections::SYMBOLS,
88        float::SYMBOLS,
89        test_time::SYMBOLS,
90    ];
91    slices.iter().flat_map(|s| s.iter().copied()).collect()
92});
93
94/// Emit all runtime function declarations to the IR string.
95pub fn emit_runtime_decls(ir: &mut String) -> Result<(), CodeGenError> {
96    for decl in RUNTIME_DECLARATIONS.iter() {
97        if let Some(cat) = decl.category {
98            writeln!(ir, "{}", cat)?;
99        }
100        writeln!(ir, "{}", decl.decl)?;
101    }
102    writeln!(ir)?;
103    Ok(())
104}