MCPcopy Create free account
hub / github.com/bytecodealliance/wasmtime / do_inlining

Function do_inlining

cranelift/codegen/src/inline.rs:112–256  ·  view source on GitHub ↗

Walk the given function, invoke the `Inline` implementation for each call instruction, and inline the callee when directed to do so. Returns whether any call was inlined.

(
    func: &mut ir::Function,
    mut inliner: impl Inline,
)

Source from the content-addressed store, hash-verified

110///
111/// Returns whether any call was inlined.
112pub(crate) fn do_inlining(
113 func: &mut ir::Function,
114 mut inliner: impl Inline,
115) -> CodegenResult<bool> {
116 trace!("function {} before inlining: {}", func.name, func);
117
118 let mut inlined_any = false;
119 let mut allocs = InliningAllocs::default();
120
121 let mut cursor = FuncCursor::new(func);
122 'block_loop: while let Some(block) = cursor.next_block() {
123 // Always keep track of our previous cursor position. Assuming that the
124 // current position is a function call that we will inline, then the
125 // previous position is just before the inlined callee function. After
126 // inlining a call, the Cranelift user can decide whether to consider
127 // any function calls in the inlined callee for further inlining or
128 // not. When they do, then we back up to this previous cursor position
129 // so that our traversal will then continue over the inlined body.
130 let mut prev_pos;
131
132 while let Some(inst) = {
133 prev_pos = cursor.position();
134 cursor.next_inst()
135 } {
136 // Make sure that `block` is always `inst`'s block, even with all of
137 // our cursor-position-updating and block-splitting-during-inlining
138 // shenanigans below.
139 debug_assert_eq!(Some(block), cursor.func.layout.inst_block(inst));
140
141 match cursor.func.dfg.insts[inst] {
142 ir::InstructionData::Call { func_ref, .. }
143 if cursor.func.dfg.ext_funcs[func_ref].patchable =>
144 {
145 // Can't inline patchable calls; they need to
146 // remain patchable and inlining the whole body is
147 // decidedly *not* patchable!
148 }
149
150 ir::InstructionData::Call {
151 opcode: opcode @ ir::Opcode::Call | opcode @ ir::Opcode::ReturnCall,
152 args: _,
153 func_ref,
154 } => {
155 trace!(
156 "considering call site for inlining: {inst}: {}",
157 cursor.func.dfg.display_inst(inst),
158 );
159 let args = cursor.func.dfg.inst_args(inst);
160 match inliner.inline(&cursor.func, inst, opcode, func_ref, args) {
161 InlineCommand::KeepCall => {
162 trace!(" --> keeping call");
163 }
164 InlineCommand::Inline {
165 callee,
166 visit_callee,
167 } => {
168 let last_inlined_block = inline_one(
169 &mut allocs,

Callers 1

inlineMethod · 0.85

Calls 10

inline_oneFunction · 0.85
OkFunction · 0.85
inst_argsMethod · 0.80
goto_bottomMethod · 0.80
newFunction · 0.50
next_blockMethod · 0.45
positionMethod · 0.45
next_instMethod · 0.45
inlineMethod · 0.45
set_positionMethod · 0.45

Tested by

no test coverage detected