|
3 | 3 | //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs |
4 | 4 | //! until stable MIR is complete. |
5 | 5 |
|
6 | | -use crate::rustc_smir::Tables; |
| 6 | +use crate::rustc_smir::{Stable, Tables, TablesWrapper}; |
7 | 7 | use rustc_data_structures::fx; |
8 | 8 | use rustc_data_structures::fx::FxIndexMap; |
9 | 9 | use rustc_middle::mir::interpret::AllocId; |
10 | 10 | use rustc_middle::ty; |
11 | 11 | use rustc_middle::ty::TyCtxt; |
12 | 12 | use rustc_span::def_id::{CrateNum, DefId}; |
13 | 13 | use rustc_span::Span; |
| 14 | +use scoped_tls::scoped_thread_local; |
14 | 15 | use stable_mir::ty::IndexedVal; |
| 16 | +use std::cell::Cell; |
| 17 | +use std::cell::RefCell; |
15 | 18 | use std::fmt::Debug; |
16 | 19 | use std::hash::Hash; |
17 | 20 | use std::ops::Index; |
18 | 21 |
|
19 | 22 | mod internal; |
20 | 23 |
|
| 24 | +pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { |
| 25 | + with_tables(|tables| item.stable(tables)) |
| 26 | +} |
| 27 | + |
| 28 | +pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { |
| 29 | + with_tables(|tables| item.internal(tables)) |
| 30 | +} |
| 31 | + |
21 | 32 | impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> { |
22 | 33 | type Output = DefId; |
23 | 34 |
|
@@ -125,18 +136,41 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { |
125 | 136 | item.id.into() |
126 | 137 | } |
127 | 138 |
|
| 139 | +// A thread local variable that stores a pointer to the tables mapping between TyCtxt |
| 140 | +// datastructures and stable MIR datastructures |
| 141 | +scoped_thread_local! (static TLV: Cell<*const ()>); |
| 142 | + |
| 143 | +pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) { |
| 144 | + assert!(!TLV.is_set()); |
| 145 | + let ptr = tables as *const _ as *const (); |
| 146 | + TLV.set(&Cell::new(ptr), || { |
| 147 | + f(); |
| 148 | + }); |
| 149 | +} |
| 150 | + |
| 151 | +/// Loads the current context and calls a function with it. |
| 152 | +/// Do not nest these, as that will ICE. |
| 153 | +pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R { |
| 154 | + assert!(TLV.is_set()); |
| 155 | + TLV.with(|tlv| { |
| 156 | + let ptr = tlv.get(); |
| 157 | + assert!(!ptr.is_null()); |
| 158 | + let wrapper = ptr as *const TablesWrapper<'tcx>; |
| 159 | + let mut tables = unsafe { (*wrapper).0.borrow_mut() }; |
| 160 | + f(&mut *tables) |
| 161 | + }) |
| 162 | +} |
| 163 | + |
128 | 164 | pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { |
129 | | - stable_mir::run( |
130 | | - Tables { |
131 | | - tcx, |
132 | | - def_ids: IndexMap::default(), |
133 | | - alloc_ids: IndexMap::default(), |
134 | | - spans: IndexMap::default(), |
135 | | - types: vec![], |
136 | | - instances: IndexMap::default(), |
137 | | - }, |
138 | | - f, |
139 | | - ); |
| 165 | + let tables = TablesWrapper(RefCell::new(Tables { |
| 166 | + tcx, |
| 167 | + def_ids: IndexMap::default(), |
| 168 | + alloc_ids: IndexMap::default(), |
| 169 | + spans: IndexMap::default(), |
| 170 | + types: vec![], |
| 171 | + instances: IndexMap::default(), |
| 172 | + })); |
| 173 | + stable_mir::run(&tables, || init(&tables, f)); |
140 | 174 | } |
141 | 175 |
|
142 | 176 | #[macro_export] |
@@ -251,7 +285,7 @@ impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V |
251 | 285 | /// Trait used to translate a stable construct to its rustc counterpart. |
252 | 286 | /// |
253 | 287 | /// This is basically a mirror of [crate::rustc_smir::Stable]. |
254 | | -pub(crate) trait RustcInternal<'tcx> { |
| 288 | +pub trait RustcInternal<'tcx> { |
255 | 289 | type T; |
256 | 290 | fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T; |
257 | 291 | } |
0 commit comments