summaryrefslogtreecommitdiff
path: root/tools/standalone_miri/miri.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-08-03 18:13:51 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-08-03 18:13:51 +0800
commit17615468f01bbe83486500f9cc4020b4cd3b6e8b (patch)
tree6e6c9964a3ab9ca5cd190782c1acce5a986b4e8e /tools/standalone_miri/miri.cpp
parent85bc7996313b4df50cbb227ae25c0721f7f5eadd (diff)
downloadmrust-17615468f01bbe83486500f9cc4020b4cd3b6e8b.tar.gz
Standalone miri - General fixes trying to get a test running
Diffstat (limited to 'tools/standalone_miri/miri.cpp')
-rw-r--r--tools/standalone_miri/miri.cpp94
1 files changed, 65 insertions, 29 deletions
diff --git a/tools/standalone_miri/miri.cpp b/tools/standalone_miri/miri.cpp
index 8fe941d9..ef8a71c9 100644
--- a/tools/standalone_miri/miri.cpp
+++ b/tools/standalone_miri/miri.cpp
@@ -26,6 +26,7 @@ class PrimitiveValue
public:
virtual ~PrimitiveValue() {}
+ virtual bool is_zero() const = 0;
virtual bool add(const PrimitiveValue& v) = 0;
virtual bool subtract(const PrimitiveValue& v) = 0;
virtual bool multiply(const PrimitiveValue& v) = 0;
@@ -51,6 +52,9 @@ struct PrimitiveUInt:
PrimitiveUInt(T v): v(v) {}
~PrimitiveUInt() override {}
+ virtual bool is_zero() const {
+ return this->v == 0;
+ }
bool add(const PrimitiveValue& x) override {
const auto* xp = &x.check<Self>("add");
T newv = this->v + xp->v;
@@ -111,6 +115,9 @@ struct PrimitiveSInt:
PrimitiveSInt(T v): v(v) {}
~PrimitiveSInt() override {}
+ virtual bool is_zero() const {
+ return this->v == 0;
+ }
// TODO: Make this correct.
bool add(const PrimitiveValue& x) override {
const auto* xp = &x.check<Self>("add");
@@ -1628,13 +1635,19 @@ bool InterpreterThread::call_extern(Value& rv, const ::std::string& link_name, c
{
if( link_name == "__rust_allocate" || link_name == "__rust_alloc" )
{
+ static unsigned s_alloc_count = 0;
+
+ auto alloc_idx = s_alloc_count ++;
+ auto alloc_name = FMT_STRING("__rust_alloc#" << alloc_idx);
auto size = args.at(0).read_usize(0);
auto align = args.at(1).read_usize(0);
- LOG_DEBUG("__rust_allocate(size=" << size << ", align=" << align << ")");
+ LOG_DEBUG("__rust_allocate(size=" << size << ", align=" << align << "): name=" << alloc_name);
+ auto alloc = Allocation::new_alloc(size, ::std::move(alloc_name));
+ LOG_TRACE("- alloc=" << alloc << " (" << alloc->size() << " bytes)");
auto rty = ::HIR::TypeRef(RawType::Unit).wrap( TypeWrapper::Ty::Pointer, 0 );
// TODO: Use the alignment when making an allocation?
- rv = Value::new_pointer(rty, 0, RelocationPtr::new_alloc(Allocation::new_alloc(size, "__rust_alloc")));
+ rv = Value::new_pointer(rty, 0, RelocationPtr::new_alloc(::std::move(alloc)));
}
else if( link_name == "__rust_reallocate" || link_name == "__rust_realloc" )
{
@@ -1643,8 +1656,9 @@ bool InterpreterThread::call_extern(Value& rv, const ::std::string& link_name, c
auto ptr_ofs = args.at(0).read_usize(0);
LOG_ASSERT(ptr_ofs == 0, "__rust_reallocate with offset pointer");
auto oldsize = args.at(1).read_usize(0);
- auto newsize = args.at(2).read_usize(0);
- auto align = args.at(3).read_usize(0);
+ // NOTE: The ordering here depends on the rust version (1.19 has: old, new, align - 1.29 has: old, align, new)
+ auto align = args.at(true /*1.29*/ ? 2 : 3).read_usize(0);
+ auto newsize = args.at(true /*1.29*/ ? 3 : 2).read_usize(0);
LOG_DEBUG("__rust_reallocate(ptr=" << alloc_ptr << ", oldsize=" << oldsize << ", newsize=" << newsize << ", align=" << align << ")");
LOG_ASSERT(alloc_ptr, "__rust_reallocate with no backing allocation attached to pointer");
@@ -2197,7 +2211,7 @@ bool InterpreterThread::call_intrinsic(Value& rv, const RcString& name, const ::
else if( name == "mul_with_overflow" )
{
const auto& ty = ty_params.tys.at(0);
-
+
auto lhs = PrimitiveValueVirt::from_value(ty, args.at(0));
auto rhs = PrimitiveValueVirt::from_value(ty, args.at(1));
bool didnt_overflow = lhs.get().multiply( rhs.get() );
@@ -2212,6 +2226,24 @@ bool InterpreterThread::call_intrinsic(Value& rv, const RcString& name, const ::
lhs.get().write_to_value(rv, dty.fields[0].first);
rv.write_u8( dty.fields[1].first, didnt_overflow ? 0 : 1 ); // Returns true if overflow happened
}
+ // - "exact_div" :: Normal divide, but UB if not an exact multiple
+ else if( name == "exact_div" )
+ {
+ const auto& ty = ty_params.tys.at(0);
+
+ auto lhs = PrimitiveValueVirt::from_value(ty, args.at(0));
+ auto rhs = PrimitiveValueVirt::from_value(ty, args.at(1));
+
+ LOG_ASSERT(!rhs.get().is_zero(), "`exact_div` with zero divisor: " << args.at(0) << " / " << args.at(1));
+ auto rem = lhs;
+ rem.get().modulo( rhs.get() );
+ LOG_ASSERT(rem.get().is_zero(), "`exact_div` with yielded non-zero remainder: " << args.at(0) << " / " << args.at(1));
+ bool didnt_overflow = lhs.get().divide( rhs.get() );
+ LOG_ASSERT(didnt_overflow, "`exact_div` failed for unknown reason: " << args.at(0) << " /" << args.at(1));
+
+ rv = Value(ty);
+ lhs.get().write_to_value(rv, 0);
+ }
// Overflowing artithmatic
else if( name == "overflowing_sub" )
{
@@ -2248,31 +2280,35 @@ bool InterpreterThread::call_intrinsic(Value& rv, const RcString& name, const ::
size_t ent_size = ty_params.tys.at(0).get_size();
auto byte_count = ent_count * ent_size;
- LOG_ASSERT(src_alloc, "Source of copy* must have an allocation");
- LOG_ASSERT(dst_alloc, "Destination of copy* must be a memory allocation");
- LOG_ASSERT(dst_alloc.is_alloc(), "Destination of copy* must be a memory allocation");
-
- switch(src_alloc.get_ty())
+ // A count of zero doesn't need to do any of the checks (TODO: Validate this rule)
+ if( byte_count > 0 )
{
- case RelocationPtr::Ty::Allocation: {
- auto v = src_alloc.alloc().read_value(src_ofs, byte_count);
- LOG_DEBUG("v = " << v);
- dst_alloc.alloc().write_value(dst_ofs, ::std::move(v));
- } break;
- case RelocationPtr::Ty::StdString:
- LOG_ASSERT(src_ofs <= src_alloc.str().size(), "");
- LOG_ASSERT(byte_count <= src_alloc.str().size(), "");
- LOG_ASSERT(src_ofs + byte_count <= src_alloc.str().size(), "");
- dst_alloc.alloc().write_bytes(dst_ofs, src_alloc.str().data() + src_ofs, byte_count);
- break;
- case RelocationPtr::Ty::Function:
- LOG_FATAL("Attempt to copy* a function");
- break;
- case RelocationPtr::Ty::FfiPointer:
- LOG_ASSERT(src_alloc.ffi().layout, "");
- LOG_ASSERT(src_alloc.ffi().layout->is_valid_read(src_ofs, byte_count), "");
- dst_alloc.alloc().write_bytes(dst_ofs, reinterpret_cast<const char*>(src_alloc.ffi().ptr_value) + src_ofs, byte_count);
- break;
+ LOG_ASSERT(src_alloc, "Source of copy* must have an allocation");
+ LOG_ASSERT(dst_alloc, "Destination of copy* must be a memory allocation");
+ LOG_ASSERT(dst_alloc.is_alloc(), "Destination of copy* must be a memory allocation");
+
+ switch(src_alloc.get_ty())
+ {
+ case RelocationPtr::Ty::Allocation: {
+ auto v = src_alloc.alloc().read_value(src_ofs, byte_count);
+ LOG_DEBUG("v = " << v);
+ dst_alloc.alloc().write_value(dst_ofs, ::std::move(v));
+ } break;
+ case RelocationPtr::Ty::StdString:
+ LOG_ASSERT(src_ofs <= src_alloc.str().size(), "");
+ LOG_ASSERT(byte_count <= src_alloc.str().size(), "");
+ LOG_ASSERT(src_ofs + byte_count <= src_alloc.str().size(), "");
+ dst_alloc.alloc().write_bytes(dst_ofs, src_alloc.str().data() + src_ofs, byte_count);
+ break;
+ case RelocationPtr::Ty::Function:
+ LOG_FATAL("Attempt to copy* a function");
+ break;
+ case RelocationPtr::Ty::FfiPointer:
+ LOG_ASSERT(src_alloc.ffi().layout, "");
+ LOG_ASSERT(src_alloc.ffi().layout->is_valid_read(src_ofs, byte_count), "");
+ dst_alloc.alloc().write_bytes(dst_ofs, reinterpret_cast<const char*>(src_alloc.ffi().ptr_value) + src_ofs, byte_count);
+ break;
+ }
}
}
else