1747ad3c4Slazypassion //! Intermediate representation of a function. 2747ad3c4Slazypassion //! 3832666c4SRyan Hunt //! The `Function` struct defined in this module owns all of its basic blocks and 4747ad3c4Slazypassion //! instructions. 5747ad3c4Slazypassion 6747ad3c4Slazypassion use crate::entity::{PrimaryMap, SecondaryMap}; 7747ad3c4Slazypassion use crate::ir::{ 8c8a6adf8STrevor Elliott self, Block, DataFlowGraph, DynamicStackSlot, DynamicStackSlotData, DynamicStackSlots, 980c147d9STrevor Elliott DynamicType, ExtFuncData, FuncRef, GlobalValue, GlobalValueData, Inst, JumpTable, 1080c147d9STrevor Elliott JumpTableData, Layout, Opcode, SigRef, Signature, SourceLocs, StackSlot, StackSlotData, 1180c147d9STrevor Elliott StackSlots, Table, TableData, Type, 12747ad3c4Slazypassion }; 1343a86f14SBenjamin Bouvier use crate::isa::CallConv; 14747ad3c4Slazypassion use crate::write::write_function; 158a9b1a90SBenjamin Bouvier use crate::HashMap; 16a0c2276eSbjorn3 #[cfg(feature = "enable-serde")] 17a0c2276eSbjorn3 use alloc::string::String; 18747ad3c4Slazypassion use core::fmt; 19747ad3c4Slazypassion 202fc964eaSbjorn3 #[cfg(feature = "enable-serde")] 21a0c2276eSbjorn3 use serde::de::{Deserializer, Error}; 22a0c2276eSbjorn3 #[cfg(feature = "enable-serde")] 23a0c2276eSbjorn3 use serde::ser::Serializer; 24a0c2276eSbjorn3 #[cfg(feature = "enable-serde")] 252fc964eaSbjorn3 use serde::{Deserialize, Serialize}; 262fc964eaSbjorn3 278a9b1a90SBenjamin Bouvier use super::entities::UserExternalNameRef; 288a9b1a90SBenjamin Bouvier use super::extname::UserFuncName; 298a9b1a90SBenjamin Bouvier use super::{RelSourceLoc, SourceLoc, UserExternalName}; 308a9b1a90SBenjamin Bouvier 31a0c2276eSbjorn3 /// A version marker used to ensure that serialized clif ir is never deserialized with a 32a0c2276eSbjorn3 /// different version of Cranelift. 3391d1d246Sbjorn3 #[derive(Default, Copy, Clone, Debug, PartialEq, Hash)] 34a0c2276eSbjorn3 pub struct VersionMarker; 35a0c2276eSbjorn3 36a0c2276eSbjorn3 #[cfg(feature = "enable-serde")] 37a0c2276eSbjorn3 impl Serialize for VersionMarker { 38a0c2276eSbjorn3 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 39a0c2276eSbjorn3 where 40a0c2276eSbjorn3 S: Serializer, 41a0c2276eSbjorn3 { 42a0c2276eSbjorn3 crate::VERSION.serialize(serializer) 43a0c2276eSbjorn3 } 44a0c2276eSbjorn3 } 45a0c2276eSbjorn3 46a0c2276eSbjorn3 #[cfg(feature = "enable-serde")] 47a0c2276eSbjorn3 impl<'de> Deserialize<'de> for VersionMarker { 48a0c2276eSbjorn3 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 49a0c2276eSbjorn3 where 50a0c2276eSbjorn3 D: Deserializer<'de>, 51a0c2276eSbjorn3 { 52a0c2276eSbjorn3 let version = String::deserialize(deserializer)?; 53a0c2276eSbjorn3 if version != crate::VERSION { 54a0c2276eSbjorn3 return Err(D::Error::custom(&format!( 55a0c2276eSbjorn3 "Expected a clif ir function for version {}, found one for version {}", 56a0c2276eSbjorn3 crate::VERSION, 57a0c2276eSbjorn3 version, 58a0c2276eSbjorn3 ))); 59a0c2276eSbjorn3 } 60a0c2276eSbjorn3 Ok(VersionMarker) 61a0c2276eSbjorn3 } 62a0c2276eSbjorn3 } 63a0c2276eSbjorn3 648a9b1a90SBenjamin Bouvier /// Function parameters used when creating this function, and that will become applied after 658a9b1a90SBenjamin Bouvier /// compilation to materialize the final `CompiledCode`. 66a9cda5afSAfonso Bordado #[derive(Clone, PartialEq)] 679ec02f9dSChristopher Serr #[cfg_attr( 689ec02f9dSChristopher Serr feature = "enable-serde", 699ec02f9dSChristopher Serr derive(serde_derive::Serialize, serde_derive::Deserialize) 709ec02f9dSChristopher Serr )] 718a9b1a90SBenjamin Bouvier pub struct FunctionParameters { 728a9b1a90SBenjamin Bouvier /// The first `SourceLoc` appearing in the function, serving as a base for every relative 738a9b1a90SBenjamin Bouvier /// source loc in the function. 748a9b1a90SBenjamin Bouvier base_srcloc: Option<SourceLoc>, 758a9b1a90SBenjamin Bouvier 768a9b1a90SBenjamin Bouvier /// External user-defined function references. 778a9b1a90SBenjamin Bouvier user_named_funcs: PrimaryMap<UserExternalNameRef, UserExternalName>, 788a9b1a90SBenjamin Bouvier 798a9b1a90SBenjamin Bouvier /// Inverted mapping of `user_named_funcs`, to deduplicate internally. 808a9b1a90SBenjamin Bouvier user_ext_name_to_ref: HashMap<UserExternalName, UserExternalNameRef>, 818a9b1a90SBenjamin Bouvier } 828a9b1a90SBenjamin Bouvier 838a9b1a90SBenjamin Bouvier impl FunctionParameters { 848a9b1a90SBenjamin Bouvier /// Creates a new `FunctionParameters` with the given name. 858a9b1a90SBenjamin Bouvier pub fn new() -> Self { 868a9b1a90SBenjamin Bouvier Self { 878a9b1a90SBenjamin Bouvier base_srcloc: None, 888a9b1a90SBenjamin Bouvier user_named_funcs: Default::default(), 898a9b1a90SBenjamin Bouvier user_ext_name_to_ref: Default::default(), 908a9b1a90SBenjamin Bouvier } 918a9b1a90SBenjamin Bouvier } 928a9b1a90SBenjamin Bouvier 938a9b1a90SBenjamin Bouvier /// Returns the base `SourceLoc`. 948a9b1a90SBenjamin Bouvier /// 958a9b1a90SBenjamin Bouvier /// If it was never explicitly set with `ensure_base_srcloc`, will return an invalid 968a9b1a90SBenjamin Bouvier /// `SourceLoc`. 978a9b1a90SBenjamin Bouvier pub fn base_srcloc(&self) -> SourceLoc { 988a9b1a90SBenjamin Bouvier self.base_srcloc.unwrap_or_default() 998a9b1a90SBenjamin Bouvier } 1008a9b1a90SBenjamin Bouvier 1018a9b1a90SBenjamin Bouvier /// Sets the base `SourceLoc`, if not set yet, and returns the base value. 1028a9b1a90SBenjamin Bouvier pub fn ensure_base_srcloc(&mut self, srcloc: SourceLoc) -> SourceLoc { 1038a9b1a90SBenjamin Bouvier match self.base_srcloc { 1048a9b1a90SBenjamin Bouvier Some(val) => val, 1058a9b1a90SBenjamin Bouvier None => { 1068a9b1a90SBenjamin Bouvier self.base_srcloc = Some(srcloc); 1078a9b1a90SBenjamin Bouvier srcloc 1088a9b1a90SBenjamin Bouvier } 1098a9b1a90SBenjamin Bouvier } 1108a9b1a90SBenjamin Bouvier } 1118a9b1a90SBenjamin Bouvier 1128a9b1a90SBenjamin Bouvier /// Retrieve a `UserExternalNameRef` for the given name, or add a new one. 1138a9b1a90SBenjamin Bouvier /// 1148a9b1a90SBenjamin Bouvier /// This method internally deduplicates same `UserExternalName` so they map to the same 1158a9b1a90SBenjamin Bouvier /// reference. 1168a9b1a90SBenjamin Bouvier pub fn ensure_user_func_name(&mut self, name: UserExternalName) -> UserExternalNameRef { 1178a9b1a90SBenjamin Bouvier if let Some(reff) = self.user_ext_name_to_ref.get(&name) { 1188a9b1a90SBenjamin Bouvier *reff 1198a9b1a90SBenjamin Bouvier } else { 1208a9b1a90SBenjamin Bouvier let reff = self.user_named_funcs.push(name.clone()); 1218a9b1a90SBenjamin Bouvier self.user_ext_name_to_ref.insert(name, reff); 1228a9b1a90SBenjamin Bouvier reff 1238a9b1a90SBenjamin Bouvier } 1248a9b1a90SBenjamin Bouvier } 1258a9b1a90SBenjamin Bouvier 1268a9b1a90SBenjamin Bouvier /// Resets an already existing user function name to a new value. 1278a9b1a90SBenjamin Bouvier pub fn reset_user_func_name(&mut self, index: UserExternalNameRef, name: UserExternalName) { 1288a9b1a90SBenjamin Bouvier if let Some(prev_name) = self.user_named_funcs.get_mut(index) { 1298a9b1a90SBenjamin Bouvier self.user_ext_name_to_ref.remove(prev_name); 1308a9b1a90SBenjamin Bouvier *prev_name = name.clone(); 1318a9b1a90SBenjamin Bouvier self.user_ext_name_to_ref.insert(name, index); 1328a9b1a90SBenjamin Bouvier } 1338a9b1a90SBenjamin Bouvier } 1348a9b1a90SBenjamin Bouvier 1358a9b1a90SBenjamin Bouvier /// Returns the internal mapping of `UserExternalNameRef` to `UserExternalName`. 1368a9b1a90SBenjamin Bouvier pub fn user_named_funcs(&self) -> &PrimaryMap<UserExternalNameRef, UserExternalName> { 1378a9b1a90SBenjamin Bouvier &self.user_named_funcs 1388a9b1a90SBenjamin Bouvier } 1398a9b1a90SBenjamin Bouvier 1408a9b1a90SBenjamin Bouvier fn clear(&mut self) { 1418a9b1a90SBenjamin Bouvier self.base_srcloc = None; 1428a9b1a90SBenjamin Bouvier self.user_named_funcs.clear(); 1438a9b1a90SBenjamin Bouvier self.user_ext_name_to_ref.clear(); 1448a9b1a90SBenjamin Bouvier } 1458a9b1a90SBenjamin Bouvier } 1468a9b1a90SBenjamin Bouvier 1478a9b1a90SBenjamin Bouvier /// Function fields needed when compiling a function. 1488a9b1a90SBenjamin Bouvier /// 1498a9b1a90SBenjamin Bouvier /// Additionally, these fields can be the same for two functions that would be compiled the same 1508a9b1a90SBenjamin Bouvier /// way, and finalized by applying `FunctionParameters` onto their `CompiledCodeStencil`. 1518a9b1a90SBenjamin Bouvier #[derive(Clone, PartialEq, Hash)] 1529ec02f9dSChristopher Serr #[cfg_attr( 1539ec02f9dSChristopher Serr feature = "enable-serde", 1549ec02f9dSChristopher Serr derive(serde_derive::Serialize, serde_derive::Deserialize) 1559ec02f9dSChristopher Serr )] 1568a9b1a90SBenjamin Bouvier pub struct FunctionStencil { 157a0c2276eSbjorn3 /// A version marker used to ensure that serialized clif ir is never deserialized with a 158a0c2276eSbjorn3 /// different version of Cranelift. 159a0c2276eSbjorn3 // Note: This must be the first field to ensure that Serde will deserialize it before 160a0c2276eSbjorn3 // attempting to deserialize other fields that are potentially changed between versions. 161a0c2276eSbjorn3 pub version_marker: VersionMarker, 162a0c2276eSbjorn3 163747ad3c4Slazypassion /// Signature of this function. 164747ad3c4Slazypassion pub signature: Signature, 165747ad3c4Slazypassion 1669c43749dSSam Parker /// Sized stack slots allocated in this function. 1679c43749dSSam Parker pub sized_stack_slots: StackSlots, 1689c43749dSSam Parker 1699c43749dSSam Parker /// Dynamic stack slots allocated in this function. 1709c43749dSSam Parker pub dynamic_stack_slots: DynamicStackSlots, 171747ad3c4Slazypassion 172747ad3c4Slazypassion /// Global values referenced. 173747ad3c4Slazypassion pub global_values: PrimaryMap<ir::GlobalValue, ir::GlobalValueData>, 174747ad3c4Slazypassion 175747ad3c4Slazypassion /// Tables referenced. 176747ad3c4Slazypassion pub tables: PrimaryMap<ir::Table, ir::TableData>, 177747ad3c4Slazypassion 178832666c4SRyan Hunt /// Data flow graph containing the primary definition of all instructions, blocks and values. 179747ad3c4Slazypassion pub dfg: DataFlowGraph, 180747ad3c4Slazypassion 181832666c4SRyan Hunt /// Layout of blocks and instructions in the function body. 182747ad3c4Slazypassion pub layout: Layout, 183747ad3c4Slazypassion 184747ad3c4Slazypassion /// Source locations. 185747ad3c4Slazypassion /// 186747ad3c4Slazypassion /// Track the original source location for each instruction. The source locations are not 187747ad3c4Slazypassion /// interpreted by Cranelift, only preserved. 1882be12a51SChris Fallin pub srclocs: SourceLocs, 1898923bac7SPeter Huene 190c9a0ba81SAlex Crichton /// An optional global value which represents an expression evaluating to 191c9a0ba81SAlex Crichton /// the stack limit for this function. This `GlobalValue` will be 192c9a0ba81SAlex Crichton /// interpreted in the prologue, if necessary, to insert a stack check to 193c9a0ba81SAlex Crichton /// ensure that a trap happens if the stack pointer goes below the 194c9a0ba81SAlex Crichton /// threshold specified here. 195c9a0ba81SAlex Crichton pub stack_limit: Option<ir::GlobalValue>, 196747ad3c4Slazypassion } 197747ad3c4Slazypassion 1988a9b1a90SBenjamin Bouvier impl FunctionStencil { 1998a9b1a90SBenjamin Bouvier fn clear(&mut self) { 200747ad3c4Slazypassion self.signature.clear(CallConv::Fast); 2019c43749dSSam Parker self.sized_stack_slots.clear(); 2029c43749dSSam Parker self.dynamic_stack_slots.clear(); 203747ad3c4Slazypassion self.global_values.clear(); 204747ad3c4Slazypassion self.tables.clear(); 205747ad3c4Slazypassion self.dfg.clear(); 206747ad3c4Slazypassion self.layout.clear(); 207747ad3c4Slazypassion self.srclocs.clear(); 208c9a0ba81SAlex Crichton self.stack_limit = None; 209747ad3c4Slazypassion } 210747ad3c4Slazypassion 211747ad3c4Slazypassion /// Creates a jump table in the function, to be used by `br_table` instructions. 212747ad3c4Slazypassion pub fn create_jump_table(&mut self, data: JumpTableData) -> JumpTable { 213b0b3f67cSTrevor Elliott self.dfg.jump_tables.push(data) 214747ad3c4Slazypassion } 215747ad3c4Slazypassion 2169c43749dSSam Parker /// Creates a sized stack slot in the function, to be used by `stack_load`, `stack_store` 2179c43749dSSam Parker /// and `stack_addr` instructions. 2189c43749dSSam Parker pub fn create_sized_stack_slot(&mut self, data: StackSlotData) -> StackSlot { 2199c43749dSSam Parker self.sized_stack_slots.push(data) 2209c43749dSSam Parker } 2219c43749dSSam Parker 2229c43749dSSam Parker /// Creates a dynamic stack slot in the function, to be used by `dynamic_stack_load`, 2239c43749dSSam Parker /// `dynamic_stack_store` and `dynamic_stack_addr` instructions. 2249c43749dSSam Parker pub fn create_dynamic_stack_slot(&mut self, data: DynamicStackSlotData) -> DynamicStackSlot { 2259c43749dSSam Parker self.dynamic_stack_slots.push(data) 226747ad3c4Slazypassion } 227747ad3c4Slazypassion 228747ad3c4Slazypassion /// Adds a signature which can later be used to declare an external function import. 229747ad3c4Slazypassion pub fn import_signature(&mut self, signature: Signature) -> SigRef { 230747ad3c4Slazypassion self.dfg.signatures.push(signature) 231747ad3c4Slazypassion } 232747ad3c4Slazypassion 233747ad3c4Slazypassion /// Declares a global value accessible to the function. 234747ad3c4Slazypassion pub fn create_global_value(&mut self, data: GlobalValueData) -> GlobalValue { 235747ad3c4Slazypassion self.global_values.push(data) 236747ad3c4Slazypassion } 237747ad3c4Slazypassion 2384053ae9eSkevaundray /// Find the global dyn_scale value associated with given DynamicType. 2399c43749dSSam Parker pub fn get_dyn_scale(&self, ty: DynamicType) -> GlobalValue { 2409c43749dSSam Parker self.dfg.dynamic_types.get(ty).unwrap().dynamic_scale 2419c43749dSSam Parker } 2429c43749dSSam Parker 2439c43749dSSam Parker /// Find the global dyn_scale for the given stack slot. 2449c43749dSSam Parker pub fn get_dynamic_slot_scale(&self, dss: DynamicStackSlot) -> GlobalValue { 2459c43749dSSam Parker let dyn_ty = self.dynamic_stack_slots.get(dss).unwrap().dyn_ty; 2469c43749dSSam Parker self.get_dyn_scale(dyn_ty) 2479c43749dSSam Parker } 2489c43749dSSam Parker 2499c43749dSSam Parker /// Get a concrete `Type` from a user defined `DynamicType`. 2509c43749dSSam Parker pub fn get_concrete_dynamic_ty(&self, ty: DynamicType) -> Option<Type> { 2519c43749dSSam Parker self.dfg 2529c43749dSSam Parker .dynamic_types 2539c43749dSSam Parker .get(ty) 2549c43749dSSam Parker .unwrap_or_else(|| panic!("Undeclared dynamic vector type: {}", ty)) 2559c43749dSSam Parker .concrete() 2569c43749dSSam Parker } 2579c43749dSSam Parker 258747ad3c4Slazypassion /// Declares a table accessible to the function. 259747ad3c4Slazypassion pub fn create_table(&mut self, data: TableData) -> Table { 260747ad3c4Slazypassion self.tables.push(data) 261747ad3c4Slazypassion } 262747ad3c4Slazypassion 263747ad3c4Slazypassion /// Find a presumed unique special-purpose function parameter value. 264747ad3c4Slazypassion /// 265747ad3c4Slazypassion /// Returns the value of the last `purpose` parameter, or `None` if no such parameter exists. 266747ad3c4Slazypassion pub fn special_param(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> { 267747ad3c4Slazypassion let entry = self.layout.entry_block().expect("Function is empty"); 268747ad3c4Slazypassion self.signature 269747ad3c4Slazypassion .special_param_index(purpose) 270832666c4SRyan Hunt .map(|i| self.dfg.block_params(entry)[i]) 271747ad3c4Slazypassion } 272747ad3c4Slazypassion 2738f95c517SYury Delendik /// Starts collection of debug information. 2748f95c517SYury Delendik pub fn collect_debug_info(&mut self) { 2758f95c517SYury Delendik self.dfg.collect_debug_info(); 2768f95c517SYury Delendik } 2778efaeec5SSean Stangl 278855a6374SY-Nak /// Rewrite the branch destination to `new_dest` if the destination matches `old_dest`. 279855a6374SY-Nak /// Does nothing if called with a non-jump or non-branch instruction. 280855a6374SY-Nak pub fn rewrite_branch_destination(&mut self, inst: Inst, old_dest: Block, new_dest: Block) { 28180c147d9STrevor Elliott for dest in self.dfg.insts[inst].branch_destination_mut(&mut self.dfg.jump_tables) { 2821e6c13d8STrevor Elliott if dest.block(&self.dfg.value_lists) == old_dest { 2832c842599STrevor Elliott dest.set_block(new_dest, &mut self.dfg.value_lists) 284b58a197dSTrevor Elliott } 285b58a197dSTrevor Elliott } 286855a6374SY-Nak } 287855a6374SY-Nak 288832666c4SRyan Hunt /// Checks that the specified block can be encoded as a basic block. 2898efaeec5SSean Stangl /// 2908efaeec5SSean Stangl /// On error, returns the first invalid instruction and an error message. 291832666c4SRyan Hunt pub fn is_block_basic(&self, block: Block) -> Result<(), (Inst, &'static str)> { 2928efaeec5SSean Stangl let dfg = &self.dfg; 293832666c4SRyan Hunt let inst_iter = self.layout.block_insts(block); 2948efaeec5SSean Stangl 2958efaeec5SSean Stangl // Ignore all instructions prior to the first branch. 29625bf8e0eSTrevor Elliott let mut inst_iter = inst_iter.skip_while(|&inst| !dfg.insts[inst].opcode().is_branch()); 2978efaeec5SSean Stangl 2988efaeec5SSean Stangl // A conditional branch is permitted in a basic block only when followed 2991fd491daSbjorn3 // by a terminal jump instruction. 3008efaeec5SSean Stangl if let Some(_branch) = inst_iter.next() { 3018efaeec5SSean Stangl if let Some(next) = inst_iter.next() { 30225bf8e0eSTrevor Elliott match dfg.insts[next].opcode() { 3031fd491daSbjorn3 Opcode::Jump => (), 3041fd491daSbjorn3 _ => return Err((next, "post-branch instruction not jump")), 3058efaeec5SSean Stangl } 3068efaeec5SSean Stangl } 3078efaeec5SSean Stangl } 3088efaeec5SSean Stangl 3098efaeec5SSean Stangl Ok(()) 3108efaeec5SSean Stangl } 311143cb014SBenjamin Bouvier 312143cb014SBenjamin Bouvier /// Returns true if the function is function that doesn't call any other functions. This is not 313143cb014SBenjamin Bouvier /// to be confused with a "leaf function" in Windows terminology. 314143cb014SBenjamin Bouvier pub fn is_leaf(&self) -> bool { 315143cb014SBenjamin Bouvier // Conservative result: if there's at least one function signature referenced in this 31658e5a62cSY-Nak // function, assume it is not a leaf. 317*a6b62d6cSAfonso Bordado let has_signatures = !self.dfg.signatures.is_empty(); 318*a6b62d6cSAfonso Bordado 319*a6b62d6cSAfonso Bordado // Under some TLS models, retrieving the address of a TLS variable requires calling a 320*a6b62d6cSAfonso Bordado // function. Conservatively assume that any function that references a tls global value 321*a6b62d6cSAfonso Bordado // is not a leaf. 322*a6b62d6cSAfonso Bordado let has_tls = self.global_values.values().any(|gv| match gv { 323*a6b62d6cSAfonso Bordado GlobalValueData::Symbol { tls, .. } => *tls, 324*a6b62d6cSAfonso Bordado _ => false, 325*a6b62d6cSAfonso Bordado }); 326*a6b62d6cSAfonso Bordado 327*a6b62d6cSAfonso Bordado !has_signatures && !has_tls 328143cb014SBenjamin Bouvier } 329090d1c2dSNick Fitzgerald 330090d1c2dSNick Fitzgerald /// Replace the `dst` instruction's data with the `src` instruction's data 331090d1c2dSNick Fitzgerald /// and then remove `src`. 332090d1c2dSNick Fitzgerald /// 333090d1c2dSNick Fitzgerald /// `src` and its result values should not be used at all, as any uses would 334090d1c2dSNick Fitzgerald /// be left dangling after calling this method. 335090d1c2dSNick Fitzgerald /// 336090d1c2dSNick Fitzgerald /// `src` and `dst` must have the same number of resulting values, and 337090d1c2dSNick Fitzgerald /// `src`'s i^th value must have the same type as `dst`'s i^th value. 338090d1c2dSNick Fitzgerald pub fn transplant_inst(&mut self, dst: Inst, src: Inst) { 339090d1c2dSNick Fitzgerald debug_assert_eq!( 340090d1c2dSNick Fitzgerald self.dfg.inst_results(dst).len(), 341090d1c2dSNick Fitzgerald self.dfg.inst_results(src).len() 342090d1c2dSNick Fitzgerald ); 343090d1c2dSNick Fitzgerald debug_assert!(self 344090d1c2dSNick Fitzgerald .dfg 345090d1c2dSNick Fitzgerald .inst_results(dst) 346090d1c2dSNick Fitzgerald .iter() 347090d1c2dSNick Fitzgerald .zip(self.dfg.inst_results(src)) 348090d1c2dSNick Fitzgerald .all(|(a, b)| self.dfg.value_type(*a) == self.dfg.value_type(*b))); 349090d1c2dSNick Fitzgerald 35025bf8e0eSTrevor Elliott self.dfg.insts[dst] = self.dfg.insts[src]; 351090d1c2dSNick Fitzgerald self.layout.remove_inst(src); 352090d1c2dSNick Fitzgerald } 3532776074dSAfonso Bordado 3542776074dSAfonso Bordado /// Size occupied by all stack slots associated with this function. 3552776074dSAfonso Bordado /// 3562776074dSAfonso Bordado /// Does not include any padding necessary due to offsets 3579c43749dSSam Parker pub fn fixed_stack_size(&self) -> u32 { 3589c43749dSSam Parker self.sized_stack_slots.values().map(|ss| ss.size).sum() 3592776074dSAfonso Bordado } 3608a9b1a90SBenjamin Bouvier 3618a9b1a90SBenjamin Bouvier /// Returns the list of relative source locations for this function. 3628a9b1a90SBenjamin Bouvier pub(crate) fn rel_srclocs(&self) -> &SecondaryMap<Inst, RelSourceLoc> { 3638a9b1a90SBenjamin Bouvier &self.srclocs 3648a9b1a90SBenjamin Bouvier } 3658a9b1a90SBenjamin Bouvier } 3668a9b1a90SBenjamin Bouvier 3678a9b1a90SBenjamin Bouvier /// Functions can be cloned, but it is not a very fast operation. 3688a9b1a90SBenjamin Bouvier /// The clone will have all the same entity numbers as the original. 369a9cda5afSAfonso Bordado #[derive(Clone, PartialEq)] 3708a9b1a90SBenjamin Bouvier #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 3718a9b1a90SBenjamin Bouvier pub struct Function { 3728a9b1a90SBenjamin Bouvier /// Name of this function. 3738a9b1a90SBenjamin Bouvier /// 3748a9b1a90SBenjamin Bouvier /// Mostly used by `.clif` files, only there for debugging / naming purposes. 3758a9b1a90SBenjamin Bouvier pub name: UserFuncName, 3768a9b1a90SBenjamin Bouvier 3778a9b1a90SBenjamin Bouvier /// All the fields required for compiling a function, independently of details irrelevant to 3788a9b1a90SBenjamin Bouvier /// compilation and that are stored in the `FunctionParameters` `params` field instead. 3798a9b1a90SBenjamin Bouvier pub stencil: FunctionStencil, 3808a9b1a90SBenjamin Bouvier 3818a9b1a90SBenjamin Bouvier /// All the parameters that can be applied onto the function stencil, that is, that don't 3828a9b1a90SBenjamin Bouvier /// matter when caching compilation artifacts. 3838a9b1a90SBenjamin Bouvier pub params: FunctionParameters, 3848a9b1a90SBenjamin Bouvier } 3858a9b1a90SBenjamin Bouvier 3868a9b1a90SBenjamin Bouvier impl core::ops::Deref for Function { 3878a9b1a90SBenjamin Bouvier type Target = FunctionStencil; 3888a9b1a90SBenjamin Bouvier 3898a9b1a90SBenjamin Bouvier fn deref(&self) -> &Self::Target { 3908a9b1a90SBenjamin Bouvier &self.stencil 3918a9b1a90SBenjamin Bouvier } 3928a9b1a90SBenjamin Bouvier } 3938a9b1a90SBenjamin Bouvier 3948a9b1a90SBenjamin Bouvier impl core::ops::DerefMut for Function { 3958a9b1a90SBenjamin Bouvier fn deref_mut(&mut self) -> &mut Self::Target { 3968a9b1a90SBenjamin Bouvier &mut self.stencil 3978a9b1a90SBenjamin Bouvier } 3988a9b1a90SBenjamin Bouvier } 3998a9b1a90SBenjamin Bouvier 4008a9b1a90SBenjamin Bouvier impl Function { 4018a9b1a90SBenjamin Bouvier /// Create a function with the given name and signature. 4028a9b1a90SBenjamin Bouvier pub fn with_name_signature(name: UserFuncName, sig: Signature) -> Self { 4038a9b1a90SBenjamin Bouvier Self { 4048a9b1a90SBenjamin Bouvier name, 4058a9b1a90SBenjamin Bouvier stencil: FunctionStencil { 4068a9b1a90SBenjamin Bouvier version_marker: VersionMarker, 4078a9b1a90SBenjamin Bouvier signature: sig, 4088a9b1a90SBenjamin Bouvier sized_stack_slots: StackSlots::new(), 4098a9b1a90SBenjamin Bouvier dynamic_stack_slots: DynamicStackSlots::new(), 4108a9b1a90SBenjamin Bouvier global_values: PrimaryMap::new(), 4118a9b1a90SBenjamin Bouvier tables: PrimaryMap::new(), 4128a9b1a90SBenjamin Bouvier dfg: DataFlowGraph::new(), 4138a9b1a90SBenjamin Bouvier layout: Layout::new(), 4148a9b1a90SBenjamin Bouvier srclocs: SecondaryMap::new(), 4158a9b1a90SBenjamin Bouvier stack_limit: None, 4168a9b1a90SBenjamin Bouvier }, 4178a9b1a90SBenjamin Bouvier params: FunctionParameters::new(), 4188a9b1a90SBenjamin Bouvier } 4198a9b1a90SBenjamin Bouvier } 4208a9b1a90SBenjamin Bouvier 4218a9b1a90SBenjamin Bouvier /// Clear all data structures in this function. 4228a9b1a90SBenjamin Bouvier pub fn clear(&mut self) { 4238a9b1a90SBenjamin Bouvier self.stencil.clear(); 4248a9b1a90SBenjamin Bouvier self.params.clear(); 4258a9b1a90SBenjamin Bouvier self.name = UserFuncName::default(); 4268a9b1a90SBenjamin Bouvier } 4278a9b1a90SBenjamin Bouvier 4288a9b1a90SBenjamin Bouvier /// Create a new empty, anonymous function with a Fast calling convention. 4298a9b1a90SBenjamin Bouvier pub fn new() -> Self { 4308a9b1a90SBenjamin Bouvier Self::with_name_signature(Default::default(), Signature::new(CallConv::Fast)) 4318a9b1a90SBenjamin Bouvier } 4328a9b1a90SBenjamin Bouvier 4338a9b1a90SBenjamin Bouvier /// Return an object that can display this function with correct ISA-specific annotations. 4348a9b1a90SBenjamin Bouvier pub fn display(&self) -> DisplayFunction<'_> { 435729e2640Sbjorn3 DisplayFunction(self) 4368a9b1a90SBenjamin Bouvier } 4378a9b1a90SBenjamin Bouvier 4388a9b1a90SBenjamin Bouvier /// Sets an absolute source location for the given instruction. 4398a9b1a90SBenjamin Bouvier /// 4408a9b1a90SBenjamin Bouvier /// If no base source location has been set yet, records it at the same time. 4418a9b1a90SBenjamin Bouvier pub fn set_srcloc(&mut self, inst: Inst, srcloc: SourceLoc) { 4428a9b1a90SBenjamin Bouvier let base = self.params.ensure_base_srcloc(srcloc); 4438a9b1a90SBenjamin Bouvier self.stencil.srclocs[inst] = RelSourceLoc::from_base_offset(base, srcloc); 4448a9b1a90SBenjamin Bouvier } 4458a9b1a90SBenjamin Bouvier 4468a9b1a90SBenjamin Bouvier /// Returns an absolute source location for the given instruction. 4478a9b1a90SBenjamin Bouvier pub fn srcloc(&self, inst: Inst) -> SourceLoc { 4488a9b1a90SBenjamin Bouvier let base = self.params.base_srcloc(); 4498a9b1a90SBenjamin Bouvier self.stencil.srclocs[inst].expand(base) 4508a9b1a90SBenjamin Bouvier } 4518a9b1a90SBenjamin Bouvier 4528a9b1a90SBenjamin Bouvier /// Declare a user-defined external function import, to be referenced in `ExtFuncData::User` later. 4538a9b1a90SBenjamin Bouvier pub fn declare_imported_user_function( 4548a9b1a90SBenjamin Bouvier &mut self, 4558a9b1a90SBenjamin Bouvier name: UserExternalName, 4568a9b1a90SBenjamin Bouvier ) -> UserExternalNameRef { 4578a9b1a90SBenjamin Bouvier self.params.ensure_user_func_name(name) 4588a9b1a90SBenjamin Bouvier } 4598a9b1a90SBenjamin Bouvier 4608a9b1a90SBenjamin Bouvier /// Declare an external function import. 4618a9b1a90SBenjamin Bouvier pub fn import_function(&mut self, data: ExtFuncData) -> FuncRef { 4628a9b1a90SBenjamin Bouvier self.stencil.dfg.ext_funcs.push(data) 4638a9b1a90SBenjamin Bouvier } 4648f95c517SYury Delendik } 4658f95c517SYury Delendik 466729e2640Sbjorn3 /// Wrapper type capable of displaying a `Function`. 467729e2640Sbjorn3 pub struct DisplayFunction<'a>(&'a Function); 468747ad3c4Slazypassion 469747ad3c4Slazypassion impl<'a> fmt::Display for DisplayFunction<'a> { 470747ad3c4Slazypassion fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 47143a86f14SBenjamin Bouvier write_function(fmt, self.0) 472747ad3c4Slazypassion } 473747ad3c4Slazypassion } 474747ad3c4Slazypassion 475747ad3c4Slazypassion impl fmt::Display for Function { 476747ad3c4Slazypassion fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 47743a86f14SBenjamin Bouvier write_function(fmt, self) 478747ad3c4Slazypassion } 479747ad3c4Slazypassion } 480747ad3c4Slazypassion 481747ad3c4Slazypassion impl fmt::Debug for Function { 482747ad3c4Slazypassion fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 48343a86f14SBenjamin Bouvier write_function(fmt, self) 484747ad3c4Slazypassion } 485747ad3c4Slazypassion } 486