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