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)] 67*9ec02f9dSChristopher Serr #[cfg_attr( 68*9ec02f9dSChristopher Serr feature = "enable-serde", 69*9ec02f9dSChristopher Serr derive(serde_derive::Serialize, serde_derive::Deserialize) 70*9ec02f9dSChristopher 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)] 152*9ec02f9dSChristopher Serr #[cfg_attr( 153*9ec02f9dSChristopher Serr feature = "enable-serde", 154*9ec02f9dSChristopher Serr derive(serde_derive::Serialize, serde_derive::Deserialize) 155*9ec02f9dSChristopher 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. 31758e5a62cSY-Nak self.dfg.signatures.is_empty() 318143cb014SBenjamin Bouvier } 319090d1c2dSNick Fitzgerald 320090d1c2dSNick Fitzgerald /// Replace the `dst` instruction's data with the `src` instruction's data 321090d1c2dSNick Fitzgerald /// and then remove `src`. 322090d1c2dSNick Fitzgerald /// 323090d1c2dSNick Fitzgerald /// `src` and its result values should not be used at all, as any uses would 324090d1c2dSNick Fitzgerald /// be left dangling after calling this method. 325090d1c2dSNick Fitzgerald /// 326090d1c2dSNick Fitzgerald /// `src` and `dst` must have the same number of resulting values, and 327090d1c2dSNick Fitzgerald /// `src`'s i^th value must have the same type as `dst`'s i^th value. 328090d1c2dSNick Fitzgerald pub fn transplant_inst(&mut self, dst: Inst, src: Inst) { 329090d1c2dSNick Fitzgerald debug_assert_eq!( 330090d1c2dSNick Fitzgerald self.dfg.inst_results(dst).len(), 331090d1c2dSNick Fitzgerald self.dfg.inst_results(src).len() 332090d1c2dSNick Fitzgerald ); 333090d1c2dSNick Fitzgerald debug_assert!(self 334090d1c2dSNick Fitzgerald .dfg 335090d1c2dSNick Fitzgerald .inst_results(dst) 336090d1c2dSNick Fitzgerald .iter() 337090d1c2dSNick Fitzgerald .zip(self.dfg.inst_results(src)) 338090d1c2dSNick Fitzgerald .all(|(a, b)| self.dfg.value_type(*a) == self.dfg.value_type(*b))); 339090d1c2dSNick Fitzgerald 34025bf8e0eSTrevor Elliott self.dfg.insts[dst] = self.dfg.insts[src]; 341090d1c2dSNick Fitzgerald self.layout.remove_inst(src); 342090d1c2dSNick Fitzgerald } 3432776074dSAfonso Bordado 3442776074dSAfonso Bordado /// Size occupied by all stack slots associated with this function. 3452776074dSAfonso Bordado /// 3462776074dSAfonso Bordado /// Does not include any padding necessary due to offsets 3479c43749dSSam Parker pub fn fixed_stack_size(&self) -> u32 { 3489c43749dSSam Parker self.sized_stack_slots.values().map(|ss| ss.size).sum() 3492776074dSAfonso Bordado } 3508a9b1a90SBenjamin Bouvier 3518a9b1a90SBenjamin Bouvier /// Returns the list of relative source locations for this function. 3528a9b1a90SBenjamin Bouvier pub(crate) fn rel_srclocs(&self) -> &SecondaryMap<Inst, RelSourceLoc> { 3538a9b1a90SBenjamin Bouvier &self.srclocs 3548a9b1a90SBenjamin Bouvier } 3558a9b1a90SBenjamin Bouvier } 3568a9b1a90SBenjamin Bouvier 3578a9b1a90SBenjamin Bouvier /// Functions can be cloned, but it is not a very fast operation. 3588a9b1a90SBenjamin Bouvier /// The clone will have all the same entity numbers as the original. 359a9cda5afSAfonso Bordado #[derive(Clone, PartialEq)] 3608a9b1a90SBenjamin Bouvier #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 3618a9b1a90SBenjamin Bouvier pub struct Function { 3628a9b1a90SBenjamin Bouvier /// Name of this function. 3638a9b1a90SBenjamin Bouvier /// 3648a9b1a90SBenjamin Bouvier /// Mostly used by `.clif` files, only there for debugging / naming purposes. 3658a9b1a90SBenjamin Bouvier pub name: UserFuncName, 3668a9b1a90SBenjamin Bouvier 3678a9b1a90SBenjamin Bouvier /// All the fields required for compiling a function, independently of details irrelevant to 3688a9b1a90SBenjamin Bouvier /// compilation and that are stored in the `FunctionParameters` `params` field instead. 3698a9b1a90SBenjamin Bouvier pub stencil: FunctionStencil, 3708a9b1a90SBenjamin Bouvier 3718a9b1a90SBenjamin Bouvier /// All the parameters that can be applied onto the function stencil, that is, that don't 3728a9b1a90SBenjamin Bouvier /// matter when caching compilation artifacts. 3738a9b1a90SBenjamin Bouvier pub params: FunctionParameters, 3748a9b1a90SBenjamin Bouvier } 3758a9b1a90SBenjamin Bouvier 3768a9b1a90SBenjamin Bouvier impl core::ops::Deref for Function { 3778a9b1a90SBenjamin Bouvier type Target = FunctionStencil; 3788a9b1a90SBenjamin Bouvier 3798a9b1a90SBenjamin Bouvier fn deref(&self) -> &Self::Target { 3808a9b1a90SBenjamin Bouvier &self.stencil 3818a9b1a90SBenjamin Bouvier } 3828a9b1a90SBenjamin Bouvier } 3838a9b1a90SBenjamin Bouvier 3848a9b1a90SBenjamin Bouvier impl core::ops::DerefMut for Function { 3858a9b1a90SBenjamin Bouvier fn deref_mut(&mut self) -> &mut Self::Target { 3868a9b1a90SBenjamin Bouvier &mut self.stencil 3878a9b1a90SBenjamin Bouvier } 3888a9b1a90SBenjamin Bouvier } 3898a9b1a90SBenjamin Bouvier 3908a9b1a90SBenjamin Bouvier impl Function { 3918a9b1a90SBenjamin Bouvier /// Create a function with the given name and signature. 3928a9b1a90SBenjamin Bouvier pub fn with_name_signature(name: UserFuncName, sig: Signature) -> Self { 3938a9b1a90SBenjamin Bouvier Self { 3948a9b1a90SBenjamin Bouvier name, 3958a9b1a90SBenjamin Bouvier stencil: FunctionStencil { 3968a9b1a90SBenjamin Bouvier version_marker: VersionMarker, 3978a9b1a90SBenjamin Bouvier signature: sig, 3988a9b1a90SBenjamin Bouvier sized_stack_slots: StackSlots::new(), 3998a9b1a90SBenjamin Bouvier dynamic_stack_slots: DynamicStackSlots::new(), 4008a9b1a90SBenjamin Bouvier global_values: PrimaryMap::new(), 4018a9b1a90SBenjamin Bouvier tables: PrimaryMap::new(), 4028a9b1a90SBenjamin Bouvier dfg: DataFlowGraph::new(), 4038a9b1a90SBenjamin Bouvier layout: Layout::new(), 4048a9b1a90SBenjamin Bouvier srclocs: SecondaryMap::new(), 4058a9b1a90SBenjamin Bouvier stack_limit: None, 4068a9b1a90SBenjamin Bouvier }, 4078a9b1a90SBenjamin Bouvier params: FunctionParameters::new(), 4088a9b1a90SBenjamin Bouvier } 4098a9b1a90SBenjamin Bouvier } 4108a9b1a90SBenjamin Bouvier 4118a9b1a90SBenjamin Bouvier /// Clear all data structures in this function. 4128a9b1a90SBenjamin Bouvier pub fn clear(&mut self) { 4138a9b1a90SBenjamin Bouvier self.stencil.clear(); 4148a9b1a90SBenjamin Bouvier self.params.clear(); 4158a9b1a90SBenjamin Bouvier self.name = UserFuncName::default(); 4168a9b1a90SBenjamin Bouvier } 4178a9b1a90SBenjamin Bouvier 4188a9b1a90SBenjamin Bouvier /// Create a new empty, anonymous function with a Fast calling convention. 4198a9b1a90SBenjamin Bouvier pub fn new() -> Self { 4208a9b1a90SBenjamin Bouvier Self::with_name_signature(Default::default(), Signature::new(CallConv::Fast)) 4218a9b1a90SBenjamin Bouvier } 4228a9b1a90SBenjamin Bouvier 4238a9b1a90SBenjamin Bouvier /// Return an object that can display this function with correct ISA-specific annotations. 4248a9b1a90SBenjamin Bouvier pub fn display(&self) -> DisplayFunction<'_> { 425729e2640Sbjorn3 DisplayFunction(self) 4268a9b1a90SBenjamin Bouvier } 4278a9b1a90SBenjamin Bouvier 4288a9b1a90SBenjamin Bouvier /// Sets an absolute source location for the given instruction. 4298a9b1a90SBenjamin Bouvier /// 4308a9b1a90SBenjamin Bouvier /// If no base source location has been set yet, records it at the same time. 4318a9b1a90SBenjamin Bouvier pub fn set_srcloc(&mut self, inst: Inst, srcloc: SourceLoc) { 4328a9b1a90SBenjamin Bouvier let base = self.params.ensure_base_srcloc(srcloc); 4338a9b1a90SBenjamin Bouvier self.stencil.srclocs[inst] = RelSourceLoc::from_base_offset(base, srcloc); 4348a9b1a90SBenjamin Bouvier } 4358a9b1a90SBenjamin Bouvier 4368a9b1a90SBenjamin Bouvier /// Returns an absolute source location for the given instruction. 4378a9b1a90SBenjamin Bouvier pub fn srcloc(&self, inst: Inst) -> SourceLoc { 4388a9b1a90SBenjamin Bouvier let base = self.params.base_srcloc(); 4398a9b1a90SBenjamin Bouvier self.stencil.srclocs[inst].expand(base) 4408a9b1a90SBenjamin Bouvier } 4418a9b1a90SBenjamin Bouvier 4428a9b1a90SBenjamin Bouvier /// Declare a user-defined external function import, to be referenced in `ExtFuncData::User` later. 4438a9b1a90SBenjamin Bouvier pub fn declare_imported_user_function( 4448a9b1a90SBenjamin Bouvier &mut self, 4458a9b1a90SBenjamin Bouvier name: UserExternalName, 4468a9b1a90SBenjamin Bouvier ) -> UserExternalNameRef { 4478a9b1a90SBenjamin Bouvier self.params.ensure_user_func_name(name) 4488a9b1a90SBenjamin Bouvier } 4498a9b1a90SBenjamin Bouvier 4508a9b1a90SBenjamin Bouvier /// Declare an external function import. 4518a9b1a90SBenjamin Bouvier pub fn import_function(&mut self, data: ExtFuncData) -> FuncRef { 4528a9b1a90SBenjamin Bouvier self.stencil.dfg.ext_funcs.push(data) 4538a9b1a90SBenjamin Bouvier } 4548f95c517SYury Delendik } 4558f95c517SYury Delendik 456729e2640Sbjorn3 /// Wrapper type capable of displaying a `Function`. 457729e2640Sbjorn3 pub struct DisplayFunction<'a>(&'a Function); 458747ad3c4Slazypassion 459747ad3c4Slazypassion impl<'a> fmt::Display for DisplayFunction<'a> { 460747ad3c4Slazypassion fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 46143a86f14SBenjamin Bouvier write_function(fmt, self.0) 462747ad3c4Slazypassion } 463747ad3c4Slazypassion } 464747ad3c4Slazypassion 465747ad3c4Slazypassion impl fmt::Display for Function { 466747ad3c4Slazypassion fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 46743a86f14SBenjamin Bouvier write_function(fmt, self) 468747ad3c4Slazypassion } 469747ad3c4Slazypassion } 470747ad3c4Slazypassion 471747ad3c4Slazypassion impl fmt::Debug for Function { 472747ad3c4Slazypassion fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 47343a86f14SBenjamin Bouvier write_function(fmt, self) 474747ad3c4Slazypassion } 475747ad3c4Slazypassion } 476