summaryrefslogtreecommitdiff
path: root/tools/standalone_miri/value.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/standalone_miri/value.cpp')
-rw-r--r--tools/standalone_miri/value.cpp445
1 files changed, 316 insertions, 129 deletions
diff --git a/tools/standalone_miri/value.cpp b/tools/standalone_miri/value.cpp
index beff8a38..cf378077 100644
--- a/tools/standalone_miri/value.cpp
+++ b/tools/standalone_miri/value.cpp
@@ -1,6 +1,10 @@
-//
-//
-//
+/*
+ * mrustc Standalone MIRI
+ * - by John Hodge (Mutabah)
+ *
+ * value.cpp
+ * - Runtime values
+ */
#include "value.hpp"
#include "hir_sim.hpp"
#include "module_tree.hpp"
@@ -9,49 +13,79 @@
#include <algorithm>
#include "debug.hpp"
-AllocationPtr Allocation::new_alloc(size_t size)
+AllocationHandle Allocation::new_alloc(size_t size)
{
Allocation* rv = new Allocation();
rv->refcount = 1;
rv->data.resize( (size + 8-1) / 8 ); // QWORDS
rv->mask.resize( (size + 8-1) / 8 ); // bitmap bytes
//LOG_DEBUG(rv << " ALLOC");
- return AllocationPtr(rv);
+ return AllocationHandle(rv);
}
-AllocationPtr AllocationPtr::new_fcn(::HIR::Path p)
+AllocationHandle::AllocationHandle(const AllocationHandle& x):
+ m_ptr(x.m_ptr)
{
- AllocationPtr rv;
+ if( m_ptr )
+ {
+ assert(m_ptr->refcount != 0);
+ assert(m_ptr->refcount != SIZE_MAX);
+ m_ptr->refcount += 1;
+ //LOG_DEBUG(m_ptr << " REF++ " << m_ptr->refcount);
+ }
+}
+AllocationHandle::~AllocationHandle()
+{
+ if( m_ptr )
+ {
+ m_ptr->refcount -= 1;
+ //LOG_DEBUG(m_ptr << " REF-- " << m_ptr->refcount);
+ if(m_ptr->refcount == 0)
+ {
+ delete m_ptr;
+ }
+ }
+}
+
+RelocationPtr RelocationPtr::new_alloc(AllocationHandle alloc)
+{
+ RelocationPtr rv;
+ auto* ptr = alloc.m_ptr;
+ alloc.m_ptr = nullptr;
+ rv.m_ptr = reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(ptr) + static_cast<uintptr_t>(Ty::Allocation) );
+ return rv;
+}
+RelocationPtr RelocationPtr::new_fcn(::HIR::Path p)
+{
+ RelocationPtr rv;
auto* ptr = new ::HIR::Path(::std::move(p));
rv.m_ptr = reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(ptr) + static_cast<uintptr_t>(Ty::Function) );
return rv;
}
-AllocationPtr AllocationPtr::new_string(const ::std::string* ptr)
+RelocationPtr RelocationPtr::new_string(const ::std::string* ptr)
{
- AllocationPtr rv;
+ RelocationPtr rv;
rv.m_ptr = reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(ptr) + static_cast<uintptr_t>(Ty::StdString) );
return rv;
}
-AllocationPtr AllocationPtr::new_ffi(FFIPointer info)
+RelocationPtr RelocationPtr::new_ffi(FFIPointer info)
{
- AllocationPtr rv;
+ RelocationPtr rv;
auto* ptr = new FFIPointer(info);
rv.m_ptr = reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(ptr) + static_cast<uintptr_t>(Ty::FfiPointer) );
return rv;
}
-AllocationPtr::AllocationPtr(const AllocationPtr& x):
+RelocationPtr::RelocationPtr(const RelocationPtr& x):
m_ptr(nullptr)
{
if( x )
{
switch(x.get_ty())
{
- case Ty::Allocation:
- m_ptr = x.m_ptr;
- assert(alloc().refcount != 0);
- assert(alloc().refcount != SIZE_MAX);
- alloc().refcount += 1;
- //LOG_DEBUG(&alloc() << " REF++ " << alloc().refcount);
- break;
+ case Ty::Allocation: {
+ auto tmp = AllocationHandle( reinterpret_cast<Allocation*>(x.get_ptr()) );
+ *this = RelocationPtr::new_alloc(tmp);
+ tmp.m_ptr = nullptr;
+ } break;
case Ty::Function: {
auto ptr_i = reinterpret_cast<uintptr_t>(new ::HIR::Path(x.fcn()));
assert( (ptr_i & 3) == 0 );
@@ -75,21 +109,15 @@ AllocationPtr::AllocationPtr(const AllocationPtr& x):
m_ptr = nullptr;
}
}
-AllocationPtr::~AllocationPtr()
+RelocationPtr::~RelocationPtr()
{
if( *this )
{
switch(get_ty())
{
- case Ty::Allocation: {
- auto* ptr = &alloc();
- ptr->refcount -= 1;
- //LOG_DEBUG(&alloc() << " REF-- " << ptr->refcount);
- if(ptr->refcount == 0)
- {
- delete ptr;
- }
- } break;
+ case Ty::Allocation:
+ (void)AllocationHandle( reinterpret_cast<Allocation*>(get_ptr()) );
+ break;
case Ty::Function: {
auto* ptr = const_cast<::HIR::Path*>(&fcn());
delete ptr;
@@ -104,7 +132,7 @@ AllocationPtr::~AllocationPtr()
}
}
}
-size_t AllocationPtr::get_size() const
+size_t RelocationPtr::get_size() const
{
if( !*this )
return 0;
@@ -123,22 +151,22 @@ size_t AllocationPtr::get_size() const
throw "Unreachable";
}
-::std::ostream& operator<<(::std::ostream& os, const AllocationPtr& x)
+::std::ostream& operator<<(::std::ostream& os, const RelocationPtr& x)
{
if( x )
{
switch(x.get_ty())
{
- case AllocationPtr::Ty::Allocation:
+ case RelocationPtr::Ty::Allocation:
os << &x.alloc();
break;
- case AllocationPtr::Ty::Function:
+ case RelocationPtr::Ty::Function:
os << x.fcn();
break;
- case AllocationPtr::Ty::StdString:
+ case RelocationPtr::Ty::StdString:
os << "\"" << x.str() << "\"";
break;
- case AllocationPtr::Ty::FfiPointer:
+ case RelocationPtr::Ty::FfiPointer:
os << "FFI " << x.ffi().source_function << " " << x.ffi().ptr_value;
break;
}
@@ -150,9 +178,93 @@ size_t AllocationPtr::get_size() const
return os;
}
+uint64_t ValueCommonRead::read_usize(size_t ofs) const
+{
+ uint64_t v = 0;
+ this->read_bytes(ofs, &v, POINTER_SIZE);
+ return v;
+}
+void ValueCommonWrite::write_usize(size_t ofs, uint64_t v)
+{
+ this->write_bytes(ofs, &v, POINTER_SIZE);
+}
+void* ValueCommonRead::read_pointer_unsafe(size_t rd_ofs, size_t req_valid, size_t& out_size, bool& out_is_mut) const
+{
+ auto ofs = read_usize(rd_ofs);
+ auto reloc = get_relocation(rd_ofs);
+ if( !reloc )
+ {
+ if( ofs != 0 ) {
+ LOG_FATAL("Read a non-zero offset with no relocation");
+ }
+ if( req_valid > 0 ) {
+ LOG_ERROR("Attempting to read a null pointer");
+ }
+ out_is_mut = false;
+ out_size = 0;
+ return nullptr;
+ }
+ else
+ {
+ switch(reloc.get_ty())
+ {
+ case RelocationPtr::Ty::Allocation: {
+ auto& a = reloc.alloc();
+ if( ofs > a.size() )
+ LOG_FATAL("Out-of-bounds pointer");
+ if( ofs + req_valid > a.size() )
+ LOG_FATAL("Out-of-bounds pointer (" << ofs << " + " << req_valid << " > " << a.size());
+ a.check_bytes_valid( ofs, req_valid );
+ out_size = a.size() - ofs;
+ out_is_mut = true;
+ return a.data_ptr() + ofs;
+ }
+ case RelocationPtr::Ty::StdString: {
+ const auto& s = reloc.str();
+ if( ofs > s.size() )
+ LOG_FATAL("Out-of-bounds pointer");
+ if( ofs + req_valid > s.size() )
+ LOG_FATAL("Out-of-bounds pointer (" << ofs << " + " << req_valid << " > " << s.size());
+ out_size = s.size() - ofs;
+ out_is_mut = false;
+ return const_cast<void*>( static_cast<const void*>(s.data() + ofs) );
+ }
+ case RelocationPtr::Ty::Function:
+ LOG_FATAL("read_pointer w/ function");
+ case RelocationPtr::Ty::FfiPointer: {
+ const auto& f = reloc.ffi();
+ // TODO: Validity?
+ //if( req_valid )
+ // LOG_FATAL("Can't request valid data from a FFI pointer");
+ // TODO: Have an idea of mutability and available size from FFI
+ out_size = f.size - ofs;
+ out_is_mut = false;
+ return reloc.ffi().ptr_value + ofs;
+ }
+ }
+ throw "";
+ }
+}
+ValueRef ValueCommonRead::read_pointer_valref_mut(size_t rd_ofs, size_t size)
+{
+ auto ofs = read_usize(rd_ofs);
+ auto reloc = get_relocation(rd_ofs);
+ if( !reloc )
+ {
+ LOG_ERROR("Getting ValRef to null pointer (no relocation)");
+ }
+ else
+ {
+ // TODO: Validate size
+ return ValueRef(reloc, ofs, size);
+ }
+}
+
void Allocation::resize(size_t new_size)
{
+ if( this->is_freed )
+ LOG_ERROR("Use of freed memory " << this);
//size_t old_size = this->size();
//size_t extra_bytes = (new_size > old_size ? new_size - old_size : 0);
@@ -167,9 +279,9 @@ void Allocation::check_bytes_valid(size_t ofs, size_t size) const
}
for(size_t i = ofs; i < ofs + size; i++)
{
- if( !(this->mask[i/8] & (1 << i%8)) )
+ if( !(this->mask[i/8] & (1 << (i%8))) )
{
- ::std::cerr << "ERROR: Invalid bytes in value" << ::std::endl;
+ LOG_ERROR("Invalid bytes in value - " << ofs << "+" << size << " - " << *this);
throw "ERROR";
}
}
@@ -179,14 +291,18 @@ void Allocation::mark_bytes_valid(size_t ofs, size_t size)
assert( ofs+size <= this->mask.size() * 8 );
for(size_t i = ofs; i < ofs + size; i++)
{
- this->mask[i/8] |= (1 << i%8);
+ this->mask[i/8] |= (1 << (i%8));
}
}
Value Allocation::read_value(size_t ofs, size_t size) const
{
Value rv;
+ TRACE_FUNCTION_R("Allocation::read_value " << this << " " << ofs << "+" << size, *this << " | " << rv);
+ if( this->is_freed )
+ LOG_ERROR("Use of freed memory " << this);
+ LOG_DEBUG(*this);
- // TODO: Determine if this can become an inline allocation.
+ // Determine if this can become an inline allocation.
bool has_reloc = false;
for(const auto& r : this->relocations)
{
@@ -205,7 +321,7 @@ Value Allocation::read_value(size_t ofs, size_t size) const
{
if( ofs <= r.slot_ofs && r.slot_ofs < ofs + size )
{
- rv.allocation.alloc().relocations.push_back({ r.slot_ofs - ofs, r.backing_alloc });
+ rv.allocation->relocations.push_back({ r.slot_ofs - ofs, r.backing_alloc });
}
}
@@ -213,14 +329,12 @@ Value Allocation::read_value(size_t ofs, size_t size) const
for(size_t i = 0; i < size; i ++)
{
size_t j = ofs + i;
- bool v = (this->mask[j/8] & (1 << j%8)) != 0;
+ const uint8_t test_mask = (1 << (j%8));
+ const uint8_t set_mask = (1 << (i%8));
+ bool v = (this->mask[j/8] & test_mask) != 0;
if( v )
{
- rv.allocation.alloc().mask[i/8] |= (1 << i%8);
- }
- else
- {
- rv.allocation.alloc().mask[i/8] &= ~(1 << i%8);
+ rv.allocation->mask[i/8] |= set_mask;
}
}
}
@@ -236,21 +350,23 @@ Value Allocation::read_value(size_t ofs, size_t size) const
for(size_t i = 0; i < size; i ++)
{
size_t j = ofs + i;
- bool v = (this->mask[j/8] & (1 << j%8)) != 0;
+ const uint8_t tst_mask = 1 << (j%8);
+ const uint8_t set_mask = 1 << (i%8);
+ bool v = (this->mask[j/8] & tst_mask) != 0;
if( v )
{
- rv.direct_data.mask[i/8] |= (1 << i%8);
+ rv.direct_data.mask[i/8] |= set_mask;
}
- //else
- //{
- // rv.direct_data.mask[i/8] &= ~(1 << i%8);
- //}
}
}
return rv;
}
void Allocation::read_bytes(size_t ofs, void* dst, size_t count) const
{
+ if( this->is_freed )
+ LOG_ERROR("Use of freed memory " << this);
+
+ LOG_DEBUG("Allocation::read_bytes " << this << " " << ofs << "+" << count);
if(count == 0)
return ;
@@ -273,10 +389,15 @@ void Allocation::read_bytes(size_t ofs, void* dst, size_t count) const
}
void Allocation::write_value(size_t ofs, Value v)
{
+ TRACE_FUNCTION_R("Allocation::write_value " << this << " " << ofs << "+" << v.size() << " " << v, *this);
+ if( this->is_freed )
+ LOG_ERROR("Use of freed memory " << this);
+ //if( this->is_read_only )
+ // LOG_ERROR("Writing to read-only allocation " << this);
if( v.allocation )
{
- size_t v_size = v.allocation.alloc().size();
- const auto& src_alloc = v.allocation.alloc();
+ size_t v_size = v.allocation->size();
+ const auto& src_alloc = *v.allocation;
// Take a copy of the source mask
auto s_mask = src_alloc.mask;
@@ -337,8 +458,15 @@ void Allocation::write_value(size_t ofs, Value v)
}
void Allocation::write_bytes(size_t ofs, const void* src, size_t count)
{
+ //LOG_DEBUG("Allocation::write_bytes " << this << " " << ofs << "+" << count);
+ if( this->is_freed )
+ LOG_ERROR("Use of freed memory " << this);
+ //if( this->is_read_only )
+ // LOG_ERROR("Writing to read-only allocation " << this);
+
if(count == 0)
return ;
+ TRACE_FUNCTION_R("Allocation::write_bytes " << this << " " << ofs << "+" << count, *this);
if(ofs >= this->size() ) {
LOG_ERROR("Out of bounds write, " << ofs << "+" << count << " > " << this->size());
throw "ERROR";
@@ -371,9 +499,10 @@ void Allocation::write_bytes(size_t ofs, const void* src, size_t count)
::std::memcpy(this->data_ptr() + ofs, src, count);
mark_bytes_valid(ofs, count);
}
-void Allocation::write_usize(size_t ofs, uint64_t v)
+void Allocation::write_ptr(size_t ofs, size_t ptr_ofs, RelocationPtr reloc)
{
- this->write_bytes(ofs, &v, POINTER_SIZE);
+ this->write_usize(ofs, ptr_ofs);
+ this->relocations.push_back(Relocation { ofs, /*POINTER_SIZE,*/ ::std::move(reloc) });
}
::std::ostream& operator<<(::std::ostream& os, const Allocation& x)
{
@@ -384,7 +513,7 @@ void Allocation::write_usize(size_t ofs, uint64_t v)
if( i != 0 )
os << " ";
- if( x.mask[i/8] & (1 << i%8) )
+ if( x.mask[i/8] & (1 << (i%8)) )
{
os << ::std::setw(2) << ::std::setfill('0') << (int)x.data_ptr()[i];
}
@@ -416,38 +545,12 @@ Value::Value()
Value::Value(::HIR::TypeRef ty)
{
size_t size = ty.get_size();
-#if 1
+
// Support inline data if the data will fit within the inline region (which is the size of the metadata)
if( ty.get_size() <= sizeof(this->direct_data.data) )
{
- struct H
- {
- static bool has_pointer(const ::HIR::TypeRef& ty)
- {
- if( ty.wrappers.empty() || ::std::all_of(ty.wrappers.begin(), ty.wrappers.end(), [](const auto& x){ return x.type == TypeWrapper::Ty::Array; }) )
- {
- // TODO: Function pointers should be _pointers_
- if( ty.inner_type == RawType::Function )
- {
- return true;
- }
- // Check the inner type
- if( ty.inner_type != RawType::Composite )
- {
- return false;
- }
- // Still not sure, check the inner for any pointers.
- for(const auto& fld : ty.composite_type->fields)
- {
- if( H::has_pointer(fld.second) )
- return true;
- }
- return false;
- }
- return true;
- }
- };
- if( ! H::has_pointer(ty) )
+ // AND the type doesn't contain a pointer (of any kind)
+ if( ! ty.has_pointer() )
{
// Will fit in a inline allocation, nice.
//LOG_TRACE("No pointers in " << ty << ", storing inline");
@@ -457,7 +560,6 @@ Value::Value(::HIR::TypeRef ty)
return ;
}
}
-#endif
// Fallback: Make a new allocation
//LOG_TRACE(" Creating allocation for " << ty);
@@ -482,18 +584,46 @@ Value Value::new_fnptr(const ::HIR::Path& fn_path)
{
Value rv( ::HIR::TypeRef(::HIR::CoreType { RawType::Function }) );
assert(rv.allocation);
- rv.allocation.alloc().relocations.push_back(Relocation { 0, AllocationPtr::new_fcn(fn_path) });
- rv.allocation.alloc().data.at(0) = 0;
- rv.allocation.alloc().mask.at(0) = 0xFF; // TODO: Get pointer size and make that much valid instead of 8 bytes
+ rv.allocation->relocations.push_back(Relocation { 0, RelocationPtr::new_fcn(fn_path) });
+ rv.allocation->data.at(0) = 0;
+ rv.allocation->mask.at(0) = 0xFF; // TODO: Get pointer size and make that much valid instead of 8 bytes
return rv;
}
Value Value::new_ffiptr(FFIPointer ffi)
{
Value rv( ::HIR::TypeRef(::HIR::CoreType { RawType::USize }) );
rv.create_allocation();
- rv.allocation.alloc().relocations.push_back(Relocation { 0, AllocationPtr::new_ffi(ffi) });
- rv.allocation.alloc().data.at(0) = 0;
- rv.allocation.alloc().mask.at(0) = 0xFF; // TODO: Get pointer size and make that much valid instead of 8 bytes
+ rv.allocation->relocations.push_back(Relocation { 0, RelocationPtr::new_ffi(ffi) });
+ rv.allocation->data.at(0) = 0;
+ rv.allocation->mask.at(0) = 0xFF; // TODO: Get pointer size and make that much valid instead of 8 bytes
+ return rv;
+}
+Value Value::new_pointer(::HIR::TypeRef ty, uint64_t v, RelocationPtr r) {
+ assert(ty.get_wrapper());
+ assert(ty.get_wrapper()->type == TypeWrapper::Ty::Borrow || ty.get_wrapper()->type == TypeWrapper::Ty::Pointer);
+ Value rv(ty);
+ rv.write_usize(0, v);
+ rv.allocation->relocations.push_back(Relocation { 0, /*POINTER_SIZE,*/ ::std::move(r) });
+ return rv;
+}
+Value Value::new_usize(uint64_t v) {
+ Value rv( ::HIR::TypeRef(RawType::USize) );
+ rv.write_usize(0, v);
+ return rv;
+}
+Value Value::new_isize(int64_t v) {
+ Value rv( ::HIR::TypeRef(RawType::ISize) );
+ rv.write_isize(0, v);
+ return rv;
+}
+Value Value::new_u32(uint32_t v) {
+ Value rv( ::HIR::TypeRef(RawType::U32) );
+ rv.write_u32(0, v);
+ return rv;
+}
+Value Value::new_i32(int32_t v) {
+ Value rv( ::HIR::TypeRef(RawType::I32) );
+ rv.write_i32(0, v);
return rv;
}
@@ -502,10 +632,10 @@ void Value::create_allocation()
assert(!this->allocation);
this->allocation = Allocation::new_alloc(this->direct_data.size);
if( this->direct_data.size > 0 )
- this->allocation.alloc().mask[0] = this->direct_data.mask[0];
+ this->allocation->mask[0] = this->direct_data.mask[0];
if( this->direct_data.size > 8 )
- this->allocation.alloc().mask[1] = this->direct_data.mask[1];
- ::std::memcpy(this->allocation.alloc().data.data(), this->direct_data.data, this->direct_data.size);
+ this->allocation->mask[1] = this->direct_data.mask[1];
+ ::std::memcpy(this->allocation->data.data(), this->direct_data.data, this->direct_data.size);
}
void Value::check_bytes_valid(size_t ofs, size_t size) const
{
@@ -513,7 +643,7 @@ void Value::check_bytes_valid(size_t ofs, size_t size) const
return ;
if( this->allocation )
{
- this->allocation.alloc().check_bytes_valid(ofs, size);
+ this->allocation->check_bytes_valid(ofs, size);
}
else
{
@@ -542,7 +672,7 @@ void Value::mark_bytes_valid(size_t ofs, size_t size)
{
if( this->allocation )
{
- this->allocation.alloc().mark_bytes_valid(ofs, size);
+ this->allocation->mark_bytes_valid(ofs, size);
}
else
{
@@ -559,7 +689,7 @@ Value Value::read_value(size_t ofs, size_t size) const
//TRACE_FUNCTION_R(ofs << ", " << size << ") - " << *this, rv);
if( this->allocation )
{
- rv = this->allocation.alloc().read_value(ofs, size);
+ rv = this->allocation->read_value(ofs, size);
}
else
{
@@ -577,7 +707,7 @@ void Value::read_bytes(size_t ofs, void* dst, size_t count) const
return ;
if( this->allocation )
{
- this->allocation.alloc().read_bytes(ofs, dst, count);
+ this->allocation->read_bytes(ofs, dst, count);
}
else
{
@@ -605,7 +735,7 @@ void Value::write_bytes(size_t ofs, const void* src, size_t count)
return ;
if( this->allocation )
{
- this->allocation.alloc().write_bytes(ofs, src, count);
+ this->allocation->write_bytes(ofs, src, count);
}
else
{
@@ -626,14 +756,14 @@ void Value::write_value(size_t ofs, Value v)
{
if( this->allocation )
{
- this->allocation.alloc().write_value(ofs, ::std::move(v));
+ this->allocation->write_value(ofs, ::std::move(v));
}
else
{
- if( v.allocation && !v.allocation.alloc().relocations.empty() )
+ if( v.allocation && !v.allocation->relocations.empty() )
{
this->create_allocation();
- this->allocation.alloc().write_value(ofs, ::std::move(v));
+ this->allocation->write_value(ofs, ::std::move(v));
}
else
{
@@ -651,16 +781,20 @@ void Value::write_value(size_t ofs, Value v)
}
}
}
-void Value::write_usize(size_t ofs, uint64_t v)
+void Value::write_ptr(size_t ofs, size_t ptr_ofs, RelocationPtr reloc)
{
- this->write_bytes(ofs, &v, POINTER_SIZE);
+ if( !this->allocation )
+ {
+ LOG_ERROR("Writing a pointer with no allocation");
+ }
+ this->allocation->write_ptr(ofs, ptr_ofs, ::std::move(reloc));
}
::std::ostream& operator<<(::std::ostream& os, const Value& v)
{
if( v.allocation )
{
- os << v.allocation.alloc();
+ os << *v.allocation;
}
else
{
@@ -687,15 +821,15 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v)
{
if( v.m_size == 0 )
return os;
- if( v.m_alloc || v.m_value->allocation )
+ if( v.m_alloc )
{
- const auto& alloc_ptr = v.m_alloc ? v.m_alloc : v.m_value->allocation;
+ const auto& alloc_ptr = v.m_alloc;;
// TODO: What if alloc_ptr isn't a data allocation?
switch(alloc_ptr.get_ty())
{
- case AllocationPtr::Ty::Allocation: {
+ case RelocationPtr::Ty::Allocation: {
const auto& alloc = alloc_ptr.alloc();
-
+
auto flags = os.flags();
os << ::std::hex;
for(size_t i = v.m_offset; i < ::std::min(alloc.size(), v.m_offset + v.m_size); i++)
@@ -724,10 +858,10 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v)
}
os << " }";
} break;
- case AllocationPtr::Ty::Function:
+ case RelocationPtr::Ty::Function:
LOG_TODO("ValueRef to " << alloc_ptr);
break;
- case AllocationPtr::Ty::StdString: {
+ case RelocationPtr::Ty::StdString: {
const auto& s = alloc_ptr.str();
assert(v.m_offset < s.size());
assert(v.m_size < s.size());
@@ -740,12 +874,44 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v)
}
os.setf(flags);
} break;
- case AllocationPtr::Ty::FfiPointer:
+ case RelocationPtr::Ty::FfiPointer:
LOG_TODO("ValueRef to " << alloc_ptr);
break;
}
}
- else
+ else if( v.m_value && v.m_value->allocation )
+ {
+ const auto& alloc = *v.m_value->allocation;
+
+ auto flags = os.flags();
+ os << ::std::hex;
+ for(size_t i = v.m_offset; i < ::std::min(alloc.size(), v.m_offset + v.m_size); i++)
+ {
+ if( i != 0 )
+ os << " ";
+
+ if( alloc.mask[i/8] & (1 << i%8) )
+ {
+ os << ::std::setw(2) << ::std::setfill('0') << (int)alloc.data_ptr()[i];
+ }
+ else
+ {
+ os << "--";
+ }
+ }
+ os.setf(flags);
+
+ os << " {";
+ for(const auto& r : alloc.relocations)
+ {
+ if( v.m_offset <= r.slot_ofs && r.slot_ofs < v.m_offset + v.m_size )
+ {
+ os << " @" << (r.slot_ofs - v.m_offset) << "=" << r.backing_alloc;
+ }
+ }
+ os << " }";
+ }
+ else if( v.m_value )
{
const auto& direct = v.m_value->direct_data;
@@ -766,24 +932,45 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v)
}
os.setf(flags);
}
+ else
+ {
+ // TODO: no value?
+ }
return os;
}
-uint64_t ValueRef::read_usize(size_t ofs) const
+Value ValueRef::read_value(size_t ofs, size_t size) const
{
- uint64_t v = 0;
- this->read_bytes(ofs, &v, POINTER_SIZE);
- return v;
+ if( size == 0 )
+ return Value();
+ if( !(ofs < m_size && size <= m_size && ofs + size <= m_size) ) {
+ LOG_ERROR("Read exceeds bounds, " << ofs << " + " << size << " > " << m_size << " - from " << *this);
+ }
+ if( m_alloc ) {
+ switch(m_alloc.get_ty())
+ {
+ case RelocationPtr::Ty::Allocation:
+ return m_alloc.alloc().read_value(m_offset + ofs, size);
+ case RelocationPtr::Ty::StdString: {
+ auto rv = Value::with_size(size, false);
+ //ASSERT_BUG(ofs <= m_alloc.str().size(), "");
+ //ASSERT_BUG(size <= m_alloc.str().size(), "");
+ //ASSERT_BUG(ofs+size <= m_alloc.str().size(), "");
+ assert(m_offset+ofs <= m_alloc.str().size() && size <= m_alloc.str().size() && m_offset+ofs+size <= m_alloc.str().size());
+ rv.write_bytes(0, m_alloc.str().data() + m_offset + ofs, size);
+ return rv;
+ }
+ default:
+ //ASSERT_BUG(m_alloc.is_alloc(), "read_value on non-data backed Value - " << );
+ throw "TODO";
+ }
+ }
+ else {
+ return m_value->read_value(m_offset + ofs, size);
+ }
}
-uint64_t Value::read_usize(size_t ofs) const
+bool ValueRef::compare(const void* other, size_t other_len) const
{
- uint64_t v = 0;
- this->read_bytes(ofs, &v, POINTER_SIZE);
- return v;
+ check_bytes_valid(0, other_len);
+ return ::std::memcmp(data_ptr(), other, other_len) == 0;
}
-uint64_t Allocation::read_usize(size_t ofs) const
-{
- uint64_t v = 0;
- this->read_bytes(ofs, &v, POINTER_SIZE);
- return v;
-} \ No newline at end of file