Coverage Report

Created: 2026-02-14 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cranelift-codegen-0.128.3/src/ir/function.rs
Line
Count
Source
1
//! Intermediate representation of a function.
2
//!
3
//! The `Function` struct defined in this module owns all of its basic blocks and
4
//! instructions.
5
6
use crate::HashMap;
7
use crate::entity::{PrimaryMap, SecondaryMap};
8
use crate::ir::DebugTags;
9
use crate::ir::{
10
    self, Block, DataFlowGraph, DynamicStackSlot, DynamicStackSlotData, DynamicStackSlots,
11
    DynamicType, ExtFuncData, FuncRef, GlobalValue, GlobalValueData, Inst, JumpTable,
12
    JumpTableData, Layout, MemoryType, MemoryTypeData, SigRef, Signature, SourceLocs, StackSlot,
13
    StackSlotData, StackSlots, Type, pcc::Fact,
14
};
15
use crate::isa::CallConv;
16
use crate::write::{write_function, write_function_spec};
17
#[cfg(feature = "enable-serde")]
18
use alloc::string::String;
19
use core::fmt;
20
21
#[cfg(feature = "enable-serde")]
22
use serde::de::{Deserializer, Error};
23
#[cfg(feature = "enable-serde")]
24
use serde::ser::Serializer;
25
#[cfg(feature = "enable-serde")]
26
use serde::{Deserialize, Serialize};
27
28
use super::entities::UserExternalNameRef;
29
use super::extname::UserFuncName;
30
use super::{RelSourceLoc, SourceLoc, UserExternalName};
31
32
/// A version marker used to ensure that serialized clif ir is never deserialized with a
33
/// different version of Cranelift.
34
#[derive(Default, Copy, Clone, Debug, PartialEq, Hash)]
35
pub struct VersionMarker;
36
37
#[cfg(feature = "enable-serde")]
38
impl Serialize for VersionMarker {
39
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
40
    where
41
        S: Serializer,
42
    {
43
        crate::VERSION.serialize(serializer)
44
    }
45
}
46
47
#[cfg(feature = "enable-serde")]
48
impl<'de> Deserialize<'de> for VersionMarker {
49
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
50
    where
51
        D: Deserializer<'de>,
52
    {
53
        let version = String::deserialize(deserializer)?;
54
        if version != crate::VERSION {
55
            return Err(D::Error::custom(&format!(
56
                "Expected a clif ir function for version {}, found one for version {}",
57
                crate::VERSION,
58
                version,
59
            )));
60
        }
61
        Ok(VersionMarker)
62
    }
63
}
64
65
/// Function parameters used when creating this function, and that will become applied after
66
/// compilation to materialize the final `CompiledCode`.
67
#[derive(Clone, PartialEq)]
68
#[cfg_attr(
69
    feature = "enable-serde",
70
    derive(serde_derive::Serialize, serde_derive::Deserialize)
