summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/trans/codegen_mmir.cpp6
-rw-r--r--tools/standalone_miri/hir_sim.cpp30
-rw-r--r--tools/standalone_miri/hir_sim.hpp1
-rw-r--r--tools/standalone_miri/main.cpp236
-rw-r--r--tools/standalone_miri/value.cpp6
-rw-r--r--tools/standalone_miri/value.hpp4
6 files changed, 210 insertions, 73 deletions
diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp
index 22c232b2..faa3598d 100644
--- a/src/trans/codegen_mmir.cpp
+++ b/src/trans/codegen_mmir.cpp
@@ -223,7 +223,7 @@ namespace
auto fld_lv = ::MIR::LValue::make_Field({ box$(self), 0 });
for(const auto& e : repr->fields)
{
- if( !m_resolve.type_is_copy(sp, e.ty) ) {
+ if( m_resolve.type_needs_drop_glue(sp, e.ty) ) {
m_of << "\t\t""DROP " << fmt(fld_lv) << ";\n";
}
fld_lv.as_Field().field_index += 1;
@@ -386,7 +386,7 @@ namespace
fld_p_lv = ::MIR::LValue::make_Field({ box$(fld_p_lv), 0 });
fld_p_lv = ::MIR::LValue::make_Field({ box$(fld_p_lv), 0 });
- if( !m_resolve.type_is_copy(sp, *ity) ) {
+ if( m_resolve.type_needs_drop_glue(sp, *ity) ) {
auto fld_lv = ::MIR::LValue::make_Deref({ box$(fld_p_lv.clone()) });
m_of << "\t\t""DROP " << fmt(fld_lv) << ";\n";
}
@@ -421,7 +421,7 @@ namespace
auto fld_lv = ::MIR::LValue::make_Field({ box$(self), 0 });
for(const auto& e : repr->fields)
{
- if( !m_resolve.type_is_copy(sp, e.ty) ) {
+ if( m_resolve.type_needs_drop_glue(sp, e.ty) ) {
m_of << "\t\t""DROP " << fmt(fld_lv) << ";\n";
}
fld_lv.as_Field().field_index += 1;
diff --git a/tools/standalone_miri/hir_sim.cpp b/tools/standalone_miri/hir_sim.cpp
index 85c05459..604f65a4 100644
--- a/tools/standalone_miri/hir_sim.cpp
+++ b/tools/standalone_miri/hir_sim.cpp
@@ -136,6 +136,36 @@ HIR::TypeRef HIR::TypeRef::wrap(TypeWrapper::Ty ty, size_t size) const
rv.wrappers.insert(rv.wrappers.begin(), { ty, size });
return rv;
}
+const HIR::TypeRef* HIR::TypeRef::get_usized_type(size_t& running_inner_size) const
+{
+ if( this->wrappers.empty() )
+ {
+ switch(this->inner_type)
+ {
+ case RawType::Composite:
+ if(!this->composite_type->variants.empty())
+ return nullptr;
+ if(this->composite_type->fields.empty())
+ return nullptr;
+ running_inner_size = this->composite_type->fields.back().first;
+ size_t tmp;
+ return this->composite_type->fields.back().second.get_usized_type(tmp);
+ case RawType::TraitObject:
+ case RawType::Str:
+ return this;
+ default:
+ return nullptr;
+ }
+ }
+ else if( this->wrappers[0].type == TypeWrapper::Ty::Slice )
+ {
+ return this;
+ }
+ else
+ {
+ return nullptr;
+ }
+}
const HIR::TypeRef* HIR::TypeRef::get_meta_type() const
{
static ::HIR::TypeRef static_usize = ::HIR::TypeRef(RawType::USize);
diff --git a/tools/standalone_miri/hir_sim.hpp b/tools/standalone_miri/hir_sim.hpp
index 504f0450..7154de13 100644
--- a/tools/standalone_miri/hir_sim.hpp
+++ b/tools/standalone_miri/hir_sim.hpp
@@ -119,6 +119,7 @@ namespace HIR {
size_t get_size(size_t ofs=0) const;
bool has_slice_meta() const; // The attached metadata is a count
+ const TypeRef* get_usized_type(size_t& running_inner_size) const;
const TypeRef* get_meta_type() const;
TypeRef get_inner() const;
TypeRef wrap(TypeWrapper::Ty ty, size_t size) const;
diff --git a/tools/standalone_miri/main.cpp b/tools/standalone_miri/main.cpp
index d6cf6702..a75e753f 100644
--- a/tools/standalone_miri/main.cpp
+++ b/tools/standalone_miri/main.cpp
@@ -21,7 +21,7 @@ struct ProgramOptions
Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector<Value> args);
Value MIRI_Invoke_Extern(const ::std::string& link_name, const ::std::string& abi, ::std::vector<Value> args);
-Value MIRI_Invoke_Intrinsic(const ModuleTree& modtree, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector<Value> args);
+Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector<Value> args);
int main(int argc, const char* argv[])
{
@@ -288,6 +288,56 @@ struct Ops {
}
};
+namespace
+{
+
+ void drop_value(ModuleTree& modtree, Value ptr, const ::HIR::TypeRef& ty)
+ {
+ if( ty.wrappers.empty() )
+ {
+ if( ty.inner_type == RawType::Composite )
+ {
+ if( ty.composite_type->drop_glue != ::HIR::Path() )
+ {
+ LOG_DEBUG("Drop - " << ty);
+
+ MIRI_Invoke(modtree, ty.composite_type->drop_glue, { ptr });
+ }
+ else
+ {
+ // No drop glue
+ }
+ }
+ else if( ty.inner_type == RawType::TraitObject )
+ {
+ LOG_TODO("Drop - " << ty << " - trait object");
+ }
+ else
+ {
+ // No destructor
+ }
+ }
+ else if( ty.wrappers[0].type == TypeWrapper::Ty::Borrow )
+ {
+ if( ty.wrappers[0].size == static_cast<size_t>(::HIR::BorrowType::Move) )
+ {
+ LOG_TODO("Drop - " << ty << " - dereference and go to inner");
+ // TODO: Clear validity on the entire inner value.
+ }
+ else
+ {
+ // No destructor
+ }
+ }
+ // TODO: Arrays
+ else
+ {
+ LOG_TODO("Drop - " << ty << " - array?");
+ }
+ }
+
+}
+
Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector<Value> args)
{
Value ret;
@@ -1312,74 +1362,31 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector<Value> ar
TU_ARM(stmt, Drop, se) {
if( se.flag_idx == ~0u || state.drop_flags.at(se.flag_idx) )
{
- auto drop_value = [&](ValueRef v, const ::HIR::TypeRef& ty) {
- if( ty.wrappers.empty() )
- {
- if( ty.inner_type == RawType::Composite )
- {
- if( ty.composite_type->drop_glue != ::HIR::Path() )
- {
- LOG_DEBUG("Drop - " << ty);
-
- // - Take a pointer to the inner
- auto alloc = v.m_alloc;
- if( !alloc )
- {
- if( !v.m_value->allocation )
- {
- v.m_value->create_allocation();
- }
- alloc = AllocationPtr(v.m_value->allocation);
- }
- size_t ofs = v.m_offset;
- assert(!ty.get_meta_type());
-
- auto ptr_ty = ty.wrap(TypeWrapper::Ty::Borrow, 2);
-
- auto ptr_val = Value(ptr_ty);
- ptr_val.write_usize(0, ofs);
- ptr_val.allocation.alloc().relocations.push_back(Relocation { 0, ::std::move(alloc) });
-
- MIRI_Invoke(modtree, ty.composite_type->drop_glue, { ptr_val });
- }
- else
- {
- // No drop glue
- }
- }
- else if( ty.inner_type == RawType::TraitObject )
- {
- LOG_TODO("Drop - " << ty << " - trait object");
- }
- else
- {
- // No destructor
- }
- }
- else if( ty.wrappers[0].type == TypeWrapper::Ty::Borrow )
- {
- if( ty.wrappers[0].size == static_cast<size_t>(::HIR::BorrowType::Move) )
- {
- LOG_TODO("Drop - " << ty << " - dereference and go to inner");
- // TODO: Clear validity on the entire inner value.
- }
- else
- {
- // No destructor
- }
- }
- // TODO: Arrays
- else
+ ::HIR::TypeRef ty;
+ auto v = state.get_value_and_type(se.slot, ty);
+
+ // - Take a pointer to the inner
+ auto alloc = v.m_alloc;
+ if( !alloc )
+ {
+ if( !v.m_value->allocation )
{
- LOG_TODO("Drop - " << ty << " - array");
+ v.m_value->create_allocation();
}
+ alloc = AllocationPtr(v.m_value->allocation);
+ }
+ size_t ofs = v.m_offset;
+ assert(!ty.get_meta_type());
- };
+ auto ptr_ty = ty.wrap(TypeWrapper::Ty::Borrow, 2);
- ::HIR::TypeRef ty;
- auto v = state.get_value_and_type(se.slot, ty);
- drop_value(v, ty);
+ auto ptr_val = Value(ptr_ty);
+ ptr_val.write_usize(0, ofs);
+ ptr_val.allocation.alloc().relocations.push_back(Relocation { 0, ::std::move(alloc) });
+
+ drop_value(modtree, ptr_val, ty);
// TODO: Clear validity on the entire inner value.
+ //alloc.mark_as_freed();
}
} break;
TU_ARM(stmt, SetDropFlag, se) {
@@ -1489,9 +1496,10 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector<Value> ar
// TODO: Assert offset/content.
assert(v.read_usize(v.m_offset) == 0);
auto& alloc_ptr = v.m_alloc ? v.m_alloc : v.m_value->allocation;
- LOG_ASSERT(alloc_ptr, "");
+ LOG_ASSERT(alloc_ptr, "Calling value that can't be a pointer (no allocation)");
auto& fcn_alloc_ptr = alloc_ptr.alloc().get_relocation(v.m_offset);
- LOG_ASSERT(fcn_alloc_ptr, "");
+ LOG_ASSERT(fcn_alloc_ptr, "Calling value with no relocation");
+ LOG_ASSERT(fcn_alloc_ptr.get_ty() == AllocationPtr::Ty::Function, "Calling value that isn't a function pointer");
fcn_p = &fcn_alloc_ptr.fcn();
}
@@ -1543,6 +1551,23 @@ Value MIRI_Invoke_Extern(const ::std::string& link_name, const ::std::string& ab
// TODO: Should this instead make a new allocation to catch use-after-free?
return ::std::move(args.at(0));
}
+ else if( link_name == "__rust_deallocate" )
+ {
+ LOG_ASSERT(args.at(0).allocation, "__rust_deallocate first argument doesn't have an allocation");
+ auto alloc_ptr = args.at(0).allocation.alloc().get_relocation(0);
+ auto ptr_ofs = args.at(0).read_usize(0);
+ LOG_ASSERT(ptr_ofs == 0, "__rust_deallocate with offset pointer");
+
+ LOG_ASSERT(alloc_ptr, "__rust_deallocate with no backing allocation attached to pointer");
+ LOG_ASSERT(alloc_ptr.is_alloc(), "__rust_deallocate with no backing allocation attached to pointer");
+ auto& alloc = alloc_ptr.alloc();
+ // TODO: Figure out how to prevent this ever being written again.
+ //alloc.mark_as_freed();
+ for(auto& v : alloc.mask)
+ v = 0;
+ // Just let it drop.
+ return Value();
+ }
#ifdef _WIN32
// WinAPI functions used by libstd
else if( link_name == "AddVectoredExceptionHandler" )
@@ -1612,8 +1637,9 @@ Value MIRI_Invoke_Extern(const ::std::string& link_name, const ::std::string& ab
{
LOG_TODO("Call external function " << link_name);
}
+ throw "";
}
-Value MIRI_Invoke_Intrinsic(const ModuleTree& modtree, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector<Value> args)
+Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector<Value> args)
{
Value rv;
TRACE_FUNCTION_R(name, rv);
@@ -1702,6 +1728,82 @@ Value MIRI_Invoke_Intrinsic(const ModuleTree& modtree, const ::std::string& name
{
rv = Value(ty_params.tys.at(0));
}
+ // - Unsized stuff
+ else if( name == "size_of_val" )
+ {
+ auto& val = args.at(0);
+ const auto& ty = ty_params.tys.at(0);
+ rv = Value(::HIR::TypeRef(RawType::USize));
+ // Get unsized type somehow.
+ // - _HAS_ to be the last type, so that makes it easier
+ size_t fixed_size = 0;
+ if( const auto* ity = ty.get_usized_type(fixed_size) )
+ {
+ const auto& meta_ty = *ty.get_meta_type();
+ LOG_DEBUG("size_of_val - " << ty << " ity=" << *ity << " meta_ty=" << meta_ty << " fixed_size=" << fixed_size);
+ size_t flex_size = 0;
+ if( !ity->wrappers.empty() )
+ {
+ LOG_ASSERT(ity->wrappers[0].type == TypeWrapper::Ty::Slice, "");
+ size_t item_size = ity->get_inner().get_size();
+ size_t item_count = val.read_usize(POINTER_SIZE);
+ flex_size = item_count * item_size;
+ LOG_DEBUG("> item_size=" << item_size << " item_count=" << item_count << " flex_size=" << flex_size);
+ }
+ else if( ity->inner_type == RawType::Str )
+ {
+ flex_size = val.read_usize(POINTER_SIZE);
+ }
+ else if( ity->inner_type == RawType::TraitObject )
+ {
+ LOG_TODO("size_of_val - Trait Object - " << ty);
+ }
+ else
+ {
+ LOG_BUG("Inner unsized type unknown - " << *ity);
+ }
+
+ rv.write_usize(0, fixed_size + flex_size);
+ }
+ else
+ {
+ rv.write_usize(0, ty.get_size());
+ }
+ }
+ else if( name == "drop_in_place" )
+ {
+ auto& val = args.at(0);
+ const auto& ty = ty_params.tys.at(0);
+ if( !ty.wrappers.empty() )
+ {
+ size_t item_count = 0;
+ switch(ty.wrappers[0].type)
+ {
+ case TypeWrapper::Ty::Slice:
+ case TypeWrapper::Ty::Array:
+ item_count = (ty.wrappers[0].type == TypeWrapper::Ty::Slice ? val.read_usize(POINTER_SIZE) : ty.wrappers[0].size);
+ break;
+ case TypeWrapper::Ty::Pointer:
+ break;
+ case TypeWrapper::Ty::Borrow:
+ break;
+ }
+ LOG_ASSERT(ty.wrappers[0].type == TypeWrapper::Ty::Slice, "drop_in_place should only exist for slices - " << ty);
+ const auto& ity = ty.get_inner();
+ size_t item_size = ity.get_size();
+
+ auto ptr = val.read_value(0, POINTER_SIZE);;
+ for(size_t i = 0; i < item_count; i ++)
+ {
+ drop_value(modtree, ptr, ity);
+ ptr.write_usize(0, ptr.read_usize(0) + item_size);
+ }
+ }
+ else
+ {
+ LOG_TODO("drop_in_place - " << ty);
+ }
+ }
// ----------------------------------------------------------------
// Checked arithmatic
else if( name == "add_with_overflow" )
diff --git a/tools/standalone_miri/value.cpp b/tools/standalone_miri/value.cpp
index 18bed61e..beff8a38 100644
--- a/tools/standalone_miri/value.cpp
+++ b/tools/standalone_miri/value.cpp
@@ -772,18 +772,18 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v)
uint64_t ValueRef::read_usize(size_t ofs) const
{
uint64_t v = 0;
- this->read_bytes(0, &v, POINTER_SIZE);
+ this->read_bytes(ofs, &v, POINTER_SIZE);
return v;
}
uint64_t Value::read_usize(size_t ofs) const
{
uint64_t v = 0;
- this->read_bytes(0, &v, POINTER_SIZE);
+ this->read_bytes(ofs, &v, POINTER_SIZE);
return v;
}
uint64_t Allocation::read_usize(size_t ofs) const
{
uint64_t v = 0;
- this->read_bytes(0, &v, POINTER_SIZE);
+ this->read_bytes(ofs, &v, POINTER_SIZE);
return v;
} \ No newline at end of file
diff --git a/tools/standalone_miri/value.hpp b/tools/standalone_miri/value.hpp
index 3dfdd369..8b103210 100644
--- a/tools/standalone_miri/value.hpp
+++ b/tools/standalone_miri/value.hpp
@@ -132,6 +132,10 @@ public:
}
return AllocationPtr();
}
+ //void mark_as_freed() {
+ // for(auto& v : mask)
+ // v = 0;
+ //}
void resize(size_t new_size);