diff options
-rw-r--r-- | tools/standalone_miri/hir_sim.cpp | 68 | ||||
-rw-r--r-- | tools/standalone_miri/hir_sim.hpp | 32 | ||||
-rw-r--r-- | tools/standalone_miri/miri.cpp | 35 | ||||
-rw-r--r-- | tools/standalone_miri/module_tree.cpp | 11 | ||||
-rw-r--r-- | tools/standalone_miri/module_tree.hpp | 20 |
5 files changed, 118 insertions, 48 deletions
diff --git a/tools/standalone_miri/hir_sim.cpp b/tools/standalone_miri/hir_sim.cpp index dc03ca8a..135ea214 100644 --- a/tools/standalone_miri/hir_sim.cpp +++ b/tools/standalone_miri/hir_sim.cpp @@ -42,18 +42,18 @@ size_t HIR::TypeRef::get_size(size_t ofs) const // Need to look up the metadata type for the actual type if( this->inner_type == RawType::Composite ) { - if( this->composite_type->dst_meta == RawType::Unreachable ) + if( this->composite_type().dst_meta == RawType::Unreachable ) { return POINTER_SIZE; } // Special case: extern types (which appear when a type is only ever used by pointer) - if( this->composite_type->dst_meta == RawType::Unit ) + if( this->composite_type().dst_meta == RawType::Unit ) { return POINTER_SIZE; } // TODO: Ideally, this inner type wouldn't be unsized itself... but checking that would be interesting. - return POINTER_SIZE + this->composite_type->dst_meta.get_size(); + return POINTER_SIZE + this->composite_type().dst_meta.get_size(); } else if( this->inner_type == RawType::Str ) return POINTER_SIZE*2; @@ -77,8 +77,8 @@ size_t HIR::TypeRef::get_size(size_t ofs) const return 0; case RawType::Composite: // NOTE: Don't care if the type has metadata - LOG_ASSERT(this->composite_type->populated, "Getting size of non-defined type - " << *this); - return this->composite_type->size; + LOG_ASSERT(this->composite_type().populated, "Getting size of non-defined type - " << *this); + return this->composite_type().size; case RawType::Unreachable: LOG_BUG("Attempting to get size of an unreachable type, " << *this); case RawType::TraitObject: @@ -126,8 +126,8 @@ size_t HIR::TypeRef::get_align(size_t ofs) const return 1; case RawType::Composite: // NOTE: Don't care if the type has metadata - LOG_ASSERT(this->composite_type->populated, "Getting alignment of non-defined type - " << *this); - return this->composite_type->alignment; + LOG_ASSERT(this->composite_type().populated, "Getting alignment of non-defined type - " << *this); + return this->composite_type().alignment; case RawType::TraitObject: case RawType::Str: return 1; @@ -217,7 +217,7 @@ bool HIR::TypeRef::has_pointer() const if( this->inner_type == RawType::Composite ) { // Still not sure, check the inner for any pointers. - for(const auto& fld : this->composite_type->fields) + for(const auto& fld : this->composite_type().fields) { if( fld.second.has_pointer() ) return true; @@ -245,13 +245,13 @@ const HIR::TypeRef* HIR::TypeRef::get_unsized_type(size_t& running_inner_size) c switch(this->inner_type) { case RawType::Composite: - if(!this->composite_type->variants.empty()) + if(!this->composite_type().variants.empty()) return nullptr; - if(this->composite_type->fields.empty()) + if(this->composite_type().fields.empty()) return nullptr; - running_inner_size = this->composite_type->fields.back().first; + running_inner_size = this->composite_type().fields.back().first; size_t tmp; - return this->composite_type->fields.back().second.get_unsized_type(tmp); + return this->composite_type().fields.back().second.get_unsized_type(tmp); case RawType::TraitObject: case RawType::Str: return this; @@ -278,11 +278,12 @@ HIR::TypeRef HIR::TypeRef::get_meta_type() const switch(this->inner_type) { case RawType::Composite: - if( this->composite_type->dst_meta == RawType::Unreachable ) + if( this->composite_type().dst_meta == RawType::Unreachable ) return TypeRef(RawType::Unreachable); - return this->composite_type->dst_meta; + return this->composite_type().dst_meta; case RawType::TraitObject: - return ::HIR::TypeRef(this->composite_type).wrap( TypeWrapper::Ty::Pointer, static_cast<size_t>(BorrowType::Shared) ); + LOG_ASSERT(this->ptr.composite_type, "get_meta_type - " << *this); + return ::HIR::TypeRef(this->ptr.composite_type).wrap( TypeWrapper::Ty::Pointer, static_cast<size_t>(BorrowType::Shared) ); case RawType::Str: return TypeRef(RawType::USize); default: @@ -316,9 +317,9 @@ HIR::TypeRef HIR::TypeRef::get_field(size_t idx, size_t& ofs) const { if( this->inner_type == RawType::Composite ) { - LOG_ASSERT(idx < this->composite_type->fields.size(), "Field " << idx << " out of bounds in type " << *this); - ofs = this->composite_type->fields.at(idx).first; - return this->composite_type->fields.at(idx).second; + LOG_ASSERT(idx < this->composite_type().fields.size(), "Field " << idx << " out of bounds in type " << *this); + ofs = this->composite_type().fields.at(idx).first; + return this->composite_type().fields.at(idx).second; } else { @@ -330,14 +331,14 @@ size_t HIR::TypeRef::get_field_ofs(size_t base_idx, const ::std::vector<size_t>& { assert(this->wrappers.size() == 0); assert(this->inner_type == RawType::Composite); - size_t ofs = this->composite_type->fields.at(base_idx).first; - const auto* ty_p = &this->composite_type->fields.at(base_idx).second; + size_t ofs = this->composite_type().fields.at(base_idx).first; + const auto* ty_p = &this->composite_type().fields.at(base_idx).second; for(auto idx : other_idx) { assert(ty_p->wrappers.size() == 0); assert(ty_p->inner_type == RawType::Composite); - ofs += ty_p->composite_type->fields.at(idx).first; - ty_p = &ty_p->composite_type->fields.at(idx).second; + ofs += ty_p->composite_type().fields.at(idx).first; + ty_p = &ty_p->composite_type().fields.at(idx).second; } ty = *ty_p; return ofs; @@ -394,19 +395,30 @@ namespace HIR { os << "()"; break; case RawType::Composite: - os << x.composite_type->my_path; + os << x.composite_type().my_path; //os << "composite_" << x.composite_type; break; case RawType::Unreachable: os << "!"; break; - case RawType::Function: - os << "function_?"; - break; + case RawType::Function: { + assert( x.ptr.function_type ); + const auto& ft = *x.ptr.function_type; + if( ft.unsafe ) + os << "unsafe "; + if( ft.abi != "Rust" ) + os << "extern \"" << ft.abi << "\" "; + os << "fn( "; + for(const auto& a : ft.args) + os << a << ", "; + os << ")"; + if( ft.ret != RawType::Unit ) + os << "-> " << ft.ret; + } break; case RawType::TraitObject: os << "dyn "; - if( x.composite_type ) - os << x.composite_type->my_path; + if( x.ptr.composite_type ) + os << x.composite_type().my_path; else os << "?"; break; diff --git a/tools/standalone_miri/hir_sim.hpp b/tools/standalone_miri/hir_sim.hpp index 9483f1bb..81d3635a 100644 --- a/tools/standalone_miri/hir_sim.hpp +++ b/tools/standalone_miri/hir_sim.hpp @@ -28,6 +28,7 @@ enum Ordering #endif struct DataType; +struct FunctionType; enum class RawType { @@ -77,7 +78,6 @@ struct TypeWrapper } }; - namespace HIR { enum class BorrowType @@ -97,24 +97,35 @@ namespace HIR { // Top to bottom list of wrappers (first entry is the outermost wrapper) ::std::vector<TypeWrapper> wrappers; RawType inner_type = RawType::Unit; - const DataType* composite_type = nullptr; + union { + const DataType* composite_type; + const FunctionType* function_type; + } ptr; TypeRef() { + ptr.composite_type = nullptr; } explicit TypeRef(const DataType* dt): - inner_type(RawType::Composite), - composite_type(dt) + inner_type(RawType::Composite) + { + ptr.composite_type = dt; + } + explicit TypeRef(const FunctionType* fp): + inner_type(RawType::Function) { + ptr.function_type = fp; } explicit TypeRef(RawType rt): inner_type(rt) { + ptr.composite_type = nullptr; } explicit TypeRef(CoreType ct): inner_type(ct.raw_type) { + ptr.composite_type = nullptr; } static TypeRef diverge() { TypeRef rv; @@ -165,6 +176,17 @@ namespace HIR { // Get the offset and type of a field (recursing using `other_idx`) size_t get_field_ofs(size_t idx, const ::std::vector<size_t>& other_idx, TypeRef& ty) const; + const DataType& composite_type() const { + assert(inner_type == RawType::Composite || inner_type == RawType::TraitObject); + assert(ptr.composite_type); + return *ptr.composite_type; + } + const FunctionType& function_type() const { + assert(inner_type == RawType::Function); + assert(ptr.function_type); + return *ptr.function_type; + } + bool operator==(const RawType& x) const { if( this->wrappers.size() != 0 ) return false; @@ -176,7 +198,7 @@ namespace HIR { Ordering ord(const TypeRef& x) const { __ORD(wrappers); __ORD_C(int, inner_type); - __ORD_C(uintptr_t, composite_type); + __ORD_C(uintptr_t, ptr.composite_type); // pointer comparison only return OrdEqual; } bool operator==(const TypeRef& x) const { diff --git a/tools/standalone_miri/miri.cpp b/tools/standalone_miri/miri.cpp index 1a235880..ab7e2e22 100644 --- a/tools/standalone_miri/miri.cpp +++ b/tools/standalone_miri/miri.cpp @@ -909,7 +909,7 @@ bool InterpreterThread::step_one(Value& out_thread_result) case RawType::Unit: LOG_FATAL("Cast of unit"); case RawType::Composite: { - const auto& dt = *src_ty.composite_type; + const auto& dt = src_ty.composite_type(); if( dt.variants.size() == 0 ) { LOG_FATAL("Cast of composite - " << src_ty); } @@ -1418,10 +1418,18 @@ bool InterpreterThread::step_one(Value& out_thread_result) state.get_value_and_type(se.dst, dst_ty); new_val = Value(dst_ty); - for(size_t i = 0; i < re.vals.size(); i++) + if( dst_ty.inner_type == RawType::Unit ) + { + LOG_ASSERT(re.vals.size() == 0 , ""); + } + else { - auto fld_ofs = dst_ty.composite_type->fields.at(i).first; - new_val.write_value(fld_ofs, state.param_to_value(re.vals[i])); + LOG_ASSERT(dst_ty.inner_type == RawType::Composite, dst_ty); + for(size_t i = 0; i < re.vals.size(); i++) + { + auto fld_ofs = dst_ty.composite_type().fields.at(i).first; + new_val.write_value(fld_ofs, state.param_to_value(re.vals[i])); + } } } break; TU_ARM(se.src, Array, re) { @@ -1489,7 +1497,8 @@ bool InterpreterThread::step_one(Value& out_thread_result) ::HIR::TypeRef dst_ty; state.get_value_and_type(se.dst, dst_ty); new_val = Value(dst_ty); - LOG_ASSERT(dst_ty.composite_type == &data_ty, "Destination type of RValue::Struct isn't the same as the input"); + LOG_ASSERT(dst_ty.inner_type == RawType::Composite, dst_ty); + LOG_ASSERT(dst_ty.ptr.composite_type == &data_ty, "Destination type of RValue::Struct isn't the same as the input"); for(size_t i = 0; i < re.vals.size(); i++) { @@ -1579,9 +1588,9 @@ bool InterpreterThread::step_one(Value& out_thread_result) // TODO: Convert the variant list into something that makes it easier to switch on. size_t found_target = SIZE_MAX; size_t default_target = SIZE_MAX; - for(size_t i = 0; i < ty.composite_type->variants.size(); i ++) + for(size_t i = 0; i < ty.composite_type().variants.size(); i ++) { - const auto& var = ty.composite_type->variants[i]; + const auto& var = ty.composite_type().variants[i]; if( var.tag_data.size() == 0 ) { // Save as the default, error for multiple defaults @@ -2589,10 +2598,10 @@ bool InterpreterThread::call_intrinsic(Value& rv, const RcString& name, const :: size_t fallback = SIZE_MAX; size_t found_index = SIZE_MAX; - assert(ty.composite_type); - for(size_t i = 0; i < ty.composite_type->variants.size(); i ++) + LOG_ASSERT(ty.inner_type == RawType::Composite, "discriminant_value " << ty); + for(size_t i = 0; i < ty.composite_type().variants.size(); i ++) { - const auto& var = ty.composite_type->variants[i]; + const auto& var = ty.composite_type().variants[i]; if( var.tag_data.size() == 0 ) { // Only seen in Option<NonNull> @@ -3135,10 +3144,10 @@ bool InterpreterThread::drop_value(Value ptr, const ::HIR::TypeRef& ty, bool is_ m_stack.insert( m_stack.end() - 1, StackFrame::make_wrapper([this,pty,ity,ptr_reloc,count, i,ofs](Value& rv, Value drop_rv) mutable { assert(i < count); i ++; + ofs += ity.get_size(); if( i < count ) { auto ptr = Value::new_pointer(pty, ofs, ptr_reloc); - ofs += ity.get_size(); assert(!drop_value(ptr, ity)); return false; } @@ -3162,12 +3171,12 @@ bool InterpreterThread::drop_value(Value ptr, const ::HIR::TypeRef& ty, bool is_ { if( ty.inner_type == RawType::Composite ) { - if( ty.composite_type->drop_glue != ::HIR::Path() ) + if( ty.composite_type().drop_glue != ::HIR::Path() ) { LOG_DEBUG("Drop - " << ty); Value tmp; - return this->call_path(tmp, ty.composite_type->drop_glue, { ptr }); + return this->call_path(tmp, ty.composite_type().drop_glue, { ptr }); } else { diff --git a/tools/standalone_miri/module_tree.cpp b/tools/standalone_miri/module_tree.cpp index 2d1eb838..91d82d85 100644 --- a/tools/standalone_miri/module_tree.cpp +++ b/tools/standalone_miri/module_tree.cpp @@ -1229,7 +1229,14 @@ RawType Parser::parse_core_type() { ret_ty = ::HIR::TypeRef::unit(); } - return ::HIR::TypeRef(RawType::Function); + auto ft = FunctionType { + is_unsafe, + ::std::move(abi), + ::std::move(args), + ::std::move(ret_ty) + }; + const auto* ft_p = &*tree.function_types.insert(::std::move(ft)).first; + return ::HIR::TypeRef(ft_p); // TODO: Use abi/ret_ty/args as part of that } else if( lex.consume_if("dyn") ) @@ -1294,7 +1301,7 @@ RawType Parser::parse_core_type() vtable_path.m_params.tys.push_back( ::std::move(atys[0].second) ); } // - TODO: Associated types? (Need to ensure ordering is correct) - rv.composite_type = this->get_composite( ::std::move(vtable_path) ); + rv.ptr.composite_type = this->get_composite( ::std::move(vtable_path) ); } else { diff --git a/tools/standalone_miri/module_tree.hpp b/tools/standalone_miri/module_tree.hpp index 5da8439f..299aa51c 100644 --- a/tools/standalone_miri/module_tree.hpp +++ b/tools/standalone_miri/module_tree.hpp @@ -49,6 +49,8 @@ class ModuleTree // Hack: Tuples are stored as `::""::<A,B,C,...>` ::std::map<::HIR::GenericPath, ::std::unique_ptr<DataType>> data_types; + ::std::set<FunctionType> function_types; // note: insertion doesn't invaliate pointers. + ::std::map<::std::string, const Function*> ext_functions; public: ModuleTree(); @@ -95,3 +97,21 @@ struct DataType }; ::std::vector<VariantValue> variants; }; + +struct FunctionType +{ + bool unsafe; + ::std::string abi; + ::std::vector<HIR::TypeRef> args; + HIR::TypeRef ret; + + bool operator<(const FunctionType& x) const { + #define _(f) if(f != x.f) return f < x.f + _(unsafe); + _(abi); + _(args); + _(ret); + #undef _ + return false; + } +}; |