Add intrinsic definition and retrieval APIs

This commit is contained in:
Mohammad Omidvar 2024-05-20 18:11:07 +00:00
parent 94be5ab448
commit f0cb386c7d
4 changed files with 68 additions and 16 deletions

View File

@ -23,8 +23,8 @@ use stable_mir::mir::{BinOp, Body, Place};
use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::target::{MachineInfo, MachineSize};
use stable_mir::ty::{ use stable_mir::ty::{
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
ForeignItemKind, GenericArgs, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, UintTy, ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind,
VariantDef, UintTy, VariantDef,
}; };
use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol};
use std::cell::RefCell; use std::cell::RefCell;
@ -307,6 +307,28 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
sig.stable(&mut *tables) sig.stable(&mut *tables)
} }
fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.internal(&mut *tables, tcx);
let intrinsic = tcx.intrinsic_raw(def_id);
intrinsic.map(|_| IntrinsicDef(def))
}
fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.0.internal(&mut *tables, tcx);
tcx.intrinsic(def_id).unwrap().name.to_string()
}
fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.0.internal(&mut *tables, tcx);
tcx.intrinsic_raw(def_id).unwrap().must_be_overridden
}
fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
let mut tables = self.0.borrow_mut(); let mut tables = self.0.borrow_mut();
let tcx = tables.tcx; let tcx = tables.tcx;
@ -645,16 +667,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
} }
} }
/// Retrieve the plain intrinsic name of an instance.
///
/// This assumes that the instance is an intrinsic.
fn intrinsic_name(&self, def: InstanceDef) -> Symbol {
let tables = self.0.borrow_mut();
let instance = tables.instances[def];
let intrinsic = tables.tcx.intrinsic(instance.def_id()).unwrap();
intrinsic.name.to_string()
}
fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> { fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
let mut tables = self.0.borrow_mut(); let mut tables = self.0.borrow_mut();
let tcx = tables.tcx; let tcx = tables.tcx;

View File

@ -13,8 +13,8 @@ use crate::target::MachineInfo;
use crate::ty::{ use crate::ty::{
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyKind, ImplDef, ImplTrait, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty,
UintTy, VariantDef, TyKind, UintTy, VariantDef,
}; };
use crate::{ use crate::{
mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind,
@ -88,6 +88,16 @@ pub trait Context {
/// Retrieve the function signature for the given generic arguments. /// Retrieve the function signature for the given generic arguments.
fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig; fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig;
/// Retrieve the intrinsic definition if the item corresponds one.
fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef>;
/// Retrieve the plain function name of an intrinsic.
fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol;
/// Returns whether the intrinsic has no meaningful body and all backends
/// need to shim all calls to it.
fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool;
/// Retrieve the closure signature for the given generic arguments. /// Retrieve the closure signature for the given generic arguments.
fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig; fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig;
@ -198,7 +208,6 @@ pub trait Context {
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>; fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
fn krate(&self, def_id: DefId) -> Crate; fn krate(&self, def_id: DefId) -> Crate;
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
fn intrinsic_name(&self, def: InstanceDef) -> Symbol;
/// Return information about the target machine. /// Return information about the target machine.
fn target_info(&self) -> MachineInfo; fn target_info(&self) -> MachineInfo;

View File

@ -106,7 +106,9 @@ impl Instance {
/// which is more convenient to match with intrinsic symbols. /// which is more convenient to match with intrinsic symbols.
pub fn intrinsic_name(&self) -> Option<Symbol> { pub fn intrinsic_name(&self) -> Option<Symbol> {
match self.kind { match self.kind {
InstanceKind::Intrinsic => Some(with(|context| context.intrinsic_name(self.def))), InstanceKind::Intrinsic => {
Some(with(|context| context.intrinsic(self.def.def_id()).unwrap().fn_name()))
}
InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None, InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None,
} }
} }

View File

@ -622,6 +622,35 @@ impl FnDef {
pub fn body(&self) -> Option<Body> { pub fn body(&self) -> Option<Body> {
with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0))) with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0)))
} }
/// Get the information of the intrinsic if this function is a definition of one.
pub fn as_intrinsic(&self) -> Option<IntrinsicDef> {
with(|cx| cx.intrinsic(self.def_id()))
}
/// Check if the function is an intrinsic.
#[inline]
pub fn is_intrinsic(&self) -> bool {
self.as_intrinsic().is_some()
}
}
crate_def! {
pub IntrinsicDef;
}
impl IntrinsicDef {
/// Returns the plain name of the intrinsic.
/// e.g., `transmute` for `core::intrinsics::transmute`.
pub fn fn_name(&self) -> Symbol {
with(|cx| cx.intrinsic_name(*self))
}
/// Returns whether the intrinsic has no meaningful body and all backends
/// need to shim all calls to it.
pub fn must_be_overridden(&self) -> bool {
with(|cx| cx.intrinsic_must_be_overridden(*self))
}
} }
crate_def! { crate_def! {