xref: /wasmtime-44.0.1/winch/codegen/src/isa/mod.rs (revision 013b35ff)
1 use anyhow::{anyhow, Result};
2 use core::fmt::Formatter;
3 use cranelift_codegen::isa::{CallConv, IsaBuilder};
4 use cranelift_codegen::settings;
5 use cranelift_codegen::{Final, MachBufferFinalized, TextSectionBuilder};
6 use std::{
7     error,
8     fmt::{self, Debug, Display},
9 };
10 use target_lexicon::{Architecture, Triple};
11 use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources};
12 
13 #[cfg(feature = "x64")]
14 pub(crate) mod x64;
15 
16 #[cfg(feature = "arm64")]
17 pub(crate) mod aarch64;
18 
19 pub(crate) mod reg;
20 
21 macro_rules! isa_builder {
22     ($name: ident, $cfg_terms: tt, $triple: ident) => {{
23         #[cfg $cfg_terms]
24         {
25             Ok($name::isa_builder($triple))
26         }
27         #[cfg(not $cfg_terms)]
28         {
29             Err(anyhow!(LookupError::SupportDisabled))
30         }
31     }};
32 }
33 
34 pub type Builder = IsaBuilder<Result<Box<dyn TargetIsa>>>;
35 
36 /// Look for an ISA builder for the given target triple.
37 pub fn lookup(triple: Triple) -> Result<Builder> {
38     match triple.architecture {
39         Architecture::X86_64 => {
40             isa_builder!(x64, (feature = "x64"), triple)
41         }
42         Architecture::Aarch64 { .. } => {
43             isa_builder!(aarch64, (feature = "arm64"), triple)
44         }
45 
46         _ => Err(anyhow!(LookupError::Unsupported)),
47     }
48 }
49 
50 impl error::Error for LookupError {}
51 impl Display for LookupError {
52     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
53         match self {
54             LookupError::Unsupported => write!(f, "This target is not supported yet"),
55             LookupError::SupportDisabled => write!(f, "Support for this target was disabled"),
56         }
57     }
58 }
59 
60 #[derive(Debug)]
61 pub(crate) enum LookupError {
62     Unsupported,
63     // This directive covers the case in which the consumer
64     // enables the `all-arch` feature; in such case, this variant
65     // will never be used. This is most likely going to change
66     // in the future; this is one of the simplest options for now.
67     #[allow(dead_code)]
68     SupportDisabled,
69 }
70 
71 /// A trait representing commonalities between the supported
72 /// instruction set architectures.
73 pub trait TargetIsa: Send + Sync {
74     /// Get the name of the ISA.
75     fn name(&self) -> &'static str;
76 
77     /// Get the target triple of the ISA.
78     fn triple(&self) -> &Triple;
79 
80     /// Get the ISA-independent flags that were used to make this trait object.
81     fn flags(&self) -> &settings::Flags;
82 
83     /// Get the ISA-dependent flag values that were used to make this trait object.
84     fn isa_flags(&self) -> Vec<settings::Value>;
85 
86     /// Get a flag indicating whether branch protection is enabled.
87     fn is_branch_protection_enabled(&self) -> bool {
88         false
89     }
90 
91     fn compile_function(
92         &self,
93         sig: &FuncType,
94         body: &FunctionBody,
95         validator: FuncValidator<ValidatorResources>,
96     ) -> Result<MachBufferFinalized<Final>>;
97 
98     /// Get the default calling convention of the underlying target triple.
99     fn call_conv(&self) -> CallConv {
100         CallConv::triple_default(&self.triple())
101     }
102 
103     /// Get the endianess of the underlying target triple.
104     fn endianness(&self) -> target_lexicon::Endianness {
105         self.triple().endianness().unwrap()
106     }
107 
108     /// See `cranelift_codegen::isa::TargetIsa::create_systemv_cie`.
109     fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
110         // By default, an ISA cannot create a System V CIE.
111         None
112     }
113 
114     /// See `cranelift_codegen::isa::TargetIsa::text_section_builder`.
115     fn text_section_builder(&self, num_labeled_funcs: usize) -> Box<dyn TextSectionBuilder>;
116 
117     /// See `cranelift_codegen::isa::TargetIsa::function_alignment`.
118     fn function_alignment(&self) -> u32;
119 }
120 
121 impl Debug for &dyn TargetIsa {
122     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
123         write!(
124             f,
125             "Target ISA {{ triple: {:?}, calling convention: {:?} }}",
126             self.triple(),
127             self.call_conv()
128         )
129     }
130 }
131