mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 11:12:43 +00:00
Rollup merge of #120982 - momvart:smir-61-foreign_kind, r=oli-obk
Add APIs for fetching foreign items Closes https://github.com/rust-lang/project-stable-mir/issues/61
This commit is contained in:
commit
71466ca804
@ -4588,6 +4588,7 @@ dependencies = [
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"scoped-tls",
|
||||
|
@ -9,6 +9,7 @@ rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
scoped-tls = "1.0"
|
||||
|
@ -85,6 +85,10 @@ impl<'tcx> Tables<'tcx> {
|
||||
stable_mir::ty::AdtDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn foreign_module_def(&mut self, did: DefId) -> stable_mir::ty::ForeignModuleDef {
|
||||
stable_mir::ty::ForeignModuleDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef {
|
||||
stable_mir::ty::ForeignDef(self.create_def_id(did))
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||
use stable_mir::mir::Body;
|
||||
use stable_mir::target::{MachineInfo, MachineSize};
|
||||
use stable_mir::ty::{
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs,
|
||||
LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, VariantDef,
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
||||
ForeignItemKind, GenericArgs, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, VariantDef,
|
||||
};
|
||||
use stable_mir::{Crate, 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::iter;
|
||||
|
||||
@ -67,6 +67,39 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||
tables.tcx.is_mir_available(def_id)
|
||||
}
|
||||
|
||||
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let tcx = tables.tcx;
|
||||
tcx.foreign_modules(crate_num.internal(&mut *tables, tcx))
|
||||
.keys()
|
||||
.map(|mod_def_id| tables.foreign_module_def(*mod_def_id))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn foreign_module(
|
||||
&self,
|
||||
mod_def: stable_mir::ty::ForeignModuleDef,
|
||||
) -> stable_mir::ty::ForeignModule {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[mod_def.def_id()];
|
||||
let mod_def = tables.tcx.foreign_modules(def_id.krate).get(&def_id).unwrap();
|
||||
mod_def.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<ForeignDef> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[mod_def.def_id()];
|
||||
tables
|
||||
.tcx
|
||||
.foreign_modules(def_id.krate)
|
||||
.get(&def_id)
|
||||
.unwrap()
|
||||
.foreign_items
|
||||
.iter()
|
||||
.map(|item_def| tables.foreign_def(*item_def))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn all_trait_decls(&self) -> stable_mir::TraitDecls {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect()
|
||||
@ -225,6 +258,21 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||
tables.tcx.is_foreign_item(tables[item])
|
||||
}
|
||||
|
||||
fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[def.def_id()];
|
||||
let tcx = tables.tcx;
|
||||
use rustc_hir::def::DefKind;
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)),
|
||||
DefKind::Static(..) => ForeignItemKind::Static(tables.static_def(def_id)),
|
||||
DefKind::ForeignTy => ForeignItemKind::Type(
|
||||
tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)),
|
||||
),
|
||||
def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind),
|
||||
}
|
||||
}
|
||||
|
||||
fn adt_kind(&self, def: AdtDef) -> AdtKind {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let tcx = tables.tcx;
|
||||
|
@ -202,41 +202,13 @@ where
|
||||
impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
|
||||
type T = stable_mir::ty::FnSig;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
use rustc_target::spec::abi;
|
||||
use stable_mir::ty::{Abi, FnSig};
|
||||
use stable_mir::ty::FnSig;
|
||||
|
||||
FnSig {
|
||||
inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(),
|
||||
c_variadic: self.c_variadic,
|
||||
unsafety: self.unsafety.stable(tables),
|
||||
abi: match self.abi {
|
||||
abi::Abi::Rust => Abi::Rust,
|
||||
abi::Abi::C { unwind } => Abi::C { unwind },
|
||||
abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind },
|
||||
abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind },
|
||||
abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind },
|
||||
abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind },
|
||||
abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind },
|
||||
abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind },
|
||||
abi::Abi::Win64 { unwind } => Abi::Win64 { unwind },
|
||||
abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind },
|
||||
abi::Abi::PtxKernel => Abi::PtxKernel,
|
||||
abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt,
|
||||
abi::Abi::X86Interrupt => Abi::X86Interrupt,
|
||||
abi::Abi::EfiApi => Abi::EfiApi,
|
||||
abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
|
||||
abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
|
||||
abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
|
||||
abi::Abi::Wasm => Abi::Wasm,
|
||||
abi::Abi::System { unwind } => Abi::System { unwind },
|
||||
abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
|
||||
abi::Abi::RustCall => Abi::RustCall,
|
||||
abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
|
||||
abi::Abi::Unadjusted => Abi::Unadjusted,
|
||||
abi::Abi::RustCold => Abi::RustCold,
|
||||
abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM,
|
||||
abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS,
|
||||
},
|
||||
abi: self.abi.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -832,3 +804,51 @@ impl<'tcx> Stable<'tcx> for ty::Movability {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_target::spec::abi::Abi {
|
||||
type T = stable_mir::ty::Abi;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
use rustc_target::spec::abi;
|
||||
use stable_mir::ty::Abi;
|
||||
match *self {
|
||||
abi::Abi::Rust => Abi::Rust,
|
||||
abi::Abi::C { unwind } => Abi::C { unwind },
|
||||
abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind },
|
||||
abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind },
|
||||
abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind },
|
||||
abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind },
|
||||
abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind },
|
||||
abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind },
|
||||
abi::Abi::Win64 { unwind } => Abi::Win64 { unwind },
|
||||
abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind },
|
||||
abi::Abi::PtxKernel => Abi::PtxKernel,
|
||||
abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt,
|
||||
abi::Abi::X86Interrupt => Abi::X86Interrupt,
|
||||
abi::Abi::EfiApi => Abi::EfiApi,
|
||||
abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
|
||||
abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
|
||||
abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
|
||||
abi::Abi::Wasm => Abi::Wasm,
|
||||
abi::Abi::System { unwind } => Abi::System { unwind },
|
||||
abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
|
||||
abi::Abi::RustCall => Abi::RustCall,
|
||||
abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
|
||||
abi::Abi::Unadjusted => Abi::Unadjusted,
|
||||
abi::Abi::RustCold => Abi::RustCold,
|
||||
abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM,
|
||||
abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule {
|
||||
type T = stable_mir::ty::ForeignModule;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
stable_mir::ty::ForeignModule {
|
||||
def_id: tables.foreign_module_def(self.def_id),
|
||||
abi: self.abi.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@ use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
||||
use crate::mir::Body;
|
||||
use crate::target::MachineInfo;
|
||||
use crate::ty::{
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs,
|
||||
GenericPredicates, Generics, ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl,
|
||||
TraitDef, Ty, TyKind, VariantDef,
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
||||
ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
|
||||
ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyKind,
|
||||
VariantDef,
|
||||
};
|
||||
use crate::{
|
||||
mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind,
|
||||
@ -31,6 +32,9 @@ pub trait Context {
|
||||
fn mir_body(&self, item: DefId) -> mir::Body;
|
||||
/// Check whether the body of a function is available.
|
||||
fn has_body(&self, item: DefId) -> bool;
|
||||
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>;
|
||||
fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule;
|
||||
fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>;
|
||||
fn all_trait_decls(&self) -> TraitDecls;
|
||||
fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls;
|
||||
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
|
||||
@ -66,6 +70,9 @@ pub trait Context {
|
||||
/// Returns whether this is a foreign item.
|
||||
fn is_foreign_item(&self, item: DefId) -> bool;
|
||||
|
||||
/// Returns the kind of a given foreign item.
|
||||
fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind;
|
||||
|
||||
/// Returns the kind of a given algebraic data type
|
||||
fn adt_kind(&self, def: AdtDef) -> AdtKind;
|
||||
|
||||
|
@ -30,7 +30,7 @@ pub use crate::error::*;
|
||||
use crate::mir::pretty::function_name;
|
||||
use crate::mir::Body;
|
||||
use crate::mir::Mutability;
|
||||
use crate::ty::{ImplDef, IndexedVal, Span, TraitDef, Ty};
|
||||
use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
|
||||
|
||||
pub mod abi;
|
||||
#[macro_use]
|
||||
@ -86,6 +86,11 @@ pub struct Crate {
|
||||
}
|
||||
|
||||
impl Crate {
|
||||
/// The list of foreign modules in this crate.
|
||||
pub fn foreign_modules(&self) -> Vec<ForeignModuleDef> {
|
||||
with(|cx| cx.foreign_modules(self.id))
|
||||
}
|
||||
|
||||
/// The list of traits declared in this crate.
|
||||
pub fn trait_decls(&self) -> TraitDecls {
|
||||
with(|cx| cx.trait_decls(self.id))
|
||||
|
@ -4,9 +4,9 @@ use super::{
|
||||
with, DefId, Error, Symbol,
|
||||
};
|
||||
use crate::abi::Layout;
|
||||
use crate::crate_def::CrateDef;
|
||||
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
|
||||
use crate::target::MachineInfo;
|
||||
use crate::{crate_def::CrateDef, mir::mono::StaticDef};
|
||||
use crate::{Filename, Opaque};
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use std::ops::Range;
|
||||
@ -539,11 +539,45 @@ pub enum Movability {
|
||||
Movable,
|
||||
}
|
||||
|
||||
crate_def! {
|
||||
pub ForeignModuleDef;
|
||||
}
|
||||
|
||||
impl ForeignModuleDef {
|
||||
pub fn module(&self) -> ForeignModule {
|
||||
with(|cx| cx.foreign_module(*self))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ForeignModule {
|
||||
pub def_id: ForeignModuleDef,
|
||||
pub abi: Abi,
|
||||
}
|
||||
|
||||
impl ForeignModule {
|
||||
pub fn items(&self) -> Vec<ForeignDef> {
|
||||
with(|cx| cx.foreign_items(self.def_id))
|
||||
}
|
||||
}
|
||||
|
||||
crate_def! {
|
||||
/// Hold information about a ForeignItem in a crate.
|
||||
pub ForeignDef;
|
||||
}
|
||||
|
||||
impl ForeignDef {
|
||||
pub fn kind(&self) -> ForeignItemKind {
|
||||
with(|cx| cx.foreign_item_kind(*self))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum ForeignItemKind {
|
||||
Fn(FnDef),
|
||||
Static(StaticDef),
|
||||
Type(Ty),
|
||||
}
|
||||
|
||||
crate_def! {
|
||||
/// Hold information about a function definition in a crate.
|
||||
pub FnDef;
|
||||
|
93
tests/ui-fulldeps/stable-mir/check_foreign.rs
Normal file
93
tests/ui-fulldeps/stable-mir/check_foreign.rs
Normal file
@ -0,0 +1,93 @@
|
||||
// run-pass
|
||||
//! Test retrieval and kinds of foreign items.
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-cross-compile
|
||||
// ignore-remote
|
||||
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
// edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(control_flow_enum)]
|
||||
|
||||
extern crate rustc_middle;
|
||||
#[macro_use]
|
||||
extern crate rustc_smir;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_interface;
|
||||
extern crate rustc_span;
|
||||
extern crate stable_mir;
|
||||
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::{
|
||||
ty::{Abi, ForeignItemKind},
|
||||
*,
|
||||
};
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
const CRATE_NAME: &str = "input";
|
||||
|
||||
/// This function uses the Stable MIR APIs to get information about the test crate.
|
||||
fn test_foreign() -> ControlFlow<()> {
|
||||
let mods =
|
||||
local_crate().foreign_modules().into_iter().map(|def| def.module()).collect::<Vec<_>>();
|
||||
assert_eq!(mods.len(), 2);
|
||||
|
||||
let rust_mod = mods.iter().find(|m| matches!(m.abi, Abi::Rust)).unwrap();
|
||||
assert_eq!(rust_mod.items().len(), 1);
|
||||
|
||||
let c_mod = mods.iter().find(|m| matches!(m.abi, Abi::C { .. })).unwrap();
|
||||
let c_items = c_mod.items();
|
||||
assert_eq!(c_items.len(), 3);
|
||||
for item in c_items {
|
||||
let kind = item.kind();
|
||||
match item.name().as_str() {
|
||||
"foo" => assert_matches!(kind, ForeignItemKind::Fn(..)),
|
||||
"bar" => assert_matches!(kind, ForeignItemKind::Static(..)),
|
||||
"Baz" => assert_matches!(kind, ForeignItemKind::Type(..)),
|
||||
name => unreachable!("Unexpected item {name}"),
|
||||
};
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||
/// For that, it will first write the dummy crate into a file.
|
||||
/// Then it will create a `StableMir` using custom arguments and then
|
||||
/// it will run the compiler.
|
||||
fn main() {
|
||||
let path = "foreign_input.rs";
|
||||
generate_input(&path).unwrap();
|
||||
let args = vec![
|
||||
"rustc".to_string(),
|
||||
"-Cpanic=abort".to_string(),
|
||||
"--crate-type=lib".to_string(),
|
||||
"--crate-name".to_string(),
|
||||
CRATE_NAME.to_string(),
|
||||
path.to_string(),
|
||||
];
|
||||
run!(args, || test_foreign()).unwrap();
|
||||
}
|
||||
|
||||
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||
let mut file = std::fs::File::create(path)?;
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
#![feature(extern_types)]
|
||||
#![allow(unused)]
|
||||
extern "Rust" {{
|
||||
fn rust_foo(x: i32) -> i32;
|
||||
}}
|
||||
extern "C" {{
|
||||
fn foo(x: i32) -> i32;
|
||||
static bar: i32;
|
||||
type Baz;
|
||||
}}
|
||||
"#
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user