cranelift_module/
module.rs

1//! Defines `Module` and related types.
2
3// TODO: Should `ir::Function` really have a `name`?
4
5// TODO: Factor out `ir::Function`'s `ext_funcs` and `global_values` into a struct
6// shared with `DataDescription`?
7
8use super::HashMap;
9use crate::data_context::DataDescription;
10use core::fmt::Display;
11use cranelift_codegen::binemit::{CodeOffset, Reloc};
12use cranelift_codegen::entity::{entity_impl, PrimaryMap};
13use cranelift_codegen::ir::function::{Function, VersionMarker};
14use cranelift_codegen::ir::ExternalName;
15use cranelift_codegen::settings::SetError;
16use cranelift_codegen::{
17    ir, isa, CodegenError, CompileError, Context, FinalizedMachReloc, FinalizedRelocTarget,
18};
19use cranelift_control::ControlPlane;
20use std::borrow::{Cow, ToOwned};
21use std::boxed::Box;
22use std::string::String;
23
24/// A module relocation.
25#[derive(Clone)]
26pub struct ModuleReloc {
27    /// The offset at which the relocation applies, *relative to the
28    /// containing section*.
29    pub offset: CodeOffset,
30    /// The kind of relocation.
31    pub kind: Reloc,
32    /// The external symbol / name to which this relocation refers.
33    pub name: ModuleRelocTarget,
34    /// The addend to add to the symbol value.
35    pub addend: i64,
36}
37
38impl ModuleReloc {
39    /// Converts a `FinalizedMachReloc` produced from a `Function` into a `ModuleReloc`.
40    pub fn from_mach_reloc(
41        mach_reloc: &FinalizedMachReloc,
42        func: &Function,
43        func_id: FuncId,
44    ) -> Self {
45        let name = match mach_reloc.target {
46            FinalizedRelocTarget::ExternalName(ExternalName::User(reff)) => {
47                let name = &func.params.user_named_funcs()[reff];
48                ModuleRelocTarget::user(name.namespace, name.index)
49            }
50            FinalizedRelocTarget::ExternalName(ExternalName::TestCase(_)) => unimplemented!(),
51            FinalizedRelocTarget::ExternalName(ExternalName::LibCall(libcall)) => {
52                ModuleRelocTarget::LibCall(libcall)
53            }
54            FinalizedRelocTarget::ExternalName(ExternalName::KnownSymbol(ks)) => {
55                ModuleRelocTarget::KnownSymbol(ks)
56            }
57            FinalizedRelocTarget::Func(offset) => {
58                ModuleRelocTarget::FunctionOffset(func_id, offset)
59            }
60        };
61        Self {
62            offset: mach_reloc.offset,
63            kind: mach_reloc.kind,
64            name,
65            addend: mach_reloc.addend,
66        }
67    }
68}
69
70/// A function identifier for use in the `Module` interface.
71#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
72#[cfg_attr(
73    feature = "enable-serde",
74    derive(serde_derive::Serialize, serde_derive::Deserialize)
75)]
76pub struct FuncId(u32);
77entity_impl!(FuncId, "funcid");
78
79/// Function identifiers are namespace 0 in `ir::ExternalName`
80impl From<FuncId> for ModuleRelocTarget {
81    fn from(id: FuncId) -> Self {
82        Self::User {
83            namespace: 0,
84            index: id.0,
85        }
86    }
87}
88
89impl FuncId {
90    /// Get the `FuncId` for the function named by `name`.
91    pub fn from_name(name: &ModuleRelocTarget) -> FuncId {
92        if let ModuleRelocTarget::User { namespace, index } = name {
93            debug_assert_eq!(*namespace, 0);
94            FuncId::from_u32(*index)
95        } else {
96            panic!("unexpected name in DataId::from_name")
97        }
98    }
99}
100
101/// A data object identifier for use in the `Module` interface.
102#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
103#[cfg_attr(
104    feature = "enable-serde",
105    derive(serde_derive::Serialize, serde_derive::Deserialize)
106)]
107pub struct DataId(u32);
108entity_impl!(DataId, "dataid");
109
110/// Data identifiers are namespace 1 in `ir::ExternalName`
111impl From<DataId> for ModuleRelocTarget {
112    fn from(id: DataId) -> Self {
113        Self::User {
114            namespace: 1,
115            index: id.0,
116        }
117    }
118}
119
120impl DataId {
121    /// Get the `DataId` for the data object named by `name`.
122    pub fn from_name(name: &ModuleRelocTarget) -> DataId {
123        if let ModuleRelocTarget::User { namespace, index } = name {
124            debug_assert_eq!(*namespace, 1);
125            DataId::from_u32(*index)
126        } else {
127            panic!("unexpected name in DataId::from_name")
128        }
129    }
130}
131
132/// Linkage refers to where an entity is defined and who can see it.
133#[derive(Copy, Clone, Debug, PartialEq, Eq)]
134#[cfg_attr(
135    feature = "enable-serde",
136    derive(serde_derive::Serialize, serde_derive::Deserialize)
137)]
138pub enum Linkage {
139    /// Defined outside of a module.
140    Import,
141    /// Defined inside the module, but not visible outside it.
142    Local,
143    /// Defined inside the module, visible outside it, and may be preempted.
144    Preemptible,
145    /// Defined inside the module, visible inside the current static linkage unit, but not outside.
146    ///
147    /// A static linkage unit is the combination of all object files passed to a linker to create
148    /// an executable or dynamic library.
149    Hidden,
150    /// Defined inside the module, and visible outside it.
151    Export,
152}
153
154impl Linkage {
155    fn merge(a: Self, b: Self) -> Self {
156        match a {
157            Self::Export => Self::Export,
158            Self::Hidden => match b {
159                Self::Export => Self::Export,
160                Self::Preemptible => Self::Preemptible,
161                _ => Self::Hidden,
162            },
163            Self::Preemptible => match b {
164                Self::Export => Self::Export,
165                _ => Self::Preemptible,
166            },
167            Self::Local => match b {
168                Self::Export => Self::Export,
169                Self::Hidden => Self::Hidden,
170                Self::Preemptible => Self::Preemptible,
171                Self::Local | Self::Import => Self::Local,
172            },
173            Self::Import => b,
174        }
175    }
176
177    /// Test whether this linkage can have a definition.
178    pub fn is_definable(self) -> bool {
179        match self {
180            Self::Import => false,
181            Self::Local | Self::Preemptible | Self::Hidden | Self::Export => true,
182        }
183    }
184
185    /// Test whether this linkage will have a definition that cannot be preempted.
186    pub fn is_final(self) -> bool {
187        match self {
188            Self::Import | Self::Preemptible => false,
189            Self::Local | Self::Hidden | Self::Export => true,
190        }
191    }
192}
193
194/// A declared name may refer to either a function or data declaration
195#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
196#[cfg_attr(
197    feature = "enable-serde",
198    derive(serde_derive::Serialize, serde_derive::Deserialize)
199)]
200pub enum FuncOrDataId {
201    /// When it's a FuncId
202    Func(FuncId),
203    /// When it's a DataId
204    Data(DataId),
205}
206
207/// Mapping to `ModuleExtName` is trivial based on the `FuncId` and `DataId` mapping.
208impl From<FuncOrDataId> for ModuleRelocTarget {
209    fn from(id: FuncOrDataId) -> Self {
210        match id {
211            FuncOrDataId::Func(funcid) => Self::from(funcid),
212            FuncOrDataId::Data(dataid) => Self::from(dataid),
213        }
214    }
215}
216
217/// Information about a function which can be called.
218#[derive(Debug)]
219#[cfg_attr(
220    feature = "enable-serde",
221    derive(serde_derive::Serialize, serde_derive::Deserialize)
222)]
223#[expect(missing_docs, reason = "self-describing fields")]
224pub struct FunctionDeclaration {
225    pub name: Option<String>,
226    pub linkage: Linkage,
227    pub signature: ir::Signature,
228}
229
230impl FunctionDeclaration {
231    /// The linkage name of the function.
232    ///
233    /// Synthesized from the given function id if it is an anonymous function.
234    pub fn linkage_name(&self, id: FuncId) -> Cow<'_, str> {
235        match &self.name {
236            Some(name) => Cow::Borrowed(name),
237            // Symbols starting with .L are completely omitted from the symbol table after linking.
238            // Using hexadecimal instead of decimal for slightly smaller symbol names and often
239            // slightly faster linking.
240            None => Cow::Owned(format!(".Lfn{:x}", id.as_u32())),
241        }
242    }
243
244    fn merge(
245        &mut self,
246        id: FuncId,
247        linkage: Linkage,
248        sig: &ir::Signature,
249    ) -> Result<(), ModuleError> {
250        self.linkage = Linkage::merge(self.linkage, linkage);
251        if &self.signature != sig {
252            return Err(ModuleError::IncompatibleSignature(
253                self.linkage_name(id).into_owned(),
254                self.signature.clone(),
255                sig.clone(),
256            ));
257        }
258        Ok(())
259    }
260}
261
262/// Error messages for all `Module` methods
263#[derive(Debug)]
264pub enum ModuleError {
265    /// Indicates an identifier was used before it was declared
266    Undeclared(String),
267
268    /// Indicates an identifier was used as data/function first, but then used as the other
269    IncompatibleDeclaration(String),
270
271    /// Indicates a function identifier was declared with a
272    /// different signature than declared previously
273    IncompatibleSignature(String, ir::Signature, ir::Signature),
274
275    /// Indicates an identifier was defined more than once
276    DuplicateDefinition(String),
277
278    /// Indicates an identifier was defined, but was declared as an import
279    InvalidImportDefinition(String),
280
281    /// Wraps a `cranelift-codegen` error
282    Compilation(CodegenError),
283
284    /// Memory allocation failure from a backend
285    Allocation {
286        /// Tell where the allocation came from
287        message: &'static str,
288        /// Io error the allocation failed with
289        err: std::io::Error,
290    },
291
292    /// Wraps a generic error from a backend
293    Backend(anyhow::Error),
294
295    /// Wraps an error from a flag definition.
296    Flag(SetError),
297}
298
299impl<'a> From<CompileError<'a>> for ModuleError {
300    fn from(err: CompileError<'a>) -> Self {
301        Self::Compilation(err.inner)
302    }
303}
304
305// This is manually implementing Error and Display instead of using thiserror to reduce the amount
306// of dependencies used by Cranelift.
307impl std::error::Error for ModuleError {
308    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
309        match self {
310            Self::Undeclared { .. }
311            | Self::IncompatibleDeclaration { .. }
312            | Self::IncompatibleSignature { .. }
313            | Self::DuplicateDefinition { .. }
314            | Self::InvalidImportDefinition { .. } => None,
315            Self::Compilation(source) => Some(source),
316            Self::Allocation { err: source, .. } => Some(source),
317            Self::Backend(source) => Some(&**source),
318            Self::Flag(source) => Some(source),
319        }
320    }
321}
322
323impl std::fmt::Display for ModuleError {
324    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
325        match self {
326            Self::Undeclared(name) => {
327                write!(f, "Undeclared identifier: {name}")
328            }
329            Self::IncompatibleDeclaration(name) => {
330                write!(f, "Incompatible declaration of identifier: {name}",)
331            }
332            Self::IncompatibleSignature(name, prev_sig, new_sig) => {
333                write!(
334                    f,
335                    "Function {name} signature {new_sig:?} is incompatible with previous declaration {prev_sig:?}",
336                )
337            }
338            Self::DuplicateDefinition(name) => {
339                write!(f, "Duplicate definition of identifier: {name}")
340            }
341            Self::InvalidImportDefinition(name) => {
342                write!(
343                    f,
344                    "Invalid to define identifier declared as an import: {name}",
345                )
346            }
347            Self::Compilation(err) => {
348                write!(f, "Compilation error: {err}")
349            }
350            Self::Allocation { message, err } => {
351                write!(f, "Allocation error: {message}: {err}")
352            }
353            Self::Backend(err) => write!(f, "Backend error: {err}"),
354            Self::Flag(err) => write!(f, "Flag error: {err}"),
355        }
356    }
357}
358
359impl std::convert::From<CodegenError> for ModuleError {
360    fn from(source: CodegenError) -> Self {
361        Self::Compilation { 0: source }
362    }
363}
364
365impl std::convert::From<SetError> for ModuleError {
366    fn from(source: SetError) -> Self {
367        Self::Flag { 0: source }
368    }
369}
370
371/// A convenient alias for a `Result` that uses `ModuleError` as the error type.
372pub type ModuleResult<T> = Result<T, ModuleError>;
373
374/// Information about a data object which can be accessed.
375#[derive(Debug)]
376#[cfg_attr(
377    feature = "enable-serde",
378    derive(serde_derive::Serialize, serde_derive::Deserialize)
379)]
380#[expect(missing_docs, reason = "self-describing fields")]
381pub struct DataDeclaration {
382    pub name: Option<String>,
383    pub linkage: Linkage,
384    pub writable: bool,
385    pub tls: bool,
386}
387
388impl DataDeclaration {
389    /// The linkage name of the data object.
390    ///
391    /// Synthesized from the given data id if it is an anonymous function.
392    pub fn linkage_name(&self, id: DataId) -> Cow<'_, str> {
393        match &self.name {
394            Some(name) => Cow::Borrowed(name),
395            // Symbols starting with .L are completely omitted from the symbol table after linking.
396            // Using hexadecimal instead of decimal for slightly smaller symbol names and often
397            // slightly faster linking.
398            None => Cow::Owned(format!(".Ldata{:x}", id.as_u32())),
399        }
400    }
401
402    fn merge(&mut self, linkage: Linkage, writable: bool, tls: bool) {
403        self.linkage = Linkage::merge(self.linkage, linkage);
404        self.writable = self.writable || writable;
405        assert_eq!(
406            self.tls, tls,
407            "Can't change TLS data object to normal or in the opposite way",
408        );
409    }
410}
411
412/// A translated `ExternalName` into something global we can handle.
413#[derive(Clone, Debug)]
414#[cfg_attr(
415    feature = "enable-serde",
416    derive(serde_derive::Serialize, serde_derive::Deserialize)
417)]
418pub enum ModuleRelocTarget {
419    /// User defined function, converted from `ExternalName::User`.
420    User {
421        /// Arbitrary.
422        namespace: u32,
423        /// Arbitrary.
424        index: u32,
425    },
426    /// Call into a library function.
427    LibCall(ir::LibCall),
428    /// Symbols known to the linker.
429    KnownSymbol(ir::KnownSymbol),
430    /// A offset inside a function
431    FunctionOffset(FuncId, CodeOffset),
432}
433
434impl ModuleRelocTarget {
435    /// Creates a user-defined external name.
436    pub fn user(namespace: u32, index: u32) -> Self {
437        Self::User { namespace, index }
438    }
439}
440
441impl Display for ModuleRelocTarget {
442    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
443        match self {
444            Self::User { namespace, index } => write!(f, "u{namespace}:{index}"),
445            Self::LibCall(lc) => write!(f, "%{lc}"),
446            Self::KnownSymbol(ks) => write!(f, "{ks}"),
447            Self::FunctionOffset(fname, offset) => write!(f, "{fname}+{offset}"),
448        }
449    }
450}
451
452/// This provides a view to the state of a module which allows `ir::ExternalName`s to be translated
453/// into `FunctionDeclaration`s and `DataDeclaration`s.
454#[derive(Debug, Default)]
455pub struct ModuleDeclarations {
456    /// A version marker used to ensure that serialized clif ir is never deserialized with a
457    /// different version of Cranelift.
458    // Note: This must be the first field to ensure that Serde will deserialize it before
459    // attempting to deserialize other fields that are potentially changed between versions.
460    _version_marker: VersionMarker,
461
462    names: HashMap<String, FuncOrDataId>,
463    functions: PrimaryMap<FuncId, FunctionDeclaration>,
464    data_objects: PrimaryMap<DataId, DataDeclaration>,
465}
466
467#[cfg(feature = "enable-serde")]
468mod serialize {
469    // This is manually implementing Serialize and Deserialize to avoid serializing the names field,
470    // which can be entirely reconstructed from the functions and data_objects fields, saving space.
471
472    use super::*;
473
474    use serde::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Unexpected, Visitor};
475    use serde::ser::{Serialize, SerializeStruct, Serializer};
476    use std::fmt;
477
478    fn get_names<E: Error>(
479        functions: &PrimaryMap<FuncId, FunctionDeclaration>,
480        data_objects: &PrimaryMap<DataId, DataDeclaration>,
481    ) -> Result<HashMap<String, FuncOrDataId>, E> {
482        let mut names = HashMap::new();
483        for (func_id, decl) in functions.iter() {
484            if let Some(name) = &decl.name {
485                let old = names.insert(name.clone(), FuncOrDataId::Func(func_id));
486                if old.is_some() {
487                    return Err(E::invalid_value(
488                        Unexpected::Other("duplicate name"),
489                        &"FunctionDeclaration's with no duplicate names",
490                    ));
491                }
492            }
493        }
494        for (data_id, decl) in data_objects.iter() {
495            if let Some(name) = &decl.name {
496                let old = names.insert(name.clone(), FuncOrDataId::Data(data_id));
497                if old.is_some() {
498                    return Err(E::invalid_value(
499                        Unexpected::Other("duplicate name"),
500                        &"DataDeclaration's with no duplicate names",
501                    ));
502                }
503            }
504        }
505        Ok(names)
506    }
507
508    impl Serialize for ModuleDeclarations {
509        fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
510            let ModuleDeclarations {
511                _version_marker,
512                functions,
513                data_objects,
514                names: _,
515            } = self;
516
517            let mut state = s.serialize_struct("ModuleDeclarations", 4)?;
518            state.serialize_field("_version_marker", _version_marker)?;
519            state.serialize_field("functions", functions)?;
520            state.serialize_field("data_objects", data_objects)?;
521            state.end()
522        }
523    }
524
525    enum ModuleDeclarationsField {
526        VersionMarker,
527        Functions,
528        DataObjects,
529        Ignore,
530    }
531
532    struct ModuleDeclarationsFieldVisitor;
533
534    impl<'de> serde::de::Visitor<'de> for ModuleDeclarationsFieldVisitor {
535        type Value = ModuleDeclarationsField;
536
537        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
538            f.write_str("field identifier")
539        }
540
541        fn visit_u64<E: Error>(self, val: u64) -> Result<Self::Value, E> {
542            match val {
543                0u64 => Ok(ModuleDeclarationsField::VersionMarker),
544                1u64 => Ok(ModuleDeclarationsField::Functions),
545                2u64 => Ok(ModuleDeclarationsField::DataObjects),
546                _ => Ok(ModuleDeclarationsField::Ignore),
547            }
548        }
549
550        fn visit_str<E: Error>(self, val: &str) -> Result<Self::Value, E> {
551            match val {
552                "_version_marker" => Ok(ModuleDeclarationsField::VersionMarker),
553                "functions" => Ok(ModuleDeclarationsField::Functions),
554                "data_objects" => Ok(ModuleDeclarationsField::DataObjects),
555                _ => Ok(ModuleDeclarationsField::Ignore),
556            }
557        }
558
559        fn visit_bytes<E: Error>(self, val: &[u8]) -> Result<Self::Value, E> {
560            match val {
561                b"_version_marker" => Ok(ModuleDeclarationsField::VersionMarker),
562                b"functions" => Ok(ModuleDeclarationsField::Functions),
563                b"data_objects" => Ok(ModuleDeclarationsField::DataObjects),
564                _ => Ok(ModuleDeclarationsField::Ignore),
565            }
566        }
567    }
568
569    impl<'de> Deserialize<'de> for ModuleDeclarationsField {
570        #[inline]
571        fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
572            d.deserialize_identifier(ModuleDeclarationsFieldVisitor)
573        }
574    }
575
576    struct ModuleDeclarationsVisitor;
577
578    impl<'de> Visitor<'de> for ModuleDeclarationsVisitor {
579        type Value = ModuleDeclarations;
580
581        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
582            f.write_str("struct ModuleDeclarations")
583        }
584
585        #[inline]
586        fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
587            let _version_marker = match seq.next_element()? {
588                Some(val) => val,
589                None => {
590                    return Err(Error::invalid_length(
591                        0usize,
592                        &"struct ModuleDeclarations with 4 elements",
593                    ));
594                }
595            };
596            let functions = match seq.next_element()? {
597                Some(val) => val,
598                None => {
599                    return Err(Error::invalid_length(
600                        2usize,
601                        &"struct ModuleDeclarations with 4 elements",
602                    ));
603                }
604            };
605            let data_objects = match seq.next_element()? {
606                Some(val) => val,
607                None => {
608                    return Err(Error::invalid_length(
609                        3usize,
610                        &"struct ModuleDeclarations with 4 elements",
611                    ));
612                }
613            };
614            let names = get_names(&functions, &data_objects)?;
615            Ok(ModuleDeclarations {
616                _version_marker,
617                names,
618                functions,
619                data_objects,
620            })
621        }
622
623        #[inline]
624        fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
625            let mut _version_marker: Option<VersionMarker> = None;
626            let mut functions: Option<PrimaryMap<FuncId, FunctionDeclaration>> = None;
627            let mut data_objects: Option<PrimaryMap<DataId, DataDeclaration>> = None;
628            while let Some(key) = map.next_key::<ModuleDeclarationsField>()? {
629                match key {
630                    ModuleDeclarationsField::VersionMarker => {
631                        if _version_marker.is_some() {
632                            return Err(Error::duplicate_field("_version_marker"));
633                        }
634                        _version_marker = Some(map.next_value()?);
635                    }
636                    ModuleDeclarationsField::Functions => {
637                        if functions.is_some() {
638                            return Err(Error::duplicate_field("functions"));
639                        }
640                        functions = Some(map.next_value()?);
641                    }
642                    ModuleDeclarationsField::DataObjects => {
643                        if data_objects.is_some() {
644                            return Err(Error::duplicate_field("data_objects"));
645                        }
646                        data_objects = Some(map.next_value()?);
647                    }
648                    _ => {
649                        map.next_value::<serde::de::IgnoredAny>()?;
650                    }
651                }
652            }
653            let _version_marker = match _version_marker {
654                Some(_version_marker) => _version_marker,
655                None => return Err(Error::missing_field("_version_marker")),
656            };
657            let functions = match functions {
658                Some(functions) => functions,
659                None => return Err(Error::missing_field("functions")),
660            };
661            let data_objects = match data_objects {
662                Some(data_objects) => data_objects,
663                None => return Err(Error::missing_field("data_objects")),
664            };
665            let names = get_names(&functions, &data_objects)?;
666            Ok(ModuleDeclarations {
667                _version_marker,
668                names,
669                functions,
670                data_objects,
671            })
672        }
673    }
674
675    impl<'de> Deserialize<'de> for ModuleDeclarations {
676        fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
677            d.deserialize_struct(
678                "ModuleDeclarations",
679                &["_version_marker", "functions", "data_objects"],
680                ModuleDeclarationsVisitor,
681            )
682        }
683    }
684}
685
686impl ModuleDeclarations {
687    /// Get the module identifier for a given name, if that name
688    /// has been declared.
689    pub fn get_name(&self, name: &str) -> Option<FuncOrDataId> {
690        self.names.get(name).copied()
691    }
692
693    /// Get an iterator of all function declarations
694    pub fn get_functions(&self) -> impl Iterator<Item = (FuncId, &FunctionDeclaration)> {
695        self.functions.iter()
696    }
697
698    /// Return whether `name` names a function, rather than a data object.
699    pub fn is_function(name: &ModuleRelocTarget) -> bool {
700        match name {
701            ModuleRelocTarget::User { namespace, .. } => *namespace == 0,
702            ModuleRelocTarget::LibCall(_)
703            | ModuleRelocTarget::KnownSymbol(_)
704            | ModuleRelocTarget::FunctionOffset(..) => {
705                panic!("unexpected module ext name")
706            }
707        }
708    }
709
710    /// Get the `FunctionDeclaration` for the function named by `name`.
711    pub fn get_function_decl(&self, func_id: FuncId) -> &FunctionDeclaration {
712        &self.functions[func_id]
713    }
714
715    /// Get an iterator of all data declarations
716    pub fn get_data_objects(&self) -> impl Iterator<Item = (DataId, &DataDeclaration)> {
717        self.data_objects.iter()
718    }
719
720    /// Get the `DataDeclaration` for the data object named by `name`.
721    pub fn get_data_decl(&self, data_id: DataId) -> &DataDeclaration {
722        &self.data_objects[data_id]
723    }
724
725    /// Declare a function in this module.
726    pub fn declare_function(
727        &mut self,
728        name: &str,
729        linkage: Linkage,
730        signature: &ir::Signature,
731    ) -> ModuleResult<(FuncId, Linkage)> {
732        // TODO: Can we avoid allocating names so often?
733        use super::hash_map::Entry::*;
734        match self.names.entry(name.to_owned()) {
735            Occupied(entry) => match *entry.get() {
736                FuncOrDataId::Func(id) => {
737                    let existing = &mut self.functions[id];
738                    existing.merge(id, linkage, signature)?;
739                    Ok((id, existing.linkage))
740                }
741                FuncOrDataId::Data(..) => {
742                    Err(ModuleError::IncompatibleDeclaration(name.to_owned()))
743                }
744            },
745            Vacant(entry) => {
746                let id = self.functions.push(FunctionDeclaration {
747                    name: Some(name.to_owned()),
748                    linkage,
749                    signature: signature.clone(),
750                });
751                entry.insert(FuncOrDataId::Func(id));
752                Ok((id, self.functions[id].linkage))
753            }
754        }
755    }
756
757    /// Declare an anonymous function in this module.
758    pub fn declare_anonymous_function(
759        &mut self,
760        signature: &ir::Signature,
761    ) -> ModuleResult<FuncId> {
762        let id = self.functions.push(FunctionDeclaration {
763            name: None,
764            linkage: Linkage::Local,
765            signature: signature.clone(),
766        });
767        Ok(id)
768    }
769
770    /// Declare a data object in this module.
771    pub fn declare_data(
772        &mut self,
773        name: &str,
774        linkage: Linkage,
775        writable: bool,
776        tls: bool,
777    ) -> ModuleResult<(DataId, Linkage)> {
778        // TODO: Can we avoid allocating names so often?
779        use super::hash_map::Entry::*;
780        match self.names.entry(name.to_owned()) {
781            Occupied(entry) => match *entry.get() {
782                FuncOrDataId::Data(id) => {
783                    let existing = &mut self.data_objects[id];
784                    existing.merge(linkage, writable, tls);
785                    Ok((id, existing.linkage))
786                }
787
788                FuncOrDataId::Func(..) => {
789                    Err(ModuleError::IncompatibleDeclaration(name.to_owned()))
790                }
791            },
792            Vacant(entry) => {
793                let id = self.data_objects.push(DataDeclaration {
794                    name: Some(name.to_owned()),
795                    linkage,
796                    writable,
797                    tls,
798                });
799                entry.insert(FuncOrDataId::Data(id));
800                Ok((id, self.data_objects[id].linkage))
801            }
802        }
803    }
804
805    /// Declare an anonymous data object in this module.
806    pub fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
807        let id = self.data_objects.push(DataDeclaration {
808            name: None,
809            linkage: Linkage::Local,
810            writable,
811            tls,
812        });
813        Ok(id)
814    }
815}
816
817/// A `Module` is a utility for collecting functions and data objects, and linking them together.
818pub trait Module {
819    /// Return the `TargetIsa` to compile for.
820    fn isa(&self) -> &dyn isa::TargetIsa;
821
822    /// Get all declarations in this module.
823    fn declarations(&self) -> &ModuleDeclarations;
824
825    /// Get the module identifier for a given name, if that name
826    /// has been declared.
827    fn get_name(&self, name: &str) -> Option<FuncOrDataId> {
828        self.declarations().get_name(name)
829    }
830
831    /// Return the target information needed by frontends to produce Cranelift IR
832    /// for the current target.
833    fn target_config(&self) -> isa::TargetFrontendConfig {
834        self.isa().frontend_config()
835    }
836
837    /// Create a new `Context` initialized for use with this `Module`.
838    ///
839    /// This ensures that the `Context` is initialized with the default calling
840    /// convention for the `TargetIsa`.
841    fn make_context(&self) -> Context {
842        let mut ctx = Context::new();
843        ctx.func.signature.call_conv = self.isa().default_call_conv();
844        ctx
845    }
846
847    /// Clear the given `Context` and reset it for use with a new function.
848    ///
849    /// This ensures that the `Context` is initialized with the default calling
850    /// convention for the `TargetIsa`.
851    fn clear_context(&self, ctx: &mut Context) {
852        ctx.clear();
853        ctx.func.signature.call_conv = self.isa().default_call_conv();
854    }
855
856    /// Create a new empty `Signature` with the default calling convention for
857    /// the `TargetIsa`, to which parameter and return types can be added for
858    /// declaring a function to be called by this `Module`.
859    fn make_signature(&self) -> ir::Signature {
860        ir::Signature::new(self.isa().default_call_conv())
861    }
862
863    /// Clear the given `Signature` and reset for use with a new function.
864    ///
865    /// This ensures that the `Signature` is initialized with the default
866    /// calling convention for the `TargetIsa`.
867    fn clear_signature(&self, sig: &mut ir::Signature) {
868        sig.clear(self.isa().default_call_conv());
869    }
870
871    /// Declare a function in this module.
872    fn declare_function(
873        &mut self,
874        name: &str,
875        linkage: Linkage,
876        signature: &ir::Signature,
877    ) -> ModuleResult<FuncId>;
878
879    /// Declare an anonymous function in this module.
880    fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId>;
881
882    /// Declare a data object in this module.
883    fn declare_data(
884        &mut self,
885        name: &str,
886        linkage: Linkage,
887        writable: bool,
888        tls: bool,
889    ) -> ModuleResult<DataId>;
890
891    /// Declare an anonymous data object in this module.
892    fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId>;
893
894    /// Use this when you're building the IR of a function to reference a function.
895    ///
896    /// TODO: Coalesce redundant decls and signatures.
897    /// TODO: Look into ways to reduce the risk of using a FuncRef in the wrong function.
898    fn declare_func_in_func(&mut self, func_id: FuncId, func: &mut ir::Function) -> ir::FuncRef {
899        let decl = &self.declarations().functions[func_id];
900        let signature = func.import_signature(decl.signature.clone());
901        let user_name_ref = func.declare_imported_user_function(ir::UserExternalName {
902            namespace: 0,
903            index: func_id.as_u32(),
904        });
905        let colocated = decl.linkage.is_final();
906        func.import_function(ir::ExtFuncData {
907            name: ir::ExternalName::user(user_name_ref),
908            signature,
909            colocated,
910        })
911    }
912
913    /// Use this when you're building the IR of a function to reference a data object.
914    ///
915    /// TODO: Same as above.
916    fn declare_data_in_func(&self, data: DataId, func: &mut ir::Function) -> ir::GlobalValue {
917        let decl = &self.declarations().data_objects[data];
918        let colocated = decl.linkage.is_final();
919        let user_name_ref = func.declare_imported_user_function(ir::UserExternalName {
920            namespace: 1,
921            index: data.as_u32(),
922        });
923        func.create_global_value(ir::GlobalValueData::Symbol {
924            name: ir::ExternalName::user(user_name_ref),
925            offset: ir::immediates::Imm64::new(0),
926            colocated,
927            tls: decl.tls,
928        })
929    }
930
931    /// TODO: Same as above.
932    fn declare_func_in_data(&self, func_id: FuncId, data: &mut DataDescription) -> ir::FuncRef {
933        data.import_function(ModuleRelocTarget::user(0, func_id.as_u32()))
934    }
935
936    /// TODO: Same as above.
937    fn declare_data_in_data(&self, data_id: DataId, data: &mut DataDescription) -> ir::GlobalValue {
938        data.import_global_value(ModuleRelocTarget::user(1, data_id.as_u32()))
939    }
940
941    /// Define a function, producing the function body from the given `Context`.
942    ///
943    /// Returns the size of the function's code and constant data.
944    ///
945    /// Unlike [`define_function_with_control_plane`] this uses a default [`ControlPlane`] for
946    /// convenience.
947    ///
948    /// Note: After calling this function the given `Context` will contain the compiled function.
949    ///
950    /// [`define_function_with_control_plane`]: Self::define_function_with_control_plane
951    fn define_function(&mut self, func: FuncId, ctx: &mut Context) -> ModuleResult<()> {
952        self.define_function_with_control_plane(func, ctx, &mut ControlPlane::default())
953    }
954
955    /// Define a function, producing the function body from the given `Context`.
956    ///
957    /// Returns the size of the function's code and constant data.
958    ///
959    /// Note: After calling this function the given `Context` will contain the compiled function.
960    fn define_function_with_control_plane(
961        &mut self,
962        func: FuncId,
963        ctx: &mut Context,
964        ctrl_plane: &mut ControlPlane,
965    ) -> ModuleResult<()>;
966
967    /// Define a function, taking the function body from the given `bytes`.
968    ///
969    /// This function is generally only useful if you need to precisely specify
970    /// the emitted instructions for some reason; otherwise, you should use
971    /// `define_function`.
972    ///
973    /// Returns the size of the function's code.
974    fn define_function_bytes(
975        &mut self,
976        func_id: FuncId,
977        alignment: u64,
978        bytes: &[u8],
979        relocs: &[ModuleReloc],
980    ) -> ModuleResult<()>;
981
982    /// Define a data object, producing the data contents from the given `DataContext`.
983    fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()>;
984}
985
986impl<M: Module + ?Sized> Module for &mut M {
987    fn isa(&self) -> &dyn isa::TargetIsa {
988        (**self).isa()
989    }
990
991    fn declarations(&self) -> &ModuleDeclarations {
992        (**self).declarations()
993    }
994
995    fn get_name(&self, name: &str) -> Option<FuncOrDataId> {
996        (**self).get_name(name)
997    }
998
999    fn target_config(&self) -> isa::TargetFrontendConfig {
1000        (**self).target_config()
1001    }
1002
1003    fn make_context(&self) -> Context {
1004        (**self).make_context()
1005    }
1006
1007    fn clear_context(&self, ctx: &mut Context) {
1008        (**self).clear_context(ctx)
1009    }
1010
1011    fn make_signature(&self) -> ir::Signature {
1012        (**self).make_signature()
1013    }
1014
1015    fn clear_signature(&self, sig: &mut ir::Signature) {
1016        (**self).clear_signature(sig)
1017    }
1018
1019    fn declare_function(
1020        &mut self,
1021        name: &str,
1022        linkage: Linkage,
1023        signature: &ir::Signature,
1024    ) -> ModuleResult<FuncId> {
1025        (**self).declare_function(name, linkage, signature)
1026    }
1027
1028    fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
1029        (**self).declare_anonymous_function(signature)
1030    }
1031
1032    fn declare_data(
1033        &mut self,
1034        name: &str,
1035        linkage: Linkage,
1036        writable: bool,
1037        tls: bool,
1038    ) -> ModuleResult<DataId> {
1039        (**self).declare_data(name, linkage, writable, tls)
1040    }
1041
1042    fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
1043        (**self).declare_anonymous_data(writable, tls)
1044    }
1045
1046    fn declare_func_in_func(&mut self, func: FuncId, in_func: &mut ir::Function) -> ir::FuncRef {
1047        (**self).declare_func_in_func(func, in_func)
1048    }
1049
1050    fn declare_data_in_func(&self, data: DataId, func: &mut ir::Function) -> ir::GlobalValue {
1051        (**self).declare_data_in_func(data, func)
1052    }
1053
1054    fn declare_func_in_data(&self, func_id: FuncId, data: &mut DataDescription) -> ir::FuncRef {
1055        (**self).declare_func_in_data(func_id, data)
1056    }
1057
1058    fn declare_data_in_data(&self, data_id: DataId, data: &mut DataDescription) -> ir::GlobalValue {
1059        (**self).declare_data_in_data(data_id, data)
1060    }
1061
1062    fn define_function(&mut self, func: FuncId, ctx: &mut Context) -> ModuleResult<()> {
1063        (**self).define_function(func, ctx)
1064    }
1065
1066    fn define_function_with_control_plane(
1067        &mut self,
1068        func: FuncId,
1069        ctx: &mut Context,
1070        ctrl_plane: &mut ControlPlane,
1071    ) -> ModuleResult<()> {
1072        (**self).define_function_with_control_plane(func, ctx, ctrl_plane)
1073    }
1074
1075    fn define_function_bytes(
1076        &mut self,
1077        func_id: FuncId,
1078        alignment: u64,
1079        bytes: &[u8],
1080        relocs: &[ModuleReloc],
1081    ) -> ModuleResult<()> {
1082        (**self).define_function_bytes(func_id, alignment, bytes, relocs)
1083    }
1084
1085    fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
1086        (**self).define_data(data_id, data)
1087    }
1088}
1089
1090impl<M: Module + ?Sized> Module for Box<M> {
1091    fn isa(&self) -> &dyn isa::TargetIsa {
1092        (**self).isa()
1093    }
1094
1095    fn declarations(&self) -> &ModuleDeclarations {
1096        (**self).declarations()
1097    }
1098
1099    fn get_name(&self, name: &str) -> Option<FuncOrDataId> {
1100        (**self).get_name(name)
1101    }
1102
1103    fn target_config(&self) -> isa::TargetFrontendConfig {
1104        (**self).target_config()
1105    }
1106
1107    fn make_context(&self) -> Context {
1108        (**self).make_context()
1109    }
1110
1111    fn clear_context(&self, ctx: &mut Context) {
1112        (**self).clear_context(ctx)
1113    }
1114
1115    fn make_signature(&self) -> ir::Signature {
1116        (**self).make_signature()
1117    }
1118
1119    fn clear_signature(&self, sig: &mut ir::Signature) {
1120        (**self).clear_signature(sig)
1121    }
1122
1123    fn declare_function(
1124        &mut self,
1125        name: &str,
1126        linkage: Linkage,
1127        signature: &ir::Signature,
1128    ) -> ModuleResult<FuncId> {
1129        (**self).declare_function(name, linkage, signature)
1130    }
1131
1132    fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
1133        (**self).declare_anonymous_function(signature)
1134    }
1135
1136    fn declare_data(
1137        &mut self,
1138        name: &str,
1139        linkage: Linkage,
1140        writable: bool,
1141        tls: bool,
1142    ) -> ModuleResult<DataId> {
1143        (**self).declare_data(name, linkage, writable, tls)
1144    }
1145
1146    fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
1147        (**self).declare_anonymous_data(writable, tls)
1148    }
1149
1150    fn declare_func_in_func(&mut self, func: FuncId, in_func: &mut ir::Function) -> ir::FuncRef {
1151        (**self).declare_func_in_func(func, in_func)
1152    }
1153
1154    fn declare_data_in_func(&self, data: DataId, func: &mut ir::Function) -> ir::GlobalValue {
1155        (**self).declare_data_in_func(data, func)
1156    }
1157
1158    fn declare_func_in_data(&self, func_id: FuncId, data: &mut DataDescription) -> ir::FuncRef {
1159        (**self).declare_func_in_data(func_id, data)
1160    }
1161
1162    fn declare_data_in_data(&self, data_id: DataId, data: &mut DataDescription) -> ir::GlobalValue {
1163        (**self).declare_data_in_data(data_id, data)
1164    }
1165
1166    fn define_function(&mut self, func: FuncId, ctx: &mut Context) -> ModuleResult<()> {
1167        (**self).define_function(func, ctx)
1168    }
1169
1170    fn define_function_with_control_plane(
1171        &mut self,
1172        func: FuncId,
1173        ctx: &mut Context,
1174        ctrl_plane: &mut ControlPlane,
1175    ) -> ModuleResult<()> {
1176        (**self).define_function_with_control_plane(func, ctx, ctrl_plane)
1177    }
1178
1179    fn define_function_bytes(
1180        &mut self,
1181        func_id: FuncId,
1182        alignment: u64,
1183        bytes: &[u8],
1184        relocs: &[ModuleReloc],
1185    ) -> ModuleResult<()> {
1186        (**self).define_function_bytes(func_id, alignment, bytes, relocs)
1187    }
1188
1189    fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
1190        (**self).define_data(data_id, data)
1191    }
1192}