winch: Add support for the <i32|i64>.div_* instructions (#5807)
* Refactor the structure and responsibilities of `CodeGenContext` This commit refactors how the `CodeGenContext` is used throughout the code generation process, making it easier to pass it around when more flexibility is desired in the MacroAssembler to perform the lowering of certain instructions. As of this change, the responsibility of the `CodeGenContext` is to provide an interface for operations that require an orchestration between the register allocator, the value stack and function's frame. The MacroAssembler is removed from the CodeGenContext as is passed as a dependency where needed, effectly using it as an independent code generation interface only. By giving more responsibilities to the `CodeGenContext` we can clearly separate the concerns of the register allocator, which previously did more than it should (e.g. popping values and spilling). This change ultimately allows passing in the `CodeGenContext` to the `MacroAssembler` when a given instruction cannot be generically described through a common interface. Allowing each implementation to decide the best way to lower a particular instruction. * winch: Add support for the WebAssembly `<i32|i64>.div_*` instructions Given that some architectures have very specific requirements on how to handle division, this change uses `CodeGenContext` as a dependency to the `div` MacroAssembler instruction to ensure that each implementation can decide on how to lower the division. This approach also allows -- in architectures where division can be expressed as an ordinary binary operation -- to rely on the `CodeGenContext::i32_binop` or `CodeGenContext::i64_binop` helpers.
This commit is contained in:
@@ -1,9 +1,18 @@
|
||||
use crate::abi::{align_to, LocalSlot};
|
||||
use crate::codegen::CodeGenContext;
|
||||
use crate::isa::reg::Reg;
|
||||
use crate::regalloc::RegAlloc;
|
||||
use cranelift_codegen::{Final, MachBufferFinalized};
|
||||
use std::{fmt::Debug, ops::Range};
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub(crate) enum DivKind {
|
||||
/// Signed division.
|
||||
Signed,
|
||||
/// Unsigned division.
|
||||
Unsigned,
|
||||
}
|
||||
|
||||
/// Operand size, in bits.
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub(crate) enum OperandSize {
|
||||
@@ -94,6 +103,19 @@ pub(crate) trait MacroAssembler {
|
||||
/// Perform multiplication operation.
|
||||
fn mul(&mut self, dst: RegImm, lhs: RegImm, rhs: RegImm, size: OperandSize);
|
||||
|
||||
/// Perform division operation.
|
||||
/// Division is special in that some architectures have specific
|
||||
/// expectations regarding the location of the instruction
|
||||
/// arguments and regarding the location of the quotient /
|
||||
/// remainder. To free the caller from having to deal with the
|
||||
/// architecure specific contraints we give this function access
|
||||
/// to the code generation context, allowing each implementation
|
||||
/// to decide the lowering path. For cases in which division is a
|
||||
/// unconstrained binary operation, the caller can decide to use
|
||||
/// the `CodeGenContext::i32_binop` or `CodeGenContext::i64_binop`
|
||||
/// functions.
|
||||
fn div(&mut self, context: &mut CodeGenContext, kind: DivKind, size: OperandSize);
|
||||
|
||||
/// Push the register to the stack, returning the offset.
|
||||
fn push(&mut self, src: Reg) -> u32;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user