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