Add 'compiler/rustc_codegen_cranelift/' from commit '793d26047f
'
git-subtree-dir: compiler/rustc_codegen_cranelift git-subtree-mainline:cf798c1ec6
git-subtree-split:793d26047f
This commit is contained in:
commit
ac4f7deb2f
86 changed files with 16617 additions and 0 deletions
206
compiler/rustc_codegen_cranelift/src/pointer.rs
Normal file
206
compiler/rustc_codegen_cranelift/src/pointer.rs
Normal file
|
@ -0,0 +1,206 @@
|
|||
//! Defines [`Pointer`] which is used to improve the quality of the generated clif ir for pointer
|
||||
//! operations.
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use rustc_target::abi::Align;
|
||||
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
|
||||
/// A pointer pointing either to a certain address, a certain stack slot or nothing.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct Pointer {
|
||||
base: PointerBase,
|
||||
offset: Offset32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) enum PointerBase {
|
||||
Addr(Value),
|
||||
Stack(StackSlot),
|
||||
Dangling(Align),
|
||||
}
|
||||
|
||||
impl Pointer {
|
||||
pub(crate) fn new(addr: Value) -> Self {
|
||||
Pointer {
|
||||
base: PointerBase::Addr(addr),
|
||||
offset: Offset32::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn stack_slot(stack_slot: StackSlot) -> Self {
|
||||
Pointer {
|
||||
base: PointerBase::Stack(stack_slot),
|
||||
offset: Offset32::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn const_addr<'a, 'tcx>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Module>,
|
||||
addr: i64,
|
||||
) -> Self {
|
||||
let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
|
||||
Pointer {
|
||||
base: PointerBase::Addr(addr),
|
||||
offset: Offset32::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dangling(align: Align) -> Self {
|
||||
Pointer {
|
||||
base: PointerBase::Dangling(align),
|
||||
offset: Offset32::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub(crate) fn base_and_offset(self) -> (PointerBase, Offset32) {
|
||||
(self.base, self.offset)
|
||||
}
|
||||
|
||||
pub(crate) fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Module>) -> Value {
|
||||
match self.base {
|
||||
PointerBase::Addr(base_addr) => {
|
||||
let offset: i64 = self.offset.into();
|
||||
if offset == 0 {
|
||||
base_addr
|
||||
} else {
|
||||
fx.bcx.ins().iadd_imm(base_addr, offset)
|
||||
}
|
||||
}
|
||||
PointerBase::Stack(stack_slot) => {
|
||||
fx.bcx
|
||||
.ins()
|
||||
.stack_addr(fx.pointer_type, stack_slot, self.offset)
|
||||
}
|
||||
PointerBase::Dangling(align) => fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn offset<'a, 'tcx>(
|
||||
self,
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Module>,
|
||||
extra_offset: Offset32,
|
||||
) -> Self {
|
||||
self.offset_i64(fx, extra_offset.into())
|
||||
}
|
||||
|
||||
pub(crate) fn offset_i64<'a, 'tcx>(
|
||||
self,
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Module>,
|
||||
extra_offset: i64,
|
||||
) -> Self {
|
||||
if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
|
||||
Pointer {
|
||||
base: self.base,
|
||||
offset: new_offset,
|
||||
}
|
||||
} else {
|
||||
let base_offset: i64 = self.offset.into();
|
||||
if let Some(new_offset) = base_offset.checked_add(extra_offset) {
|
||||
let base_addr = match self.base {
|
||||
PointerBase::Addr(addr) => addr,
|
||||
PointerBase::Stack(stack_slot) => {
|
||||
fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)
|
||||
}
|
||||
PointerBase::Dangling(align) => fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap()),
|
||||
};
|
||||
let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
|
||||
Pointer {
|
||||
base: PointerBase::Addr(addr),
|
||||
offset: Offset32::new(0),
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"self.offset ({}) + extra_offset ({}) not representable in i64",
|
||||
base_offset, extra_offset
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn offset_value<'a, 'tcx>(
|
||||
self,
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Module>,
|
||||
extra_offset: Value,
|
||||
) -> Self {
|
||||
match self.base {
|
||||
PointerBase::Addr(addr) => Pointer {
|
||||
base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
|
||||
offset: self.offset,
|
||||
},
|
||||
PointerBase::Stack(stack_slot) => {
|
||||
let base_addr = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.stack_addr(fx.pointer_type, stack_slot, self.offset);
|
||||
Pointer {
|
||||
base: PointerBase::Addr(fx.bcx.ins().iadd(base_addr, extra_offset)),
|
||||
offset: Offset32::new(0),
|
||||
}
|
||||
}
|
||||
PointerBase::Dangling(align) => {
|
||||
let addr = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap());
|
||||
Pointer {
|
||||
base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
|
||||
offset: self.offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load<'a, 'tcx>(
|
||||
self,
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Module>,
|
||||
ty: Type,
|
||||
flags: MemFlags,
|
||||
) -> Value {
|
||||
match self.base {
|
||||
PointerBase::Addr(base_addr) => fx.bcx.ins().load(ty, flags, base_addr, self.offset),
|
||||
PointerBase::Stack(stack_slot) => {
|
||||
if ty == types::I128 || ty.is_vector() {
|
||||
// WORKAROUND for stack_load.i128 and stack_load.iXxY not being implemented
|
||||
let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
|
||||
fx.bcx.ins().load(ty, flags, base_addr, self.offset)
|
||||
} else {
|
||||
fx.bcx.ins().stack_load(ty, stack_slot, self.offset)
|
||||
}
|
||||
}
|
||||
PointerBase::Dangling(_align) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn store<'a, 'tcx>(
|
||||
self,
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Module>,
|
||||
value: Value,
|
||||
flags: MemFlags,
|
||||
) {
|
||||
match self.base {
|
||||
PointerBase::Addr(base_addr) => {
|
||||
fx.bcx.ins().store(flags, value, base_addr, self.offset);
|
||||
}
|
||||
PointerBase::Stack(stack_slot) => {
|
||||
let val_ty = fx.bcx.func.dfg.value_type(value);
|
||||
if val_ty == types::I128 || val_ty.is_vector() {
|
||||
// WORKAROUND for stack_store.i128 and stack_store.iXxY not being implemented
|
||||
let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
|
||||
fx.bcx.ins().store(flags, value, base_addr, self.offset);
|
||||
} else {
|
||||
fx.bcx.ins().stack_store(value, stack_slot, self.offset);
|
||||
}
|
||||
}
|
||||
PointerBase::Dangling(_align) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue