1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! Lowering errors: every unhandled AST shape must produce one of these,
//! never panic!/unimplemented!/a silent no-op.
use std::fmt;
#[derive(Debug, Clone)]
pub struct LoweringError {
pub message: String,
pub at: String,
}
impl LoweringError {
pub fn unsupported(what: &str, at: &str) -> Self {
Self {
message: format!("unsupported: {what}"),
at: at.into(),
}
}
pub fn unsupported_at(what: &str, sym: &sv_lang::Symbol) -> Self {
Self {
message: format!("unsupported: {what}"),
at: sym.hierarchical_path(),
}
}
}
impl fmt::Display for LoweringError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} (at {})", self.message, self.at)
}
}
impl std::error::Error for LoweringError {}
/// Task 4 (A2-part2; ledger CG-127, RT-003): every failure mode the AOT
/// backend (`crate::aot::AotBackend`, `crate::pipeline::compile_to_object`)
/// can hit -- a distinct type from [`LoweringError`] (which is specifically
/// "this AST shape has no lowering yet"): every `CodegenError` variant here
/// is instead about turning an ALREADY-lowered `Module` into a real,
/// loadable artifact (object emission, system-linker invocation, and the
/// post-link `dlopen`/`dlsym` probe `AotBackend::link` itself performs to
/// populate `AotKernelHandle`) -- never a silent guess, never a panic.
#[derive(Debug)]
pub enum CodegenError {
/// A plan failed to lower to LLVM IR at all (reuses [`LoweringError`]
/// unchanged -- `compile_to_object` hits this at the exact same call
/// site `build_pipeline` does, just wrapped in this crate's own AOT-path
/// error type).
Lowering(LoweringError),
/// `AotBackend::emit_object`: target-machine initialization/creation or
/// the `write_to_file` emission step itself failed.
ObjectEmission(String),
/// `AotBackend::link`: the system linker could not be spawned, or exited
/// non-zero.
Link(String),
/// `AotBackend::link`'s own post-link probe: the just-produced `.so`
/// could not be `dlopen`'d, or a required symbol (`sim_abi_version`/
/// `sim_process_count`) could not be `dlsym`'d from it -- a `.so` that
/// links but fails this probe is never reported as `Ok`.
Load(String),
Io(std::io::Error),
}
impl From<LoweringError> for CodegenError {
fn from(e: LoweringError) -> Self {
CodegenError::Lowering(e)
}
}
impl fmt::Display for CodegenError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CodegenError::Lowering(e) => write!(f, "lowering error: {e}"),
CodegenError::ObjectEmission(msg) => write!(f, "object emission failed: {msg}"),
CodegenError::Link(msg) => write!(f, "link failed: {msg}"),
CodegenError::Load(msg) => write!(f, "AOT .so load probe failed: {msg}"),
CodegenError::Io(e) => write!(f, "I/O error: {e}"),
}
}
}
impl std::error::Error for CodegenError {}