summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_smir
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /compiler/rustc_smir
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_smir')
-rw-r--r--compiler/rustc_smir/Cargo.toml19
-rw-r--r--compiler/rustc_smir/README.md37
-rw-r--r--compiler/rustc_smir/rust-toolchain.toml2
-rw-r--r--compiler/rustc_smir/src/lib.rs8
-rw-r--r--compiler/rustc_smir/src/mir.rs10
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs32
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs162
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir.rs3
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs69
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs73
-rw-r--r--compiler/rustc_smir/src/very_unstable.rs27
11 files changed, 384 insertions, 58 deletions
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index 5e0d1f369..fb97ee5be 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -4,25 +4,12 @@ version = "0.0.0"
edition = "2021"
[dependencies]
-rustc_borrowck = { path = "../rustc_borrowck", optional = true }
-rustc_driver = { path = "../rustc_driver", optional = true }
-rustc_hir = { path = "../rustc_hir", optional = true }
-rustc_interface = { path = "../rustc_interface", optional = true }
rustc_middle = { path = "../rustc_middle", optional = true }
-rustc_mir_dataflow = { path = "../rustc_mir_dataflow", optional = true }
-rustc_mir_transform = { path = "../rustc_mir_transform", optional = true }
-rustc_serialize = { path = "../rustc_serialize", optional = true }
-rustc_trait_selection = { path = "../rustc_trait_selection", optional = true }
+rustc_span = { path = "../rustc_span", optional = true }
+tracing = "0.1"
[features]
default = [
- "rustc_borrowck",
- "rustc_driver",
- "rustc_hir",
- "rustc_interface",
"rustc_middle",
- "rustc_mir_dataflow",
- "rustc_mir_transform",
- "rustc_serialize",
- "rustc_trait_selection",
+ "rustc_span",
]
diff --git a/compiler/rustc_smir/README.md b/compiler/rustc_smir/README.md
index ae49098dd..31dee955f 100644
--- a/compiler/rustc_smir/README.md
+++ b/compiler/rustc_smir/README.md
@@ -73,3 +73,40 @@ git subtree pull --prefix=compiler/rustc_smir https://github.com/rust-lang/proje
Note: only ever sync to rustc from the project-stable-mir's `smir` branch. Do not sync with your own forks.
Then open a PR against rustc just like a regular PR.
+
+## Stable MIR Design
+
+The stable-mir will follow a similar approach to proc-macro2. It’s
+implementation will eventually be broken down into two main crates:
+
+- `stable_mir`: Public crate, to be published on crates.io, which will contain
+the stable data structure as well as proxy APIs to make calls to the
+compiler.
+- `rustc_smir`: The compiler crate that will translate from internal MIR to
+SMIR. This crate will also implement APIs that will be invoked by
+stable-mir to query the compiler for more information.
+
+This will help tools to communicate with the rust compiler via stable APIs. Tools will depend on
+`stable_mir` crate, which will invoke the compiler using APIs defined in `rustc_smir`. I.e.:
+
+```
+ ┌──────────────────────────────────┐ ┌──────────────────────────────────┐
+ │ External Tool ┌──────────┐ │ │ ┌──────────┐ Rust Compiler │
+ │ │ │ │ │ │ │ │
+ │ │stable_mir| │ │ │rustc_smir│ │
+ │ │ │ ├──────────►| │ │ │
+ │ │ │ │◄──────────┤ │ │ │
+ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │
+ │ └──────────┘ │ │ └──────────┘ │
+ └──────────────────────────────────┘ └──────────────────────────────────┘
+```
+
+More details can be found here:
+https://hackmd.io/XhnYHKKuR6-LChhobvlT-g?view
+
+For now, the code for these two crates are in separate modules of this crate.
+The modules have the same name for simplicity. We also have a third module,
+`rustc_internal` which will expose APIs and definitions that allow users to
+gather information from internal MIR constructs that haven't been exposed in
+the `stable_mir` module.
diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml
index 7b696fc1f..157dfd620 100644
--- a/compiler/rustc_smir/rust-toolchain.toml
+++ b/compiler/rustc_smir/rust-toolchain.toml
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-06-01"
+channel = "nightly-2023-02-28"
components = [ "rustfmt", "rustc-dev" ]
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index 3e93c6bba..54d474db0 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -11,9 +11,9 @@
test(attr(allow(unused_variables), deny(warnings)))
)]
#![cfg_attr(not(feature = "default"), feature(rustc_private))]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-pub mod mir;
+pub mod rustc_internal;
+pub mod stable_mir;
-pub mod very_unstable;
+// Make this module private for now since external users should not call these directly.
+mod rustc_smir;
diff --git a/compiler/rustc_smir/src/mir.rs b/compiler/rustc_smir/src/mir.rs
deleted file mode 100644
index 887e65729..000000000
--- a/compiler/rustc_smir/src/mir.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-pub use crate::very_unstable::hir::ImplicitSelfKind;
-pub use crate::very_unstable::middle::mir::{
- visit::MutVisitor, AggregateKind, AssertKind, BasicBlock, BasicBlockData, BinOp, BindingForm,
- BlockTailInfo, Body, BorrowKind, CastKind, ClearCrossCrate, Constant, ConstantKind,
- CopyNonOverlapping, Coverage, FakeReadCause, Field, GeneratorInfo, InlineAsmOperand, Local,
- LocalDecl, LocalInfo, LocalKind, Location, MirPhase, MirSource, NullOp, Operand, Place,
- PlaceRef, ProjectionElem, ProjectionKind, Promoted, RetagKind, Rvalue, Safety, SourceInfo,
- SourceScope, SourceScopeData, SourceScopeLocalData, Statement, StatementKind, UnOp,
- UserTypeProjection, UserTypeProjections, VarBindingForm, VarDebugInfo, VarDebugInfoContents,
-};
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
new file mode 100644
index 000000000..5998c8b65
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -0,0 +1,32 @@
+//! Module that implements the bridge between Stable MIR and internal compiler MIR.
+//!
+//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
+//! until stable MIR is complete.
+
+use std::sync::RwLock;
+
+use crate::stable_mir;
+pub use rustc_span::def_id::{CrateNum, DefId};
+
+static DEF_ID_MAP: RwLock<Vec<DefId>> = RwLock::new(Vec::new());
+
+pub fn item_def_id(item: &stable_mir::CrateItem) -> DefId {
+ DEF_ID_MAP.read().unwrap()[item.0]
+}
+
+pub fn crate_item(did: DefId) -> stable_mir::CrateItem {
+ // FIXME: this becomes inefficient when we have too many ids
+ let mut map = DEF_ID_MAP.write().unwrap();
+ for (i, &d) in map.iter().enumerate() {
+ if d == did {
+ return stable_mir::CrateItem(i);
+ }
+ }
+ let id = map.len();
+ map.push(did);
+ stable_mir::CrateItem(id)
+}
+
+pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
+ item.id.into()
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
new file mode 100644
index 000000000..4dad3c6bc
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -0,0 +1,162 @@
+//! Module that implements what will become the rustc side of Stable MIR.
+//!
+//! This module is responsible for building Stable MIR components from internal components.
+//!
+//! This module is not intended to be invoked directly by users. It will eventually
+//! become the public API of rustc that will be invoked by the `stable_mir` crate.
+//!
+//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
+
+use crate::{
+ rustc_internal::{crate_item, item_def_id},
+ stable_mir::{self},
+};
+use rustc_middle::ty::{tls::with, TyCtxt};
+use rustc_span::def_id::{CrateNum, LOCAL_CRATE};
+use tracing::debug;
+
+/// Get information about the local crate.
+pub fn local_crate() -> stable_mir::Crate {
+ with(|tcx| smir_crate(tcx, LOCAL_CRATE))
+}
+
+/// Retrieve a list of all external crates.
+pub fn external_crates() -> Vec<stable_mir::Crate> {
+ with(|tcx| tcx.crates(()).iter().map(|crate_num| smir_crate(tcx, *crate_num)).collect())
+}
+
+/// Find a crate with the given name.
+pub fn find_crate(name: &str) -> Option<stable_mir::Crate> {
+ with(|tcx| {
+ [LOCAL_CRATE].iter().chain(tcx.crates(()).iter()).find_map(|crate_num| {
+ let crate_name = tcx.crate_name(*crate_num).to_string();
+ (name == crate_name).then(|| smir_crate(tcx, *crate_num))
+ })
+ })
+}
+
+/// Retrieve all items of the local crate that have a MIR associated with them.
+pub fn all_local_items() -> stable_mir::CrateItems {
+ with(|tcx| tcx.mir_keys(()).iter().map(|item| crate_item(item.to_def_id())).collect())
+}
+
+pub fn entry_fn() -> Option<stable_mir::CrateItem> {
+ with(|tcx| Some(crate_item(tcx.entry_fn(())?.0)))
+}
+
+/// Build a stable mir crate from a given crate number.
+fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
+ let crate_name = tcx.crate_name(crate_num).to_string();
+ let is_local = crate_num == LOCAL_CRATE;
+ debug!(?crate_name, ?crate_num, "smir_crate");
+ stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
+}
+
+pub fn mir_body(item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
+ with(|tcx| {
+ let def_id = item_def_id(item);
+ let mir = tcx.optimized_mir(def_id);
+ stable_mir::mir::Body {
+ blocks: mir
+ .basic_blocks
+ .iter()
+ .map(|block| stable_mir::mir::BasicBlock {
+ terminator: rustc_terminator_to_terminator(block.terminator()),
+ statements: block.statements.iter().map(rustc_statement_to_statement).collect(),
+ })
+ .collect(),
+ }
+ })
+}
+
+fn rustc_statement_to_statement(
+ s: &rustc_middle::mir::Statement<'_>,
+) -> stable_mir::mir::Statement {
+ use rustc_middle::mir::StatementKind::*;
+ match &s.kind {
+ Assign(assign) => stable_mir::mir::Statement::Assign(
+ rustc_place_to_place(&assign.0),
+ rustc_rvalue_to_rvalue(&assign.1),
+ ),
+ FakeRead(_) => todo!(),
+ SetDiscriminant { .. } => todo!(),
+ Deinit(_) => todo!(),
+ StorageLive(_) => todo!(),
+ StorageDead(_) => todo!(),
+ Retag(_, _) => todo!(),
+ PlaceMention(_) => todo!(),
+ AscribeUserType(_, _) => todo!(),
+ Coverage(_) => todo!(),
+ Intrinsic(_) => todo!(),
+ ConstEvalCounter => todo!(),
+ Nop => stable_mir::mir::Statement::Nop,
+ }
+}
+
+fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Operand {
+ use rustc_middle::mir::Rvalue::*;
+ match rvalue {
+ Use(op) => rustc_op_to_op(op),
+ Repeat(_, _) => todo!(),
+ Ref(_, _, _) => todo!(),
+ ThreadLocalRef(_) => todo!(),
+ AddressOf(_, _) => todo!(),
+ Len(_) => todo!(),
+ Cast(_, _, _) => todo!(),
+ BinaryOp(_, _) => todo!(),
+ CheckedBinaryOp(_, _) => todo!(),
+ NullaryOp(_, _) => todo!(),
+ UnaryOp(_, _) => todo!(),
+ Discriminant(_) => todo!(),
+ Aggregate(_, _) => todo!(),
+ ShallowInitBox(_, _) => todo!(),
+ CopyForDeref(_) => todo!(),
+ }
+}
+
+fn rustc_op_to_op(op: &rustc_middle::mir::Operand<'_>) -> stable_mir::mir::Operand {
+ use rustc_middle::mir::Operand::*;
+ match op {
+ Copy(place) => stable_mir::mir::Operand::Copy(rustc_place_to_place(place)),
+ Move(place) => stable_mir::mir::Operand::Move(rustc_place_to_place(place)),
+ Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()),
+ }
+}
+
+fn rustc_place_to_place(place: &rustc_middle::mir::Place<'_>) -> stable_mir::mir::Place {
+ assert_eq!(&place.projection[..], &[]);
+ stable_mir::mir::Place { local: place.local.as_usize() }
+}
+
+fn rustc_terminator_to_terminator(
+ terminator: &rustc_middle::mir::Terminator<'_>,
+) -> stable_mir::mir::Terminator {
+ use rustc_middle::mir::TerminatorKind::*;
+ use stable_mir::mir::Terminator;
+ match &terminator.kind {
+ Goto { target } => Terminator::Goto { target: target.as_usize() },
+ SwitchInt { discr, targets } => Terminator::SwitchInt {
+ discr: rustc_op_to_op(discr),
+ targets: targets
+ .iter()
+ .map(|(value, target)| stable_mir::mir::SwitchTarget {
+ value,
+ target: target.as_usize(),
+ })
+ .collect(),
+ otherwise: targets.otherwise().as_usize(),
+ },
+ Resume => Terminator::Resume,
+ Terminate => Terminator::Abort,
+ Return => Terminator::Return,
+ Unreachable => Terminator::Unreachable,
+ Drop { .. } => todo!(),
+ Call { .. } => todo!(),
+ Assert { .. } => todo!(),
+ Yield { .. } => todo!(),
+ GeneratorDrop => todo!(),
+ FalseEdge { .. } => todo!(),
+ FalseUnwind { .. } => todo!(),
+ InlineAsm { .. } => todo!(),
+ }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mir.rs b/compiler/rustc_smir/src/stable_mir/mir.rs
new file mode 100644
index 000000000..a9dbc3463
--- /dev/null
+++ b/compiler/rustc_smir/src/stable_mir/mir.rs
@@ -0,0 +1,3 @@
+mod body;
+
+pub use body::*;
diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs
new file mode 100644
index 000000000..c504065c9
--- /dev/null
+++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs
@@ -0,0 +1,69 @@
+#[derive(Clone, Debug)]
+pub struct Body {
+ pub blocks: Vec<BasicBlock>,
+}
+
+#[derive(Clone, Debug)]
+pub struct BasicBlock {
+ pub statements: Vec<Statement>,
+ pub terminator: Terminator,
+}
+
+#[derive(Clone, Debug)]
+pub enum Terminator {
+ Goto {
+ target: usize,
+ },
+ SwitchInt {
+ discr: Operand,
+ targets: Vec<SwitchTarget>,
+ otherwise: usize,
+ },
+ Resume,
+ Abort,
+ Return,
+ Unreachable,
+ Drop {
+ place: Place,
+ target: usize,
+ unwind: Option<usize>,
+ },
+ Call {
+ func: Operand,
+ args: Vec<Operand>,
+ destination: Place,
+ target: Option<usize>,
+ cleanup: Option<usize>,
+ },
+ Assert {
+ cond: Operand,
+ expected: bool,
+ msg: String,
+ target: usize,
+ cleanup: Option<usize>,
+ },
+}
+
+#[derive(Clone, Debug)]
+pub enum Statement {
+ Assign(Place, Operand),
+ Nop,
+}
+
+#[derive(Clone, Debug)]
+pub enum Operand {
+ Copy(Place),
+ Move(Place),
+ Constant(String),
+}
+
+#[derive(Clone, Debug)]
+pub struct Place {
+ pub local: usize,
+}
+
+#[derive(Clone, Debug)]
+pub struct SwitchTarget {
+ pub value: u128,
+ pub target: usize,
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
new file mode 100644
index 000000000..1d2efb5ea
--- /dev/null
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -0,0 +1,73 @@
+//! Module that implements the public interface to the Stable MIR.
+//!
+//! This module shall contain all type definitions and APIs that we expect 3P tools to invoke to
+//! interact with the compiler.
+//!
+//! The goal is to eventually move this module to its own crate which shall be published on
+//! [crates.io](https://crates.io).
+//!
+//! ## Note:
+//!
+//! There shouldn't be any direct references to internal compiler constructs in this module.
+//! If you need an internal construct, consider using `rustc_internal` or `rustc_smir`.
+
+pub mod mir;
+
+/// Use String for now but we should replace it.
+pub type Symbol = String;
+
+/// The number that identifies a crate.
+pub type CrateNum = usize;
+
+/// A unique identification number for each item accessible for the current compilation unit.
+pub type DefId = usize;
+
+/// A list of crate items.
+pub type CrateItems = Vec<CrateItem>;
+
+/// Holds information about a crate.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct Crate {
+ pub(crate) id: CrateNum,
+ pub name: Symbol,
+ pub is_local: bool,
+}
+
+/// Holds information about an item in the crate.
+/// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to
+/// use this item.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct CrateItem(pub(crate) DefId);
+
+impl CrateItem {
+ pub fn body(&self) -> mir::Body {
+ crate::rustc_smir::mir_body(self)
+ }
+}
+
+/// Return the function where execution starts if the current
+/// crate defines that. This is usually `main`, but could be
+/// `start` if the crate is a no-std crate.
+pub fn entry_fn() -> Option<CrateItem> {
+ crate::rustc_smir::entry_fn()
+}
+
+/// Access to the local crate.
+pub fn local_crate() -> Crate {
+ crate::rustc_smir::local_crate()
+}
+
+/// Try to find a crate with the given name.
+pub fn find_crate(name: &str) -> Option<Crate> {
+ crate::rustc_smir::find_crate(name)
+}
+
+/// Try to find a crate with the given name.
+pub fn external_crates() -> Vec<Crate> {
+ crate::rustc_smir::external_crates()
+}
+
+/// Retrieve all items in the local crate that have a MIR associated with them.
+pub fn all_local_items() -> CrateItems {
+ crate::rustc_smir::all_local_items()
+}
diff --git a/compiler/rustc_smir/src/very_unstable.rs b/compiler/rustc_smir/src/very_unstable.rs
deleted file mode 100644
index 12ba133db..000000000
--- a/compiler/rustc_smir/src/very_unstable.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//! This module reexports various crates and modules from unstable rustc APIs.
-//! Add anything you need here and it will get slowly transferred to a stable API.
-//! Only use rustc_smir in your dependencies and use the reexports here instead of
-//! directly referring to the unstable crates.
-
-macro_rules! crates {
- ($($rustc_name:ident -> $name:ident,)*) => {
- $(
- #[cfg(not(feature = "default"))]
- pub extern crate $rustc_name as $name;
- #[cfg(feature = "default")]
- pub use $rustc_name as $name;
- )*
- }
-}
-
-crates! {
- rustc_borrowck -> borrowck,
- rustc_driver -> driver,
- rustc_hir -> hir,
- rustc_interface -> interface,
- rustc_middle -> middle,
- rustc_mir_dataflow -> dataflow,
- rustc_mir_transform -> transform,
- rustc_serialize -> serialize,
- rustc_trait_selection -> trait_selection,
-}