1 //! Legalize ABI boundaries.
2 //!
3 //! This legalizer sub-module contains code for dealing with ABI boundaries:
4 //!
5 //! - Function arguments passed to the entry block.
6 //! - Function arguments passed to call instructions.
7 //! - Return values from call instructions.
8 //! - Return values passed to return instructions.
9 //!
10 //! The ABI boundary legalization happens in two phases:
11 //!
12 //! 1. The `legalize_signatures` function rewrites all the preamble signatures with ABI information
13 //!    and possibly new argument types. It also rewrites the entry block arguments to match.
14 //! 2. The `handle_call_abi` and `handle_return_abi` functions rewrite call and return instructions
15 //!    to match the new ABI signatures.
16 //!
17 //! Between the two phases, preamble signatures and call/return arguments don't match. This
18 //! intermediate state doesn't type check.
19 
20 use crate::abi::{legalize_abi_value, ValueConversion};
21 use crate::cursor::{Cursor, FuncCursor};
22 use crate::flowgraph::ControlFlowGraph;
23 use crate::ir::instructions::CallInfo;
24 use crate::ir::{
25     AbiParam, ArgumentLoc, ArgumentPurpose, Block, DataFlowGraph, Function, Inst, InstBuilder,
26     MemFlags, SigRef, Signature, StackSlotData, StackSlotKind, Type, Value, ValueLoc,
27 };
28 use crate::isa::TargetIsa;
29 use crate::legalizer::split::{isplit, vsplit};
30 use alloc::borrow::Cow;
31 use alloc::vec::Vec;
32 use core::mem;
33 use cranelift_entity::EntityList;
34 use log::debug;
35 
36 /// Legalize all the function signatures in `func`.
37 ///
38 /// This changes all signatures to be ABI-compliant with full `ArgumentLoc` annotations. It doesn't
39 /// change the entry block arguments, calls, or return instructions, so this can leave the function
40 /// in a state with type discrepancies.
legalize_signatures(func: &mut Function, isa: &dyn TargetIsa)41 pub fn legalize_signatures(func: &mut Function, isa: &dyn TargetIsa) {
42     if let Some(new) = legalize_signature(&func.signature, true, isa) {
43         let old = mem::replace(&mut func.signature, new);
44         func.old_signature = Some(old);
45     }
46 
47     for (sig_ref, sig_data) in func.dfg.signatures.iter_mut() {
48         if let Some(new) = legalize_signature(sig_data, false, isa) {
49             let old = mem::replace(sig_data, new);
50             func.dfg.old_signatures[sig_ref] = Some(old);
51         }
52     }
53 
54     if let Some(entry) = func.layout.entry_block() {
55         legalize_entry_params(func, entry);
56         spill_entry_params(func, entry);
57     }
58 }
59 
60 /// Legalize the libcall signature, which we may generate on the fly after
61 /// `legalize_signatures` has been called.
legalize_libcall_signature(signature: &mut Signature, isa: &dyn TargetIsa)62 pub fn legalize_libcall_signature(signature: &mut Signature, isa: &dyn TargetIsa) {
63     if let Some(s) = legalize_signature(signature, false, isa) {
64         *signature = s;
65     }
66 }
67 
68 /// Legalize the given signature.
69 ///
70 /// `current` is true if this is the signature for the current function.
legalize_signature( signature: &Signature, current: bool, isa: &dyn TargetIsa, ) -> Option<Signature>71 fn legalize_signature(
72     signature: &Signature,
73     current: bool,
74     isa: &dyn TargetIsa,
75 ) -> Option<Signature> {
76     let mut cow = Cow::Borrowed(signature);
77     isa.legalize_signature(&mut cow, current);
78     match cow {
79         Cow::Borrowed(_) => None,
80         Cow::Owned(s) => Some(s),
81     }
82 }
83 
84 /// Legalize the entry block parameters after `func`'s signature has been legalized.
85 ///
86 /// The legalized signature may contain more parameters than the original signature, and the
87 /// parameter types have been changed. This function goes through the parameters of the entry block
88 /// and replaces them with parameters of the right type for the ABI.
89 ///
90 /// The original entry block parameters are computed from the new ABI parameters by code inserted at
91 /// the top of the entry block.
legalize_entry_params(func: &mut Function, entry: Block)92 fn legalize_entry_params(func: &mut Function, entry: Block) {
93     let mut has_sret = false;
94     let mut has_link = false;
95     let mut has_vmctx = false;
96     let mut has_sigid = false;
97     let mut has_stack_limit = false;
98 
99     // Insert position for argument conversion code.
100     // We want to insert instructions before the first instruction in the entry block.
101     // If the entry block is empty, append instructions to it instead.
102     let mut pos = FuncCursor::new(func).at_first_inst(entry);
103 
104     // Keep track of the argument types in the ABI-legalized signature.
105     let mut abi_arg = 0;
106 
107     // Process the block parameters one at a time, possibly replacing one argument with multiple new
108     // ones. We do this by detaching the entry block parameters first.
109     let block_params = pos.func.dfg.detach_block_params(entry);
110     let mut old_arg = 0;
111     while let Some(arg) = block_params.get(old_arg, &pos.func.dfg.value_lists) {
112         old_arg += 1;
113 
114         let abi_type = pos.func.signature.params[abi_arg];
115         let arg_type = pos.func.dfg.value_type(arg);
116         if arg_type == abi_type.value_type {
117             // No value translation is necessary, this argument matches the ABI type.
118             // Just use the original block argument value. This is the most common case.
119             pos.func.dfg.attach_block_param(entry, arg);
120             match abi_type.purpose {
121                 ArgumentPurpose::Normal => {}
122                 ArgumentPurpose::FramePointer => {}
123                 ArgumentPurpose::CalleeSaved => {}
124                 ArgumentPurpose::StructReturn => {
125                     debug_assert!(!has_sret, "Multiple sret arguments found");
126                     has_sret = true;
127                 }
128                 ArgumentPurpose::VMContext => {
129                     debug_assert!(!has_vmctx, "Multiple vmctx arguments found");
130                     has_vmctx = true;
131                 }
132                 ArgumentPurpose::SignatureId => {
133                     debug_assert!(!has_sigid, "Multiple sigid arguments found");
134                     has_sigid = true;
135                 }
136                 ArgumentPurpose::StackLimit => {
137                     debug_assert!(!has_stack_limit, "Multiple stack_limit arguments found");
138                     has_stack_limit = true;
139                 }
140                 _ => panic!("Unexpected special-purpose arg {}", abi_type),
141             }
142             abi_arg += 1;
143         } else {
144             // Compute the value we want for `arg` from the legalized ABI parameters.
145             let mut get_arg = |func: &mut Function, ty| {
146                 let abi_type = func.signature.params[abi_arg];
147                 debug_assert_eq!(
148                     abi_type.purpose,
149                     ArgumentPurpose::Normal,
150                     "Can't legalize special-purpose argument"
151                 );
152                 if ty == abi_type.value_type {
153                     abi_arg += 1;
154                     Ok(func.dfg.append_block_param(entry, ty))
155                 } else {
156                     Err(abi_type)
157                 }
158             };
159             let converted = convert_from_abi(&mut pos, arg_type, Some(arg), &mut get_arg);
160             // The old `arg` is no longer an attached block argument, but there are probably still
161             // uses of the value.
162             debug_assert_eq!(pos.func.dfg.resolve_aliases(arg), converted);
163         }
164     }
165 
166     // The legalized signature may contain additional parameters representing special-purpose
167     // registers.
168     for &arg in &pos.func.signature.params[abi_arg..] {
169         match arg.purpose {
170             // Any normal parameters should have been processed above.
171             ArgumentPurpose::Normal => {
172                 panic!("Leftover arg: {}", arg);
173             }
174             // The callee-save parameters should not appear until after register allocation is
175             // done.
176             ArgumentPurpose::FramePointer | ArgumentPurpose::CalleeSaved => {
177                 panic!("Premature callee-saved arg {}", arg);
178             }
179             // These can be meaningfully added by `legalize_signature()`.
180             ArgumentPurpose::Link => {
181                 debug_assert!(!has_link, "Multiple link parameters found");
182                 has_link = true;
183             }
184             ArgumentPurpose::StructReturn => {
185                 debug_assert!(!has_sret, "Multiple sret parameters found");
186                 has_sret = true;
187             }
188             ArgumentPurpose::VMContext => {
189                 debug_assert!(!has_vmctx, "Multiple vmctx parameters found");
190                 has_vmctx = true;
191             }
192             ArgumentPurpose::SignatureId => {
193                 debug_assert!(!has_sigid, "Multiple sigid parameters found");
194                 has_sigid = true;
195             }
196             ArgumentPurpose::StackLimit => {
197                 debug_assert!(!has_stack_limit, "Multiple stack_limit parameters found");
198                 has_stack_limit = true;
199             }
200         }
201 
202         // Just create entry block values to match here. We will use them in `handle_return_abi()`
203         // below.
204         pos.func.dfg.append_block_param(entry, arg.value_type);
205     }
206 }
207 
208 /// Legalize the results returned from a call instruction to match the ABI signature.
209 ///
210 /// The cursor `pos` points to a call instruction with at least one return value. The cursor will
211 /// be left pointing after the instructions inserted to convert the return values.
212 ///
213 /// This function is very similar to the `legalize_entry_params` function above.
214 ///
215 /// Returns the possibly new instruction representing the call.
legalize_inst_results<ResType>(pos: &mut FuncCursor, mut get_abi_type: ResType) -> Inst where ResType: FnMut(&Function, usize) -> AbiParam,216 fn legalize_inst_results<ResType>(pos: &mut FuncCursor, mut get_abi_type: ResType) -> Inst
217 where
218     ResType: FnMut(&Function, usize) -> AbiParam,
219 {
220     let call = pos
221         .current_inst()
222         .expect("Cursor must point to a call instruction");
223 
224     // We theoretically allow for call instructions that return a number of fixed results before
225     // the call return values. In practice, it doesn't happen.
226     debug_assert_eq!(
227         pos.func.dfg[call]
228             .opcode()
229             .constraints()
230             .num_fixed_results(),
231         0,
232         "Fixed results on calls not supported"
233     );
234 
235     let results = pos.func.dfg.detach_results(call);
236     let mut next_res = 0;
237     let mut abi_res = 0;
238 
239     // Point immediately after the call.
240     pos.next_inst();
241 
242     while let Some(res) = results.get(next_res, &pos.func.dfg.value_lists) {
243         next_res += 1;
244 
245         let res_type = pos.func.dfg.value_type(res);
246         if res_type == get_abi_type(pos.func, abi_res).value_type {
247             // No value translation is necessary, this result matches the ABI type.
248             pos.func.dfg.attach_result(call, res);
249             abi_res += 1;
250         } else {
251             let mut get_res = |func: &mut Function, ty| {
252                 let abi_type = get_abi_type(func, abi_res);
253                 if ty == abi_type.value_type {
254                     let last_res = func.dfg.append_result(call, ty);
255                     abi_res += 1;
256                     Ok(last_res)
257                 } else {
258                     Err(abi_type)
259                 }
260             };
261             let v = convert_from_abi(pos, res_type, Some(res), &mut get_res);
262             debug_assert_eq!(pos.func.dfg.resolve_aliases(res), v);
263         }
264     }
265 
266     call
267 }
268 
assert_is_valid_sret_legalization( old_ret_list: &EntityList<Value>, old_sig: &Signature, new_sig: &Signature, pos: &FuncCursor, )269 fn assert_is_valid_sret_legalization(
270     old_ret_list: &EntityList<Value>,
271     old_sig: &Signature,
272     new_sig: &Signature,
273     pos: &FuncCursor,
274 ) {
275     debug_assert_eq!(
276         old_sig.returns.len(),
277         old_ret_list.len(&pos.func.dfg.value_lists)
278     );
279 
280     // Assert that the only difference in special parameters is that there
281     // is an appended struct return pointer parameter.
282     let old_special_params: Vec<_> = old_sig
283         .params
284         .iter()
285         .filter(|r| r.purpose != ArgumentPurpose::Normal)
286         .collect();
287     let new_special_params: Vec<_> = new_sig
288         .params
289         .iter()
290         .filter(|r| r.purpose != ArgumentPurpose::Normal)
291         .collect();
292     debug_assert_eq!(old_special_params.len() + 1, new_special_params.len());
293     debug_assert!(old_special_params
294         .iter()
295         .zip(&new_special_params)
296         .all(|(old, new)| old.purpose == new.purpose));
297     debug_assert_eq!(
298         new_special_params.last().unwrap().purpose,
299         ArgumentPurpose::StructReturn
300     );
301 
302     // If the special returns have changed at all, then the only change
303     // should be that the struct return pointer is returned back out of the
304     // function, so that callers don't have to load its stack address again.
305     let old_special_returns: Vec<_> = old_sig
306         .returns
307         .iter()
308         .filter(|r| r.purpose != ArgumentPurpose::Normal)
309         .collect();
310     let new_special_returns: Vec<_> = new_sig
311         .returns
312         .iter()
313         .filter(|r| r.purpose != ArgumentPurpose::Normal)
314         .collect();
315     debug_assert!(old_special_returns
316         .iter()
317         .zip(&new_special_returns)
318         .all(|(old, new)| old.purpose == new.purpose));
319     debug_assert!(
320         old_special_returns.len() == new_special_returns.len()
321             || (old_special_returns.len() + 1 == new_special_returns.len()
322                 && new_special_returns.last().unwrap().purpose == ArgumentPurpose::StructReturn)
323     );
324 }
325 
legalize_sret_call(isa: &dyn TargetIsa, pos: &mut FuncCursor, sig_ref: SigRef, call: Inst)326 fn legalize_sret_call(isa: &dyn TargetIsa, pos: &mut FuncCursor, sig_ref: SigRef, call: Inst) {
327     let old_ret_list = pos.func.dfg.detach_results(call);
328     let old_sig = pos.func.dfg.old_signatures[sig_ref]
329         .take()
330         .expect("must have an old signature when using an `sret` parameter");
331 
332     // We make a bunch of assumptions about the shape of the old, multi-return
333     // signature and the new, sret-using signature in this legalization
334     // function. Assert that these assumptions hold true in debug mode.
335     if cfg!(debug_assertions) {
336         assert_is_valid_sret_legalization(
337             &old_ret_list,
338             &old_sig,
339             &pos.func.dfg.signatures[sig_ref],
340             &pos,
341         );
342     }
343 
344     // Go through and remove all normal return values from the `call`
345     // instruction's returns list. These will be stored into the stack slot that
346     // the sret points to. At the same time, calculate the size of the sret
347     // stack slot.
348     let mut sret_slot_size = 0;
349     for (i, ret) in old_sig.returns.iter().enumerate() {
350         let v = old_ret_list.get(i, &pos.func.dfg.value_lists).unwrap();
351         let ty = pos.func.dfg.value_type(v);
352         if ret.purpose == ArgumentPurpose::Normal {
353             debug_assert_eq!(ret.location, ArgumentLoc::Unassigned);
354             let ty = legalized_type_for_sret(ty);
355             let size = ty.bytes();
356             sret_slot_size = round_up_to_multiple_of_type_align(sret_slot_size, ty) + size;
357         } else {
358             let new_v = pos.func.dfg.append_result(call, ty);
359             pos.func.dfg.change_to_alias(v, new_v);
360         }
361     }
362 
363     let stack_slot = pos.func.stack_slots.push(StackSlotData {
364         kind: StackSlotKind::StructReturnSlot,
365         size: sret_slot_size,
366         offset: None,
367     });
368 
369     // Append the sret pointer to the `call` instruction's arguments.
370     let ptr_type = Type::triple_pointer_type(isa.triple());
371     let sret_arg = pos.ins().stack_addr(ptr_type, stack_slot, 0);
372     pos.func.dfg.append_inst_arg(call, sret_arg);
373 
374     // The sret pointer might be returned by the signature as well. If so, we
375     // need to add it to the `call` instruction's results list.
376     //
377     // Additionally, when the sret is explicitly returned in this calling
378     // convention, then use it when loading the sret returns back into ssa
379     // values to avoid keeping the original `sret_arg` live and potentially
380     // having to do spills and fills.
381     let sret =
382         if pos.func.dfg.signatures[sig_ref].uses_special_return(ArgumentPurpose::StructReturn) {
383             pos.func.dfg.append_result(call, ptr_type)
384         } else {
385             sret_arg
386         };
387 
388     // Finally, load each of the call's return values out of the sret stack
389     // slot.
390     pos.goto_after_inst(call);
391     let mut offset = 0;
392     for i in 0..old_ret_list.len(&pos.func.dfg.value_lists) {
393         if old_sig.returns[i].purpose != ArgumentPurpose::Normal {
394             continue;
395         }
396 
397         let old_v = old_ret_list.get(i, &pos.func.dfg.value_lists).unwrap();
398         let ty = pos.func.dfg.value_type(old_v);
399         let mut legalized_ty = legalized_type_for_sret(ty);
400 
401         offset = round_up_to_multiple_of_type_align(offset, legalized_ty);
402 
403         let new_legalized_v =
404             pos.ins()
405                 .load(legalized_ty, MemFlags::trusted(), sret, offset as i32);
406 
407         // "Illegalize" the loaded value from the legalized type back to its
408         // original `ty`. This is basically the opposite of
409         // `legalize_type_for_sret_store`.
410         let mut new_v = new_legalized_v;
411         if ty.is_bool() {
412             legalized_ty = legalized_ty.as_bool_pedantic();
413             new_v = pos.ins().raw_bitcast(legalized_ty, new_v);
414 
415             if ty.bits() < legalized_ty.bits() {
416                 legalized_ty = ty;
417                 new_v = pos.ins().breduce(legalized_ty, new_v);
418             }
419         }
420 
421         pos.func.dfg.change_to_alias(old_v, new_v);
422 
423         offset += legalized_ty.bytes();
424     }
425 
426     pos.func.dfg.old_signatures[sig_ref] = Some(old_sig);
427 }
428 
429 /// Compute original value of type `ty` from the legalized ABI arguments.
430 ///
431 /// The conversion is recursive, controlled by the `get_arg` closure which is called to retrieve an
432 /// ABI argument. It returns:
433 ///
434 /// - `Ok(arg)` if the requested type matches the next ABI argument.
435 /// - `Err(arg_type)` if further conversions are needed from the ABI argument `arg_type`.
436 ///
437 /// If the `into_result` value is provided, the converted result will be written into that value.
convert_from_abi<GetArg>( pos: &mut FuncCursor, ty: Type, into_result: Option<Value>, get_arg: &mut GetArg, ) -> Value where GetArg: FnMut(&mut Function, Type) -> Result<Value, AbiParam>,438 fn convert_from_abi<GetArg>(
439     pos: &mut FuncCursor,
440     ty: Type,
441     into_result: Option<Value>,
442     get_arg: &mut GetArg,
443 ) -> Value
444 where
445     GetArg: FnMut(&mut Function, Type) -> Result<Value, AbiParam>,
446 {
447     // Terminate the recursion when we get the desired type.
448     let arg_type = match get_arg(pos.func, ty) {
449         Ok(v) => {
450             debug_assert_eq!(pos.func.dfg.value_type(v), ty);
451             debug_assert_eq!(into_result, None);
452             return v;
453         }
454         Err(t) => t,
455     };
456 
457     // Reconstruct how `ty` was legalized into the `arg_type` argument.
458     let conversion = legalize_abi_value(ty, &arg_type);
459 
460     debug!("convert_from_abi({}): {:?}", ty, conversion);
461 
462     // The conversion describes value to ABI argument. We implement the reverse conversion here.
463     match conversion {
464         // Construct a `ty` by concatenating two ABI integers.
465         ValueConversion::IntSplit => {
466             let abi_ty = ty.half_width().expect("Invalid type for conversion");
467             let lo = convert_from_abi(pos, abi_ty, None, get_arg);
468             let hi = convert_from_abi(pos, abi_ty, None, get_arg);
469             debug!(
470                 "intsplit {}: {}, {}: {}",
471                 lo,
472                 pos.func.dfg.value_type(lo),
473                 hi,
474                 pos.func.dfg.value_type(hi)
475             );
476             pos.ins().with_results([into_result]).iconcat(lo, hi)
477         }
478         // Construct a `ty` by concatenating two halves of a vector.
479         ValueConversion::VectorSplit => {
480             let abi_ty = ty.half_vector().expect("Invalid type for conversion");
481             let lo = convert_from_abi(pos, abi_ty, None, get_arg);
482             let hi = convert_from_abi(pos, abi_ty, None, get_arg);
483             pos.ins().with_results([into_result]).vconcat(lo, hi)
484         }
485         // Construct a `ty` by bit-casting from an integer type.
486         ValueConversion::IntBits => {
487             debug_assert!(!ty.is_int());
488             let abi_ty = Type::int(ty.bits()).expect("Invalid type for conversion");
489             let arg = convert_from_abi(pos, abi_ty, None, get_arg);
490             pos.ins().with_results([into_result]).bitcast(ty, arg)
491         }
492         // ABI argument is a sign-extended version of the value we want.
493         ValueConversion::Sext(abi_ty) => {
494             let arg = convert_from_abi(pos, abi_ty, None, get_arg);
495             // TODO: Currently, we don't take advantage of the ABI argument being sign-extended.
496             // We could insert an `assert_sreduce` which would fold with a following `sextend` of
497             // this value.
498             pos.ins().with_results([into_result]).ireduce(ty, arg)
499         }
500         ValueConversion::Uext(abi_ty) => {
501             let arg = convert_from_abi(pos, abi_ty, None, get_arg);
502             // TODO: Currently, we don't take advantage of the ABI argument being sign-extended.
503             // We could insert an `assert_ureduce` which would fold with a following `uextend` of
504             // this value.
505             pos.ins().with_results([into_result]).ireduce(ty, arg)
506         }
507         // ABI argument is a pointer to the value we want.
508         ValueConversion::Pointer(abi_ty) => {
509             let arg = convert_from_abi(pos, abi_ty, None, get_arg);
510             pos.ins()
511                 .with_results([into_result])
512                 .load(ty, MemFlags::new(), arg, 0)
513         }
514     }
515 }
516 
517 /// Convert `value` to match an ABI signature by inserting instructions at `pos`.
518 ///
519 /// This may require expanding the value to multiple ABI arguments. The conversion process is
520 /// recursive and controlled by the `put_arg` closure. When a candidate argument value is presented
521 /// to the closure, it will perform one of two actions:
522 ///
523 /// 1. If the suggested argument has an acceptable value type, consume it by adding it to the list
524 ///    of arguments and return `Ok(())`.
525 /// 2. If the suggested argument doesn't have the right value type, don't change anything, but
526 ///    return the `Err(AbiParam)` that is needed.
527 ///
convert_to_abi<PutArg>( pos: &mut FuncCursor, cfg: &ControlFlowGraph, value: Value, put_arg: &mut PutArg, ) where PutArg: FnMut(&mut Function, Value) -> Result<(), AbiParam>,528 fn convert_to_abi<PutArg>(
529     pos: &mut FuncCursor,
530     cfg: &ControlFlowGraph,
531     value: Value,
532     put_arg: &mut PutArg,
533 ) where
534     PutArg: FnMut(&mut Function, Value) -> Result<(), AbiParam>,
535 {
536     // Start by invoking the closure to either terminate the recursion or get the argument type
537     // we're trying to match.
538     let arg_type = match put_arg(pos.func, value) {
539         Ok(_) => return,
540         Err(t) => t,
541     };
542 
543     let ty = pos.func.dfg.value_type(value);
544     match legalize_abi_value(ty, &arg_type) {
545         ValueConversion::IntSplit => {
546             let curpos = pos.position();
547             let srcloc = pos.srcloc();
548             let (lo, hi) = isplit(&mut pos.func, cfg, curpos, srcloc, value);
549             convert_to_abi(pos, cfg, lo, put_arg);
550             convert_to_abi(pos, cfg, hi, put_arg);
551         }
552         ValueConversion::VectorSplit => {
553             let curpos = pos.position();
554             let srcloc = pos.srcloc();
555             let (lo, hi) = vsplit(&mut pos.func, cfg, curpos, srcloc, value);
556             convert_to_abi(pos, cfg, lo, put_arg);
557             convert_to_abi(pos, cfg, hi, put_arg);
558         }
559         ValueConversion::IntBits => {
560             debug_assert!(!ty.is_int());
561             let abi_ty = Type::int(ty.bits()).expect("Invalid type for conversion");
562             let arg = pos.ins().bitcast(abi_ty, value);
563             convert_to_abi(pos, cfg, arg, put_arg);
564         }
565         ValueConversion::Sext(abi_ty) => {
566             let arg = pos.ins().sextend(abi_ty, value);
567             convert_to_abi(pos, cfg, arg, put_arg);
568         }
569         ValueConversion::Uext(abi_ty) => {
570             let arg = pos.ins().uextend(abi_ty, value);
571             convert_to_abi(pos, cfg, arg, put_arg);
572         }
573         ValueConversion::Pointer(abi_ty) => {
574             // Note: This conversion can only happen for call arguments,
575             // so we can allocate the value on stack safely.
576             let stack_slot = pos.func.create_stack_slot(StackSlotData {
577                 kind: StackSlotKind::ExplicitSlot,
578                 size: ty.bytes(),
579                 offset: None,
580             });
581             let arg = pos.ins().stack_addr(abi_ty, stack_slot, 0);
582             pos.ins().store(MemFlags::new(), value, arg, 0);
583             convert_to_abi(pos, cfg, arg, put_arg);
584         }
585     }
586 }
587 
588 /// Check if a sequence of arguments match a desired sequence of argument types.
check_arg_types(dfg: &DataFlowGraph, args: &[Value], types: &[AbiParam]) -> bool589 fn check_arg_types(dfg: &DataFlowGraph, args: &[Value], types: &[AbiParam]) -> bool {
590     let arg_types = args.iter().map(|&v| dfg.value_type(v));
591     let sig_types = types.iter().map(|&at| at.value_type);
592     arg_types.eq(sig_types)
593 }
594 
595 /// Check if the arguments of the call `inst` match the signature.
596 ///
597 /// Returns `Ok(())` if the signature matches and no changes are needed, or `Err(sig_ref)` if the
598 /// signature doesn't match.
check_call_signature(dfg: &DataFlowGraph, inst: Inst) -> Result<(), SigRef>599 fn check_call_signature(dfg: &DataFlowGraph, inst: Inst) -> Result<(), SigRef> {
600     // Extract the signature and argument values.
601     let (sig_ref, args) = match dfg[inst].analyze_call(&dfg.value_lists) {
602         CallInfo::Direct(func, args) => (dfg.ext_funcs[func].signature, args),
603         CallInfo::Indirect(sig_ref, args) => (sig_ref, args),
604         CallInfo::NotACall => panic!("Expected call, got {:?}", dfg[inst]),
605     };
606     let sig = &dfg.signatures[sig_ref];
607 
608     if check_arg_types(dfg, args, &sig.params[..])
609         && check_arg_types(dfg, dfg.inst_results(inst), &sig.returns[..])
610     {
611         // All types check out.
612         Ok(())
613     } else {
614         // Call types need fixing.
615         Err(sig_ref)
616     }
617 }
618 
619 /// Check if the arguments of the return `inst` match the signature.
check_return_signature(dfg: &DataFlowGraph, inst: Inst, sig: &Signature) -> bool620 fn check_return_signature(dfg: &DataFlowGraph, inst: Inst, sig: &Signature) -> bool {
621     check_arg_types(dfg, dfg.inst_variable_args(inst), &sig.returns)
622 }
623 
624 /// Insert ABI conversion code for the arguments to the call or return instruction at `pos`.
625 ///
626 /// - `abi_args` is the number of arguments that the ABI signature requires.
627 /// - `get_abi_type` is a closure that can provide the desired `AbiParam` for a given ABI
628 ///   argument number in `0..abi_args`.
629 ///
legalize_inst_arguments<ArgType>( pos: &mut FuncCursor, cfg: &ControlFlowGraph, abi_args: usize, mut get_abi_type: ArgType, ) where ArgType: FnMut(&Function, usize) -> AbiParam,630 fn legalize_inst_arguments<ArgType>(
631     pos: &mut FuncCursor,
632     cfg: &ControlFlowGraph,
633     abi_args: usize,
634     mut get_abi_type: ArgType,
635 ) where
636     ArgType: FnMut(&Function, usize) -> AbiParam,
637 {
638     let inst = pos
639         .current_inst()
640         .expect("Cursor must point to a call instruction");
641 
642     // Lift the value list out of the call instruction so we modify it.
643     let mut vlist = pos.func.dfg[inst]
644         .take_value_list()
645         .expect("Call must have a value list");
646 
647     // The value list contains all arguments to the instruction, including the callee on an
648     // indirect call which isn't part of the call arguments that must match the ABI signature.
649     // Figure out how many fixed values are at the front of the list. We won't touch those.
650     let num_fixed_values = pos.func.dfg[inst]
651         .opcode()
652         .constraints()
653         .num_fixed_value_arguments();
654     let have_args = vlist.len(&pos.func.dfg.value_lists) - num_fixed_values;
655     if abi_args < have_args {
656         // This happens with multiple return values after we've legalized the
657         // signature but haven't legalized the return instruction yet. This
658         // legalization is handled in `handle_return_abi`.
659         pos.func.dfg[inst].put_value_list(vlist);
660         return;
661     }
662 
663     // Grow the value list to the right size and shift all the existing arguments to the right.
664     // This lets us write the new argument values into the list without overwriting the old
665     // arguments.
666     //
667     // Before:
668     //
669     //    <-->              fixed_values
670     //        <-----------> have_args
671     //   [FFFFOOOOOOOOOOOOO]
672     //
673     // After grow_at():
674     //
675     //    <-->                     fixed_values
676     //               <-----------> have_args
677     //        <------------------> abi_args
678     //   [FFFF-------OOOOOOOOOOOOO]
679     //               ^
680     //               old_arg_offset
681     //
682     // After writing the new arguments:
683     //
684     //    <-->                     fixed_values
685     //        <------------------> abi_args
686     //   [FFFFNNNNNNNNNNNNNNNNNNNN]
687     //
688     vlist.grow_at(
689         num_fixed_values,
690         abi_args - have_args,
691         &mut pos.func.dfg.value_lists,
692     );
693     let old_arg_offset = num_fixed_values + abi_args - have_args;
694 
695     let mut abi_arg = 0;
696     for old_arg in 0..have_args {
697         let old_value = vlist
698             .get(old_arg_offset + old_arg, &pos.func.dfg.value_lists)
699             .unwrap();
700         let mut put_arg = |func: &mut Function, arg| {
701             let abi_type = get_abi_type(func, abi_arg);
702             if func.dfg.value_type(arg) == abi_type.value_type {
703                 // This is the argument type we need.
704                 vlist.as_mut_slice(&mut func.dfg.value_lists)[num_fixed_values + abi_arg] = arg;
705                 abi_arg += 1;
706                 Ok(())
707             } else {
708                 Err(abi_type)
709             }
710         };
711         convert_to_abi(pos, cfg, old_value, &mut put_arg);
712     }
713 
714     // Put the modified value list back.
715     pos.func.dfg[inst].put_value_list(vlist);
716 }
717 
718 /// Ensure that the `ty` being returned is a type that can be loaded and stored
719 /// (potentially after another narrowing legalization) from memory, since it
720 /// will go into the `sret` space.
legalized_type_for_sret(ty: Type) -> Type721 fn legalized_type_for_sret(ty: Type) -> Type {
722     if ty.is_bool() {
723         let bits = std::cmp::max(8, ty.bits());
724         Type::int(bits).unwrap()
725     } else {
726         ty
727     }
728 }
729 
730 /// Insert any legalization code required to ensure that `val` can be stored
731 /// into the `sret` memory. Returns the (potentially new, potentially
732 /// unmodified) legalized value and its type.
legalize_type_for_sret_store(pos: &mut FuncCursor, val: Value, ty: Type) -> (Value, Type)733 fn legalize_type_for_sret_store(pos: &mut FuncCursor, val: Value, ty: Type) -> (Value, Type) {
734     if ty.is_bool() {
735         let bits = std::cmp::max(8, ty.bits());
736         let ty = Type::int(bits).unwrap();
737         let val = pos.ins().bint(ty, val);
738         (val, ty)
739     } else {
740         (val, ty)
741     }
742 }
743 
744 /// Insert ABI conversion code before and after the call instruction at `pos`.
745 ///
746 /// Instructions inserted before the call will compute the appropriate ABI values for the
747 /// callee's new ABI-legalized signature. The function call arguments are rewritten in place to
748 /// match the new signature.
749 ///
750 /// Instructions will be inserted after the call to convert returned ABI values back to the
751 /// original return values. The call's result values will be adapted to match the new signature.
752 ///
753 /// Returns `true` if any instructions were inserted.
handle_call_abi( isa: &dyn TargetIsa, mut inst: Inst, func: &mut Function, cfg: &ControlFlowGraph, ) -> bool754 pub fn handle_call_abi(
755     isa: &dyn TargetIsa,
756     mut inst: Inst,
757     func: &mut Function,
758     cfg: &ControlFlowGraph,
759 ) -> bool {
760     let pos = &mut FuncCursor::new(func).at_inst(inst);
761     pos.use_srcloc(inst);
762 
763     // Start by checking if the argument types already match the signature.
764     let sig_ref = match check_call_signature(&pos.func.dfg, inst) {
765         Ok(_) => return spill_call_arguments(pos),
766         Err(s) => s,
767     };
768 
769     let sig = &pos.func.dfg.signatures[sig_ref];
770     let old_sig = &pos.func.dfg.old_signatures[sig_ref];
771 
772     if sig.uses_struct_return_param()
773         && old_sig
774             .as_ref()
775             .map_or(false, |s| !s.uses_struct_return_param())
776     {
777         legalize_sret_call(isa, pos, sig_ref, inst);
778     } else {
779         if !pos.func.dfg.signatures[sig_ref].returns.is_empty() {
780             inst = legalize_inst_results(pos, |func, abi_res| {
781                 func.dfg.signatures[sig_ref].returns[abi_res]
782             });
783         }
784     }
785 
786     // Go back and fix the call arguments to match the ABI signature.
787     pos.goto_inst(inst);
788     let abi_args = pos.func.dfg.signatures[sig_ref].params.len();
789     legalize_inst_arguments(pos, cfg, abi_args, |func, abi_arg| {
790         func.dfg.signatures[sig_ref].params[abi_arg]
791     });
792 
793     debug_assert!(
794         check_call_signature(&pos.func.dfg, inst).is_ok(),
795         "Signature still wrong: {}, {}{}",
796         pos.func.dfg.display_inst(inst, None),
797         sig_ref,
798         pos.func.dfg.signatures[sig_ref]
799     );
800 
801     // Go back and insert spills for any stack arguments.
802     pos.goto_inst(inst);
803     spill_call_arguments(pos);
804 
805     // Yes, we changed stuff.
806     true
807 }
808 
809 /// Insert ABI conversion code before and after the return instruction at `inst`.
810 ///
811 /// Return `true` if any instructions were inserted.
handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool812 pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool {
813     // Check if the returned types already match the signature.
814     if check_return_signature(&func.dfg, inst, &func.signature) {
815         return false;
816     }
817 
818     // Count the special-purpose return values (`link`, `sret`, and `vmctx`) that were appended to
819     // the legalized signature.
820     let special_args = func
821         .signature
822         .returns
823         .iter()
824         .rev()
825         .take_while(|&rt| {
826             rt.purpose == ArgumentPurpose::Link
827                 || rt.purpose == ArgumentPurpose::StructReturn
828                 || rt.purpose == ArgumentPurpose::VMContext
829         })
830         .count();
831     let abi_args = func.signature.returns.len() - special_args;
832 
833     let pos = &mut FuncCursor::new(func).at_inst(inst);
834     pos.use_srcloc(inst);
835 
836     legalize_inst_arguments(pos, cfg, abi_args, |func, abi_arg| {
837         let arg = func.signature.returns[abi_arg];
838         debug_assert!(
839             !arg.legalized_to_pointer,
840             "Return value cannot be legalized to pointer"
841         );
842         arg
843     });
844     // Append special return arguments for any `sret`, `link`, and `vmctx` return values added to
845     // the legalized signature. These values should simply be propagated from the entry block
846     // arguments.
847     if special_args > 0 {
848         debug!(
849             "Adding {} special-purpose arguments to {}",
850             special_args,
851             pos.func.dfg.display_inst(inst, None)
852         );
853         let mut vlist = pos.func.dfg[inst].take_value_list().unwrap();
854         let mut sret = None;
855 
856         for arg in &pos.func.signature.returns[abi_args..] {
857             match arg.purpose {
858                 ArgumentPurpose::Link
859                 | ArgumentPurpose::StructReturn
860                 | ArgumentPurpose::VMContext => {}
861                 ArgumentPurpose::Normal => panic!("unexpected return value {}", arg),
862                 _ => panic!("Unsupported special purpose return value {}", arg),
863             }
864             // A `link`/`sret`/`vmctx` return value can only appear in a signature that has a
865             // unique matching argument. They are appended at the end, so search the signature from
866             // the end.
867             let idx = pos
868                 .func
869                 .signature
870                 .params
871                 .iter()
872                 .rposition(|t| t.purpose == arg.purpose)
873                 .expect("No matching special purpose argument.");
874             // Get the corresponding entry block value and add it to the return instruction's
875             // arguments.
876             let val = pos
877                 .func
878                 .dfg
879                 .block_params(pos.func.layout.entry_block().unwrap())[idx];
880             debug_assert_eq!(pos.func.dfg.value_type(val), arg.value_type);
881             vlist.push(val, &mut pos.func.dfg.value_lists);
882 
883             if let ArgumentPurpose::StructReturn = arg.purpose {
884                 sret = Some(val);
885             }
886         }
887 
888         // Store all the regular returns into the retptr space and remove them
889         // from the `return` instruction's value list.
890         if let Some(sret) = sret {
891             let mut offset = 0;
892             let num_regular_rets = vlist.len(&pos.func.dfg.value_lists) - special_args;
893             for i in 0..num_regular_rets {
894                 debug_assert_eq!(
895                     pos.func.old_signature.as_ref().unwrap().returns[i].purpose,
896                     ArgumentPurpose::Normal,
897                 );
898 
899                 // The next return value to process is always at `0`, since the
900                 // list is emptied as we iterate.
901                 let v = vlist.get(0, &pos.func.dfg.value_lists).unwrap();
902                 let ty = pos.func.dfg.value_type(v);
903                 let (v, ty) = legalize_type_for_sret_store(pos, v, ty);
904 
905                 let size = ty.bytes();
906                 offset = round_up_to_multiple_of_type_align(offset, ty);
907 
908                 pos.ins().store(MemFlags::trusted(), v, sret, offset as i32);
909                 vlist.remove(0, &mut pos.func.dfg.value_lists);
910 
911                 offset += size;
912             }
913         }
914         pos.func.dfg[inst].put_value_list(vlist);
915     }
916 
917     debug_assert_eq!(
918         pos.func.dfg.inst_variable_args(inst).len(),
919         abi_args + special_args
920     );
921     debug_assert!(
922         check_return_signature(&pos.func.dfg, inst, &pos.func.signature),
923         "Signature still wrong: {} / signature {}",
924         pos.func.dfg.display_inst(inst, None),
925         pos.func.signature
926     );
927 
928     // Yes, we changed stuff.
929     true
930 }
931 
round_up_to_multiple_of_type_align(bytes: u32, ty: Type) -> u32932 fn round_up_to_multiple_of_type_align(bytes: u32, ty: Type) -> u32 {
933     // We don't have a dedicated alignment for types, so assume they are
934     // size-aligned.
935     let align = ty.bytes();
936     round_up_to_multiple_of_pow2(bytes, align)
937 }
938 
939 /// Round `n` up to the next multiple of `to` that is greater than or equal to
940 /// `n`.
941 ///
942 /// `to` must be a power of two and greater than zero.
943 ///
944 /// This is useful for rounding an offset or pointer up to some type's required
945 /// alignment.
round_up_to_multiple_of_pow2(n: u32, to: u32) -> u32946 fn round_up_to_multiple_of_pow2(n: u32, to: u32) -> u32 {
947     debug_assert!(to > 0);
948     debug_assert!(to.is_power_of_two());
949 
950     // The simple version of this function is
951     //
952     //     (n + to - 1) / to * to
953     //
954     // Consider the numerator: `n + to - 1`. This is ensuring that if there is
955     // any remainder for `n / to`, then the result of the division is one
956     // greater than `n / to`, and that otherwise we get exactly the same result
957     // as `n / to` due to integer division rounding off the remainder. In other
958     // words, we only round up if `n` is not aligned to `to`.
959     //
960     // However, we know `to` is a power of two, and therefore `anything / to` is
961     // equivalent to `anything >> log2(to)` and `anything * to` is equivalent to
962     // `anything << log2(to)`. We can therefore rewrite our simplified function
963     // into the following:
964     //
965     //     (n + to - 1) >> log2(to) << log2(to)
966     //
967     // But shifting a value right by some number of bits `b` and then shifting
968     // it left by that same number of bits `b` is equivalent to clearing the
969     // bottom `b` bits of the number. We can clear the bottom `b` bits of a
970     // number by bit-wise and'ing the number with the bit-wise not of `2^b - 1`.
971     // Plugging this into our function and simplifying, we get:
972     //
973     //       (n + to - 1) >> log2(to) << log2(to)
974     //     = (n + to - 1) & !(2^log2(to) - 1)
975     //     = (n + to - 1) & !(to - 1)
976     //
977     // And now we have the final version of this function!
978 
979     (n + to - 1) & !(to - 1)
980 }
981 
982 /// Assign stack slots to incoming function parameters on the stack.
983 ///
984 /// Values that are passed into the function on the stack must be assigned to an `IncomingArg`
985 /// stack slot already during legalization.
spill_entry_params(func: &mut Function, entry: Block)986 fn spill_entry_params(func: &mut Function, entry: Block) {
987     for (abi, &arg) in func
988         .signature
989         .params
990         .iter()
991         .zip(func.dfg.block_params(entry))
992     {
993         if let ArgumentLoc::Stack(offset) = abi.location {
994             let ss = func.stack_slots.make_incoming_arg(abi.value_type, offset);
995             func.locations[arg] = ValueLoc::Stack(ss);
996         }
997     }
998 }
999 
1000 /// Assign stack slots to outgoing function arguments on the stack.
1001 ///
1002 /// Values that are passed to a called function on the stack must be assigned to a matching
1003 /// `OutgoingArg` stack slot. The assignment must happen immediately before the call.
1004 ///
1005 /// TODO: The outgoing stack slots can be written a bit earlier, as long as there are no branches
1006 /// or calls between writing the stack slots and the call instruction. Writing the slots earlier
1007 /// could help reduce register pressure before the call.
spill_call_arguments(pos: &mut FuncCursor) -> bool1008 fn spill_call_arguments(pos: &mut FuncCursor) -> bool {
1009     let inst = pos
1010         .current_inst()
1011         .expect("Cursor must point to a call instruction");
1012     let sig_ref = pos
1013         .func
1014         .dfg
1015         .call_signature(inst)
1016         .expect("Call instruction expected.");
1017 
1018     // Start by building a list of stack slots and arguments to be replaced.
1019     // This requires borrowing `pos.func.dfg`, so we can't change anything.
1020     let arglist = {
1021         let locations = &pos.func.locations;
1022         let stack_slots = &mut pos.func.stack_slots;
1023         pos.func
1024             .dfg
1025             .inst_variable_args(inst)
1026             .iter()
1027             .zip(&pos.func.dfg.signatures[sig_ref].params)
1028             .enumerate()
1029             .filter_map(|(idx, (&arg, abi))| {
1030                 match abi.location {
1031                     ArgumentLoc::Stack(offset) => {
1032                         // Assign `arg` to a new stack slot, unless it's already in the correct
1033                         // slot. The legalization needs to be idempotent, so we should see a
1034                         // correct outgoing slot on the second pass.
1035                         let ss = stack_slots.get_outgoing_arg(abi.value_type, offset);
1036                         if locations[arg] != ValueLoc::Stack(ss) {
1037                             Some((idx, arg, ss))
1038                         } else {
1039                             None
1040                         }
1041                     }
1042                     _ => None,
1043                 }
1044             })
1045             .collect::<Vec<_>>()
1046     };
1047 
1048     if arglist.is_empty() {
1049         return false;
1050     }
1051 
1052     // Insert the spill instructions and rewrite call arguments.
1053     for (idx, arg, ss) in arglist {
1054         let stack_val = pos.ins().spill(arg);
1055         pos.func.locations[stack_val] = ValueLoc::Stack(ss);
1056         pos.func.dfg.inst_variable_args_mut(inst)[idx] = stack_val;
1057     }
1058 
1059     // We changed stuff.
1060     true
1061 }
1062 
1063 #[cfg(test)]
1064 mod tests {
1065     use super::round_up_to_multiple_of_pow2;
1066 
1067     #[test]
round_up_to_multiple_of_pow2_works()1068     fn round_up_to_multiple_of_pow2_works() {
1069         for (n, to, expected) in vec![
1070             (0, 1, 0),
1071             (1, 1, 1),
1072             (2, 1, 2),
1073             (0, 2, 0),
1074             (1, 2, 2),
1075             (2, 2, 2),
1076             (3, 2, 4),
1077             (0, 4, 0),
1078             (1, 4, 4),
1079             (2, 4, 4),
1080             (3, 4, 4),
1081             (4, 4, 4),
1082             (5, 4, 8),
1083         ] {
1084             let actual = round_up_to_multiple_of_pow2(n, to);
1085             assert_eq!(
1086                 actual, expected,
1087                 "round_up_to_multiple_of_pow2(n = {}, to = {}) = {} (expected {})",
1088                 n, to, actual, expected
1089             );
1090         }
1091     }
1092 }
1093