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

Miri api refactor #50967

Merged
merged 42 commits into from
May 25, 2018
Merged

Miri api refactor #50967

merged 42 commits into from
May 25, 2018

Conversation

oli-obk
Copy link
Contributor

@oli-obk oli-obk commented May 22, 2018

r? @eddyb

cc @Zoxc

based on #50916

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 22, 2018
ByRef(Pointer, Align),
ByVal(PrimVal),
ByValPair(PrimVal, PrimVal),
ByRef(Scalar, Align),
Copy link
Member

Choose a reason for hiding this comment

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

Should this be Pointer? Or is there a real usecase of ByRef pointing to a non-allocation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, it's used to preserve zst identity

Copy link
Member

Choose a reason for hiding this comment

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

But this is Value, which means the address shouldn't be observable, only the value behind the pointer.

/// matches Value's optimizations for easy conversions between these two types
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
pub enum ConstValue<'tcx> {
/// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
ByVal(PrimVal),
/// Used only for types with layout::abi::Scalar ABI and ZSTs which use Scalar::Undef
Copy link
Member

Choose a reason for hiding this comment

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

Scalar::Undef comment outdated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

Copy link
Member

Choose a reason for hiding this comment

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

Doesn't seem changed to me.

}

#[inline]
pub fn to_primval(&self) -> Option<PrimVal> {
pub fn to_primval(&self) -> Option<Scalar> {
Copy link
Member

Choose a reason for hiding this comment

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

Should primval be replaced with scalar?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, done

}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PrimValKind {
pub enum ScalarKind {
I8, I16, I32, I64, I128,
U8, U16, U32, U64, U128,
Copy link
Member

Choose a reason for hiding this comment

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

You could at least wrap layout::Integer for signed and unsigned integers, if you want to keep ScalarKind at all (as opposed to reusing layout::Primitive).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -1755,6 +1757,25 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
}
}

/// If this type is a scalar, compute its size without
/// going through `tcx.layout_of`
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this is a good idea...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

and it's gone!

values.iter()
.map(|&u| {
let mut s = String::new();
print_miri_value(
Value::ByVal(PrimVal::Bytes(u)),
Value::Scalar(Scalar::Bits { bits: u, defined: size }),
Copy link
Member

Choose a reason for hiding this comment

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

Since this is for printing, could you pass in 128? There are certainly 128 defined bits, trivially.

Copy link
Member

Choose a reason for hiding this comment

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

Oh this is used for sign extension o_O.

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 will still be passing this as a Scalar, because the function is also called elsewhere with other variants, but I fixed the sign extension thing

Scalar::Bits {
bits: s.len() as u128,
defined: self.tcx.data_layout.pointer_size.bits() as u8,
},
Copy link
Member

Choose a reason for hiding this comment

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

Can't this use .to_value_with_len?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

jup, done

@bors
Copy link
Contributor

bors commented May 23, 2018

☔ The latest upstream changes (presumably #50866) made this pull request unmergeable. Please resolve the merge conflicts.

@oli-obk oli-obk force-pushed the miri_api_refactor branch 3 times, most recently from 85638ee to ca34069 Compare May 23, 2018 16:45
@@ -1149,11 +1149,17 @@ impl<'tcx> TerminatorKind<'tcx> {
Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
Goto { .. } => vec!["".into()],
SwitchInt { ref values, switch_ty, .. } => {
let size = ty::tls::with(|tcx| {
Copy link
Member

Choose a reason for hiding this comment

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

Please call this bits, or, better, keep the name but do size.bits() as u8 at use sites.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

write!(f, "{}f32", Single::from_bits(bits)),
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) =>
(Value::Scalar(Scalar::Bits { bits, defined: 64 }), &TyFloat(ast::FloatTy::F64)) =>
Copy link
Member

Choose a reason for hiding this comment

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

Can you remove all the defined pattern-matching in here?

},
(Value::Scalar(Scalar::Bits { bits, defined: 32 }), &TyChar) =>
write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
(Value::Scalar(Scalar::Bits { defined: 0, .. }), &TyFnDef(did, _)) =>
Copy link
Member

Choose a reason for hiding this comment

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

Also two more cases here.

Copy link
Member

Choose a reason for hiding this comment

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

In fact, this specific one can ignore even whether the value is a Value::Scalar.

@@ -1514,28 +1513,28 @@ impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> {
}

// Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
impl<'a, 'tcx, 'empty> TyCtxt<'a, 'tcx, 'empty> {
Copy link
Member

Choose a reason for hiding this comment

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

Please use impl<'a, 'tcx> TyCtxt<'a, 'tcx, '_> if you don't want to name the lifetime.

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 tried that, that doesn't compile

Copy link
Member

Choose a reason for hiding this comment

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

Doesn't it need a feature-gate? in_band_lifetimes I think?

param_env: param_env_and_ty.param_env
};
cx.layout_of(param_env_and_ty.value)
}
}

impl<'a, 'tcx> ty::maps::TyCtxtAt<'a, 'tcx, 'tcx> {
impl<'a, 'tcx, 'empty> ty::maps::TyCtxtAt<'a, 'tcx, 'empty> {
Copy link
Member

Choose a reason for hiding this comment

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

Same here.

@@ -68,7 +70,7 @@ pub fn primval_to_llvm(cx: &CodegenCx,
&C_usize(cx, ptr.offset.bytes()),
1,
) };
if scalar.value != layout::Pointer {
if layout.value != layout::Pointer {
unsafe { llvm::LLVMConstPtrToInt(llval, llty.to_ref()) }
} else {
consts::bitcast(llval, llty)
Copy link
Member

Choose a reason for hiding this comment

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

Looking at this, this sort of thing probably needs to always use bitcast after LLVMConstPtrToInt, in case the latter is needed at all. You should add a test for an union used to convert a reference into a f32 / f64 (depending on #[cfg(target_pointer_width)]), which I highly suspect trips a LLVM assertion in the current state of the code.

let param_ty = self.param_env.and(gcx.lift(&ty).unwrap());
let bit_width = gcx.layout_of(param_ty).unwrap().size.bits();
trace!("clamp {} with size {} and amt {}", n, bit_width, 128 - bit_width);
let amt = 128 - bit_width;
let result = (n << amt) >> amt;
Copy link
Member

Choose a reason for hiding this comment

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

Can't this use some truncate function from miri?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

won't fix in this PR, there's an issue open for cleaning up this kind of code: #49937

Scalar::Bits {
bits: s.len() as u128,
defined: self.tcx.data_layout.pointer_size.bits() as u8,
}
Copy link
Member

Choose a reason for hiding this comment

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

Can't this use with_len or something?

LitKind::Int(n, _) if neg => {
let n = n as i128;
let n = n.overflowing_neg().0;
let n = clamp(n as u128);
ConstValue::ByVal(PrimVal::Bytes(n))
clamp(n as u128)
Copy link
Member

Choose a reason for hiding this comment

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

Is this a true clamping operation (i.e. saturating), or a truncation? I actually expect truncation.

lo,
hi,
self.param_env.and(ty),
).unwrap();
Copy link
Member

Choose a reason for hiding this comment

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

Note that this unwrap can fail - we should be matching on Option<Ordering> below and explicitly list all the possible cases - currently the _ success at the end of the match would catch None which would be bad.

))
) if size_a == size_b && defined_a == defined_b &&
ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 &&
tcx.data_layout.pointer_size.bits() == defined_a.into() => {
Copy link
Member

Choose a reason for hiding this comment

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

You're comparing defined again. At most these should <= relationships, not ==.

Copy link
Member

@eddyb eddyb May 24, 2018

Choose a reason for hiding this comment

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

That is, each of defined_a and defined_b should be larger or equal to pointer_size.bits() - why not use to_bits with usize instead?

let map = tcx.alloc_map.lock();
let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
if alloc_a.bytes.len() as u64 == size_a as u64 {
Copy link
Member

Choose a reason for hiding this comment

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

Would be better to cast alloc_a.bytes.len() to u128.

PrimVal::Bytes(bytes) => {
let v = ((bytes as u128) % (1 << self.pointer_size().bytes())) as u64;
Scalar::Bits { bits, defined } => {
if defined <= self.pointer_size().bits() as u8 {
Copy link
Member

Choose a reason for hiding this comment

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

This seems wrong, shouldn't be <?

Copy link
Member

Choose a reason for hiding this comment

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

Also, please cast the small type to the large one for comparisons.

return err!(ReadUndefBytes);
}
// FIXME: what on earth does this line do? docs or fix needed!
let v = ((bits as u128) % (1 << self.pointer_size().bytes())) as u64;
Copy link
Member

Choose a reason for hiding this comment

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

It's a truncation, shouldn't be necessary nowadays.

assert_eq!(size, self.pointer_size());
val.offset.bytes() as u128
}

PrimVal::Bytes(bytes) => bytes,
Scalar::Bits { bits, defined } if defined >= size.bits() as u8 && defined != 0 => bits,
Copy link
Member

Choose a reason for hiding this comment

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

I'd write size.bits() != 0 here instead.

Value::ByVal(PrimVal::Undef) => err!(ReadUndefBytes),
Value::ByVal(_) => bug!("expected ptr and length, got {:?}", value),
Value::Scalar(Scalar::Bits { defined: 0, .. }) => err!(ReadUndefBytes),
Value::Scalar(_) => bug!("expected ptr and length, got {:?}", value),
Copy link
Member

Choose a reason for hiding this comment

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

How is it possible to get a Value::Scalar(Scalar::undef()) for a type with an Abi::ScalarPair?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

by reading a fat pointer from undefined bytes I'd presume

Copy link
Member

Choose a reason for hiding this comment

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

That should produce a ScalarPair with two undefs.

PartialOrd, Ord)]
pub enum FloatTy {
F32,
F64,
Copy link
Member

@eddyb eddyb May 24, 2018

Choose a reason for hiding this comment

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

For the record, I disagree with this, in general rustc's typesystem should not include rustc_target::abi types.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 25, 2018
@oli-obk
Copy link
Contributor Author

oli-obk commented May 25, 2018

@bors r=eddyb

@bors
Copy link
Contributor

bors commented May 25, 2018

📌 Commit 50d3783 has been approved by eddyb

@bors
Copy link
Contributor

bors commented May 25, 2018

⌛ Testing commit 50d3783 with merge 53fc7286e4ea16cc5909e0ad96d16e714501132c...

@bors
Copy link
Contributor

bors commented May 25, 2018

💔 Test failed - status-appveyor

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 25, 2018
@rust-highfive
Copy link
Collaborator

The job armhf-gnu of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:50:58] 
[00:50:58] ---- [ui] ui/const-eval/ref_to_int_match.rs stdout ----
[00:50:58] diff of stderr:
[00:50:58] 
[00:50:58] - error[E0030]: lower range bound must be less than or equal to upper
[00:50:58] + error[E0308]: mismatched types
[00:50:58] 2   --> $DIR/ref_to_int_match.rs:14:9
[00:50:58] 3    |
[00:50:58] 4 LL |         10...BAR => {}, //~ ERROR lower range bound must be less than or equal to upper
[00:50:58] 
[00:50:58] -    |         ^^ lower bound larger than upper bound
[00:50:58] +    |         ^^^^^^^^ expected u64, found u32
[00:50:58] 7 error: aborting due to previous error
[00:50:58] 8 
[00:50:58] 
[00:50:58] - For more information about this error, try `rustc --explain E0030`.
[00:50:58] - For more information about this error, try `rustc --explain E0030`.
[00:50:58] + For more information about this error, try `rustc --explain E0308`.
[00:50:58] 10 
[00:50:58] 
[00:50:58] 
[00:50:58] The actual stderr differed from the expected stderr.
[00:50:58] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/const-eval/ref_to_int_match/ref_to_int_match.stderr
[00:50:58] To update references, rerun the tests and pass the `--bless` flag
[00:50:58] To only update this specific test, also pass `--test-args const-eval/ref_to_int_match.rs`
[00:50:58] error: 1 errors occurred comparing output.
[00:50:58] status: exit code: 101
[00:50:58] status: exit code: 101
[00:50:58] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/const-eval/ref_to_int_match.rs" "--target=arm-unknown-linux-gnueabihf" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/const-eval/ref_to_int_match/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/arm-unknown-linux-gnueabihf/native/rust-test-helpers" "-Clinker=arm-linux-gnueabihf-gcc" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/const-eval/ref_to_int_match/auxiliary" "-A" "unused"
[00:50:58] ------------------------------------------
[00:50:58] 
[00:50:58] ------------------------------------------
[00:50:58] stderr:
[00:50:58] stderr:
[00:50:58] ------------------------------------------
[00:50:58] {"message":"mismatched types","code":{"code":"E0308","explanation":"\nThis error occurs when the compiler was unable to infer the concrete type of a\nvariable. It can occur for several cases, the most common of which is a\nmismatch in the expected type that the compiler inferred for a variable's\ninitializing expression, and the actual type explicitly assigned to the\nvariable.\n\nFor example:\n\n```compile_fail,E0308\nlet x: i32 = \"I am not a number!\";\n//     ~~~   ~~~~~~~~~~~~~~~~~~~~\n//      |             |\n//      |    initializing expression;\n//      |    compiler infers type `&str`\n//      |\n//    type `i32` assigned to variable `x`\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/const-eval/ref_to_int_match.rs","byte_start":527,"byte_end":535,"line_start":14,"line_end":14,"column_start":9,"column_end":17,"is_primary":true,"text":[{"text":"        10...BAR => {}, //~ ERROR lower range bound must be less than or equal to upper","highlight_start":9,"highlight_end":17}],"label":"expected u64, found u32","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types\n  --> /checkout/src/test/ui/const-eval/ref_to_int_match.rs:14:9\n   |\nLL |         10...BAR => {}, //~ ERROR lower range bound must be less than or equal to upper\n   |         ^^^^^^^^ expected u64, found u32\n\n"}
[00:50:58] {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error\n\n"}
[00:50:58] {"message":"For more information about this error, try `rustc --explain E0308`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0308`.\n"}
[00:50:58] ------------------------------------------
[00:50:58] 
[00:50:58] thread '[ui] ui/const-eval/ref_to_int_match.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3053:9
[00:50:58] note: Run with `RUST_BACKTRACE=1` for a backtrace.
---
[00:50:58] 
[00:50:58] thread 'main' panicked at 'Some tests failed', tools/compiletest/src/main.rs:498:22
[00:50:58] 
[00:50:58] 
[00:50:58] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/arm-unknown-linux-gnueabihf/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-arm-unknown-linux-gnueabihf" "--mode" "ui" "--target" "arm-unknown-linux-gnueabihf" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/checkout/obj/build/x86_64-unknown-linux-gnu/llvm/build/bin/FileCheck" "--linker" "arm-linux-gnueabihf-gcc" "--host-rustcflags" "-Crpath -O -Zunstable-options " "--target-rustcflags" "-Crpath -O -Zunstable-options  -Lnative=/checkout/obj/build/arm-unknown-linux-gnueabihf/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--llvm-version" "6.0.1\n" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--remote-test-client" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/remote-test-client" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[00:50:58] 
[00:50:58] 
[00:50:58] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test --target arm-unknown-linux-gnueabihf
[00:50:58] Build completed unsuccessfully in 0:48:01

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@oli-obk
Copy link
Contributor Author

oli-obk commented May 25, 2018

@bors r=eddyb

@bors
Copy link
Contributor

bors commented May 25, 2018

📌 Commit 5f599bb has been approved by eddyb

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 25, 2018
@bors
Copy link
Contributor

bors commented May 25, 2018

⌛ Testing commit 5f599bb with merge 990d8aa...

bors added a commit that referenced this pull request May 25, 2018
@bors
Copy link
Contributor

bors commented May 25, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: eddyb
Pushing 990d8aa to master...

@@ -780,7 +793,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
let ty = self.place_ty(place);
let place = self.eval_place(place)?;
let discr_val = self.read_discriminant_value(place, ty)?;
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
let defined = self.layout_of(ty).unwrap().size.bits() as u8;
Copy link
Member

Choose a reason for hiding this comment

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

I believe this causes #51086. ty is the enum of which the discriminant is taken. This should have been dest_ty

@oli-obk oli-obk deleted the miri_api_refactor branch May 30, 2018 14:12
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Nov 8, 2019
rustc_target: inline abi::FloatTy into abi::Primitive.

This effectively undoes a small part of @oli-obk's rust-lang#50967, now that the rest of the compiler doesn't use the `FloatTy` definition from `rustc_target`, post-rust-lang#65884.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants