diff options
-rw-r--r-- | src/trans/codegen_mmir.cpp | 6 | ||||
-rw-r--r-- | tools/standalone_miri/hir_sim.cpp | 30 | ||||
-rw-r--r-- | tools/standalone_miri/hir_sim.hpp | 1 | ||||
-rw-r--r-- | tools/standalone_miri/main.cpp | 236 | ||||
-rw-r--r-- | tools/standalone_miri/value.cpp | 6 | ||||
-rw-r--r-- | tools/standalone_miri/value.hpp | 4 |
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); |