Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions winch/codegen/src/abi/addressing_mode.rs

This file was deleted.

2 changes: 0 additions & 2 deletions winch/codegen/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use smallvec::SmallVec;
use std::ops::{Add, BitAnd, Not, Sub};
use wasmparser::{FuncType, ValType};

pub(crate) mod addressing_mode;
pub(crate) use addressing_mode::*;
pub(crate) mod local;
pub(crate) use local::*;

Expand Down
144 changes: 144 additions & 0 deletions winch/codegen/src/isa/aarch64/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//! Aarch64 addressing mode.

use anyhow::{anyhow, Context, Result};
use cranelift_codegen::{
ir::types,
isa::aarch64::inst::{AMode, PairAMode, SImm7Scaled, SImm9},
};

use super::regs;
use crate::reg::Reg;

/// Aarch64 indexing mode.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum Indexing {
/// Pre-indexed.
Pre,
/// Post-indexed.
Post,
}

/// Memory address representation.
#[derive(Debug, Copy, Clone)]
pub(crate) enum Address {
/// Base register with an arbitrary offset. Potentially gets
/// lowered into multiple instructions during code emission
/// depending on the offset.
Offset {
/// Base register.
base: Reg,
/// Offset.
offset: i64,
},
/// Specialized indexed register and offset variant using
/// the stack pointer.
IndexedSPOffset {
/// Offset.
offset: i64,
/// Indexing mode.
indexing: Indexing,
},
}

impl Address {
/// Create a pre-indexed addressing mode from the stack pointer.
pub fn pre_indexed_from_sp(offset: i64) -> Self {
Self::IndexedSPOffset {
offset,
indexing: Indexing::Pre,
}
}

/// Create a post-indexed addressing mode from the stack pointer.
pub fn post_indexed_from_sp(offset: i64) -> Self {
Self::IndexedSPOffset {
offset,
indexing: Indexing::Post,
}
}

/// Create an offset addressing mode with
/// the shadow stack pointer register
/// as a base.
pub fn from_shadow_sp(offset: i64) -> Self {
Self::Offset {
base: regs::shadow_sp(),
offset,
}
}

/// Create register and arbitrary offset addressing mode.
pub fn offset(base: Reg, offset: i64) -> Self {
// This exists to enforce the sp vs shadow_sp invariant, the
// sp generally should not be used as a base register in an
// address. In the cases where its usage is required and where
// we are sure that it's 16-byte aligned, the address should
// be constructed via the `Self::pre_indexed_sp` and
// Self::post_indexed_sp functions.
// For more details around the stack pointer and shadow stack
// pointer see the docs at regs::shadow_sp().
assert!(
base != regs::sp(),
"stack pointer not allowed in arbitrary offset addressing mode"
);
Self::Offset { base, offset }
}
}

// Conversions between `winch-codegen`'s addressing mode representation
// and `cranelift-codegen`s addressing mode representation for aarch64.

impl TryFrom<Address> for PairAMode {
type Error = anyhow::Error;

fn try_from(addr: Address) -> Result<Self> {
use Address::*;
use Indexing::*;

match addr {
IndexedSPOffset { offset, indexing } => {
let simm7 = SImm7Scaled::maybe_from_i64(offset, types::I64).with_context(|| {
format!("Failed to convert {} to signed scaled 7 bit offset", offset)
})?;

if indexing == Pre {
Ok(PairAMode::SPPreIndexed(simm7))
} else {
Ok(PairAMode::SPPostIndexed(simm7))
}
}
other => Err(anyhow!(
"Could not convert {:?} to addressing mode for register pairs",
other
)),
}
}
}

impl TryFrom<Address> for AMode {
type Error = anyhow::Error;

fn try_from(addr: Address) -> Result<Self> {
use Address::*;
use Indexing::*;

match addr {
IndexedSPOffset { offset, indexing } => {
let simm9 = SImm9::maybe_from_i64(offset).ok_or_else(|| {
anyhow!("Failed to convert {} to signed 9-bit offset", offset)
})?;

if indexing == Pre {
Ok(AMode::SPPreIndexed { simm9 })
} else {
Ok(AMode::SPPostIndexed { simm9 })
}
}
Offset { base, offset } => Ok(AMode::RegOffset {
rn: base.into(),
off: offset,
ty: types::I64,
}),
}
}
}
Loading