about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-02-15 09:20:18 +0100
committerGitHub <noreply@github.com>2024-02-15 09:20:18 +0100
commit71466ca804d2c6c67824d0c80b9f20db3ab29af2 (patch)
tree5395feedc396cb60aaf1563cba360664a26562ba
parent09776009eaa0ea4eeabd4d5ee4f76981a16b48ea (diff)
parent2e691a5c12f4d96da6938f26cbf3de7d404edc87 (diff)
downloadrust-71466ca804d2c6c67824d0c80b9f20db3ab29af2.tar.gz
rust-71466ca804d2c6c67824d0c80b9f20db3ab29af2.zip
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
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_smir/Cargo.toml1
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs54
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs80
-rw-r--r--compiler/stable_mir/src/compiler_interface.rs13
-rw-r--r--compiler/stable_mir/src/lib.rs7
-rw-r--r--compiler/stable_mir/src/ty.rs36
-rw-r--r--tests/ui-fulldeps/stable-mir/check_foreign.rs93
9 files changed, 251 insertions, 38 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6f9248f140c..f9ad78e3795 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4588,6 +4588,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_middle",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "scoped-tls",
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index c9e23efcb10..1e0a60bc371 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -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"
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 43987fcf10f..6bb8c5452b9 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -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))
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 70d7200bf60..b95186b0a1c 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -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;
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 959a17d24b7..29081418200 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -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),
+        }
+    }
+}
diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs
index de045f6b56c..6272f793f40 100644
--- a/compiler/stable_mir/src/compiler_interface.rs
+++ b/compiler/stable_mir/src/compiler_interface.rs
@@ -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;
 
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 4f57f532a40..d849c834ae0 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -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))
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index bdda9295347..658e8aa28b5 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -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;
@@ -540,10 +540,44 @@ pub enum Movability {
 }
 
 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;
diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs
new file mode 100644
index 00000000000..e6c59354d5e
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs
@@ -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(())
+}