diff options
Diffstat (limited to 'src/hir')
-rw-r--r-- | src/hir/deserialise.cpp | 4 | ||||
-rw-r--r-- | src/hir/expr.cpp | 2 | ||||
-rw-r--r-- | src/hir/expr.hpp | 5 | ||||
-rw-r--r-- | src/hir/expr_ptr.cpp | 54 | ||||
-rw-r--r-- | src/hir/expr_ptr.hpp | 44 | ||||
-rw-r--r-- | src/hir/expr_state.hpp | 42 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 22 | ||||
-rw-r--r-- | src/hir/hir.cpp | 64 | ||||
-rw-r--r-- | src/hir/hir.hpp | 13 | ||||
-rw-r--r-- | src/hir/item_path.hpp | 20 |
10 files changed, 263 insertions, 7 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 17a93730..afce2fe4 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -734,7 +734,9 @@ ::HIR::LifetimeRef HirDeserialiser::deserialise_lifetimeref() { - return { static_cast<uint32_t>(m_in.read_count()) }; + ::HIR::LifetimeRef rv; + rv.binding = static_cast<uint32_t>(m_in.read_count()); + return rv; } ::HIR::TypeRef HirDeserialiser::deserialise_type() diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index 47f13052..07504ea7 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -172,7 +172,7 @@ DEF_VISIT(ExprNode_ArrayList, node, ) DEF_VISIT(ExprNode_ArraySized, node, visit_node_ptr(node.m_val); - visit_node_ptr(node.m_size); + //visit_node_ptr(node.m_size); ) DEF_VISIT(ExprNode_Closure, node, diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 37efac31..55a4eaf2 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -758,14 +758,15 @@ struct ExprNode_ArrayList: NODE_METHODS(); }; +// TODO: Might want a second variant for dynamically-sized arrays struct ExprNode_ArraySized: public ExprNode { ::HIR::ExprNodeP m_val; - ::HIR::ExprNodeP m_size; // TODO: Has to be constant + ::HIR::ExprPtr m_size; size_t m_size_val; - ExprNode_ArraySized(Span sp, ::HIR::ExprNodeP val, ::HIR::ExprNodeP size): + ExprNode_ArraySized(Span sp, ::HIR::ExprNodeP val, ::HIR::ExprPtr size): ExprNode(mv$(sp)), m_val( mv$(val) ), m_size( mv$(size) ), diff --git a/src/hir/expr_ptr.cpp b/src/hir/expr_ptr.cpp index 1f4cb1c3..fcef34bd 100644 --- a/src/hir/expr_ptr.cpp +++ b/src/hir/expr_ptr.cpp @@ -7,6 +7,7 @@ */ #include <hir/expr_ptr.hpp> #include <hir/expr.hpp> +#include <hir/expr_state.hpp> ::HIR::ExprPtr::ExprPtr(::std::unique_ptr< ::HIR::ExprNode> v): node( mv$(v) ) @@ -32,3 +33,56 @@ this->ptr = nullptr; return rv; } + +::HIR::ExprStatePtr::ExprStatePtr(ExprState x): + ptr(new ExprState( ::std::move(x) )) +{ +} +::HIR::ExprStatePtr::~ExprStatePtr() +{ + delete ptr; + ptr = nullptr; +} + + +const ::MIR::Function* HIR::ExprPtr::get_mir_opt() const +{ + if(!this->m_mir) + return nullptr; + return &*this->m_mir; +} +const ::MIR::Function& HIR::ExprPtr::get_mir_or_error(const Span& sp) const +{ + if(!this->m_mir) + BUG(sp, "No MIR"); + return *this->m_mir; +} +::MIR::Function& HIR::ExprPtr::get_mir_or_error_mut(const Span& sp) +{ + if(!this->m_mir) + BUG(sp, "No MIR"); + return *this->m_mir; +} +const ::MIR::Function* HIR::ExprPtr::get_ext_mir() const +{ + if(this->node) + return nullptr; + if(!this->m_mir) + return nullptr; + return &*this->m_mir; +} +::MIR::Function* HIR::ExprPtr::get_ext_mir_mut() +{ + if(this->node) + return nullptr; + if(!this->m_mir) + return nullptr; + return &*this->m_mir; +} +void HIR::ExprPtr::set_mir(::MIR::FunctionPointer mir) +{ + assert( !this->m_mir ); + m_mir = ::std::move(mir); +} + + diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp index 97991bf2..b510e737 100644 --- a/src/hir/expr_ptr.hpp +++ b/src/hir/expr_ptr.hpp @@ -12,10 +12,14 @@ #include <mir/mir_ptr.hpp> +class Span; + namespace HIR { class TypeRef; class ExprNode; +class Crate; +class ExprState; class ExprPtrInner { @@ -53,20 +57,49 @@ public: ::HIR::ExprNode* operator->() { assert(ptr); return ptr; } const ::HIR::ExprNode* operator->() const { assert(ptr); return ptr; } }; +class ExprStatePtr +{ + ::HIR::ExprState* ptr; +public: + ExprStatePtr(): ptr(nullptr) {} + ExprStatePtr(ExprState ); + ExprStatePtr(const ExprStatePtr&) = delete; + ExprStatePtr(ExprStatePtr&& x): ptr(x.ptr) { x.ptr = nullptr; } + ~ExprStatePtr(); + + ExprStatePtr& operator=(const ExprStatePtr&) = delete; + ExprStatePtr& operator=(ExprStatePtr&& x) { this->~ExprStatePtr(); ptr = x.ptr; x.ptr = nullptr; return *this; } + + operator bool () const { return ptr != nullptr; } + + ::HIR::ExprState& operator*() { assert(ptr); return *ptr; } + const ::HIR::ExprState& operator*() const { assert(ptr); return *ptr; } + ::HIR::ExprState* operator->() { assert(ptr); return ptr; } + const ::HIR::ExprState* operator->() const { assert(ptr); return ptr; } +}; class ExprPtr { + //::HIR::Path m_path; ::HIR::ExprPtrInner node; + public: ::std::vector< ::HIR::TypeRef> m_bindings; ::std::vector< ::HIR::TypeRef> m_erased_types; + + // Public because too much relies on access to it ::MIR::FunctionPointer m_mir; + ::HIR::ExprStatePtr m_state; + public: ExprPtr() {} ExprPtr(::std::unique_ptr< ::HIR::ExprNode> _); + ExprPtr(const ExprPtr&) = delete; + ExprPtr(ExprPtr&&) = default; + /// Take the innards and turn into a unique_ptr - used so typecheck can edit the root node. ::std::unique_ptr< ::HIR::ExprNode> into_unique(); operator bool () const { return node; } ::HIR::ExprNode* get() const { return node.get(); } @@ -76,6 +109,17 @@ public: const ::HIR::ExprNode& operator*() const { return *node; } ::HIR::ExprNode* operator->() { return &*node; } const ::HIR::ExprNode* operator->() const { return &*node; } + + //void ensure_typechecked(const ::HIR::Crate& crate) const; + /// Get MIR (checks if the MIR should be available) + const ::MIR::Function* get_mir_opt() const; + const ::MIR::Function& get_mir_or_error(const Span& sp) const; + ::MIR::Function& get_mir_or_error_mut(const Span& sp); + /// Get external MIR, returns nullptr if none + const ::MIR::Function* get_ext_mir() const; + ::MIR::Function* get_ext_mir_mut(); + + void set_mir(::MIR::FunctionPointer mir); }; } // namespace HIR diff --git a/src/hir/expr_state.hpp b/src/hir/expr_state.hpp new file mode 100644 index 00000000..5491b4d3 --- /dev/null +++ b/src/hir/expr_state.hpp @@ -0,0 +1,42 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * hir/expr_state.hpp + * - Extra state for expression pointers + */ +#pragma once +#include <hir/hir.hpp> + +namespace HIR { + +struct ExprState +{ + ::HIR::SimplePath m_mod_path; + const ::HIR::Module& m_module; + + ::HIR::GenericParams* m_impl_generics; + ::HIR::GenericParams* m_item_generics; + + ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits; + + enum class Stage { + Created, + TypecheckRequest, + Typecheck, + MirRequest, + Mir, + }; + mutable Stage stage; + + ExprState(const ::HIR::Module& mod_ptr, ::HIR::SimplePath mod_path): + m_mod_path(::std::move(mod_path)), + m_module(mod_ptr), + m_impl_generics(nullptr), + m_item_generics(nullptr), + stage(Stage::Created) + { + } +}; + +} diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 9c8f34f6..40c872fa 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -26,6 +26,7 @@ ::std::string g_core_crate; ::std::string g_crate_name; ::HIR::Crate* g_crate_ptr = nullptr; +const ::AST::Crate* g_ast_crate_ptr; // -------------------------------------------------------------------- ::std::string LowerHIR_LifetimeRef(const ::AST::LifetimeRef& r) @@ -1298,7 +1299,11 @@ namespace { ::HIR::Linkage linkage; // Convert #[link_name/no_mangle] attributes into the name - if( const auto* a = attrs.get("link_name") ) + if( g_ast_crate_ptr->m_test_harness && f.code().is_valid() ) + { + // If we're making a test harness, and this item defines code, don't apply the linkage rules + } + else if( const auto* a = attrs.get("link_name") ) { if( !a->has_string() ) ERROR(sp, E0000, "#[link_name] requires a string"); @@ -1758,6 +1763,7 @@ public: } g_crate_ptr = &rv; + g_ast_crate_ptr = &crate; g_crate_name = rv.m_crate_name; g_core_crate = (crate.m_load_std == ::AST::Crate::LOAD_NONE ? rv.m_crate_name : "core"); auto& macros = rv.m_exported_macros; @@ -1832,7 +1838,19 @@ public: const auto& name = lang.first; const auto& path = lang.second; auto irv = rv.m_lang_items.insert( ::std::make_pair(name, path) ); - if( irv.second == false && irv.first->second != path ) + if( irv.second == true ) + { + // Doesn't yet exist, all good + } + else if( irv.first->second == path ) + { + // Equal definitions, also good (TODO: How can this happen?) + } + else if( irv.first->second.m_components.empty() && path.m_components.empty() ) + { + // Both are just markers, also good (e.g. #![needs_panic_runtime]) + } + else { ERROR(sp, E0000, "Conflicting definitions of lang item '" << name << "'. " << path << " and " << irv.first->second); } diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index ee66ed5b..9f9bc1c3 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -10,6 +10,11 @@ #include "hir.hpp" #include <algorithm> #include <hir_typeck/common.hpp> +#include <hir_typeck/expr_visit.hpp> // for invoking typecheck +#include "item_path.hpp" +#include "expr_state.hpp" +#include <hir_expand/main_bindings.hpp> +#include <mir/main_bindings.hpp> namespace HIR { ::std::ostream& operator<<(::std::ostream& os, const ::HIR::Literal& v) @@ -1282,3 +1287,62 @@ bool ::HIR::Crate::find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type } return false; } + +const ::MIR::Function* HIR::Crate::get_or_gen_mir(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& ep, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_ty) const +{ + if( !ep ) + { + return &*ep.m_mir; + } + else + { + if( !ep.m_mir ) + { + ASSERT_BUG(Span(), ep.m_state, "No ExprState for " << ip); + + auto& ep_mut = const_cast<::HIR::ExprPtr&>(ep); + + // Ensure typechecked + if( ep.m_state->stage < ::HIR::ExprState::Stage::Typecheck ) + { + if( ep.m_state->stage == ::HIR::ExprState::Stage::TypecheckRequest ) + ERROR(Span(), E0000, "Loop in constant evaluation"); + ep.m_state->stage = ::HIR::ExprState::Stage::TypecheckRequest; + + // TODO: Set debug/timing stage + //Debug_SetStagePre("HIR Typecheck"); + // - Can store that on the Expr, OR get it from the item path + typeck::ModuleState ms { const_cast<::HIR::Crate&>(*this) }; + ms.m_impl_generics = ep.m_state->m_impl_generics; + ms.m_item_generics = ep.m_state->m_item_generics; + ms.m_traits = ep.m_state->m_traits; + Typecheck_Code(ms, const_cast<::HIR::Function::args_t&>(args), ret_ty, ep_mut); + //Debug_SetStagePre("Expand HIR Annotate"); + HIR_Expand_AnnotateUsage_Expr(*this, ep_mut); + //Debug_SetStagePre("Expand HIR Closures"); + HIR_Expand_Closures_Expr(*this, ep_mut); + //Debug_SetStagePre("Expand HIR Calls"); + HIR_Expand_UfcsEverything_Expr(*this, ep_mut); + //Debug_SetStagePre("Expand HIR Reborrows"); + HIR_Expand_Reborrows_Expr(*this, ep_mut); + //Debug_SetStagePre("Expand HIR ErasedType"); + //HIR_Expand_ErasedType(*this, ep_mut); // - Maybe? + //Typecheck_Expressions_Validate(*hir_crate); + + ep.m_state->stage = ::HIR::ExprState::Stage::Typecheck; + } + // Generate MIR + if( ep.m_state->stage < ::HIR::ExprState::Stage::Mir ) + { + if( ep.m_state->stage == ::HIR::ExprState::Stage::MirRequest ) + ERROR(Span(), E0000, "Loop in constant evaluation"); + ep.m_state->stage = ::HIR::ExprState::Stage::MirRequest; + //Debug_SetStage("Lower MIR"); + HIR_GenerateMIR_Expr(*this, ip, ep_mut, args, ret_ty); + ep.m_state->stage = ::HIR::ExprState::Stage::Mir; + } + assert(ep.m_mir); + } + return &*ep.m_mir; + } +} diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index d693c61d..33200e96 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -39,6 +39,8 @@ class Static; class ValueItem; class TypeItem; +class ItemPath; + template<typename Ent> struct VisEnt { @@ -346,6 +348,8 @@ public: // Contains types, traits, and modules ::std::unordered_map< ::std::string, ::std::unique_ptr<VisEnt<TypeItem>> > m_mod_items; + ::std::vector< ::std::pair<::std::string, Static> > m_inline_statics; + Module() {} Module(const Module&) = delete; Module(Module&& x) = default; @@ -536,6 +540,15 @@ public: bool find_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const; bool find_auto_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::MarkerImpl&)> callback) const; bool find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const; + + const ::MIR::Function* get_or_gen_mir(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& ep, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_ty) const; + const ::MIR::Function* get_or_gen_mir(const ::HIR::ItemPath& ip, const ::HIR::Function& fcn) const { + return get_or_gen_mir(ip, fcn.m_code, fcn.m_args, fcn.m_return); + } + const ::MIR::Function* get_or_gen_mir(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& ep, const ::HIR::TypeRef& exp_ty) const { + static ::HIR::Function::args_t s_args; + return get_or_gen_mir(ip, ep, s_args, exp_ty); + } }; } // namespace HIR diff --git a/src/hir/item_path.hpp b/src/hir/item_path.hpp index 11e3b0f4..d19435eb 100644 --- a/src/hir/item_path.hpp +++ b/src/hir/item_path.hpp @@ -18,12 +18,17 @@ public: const ::HIR::PathParams* trait_params = nullptr; const char* name = nullptr; const char* crate_name = nullptr; + const ::HIR::Path* wrapped = nullptr; ItemPath(const ::std::string& crate): crate_name(crate.c_str()) {} ItemPath(const ItemPath& p, const char* n): parent(&p), name(n) {} + ItemPath(const ::HIR::Path& p): + wrapped(&p) + { + } ItemPath(const ::HIR::TypeRef& type): ty(&type) {} @@ -40,7 +45,14 @@ public: const ::HIR::PathParams* trait_args() const { return trait_params; } ::HIR::SimplePath get_simple_path() const { - if( parent ) { + if( wrapped ) { + assert(wrapped->m_data.is_Generic()); + return wrapped->m_data.as_Generic().m_path; + } + else if( trait && !name ) { + return trait->clone(); + } + else if( parent ) { assert(name); return parent->get_simple_path() + name; } @@ -51,6 +63,9 @@ public: } } ::HIR::Path get_full_path() const { + if( wrapped ) { + return wrapped->clone(); + } assert(parent); assert(name); @@ -95,6 +110,9 @@ public: } friend ::std::ostream& operator<<(::std::ostream& os, const ItemPath& x) { + if( x.wrapped ) { + return os << *x.wrapped; + } if( x.parent ) { os << *x.parent; } |