Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly version the JSON schema #75

Merged
merged 2 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,20 @@ book](https://doc.rust-lang.org/book/2018-edition/ch01-01-installation.html)).

See the [crux-mir][crux-mir-repo] README for usage instructions.

## JSON schema

`mir-json` and related tools produce MIR JSON files as output, which the
contain the intermediate MIR code from the compiled program in a
machine-readable format. Downstream tools are sensitive to the particular
schema that a MIR JSON file uses, so we explicitly record the version of the
JSON schema in each MIR JSON file (in the `"version"` field).

Any time that `mir-json` is updated such that the JSON schema must also be
changed, we will also update the schema version number. The version number is
represented as a single integer. Any changes to the schema are assumed to be
backwards-incompatible with previous versions of the schema, so all version
bumps should be treated as major version bumps. Each change to the schema is
described in the [`SCHEMA_VERSIONING.md`](SCHEMA_VERSIONING.md) file.


[crux-mir-repo]: https://github.com/GaloisInc/crucible/tree/master/crux-mir
8 changes: 8 additions & 0 deletions SCHEMA_CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
The following document describes the changes to the JSON schema that
`mir-json`–produced files adhere to. (This document should not be interpreted
as a changelog for the code in the `mir-json` tools themselves, which are
versioned separately.)

## 1

Initial schema version.
2 changes: 2 additions & 0 deletions src/analyz/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mod ty_json;
use analyz::to_json::*;
use analyz::ty_json::*;
use lib_util::{self, JsonOutput, EntryKind};
use schema_ver::SCHEMA_VER;

basic_json_enum_impl!(mir::BinOp);

Expand Down Expand Up @@ -1168,6 +1169,7 @@ pub fn analyze_nonstreaming<'tcx>(
let total_items = out.fns.len() + out.adts.len() + out.statics.len() + out.vtables.len() +
out.traits.len() + out.intrinsics.len();
let j = json!({
"version": SCHEMA_VER,
"fns": out.fns,
"adts": out.adts,
"statics": out.statics,
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ extern crate rustc_target;
pub mod analyz;
pub mod lib_util;
pub mod link;
pub mod schema_ver;

mod tar_stream;
9 changes: 8 additions & 1 deletion src/lib_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use serde_cbor;
use serde_json;
use tar;

use crate::schema_ver::SCHEMA_VER;
use crate::tar_stream::{TarStream, TarEntryStream};

#[derive(Debug, Default, Serialize, Deserialize)]
Expand All @@ -39,6 +40,9 @@ pub struct CrateIndex {
pub items: HashMap<StringId, ItemData>,

pub roots: Vec<StringId>,

/// The schema version in use. (See also `SCHEMA_VER`.)
pub version: u64,
}

/// Metadata about a single item.
Expand Down Expand Up @@ -245,7 +249,9 @@ impl EmitterState {
let mut roots = self.roots.into_iter().collect::<Vec<_>>();
roots.sort();

CrateIndex { names, items, roots }
let version = SCHEMA_VER;

CrateIndex { names, items, roots, version }
}
}

Expand Down Expand Up @@ -296,6 +302,7 @@ impl<W: Write> Emitter<W> {

pub fn emit_crate(&mut self, j: &JsonValue) -> io::Result<()> {
write!(self.writer, "{{")?;
write!(self.writer, "\"version\":{:?},", SCHEMA_VER)?;
self.emit_table_from(EntryKind::Fn, j)?;
write!(self.writer, ",")?;
self.emit_table_from(EntryKind::Adt, j)?;
Expand Down
20 changes: 20 additions & 0 deletions src/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use serde_cbor;
use serde_json;

use crate::lib_util::{self, CrateIndex, InternTable, EntryKind, StringId};
use crate::schema_ver::SCHEMA_VER;


fn read_crates<R: Read + Seek>(
Expand Down Expand Up @@ -62,13 +63,31 @@ fn collect_roots(
roots
}

/// Ensure that all `CrateIndex`es have the same MIR JSON schema version as the
/// version this build of `mir-json` is using (i.e., the same as `SCHEMA_VER`).
/// If there is at least one `CrateIndex` that has a different schema version,
/// return an error.
fn check_matching_versions(indexes: &[CrateIndex]) -> serde_cbor::Result<()> {
for index in indexes {
if SCHEMA_VER != index.version {
return Err(serde::ser::Error::custom(format!(
"Expected MIR JSON schema version {:?}, but found a crate using version {:?}",
SCHEMA_VER,
index.version,
)));
}
}

Ok(())
}

/// Combine the contents of `ocs`, producing a combined JSON crate data object as the result.
pub fn link_crates<R, W>(inputs: &mut [R], mut output: W) -> serde_cbor::Result<()>
where R: Read + Seek, W: Write {
let (indexes, json_offsets) = read_crates(inputs)?;
let (it, defs, translate) = assign_global_ids(&indexes);
let roots = collect_roots(&indexes, &translate);
check_matching_versions(&indexes)?;


let mut seen_names = HashSet::new();
Expand Down Expand Up @@ -117,6 +136,7 @@ where R: Read + Seek, W: Write {

// Write tables to the output, copying the serialized content of each entry.
write!(output, "{{")?;
write!(output, "\"version\":{:?},", SCHEMA_VER)?;
for (i, kind) in EntryKind::each().enumerate() {
if i > 0 {
write!(output, ",")?;
Expand Down
9 changes: 9 additions & 0 deletions src/schema_ver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/// The version of the JSON schema that `mir-json` follows. This is intended for
/// use by downstream tools to quickly determine if they are ingesting a MIR
/// JSON file that is compatible with the version of the schema that they are
/// expecting.
///
/// Each version of the schema is assumed to be backwards-incompatible with
/// previous versions of the schema. As such, any time this version number is
/// bumped, it should be treated as a major version bump.
pub const SCHEMA_VER: u64 = 1;