1747ad3c4Slazypassion //! Result and error types representing the outcome of compiling a function.
2747ad3c4Slazypassion 
3ff37c9d8SBenjamin Bouvier use crate::{ir::Function, verifier::VerifierErrors};
40889323aSSSD use alloc::string::String;
5*2f7dbd61SChris Fallin use regalloc2::checker::CheckerErrors;
6747ad3c4Slazypassion 
7747ad3c4Slazypassion /// A compilation error.
8747ad3c4Slazypassion ///
9747ad3c4Slazypassion /// When Cranelift fails to compile a function, it will return one of these error codes.
10a0318f36SChris Fallin #[derive(Debug)]
11747ad3c4Slazypassion pub enum CodegenError {
12747ad3c4Slazypassion     /// A list of IR verifier errors.
13747ad3c4Slazypassion     ///
14747ad3c4Slazypassion     /// This always represents a bug, either in the code that generated IR for Cranelift, or a bug
15747ad3c4Slazypassion     /// in Cranelift itself.
1603fdbadfSbjorn3     Verifier(VerifierErrors),
17747ad3c4Slazypassion 
18747ad3c4Slazypassion     /// An implementation limit was exceeded.
19747ad3c4Slazypassion     ///
20747ad3c4Slazypassion     /// Cranelift can compile very large and complicated functions, but the [implementation has
21747ad3c4Slazypassion     /// limits][limits] that cause compilation to fail when they are exceeded.
22747ad3c4Slazypassion     ///
23a92a31d8SAlex Crichton     /// [limits]: https://github.com/bytecodealliance/wasmtime/blob/main/cranelift/docs/ir.md#implementation-limits
24747ad3c4Slazypassion     ImplLimitExceeded,
25747ad3c4Slazypassion 
26747ad3c4Slazypassion     /// The code size for the function is too large.
27747ad3c4Slazypassion     ///
28747ad3c4Slazypassion     /// Different target ISAs may impose a limit on the size of a compiled function. If that limit
29747ad3c4Slazypassion     /// is exceeded, compilation fails.
30747ad3c4Slazypassion     CodeTooLarge,
312fb7e9f3SPeter Huene 
32698dc9c4SBenjamin Bouvier     /// Something is not supported by the code generator. This might be an indication that a
33698dc9c4SBenjamin Bouvier     /// feature is used without explicitly enabling it, or that something is temporarily
34698dc9c4SBenjamin Bouvier     /// unsupported by a given target backend.
35698dc9c4SBenjamin Bouvier     Unsupported(String),
36698dc9c4SBenjamin Bouvier 
372fb7e9f3SPeter Huene     /// A failure to map Cranelift register representation to a DWARF register representation.
382fb7e9f3SPeter Huene     #[cfg(feature = "unwind")]
392fb7e9f3SPeter Huene     RegisterMappingError(crate::isa::unwind::systemv::RegisterMappingError),
40a0318f36SChris Fallin 
41a0318f36SChris Fallin     /// Register allocator internal error discovered by the symbolic checker.
42a0318f36SChris Fallin     Regalloc(CheckerErrors),
43747ad3c4Slazypassion }
44747ad3c4Slazypassion 
45747ad3c4Slazypassion /// A convenient alias for a `Result` that uses `CodegenError` as the error type.
46747ad3c4Slazypassion pub type CodegenResult<T> = Result<T, CodegenError>;
4703fdbadfSbjorn3 
4882f3ad4fSbjorn3 // This is manually implementing Error and Display instead of using thiserror to reduce the amount
4982f3ad4fSbjorn3 // of dependencies used by Cranelift.
500889323aSSSD impl core::error::Error for CodegenError {
source(&self) -> Option<&(dyn core::error::Error + 'static)>510889323aSSSD     fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
5203fdbadfSbjorn3         match self {
5303fdbadfSbjorn3             CodegenError::Verifier(source) => Some(source),
5403fdbadfSbjorn3             CodegenError::ImplLimitExceeded { .. }
5503fdbadfSbjorn3             | CodegenError::CodeTooLarge { .. }
5603fdbadfSbjorn3             | CodegenError::Unsupported { .. } => None,
5703fdbadfSbjorn3             #[cfg(feature = "unwind")]
5803fdbadfSbjorn3             CodegenError::RegisterMappingError { .. } => None,
59a0318f36SChris Fallin             CodegenError::Regalloc(..) => None,
6003fdbadfSbjorn3         }
6103fdbadfSbjorn3     }
6203fdbadfSbjorn3 }
6303fdbadfSbjorn3 
640889323aSSSD impl core::fmt::Display for CodegenError {
fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result650889323aSSSD     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
6603fdbadfSbjorn3         match self {
6703fdbadfSbjorn3             CodegenError::Verifier(_) => write!(f, "Verifier errors"),
6803fdbadfSbjorn3             CodegenError::ImplLimitExceeded => write!(f, "Implementation limit exceeded"),
6903fdbadfSbjorn3             CodegenError::CodeTooLarge => write!(f, "Code for function is too large"),
70a0442ea0SHamir Mahal             CodegenError::Unsupported(feature) => write!(f, "Unsupported feature: {feature}"),
7103fdbadfSbjorn3             #[cfg(feature = "unwind")]
7203fdbadfSbjorn3             CodegenError::RegisterMappingError(_0) => write!(f, "Register mapping error"),
73a0442ea0SHamir Mahal             CodegenError::Regalloc(errors) => write!(f, "Regalloc validation errors: {errors:?}"),
7403fdbadfSbjorn3         }
7503fdbadfSbjorn3     }
7603fdbadfSbjorn3 }
7703fdbadfSbjorn3 
7803fdbadfSbjorn3 impl From<VerifierErrors> for CodegenError {
from(source: VerifierErrors) -> Self7903fdbadfSbjorn3     fn from(source: VerifierErrors) -> Self {
8003fdbadfSbjorn3         CodegenError::Verifier { 0: source }
8103fdbadfSbjorn3     }
8203fdbadfSbjorn3 }
83ff37c9d8SBenjamin Bouvier 
84ff37c9d8SBenjamin Bouvier /// Compilation error, with the accompanying function to help printing it.
85ff37c9d8SBenjamin Bouvier pub struct CompileError<'a> {
86ff37c9d8SBenjamin Bouvier     /// Underlying `CodegenError` that triggered the error.
87ff37c9d8SBenjamin Bouvier     pub inner: CodegenError,
88ff37c9d8SBenjamin Bouvier     /// Function we tried to compile, for display purposes.
89ff37c9d8SBenjamin Bouvier     pub func: &'a Function,
90ff37c9d8SBenjamin Bouvier }
91ff37c9d8SBenjamin Bouvier 
92ff37c9d8SBenjamin Bouvier // By default, have `CompileError` be displayed as the internal error, and let consumers care if
93ff37c9d8SBenjamin Bouvier // they want to use the func field for adding details.
94ff37c9d8SBenjamin Bouvier impl<'a> core::fmt::Debug for CompileError<'a> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result95ff37c9d8SBenjamin Bouvier     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
96ff37c9d8SBenjamin Bouvier         self.inner.fmt(f)
97ff37c9d8SBenjamin Bouvier     }
98ff37c9d8SBenjamin Bouvier }
99ff37c9d8SBenjamin Bouvier 
100ff37c9d8SBenjamin Bouvier /// A convenient alias for a `Result` that uses `CompileError` as the error type.
101ff37c9d8SBenjamin Bouvier pub type CompileResult<'a, T> = Result<T, CompileError<'a>>;
102