summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-08-16 18:46:31 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-08-16 18:46:31 +0800
commit096831d89d1f70db1cf7b62fb61a763a6b1a6890 (patch)
tree0cd7be9e22f4ea143c4f4b26f23785050f45ee9c /tools
parent18c3d284a6c5bce86f72fbff64e98d3db9a306a9 (diff)
downloadmrust-096831d89d1f70db1cf7b62fb61a763a6b1a6890.tar.gz
Standalone MIRI - More u128, general improvements in running a proc macro
Diffstat (limited to 'tools')
-rw-r--r--tools/standalone_miri/miri.cpp101
-rw-r--r--tools/standalone_miri/u128.hpp155
-rw-r--r--tools/standalone_miri/value.hpp2
3 files changed, 244 insertions, 14 deletions
diff --git a/tools/standalone_miri/miri.cpp b/tools/standalone_miri/miri.cpp
index 97343714..55ac81bb 100644
--- a/tools/standalone_miri/miri.cpp
+++ b/tools/standalone_miri/miri.cpp
@@ -341,6 +341,7 @@ struct MirHelpers
auto len = vr.m_metadata->read_usize(0);
LOG_ASSERT(idx < len, "Slice index out of range");
vr.m_offset += ty.get_size() * idx;
+ vr.m_metadata.reset();
}
else
{
@@ -433,8 +434,8 @@ struct MirHelpers
LOG_DEBUG("sizeof(" << ty << ") = " << ty.get_size());
LOG_ASSERT(vr.m_size == POINTER_SIZE, "Deref of a value that isn't a pointer-sized value (size=" << vr << ") - " << vr << ": " << ptr_ty);
size = ty.get_size();
- if( !alloc ) {
- LOG_ERROR("Deref of a value with no relocation - " << vr);
+ if( !alloc && size > 0 ) {
+ LOG_ERROR("Deref of a non-ZST pointer with no relocation - " << vr);
}
}
@@ -502,7 +503,11 @@ struct MirHelpers
ty = ::HIR::TypeRef(ce.t);
Value val = Value(ty);
val.write_bytes(0, &ce.v, ::std::min(ty.get_size(), sizeof(ce.v))); // TODO: Endian
- // TODO: i128/u128 need the upper bytes cleared+valid
+ // i128/u128 need the upper bytes cleared+valid
+ if( ce.t.raw_type == RawType::U128 ) {
+ uint64_t zero = 0;
+ val.write_bytes(8, &zero, 8);
+ }
return val;
} break;
TU_ARM(c, Bool, ce) {
@@ -799,8 +804,8 @@ bool InterpreterThread::step_one(Value& out_thread_result)
case RawType::Bool: throw "ERROR";
case RawType::F32: throw "BUG";
case RawType::F64: dst_val = static_cast<float>( src_value.read_f64(0) ); break;
- case RawType::USize: throw "TODO";// /*dst_val = src_value.read_usize();*/ break;
- case RawType::ISize: throw "TODO";// /*dst_val = src_value.read_isize();*/ break;
+ case RawType::USize: LOG_TODO("f32 from " << src_ty);// /*dst_val = src_value.read_usize();*/ break;
+ case RawType::ISize: LOG_TODO("f32 from " << src_ty);// /*dst_val = src_value.read_isize();*/ break;
case RawType::U8: dst_val = static_cast<float>( src_value.read_u8 (0) ); break;
case RawType::I8: dst_val = static_cast<float>( src_value.read_i8 (0) ); break;
case RawType::U16: dst_val = static_cast<float>( src_value.read_u16(0) ); break;
@@ -809,8 +814,8 @@ bool InterpreterThread::step_one(Value& out_thread_result)
case RawType::I32: dst_val = static_cast<float>( src_value.read_i32(0) ); break;
case RawType::U64: dst_val = static_cast<float>( src_value.read_u64(0) ); break;
case RawType::I64: dst_val = static_cast<float>( src_value.read_i64(0) ); break;
- case RawType::U128: throw "TODO";// /*dst_val = src_value.read_u128();*/ break;
- case RawType::I128: throw "TODO";// /*dst_val = src_value.read_i128();*/ break;
+ case RawType::U128: LOG_TODO("f32 from " << src_ty);// /*dst_val = src_value.read_u128();*/ break;
+ case RawType::I128: LOG_TODO("f32 from " << src_ty);// /*dst_val = src_value.read_i128();*/ break;
}
new_val.write_f32(0, dst_val);
} break;
@@ -990,6 +995,13 @@ bool InterpreterThread::step_one(Value& out_thread_result)
if(0)
case RawType::I64:
dst_val = static_cast<uint64_t>( src_value.read_i64(0) );
+ if(0)
+ case RawType::U128:
+ dst_val = static_cast<uint64_t>( src_value.read_u128(0) );
+ if(0)
+ case RawType::I128:
+ LOG_TODO("Cast i128 to " << re.type);
+ //dst_val = static_cast<uint64_t>( src_value.read_i128(0) );
switch(re.type.inner_type)
{
@@ -1027,13 +1039,20 @@ bool InterpreterThread::step_one(Value& out_thread_result)
throw "";
}
break;
- case RawType::U128: throw "TODO"; /*dst_val = src_value.read_u128();*/ break;
- case RawType::I128: throw "TODO"; /*dst_val = src_value.read_i128();*/ break;
}
} break;
case RawType::U128:
- case RawType::I128:
- LOG_TODO("Cast to " << re.type);
+ case RawType::I128: {
+ U128 dst_val;
+ switch(src_ty.inner_type)
+ {
+ case RawType::U8: dst_val = src_value.read_u8 (0); break;
+ case RawType::I8: dst_val = src_value.read_i8 (0); break;
+ default:
+ LOG_TODO("Cast " << src_ty << " to " << re.type);
+ }
+ new_val.write_u128(0, dst_val);
+ } break;
}
}
} break;
@@ -1150,6 +1169,8 @@ bool InterpreterThread::step_one(Value& out_thread_result)
case RawType::ISize: res = res != 0 ? res : Ops::do_compare(v_l.read_isize(0), v_r.read_isize(0)); break;
case RawType::Char: res = res != 0 ? res : Ops::do_compare(v_l.read_u32(0), v_r.read_u32(0)); break;
case RawType::Bool: res = res != 0 ? res : Ops::do_compare(v_l.read_u8(0), v_r.read_u8(0)); break; // TODO: `read_bool` that checks for bool values?
+ case RawType::U128: res = res != 0 ? res : Ops::do_compare(v_l.read_u128(0), v_r.read_u128(0)); break;
+ case RawType::I128: res = res != 0 ? res : Ops::do_compare(v_l.read_i128(0), v_r.read_i128(0)); break;
default:
LOG_TODO("BinOp comparisons - " << se.src << " w/ " << ty_l);
}
@@ -1197,6 +1218,7 @@ bool InterpreterThread::step_one(Value& out_thread_result)
switch(ty_l.inner_type)
{
// TODO: U128
+ case RawType::U128: new_val.write_u128(0, Ops::do_bitwise(v_l.read_u128(0), U128(shift), re.op)); break;
case RawType::U64: new_val.write_u64(0, Ops::do_bitwise(v_l.read_u64(0), static_cast<uint64_t>(shift), re.op)); break;
case RawType::U32: new_val.write_u32(0, Ops::do_bitwise(v_l.read_u32(0), static_cast<uint32_t>(shift), re.op)); break;
case RawType::U16: new_val.write_u16(0, Ops::do_bitwise(v_l.read_u16(0), static_cast<uint16_t>(shift), re.op)); break;
@@ -1217,7 +1239,10 @@ bool InterpreterThread::step_one(Value& out_thread_result)
new_val = Value(ty_l);
switch(ty_l.inner_type)
{
- // TODO: U128/I128
+ case RawType::U128:
+ case RawType::I128:
+ new_val.write_u128( 0, Ops::do_bitwise(v_l.read_u128(0), v_r.read_u128(0), re.op) );
+ break;
case RawType::U64:
case RawType::I64:
new_val.write_u64( 0, Ops::do_bitwise(v_l.read_u64(0), v_r.read_u64(0), re.op) );
@@ -1621,6 +1646,7 @@ bool InterpreterThread::step_one(Value& out_thread_result)
case RawType::U64: switch_val = v.read_u64(0); break;
case RawType::U128: LOG_TODO("Terminator::SwitchValue::Unsigned with u128");
case RawType::USize: switch_val = v.read_usize(0); break;
+ case RawType::Char: switch_val = v.read_u32(0); break;
default:
LOG_ERROR("Terminator::SwitchValue::Unsigned with unexpected type - " << ty);
}
@@ -1913,7 +1939,7 @@ bool InterpreterThread::call_extern(Value& rv, const ::std::string& link_name, c
return reinterpret_cast<const char*>(v.read_pointer_const(0, len + 1)); // Final read will trigger an error if the NUL isn't there
}
};
- if( link_name == "__rust_allocate" || link_name == "__rust_alloc" )
+ if( link_name == "__rust_allocate" || link_name == "__rust_alloc" || link_name == "__rust_alloc_zeroed" )
{
static unsigned s_alloc_count = 0;
@@ -1921,11 +1947,16 @@ bool InterpreterThread::call_extern(Value& rv, const ::std::string& link_name, c
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 << "): name=" << alloc_name);
+ LOG_DEBUG(link_name << "(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 );
+ if( link_name == "__rust_alloc_zeroed" )
+ {
+ alloc->mark_bytes_valid(0, size);
+ }
+
// TODO: Use the alignment when making an allocation?
rv = Value::new_pointer(rty, Allocation::PTR_BASE, RelocationPtr::new_alloc(::std::move(alloc)));
}
@@ -2412,6 +2443,23 @@ bool InterpreterThread::call_extern(Value& rv, const ::std::string& link_name, c
{
rv = Value::new_i32(-1);
}
+ else if( link_name == "memcmp" )
+ {
+ auto n = args.at(2).read_usize(0);
+ int rv_i;
+ if( n > 0 )
+ {
+ const void* ptr_b = args.at(1).read_pointer_const(0, n);
+ const void* ptr_a = args.at(0).read_pointer_const(0, n);
+
+ rv_i = memcmp(ptr_a, ptr_b, n);
+ }
+ else
+ {
+ rv_i = 0;
+ }
+ rv = Value::new_i32(rv_i);
+ }
// - `void *memchr(const void *s, int c, size_t n);`
else if( link_name == "memchr" )
{
@@ -2696,6 +2744,31 @@ bool InterpreterThread::call_intrinsic(Value& rv, const RcString& name, const ::
rv = ::std::move(args.at(0));
rv.write_ptr(0, Allocation::PTR_BASE + new_ofs, ptr_alloc);
}
+ else if( name == "arith_offset" ) // Doesn't check validity, and allows wrapping
+ {
+ auto ptr_alloc = args.at(0).get_relocation(0);
+ auto ptr_ofs = args.at(0).read_usize(0);
+ //LOG_ASSERT(ptr_ofs >= Allocation::PTR_BASE, "`offset` with invalid pointer - " << args.at(0));
+ //ptr_ofs -= Allocation::PTR_BASE;
+ auto& ofs_val = args.at(1);
+
+ auto delta_counts = ofs_val.read_usize(0);
+ auto new_ofs = ptr_ofs + delta_counts * ty_params.tys.at(0).get_size();
+ if(POINTER_SIZE != 8) {
+ new_ofs &= 0xFFFFFFFF;
+ }
+ //new_ofs += Allocation::PTR_BASE;
+
+ rv = ::std::move(args.at(0));
+ if( ptr_alloc )
+ {
+ rv.write_ptr(0, new_ofs, ptr_alloc);
+ }
+ else
+ {
+ rv.write_usize(0, new_ofs);
+ }
+ }
// effectively ptr::write
else if( name == "move_val_init" )
{
diff --git a/tools/standalone_miri/u128.hpp b/tools/standalone_miri/u128.hpp
index 03c004d9..8403b94a 100644
--- a/tools/standalone_miri/u128.hpp
+++ b/tools/standalone_miri/u128.hpp
@@ -2,9 +2,126 @@
class U128
{
+ friend class I128;
uint64_t lo, hi;
public:
U128(): lo(0), hi(0) {}
+
+ U128(uint8_t v): lo(v), hi(0) {}
+ U128(int8_t v): lo(v), hi(v < 0 ? -1 : 0) {}
+
+ void fmt(::std::ostream& os) const { os << hi << ":" << lo; }
+
+ int cmp(U128 v) const {
+ if( hi != v.hi ) {
+ return (hi < v.hi ? -1 : 1);
+ }
+ if( lo != v.lo ) {
+ return (lo < v.lo ? -1 : 1);
+ }
+ return 0;
+ }
+ int cmp(unsigned v) const {
+ if(hi)
+ return 1;
+ if(lo < v)
+ return -1;
+ if(lo > v)
+ return 1;
+ return 0;
+ }
+
+ template<typename T> bool operator< (const T& v) const { return this->cmp(v) < 0; }
+ template<typename T> bool operator<=(const T& v) const { return this->cmp(v) <= 0; }
+ template<typename T> bool operator> (const T& v) const { return this->cmp(v) > 0; }
+ template<typename T> bool operator>=(const T& v) const { return this->cmp(v) >= 0; }
+ template<typename T> bool operator==(const T& v) const { return this->cmp(v) == 0; }
+ template<typename T> bool operator!=(const T& v) const { return this->cmp(v) != 0; }
+
+ operator uint8_t() const { return static_cast<uint8_t>(lo); }
+
+ U128 operator&(U128 x) const {
+ U128 rv;
+ rv.lo = this->lo & x.lo;
+ rv.hi = this->hi & x.hi;
+ return rv;
+ }
+ U128 operator|(U128 x) const {
+ U128 rv;
+ rv.lo = this->lo | x.lo;
+ rv.hi = this->hi | x.hi;
+ return rv;
+ }
+ U128 operator^(U128 x) const {
+ U128 rv;
+ rv.lo = this->lo ^ x.lo;
+ rv.hi = this->hi ^ x.hi;
+ return rv;
+ }
+
+ U128 operator<<(U128 n) const
+ {
+ if( n < 128 )
+ {
+ return *this << static_cast<uint8_t>(n);
+ }
+ else
+ {
+ return U128();
+ }
+ }
+ U128 operator<<(uint8_t n) const
+ {
+ if(n == 0)
+ {
+ return *this;
+ }
+ else if( n < 64 )
+ {
+ U128 rv;
+ rv.lo = lo << n;
+ rv.hi = (hi << n) | (lo >> (64-n));
+ return rv;
+ }
+ else if( n < 128 )
+ {
+ U128 rv;
+ rv.lo = 0;
+ rv.hi = (lo << (n-64));
+ return rv;
+ }
+ else
+ {
+ return U128();
+ }
+ }
+ U128 operator>>(uint8_t n) const
+ {
+ if(n == 0)
+ {
+ return *this;
+ }
+ else if( n < 64 )
+ {
+ U128 rv;
+ rv.lo = (lo >> n) | (hi << (64-n));
+ rv.hi = (hi >> n);
+ return rv;
+ }
+ else if( n < 128 )
+ {
+ U128 rv;
+ rv.lo = (hi >> (n-64));
+ rv.hi = 0;
+ return rv;
+ }
+ else
+ {
+ return U128();
+ }
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const U128& x) { x.fmt(os); return os; }
};
class I128
@@ -12,4 +129,42 @@ class I128
U128 v;
public:
I128() {}
+
+ int cmp(I128 x) const {
+ if(v.hi != x.v.hi)
+ return (static_cast<int64_t>(v.hi) < static_cast<int64_t>(x.v.hi) ? -1 : 1);
+ if(v.lo != x.v.lo)
+ {
+ if( static_cast<int64_t>(v.hi) < 0 )
+ {
+ // Negative, so larger raw value is the smaller
+ return (v.lo > x.v.lo ? -1 : 1);
+ }
+ else
+ {
+ return (v.lo < x.v.lo ? -1 : 1);
+ }
+ }
+ return 0;
+ }
+ //int cmp(int v) const {
+ // if(hi)
+ // return 1;
+ // if(lo < v)
+ // return -1;
+ // if(lo > v)
+ // return 1;
+ // return 0;
+ //}
+
+ template<typename T> bool operator< (const T& v) const { return this->cmp(v) < 0; }
+ template<typename T> bool operator<=(const T& v) const { return this->cmp(v) <= 0; }
+ template<typename T> bool operator> (const T& v) const { return this->cmp(v) > 0; }
+ template<typename T> bool operator>=(const T& v) const { return this->cmp(v) >= 0; }
+ template<typename T> bool operator==(const T& v) const { return this->cmp(v) == 0; }
+ template<typename T> bool operator!=(const T& v) const { return this->cmp(v) != 0; }
+
+ void fmt(::std::ostream& os) const { os << v.hi << ":" << v.lo; }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const I128& x) { x.fmt(os); return os; }
};
diff --git a/tools/standalone_miri/value.hpp b/tools/standalone_miri/value.hpp
index 764df8fa..dea4c890 100644
--- a/tools/standalone_miri/value.hpp
+++ b/tools/standalone_miri/value.hpp
@@ -235,10 +235,12 @@ struct ValueCommonWrite:
void write_u16(size_t ofs, uint16_t v) { write_bytes(ofs, &v, 2); }
void write_u32(size_t ofs, uint32_t v) { write_bytes(ofs, &v, 4); }
void write_u64(size_t ofs, uint64_t v) { write_bytes(ofs, &v, 8); }
+ void write_u128(size_t ofs, U128 v) { write_bytes(ofs, &v, 16); }
void write_i8 (size_t ofs, int8_t v) { write_u8 (ofs, static_cast<uint8_t >(v)); }
void write_i16(size_t ofs, int16_t v) { write_u16(ofs, static_cast<uint16_t>(v)); }
void write_i32(size_t ofs, int32_t v) { write_u32(ofs, static_cast<uint32_t>(v)); }
void write_i64(size_t ofs, int64_t v) { write_u64(ofs, static_cast<uint64_t>(v)); }
+ void write_i128(size_t ofs, I128 v) { write_bytes(ofs, &v, 16); }
void write_f32(size_t ofs, float v) { write_bytes(ofs, &v, 4); }
void write_f64(size_t ofs, double v) { write_bytes(ofs, &v, 8); }
void write_usize(size_t ofs, uint64_t v);