diff options
Diffstat (limited to 'tools/standalone_miri/value.cpp')
-rw-r--r-- | tools/standalone_miri/value.cpp | 445 |
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 |