From d9de6188df98ed2c25c1c7538bf7ed3e5465a920 Mon Sep 17 00:00:00 2001 From: Xavier Denis Date: Mon, 11 Mar 2024 22:38:44 +0100 Subject: [PATCH] Update creusot-metadata --- creusot-metadata/src/decoder.rs | 145 ++++++++++++++---------------- creusot-metadata/src/encoder.rs | 152 +++++++++++++++++++------------- creusot-metadata/src/lib.rs | 47 ++-------- 3 files changed, 163 insertions(+), 181 deletions(-) diff --git a/creusot-metadata/src/decoder.rs b/creusot-metadata/src/decoder.rs index cf3df46432..24e744a842 100644 --- a/creusot-metadata/src/decoder.rs +++ b/creusot-metadata/src/decoder.rs @@ -34,79 +34,28 @@ impl<'a, 'tcx> MetadataDecoder<'a, 'tcx> { self.file_index_to_file .entry(index) .or_insert_with(|| { - let stable_id = self.file_index_to_stable_id[&index].translate(self.tcx); - self.tcx.cstore_untracked().import_source_files(self.tcx.sess, stable_id.cnum); + let source_file_id = &self.file_index_to_stable_id[&index]; + let source_file_cnum = + self.tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id); + + self.tcx.cstore_untracked().import_source_files(self.tcx.sess, source_file_cnum); self.tcx .sess .source_map() - .source_file_by_stable_id(stable_id) + .source_file_by_stable_id(source_file_id.stable_source_file_id) .expect("failed to lookup `SourceFile` in new context") }) .clone() } } -// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two -// compilation sessions. We use the `DefPathHash`, which is stable across -// sessions, to map the old `DefId` to the new one. -impl<'a, 'tcx> Decodable> for DefId { - fn decode(d: &mut MetadataDecoder<'a, 'tcx>) -> Self { - let def_path_hash = DefPathHash::decode(d); - d.tcx.def_path_hash_to_def_id(def_path_hash, &mut || panic!("Cannot resolve crate.")) - } -} - -impl<'a, 'tcx> Decodable> for CrateNum { - fn decode(d: &mut MetadataDecoder<'a, 'tcx>) -> CrateNum { - let stable_id = StableCrateId::decode(d); - d.tcx.stable_crate_id_to_crate_num(stable_id) - } -} - -// This impl makes sure that we get a runtime error when we try decode a -// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic -// because we would not know how to transform the `DefIndex` to the current -// context. -impl<'a, 'tcx> Decodable> for DefIndex { - fn decode(_: &mut MetadataDecoder<'a, 'tcx>) -> DefIndex { - panic!("trying to decode `DefIndex` outside the context of a `DefId`") - } -} - -impl<'a, 'tcx> Decodable> for SyntaxContext { - fn decode(decoder: &mut MetadataDecoder<'a, 'tcx>) -> Self { - let syntax_contexts = decoder.syntax_contexts; - rustc_span::hygiene::decode_syntax_context(decoder, &decoder.hygiene_context, |this, id| { - // This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing. - // We look up the position of the associated `SyntaxData` and decode it. - let pos = syntax_contexts.get(&id).unwrap(); - this.with_position(pos.to_usize(), |decoder| SyntaxContextData::decode(decoder)) - }) - } -} - -impl<'a, 'tcx> Decodable> for ExpnId { - fn decode(decoder: &mut MetadataDecoder<'a, 'tcx>) -> Self { - let stable_id = StableCrateId::decode(decoder); - let cnum = decoder.tcx.stable_crate_id_to_crate_num(stable_id); - let index = u32::decode(decoder); - - let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |_| { - let pos = decoder.expn_data.get(&(stable_id, index)).unwrap(); - decoder.with_position(pos.to_usize(), |decoder| { - let data = ExpnData::decode(decoder); - let hash = ExpnHash::decode(decoder); - (data, hash) - }) - }); - expn_id - } -} +implement_ty_decoder!(MetadataDecoder<'a, 'tcx>); -impl<'a, 'tcx> Decodable> for Span { - fn decode(decoder: &mut MetadataDecoder<'a, 'tcx>) -> Self { - let ctxt = SyntaxContext::decode(decoder); - let tag: u8 = Decodable::decode(decoder); +use rustc_span::{AttrId, SpanDecoder}; +impl SpanDecoder for MetadataDecoder<'_, '_> { + fn decode_span(&mut self) -> Span { + let ctxt = SyntaxContext::decode(self); + let tag: u8 = Decodable::decode(self); if tag == TAG_PARTIAL_SPAN { return DUMMY_SP.with_ctxt(ctxt); @@ -114,49 +63,89 @@ impl<'a, 'tcx> Decodable> for Span { debug_assert!(tag == TAG_FULL_SPAN); - let source_file_index = SourceFileIndex::decode(decoder); - let lo = BytePos::decode(decoder); - let len = BytePos::decode(decoder); + let source_file_index = SourceFileIndex::decode(self); + + let lo = BytePos::decode(self); + let len = BytePos::decode(self); - let file = decoder.file_index_to_file(source_file_index); + let file = self.file_index_to_file(source_file_index); let lo = file.start_pos + lo; let hi = lo + len; Span::new(lo, hi, ctxt, None) } -} -// copy&paste impl from rustc_metadata -impl<'a, 'tcx> Decodable> for Symbol { - fn decode(d: &mut MetadataDecoder<'a, 'tcx>) -> Self { - let tag = d.read_u8(); + fn decode_symbol(&mut self) -> Symbol { + let tag = self.read_u8(); match tag { SYMBOL_STR => { - let s = d.read_str(); + let s = self.read_str(); Symbol::intern(s) } SYMBOL_OFFSET => { // read str offset - let pos = d.read_usize(); + let pos = self.read_usize(); // move to str ofset and read - let sym = d.opaque.with_position(pos, |d| { + let sym = self.opaque.with_position(pos, |d| { let s = d.read_str(); Symbol::intern(s) }); sym } SYMBOL_PREINTERNED => { - let symbol_index = d.read_u32(); + let symbol_index = self.read_u32(); Symbol::new_from_decoded(symbol_index) } _ => unreachable!(), } } -} -implement_ty_decoder!(MetadataDecoder<'a, 'tcx>); + fn decode_expn_id(&mut self) -> ExpnId { + let stable_id = StableCrateId::decode(self); + let cnum = self.tcx.stable_crate_id_to_crate_num(stable_id); + let index = u32::decode(self); + + let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |_| { + let pos = self.expn_data.get(&(stable_id, index)).unwrap(); + self.with_position(pos.to_usize(), |decoder| { + let data = ExpnData::decode(decoder); + let hash = ExpnHash::decode(decoder); + (data, hash) + }) + }); + expn_id + } + fn decode_syntax_context(&mut self) -> SyntaxContext { + let syntax_contexts = self.syntax_contexts; + rustc_span::hygiene::decode_syntax_context(self, &self.hygiene_context, |this, id| { + // This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing. + // We look up the position of the associated `SyntaxData` and decode it. + let pos = syntax_contexts.get(&id).unwrap(); + this.with_position(pos.to_usize(), |decoder| SyntaxContextData::decode(decoder)) + }) + } + fn decode_crate_num(&mut self) -> CrateNum { + let stable_id = StableCrateId::decode(self); + self.tcx.stable_crate_id_to_crate_num(stable_id) + } + fn decode_def_index(&mut self) -> DefIndex { + panic!("trying to decode `DefIndex` outside the context of a `DefId`") + } + + // Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two + // compilation sessions. We use the `DefPathHash`, which is stable across + // sessions, to map the old `DefId` to the new one. + fn decode_def_id(&mut self) -> DefId { + let def_path_hash = DefPathHash::decode(self); + self.tcx.def_path_hash_to_def_id(def_path_hash, &mut || panic!("Cannot resolve crate.")) + } + + fn decode_attr_id(&mut self) -> AttrId { + todo!() + } +} impl<'a, 'tcx> TyDecoder for MetadataDecoder<'a, 'tcx> { // Whether crate-local information can be cleared while encoding diff --git a/creusot-metadata/src/encoder.rs b/creusot-metadata/src/encoder.rs index cd58464fd7..244da48563 100644 --- a/creusot-metadata/src/encoder.rs +++ b/creusot-metadata/src/encoder.rs @@ -16,7 +16,11 @@ use rustc_span::{ hygiene::{raw_encode_syntax_context, HygieneEncodeContext}, ExpnId, SourceFile, Span, Symbol, SyntaxContext, }; -use std::{collections::hash_map::Entry, io::Error, path::Path}; +use std::{ + collections::hash_map::Entry, + io::Error, + path::{Path, PathBuf}, +}; pub struct MetadataEncoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -29,7 +33,7 @@ pub struct MetadataEncoder<'a, 'tcx> { } impl<'a, 'tcx> MetadataEncoder<'a, 'tcx> { - pub fn finish(self) -> Result { + pub fn finish(mut self) -> Result { self.opaque.finish() } @@ -68,88 +72,71 @@ impl<'a, 'tcx> Encoder for MetadataEncoder<'a, 'tcx> { } } -impl<'a, 'tcx> Encodable> for DefId { - fn encode(&self, s: &mut MetadataEncoder<'a, 'tcx>) { - s.tcx.def_path_hash(*self).encode(s) - } -} - -impl<'a, 'tcx> Encodable> for CrateNum { - fn encode(&self, s: &mut MetadataEncoder<'a, 'tcx>) { - s.tcx.stable_crate_id(*self).encode(s) - } -} - -impl<'a, 'tcx> Encodable> for DefIndex { - fn encode(&self, _: &mut MetadataEncoder<'a, 'tcx>) { - panic!("encoding `DefIndex` without context"); - } -} - -impl<'a, 'tcx> Encodable> for SyntaxContext { - fn encode(&self, s: &mut MetadataEncoder<'a, 'tcx>) { - raw_encode_syntax_context(*self, &s.hygiene_context, s); - } -} - -impl<'a, 'tcx> Encodable> for ExpnId { - fn encode(&self, s: &mut MetadataEncoder<'a, 'tcx>) { - s.hygiene_context.schedule_expn_data_for_encoding(*self); - self.krate.encode(s); - self.local_id.as_u32().encode(s); - } -} - -impl<'a, 'tcx> Encodable> for Span { - fn encode(&self, s: &mut MetadataEncoder<'a, 'tcx>) { - let span = self.data(); - span.ctxt.encode(s); +use rustc_span::SpanEncoder; +impl SpanEncoder for MetadataEncoder<'_, '_> { + fn encode_span(&mut self, span: Span) { + let span = span.data(); + span.ctxt.encode(self); if span.is_dummy() { - return TAG_PARTIAL_SPAN.encode(s); + return TAG_PARTIAL_SPAN.encode(self); } - let source_file = s.tcx.sess().source_map().lookup_source_file(span.lo); + let source_file = self.tcx.sess().source_map().lookup_source_file(span.lo); if !source_file.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. - return TAG_PARTIAL_SPAN.encode(s); + return TAG_PARTIAL_SPAN.encode(self); } let lo = span.lo - source_file.start_pos; let len = span.hi - span.lo; - let source_file_index = s.source_file_index(source_file); + let source_file_index = self.source_file_index(source_file); - TAG_FULL_SPAN.encode(s); - source_file_index.encode(s); - lo.encode(s); - len.encode(s); + TAG_FULL_SPAN.encode(self); + source_file_index.encode(self); + lo.encode(self); + len.encode(self); } -} - -impl<'a, 'tcx> Encodable> for Symbol { - fn encode(&self, s: &mut MetadataEncoder<'a, 'tcx>) { + fn encode_symbol(&mut self, sym: Symbol) { // if symbol preinterned, emit tag and symbol index - if self.is_preinterned() { - s.opaque.emit_u8(SYMBOL_PREINTERNED); - s.opaque.emit_u32(self.as_u32()); + if sym.is_preinterned() { + self.opaque.emit_u8(SYMBOL_PREINTERNED); + self.opaque.emit_u32(sym.as_u32()); } else { // otherwise write it as string or as offset to it - match s.symbol_table.entry(*self) { + match self.symbol_table.entry(sym) { Entry::Vacant(o) => { - s.opaque.emit_u8(SYMBOL_STR); - let pos = s.opaque.position(); + self.opaque.emit_u8(SYMBOL_STR); + let pos = self.opaque.position(); o.insert(pos); - s.emit_str(self.as_str()); + self.emit_str(sym.as_str()); } Entry::Occupied(o) => { let x = *o.get(); - s.emit_u8(SYMBOL_OFFSET); - s.emit_usize(x); + self.emit_u8(SYMBOL_OFFSET); + self.emit_usize(x); } } } } + fn encode_expn_id(&mut self, eid: ExpnId) { + self.hygiene_context.schedule_expn_data_for_encoding(eid); + eid.krate.encode(self); + eid.local_id.as_u32().encode(self); + } + fn encode_syntax_context(&mut self, ctx: SyntaxContext) { + raw_encode_syntax_context(ctx, &self.hygiene_context, self); + } + fn encode_crate_num(&mut self, cnum: CrateNum) { + self.tcx.stable_crate_id(cnum).encode(self) + } + fn encode_def_index(&mut self, _: DefIndex) { + panic!("encoding `DefIndex` without context"); + } + fn encode_def_id(&mut self, id: DefId) { + self.tcx.def_path_hash(id).encode(self) + } } impl<'a, 'tcx> TyEncoder for MetadataEncoder<'a, 'tcx> { @@ -179,19 +166,58 @@ pub fn encode_metadata<'tcx, T: for<'a> Encodable>>( tcx: TyCtxt<'tcx>, path: &Path, x: T, -) -> Result<(), Error> { +) -> Result<(), (PathBuf, Error)> { let (file_to_file_index, file_index_to_stable_id) = { let files = tcx.sess.source_map().files(); let mut file_to_file_index = FxHashMap::with_capacity_and_hasher(files.len(), Default::default()); let mut file_index_to_stable_id = FxHashMap::with_capacity_and_hasher(files.len(), Default::default()); - + use rustc_span::def_id::LOCAL_CRATE; + let source_map = tcx.sess.source_map(); + let working_directory = &tcx.sess.opts.working_dir; + let local_crate_stable_id = tcx.stable_crate_id(LOCAL_CRATE); + + // This portion of the code is adapted from the rustc metadata encoder, while the rest of + // the code in this file is based off the rustc incremental cache encoder. + // + // Probably we should refactor the code to be exclusively based on the metadata encoder for (index, file) in files.iter().enumerate() { let index = SourceFileIndex(index as u32); let file_ptr: *const SourceFile = &**file as *const _; file_to_file_index.insert(file_ptr, index); - let source_file_id = EncodedSourceFileId::new(tcx, &file); + + let mut adapted_source_file = (**file).clone(); + if adapted_source_file.cnum == LOCAL_CRATE { + use rustc_span::FileName; + match file.name { + FileName::Real(ref original_file_name) => { + let adapted_file_name = if tcx.sess.should_prefer_remapped_for_codegen() { + source_map.path_mapping().to_embeddable_absolute_path( + original_file_name.clone(), + working_directory, + ) + } else { + source_map.path_mapping().to_local_embeddable_absolute_path( + original_file_name.clone(), + working_directory, + ) + }; + + adapted_source_file.name = FileName::Real(adapted_file_name); + } + _ => { + // expanded code, not from a file + } + }; + use rustc_span::StableSourceFileId; + adapted_source_file.stable_id = StableSourceFileId::from_filename_for_export( + &adapted_source_file.name, + local_crate_stable_id, + ); + } + + let source_file_id = EncodedSourceFileId::new(tcx, &adapted_source_file); file_index_to_stable_id.insert(index, source_file_id); } @@ -202,7 +228,7 @@ pub fn encode_metadata<'tcx, T: for<'a> Encodable>>( let mut encoder = MetadataEncoder { tcx, - opaque: FileEncoder::new(path)?, + opaque: FileEncoder::new(path).unwrap(), type_shorthands: Default::default(), predicate_shorthands: Default::default(), hygiene_context: &hygiene_context, diff --git a/creusot-metadata/src/lib.rs b/creusot-metadata/src/lib.rs index d062575960..e20e08e328 100644 --- a/creusot-metadata/src/lib.rs +++ b/creusot-metadata/src/lib.rs @@ -26,19 +26,12 @@ mod encoder; pub use decoder::decode_metadata; pub use encoder::encode_metadata; -use rustc_data_structures::{ - fx::FxHashMap, - stable_hasher::{Hash64, StableHasher}, -}; +use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::TyCtxt; -use rustc_span::{ - def_id::{StableCrateId, LOCAL_CRATE}, - source_map::StableSourceFileId, - FileName, SourceFile, -}; +use rustc_span::{def_id::StableCrateId, SourceFile, StableSourceFileId}; use std::hash::Hash; -#[derive(Encodable, Decodable, Eq, PartialEq, Hash, Clone, Copy)] +#[derive(Encodable, Decodable, Eq, PartialEq, Hash, Clone, Copy, Debug)] struct SourceFileIndex(u32); #[derive(Encodable, Decodable, Clone, Copy)] @@ -61,42 +54,16 @@ impl AbsoluteBytePos { /// is the only thing available when decoding the [Footer]. #[derive(Encodable, Decodable, Clone, Debug)] struct EncodedSourceFileId { - file_name_hash: Hash64, + stable_source_file_id: StableSourceFileId, stable_crate_id: StableCrateId, } impl EncodedSourceFileId { - fn translate(&self, tcx: TyCtxt<'_>) -> StableSourceFileId { - let cnum = tcx.stable_crate_id_to_crate_num(self.stable_crate_id); - StableSourceFileId { file_name_hash: self.file_name_hash, cnum } - } - + #[inline] fn new(tcx: TyCtxt<'_>, file: &SourceFile) -> EncodedSourceFileId { - if file.cnum == LOCAL_CRATE { - /* Cf rustc_metadata::rmeta::encode_source_map */ - if let FileName::Real(ref original_file_name) = file.name { - let adapted_file_name = - tcx.sess.source_map().path_mapping().to_embeddable_absolute_path( - original_file_name.clone(), - &tcx.sess.opts.working_dir, - ); - if adapted_file_name != *original_file_name { - let file_name_hash = { - let mut hasher = StableHasher::new(); - FileName::Real(adapted_file_name).hash(&mut hasher); - hasher.finish::<_>() - }; - return EncodedSourceFileId { - file_name_hash, - stable_crate_id: tcx.stable_crate_id(LOCAL_CRATE), - }; - } - } - } - let source_file_id = StableSourceFileId::new(file); EncodedSourceFileId { - file_name_hash: source_file_id.file_name_hash, - stable_crate_id: tcx.stable_crate_id(source_file_id.cnum), + stable_source_file_id: file.stable_id, + stable_crate_id: tcx.stable_crate_id(file.cnum), } } }