1 //! Result and error types representing the outcome of compiling a function. 2 3 use crate::{ir::Function, verifier::VerifierErrors}; 4 use alloc::string::String; 5 use regalloc2::checker::CheckerErrors; 6 7 /// A compilation error. 8 /// 9 /// When Cranelift fails to compile a function, it will return one of these error codes. 10 #[derive(Debug)] 11 pub enum CodegenError { 12 /// A list of IR verifier errors. 13 /// 14 /// This always represents a bug, either in the code that generated IR for Cranelift, or a bug 15 /// in Cranelift itself. 16 Verifier(VerifierErrors), 17 18 /// An implementation limit was exceeded. 19 /// 20 /// Cranelift can compile very large and complicated functions, but the [implementation has 21 /// limits][limits] that cause compilation to fail when they are exceeded. 22 /// 23 /// [limits]: https://github.com/bytecodealliance/wasmtime/blob/main/cranelift/docs/ir.md#implementation-limits 24 ImplLimitExceeded, 25 26 /// The code size for the function is too large. 27 /// 28 /// Different target ISAs may impose a limit on the size of a compiled function. If that limit 29 /// is exceeded, compilation fails. 30 CodeTooLarge, 31 32 /// Something is not supported by the code generator. This might be an indication that a 33 /// feature is used without explicitly enabling it, or that something is temporarily 34 /// unsupported by a given target backend. 35 Unsupported(String), 36 37 /// A failure to map Cranelift register representation to a DWARF register representation. 38 #[cfg(feature = "unwind")] 39 RegisterMappingError(crate::isa::unwind::systemv::RegisterMappingError), 40 41 /// Register allocator internal error discovered by the symbolic checker. 42 Regalloc(CheckerErrors), 43 } 44 45 /// A convenient alias for a `Result` that uses `CodegenError` as the error type. 46 pub type CodegenResult<T> = Result<T, CodegenError>; 47 48 // This is manually implementing Error and Display instead of using thiserror to reduce the amount 49 // of dependencies used by Cranelift. 50 impl core::error::Error for CodegenError { source(&self) -> Option<&(dyn core::error::Error + 'static)>51 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { 52 match self { 53 CodegenError::Verifier(source) => Some(source), 54 CodegenError::ImplLimitExceeded { .. } 55 | CodegenError::CodeTooLarge { .. } 56 | CodegenError::Unsupported { .. } => None, 57 #[cfg(feature = "unwind")] 58 CodegenError::RegisterMappingError { .. } => None, 59 CodegenError::Regalloc(..) => None, 60 } 61 } 62 } 63 64 impl core::fmt::Display for CodegenError { fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result65 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { 66 match self { 67 CodegenError::Verifier(_) => write!(f, "Verifier errors"), 68 CodegenError::ImplLimitExceeded => write!(f, "Implementation limit exceeded"), 69 CodegenError::CodeTooLarge => write!(f, "Code for function is too large"), 70 CodegenError::Unsupported(feature) => write!(f, "Unsupported feature: {feature}"), 71 #[cfg(feature = "unwind")] 72 CodegenError::RegisterMappingError(_0) => write!(f, "Register mapping error"), 73 CodegenError::Regalloc(errors) => write!(f, "Regalloc validation errors: {errors:?}"), 74 } 75 } 76 } 77 78 impl From<VerifierErrors> for CodegenError { from(source: VerifierErrors) -> Self79 fn from(source: VerifierErrors) -> Self { 80 CodegenError::Verifier { 0: source } 81 } 82 } 83 84 /// Compilation error, with the accompanying function to help printing it. 85 pub struct CompileError<'a> { 86 /// Underlying `CodegenError` that triggered the error. 87 pub inner: CodegenError, 88 /// Function we tried to compile, for display purposes. 89 pub func: &'a Function, 90 } 91 92 // By default, have `CompileError` be displayed as the internal error, and let consumers care if 93 // they want to use the func field for adding details. 94 impl<'a> core::fmt::Debug for CompileError<'a> { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result95 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 96 self.inner.fmt(f) 97 } 98 } 99 100 /// A convenient alias for a `Result` that uses `CompileError` as the error type. 101 pub type CompileResult<'a, T> = Result<T, CompileError<'a>>; 102