rustc_monomorphize/offload/
manifest.rs1use std::fs;
8
9use rustc_data_structures::fx::FxHashMap;
10use rustc_data_structures::sync::Lock;
11use rustc_hir::def_id::{DefId, DefIndex, LOCAL_CRATE, StableCrateId};
12use rustc_middle::bug;
13use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
14use rustc_middle::mono::MonoItem;
15use rustc_middle::ty::codec::{TyDecoder, TyEncoder};
16use rustc_middle::ty::{self, Ty, TyCtxt};
17use rustc_serialize::opaque::{FileEncoder, MemDecoder};
18use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
19use rustc_span::{
20 BlobDecoder, BytePos, ByteSymbol, Pos, Span, SpanDecoder, SpanEncoder, Symbol, SyntaxContext,
21};
22
23pub(crate) struct OffloadManifestEncoder<'a, 'tcx> {
24 encoder: FileEncoder<'a>,
25 type_shorthands: FxHashMap<Ty<'tcx>, usize>,
26 predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
27 tcx: TyCtxt<'tcx>,
28}
29
30impl<'a, 'tcx> OffloadManifestEncoder<'a, 'tcx> {
31 pub(crate) fn new(path: &'a std::path::Path, tcx: TyCtxt<'tcx>) -> std::io::Result<Self> {
32 let encoder = FileEncoder::new(path)?;
33 Ok(OffloadManifestEncoder {
34 encoder,
35 type_shorthands: FxHashMap::default(),
36 predicate_shorthands: FxHashMap::default(),
37 tcx,
38 })
39 }
40
41 pub(crate) fn finish(mut self) -> std::io::Result<()> {
42 self.encoder.finish().map(|_| ()).map_err(|(_, e)| e)
43 }
44}
45
46impl<'a, 'tcx> Encoder for OffloadManifestEncoder<'a, 'tcx> {
47 fn emit_usize(&mut self, v: usize) {
48 self.encoder.emit_usize(v);
49 }
50 fn emit_u128(&mut self, v: u128) {
51 self.encoder.emit_u128(v);
52 }
53 fn emit_u64(&mut self, v: u64) {
54 self.encoder.emit_u64(v);
55 }
56 fn emit_u32(&mut self, v: u32) {
57 self.encoder.emit_u32(v);
58 }
59 fn emit_u16(&mut self, v: u16) {
60 self.encoder.emit_u16(v);
61 }
62 fn emit_u8(&mut self, v: u8) {
63 self.encoder.emit_u8(v);
64 }
65 fn emit_isize(&mut self, v: isize) {
66 self.encoder.emit_isize(v);
67 }
68 fn emit_i128(&mut self, v: i128) {
69 self.encoder.emit_i128(v);
70 }
71 fn emit_i64(&mut self, v: i64) {
72 self.encoder.emit_i64(v);
73 }
74 fn emit_i32(&mut self, v: i32) {
75 self.encoder.emit_i32(v);
76 }
77 fn emit_i16(&mut self, v: i16) {
78 self.encoder.emit_i16(v);
79 }
80 fn emit_i8(&mut self, v: i8) {
81 self.encoder.emit_i8(v);
82 }
83 fn emit_raw_bytes(&mut self, v: &[u8]) {
84 self.encoder.emit_raw_bytes(v);
85 }
86}
87
88impl<'a, 'tcx> SpanEncoder for OffloadManifestEncoder<'a, 'tcx> {
89 fn encode_span(&mut self, _span: Span) {
90 self.emit_usize(0);
92 self.emit_usize(0);
93 self.emit_u32(0);
94 }
95
96 fn encode_symbol(&mut self, sym: rustc_span::Symbol) {
97 sym.as_str().encode(self);
98 }
99
100 fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol) {
101 let bytes = byte_sym.as_byte_str();
102 if true {
if !bytes.is_empty() {
{
::core::panicking::panic_fmt(format_args!("ByteSymbols with content are not expected in offload manifests"));
}
};
};debug_assert!(
103 bytes.is_empty(),
104 "ByteSymbols with content are not expected in offload manifests"
105 );
106 self.emit_usize(bytes.len());
107 self.emit_raw_bytes(bytes.as_ref())
108 }
109
110 fn encode_expn_id(&mut self, _expn_id: rustc_span::ExpnId) {
111 self.emit_u32(0);
112 }
113
114 fn encode_syntax_context(&mut self, _syntax_context: SyntaxContext) {
115 self.emit_u32(0);
116 }
117
118 fn encode_crate_num(&mut self, crate_num: rustc_span::def_id::CrateNum) {
119 self.tcx.stable_crate_id(crate_num).encode(self);
120 }
121
122 fn encode_def_index(&mut self, def_index: rustc_span::def_id::DefIndex) {
123 def_index.as_u32().encode(self);
124 }
125
126 fn encode_def_id(&mut self, def_id: rustc_span::def_id::DefId) {
127 let crate_name = self.tcx.crate_name(def_id.krate);
128 let def_path = self.tcx.def_path(def_id);
129 crate_name.encode(self);
130 def_path.to_string_no_crate_verbose().encode(self);
131 }
132}
133
134impl<'a, 'tcx> TyEncoder<'tcx> for OffloadManifestEncoder<'a, 'tcx> {
135 const CLEAR_CROSS_CRATE: bool = true;
136
137 fn position(&self) -> usize {
138 self.encoder.position()
139 }
140
141 fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
142 &mut self.type_shorthands
143 }
144
145 fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
146 &mut self.predicate_shorthands
147 }
148
149 fn encode_alloc_id(&mut self, _alloc_id: &rustc_middle::mir::interpret::AllocId) {
150 }
152}
153
154const UNRESOLVED_DEF_ID: DefId = DefId {
155 krate: rustc_span::def_id::CrateNum::MAX,
156 index: rustc_span::def_id::DefIndex::from_u32(0),
157};
158
159pub(crate) struct OffloadManifestDecoder<'a, 'tcx> {
161 decoder: MemDecoder<'a>,
162 type_shorthands: Lock<FxHashMap<usize, Ty<'tcx>>>,
163 #[allow(dead_code)]
164 predicate_shorthands: Lock<FxHashMap<usize, ty::PredicateKind<'tcx>>>,
165 tcx: TyCtxt<'tcx>,
166 def_path_map: Lock<Option<FxHashMap<(Symbol, String), DefId>>>,
169}
170
171impl<'a, 'tcx> OffloadManifestDecoder<'a, 'tcx> {
172 pub(crate) fn new(data: &'a [u8], tcx: TyCtxt<'tcx>) -> Result<Self, ()> {
173 let decoder = MemDecoder::new(data, 0)?;
174 Ok(OffloadManifestDecoder {
175 decoder,
176 type_shorthands: Lock::new(FxHashMap::default()),
177 predicate_shorthands: Lock::new(FxHashMap::default()),
178 tcx,
179 def_path_map: Lock::new(None),
180 })
181 }
182
183 fn get_or_build_def_path_map(&self) -> FxHashMap<(Symbol, String), DefId> {
185 let mut guard = self.def_path_map.lock();
186 if let Some(map) = guard.as_ref() {
187 return map.clone();
188 }
189 let map = Self::build_def_path_map(self.tcx);
190 *guard = Some(map.clone());
191 map
192 }
193
194 fn build_def_path_map(tcx: TyCtxt<'tcx>) -> FxHashMap<(Symbol, String), DefId> {
196 let mut map: FxHashMap<(Symbol, String), DefId> = FxHashMap::default();
197
198 let local_crate_name = tcx.crate_name(LOCAL_CRATE);
199 let krate_items = tcx.hir_crate_items(());
200 let local_def_ids = krate_items
201 .free_items()
202 .map(|id| id.owner_id.to_def_id())
203 .chain(krate_items.trait_items().map(|id| id.owner_id.to_def_id()))
204 .chain(krate_items.impl_items().map(|id| id.owner_id.to_def_id()))
205 .chain(krate_items.foreign_items().map(|id| id.owner_id.to_def_id()));
206 for item_id in local_def_ids {
207 let def_id = item_id;
208 let def_path = tcx.def_path(def_id);
209 map.insert((local_crate_name, def_path.to_string_no_crate_verbose()), def_id);
210 }
211
212 for &cnum in tcx.crates(()) {
213 if cnum == LOCAL_CRATE {
214 continue;
215 }
216 let crate_name = tcx.crate_name(cnum);
217 let num_defs = tcx.num_extern_def_ids(cnum);
218 for i in 0..num_defs {
219 let def_id = DefId { krate: cnum, index: DefIndex::from_usize(i) };
220 let def_path = tcx.def_path(def_id);
221 map.entry((crate_name, def_path.to_string_no_crate_verbose())).or_insert(def_id);
222 }
223 }
224
225 map
226 }
227}
228
229impl<'a, 'tcx> Decoder for OffloadManifestDecoder<'a, 'tcx> {
230 fn read_usize(&mut self) -> usize {
231 self.decoder.read_usize()
232 }
233 fn read_u128(&mut self) -> u128 {
234 self.decoder.read_u128()
235 }
236 fn read_u64(&mut self) -> u64 {
237 self.decoder.read_u64()
238 }
239 fn read_u32(&mut self) -> u32 {
240 self.decoder.read_u32()
241 }
242 fn read_u16(&mut self) -> u16 {
243 self.decoder.read_u16()
244 }
245 fn read_u8(&mut self) -> u8 {
246 self.decoder.read_u8()
247 }
248 fn read_isize(&mut self) -> isize {
249 self.decoder.read_isize()
250 }
251 fn read_i128(&mut self) -> i128 {
252 self.decoder.read_i128()
253 }
254 fn read_i64(&mut self) -> i64 {
255 self.decoder.read_i64()
256 }
257 fn read_i32(&mut self) -> i32 {
258 self.decoder.read_i32()
259 }
260 fn read_i16(&mut self) -> i16 {
261 self.decoder.read_i16()
262 }
263 fn read_i8(&mut self) -> i8 {
264 self.decoder.read_i8()
265 }
266 fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
267 self.decoder.read_raw_bytes(len)
268 }
269 fn peek_byte(&self) -> u8 {
270 self.decoder.peek_byte()
271 }
272 fn position(&self) -> usize {
273 self.decoder.position()
274 }
275}
276
277impl<'a, 'tcx> BlobDecoder for OffloadManifestDecoder<'a, 'tcx> {
278 fn decode_symbol(&mut self) -> rustc_span::Symbol {
279 let s: String = Decodable::decode(self);
280 rustc_span::Symbol::intern(&s)
281 }
282
283 fn decode_byte_symbol(&mut self) -> ByteSymbol {
284 let len = self.read_usize();
285 let bytes = self.read_raw_bytes(len);
286 ByteSymbol::intern(bytes)
287 }
288
289 fn decode_def_index(&mut self) -> rustc_span::def_id::DefIndex {
290 let v = self.read_u32();
291 rustc_span::def_id::DefIndex::from_u32(v)
292 }
293}
294
295impl<'a, 'tcx> SpanDecoder for OffloadManifestDecoder<'a, 'tcx> {
296 fn decode_span(&mut self) -> Span {
297 let lo = self.read_usize();
298 let hi = self.read_usize();
299 let _ctxt = self.read_u32();
300 Span::new(BytePos::from_usize(lo), BytePos::from_usize(hi), SyntaxContext::root(), None)
301 }
302
303 fn decode_expn_id(&mut self) -> rustc_span::ExpnId {
304 let _ = self.read_u32();
305 rustc_span::ExpnId::root()
306 }
307
308 fn decode_syntax_context(&mut self) -> SyntaxContext {
309 let _ = self.read_u32();
310 SyntaxContext::root()
311 }
312
313 fn decode_crate_num(&mut self) -> rustc_span::def_id::CrateNum {
314 let stable_id: StableCrateId = Decodable::decode(self);
315 self.tcx.stable_crate_id_to_crate_num(stable_id)
316 }
317
318 fn decode_def_id(&mut self) -> rustc_span::def_id::DefId {
319 let crate_name: String = Decodable::decode(self);
320 let crate_name = Symbol::intern(&crate_name);
321 let def_path_str: String = Decodable::decode(self);
322 let map = self.get_or_build_def_path_map();
323 map.get(&(crate_name, def_path_str)).copied().unwrap_or(UNRESOLVED_DEF_ID)
324 }
325
326 fn decode_attr_id(&mut self) -> rustc_ast::AttrId {
327 self.tcx.dcx().fatal("AttrIds are not expected in offload manifests");
328 }
329}
330
331impl<'a, 'tcx> TyDecoder<'tcx> for OffloadManifestDecoder<'a, 'tcx> {
332 const CLEAR_CROSS_CRATE: bool = true;
333
334 fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
335 where
336 F: FnOnce(&mut Self) -> Ty<'tcx>,
337 {
338 if let Some(ty) = self.type_shorthands.lock().get(&shorthand) {
339 return *ty;
340 }
341 let ty = or_insert_with(self);
342 self.type_shorthands.lock().insert(shorthand, ty);
343 ty
344 }
345
346 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
347 where
348 F: FnOnce(&mut Self) -> R,
349 {
350 let new_decoder = self.decoder.split_at(pos);
351 let old_decoder = std::mem::replace(&mut self.decoder, new_decoder);
352 let result = f(self);
353 self.decoder = old_decoder;
354 result
355 }
356
357 fn decode_alloc_id(&mut self) -> rustc_middle::mir::interpret::AllocId {
358 self.tcx.dcx().fatal("AllocIds are not expected in offload manifests");
359 }
360}
361
362impl<'a, 'tcx> rustc_middle::ty::InternerDecoder for OffloadManifestDecoder<'a, 'tcx> {
363 type Interner = TyCtxt<'tcx>;
364
365 #[inline]
366 fn interner(&self) -> Self::Interner {
367 self.tcx
368 }
369}
370
371pub(crate) fn write_manifest<'tcx>(
373 path: &std::path::Path,
374 tcx: TyCtxt<'tcx>,
375 instances: &[ty::Instance<'tcx>],
376) -> std::io::Result<()> {
377 let mut encoder = OffloadManifestEncoder::new(path, tcx)?;
378 instances.encode(&mut encoder);
379 encoder.finish()
380}
381
382pub fn write_host_metadata_offload_manifest<'tcx>(tcx: TyCtxt<'tcx>) {
385 let Some(path) = tcx.sess.opts.unstable_opts.offload.iter().find_map(|o| {
386 if let rustc_session::config::Offload::HostMetadata(p) = o { Some(p) } else { None }
387 }) else {
388 ::rustc_middle::util::bug::bug_fmt(format_args!("HostMetadata path not found; caller should have checked"));bug!("HostMetadata path not found; caller should have checked");
389 };
390
391 let partitions = tcx.collect_and_partition_mono_items(());
392 let mono_items: Vec<MonoItem<'_>> = partitions
393 .codegen_units
394 .iter()
395 .flat_map(|cgu| cgu.items().iter())
396 .map(|(item, _)| *item)
397 .collect();
398
399 let instances: Vec<ty::Instance<'tcx>> = mono_items
400 .iter()
401 .filter_map(|item| {
402 if let MonoItem::Fn(instance) = item {
403 if tcx
404 .codegen_fn_attrs(instance.def_id())
405 .flags
406 .contains(CodegenFnAttrFlags::OFFLOAD_KERNEL)
407 {
408 Some(*instance)
409 } else {
410 None
411 }
412 } else {
413 None
414 }
415 })
416 .collect();
417
418 if let Err(e) = write_manifest(std::path::Path::new(path), tcx, &instances) {
419 tcx.dcx().emit_fatal(crate::diagnostics::OffloadManifestWriteError {
420 path: path.clone(),
421 err: e.to_string(),
422 });
423 }
424}
425
426pub(crate) fn read_manifest<'tcx>(
428 path: &std::path::Path,
429 tcx: TyCtxt<'tcx>,
430) -> std::io::Result<Vec<ty::Instance<'tcx>>> {
431 let data = fs::read(path)?;
432 let mut decoder = OffloadManifestDecoder::new(&data, tcx)
433 .map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid manifest"))?;
434
435 let instances: Vec<ty::Instance<'tcx>> = Decodable::decode(&mut decoder);
436
437 Ok(instances)
438}