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

Resolve duplicate crate dependencies (support multiple versions) #430

Merged
merged 1 commit into from
Aug 26, 2021

Conversation

avanhatt
Copy link
Contributor

@avanhatt avanhatt commented Aug 17, 2021

Description of changes:

When building with Cargo RMC, you can run into name conflicts with global allocations if two different versions of a crate are pulled into dependencies.

There are two different problems that this PR addresses:

  1. Global allocations.
  2. Struct types.

Global allocations

We should use the full crate name, including a mangled versioning info string, when naming allocations.

Example:

Before:
Name: getrandom::alloc174
Error:

error: conflicting array sizes for variable 'getrandom::alloc174'
old definition in module '' 
struct getrandom::alloc174::struct {
  unsigned char [10] 0;
}
new definition in module '' 
struct getrandom::alloc174::struct {
  unsigned char [15] 0;
}

reason for conflict at #this.0: array types differ

unsigned char [10]
unsigned char [15]

After: 1vemgcjvp3r154gr::getrandom::alloc174

Struct types

If the same struct is defined differently across versions of a crate, the C we generate has conflicts. This PR now adds the unique type ID, which differs across crates, to the type mangled name.

Before:

reason for conflict at #this.ptr.pointer->data: number of members is different (2/3)

struct mmap::GuestRegionMmap {
  struct mmap_unix::MmapRegion mapping;
  struct guest_memory::GuestAddress guest_base;
}
struct mmap::GuestRegionMmap {
  struct vm_memory::MmapRegion mapping;
  struct vm_memory::GuestAddress guest_base;
  struct std::option::Option<bitmap::Bitmap> dirty_bitmap;
}

After: mmap::GuestRegionMmap::3024063347542320770

Resolved issues:

Resolves #429

Testing:

  • How is this change tested?

Added a new test that creates a diamond crate dependency, where two dependencies use different version of a crate with the same name. Run as its own script since it needs Cargo RMC.

#         dependency1
#        /           \ v0.1.0
#   main             dependency3
#        \           / v0.1.1
#         dependency2

Also manually running on a (private) codebase with this issue.

  • Is this a refactor change?

No.

Checklist

  • Each commit message has a non-empty body, explaining why the change was made
  • Methods or procedures are documented
  • Regression or unit tests are included, or existing tests cover the modified code
  • My PR is restricted to a single feature or bugfix

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

@avanhatt avanhatt force-pushed the dependencies branch 4 times, most recently from 2f75433 to 5948728 Compare August 18, 2021 14:38
@avanhatt avanhatt changed the base branch from main-154-2021-08-06 to main-154-2021-08-17 August 19, 2021 13:49
.gitignore Outdated
@@ -80,3 +80,5 @@ src/test/rustdoc-gui/src/**.lock
/.ninja_deps
/.ninja_log
/src/test/dashboard
**Cargo.lock
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need **

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

@@ -54,13 +57,15 @@ pub struct GotocCtx<'tcx> {
impl<'tcx> GotocCtx<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> GotocCtx<'tcx> {
let (thks, fhks) = type_and_fn_hooks();
let crate_name = full_crate_name(tcx);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just call this full_crate_name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

self.tcx.crate_name(LOCAL_CRATE).to_string()
}

/// The full crate name including versioning info
pub fn full_crate_name(&self) -> String {
self.full_crate_name.clone()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to clone here? Or should we return &str?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

@@ -268,6 +279,21 @@ impl MetadataLoader for GotocMetadataLoader {
}
}

/// The full crate name should use the Codegen Unit builder to include full name resolution,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this where this function belongs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see an argument for either, where it's used for global names, or compiler/rustc_codegen_llvm/src/gotoc/mir_to_goto/utils/names.rs. Maybe the right thing is to move both the global name stuff and this to names.rs, thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think that makes sense

@@ -0,0 +1,39 @@
#!/bin/bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed!

# Test for platform
platform=`uname -sp`
if [[ $platform != "Linux x86_64" ]]; then
echo "Codegen script only works on Linux x86 platform"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens on mac?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the given command, it fails to find std:

error[E0463]: can't find crate for `std`
  |
  = note: the `x86_64-unknown-linux-gnu` target may not be installed
  = help: consider downloading the target with `rustup target add x86_64-unknown-linux-gnu`
  = help: consider building the standard library from source with `cargo build -Zbuild-std`

If you try to build std (using nightly), you hit ICE's within building std. This block to skip is copied from the Firecrackers regression test.


# Compile crates with RMC backend
cd $(dirname $0)
rm -rf build
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does cargo rmc not work

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it fails with:

rmc (dependencies) $ ./src/test/rmc-dependency-test/diamond-dependency/run-dependency-test.sh
ERROR: Unexpected number of json outputs: 5

It seems like the script for it assumes a single symbol table output, but here we get one per dependency and main.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets file a ticket for that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avanhatt avanhatt requested a review from danielsn August 20, 2021 17:56
@avanhatt avanhatt force-pushed the dependencies branch 2 times, most recently from e36b13f to 7f5d99e Compare August 24, 2021 18:18
@avanhatt avanhatt changed the title Full crate name for allocations (support multiple crate versions) Resolve duplicate crate dependencies (support multiple versions) Aug 24, 2021
Copy link
Contributor

@danielsn danielsn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved modulo comments.

// of the same crate that could be pulled in by dependencies. However, RMC's
// treatment of FFI C calls asssumes that we generate the same name for structs
// as the C name, so don't mangle in that case.
let is_repr_c_adt = match *t.kind() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a useful helper function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, moved.

// Crate resolution: mangled names need to be distinct across different versions
// of the same crate that could be pulled in by dependencies. However, RMC's
// treatment of FFI C calls asssumes that we generate the same name for structs
// as the C name, so don't mangle in that case.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a hack. We should note it as such, and have a tracking issue to do the right thing here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed and adding

self.tcx.crate_name(LOCAL_CRATE).to_string()
}

/// The full crate name including versioning info
pub fn full_crate_name(&self) -> &str {
&self.full_crate_name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we cache this one and not the other one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One we pull directly from MIR, the other will build from two parts. Maybe with the to_string in the first case it's the same, though?

@@ -268,6 +279,21 @@ impl MetadataLoader for GotocMetadataLoader {
}
}

/// The full crate name should use the Codegen Unit builder to include full name resolution,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think that makes sense


// Export a function that takes a struct type which differs between this crate
// and the other vesion.
pub fn take_foo(foo: &Foo) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would there be an advantage to returning foo.x + foo.y so that upstream tests could assert on that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, thanks


# Compile crates with RMC backend
cd $(dirname $0)
rm -rf build
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets file a ticket for that

# Compile crates with RMC backend
cd $(dirname $0)
rm -rf build
CARGO_TARGET_DIR=build RUST_BACKTRACE=1 RUSTFLAGS="-Z codegen-backend=gotoc --cfg=rmc" RUSTC=rmc-rustc cargo build --target x86_64-unknown-linux-gnu 2> $LOG
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we use the osx target here and build on mac

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC it requires rebuilding the std lib on mac, which then fails. We can look at this again together.

@avanhatt avanhatt changed the base branch from main-154-2021-08-17 to main-154-2021-08-24 August 25, 2021 18:03
@avanhatt avanhatt merged commit a0c3988 into model-checking:main-154-2021-08-24 Aug 26, 2021
@avanhatt avanhatt deleted the dependencies branch September 14, 2021 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix multiple version of dependencies for global allocations
2 participants