71
)]
72
pub struct FunctionParameters {
73
    /// The first `SourceLoc` appearing in the function, serving as a base for every relative
74
    /// source loc in the function.
75
    base_srcloc: Option<SourceLoc>,
76
77
    /// External user-defined function references.
78
    user_named_funcs: PrimaryMap<UserExternalNameRef, UserExternalName>,
79
80
    /// Inverted mapping of `user_named_funcs`, to deduplicate internally.
81
    user_ext_name_to_ref: HashMap<UserExternalName, UserExternalNameRef>,
82
}
83
84
impl FunctionParameters {
85
    /// Creates a new `FunctionParameters` with the given name.
86
629k
    pub fn new() -> Self {
87
629k
        Self {
88
629k
            base_srcloc: None,
89
629k
            user_named_funcs: Default::default(),
90
629k
            user_ext_name_to_ref: Default::default(),
91
629k
        }
92
629k
    }
<cranelift_codegen::ir::function::FunctionParameters>::new
Line
Count
Source
86
157k
    pub fn new() -> Self {
87
157k
        Self {
88
157k
            base_srcloc: None,
89
157k
            user_named_funcs: Default::default(),
90
157k
            user_ext_name_to_ref: Default::default(),
91
157k
        }
92
157k
    }
<cranelift_codegen::ir::function::FunctionParameters>::new
Line
Count
Source
86
472k
    pub fn new() -> Self {
87
472k
        Self {
88
472k
            base_srcloc: None,
89
472k
            user_named_funcs: Default::default(),
90
472k
            user_ext_name_to_ref: Default::default(),
91
472k
        }
92
472k
    }
93
94
    /// Returns the base `SourceLoc`.
95
    ///
96
    /// If it was never explicitly set with `ensure_base_srcloc`, will return an invalid
97
    /// `SourceLoc`.
98
2.04M
    pub fn base_srcloc(&self) -> SourceLoc {
99
2.04M
        self.base_srcloc.unwrap_or_default()
100
2.04M
    }
<cranelift_codegen::ir::function::FunctionParameters>::base_srcloc
Line
Count
Source
98
209k
    pub fn base_srcloc(&self) -> SourceLoc {
99
209k
        self.base_srcloc.unwrap_or_default()
100
209k
    }
<cranelift_codegen::ir::function::FunctionParameters>::base_srcloc
Line
Count
Source
98
1.83M
    pub fn base_srcloc(&self) -> SourceLoc {
99
1.83M
        self.base_srcloc.unwrap_or_default()
100
1.83M
    }
101
102
    /// Sets the base `SourceLoc`, if not set yet, and returns the base value.
103
19.2M
    pub fn ensure_base_srcloc(&mut self, srcloc: SourceLoc) -> SourceLoc {
104
19.2M
        match self.base_srcloc {
105
19.0M
            Some(val) => val,
106
            None => {
107
231k
                self.base_srcloc = Some(srcloc);
108
231k
                srcloc
109
            }
110
        }
111
19.2M
    }
<cranelift_codegen::ir::function::FunctionParameters>::ensure_base_srcloc
Line
Count
Source
103
1.78M
    pub fn ensure_base_srcloc(&mut self, srcloc: SourceLoc) -> SourceLoc {
104
1.78M
        match self.base_srcloc {
105
1.74M
            Some(val) => val,
106
            None => {
107
35.6k
                self.base_srcloc = Some(srcloc);
108
35.6k
                srcloc
109
            }
110
        }
111
1.78M
    }
<cranelift_codegen::ir::function::FunctionParameters>::ensure_base_srcloc
Line
Count
Source
103
17.4M
    pub fn ensure_base_srcloc(&mut self, srcloc: SourceLoc) -> SourceLoc {
104
17.4M
        match self.base_srcloc {
105
17.2M
            Some(val) => val,
106
            None => {
107
195k
                self.base_srcloc = Some(srcloc);
108
195k
                srcloc
109
            }
110
        }
111
17.4M
    }
112
113
    /// Retrieve a `UserExternalNameRef` for the given name, or add a new one.
114
    ///
115
    /// This method internally deduplicates same `UserExternalName` so they map to the same
116
    /// reference.
117
236k
    pub fn ensure_user_func_name(&mut self, name: UserExternalName) -> UserExternalNameRef {
118
236k
        if let Some(reff) = self.user_ext_name_to_ref.get(&name) {
119
1.18k
            *reff
120
        } else {
121
235k
            let reff = self.user_named_funcs.push(name.clone());
122
235k
            self.user_ext_name_to_ref.insert(name, reff);
123
235k
            reff
124
        }
125
236k
    }
<cranelift_codegen::ir::function::FunctionParameters>::ensure_user_func_name
Line
Count
Source
117
36.5k
    pub fn ensure_user_func_name(&mut self, name: UserExternalName) -> UserExternalNameRef {
118
36.5k
        if let Some(reff) = self.user_ext_name_to_ref.get(&name) {
119
472
            *reff
120
        } else {
121
36.0k
            let reff = self.user_named_funcs.push(name.clone());
122
36.0k
            self.user_ext_name_to_ref.insert(name, reff);
123
36.0k
            reff
124
        }
125
36.5k
    }
<cranelift_codegen::ir::function::FunctionParameters>::ensure_user_func_name
Line
Count
Source
117
200k
    pub fn ensure_user_func_name(&mut self, name: UserExternalName) -> UserExternalNameRef {
118
200k
        if let Some(reff) = self.user_ext_name_to_ref.get(&name) {
119
712
            *reff
120
        } else {
121
199k
            let reff = self.user_named_funcs.push(name.clone());
122
199k
            self.user_ext_name_to_ref.insert(name, reff);
123
199k
            reff
124
        }
125
200k
    }
126
127
    /// Resets an already existing user function name to a new value.
128
0
    pub fn reset_user_func_name(&mut self, index: UserExternalNameRef, name: UserExternalName) {
129
0
        if let Some(prev_name) = self.user_named_funcs.get_mut(index) {
130
0
            self.user_ext_name_to_ref.remove(prev_name);
131
0
            *prev_name = name.clone();
132
0
            self.user_ext_name_to_ref.insert(name, index);
133
0
        }
134
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionParameters>::reset_user_func_name
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionParameters>::reset_user_func_name
135
136
    /// Returns the internal mapping of `UserExternalNameRef` to `UserExternalName`.
137
693k
    pub fn user_named_funcs(&self) -> &PrimaryMap<UserExternalNameRef, UserExternalName> {
138
693k
        &self.user_named_funcs
139
693k
    }
<cranelift_codegen::ir::function::FunctionParameters>::user_named_funcs
Line
Count
Source
137
107k
    pub fn user_named_funcs(&self) -> &PrimaryMap<UserExternalNameRef, UserExternalName> {
138
107k
        &self.user_named_funcs
139
107k
    }
<cranelift_codegen::ir::function::FunctionParameters>::user_named_funcs
Line
Count
Source
137
586k
    pub fn user_named_funcs(&self) -> &PrimaryMap<UserExternalNameRef, UserExternalName> {
138
586k
        &self.user_named_funcs
139
586k
    }
140
141
0
    fn clear(&mut self) {
142
0
        self.base_srcloc = None;
143
0
        self.user_named_funcs.clear();
144
0
        self.user_ext_name_to_ref.clear();
145
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionParameters>::clear
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionParameters>::clear
146
}
147
148
/// Function fields needed when compiling a function.
149
///
150
/// Additionally, these fields can be the same for two functions that would be compiled the same
151
/// way, and finalized by applying `FunctionParameters` onto their `CompiledCodeStencil`.
152
#[derive(Clone, PartialEq, Hash)]
153
#[cfg_attr(
154
    feature = "enable-serde",
155
    derive(serde_derive::Serialize, serde_derive::Deserialize)
156
)]
157
pub struct FunctionStencil {
158
    /// A version marker used to ensure that serialized clif ir is never deserialized with a
159
    /// different version of Cranelift.
160
    // Note: This must be the first field to ensure that Serde will deserialize it before
161
    // attempting to deserialize other fields that are potentially changed between versions.
162
    pub version_marker: VersionMarker,
163
164
    /// Signature of this function.
165
    pub signature: Signature,
166
167
    /// Sized stack slots allocated in this function.
168
    pub sized_stack_slots: StackSlots,
169
170
    /// Dynamic stack slots allocated in this function.
171
    pub dynamic_stack_slots: DynamicStackSlots,
172
173
    /// Global values referenced.
174
    pub global_values: PrimaryMap<ir::GlobalValue, ir::GlobalValueData>,
175
176
    /// Global value proof-carrying-code facts.
177
    pub global_value_facts: SecondaryMap<ir::GlobalValue, Option<Fact>>,
178
179
    /// Memory types for proof-carrying code.
180
    pub memory_types: PrimaryMap<ir::MemoryType, ir::MemoryTypeData>,
181
182
    /// Data flow graph containing the primary definition of all instructions, blocks and values.
183
    pub dfg: DataFlowGraph,
184
185
    /// Layout of blocks and instructions in the function body.
186
    pub layout: Layout,
187
188
    /// Source locations.
189
    ///
190
    /// Track the original source location for each instruction. The source locations are not
191
    /// interpreted by Cranelift, only preserved.
192
    pub srclocs: SourceLocs,
193
194
    /// Opaque debug-info tags on sequence-point and call
195
    /// instructions.
196
    ///
197
    /// These tags are not interpreted by Cranelift, and are passed
198
    /// through to compilation-result metadata. The only semantic
199
    /// structure that Cranelift imposes is that when inlining, it
200
    /// prepends the callsite call instruction's tags to the tags on
201
    /// inlined instructions.
202
    ///
203
    /// In order to ensure clarity around guaranteed compiler
204
    /// behavior, tags are only permitted on instructions whose
205
    /// presence and sequence will remain the same in the compiled
206
    /// output: namely, `sequence_point` instructions and ordinary
207
    /// call instructions.
208
    pub debug_tags: DebugTags,
209
210
    /// An optional global value which represents an expression evaluating to
211
    /// the stack limit for this function. This `GlobalValue` will be
212
    /// interpreted in the prologue, if necessary, to insert a stack check to
213
    /// ensure that a trap happens if the stack pointer goes below the
214
    /// threshold specified here.
215
    pub stack_limit: Option<ir::GlobalValue>,
216
}
217
218
impl FunctionStencil {
219
0
    fn clear(&mut self) {
220
0
        self.signature.clear(CallConv::Fast);
221
0
        self.sized_stack_slots.clear();
222
0
        self.dynamic_stack_slots.clear();
223
0
        self.global_values.clear();
224
0
        self.global_value_facts.clear();
225
0
        self.memory_types.clear();
226
0
        self.dfg.clear();
227
0
        self.layout.clear();
228
0
        self.srclocs.clear();
229
0
        self.debug_tags.clear();
230
0
        self.stack_limit = None;
231
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::clear
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::clear
232
233
    /// Creates a jump table in the function, to be used by `br_table` instructions.
234
1.22k
    pub fn create_jump_table(&mut self, data: JumpTableData) -> JumpTable {
235
1.22k
        self.dfg.jump_tables.push(data)
236
1.22k
    }
<cranelift_codegen::ir::function::FunctionStencil>::create_jump_table
Line
Count
Source
234
106
    pub fn create_jump_table(&mut self, data: JumpTableData) -> JumpTable {
235
106
        self.dfg.jump_tables.push(data)
236
106
    }
<cranelift_codegen::ir::function::FunctionStencil>::create_jump_table
Line
Count
Source
234
1.12k
    pub fn create_jump_table(&mut self, data: JumpTableData) -> JumpTable {
235
1.12k
        self.dfg.jump_tables.push(data)
236
1.12k
    }
237
238
    /// Creates a sized stack slot in the function, to be used by `stack_load`, `stack_store`
239
    /// and `stack_addr` instructions.
240
0
    pub fn create_sized_stack_slot(&mut self, data: StackSlotData) -> StackSlot {
241
0
        self.sized_stack_slots.push(data)
242
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::create_sized_stack_slot
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::create_sized_stack_slot
243
244
    /// Creates a dynamic stack slot in the function, to be used by `dynamic_stack_load`,
245
    /// `dynamic_stack_store` and `dynamic_stack_addr` instructions.
246
0
    pub fn create_dynamic_stack_slot(&mut self, data: DynamicStackSlotData) -> DynamicStackSlot {
247
0
        self.dynamic_stack_slots.push(data)
248
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::create_dynamic_stack_slot
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::create_dynamic_stack_slot
249
250
    /// Adds a signature which can later be used to declare an external function import.
251
247k
    pub fn import_signature(&mut self, signature: Signature) -> SigRef {
252
247k
        self.dfg.signatures.push(signature)
253
247k
    }
<cranelift_codegen::ir::function::FunctionStencil>::import_signature
Line
Count
Source
251
65.1k
    pub fn import_signature(&mut self, signature: Signature) -> SigRef {
252
65.1k
        self.dfg.signatures.push(signature)
253
65.1k
    }
<cranelift_codegen::ir::function::FunctionStencil>::import_signature
Line
Count
Source
251
182k
    pub fn import_signature(&mut self, signature: Signature) -> SigRef {
252
182k
        self.dfg.signatures.push(signature)
253
182k
    }
254
255
    /// Declares a global value accessible to the function.
256
160k
    pub fn create_global_value(&mut self, data: GlobalValueData) -> GlobalValue {
257
160k
        self.global_values.push(data)
258
160k
    }
<cranelift_codegen::ir::function::FunctionStencil>::create_global_value
Line
Count
Source
256
11.4k
    pub fn create_global_value(&mut self, data: GlobalValueData) -> GlobalValue {
257
11.4k
        self.global_values.push(data)
258
11.4k
    }
<cranelift_codegen::ir::function::FunctionStencil>::create_global_value
Line
Count
Source
256
148k
    pub fn create_global_value(&mut self, data: GlobalValueData) -> GlobalValue {
257
148k
        self.global_values.push(data)
258
148k
    }
259
260
    /// Declares a memory type for use by the function.
261
0
    pub fn create_memory_type(&mut self, data: MemoryTypeData) -> MemoryType {
262
0
        self.memory_types.push(data)
263
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::create_memory_type
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::create_memory_type
264
265
    /// Find the global dyn_scale value associated with given DynamicType.
266
0
    pub fn get_dyn_scale(&self, ty: DynamicType) -> GlobalValue {
267
0
        self.dfg.dynamic_types.get(ty).unwrap().dynamic_scale
268
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_dyn_scale
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_dyn_scale
269
270
    /// Find the global dyn_scale for the given stack slot.
271
0
    pub fn get_dynamic_slot_scale(&self, dss: DynamicStackSlot) -> GlobalValue {
272
0
        let dyn_ty = self.dynamic_stack_slots.get(dss).unwrap().dyn_ty;
273
0
        self.get_dyn_scale(dyn_ty)
274
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_dynamic_slot_scale
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_dynamic_slot_scale
275
276
    /// Get a concrete `Type` from a user defined `DynamicType`.
277
0
    pub fn get_concrete_dynamic_ty(&self, ty: DynamicType) -> Option<Type> {
278
0
        self.dfg
279
0
            .dynamic_types
280
0
            .get(ty)
281
0
            .unwrap_or_else(|| panic!("Undeclared dynamic vector type: {ty}"))
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_concrete_dynamic_ty::{closure#0}
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_concrete_dynamic_ty::{closure#0}
282
0
            .concrete()
283
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_concrete_dynamic_ty
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::get_concrete_dynamic_ty
284
285
    /// Find a presumed unique special-purpose function parameter value.
286
    ///
287
    /// Returns the value of the last `purpose` parameter, or `None` if no such parameter exists.
288
2.30M
    pub fn special_param(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> {
289
2.30M
        let entry = self.layout.entry_block().expect("Function is empty");
290
2.30M
        self.signature
291
2.30M
            .special_param_index(purpose)
292
2.30M
            .map(|i| self.dfg.block_params(entry)[i])
<cranelift_codegen::ir::function::FunctionStencil>::special_param::{closure#0}
Line
Count
Source
292
172k
            .map(|i| self.dfg.block_params(entry)[i])
<cranelift_codegen::ir::function::FunctionStencil>::special_param::{closure#0}
Line
Count
Source
292
2.12M
            .map(|i| self.dfg.block_params(entry)[i])
293
2.30M
    }
<cranelift_codegen::ir::function::FunctionStencil>::special_param
Line
Count
Source
288
172k
    pub fn special_param(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> {
289
172k
        let entry = self.layout.entry_block().expect("Function is empty");
290
172k
        self.signature
291
172k
            .special_param_index(purpose)
292
172k
            .map(|i| self.dfg.block_params(entry)[i])
293
172k
    }
<cranelift_codegen::ir::function::FunctionStencil>::special_param
Line
Count
Source
288
2.12M
    pub fn special_param(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> {
289
2.12M
        let entry = self.layout.entry_block().expect("Function is empty");
290
2.12M
        self.signature
291
2.12M
            .special_param_index(purpose)
292
2.12M
            .map(|i| self.dfg.block_params(entry)[i])
293
2.12M
    }
294
295
    /// Starts collection of debug information.
296
0
    pub fn collect_debug_info(&mut self) {
297
0
        self.dfg.collect_debug_info();
298
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::collect_debug_info
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::collect_debug_info
299
300
    /// Rewrite the branch destination to `new_dest` if the destination matches `old_dest`.
301
    /// Does nothing if called with a non-jump or non-branch instruction.
302
0
    pub fn rewrite_branch_destination(&mut self, inst: Inst, old_dest: Block, new_dest: Block) {
303
0
        for dest in self.dfg.insts[inst]
304
0
            .branch_destination_mut(&mut self.dfg.jump_tables, &mut self.dfg.exception_tables)
305
        {
306
0
            if dest.block(&self.dfg.value_lists) == old_dest {
307
0
                dest.set_block(new_dest, &mut self.dfg.value_lists)
308
0
            }
309
        }
310
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::rewrite_branch_destination
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::rewrite_branch_destination
311
312
    /// Checks that the specified block can be encoded as a basic block.
313
    ///
314
    /// On error, returns the first invalid instruction and an error message.
315
13.0M
    pub fn is_block_basic(&self, block: Block) -> Result<(), (Inst, &'static str)> {
316
13.0M
        let dfg = &self.dfg;
317
13.0M
        let inst_iter = self.layout.block_insts(block);
318
319
        // Ignore all instructions prior to the first branch.
320
115M
        let mut inst_iter = inst_iter.skip_while(|&inst| !dfg.insts[inst].opcode().is_branch());
<cranelift_codegen::ir::function::FunctionStencil>::is_block_basic::{closure#0}
Line
Count
Source
320
15.7M
        let mut inst_iter = inst_iter.skip_while(|&inst| !dfg.insts[inst].opcode().is_branch());
<cranelift_codegen::ir::function::FunctionStencil>::is_block_basic::{closure#0}
Line
Count
Source
320
100M
        let mut inst_iter = inst_iter.skip_while(|&inst| !dfg.insts[inst].opcode().is_branch());
321
322
13.0M
        if let Some(_branch) = inst_iter.next() {
323
9.67M
            if let Some(next) = inst_iter.next() {
324
0
                return Err((next, "post-terminator instruction"));
325
9.67M
            }
326
3.37M
        }
327
328
13.0M
        Ok(())
329
13.0M
    }
<cranelift_codegen::ir::function::FunctionStencil>::is_block_basic
Line
Count
Source
315
1.33M
    pub fn is_block_basic(&self, block: Block) -> Result<(), (Inst, &'static str)> {
316
1.33M
        let dfg = &self.dfg;
317
1.33M
        let inst_iter = self.layout.block_insts(block);
318
319
        // Ignore all instructions prior to the first branch.
320
1.33M
        let mut inst_iter = inst_iter.skip_while(|&inst| !dfg.insts[inst].opcode().is_branch());
321
322
1.33M
        if let Some(_branch) = inst_iter.next() {
323
754k
            if let Some(next) = inst_iter.next() {
324
0
                return Err((next, "post-terminator instruction"));
325
754k
            }
326
577k
        }
327
328
1.33M
        Ok(())
329
1.33M
    }
<cranelift_codegen::ir::function::FunctionStencil>::is_block_basic
Line
Count
Source
315
11.7M
    pub fn is_block_basic(&self, block: Block) -> Result<(), (Inst, &'static str)> {
316
11.7M
        let dfg = &self.dfg;
317
11.7M
        let inst_iter = self.layout.block_insts(block);
318
319
        // Ignore all instructions prior to the first branch.
320
11.7M
        let mut inst_iter = inst_iter.skip_while(|&inst| !dfg.insts[inst].opcode().is_branch());
321
322
11.7M
        if let Some(_branch) = inst_iter.next() {
323
8.92M
            if let Some(next) = inst_iter.next() {
324
0
                return Err((next, "post-terminator instruction"));
325
8.92M
            }
326
2.79M
        }
327
328
11.7M
        Ok(())
329
11.7M
    }
330
331
    /// Returns an iterator over the blocks succeeding the given block.
332
16.2M
    pub fn block_successors(&self, block: Block) -> impl DoubleEndedIterator<Item = Block> + '_ {
333
16.2M
        self.layout.last_inst(block).into_iter().flat_map(|inst| {
334
16.2M
            self.dfg.insts[inst]
335
16.2M
                .branch_destination(&self.dfg.jump_tables, &self.dfg.exception_tables)
336
16.2M
                .iter()
337
16.2M
                .map(|block| block.block(&self.dfg.value_lists))
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}::{closure#0}
<cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}::{closure#0}
Line
Count
Source
337
1.26M
                .map(|block| block.block(&self.dfg.value_lists))
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}::{closure#0}
<cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}::{closure#0}
Line
Count
Source
337
13.6M
                .map(|block| block.block(&self.dfg.value_lists))
338
16.2M
        })
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}
<cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}
Line
Count
Source
333
1.77M
        self.layout.last_inst(block).into_iter().flat_map(|inst| {
334
1.77M
            self.dfg.insts[inst]
335
1.77M
                .branch_destination(&self.dfg.jump_tables, &self.dfg.exception_tables)
336
1.77M
                .iter()
337
1.77M
                .map(|block| block.block(&self.dfg.value_lists))
338
1.77M
        })
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}
<cranelift_codegen::ir::function::FunctionStencil>::block_successors::{closure#0}
Line
Count
Source
333
14.5M
        self.layout.last_inst(block).into_iter().flat_map(|inst| {
334
14.5M
            self.dfg.insts[inst]
335
14.5M
                .branch_destination(&self.dfg.jump_tables, &self.dfg.exception_tables)
336
14.5M
                .iter()
337
14.5M
                .map(|block| block.block(&self.dfg.value_lists))
338
14.5M
        })
339
16.2M
    }
<cranelift_codegen::ir::function::FunctionStencil>::block_successors
Line
Count
Source
332
1.77M
    pub fn block_successors(&self, block: Block) -> impl DoubleEndedIterator<Item = Block> + '_ {
333
1.77M
        self.layout.last_inst(block).into_iter().flat_map(|inst| {
334
            self.dfg.insts[inst]
335
                .branch_destination(&self.dfg.jump_tables, &self.dfg.exception_tables)
336
                .iter()
337
                .map(|block| block.block(&self.dfg.value_lists))
338
        })
339
1.77M
    }
<cranelift_codegen::ir::function::FunctionStencil>::block_successors
Line
Count
Source
332
14.5M
    pub fn block_successors(&self, block: Block) -> impl DoubleEndedIterator<Item = Block> + '_ {
333
14.5M
        self.layout.last_inst(block).into_iter().flat_map(|inst| {
334
            self.dfg.insts[inst]
335
                .branch_destination(&self.dfg.jump_tables, &self.dfg.exception_tables)
336
                .iter()
337
                .map(|block| block.block(&self.dfg.value_lists))
338
        })
339
14.5M
    }
340
341
    /// Replace the `dst` instruction's data with the `src` instruction's data
342
    /// and then remove `src`.
343
    ///
344
    /// `src` and its result values should not be used at all, as any uses would
345
    /// be left dangling after calling this method.
346
    ///
347
    /// `src` and `dst` must have the same number of resulting values, and
348
    /// `src`'s i^th value must have the same type as `dst`'s i^th value.
349
0
    pub fn transplant_inst(&mut self, dst: Inst, src: Inst) {
350
0
        debug_assert_eq!(
351
0
            self.dfg.inst_results(dst).len(),
352
0
            self.dfg.inst_results(src).len()
353
        );
354
0
        debug_assert!(
355
0
            self.dfg
356
0
                .inst_results(dst)
357
0
                .iter()
358
0
                .zip(self.dfg.inst_results(src))
359
0
                .all(|(a, b)| self.dfg.value_type(*a) == self.dfg.value_type(*b))
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::transplant_inst::{closure#0}
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::transplant_inst::{closure#0}
360
        );
361
362
0
        self.dfg.insts[dst] = self.dfg.insts[src];
363
0
        self.layout.remove_inst(src);
364
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::transplant_inst
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::transplant_inst
365
366
    /// Size occupied by all stack slots associated with this function.
367
    ///
368
    /// Does not include any padding necessary due to offsets
369
0
    pub fn fixed_stack_size(&self) -> u32 {
370
0
        self.sized_stack_slots.values().map(|ss| ss.size).sum()
371
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::fixed_stack_size
Unexecuted instantiation: <cranelift_codegen::ir::function::FunctionStencil>::fixed_stack_size
372
373
    /// Returns the list of relative source locations for this function.
374
14.3M
    pub(crate) fn rel_srclocs(&self) -> &SecondaryMap<Inst, RelSourceLoc> {
375
14.3M
        &self.srclocs
376
14.3M
    }
<cranelift_codegen::ir::function::FunctionStencil>::rel_srclocs
Line
Count
Source
374
2.10M
    pub(crate) fn rel_srclocs(&self) -> &SecondaryMap<Inst, RelSourceLoc> {
375
2.10M
        &self.srclocs
376
2.10M
    }
<cranelift_codegen::ir::function::FunctionStencil>::rel_srclocs
Line
Count
Source
374
12.2M
    pub(crate) fn rel_srclocs(&self) -> &SecondaryMap<Inst, RelSourceLoc> {
375
12.2M
        &self.srclocs
376
12.2M
    }
377
}
378
379
/// Functions can be cloned, but it is not a very fast operation.
380
/// The clone will have all the same entity numbers as the original.
381
#[derive(Clone, PartialEq)]
382
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
383
pub struct Function {
384
    /// Name of this function.
385
    ///
386
    /// Mostly used by `.clif` files, only there for debugging / naming purposes.
387
    pub name: UserFuncName,
388
389
    /// All the fields required for compiling a function, independently of details irrelevant to
390
    /// compilation and that are stored in the `FunctionParameters` `params` field instead.
391
    pub stencil: FunctionStencil,
392
393
    /// All the parameters that can be applied onto the function stencil, that is, that don't
394
    /// matter when caching compilation artifacts.
395
    pub params: FunctionParameters,
396
}
397
398
impl core::ops::Deref for Function {
399
    type Target = FunctionStencil;
400
401
6.42G
    fn deref(&self) -> &Self::Target {
402
6.42G
        &self.stencil
403
6.42G
    }
<cranelift_codegen::ir::function::Function as core::ops::deref::Deref>::deref
Line
Count
Source
401
892M
    fn deref(&self) -> &Self::Target {
402
892M
        &self.stencil
403
892M
    }
<cranelift_codegen::ir::function::Function as core::ops::deref::Deref>::deref
Line
Count
Source
401
5.53G
    fn deref(&self) -> &Self::Target {
402
5.53G
        &self.stencil
403
5.53G
    }
404
}
405
406
impl core::ops::DerefMut for Function {
407
175M
    fn deref_mut(&mut self) -> &mut Self::Target {
408
175M
        &mut self.stencil
409
175M
    }
<cranelift_codegen::ir::function::Function as core::ops::deref::DerefMut>::deref_mut
Line
Count
Source
407
21.0M
    fn deref_mut(&mut self) -> &mut Self::Target {
408
21.0M
        &mut self.stencil
409
21.0M
    }
<cranelift_codegen::ir::function::Function as core::ops::deref::DerefMut>::deref_mut
Line
Count
Source
407
154M
    fn deref_mut(&mut self) -> &mut Self::Target {
408
154M
        &mut self.stencil
409
154M
    }
410
}
411
412
impl Function {
413
    /// Create a function with the given name and signature.
414
629k
    pub fn with_name_signature(name: UserFuncName, sig: Signature) -> Self {
415
629k
        Self {
416
629k
            name,
417
629k
            stencil: FunctionStencil {
418
629k
                version_marker: VersionMarker,
419
629k
                signature: sig,
420
629k
                sized_stack_slots: StackSlots::new(),
421
629k
                dynamic_stack_slots: DynamicStackSlots::new(),
422
629k
                global_values: PrimaryMap::new(),
423
629k
                global_value_facts: SecondaryMap::new(),
424
629k
                memory_types: PrimaryMap::new(),
425
629k
                dfg: DataFlowGraph::new(),
426
629k
                layout: Layout::new(),
427
629k
                srclocs: SecondaryMap::new(),
428
629k
                stack_limit: None,
429
629k
                debug_tags: DebugTags::default(),
430
629k
            },
431
629k
            params: FunctionParameters::new(),
432
629k
        }
433
629k
    }
<cranelift_codegen::ir::function::Function>::with_name_signature
Line
Count
Source
414
157k
    pub fn with_name_signature(name: UserFuncName, sig: Signature) -> Self {
415
157k
        Self {
416
157k
            name,
417
157k
            stencil: FunctionStencil {
418
157k
                version_marker: VersionMarker,
419
157k
                signature: sig,
420
157k
                sized_stack_slots: StackSlots::new(),
421
157k
                dynamic_stack_slots: DynamicStackSlots::new(),
422
157k
                global_values: PrimaryMap::new(),
423
157k
                global_value_facts: SecondaryMap::new(),
424
157k
                memory_types: PrimaryMap::new(),
425
157k
                dfg: DataFlowGraph::new(),
426
157k
                layout: Layout::new(),
427
157k
                srclocs: SecondaryMap::new(),
428
157k
                stack_limit: None,
429
157k
                debug_tags: DebugTags::default(),
430
157k
            },
431
157k
            params: FunctionParameters::new(),
432
157k
        }
433
157k
    }
<cranelift_codegen::ir::function::Function>::with_name_signature
Line
Count
Source
414
472k
    pub fn with_name_signature(name: UserFuncName, sig: Signature) -> Self {
415
472k
        Self {
416
472k
            name,
417
472k
            stencil: FunctionStencil {
418
472k
                version_marker: VersionMarker,
419
472k
                signature: sig,
420
472k
                sized_stack_slots: StackSlots::new(),
421
472k
                dynamic_stack_slots: DynamicStackSlots::new(),
422
472k
                global_values: PrimaryMap::new(),
423
472k
                global_value_facts: SecondaryMap::new(),
424
472k
                memory_types: PrimaryMap::new(),
425
472k
                dfg: DataFlowGraph::new(),
426
472k
                layout: Layout::new(),
427
472k
                srclocs: SecondaryMap::new(),
428
472k
                stack_limit: None,
429
472k
                debug_tags: DebugTags::default(),
430
472k
            },
431
472k
            params: FunctionParameters::new(),
432
472k
        }
433
472k
    }
434
435
    /// Clear all data structures in this function.
436
0
    pub fn clear(&mut self) {
437
0
        self.stencil.clear();
438
0
        self.params.clear();
439
0
        self.name = UserFuncName::default();
440
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::clear
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::clear
441
442
    /// Create a new empty, anonymous function with a Fast calling convention.
443
430k
    pub fn new() -> Self {
444
430k
        Self::with_name_signature(Default::default(), Signature::new(CallConv::Fast))
445
430k
    }
<cranelift_codegen::ir::function::Function>::new
Line
Count
Source
443
96.6k
    pub fn new() -> Self {
444
96.6k
        Self::with_name_signature(Default::default(), Signature::new(CallConv::Fast))
445
96.6k
    }
<cranelift_codegen::ir::function::Function>::new
Line
Count
Source
443
333k
    pub fn new() -> Self {
444
333k
        Self::with_name_signature(Default::default(), Signature::new(CallConv::Fast))
445
333k
    }
446
447
    /// Return an object that can display this function with correct ISA-specific annotations.
448
0
    pub fn display(&self) -> DisplayFunction<'_> {
449
0
        DisplayFunction(self)
450
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::display
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::display
451
452
    /// Return an object that can display this function's name and signature.
453
0
    pub fn display_spec(&self) -> DisplayFunctionSpec<'_> {
454
0
        DisplayFunctionSpec(self)
455
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::display_spec
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::display_spec
456
457
    /// Sets an absolute source location for the given instruction.
458
    ///
459
    /// If no base source location has been set yet, records it at the same time.
460
17.7M
    pub fn set_srcloc(&mut self, inst: Inst, srcloc: SourceLoc) {
461
17.7M
        let base = self.params.ensure_base_srcloc(srcloc);
462
17.7M
        self.stencil.srclocs[inst] = RelSourceLoc::from_base_offset(base, srcloc);
463
17.7M
    }
<cranelift_codegen::ir::function::Function>::set_srcloc
Line
Count
Source
460
1.64M
    pub fn set_srcloc(&mut self, inst: Inst, srcloc: SourceLoc) {
461
1.64M
        let base = self.params.ensure_base_srcloc(srcloc);
462
1.64M
        self.stencil.srclocs[inst] = RelSourceLoc::from_base_offset(base, srcloc);
463
1.64M
    }
<cranelift_codegen::ir::function::Function>::set_srcloc
Line
Count
Source
460
16.1M
    pub fn set_srcloc(&mut self, inst: Inst, srcloc: SourceLoc) {
461
16.1M
        let base = self.params.ensure_base_srcloc(srcloc);
462
16.1M
        self.stencil.srclocs[inst] = RelSourceLoc::from_base_offset(base, srcloc);
463
16.1M
    }
464
465
    /// Returns an absolute source location for the given instruction.
466
1.39M
    pub fn srcloc(&self, inst: Inst) -> SourceLoc {
467
1.39M
        let base = self.params.base_srcloc();
468
1.39M
        self.stencil.srclocs[inst].expand(base)
469
1.39M
    }
<cranelift_codegen::ir::function::Function>::srcloc
Line
Count
Source
466
85.9k
    pub fn srcloc(&self, inst: Inst) -> SourceLoc {
467
85.9k
        let base = self.params.base_srcloc();
468
85.9k
        self.stencil.srclocs[inst].expand(base)
469
85.9k
    }
<cranelift_codegen::ir::function::Function>::srcloc
Line
Count
Source
466
1.31M
    pub fn srcloc(&self, inst: Inst) -> SourceLoc {
467
1.31M
        let base = self.params.base_srcloc();
468
1.31M
        self.stencil.srclocs[inst].expand(base)
469
1.31M
    }
470
471
    /// Declare a user-defined external function import, to be referenced in `ExtFuncData::User` later.
472
0
    pub fn declare_imported_user_function(
473
0
        &mut self,
474
0
        name: UserExternalName,
475
0
    ) -> UserExternalNameRef {
476
0
        self.params.ensure_user_func_name(name)
477
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::declare_imported_user_function
Unexecuted instantiation: <cranelift_codegen::ir::function::Function>::declare_imported_user_function
478
479
    /// Declare an external function import.
480
5.45k
    pub fn import_function(&mut self, data: ExtFuncData) -> FuncRef {
481
5.45k
        self.stencil.dfg.ext_funcs.push(data)
482
5.45k
    }
<cranelift_codegen::ir::function::Function>::import_function
Line
Count
Source
480
866
    pub fn import_function(&mut self, data: ExtFuncData) -> FuncRef {
481
866
        self.stencil.dfg.ext_funcs.push(data)
482
866
    }
<cranelift_codegen::ir::function::Function>::import_function
Line
Count
Source
480
4.58k
    pub fn import_function(&mut self, data: ExtFuncData) -> FuncRef {
481
4.58k
        self.stencil.dfg.ext_funcs.push(data)
482
4.58k
    }
483
}
484
485
/// Wrapper type capable of displaying a `Function`.
486
pub struct DisplayFunction<'a>(&'a Function);
487
488
impl<'a> fmt::Display for DisplayFunction<'a> {
489
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
490
0
        write_function(fmt, self.0)
491
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::DisplayFunction as core::fmt::Display>::fmt
Unexecuted instantiation: <cranelift_codegen::ir::function::DisplayFunction as core::fmt::Display>::fmt
492
}
493
494
impl fmt::Display for Function {
495
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
496
0
        write_function(fmt, self)
497
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::Function as core::fmt::Display>::fmt
Unexecuted instantiation: <cranelift_codegen::ir::function::Function as core::fmt::Display>::fmt
498
}
499
500
impl fmt::Debug for Function {
501
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
502
0
        write_function(fmt, self)
503
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::Function as core::fmt::Debug>::fmt
Unexecuted instantiation: <cranelift_codegen::ir::function::Function as core::fmt::Debug>::fmt
504
}
505
506
/// Wrapper type capable of displaying a 'Function's name and signature.
507
pub struct DisplayFunctionSpec<'a>(&'a Function);
508
509
impl<'a> fmt::Display for DisplayFunctionSpec<'a> {
510
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
511
0
        write_function_spec(fmt, self.0)
512
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::DisplayFunctionSpec as core::fmt::Display>::fmt
Unexecuted instantiation: <cranelift_codegen::ir::function::DisplayFunctionSpec as core::fmt::Display>::fmt
513
}
514
515
impl<'a> fmt::Debug for DisplayFunctionSpec<'a> {
516
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
517
0
        write_function_spec(fmt, self.0)
518
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::function::DisplayFunctionSpec as core::fmt::Debug>::fmt
Unexecuted instantiation: <cranelift_codegen::ir::function::DisplayFunctionSpec as core::fmt::Debug>::fmt
519
}