summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-08-03 22:27:21 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-08-03 22:27:21 +0800
commit2612c15cc92a7b9331a2bf6970df506d92b9c48f (patch)
tree43361c58f92439dc69c1513ae1a323900a1783ec /tools
parent7f6d0fed8b2d713daa1668c66ffdcc5ac89d7874 (diff)
downloadmrust-2612c15cc92a7b9331a2bf6970df506d92b9c48f.tar.gz
Standalone MIRI - discriminant_value
Diffstat (limited to 'tools')
-rw-r--r--tools/standalone_miri/miri.cpp56
-rw-r--r--tools/standalone_miri/value.cpp10
-rw-r--r--tools/standalone_miri/value.hpp5
3 files changed, 60 insertions, 11 deletions
diff --git a/tools/standalone_miri/miri.cpp b/tools/standalone_miri/miri.cpp
index c955ef3b..67023205 100644
--- a/tools/standalone_miri/miri.cpp
+++ b/tools/standalone_miri/miri.cpp
@@ -830,23 +830,26 @@ bool InterpreterThread::step_one(Value& out_thread_result)
LOG_ASSERT(re.type.inner_type == RawType::USize, "Function pointers can only be casted to usize, instead " << re.type);
new_val = src_value.read_value(0, re.type.get_size());
break;
- case RawType::Char:
+ case RawType::Char: {
+ uint32_t v = src_value.read_u32(0);
switch(re.type.inner_type)
{
- case RawType::U8: {
- uint32_t v = src_value.read_u32(0);
+ case RawType::U8:
if( v > 0xFF ) {
LOG_NOTICE("Casting to u8 from char above 255");
}
new_val.write_u8(0, v & 0xFF);
- } break;
+ break;
case RawType::U32:
new_val = src_value.read_value(0, 4);
break;
+ case RawType::USize:
+ new_val.write_usize(0, v);
+ break;
default:
LOG_ERROR("Char can only be casted to u32/u8, instead " << re.type);
}
- break;
+ } break;
case RawType::Unit:
LOG_FATAL("Cast of unit");
case RawType::Composite: {
@@ -2093,10 +2096,49 @@ bool InterpreterThread::call_intrinsic(Value& rv, const RcString& name, const ::
{
it = type_ids.insert(it, ty_T);
}
-
+
rv = Value::with_size(POINTER_SIZE, false);
rv.write_usize(0, it - type_ids.begin());
}
+ else if( name == "discriminant_value" )
+ {
+ const auto& ty = ty_params.tys.at(0);
+ ValueRef val = args.at(0).deref(0, ty);
+
+ size_t fallback = SIZE_MAX;
+ size_t found_index = SIZE_MAX;
+ assert(ty.composite_type);
+ for(size_t i = 0; i < ty.composite_type->variants.size(); i ++)
+ {
+ const auto& var = ty.composite_type->variants[i];
+ if( var.tag_data.size() == 0 )
+ {
+ // Only seen in Option<NonNull>
+ assert(fallback == SIZE_MAX);
+ fallback = i;
+ }
+ else
+ {
+ // Get offset to the tag
+ ::HIR::TypeRef tag_ty;
+ size_t tag_ofs = ty.get_field_ofs(var.base_field, var.field_path, tag_ty);
+ // Compare
+ if( val.compare(tag_ofs, var.tag_data.data(), var.tag_data.size()) == 0 )
+ {
+ found_index = i;
+ break ;
+ }
+ }
+ }
+
+ if( found_index == SIZE_MAX )
+ {
+ LOG_ASSERT(fallback != SIZE_MAX, "Can't find variant of " << ty << " for " << val);
+ found_index = fallback;
+ }
+
+ rv = Value::new_usize(found_index);
+ }
else if( name == "atomic_fence" || name == "atomic_fence_acq" )
{
rv = Value();
@@ -2192,7 +2234,7 @@ bool InterpreterThread::call_intrinsic(Value& rv, const RcString& name, const ::
rv = Value::with_size( ty_T.get_size() + 1, false );
rv.write_value(0, data_ref.read_value(0, old_v.size()));
LOG_DEBUG("> *ptr = " << data_ref);
- if( data_ref.compare(old_v.data_ptr(), old_v.size()) == true ) {
+ if( data_ref.compare(0, old_v.data_ptr(), old_v.size()) == true ) {
data_ref.m_alloc.alloc().write_value( data_ref.m_offset, new_v );
rv.write_u8( old_v.size(), 1 );
}
diff --git a/tools/standalone_miri/value.cpp b/tools/standalone_miri/value.cpp
index 3fb4c238..363d980b 100644
--- a/tools/standalone_miri/value.cpp
+++ b/tools/standalone_miri/value.cpp
@@ -309,6 +309,10 @@ ValueRef ValueCommonRead::read_pointer_valref_mut(size_t rd_ofs, size_t size)
return ValueRef(reloc, ofs, size);
}
}
+ValueRef ValueCommonRead::deref(size_t ofs, const ::HIR::TypeRef& ty)
+{
+ return read_pointer_valref_mut(ofs, ty.get_size());
+}
void Allocation::resize(size_t new_size)
@@ -991,8 +995,8 @@ Value ValueRef::read_value(size_t ofs, size_t size) const
return m_value->read_value(m_offset + ofs, size);
}
}
-bool ValueRef::compare(const void* other, size_t other_len) const
+bool ValueRef::compare(size_t offset, const void* other, size_t other_len) const
{
- check_bytes_valid(0, other_len);
- return ::std::memcmp(data_ptr(), other, other_len) == 0;
+ check_bytes_valid(offset, other_len);
+ return ::std::memcmp(data_ptr() + offset, other, other_len) == 0;
}
diff --git a/tools/standalone_miri/value.hpp b/tools/standalone_miri/value.hpp
index e8567d02..5e5ccc4f 100644
--- a/tools/standalone_miri/value.hpp
+++ b/tools/standalone_miri/value.hpp
@@ -201,6 +201,9 @@ struct ValueCommonRead
uint64_t read_usize(size_t ofs) const;
int64_t read_isize(size_t ofs) const { return static_cast<int64_t>(read_usize(ofs)); }
+ /// De-reference a pointer (of target type `ty`) at the given offset, and return a reference to it
+ ValueRef deref(size_t ofs, const ::HIR::TypeRef& ty);
+
/// Read a pointer from the value, requiring at least `req_valid` valid bytes, saves avaliable space in `size`
void* read_pointer_unsafe(size_t rd_ofs, size_t req_valid, size_t& size, bool& is_mut) const;
/// Read a pointer, requiring `req_len` valid bytes
@@ -515,6 +518,6 @@ struct ValueRef:
}
}
- bool compare(const void* other, size_t other_len) const;
+ bool compare(size_t offset, const void* other, size_t other_len) const;
};
extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v);