Skip to content

Commit

Permalink
Rollup merge of rust-lang#119094 - celinval:smir-layout, r=compiler-e…
Browse files Browse the repository at this point in the history
…rrors

Add function ABI and type layout to StableMIR

This change introduces a new module to StableMIR named `abi` with information from `rustc_target::abi` and `rustc_abi`, that allow users to retrieve more low level information required to perform bit-precise analysis.

The layout of a type can be retrieved via `Ty::layout`, and the instance ABI can be retrieved via `Instance::fn_abi()`.

To properly handle errors while retrieve layout information, we had to implement a few layout related traits.

r? ``@compiler-errors``
  • Loading branch information
compiler-errors committed Dec 19, 2023
2 parents b1a4194 + 76b3e6d commit 277ea59
Show file tree
Hide file tree
Showing 14 changed files with 796 additions and 25 deletions.
9 changes: 9 additions & 0 deletions compiler/rustc_smir/src/rustc_internal/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use crate::rustc_smir::Tables;
use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
use rustc_span::Symbol;
use stable_mir::abi::Layout;
use stable_mir::mir::alloc::AllocId;
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
use stable_mir::mir::{Mutability, Safety};
Expand Down Expand Up @@ -460,6 +461,14 @@ impl<'tcx> RustcInternal<'tcx> for Span {
}
}

impl<'tcx> RustcInternal<'tcx> for Layout {
type T = rustc_target::abi::Layout<'tcx>;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
tables.layouts[*self]
}
}

impl<'tcx, T> RustcInternal<'tcx> for &T
where
T: RustcInternal<'tcx>,
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_smir/src/rustc_internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Span;
use scoped_tls::scoped_thread_local;
use stable_mir::abi::Layout;
use stable_mir::ty::IndexedVal;
use stable_mir::Error;
use std::cell::Cell;
Expand Down Expand Up @@ -136,6 +137,10 @@ impl<'tcx> Tables<'tcx> {
pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef {
stable_mir::mir::mono::StaticDef(self.create_def_id(did))
}

pub(crate) fn layout_id(&mut self, layout: rustc_target::abi::Layout<'tcx>) -> Layout {
self.layouts.create_or_fetch(layout)
}
}

pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
Expand Down Expand Up @@ -180,6 +185,7 @@ where
types: IndexMap::default(),
instances: IndexMap::default(),
constants: IndexMap::default(),
layouts: IndexMap::default(),
}));
stable_mir::compiler_interface::run(&tables, || init(&tables, f))
}
Expand Down
75 changes: 73 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@
//! This trait is currently the main interface between the Rust compiler,
//! and the `stable_mir` crate.

#![allow(rustc::usage_of_qualified_ty)]

use rustc_abi::HasDataLayout;
use rustc_middle::ty;
use rustc_middle::ty::layout::{
FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers,
};
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
use rustc_middle::ty::{
GenericPredicates, Instance, ParamEnv, ScalarInt, TypeVisitableExt, ValTree,
GenericPredicates, Instance, List, ParamEnv, ScalarInt, TyCtxt, TypeVisitableExt, ValTree,
};
use rustc_span::def_id::LOCAL_CRATE;
use stable_mir::abi::{FnAbi, Layout, LayoutShape};
use stable_mir::compiler_interface::Context;
use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::mir::mono::{InstanceDef, StaticDef};
Expand Down Expand Up @@ -280,7 +287,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
}

#[allow(rustc::usage_of_qualified_ty)]
fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let inner = ty.internal(&mut *tables);
Expand Down Expand Up @@ -335,6 +341,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables)
}

fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables))
}

fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
let mut tables = self.0.borrow_mut();
let def_id = tables.instances[def].def_id();
Expand Down Expand Up @@ -473,6 +485,65 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
)
}
}

fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
let mut tables = self.0.borrow_mut();
let ty = ty.internal(&mut *tables);
let layout = tables.layout_of(ty)?.layout;
Ok(layout.stable(&mut *tables))
}

fn layout_shape(&self, id: Layout) -> LayoutShape {
let mut tables = self.0.borrow_mut();
id.internal(&mut *tables).0.stable(&mut *tables)
}
}

pub struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);

/// Implement error handling for extracting function ABI information.
impl<'tcx> FnAbiOfHelpers<'tcx> for Tables<'tcx> {
type FnAbiOfResult = Result<&'tcx rustc_target::abi::call::FnAbi<'tcx, ty::Ty<'tcx>>, Error>;

#[inline]
fn handle_fn_abi_err(
&self,
err: ty::layout::FnAbiError<'tcx>,
_span: rustc_span::Span,
fn_abi_request: ty::layout::FnAbiRequest<'tcx>,
) -> Error {
Error::new(format!("Failed to get ABI for `{fn_abi_request:?}`: {err:?}"))
}
}

impl<'tcx> LayoutOfHelpers<'tcx> for Tables<'tcx> {
type LayoutOfResult = Result<ty::layout::TyAndLayout<'tcx>, Error>;

#[inline]
fn handle_layout_err(
&self,
err: ty::layout::LayoutError<'tcx>,
_span: rustc_span::Span,
ty: ty::Ty<'tcx>,
) -> Error {
Error::new(format!("Failed to get layout for `{ty}`: {err}"))
}
}

impl<'tcx> HasParamEnv<'tcx> for Tables<'tcx> {
fn param_env(&self) -> ty::ParamEnv<'tcx> {
ty::ParamEnv::reveal_all()
}
}

impl<'tcx> HasTyCtxt<'tcx> for Tables<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
}

impl<'tcx> HasDataLayout for Tables<'tcx> {
fn data_layout(&self) -> &rustc_abi::TargetDataLayout {
self.tcx.data_layout()
}
}
Loading

0 comments on commit 277ea59

Please sign in to comment.