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