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 `DataContext`?
7 
8 use super::HashMap;
9 use crate::data_context::DataContext;
10 use crate::Backend;
11 use cranelift_codegen::binemit::{self, CodeInfo};
12 use cranelift_codegen::entity::{entity_impl, PrimaryMap};
13 use cranelift_codegen::{ir, isa, CodegenError, Context};
14 use log::info;
15 use std::borrow::ToOwned;
16 use std::convert::TryInto;
17 use std::string::String;
18 use std::vec::Vec;
19 use thiserror::Error;
20 
21 /// A function identifier for use in the `Module` interface.
22 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
23 pub struct FuncId(u32);
24 entity_impl!(FuncId, "funcid");
25 
26 /// Function identifiers are namespace 0 in `ir::ExternalName`
27 impl From<FuncId> for ir::ExternalName {
28     fn from(id: FuncId) -> Self {
29         Self::User {
30             namespace: 0,
31             index: id.0,
32         }
33     }
34 }
35 
36 /// A data object identifier for use in the `Module` interface.
37 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
38 pub struct DataId(u32);
39 entity_impl!(DataId, "dataid");
40 
41 /// Data identifiers are namespace 1 in `ir::ExternalName`
42 impl From<DataId> for ir::ExternalName {
43     fn from(id: DataId) -> Self {
44         Self::User {
45             namespace: 1,
46             index: id.0,
47         }
48     }
49 }
50 
51 /// Linkage refers to where an entity is defined and who can see it.
52 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
53 pub enum Linkage {
54     /// Defined outside of a module.
55     Import,
56     /// Defined inside the module, but not visible outside it.
57     Local,
58     /// Defined inside the module, visible outside it, and may be preempted.
59     Preemptible,
60     /// Defined inside the module, visible inside the current static linkage unit, but not outside.
61     ///
62     /// A static linkage unit is the combination of all object files passed to a linker to create
63     /// an executable or dynamic library.
64     Hidden,
65     /// Defined inside the module, and visible outside it.
66     Export,
67 }
68 
69 impl Linkage {
70     fn merge(a: Self, b: Self) -> Self {
71         match a {
72             Self::Export => Self::Export,
73             Self::Hidden => match b {
74                 Self::Export => Self::Export,
75                 Self::Preemptible => Self::Preemptible,
76                 _ => Self::Hidden,
77             },
78             Self::Preemptible => match b {
79                 Self::Export => Self::Export,
80                 _ => Self::Preemptible,
81             },
82             Self::Local => match b {
83                 Self::Export => Self::Export,
84                 Self::Hidden => Self::Hidden,
85                 Self::Preemptible => Self::Preemptible,
86                 Self::Local | Self::Import => Self::Local,
87             },
88             Self::Import => b,
89         }
90     }
91 
92     /// Test whether this linkage can have a definition.
93     pub fn is_definable(self) -> bool {
94         match self {
95             Self::Import => false,
96             Self::Local | Self::Preemptible | Self::Hidden | Self::Export => true,
97         }
98     }
99 
100     /// Test whether this linkage will have a definition that cannot be preempted.
101     pub fn is_final(self) -> bool {
102         match self {
103             Self::Import | Self::Preemptible => false,
104             Self::Local | Self::Hidden | Self::Export => true,
105         }
106     }
107 }
108 
109 /// A declared name may refer to either a function or data declaration
110 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
111 pub enum FuncOrDataId {
112     /// When it's a FuncId
113     Func(FuncId),
114     /// When it's a DataId
115     Data(DataId),
116 }
117 
118 /// Mapping to `ir::ExternalName` is trivial based on the `FuncId` and `DataId` mapping.
119 impl From<FuncOrDataId> for ir::ExternalName {
120     fn from(id: FuncOrDataId) -> Self {
121         match id {
122             FuncOrDataId::Func(funcid) => Self::from(funcid),
123             FuncOrDataId::Data(dataid) => Self::from(dataid),
124         }
125     }
126 }
127 
128 /// Information about a function which can be called.
129 pub struct FunctionDeclaration {
130     pub name: String,
131     pub linkage: Linkage,
132     pub signature: ir::Signature,
133 }
134 
135 /// Error messages for all `Module` and `Backend` methods
136 #[derive(Error, Debug)]
137 pub enum ModuleError {
138     /// Indicates an identifier was used before it was declared
139     #[error("Undeclared identifier: {0}")]
140     Undeclared(String),
141     /// Indicates an identifier was used as data/function first, but then used as the other
142     #[error("Incompatible declaration of identifier: {0}")]
143     IncompatibleDeclaration(String),
144     /// Indicates a function identifier was declared with a
145     /// different signature than declared previously
146     #[error("Function {0} signature {2:?} is incompatible with previous declaration {1:?}")]
147     IncompatibleSignature(String, ir::Signature, ir::Signature),
148     /// Indicates an identifier was defined more than once
149     #[error("Duplicate definition of identifier: {0}")]
150     DuplicateDefinition(String),
151     /// Indicates an identifier was defined, but was declared as an import
152     #[error("Invalid to define identifier declared as an import: {0}")]
153     InvalidImportDefinition(String),
154     /// Indicates a too-long function was defined
155     #[error("Function {0} exceeds the maximum function size")]
156     FunctionTooLarge(String),
157     /// Wraps a `cranelift-codegen` error
158     #[error("Compilation error: {0}")]
159     Compilation(#[from] CodegenError),
160     /// Wraps a generic error from a backend
161     #[error("Backend error: {0}")]
162     Backend(#[source] anyhow::Error),
163 }
164 
165 /// A convenient alias for a `Result` that uses `ModuleError` as the error type.
166 pub type ModuleResult<T> = Result<T, ModuleError>;
167 
168 /// A function belonging to a `Module`.
169 pub struct ModuleFunction<B>
170 where
171     B: Backend,
172 {
173     /// The function declaration.
174     pub decl: FunctionDeclaration,
175     /// The compiled artifact, once it's available.
176     pub compiled: Option<B::CompiledFunction>,
177 }
178 
179 impl<B> ModuleFunction<B>
180 where
181     B: Backend,
182 {
183     fn merge(&mut self, linkage: Linkage, sig: &ir::Signature) -> Result<(), ModuleError> {
184         self.decl.linkage = Linkage::merge(self.decl.linkage, linkage);
185         if &self.decl.signature != sig {
186             return Err(ModuleError::IncompatibleSignature(
187                 self.decl.name.clone(),
188                 self.decl.signature.clone(),
189                 sig.clone(),
190             ));
191         }
192         Ok(())
193     }
194 }
195 
196 /// Information about a data object which can be accessed.
197 pub struct DataDeclaration {
198     pub name: String,
199     pub linkage: Linkage,
200     pub writable: bool,
201     pub tls: bool,
202     pub align: Option<u8>,
203 }
204 
205 /// A data object belonging to a `Module`.
206 struct ModuleData<B>
207 where
208     B: Backend,
209 {
210     /// The data object declaration.
211     decl: DataDeclaration,
212     /// The "compiled" artifact, once it's available.
213     compiled: Option<B::CompiledData>,
214 }
215 
216 impl<B> ModuleData<B>
217 where
218     B: Backend,
219 {
220     fn merge(&mut self, linkage: Linkage, writable: bool, tls: bool, align: Option<u8>) {
221         self.decl.linkage = Linkage::merge(self.decl.linkage, linkage);
222         self.decl.writable = self.decl.writable || writable;
223         self.decl.align = self.decl.align.max(align);
224         assert_eq!(
225             self.decl.tls, tls,
226             "Can't change TLS data object to normal or in the opposite way",
227         );
228     }
229 }
230 
231 /// The functions and data objects belonging to a module.
232 struct ModuleContents<B>
233 where
234     B: Backend,
235 {
236     functions: PrimaryMap<FuncId, ModuleFunction<B>>,
237     data_objects: PrimaryMap<DataId, ModuleData<B>>,
238 }
239 
240 impl<B> ModuleContents<B>
241 where
242     B: Backend,
243 {
244     fn get_function_id(&self, name: &ir::ExternalName) -> FuncId {
245         if let ir::ExternalName::User { namespace, index } = *name {
246             debug_assert_eq!(namespace, 0);
247             FuncId::from_u32(index)
248         } else {
249             panic!("unexpected ExternalName kind {}", name)
250         }
251     }
252 
253     fn get_data_id(&self, name: &ir::ExternalName) -> DataId {
254         if let ir::ExternalName::User { namespace, index } = *name {
255             debug_assert_eq!(namespace, 1);
256             DataId::from_u32(index)
257         } else {
258             panic!("unexpected ExternalName kind {}", name)
259         }
260     }
261 
262     fn get_function_info(&self, name: &ir::ExternalName) -> &ModuleFunction<B> {
263         &self.functions[self.get_function_id(name)]
264     }
265 
266     /// Get the `DataDeclaration` for the function named by `name`.
267     fn get_data_info(&self, name: &ir::ExternalName) -> &ModuleData<B> {
268         &self.data_objects[self.get_data_id(name)]
269     }
270 }
271 
272 /// This provides a view to the state of a module which allows `ir::ExternalName`s to be translated
273 /// into `FunctionDeclaration`s and `DataDeclaration`s.
274 pub struct ModuleNamespace<'a, B: 'a>
275 where
276     B: Backend,
277 {
278     contents: &'a ModuleContents<B>,
279 }
280 
281 impl<'a, B> ModuleNamespace<'a, B>
282 where
283     B: Backend,
284 {
285     /// Get the `FuncId` for the function named by `name`.
286     pub fn get_function_id(&self, name: &ir::ExternalName) -> FuncId {
287         self.contents.get_function_id(name)
288     }
289 
290     /// Get the `DataId` for the data object named by `name`.
291     pub fn get_data_id(&self, name: &ir::ExternalName) -> DataId {
292         self.contents.get_data_id(name)
293     }
294 
295     /// Get the `FunctionDeclaration` for the function named by `name`.
296     pub fn get_function_decl(&self, name: &ir::ExternalName) -> &FunctionDeclaration {
297         &self.contents.get_function_info(name).decl
298     }
299 
300     /// Get the `DataDeclaration` for the data object named by `name`.
301     pub fn get_data_decl(&self, name: &ir::ExternalName) -> &DataDeclaration {
302         &self.contents.get_data_info(name).decl
303     }
304 
305     /// Get the definition for the function named by `name`, along with its name
306     /// and signature.
307     pub fn get_function_definition(
308         &self,
309         name: &ir::ExternalName,
310     ) -> (Option<&B::CompiledFunction>, &str, &ir::Signature) {
311         let info = self.contents.get_function_info(name);
312         debug_assert!(
313             !info.decl.linkage.is_definable() || info.compiled.is_some(),
314             "Finalization requires a definition for function {}.",
315             name,
316         );
317         debug_assert_eq!(info.decl.linkage.is_definable(), info.compiled.is_some());
318 
319         (
320             info.compiled.as_ref(),
321             &info.decl.name,
322             &info.decl.signature,
323         )
324     }
325 
326     /// Get the definition for the data object named by `name`, along with its name
327     /// and writable flag
328     pub fn get_data_definition(
329         &self,
330         name: &ir::ExternalName,
331     ) -> (Option<&B::CompiledData>, &str, bool) {
332         let info = self.contents.get_data_info(name);
333         debug_assert!(
334             !info.decl.linkage.is_definable() || info.compiled.is_some(),
335             "Finalization requires a definition for data object {}.",
336             name,
337         );
338         debug_assert_eq!(info.decl.linkage.is_definable(), info.compiled.is_some());
339 
340         (info.compiled.as_ref(), &info.decl.name, info.decl.writable)
341     }
342 
343     /// Return whether `name` names a function, rather than a data object.
344     pub fn is_function(&self, name: &ir::ExternalName) -> bool {
345         if let ir::ExternalName::User { namespace, .. } = *name {
346             namespace == 0
347         } else {
348             panic!("unexpected ExternalName kind {}", name)
349         }
350     }
351 }
352 
353 /// A `Module` is a utility for collecting functions and data objects, and linking them together.
354 pub struct Module<B>
355 where
356     B: Backend,
357 {
358     names: HashMap<String, FuncOrDataId>,
359     contents: ModuleContents<B>,
360     functions_to_finalize: Vec<FuncId>,
361     data_objects_to_finalize: Vec<DataId>,
362     backend: B,
363 }
364 
365 pub struct ModuleCompiledFunction {
366     pub size: binemit::CodeOffset,
367 }
368 
369 impl<B> Module<B>
370 where
371     B: Backend,
372 {
373     /// Create a new `Module`.
374     pub fn new(backend_builder: B::Builder) -> Self {
375         Self {
376             names: HashMap::new(),
377             contents: ModuleContents {
378                 functions: PrimaryMap::new(),
379                 data_objects: PrimaryMap::new(),
380             },
381             functions_to_finalize: Vec::new(),
382             data_objects_to_finalize: Vec::new(),
383             backend: B::new(backend_builder),
384         }
385     }
386 
387     /// Get the module identifier for a given name, if that name
388     /// has been declared.
389     pub fn get_name(&self, name: &str) -> Option<FuncOrDataId> {
390         self.names.get(name).cloned()
391     }
392 
393     /// Return the target information needed by frontends to produce Cranelift IR
394     /// for the current target.
395     pub fn target_config(&self) -> isa::TargetFrontendConfig {
396         self.backend.isa().frontend_config()
397     }
398 
399     /// Create a new `Context` initialized for use with this `Module`.
400     ///
401     /// This ensures that the `Context` is initialized with the default calling
402     /// convention for the `TargetIsa`.
403     pub fn make_context(&self) -> Context {
404         let mut ctx = Context::new();
405         ctx.func.signature.call_conv = self.backend.isa().default_call_conv();
406         ctx
407     }
408 
409     /// Clear the given `Context` and reset it for use with a new function.
410     ///
411     /// This ensures that the `Context` is initialized with the default calling
412     /// convention for the `TargetIsa`.
413     pub fn clear_context(&self, ctx: &mut Context) {
414         ctx.clear();
415         ctx.func.signature.call_conv = self.backend.isa().default_call_conv();
416     }
417 
418     /// Create a new empty `Signature` with the default calling convention for
419     /// the `TargetIsa`, to which parameter and return types can be added for
420     /// declaring a function to be called by this `Module`.
421     pub fn make_signature(&self) -> ir::Signature {
422         ir::Signature::new(self.backend.isa().default_call_conv())
423     }
424 
425     /// Clear the given `Signature` and reset for use with a new function.
426     ///
427     /// This ensures that the `Signature` is initialized with the default
428     /// calling convention for the `TargetIsa`.
429     pub fn clear_signature(&self, sig: &mut ir::Signature) {
430         sig.clear(self.backend.isa().default_call_conv());
431     }
432 
433     /// Declare a function in this module.
434     pub fn declare_function(
435         &mut self,
436         name: &str,
437         linkage: Linkage,
438         signature: &ir::Signature,
439     ) -> ModuleResult<FuncId> {
440         // TODO: Can we avoid allocating names so often?
441         use super::hash_map::Entry::*;
442         match self.names.entry(name.to_owned()) {
443             Occupied(entry) => match *entry.get() {
444                 FuncOrDataId::Func(id) => {
445                     let existing = &mut self.contents.functions[id];
446                     existing.merge(linkage, signature)?;
447                     self.backend
448                         .declare_function(id, name, existing.decl.linkage);
449                     Ok(id)
450                 }
451                 FuncOrDataId::Data(..) => {
452                     Err(ModuleError::IncompatibleDeclaration(name.to_owned()))
453                 }
454             },
455             Vacant(entry) => {
456                 let id = self.contents.functions.push(ModuleFunction {
457                     decl: FunctionDeclaration {
458                         name: name.to_owned(),
459                         linkage,
460                         signature: signature.clone(),
461                     },
462                     compiled: None,
463                 });
464                 entry.insert(FuncOrDataId::Func(id));
465                 self.backend.declare_function(id, name, linkage);
466                 Ok(id)
467             }
468         }
469     }
470 
471     /// An iterator over functions that have been declared in this module.
472     pub fn declared_functions(&self) -> core::slice::Iter<'_, ModuleFunction<B>> {
473         self.contents.functions.values()
474     }
475 
476     /// Declare a data object in this module.
477     pub fn declare_data(
478         &mut self,
479         name: &str,
480         linkage: Linkage,
481         writable: bool,
482         tls: bool,
483         align: Option<u8>, // An alignment bigger than 128 is unlikely
484     ) -> ModuleResult<DataId> {
485         // TODO: Can we avoid allocating names so often?
486         use super::hash_map::Entry::*;
487         match self.names.entry(name.to_owned()) {
488             Occupied(entry) => match *entry.get() {
489                 FuncOrDataId::Data(id) => {
490                     let existing = &mut self.contents.data_objects[id];
491                     existing.merge(linkage, writable, tls, align);
492                     self.backend.declare_data(
493                         id,
494                         name,
495                         existing.decl.linkage,
496                         existing.decl.writable,
497                         existing.decl.tls,
498                         existing.decl.align,
499                     );
500                     Ok(id)
501                 }
502 
503                 FuncOrDataId::Func(..) => {
504                     Err(ModuleError::IncompatibleDeclaration(name.to_owned()))
505                 }
506             },
507             Vacant(entry) => {
508                 let id = self.contents.data_objects.push(ModuleData {
509                     decl: DataDeclaration {
510                         name: name.to_owned(),
511                         linkage,
512                         writable,
513                         tls,
514                         align,
515                     },
516                     compiled: None,
517                 });
518                 entry.insert(FuncOrDataId::Data(id));
519                 self.backend
520                     .declare_data(id, name, linkage, writable, tls, align);
521                 Ok(id)
522             }
523         }
524     }
525 
526     /// Use this when you're building the IR of a function to reference a function.
527     ///
528     /// TODO: Coalesce redundant decls and signatures.
529     /// TODO: Look into ways to reduce the risk of using a FuncRef in the wrong function.
530     pub fn declare_func_in_func(&self, func: FuncId, in_func: &mut ir::Function) -> ir::FuncRef {
531         let decl = &self.contents.functions[func].decl;
532         let signature = in_func.import_signature(decl.signature.clone());
533         let colocated = decl.linkage.is_final();
534         in_func.import_function(ir::ExtFuncData {
535             name: ir::ExternalName::user(0, func.as_u32()),
536             signature,
537             colocated,
538         })
539     }
540 
541     /// Use this when you're building the IR of a function to reference a data object.
542     ///
543     /// TODO: Same as above.
544     pub fn declare_data_in_func(&self, data: DataId, func: &mut ir::Function) -> ir::GlobalValue {
545         let decl = &self.contents.data_objects[data].decl;
546         let colocated = decl.linkage.is_final();
547         func.create_global_value(ir::GlobalValueData::Symbol {
548             name: ir::ExternalName::user(1, data.as_u32()),
549             offset: ir::immediates::Imm64::new(0),
550             colocated,
551             tls: decl.tls,
552         })
553     }
554 
555     /// TODO: Same as above.
556     pub fn declare_func_in_data(&self, func: FuncId, ctx: &mut DataContext) -> ir::FuncRef {
557         ctx.import_function(ir::ExternalName::user(0, func.as_u32()))
558     }
559 
560     /// TODO: Same as above.
561     pub fn declare_data_in_data(&self, data: DataId, ctx: &mut DataContext) -> ir::GlobalValue {
562         ctx.import_global_value(ir::ExternalName::user(1, data.as_u32()))
563     }
564 
565     /// Define a function, producing the function body from the given `Context`.
566     ///
567     /// Returns the size of the function's code and constant data.
568     ///
569     /// Note: After calling this function the given `Context` will contain the compiled function.
570     pub fn define_function<TS>(
571         &mut self,
572         func: FuncId,
573         ctx: &mut Context,
574         trap_sink: &mut TS,
575     ) -> ModuleResult<ModuleCompiledFunction>
576     where
577         TS: binemit::TrapSink,
578     {
579         info!(
580             "defining function {}: {}",
581             func,
582             ctx.func.display(self.backend.isa())
583         );
584         let CodeInfo { total_size, .. } = ctx.compile(self.backend.isa())?;
585         let info = &self.contents.functions[func];
586         if info.compiled.is_some() {
587             return Err(ModuleError::DuplicateDefinition(info.decl.name.clone()));
588         }
589         if !info.decl.linkage.is_definable() {
590             return Err(ModuleError::InvalidImportDefinition(info.decl.name.clone()));
591         }
592 
593         let compiled = self.backend.define_function(
594             func,
595             &info.decl.name,
596             ctx,
597             &ModuleNamespace::<B> {
598                 contents: &self.contents,
599             },
600             total_size,
601             trap_sink,
602         )?;
603 
604         self.contents.functions[func].compiled = Some(compiled);
605         self.functions_to_finalize.push(func);
606         Ok(ModuleCompiledFunction { size: total_size })
607     }
608 
609     /// Define a function, taking the function body from the given `bytes`.
610     ///
611     /// This function is generally only useful if you need to precisely specify
612     /// the emitted instructions for some reason; otherwise, you should use
613     /// `define_function`.
614     ///
615     /// Returns the size of the function's code.
616     pub fn define_function_bytes(
617         &mut self,
618         func: FuncId,
619         bytes: &[u8],
620     ) -> ModuleResult<ModuleCompiledFunction> {
621         info!("defining function {} with bytes", func);
622         let info = &self.contents.functions[func];
623         if info.compiled.is_some() {
624             return Err(ModuleError::DuplicateDefinition(info.decl.name.clone()));
625         }
626         if !info.decl.linkage.is_definable() {
627             return Err(ModuleError::InvalidImportDefinition(info.decl.name.clone()));
628         }
629 
630         let total_size: u32 = match bytes.len().try_into() {
631             Ok(total_size) => total_size,
632             _ => Err(ModuleError::FunctionTooLarge(info.decl.name.clone()))?,
633         };
634 
635         let compiled = self.backend.define_function_bytes(
636             func,
637             &info.decl.name,
638             bytes,
639             &ModuleNamespace::<B> {
640                 contents: &self.contents,
641             },
642         )?;
643 
644         self.contents.functions[func].compiled = Some(compiled);
645         self.functions_to_finalize.push(func);
646         Ok(ModuleCompiledFunction { size: total_size })
647     }
648 
649     /// Define a data object, producing the data contents from the given `DataContext`.
650     pub fn define_data(&mut self, data: DataId, data_ctx: &DataContext) -> ModuleResult<()> {
651         let compiled = {
652             let info = &self.contents.data_objects[data];
653             if info.compiled.is_some() {
654                 return Err(ModuleError::DuplicateDefinition(info.decl.name.clone()));
655             }
656             if !info.decl.linkage.is_definable() {
657                 return Err(ModuleError::InvalidImportDefinition(info.decl.name.clone()));
658             }
659             Some(self.backend.define_data(
660                 data,
661                 &info.decl.name,
662                 info.decl.writable,
663                 info.decl.tls,
664                 info.decl.align,
665                 data_ctx,
666                 &ModuleNamespace::<B> {
667                     contents: &self.contents,
668                 },
669             )?)
670         };
671         self.contents.data_objects[data].compiled = compiled;
672         self.data_objects_to_finalize.push(data);
673         Ok(())
674     }
675 
676     /// Write the address of `what` into the data for `data` at `offset`. `data` must refer to a
677     /// defined data object.
678     pub fn write_data_funcaddr(&mut self, data: DataId, offset: usize, what: ir::FuncRef) {
679         let info = &mut self.contents.data_objects[data];
680         debug_assert!(
681             info.decl.linkage.is_definable(),
682             "imported data cannot contain references"
683         );
684         self.backend.write_data_funcaddr(
685             &mut info
686                 .compiled
687                 .as_mut()
688                 .expect("`data` must refer to a defined data object"),
689             offset,
690             what,
691         );
692     }
693 
694     /// Write the address of `what` plus `addend` into the data for `data` at `offset`. `data` must
695     /// refer to a defined data object.
696     pub fn write_data_dataaddr(
697         &mut self,
698         data: DataId,
699         offset: usize,
700         what: ir::GlobalValue,
701         addend: binemit::Addend,
702     ) {
703         let info = &mut self.contents.data_objects[data];
704         debug_assert!(
705             info.decl.linkage.is_definable(),
706             "imported data cannot contain references"
707         );
708         self.backend.write_data_dataaddr(
709             &mut info
710                 .compiled
711                 .as_mut()
712                 .expect("`data` must refer to a defined data object"),
713             offset,
714             what,
715             addend,
716         );
717     }
718 
719     /// Finalize all functions and data objects that are defined but not yet finalized.
720     /// All symbols referenced in their bodies that are declared as needing a definition
721     /// must be defined by this point.
722     ///
723     /// Use `get_finalized_function` and `get_finalized_data` to obtain the final
724     /// artifacts.
725     ///
726     /// This method is not relevant for `Backend` implementations that do not provide
727     /// `Backend::FinalizedFunction` or `Backend::FinalizedData`.
728     pub fn finalize_definitions(&mut self) {
729         for func in self.functions_to_finalize.drain(..) {
730             let info = &self.contents.functions[func];
731             debug_assert!(info.decl.linkage.is_definable());
732             self.backend.finalize_function(
733                 func,
734                 info.compiled
735                     .as_ref()
736                     .expect("function must be compiled before it can be finalized"),
737                 &ModuleNamespace::<B> {
738                     contents: &self.contents,
739                 },
740             );
741         }
742         for data in self.data_objects_to_finalize.drain(..) {
743             let info = &self.contents.data_objects[data];
744             debug_assert!(info.decl.linkage.is_definable());
745             self.backend.finalize_data(
746                 data,
747                 info.compiled
748                     .as_ref()
749                     .expect("data object must be compiled before it can be finalized"),
750                 &ModuleNamespace::<B> {
751                     contents: &self.contents,
752                 },
753             );
754         }
755         self.backend.publish();
756     }
757 
758     /// Return the finalized artifact from the backend, if it provides one.
759     pub fn get_finalized_function(&mut self, func: FuncId) -> B::FinalizedFunction {
760         let info = &self.contents.functions[func];
761         debug_assert!(
762             !self.functions_to_finalize.iter().any(|x| *x == func),
763             "function not yet finalized"
764         );
765         self.backend.get_finalized_function(
766             info.compiled
767                 .as_ref()
768                 .expect("function must be compiled before it can be finalized"),
769         )
770     }
771 
772     /// Return the finalized artifact from the backend, if it provides one.
773     pub fn get_finalized_data(&mut self, data: DataId) -> B::FinalizedData {
774         let info = &self.contents.data_objects[data];
775         debug_assert!(
776             !self.data_objects_to_finalize.iter().any(|x| *x == data),
777             "data object not yet finalized"
778         );
779         self.backend.get_finalized_data(
780             info.compiled
781                 .as_ref()
782                 .expect("data object must be compiled before it can be finalized"),
783         )
784     }
785 
786     /// Return the target isa
787     pub fn isa(&self) -> &dyn isa::TargetIsa {
788         self.backend.isa()
789     }
790 
791     /// Consume the module and return the resulting `Product`. Some `Backend`
792     /// implementations may provide additional functionality available after
793     /// a `Module` is complete.
794     pub fn finish(self) -> B::Product {
795         self.backend.finish(&ModuleNamespace::<B> {
796             contents: &self.contents,
797         })
798     }
799 }
800