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