diff options
| author | John Hodge (Mutabah) <acessdev@gmail.com> | 2018-09-30 21:35:32 +0800 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-30 21:35:32 +0800 | 
| commit | bd3d69813cc54439fdc0db33943fa1254db3df06 (patch) | |
| tree | 389b3f9fff419bd38275fddbf63fcbf3142d2f1c | |
| parent | d85ac84278fa0322f1df0b16a45a1cdde83cba57 (diff) | |
| parent | fe8018c3b2e2be2c3153a5c1a1bb73cd9c6ca370 (diff) | |
| download | mrust-bd3d69813cc54439fdc0db33943fa1254db3df06.tar.gz | |
Merge pull request #84 from thepowersgang/ondemand-generation
Generate MIR when required for constant evaluation
31 files changed, 844 insertions, 1938 deletions
| @@ -106,7 +106,6 @@ OBJ += hir_typeck/expr_check.o  OBJ += hir_expand/annotate_value_usage.o hir_expand/closures.o  OBJ += hir_expand/ufcs_everything.o  OBJ += hir_expand/reborrow.o hir_expand/erased_types.o hir_expand/vtable.o -OBJ += hir_expand/const_eval_full.o  OBJ += mir/mir.o mir/mir_ptr.o  OBJ +=  mir/dump.o mir/helpers.o mir/visit_crate_mir.o  OBJ +=  mir/from_hir.o mir/from_hir_match.o mir/mir_builder.o 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/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 20b9ad58..8024e1c0 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -38,6 +38,8 @@ class Static;  class ValueItem;  class TypeItem; +class ItemPath; +  template<typename Ent>  struct VisEnt  { @@ -343,6 +345,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; @@ -533,6 +537,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;          } diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 5418da85..227ccd9f 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -13,6 +13,8 @@  #include <algorithm>    // std::find_if  #include <hir_typeck/static.hpp> +#include <hir_typeck/expr_visit.hpp>    // For ModuleState +#include <hir/expr_state.hpp>  void ConvertHIR_Bind(::HIR::Crate& crate); @@ -95,10 +97,35 @@ namespace {      {          const ::HIR::Crate& m_crate; +        typeck::ModuleState m_ms; + +        struct CurMod { +            const ::HIR::Module* ptr; +            const ::HIR::ItemPath*  path; +        } m_cur_module; +      public:          Visitor(const ::HIR::Crate& crate): -            m_crate(crate) -        {} +            m_crate(crate), +            m_ms(crate) +        { +            static ::HIR::ItemPath  root_path(""); +            m_cur_module.ptr = &crate.m_root_module; +            m_cur_module.path = &root_path; +        } + +        void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override +        { +            auto parent_mod = m_cur_module; +            m_cur_module.ptr = &mod; +            m_cur_module.path = &p; + +            m_ms.push_traits(mod); +            ::HIR::Visitor::visit_module(p, mod); +            m_ms.pop_traits(mod); + +            m_cur_module = parent_mod; +        }          void visit_trait_path(::HIR::TraitPath& p) override          { @@ -400,17 +427,86 @@ namespace {              ::HIR::Visitor::visit_type(ty);          } -        void visit_static(::HIR::ItemPath p, ::HIR::Static& i) override +        void visit_type_impl(::HIR::TypeImpl& impl) override          { -            ::HIR::Visitor::visit_static(p, i); -            visit_literal(Span(), i.m_value_res); +            TRACE_FUNCTION_F("impl " << impl.m_type); +            auto _ = this->m_ms.set_impl_generics(impl.m_params); + +            const auto* mod = (impl.m_src_module != ::HIR::SimplePath() ? &this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module) : nullptr); +            if(mod) +                m_ms.push_traits(*mod); +            ::HIR::Visitor::visit_type_impl(impl); +            if(mod) +                m_ms.pop_traits(*mod);          } -        void visit_constant(::HIR::ItemPath p, ::HIR::Constant& i) override +        void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override          { -            ::HIR::Visitor::visit_constant(p, i); -            visit_literal(Span(), i.m_value_res); +            TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type); +            auto _ = this->m_ms.set_impl_generics(impl.m_params); + +            const auto* mod = (impl.m_src_module != ::HIR::SimplePath() ? &this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module) : nullptr); +            if(mod) +                m_ms.push_traits(*mod); +            m_ms.m_traits.push_back( ::std::make_pair( &trait_path, &this->m_ms.m_crate.get_trait_by_path(Span(), trait_path) ) ); +            ::HIR::Visitor::visit_trait_impl(trait_path, impl); +            m_ms.m_traits.pop_back( ); +            if(mod) +                m_ms.pop_traits(*mod); +        } +        void visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HIR::MarkerImpl& impl) override +        { +            TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type << " { }"); +            auto _ = this->m_ms.set_impl_generics(impl.m_params); + +            const auto* mod = (impl.m_src_module != ::HIR::SimplePath() ? &this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module) : nullptr); +            if(mod) +                m_ms.push_traits(*mod); +            ::HIR::Visitor::visit_marker_impl(trait_path, impl); +            if(mod) +                m_ms.pop_traits(*mod);          } +        void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override +        { +            auto _ = this->m_ms.set_impl_generics(item.m_params); +            ::HIR::Visitor::visit_trait(p, item); +        } +        // TODO: Are generics for types "item" or "impl"? +        void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override +        { +            auto _ = this->m_ms.set_item_generics(item.m_params); +            ::HIR::Visitor::visit_enum(p, item); +        } +        void visit_struct(::HIR::ItemPath p, ::HIR::Struct& item) override +        { +            auto _ = this->m_ms.set_item_generics(item.m_params); +            ::HIR::Visitor::visit_struct(p, item); +        } +        void visit_union(::HIR::ItemPath p, ::HIR::Union& item) override +        { +            auto _ = this->m_ms.set_item_generics(item.m_params); +            ::HIR::Visitor::visit_union(p, item); +        } + +        void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override +        { +            auto _ = this->m_ms.set_item_generics(item.m_params); +            ::HIR::Visitor::visit_function(p, item); +        } +        void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override +        { +            //auto _ = this->m_ms.set_item_generics(item.m_params); +            ::HIR::Visitor::visit_static(p, item); +            visit_literal(Span(), item.m_value_res); +        } +        void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override +        { +            auto _ = this->m_ms.set_item_generics(item.m_params); +            ::HIR::Visitor::visit_constant(p, item); +            visit_literal(Span(), item.m_value_res); +        } + +        // Actual expressions          void visit_expr(::HIR::ExprPtr& expr) override          {              struct ExprVisitor: @@ -473,6 +569,11 @@ namespace {                      upper_visitor.visit_generic_path(node.m_path, ::HIR::Visitor::PathContext::TYPE);                      ::HIR::ExprVisitorDef::visit(node);                  } +                void visit(::HIR::ExprNode_ArraySized& node) override +                { +                    upper_visitor.visit_expr(node.m_size); +                    ::HIR::ExprVisitorDef::visit(node); +                }                  void visit(::HIR::ExprNode_Closure& node) override                  { @@ -488,12 +589,22 @@ namespace {              for(auto& ty : expr.m_erased_types)                  visit_type(ty); +            // Set up the module state +            { +                expr.m_state = ::HIR::ExprStatePtr(::HIR::ExprState(*m_cur_module.ptr, m_cur_module.path->get_simple_path())); +                expr.m_state->m_traits = m_ms.m_traits; // TODO: Only obtain the current module's set +                expr.m_state->m_impl_generics = m_ms.m_impl_generics; +                expr.m_state->m_item_generics = m_ms.m_item_generics; +            } + +            // Local expression              if( expr.get() != nullptr )              {                  ExprVisitor v { *this };                  (*expr).visit(v);              } -            else if( expr.m_mir ) +            // External expression (has MIR) +            else if( auto* mir = expr.get_ext_mir_mut() )              {                  struct H {                      static void visit_lvalue(Visitor& upper_visitor, ::MIR::LValue& lv) @@ -546,9 +657,9 @@ namespace {                          )                      }                  }; -                for(auto& ty : expr.m_mir->locals) +                for(auto& ty : mir->locals)                      this->visit_type(ty); -                for(auto& block : expr.m_mir->blocks) +                for(auto& block : mir->blocks)                  {                      for(auto& stmt : block.statements)                      { diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 5a41e954..ec313e4a 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -14,18 +14,17 @@  #include <hir_typeck/common.hpp>    // Monomorph  #include <mir/helpers.hpp>  #include <trans/target.hpp> +#include <hir/expr_state.hpp>  namespace { -    typedef ::std::vector< ::std::pair< ::std::string, ::HIR::Static> > t_new_values; -      struct NewvalState { -        t_new_values&   newval_output; +        const ::HIR::Module&   mod;          const ::HIR::ItemPath&  mod_path;          ::std::string   name_prefix;          unsigned int next_item_idx; -        NewvalState(t_new_values& newval_output, const ::HIR::ItemPath& mod_path, ::std::string prefix): -            newval_output(newval_output), +        NewvalState(const ::HIR::Module& mod, const ::HIR::ItemPath& mod_path, ::std::string prefix): +            mod(mod),              mod_path(mod_path),              name_prefix(prefix),              next_item_idx(0) @@ -36,8 +35,9 @@ namespace {          {              auto name = FMT(name_prefix << next_item_idx);              next_item_idx ++; -            auto rv = (mod_path + name.c_str()).get_simple_path(); -            newval_output.push_back( ::std::make_pair( mv$(name), ::HIR::Static { +            DEBUG("mod_path = " << mod_path); +            auto rv = mod_path.get_simple_path() + name.c_str(); +            const_cast<::HIR::Module&>(mod).m_inline_statics.push_back( ::std::make_pair( mv$(name), ::HIR::Static {                  ::HIR::Linkage {},                  false,                  mv$(type), @@ -47,8 +47,23 @@ namespace {              return rv;          }      }; +    struct Evaluator +    { +        const Span& root_span; +        StaticTraitResolve  resolve; +        NewvalState nvs; + +        Evaluator(const Span& sp, const ::HIR::Crate& crate, NewvalState nvs): +            root_span(sp), +            resolve(crate), +            nvs( ::std::move(nvs) ) +        { +        } + +        ::HIR::Literal evaluate_constant(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp); -    ::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args={}); +        ::HIR::Literal evaluate_constant_mir(const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args); +    };      ::HIR::Literal clone_literal(const ::HIR::Literal& v)      { @@ -155,10 +170,12 @@ namespace {          }          throw "";      } -    EntPtr get_ent_fullpath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, EntNS ns) +    EntPtr get_ent_fullpath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, EntNS ns, MonomorphState& out_ms)      {          TU_MATCH(::HIR::Path::Data, (path.m_data), (e),          (Generic, +            out_ms = MonomorphState {}; +            out_ms.pp_method = &e.m_params;              return get_ent_simplepath(sp, crate, e.m_path, ns);              ),          (UfcsInherent, @@ -191,6 +208,9 @@ namespace {                  }                  return false;                  }); +            out_ms = MonomorphState {}; +            out_ms.pp_method = &e.params; +            out_ms.pp_impl = &e.impl_params;              return rv;              ),          (UfcsKnown, @@ -225,6 +245,9 @@ namespace {                  }                  return false;                  }); +            out_ms = MonomorphState {}; +            out_ms.pp_method = &e.params; +            // TODO: How to get pp_impl here? Needs specialisation magic.              return rv;              ),          (UfcsUnknown, @@ -234,9 +257,9 @@ namespace {          )          throw "";      } -    const ::HIR::Function& get_function(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path) +    const ::HIR::Function& get_function(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, MonomorphState& out_ms)      { -        auto rv = get_ent_fullpath(sp, crate, path, EntNS::Value); +        auto rv = get_ent_fullpath(sp, crate, path, EntNS::Value, out_ms);          TU_IFLET( EntPtr, rv, Function, e,              return *e;          ) @@ -245,845 +268,114 @@ namespace {          }      } -    ::HIR::Literal evaluate_constant_hir(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprNode& expr, ::HIR::TypeRef exp_type, ::std::vector< ::HIR::Literal> args) +    ::HIR::Literal Evaluator::evaluate_constant_mir(const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args)      { -        // TODO: Force this function/tree through the entire pipeline so we can MIR it? -        // - Requires a HUGE change to the way the compiler operates. -        struct Visitor: -            public ::HIR::ExprVisitor -        { -            const ::HIR::Crate& m_crate; -            NewvalState m_newval_state; - -            ::std::vector< ::HIR::Literal>   m_values; - -            ::HIR::TypeRef  m_exp_type; -            ::HIR::TypeRef  m_rv_type; -            ::HIR::Literal  m_rv; - -            Visitor(const ::HIR::Crate& crate, NewvalState newval_state, ::HIR::TypeRef exp_ty): -                m_crate(crate), -                m_newval_state( mv$(newval_state) ), -                m_exp_type( mv$(exp_ty) ) -            {} - -            void badnode(const ::HIR::ExprNode& node) const { -                ERROR(node.span(), E0000, "Node " << typeid(node).name() << " not allowed in constant expression"); -            } - -            void visit(::HIR::ExprNode_Block& node) override { -                TRACE_FUNCTION_F("_Block"); - -                for(const auto& e : node.m_nodes) -                { -                    e->visit(*this); -                } -                if( node.m_value_node ) -                    node.m_value_node->visit(*this); -                else -                    ; -            } -            void visit(::HIR::ExprNode_Asm& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_Return& node) override { -                TODO(node.span(), "ExprNode_Return"); -            } -            void visit(::HIR::ExprNode_Let& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_Loop& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_LoopControl& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_Match& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_If& node) override { -                badnode(node); -            } - -            void visit(::HIR::ExprNode_Assign& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_BinOp& node) override { -                TRACE_FUNCTION_F("_BinOp"); - -                node.m_left->visit(*this); -                auto left = mv$(m_rv); -                auto ret_type = mv$(m_rv_type); - -                node.m_right->visit(*this); -                auto right = mv$(m_rv); - -                if( left.tag() != right.tag() ) { -                    ERROR(node.span(), E0000, "ExprNode_BinOp - Types mismatched - " << left.tag_str() << " != " << right.tag_str()); -                } - -                // Keep m_rv_type -                switch(node.m_op) -                { -                case ::HIR::ExprNode_BinOp::Op::CmpEqu: -                case ::HIR::ExprNode_BinOp::Op::CmpNEqu: -                case ::HIR::ExprNode_BinOp::Op::CmpLt: -                case ::HIR::ExprNode_BinOp::Op::CmpLtE: -                case ::HIR::ExprNode_BinOp::Op::CmpGt: -                case ::HIR::ExprNode_BinOp::Op::CmpGtE: -                    ERROR(node.span(), E0000, "ExprNode_BinOp - Comparisons"); -                    break; -                case ::HIR::ExprNode_BinOp::Op::BoolAnd: -                case ::HIR::ExprNode_BinOp::Op::BoolOr: -                    ERROR(node.span(), E0000, "ExprNode_BinOp - Logicals"); -                    break; +        // TODO: Full-blown miri +        TRACE_FUNCTION_F("exp=" << exp << ", args=" << args); -                case ::HIR::ExprNode_BinOp::Op::Add: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le + re); ), -                    (Float,     m_rv = ::HIR::Literal(le + re); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Sub: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le - re); ), -                    (Float,     m_rv = ::HIR::Literal(le - re); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Mul: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le * re); ), -                    (Float,     m_rv = ::HIR::Literal(le * re); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Div: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le / re); ), -                    (Float,     m_rv = ::HIR::Literal(le / re); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Mod: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le % re); ), -                    (Float,     ERROR(node.span(), E0000, "modulo operator on float in constant"); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::And: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le % re); ), -                    (Float,     ERROR(node.span(), E0000, "bitwise and operator on float in constant"); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Or: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le | re); ), -                    (Float,     ERROR(node.span(), E0000, "bitwise or operator on float in constant"); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Xor: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le ^ re); ), -                    (Float,     ERROR(node.span(), E0000, "bitwise xor operator on float in constant"); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Shr: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le >> re); ), -                    (Float,     ERROR(node.span(), E0000, "bitwise shift right operator on float in constant"); ) -                    ) -                    break; -                case ::HIR::ExprNode_BinOp::Op::Shl: -                    TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(le << re); ), -                    (Float,     ERROR(node.span(), E0000, "bitwise shift left operator on float in constant"); ) -                    ) -                    break; -                } +        ::MIR::TypeResolve  state { this->root_span, this->resolve, FMT_CB(,), exp, {}, fcn }; -                m_rv_type = mv$(ret_type); -            } -            void visit(::HIR::ExprNode_UniOp& node) override { -                TRACE_FUNCTION_FR("_UniOp", m_rv); +        ::HIR::Literal  retval; +        ::std::vector< ::HIR::Literal>  locals( fcn.locals.size() ); -                auto exp_type = m_exp_type.clone(); -                node.m_value->visit(*this); -                auto val = mv$(m_rv); +        struct LocalState { +            typedef ::std::vector< ::HIR::Literal>  t_vec_lit; +            ::MIR::TypeResolve& state; +            ::HIR::Literal&  retval; +            ::std::vector< ::HIR::Literal>&  args; +            ::std::vector< ::HIR::Literal>&  locals; -                // Keep m_rv_type -                switch(node.m_op) -                { -                case ::HIR::ExprNode_UniOp::Op::Invert: -                    TU_MATCH_DEF(::HIR::Literal, (val), (e), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal::make_Integer(~e); ), -                    (Float,     ERROR(node.span(), E0000, "not operator on float in constant"); ) -                    ) -                    break; -                case ::HIR::ExprNode_UniOp::Op::Negate: -                    TU_MATCH_DEF(::HIR::Literal, (val), (e), -                    ( throw ""; ), -                    (Integer,   m_rv = ::HIR::Literal(static_cast<uint64_t>(-static_cast<int64_t>(e))); ), -                    (Float,     m_rv = ::HIR::Literal(-e); ) -                    ) -                    break; -                } -                m_rv_type = mv$(exp_type); -            } -            void visit(::HIR::ExprNode_Borrow& node) override { +            LocalState(::MIR::TypeResolve& state, ::HIR::Literal& retval, t_vec_lit& args, t_vec_lit& locals): +                state(state), +                retval(retval), +                args(args), +                locals(locals) +            {} -                ::HIR::TypeRef  exp_ty_inner; -                TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_exp_type.m_data), (te), -                ( -                    //ERROR(node.span(), E0000, "Invalid expected type for a &-ptr - " << m_exp_type); -                    DEBUG("_Borrow: Unknown " << m_exp_type); -                    exp_ty_inner = m_exp_type.clone(); +            ::HIR::Literal& get_lval(const ::MIR::LValue& lv) +            { +                TU_MATCHA( (lv), (e), +                (Return, +                    return retval;                      ), -                (Infer, +                (Local, +                    if( e >= locals.size() ) +                        MIR_BUG(state, "Local index out of range - " << e << " >= " << locals.size()); +                    return locals[e];                      ), -                (Borrow, -                    exp_ty_inner = mv$( *te.inner ); -                    DEBUG("_Borrow: borrow expecting inner " << exp_ty_inner); -                    ) -                ) - -                m_exp_type = exp_ty_inner.clone(); -                node.m_value->visit(*this); -                auto val = mv$(m_rv); - -                if( node.m_type != ::HIR::BorrowType::Shared ) { -                    ERROR(node.span(), E0000, "Only shared borrows are allowed in constants"); -                } - -                if( visit_ty_with(m_rv_type, [&](const auto& x){ return x.m_data.is_Infer(); }) ) { -                    if( visit_ty_with(exp_ty_inner, [&](const auto& x){ return x.m_data.is_Infer(); }) ) { -                        ERROR(node.span(), E0000, "Could not trivially infer type of referenced static - " << m_rv_type << ", lit = " << val << ", exp=&" << exp_ty_inner); -                    } -                    else { -                        m_rv_type = mv$(exp_ty_inner); -                    } -                } - -                m_rv_type = ::HIR::TypeRef::new_borrow( node.m_type, mv$(m_rv_type) ); -                m_rv = ::HIR::Literal::make_BorrowData( box$(val) ); -            } -            void visit(::HIR::ExprNode_Cast& node) override { -                TRACE_FUNCTION_F("_Cast"); - -                m_exp_type = ::HIR::TypeRef();  // Can't know. - -                node.m_value->visit(*this); -                auto val = mv$(m_rv); -                //DEBUG("ExprNode_Cast - val = " << val << " as " << node.m_type); -                TU_MATCH_DEF( ::HIR::TypeRef::Data, (node.m_res_type.m_data), (te), -                ( -                    m_rv = mv$(val); +                (Argument, +                    if( e.idx >= args.size() ) +                        MIR_BUG(state, "Local index out of range - " << e.idx << " >= " << args.size()); +                    return args[e.idx];                      ), -                (Primitive, -                    switch(te) -                    { -                    case ::HIR::CoreType::F32: -                    case ::HIR::CoreType::F64: -                        TU_MATCH_DEF( ::HIR::Literal, (val), (ve), -                        ( BUG(node.span(), "Cast to float, bad literal " << val.tag_str()); ), -                        (Float, -                            m_rv = mv$(val); -                            ), -                        (Integer, -                            m_rv = ::HIR::Literal(static_cast<double>(ve)); -                            ) -                        ) -                        break; -                    case ::HIR::CoreType::I8:   case ::HIR::CoreType::U8: -                    case ::HIR::CoreType::I16:  case ::HIR::CoreType::U16: -                    case ::HIR::CoreType::I32:  case ::HIR::CoreType::U32: -                    case ::HIR::CoreType::I64:  case ::HIR::CoreType::U64: -                    case ::HIR::CoreType::I128: case ::HIR::CoreType::U128: -                    case ::HIR::CoreType::Isize:  case ::HIR::CoreType::Usize: -                        TU_MATCH_DEF( ::HIR::Literal, (val), (ve), -                        ( BUG(node.span(), "Cast to float, bad literal " << val.tag_str()); ), -                        (Integer, -                            m_rv = mv$(val); -                            ), -                        (Float, -                            m_rv = ::HIR::Literal(static_cast<uint64_t>(ve)); -                            ) -                        ) -                        break; -                    default: -                        m_rv = mv$(val); -                        break; -                    } -                    ) -                ) -                m_rv_type = node.m_res_type.clone(); -            } -            void visit(::HIR::ExprNode_Unsize& node) override { -                TRACE_FUNCTION_F("_Unsize"); -                m_exp_type = ::HIR::TypeRef();  // Can't know. -                node.m_value->visit(*this); -                //auto val = mv$(m_rv); -                //DEBUG("ExprNode_Unsize - val = " << val << " as " << node.m_type); -                m_rv_type = node.m_res_type.clone(); -            } -            void visit(::HIR::ExprNode_Index& node) override { - -                auto exp_ty = mv$(m_exp_type); -                // Index -                m_exp_type = ::HIR::TypeRef(::HIR::CoreType::Usize); -                node.m_index->visit(*this); -                if( !m_rv.is_Integer() ) -                    ERROR(node.span(), E0000, "Array index isn't an integer - got " << m_rv.tag_str()); -                auto idx = static_cast<size_t>( m_rv.as_Integer() ); - -                // Value -                m_exp_type = ::HIR::TypeRef::new_slice( mv$(exp_ty) ); -                node.m_value->visit(*this); -                if( !m_rv.is_List() ) -                    ERROR(node.span(), E0000, "Indexed value isn't a list - got " << m_rv.tag_str()); -                auto v = mv$( m_rv.as_List() ); - -                // -> Perform -                if( idx >= v.size() ) -                    ERROR(node.span(), E0000, "Constant array index " << idx << " out of range " << v.size()); -                m_rv = mv$(v[idx]); - -                TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_rv_type.m_data), (e), -                ( -                    ERROR(node.span(), E0000, "Indexing non-array - " << m_rv_type); +                (Static, +                    MIR_TODO(state, "LValue::Static - " << e);                      ), -                (Array, -                    auto tmp = mv$(e.inner); -                    m_rv_type = mv$(*tmp); -                    ) -                ) -            } -            void visit(::HIR::ExprNode_Deref& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_Emplace& node) override { -                badnode(node); -            } - -            void visit(::HIR::ExprNode_TupleVariant& node) override { -                m_exp_type = ::HIR::TypeRef(); - -                ::std::vector< ::HIR::Literal>  vals; -                for(const auto& vn : node.m_args ) { -                    vn->visit(*this); -                    assert( !m_rv.is_Invalid() ); -                    vals.push_back( mv$(m_rv) ); -                } - -                if( node.m_is_struct ) -                { -                    const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path); -                    ASSERT_BUG(node.span(), ent.is_Struct(), "_TupleVariant with m_is_struct set pointing to " << ent.tag_str()); -                    const auto& str = ent.as_Struct(); - -                    m_rv = ::HIR::Literal::make_List(mv$(vals)); -                    m_rv_type = ::HIR::TypeRef::new_path( node.m_path.clone(), ::HIR::TypeRef::TypePathBinding(&str) ); -                } -                else -                { -                    const auto& varname = node.m_path.m_path.m_components.back(); -                    auto tmp_path = node.m_path.m_path; -                    tmp_path.m_components.pop_back(); -                    const auto& ent = m_crate.get_typeitem_by_path(node.span(), tmp_path); -                    ASSERT_BUG(node.span(), ent.is_Enum(), "_TupleVariant with m_is_struct clear pointing to " << ent.tag_str()); -                    const auto& enm = ent.as_Enum(); - -                    auto var_idx = enm.find_variant(varname); -                    ASSERT_BUG(node.span(), var_idx != SIZE_MAX, "_TupleVariant points to unknown variant - " << node.m_path); - -                    auto inner = box$( ::HIR::Literal::make_List(mv$(vals)) ); -                    m_rv = ::HIR::Literal::make_Variant({ static_cast<unsigned>(var_idx), mv$(inner) }); -                    m_rv_type = ::HIR::TypeRef::new_path( mv$(tmp_path), ::HIR::TypeRef::TypePathBinding(&enm) ); -                } -            } -            void visit(::HIR::ExprNode_CallPath& node) override -            { - -                TRACE_FUNCTION_FR("_CallPath - " << node.m_path, m_rv); -                auto& fcn = get_function(node.span(), m_crate, node.m_path); - -                // TODO: Set m_const during parse -                //if( ! fcn.m_const ) { -                //    ERROR(node.span(), E0000, "Calling non-const function in const context - " << node.m_path); -                //} - -                if( fcn.m_args.size() != node.m_args.size() ) { -                    ERROR(node.span(), E0000, "Incorrect argument count for " << node.m_path << " - expected " << fcn.m_args.size() << ", got " << node.m_args.size()); -                } -                auto exp_ret_type = mv$( m_exp_type ); - -                ::std::vector< ::HIR::Literal>  args; -                args.reserve( fcn.m_args.size() ); -                for(unsigned int i = 0; i < fcn.m_args.size(); i ++ ) -                { -                    const auto& pattern = fcn.m_args[i].first; -                    if( monomorphise_type_needed(fcn.m_args[i].second) ) { -                        m_exp_type = ::HIR::TypeRef(); -                    } -                    else { -                        m_exp_type = fcn.m_args[i].second.clone(); -                    } -                    TU_IFLET(::HIR::Pattern::Data, pattern.m_data, Any, e, -                        // Good -                    ) -                    else { -                        ERROR(node.span(), E0000, "Constant functions can't have destructuring pattern argments"); -                    } - -                    node.m_args[i]->visit(*this); -                    args.push_back( mv$(m_rv) ); -                } - -                exp_ret_type = fcn.m_return.clone(); - -                // Call by invoking evaluate_constant on the function -                { -                    TRACE_FUNCTION_F("Call const fn " << node.m_path << " args={ " << args << " }"); -                    m_rv = evaluate_constant(node.span(), m_crate, m_newval_state,  fcn.m_code, mv$(exp_ret_type), mv$(args)); -                } -            } -            void visit(::HIR::ExprNode_CallValue& node) override { -                badnode(node); -            } -            void visit(::HIR::ExprNode_CallMethod& node) override { -                // TODO: const methods -                badnode(node); -            } -            void visit(::HIR::ExprNode_Field& node) override { -                const auto& sp = node.span(); -                TRACE_FUNCTION_FR("_Field", m_rv); - -                m_exp_type = ::HIR::TypeRef(); - -                node.m_value->visit(*this); -                auto val = mv$( m_rv ); - -                if( !val.is_List() ) -                    ERROR(sp, E0000, "Field access on invalid literal type - " << val.tag_str()); -                auto& vals = val.as_List(); - -                ::HIR::TypeRef  ty = mv$(m_rv_type); -                TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (e), -                ( -                    ERROR(sp, E0000, "Field access on invalid type - " << ty); +                (Field, +                    auto& val = get_lval(*e.val); +                    MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv); +                    auto& vals = val.as_List(); +                    MIR_ASSERT(state, e.field_index < vals.size(), "LValue::Field index out of range"); +                    return vals[ e.field_index ];                      ), -                (Path, -                    TU_MATCHA( (e.binding), (pbe), -                    (Unbound, -                        ERROR(sp, E0000, "Field access on invalid type - " << ty); -                        ), -                    (Opaque, -                        ERROR(sp, E0000, "Field access on invalid type - " << ty); -                        ), -                    (Struct, -                        auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &e.path.m_data.as_Generic().m_params, nullptr); -                        const auto& str = *pbe; -                        unsigned int idx=0; -                        TU_MATCHA( (str.m_data), (se), -                        (Unit, -                            ERROR(sp, E0000, "Field access on invalid type - " << ty << " - Unit-like"); -                            ), -                        (Tuple, -                            idx = ::std::atoi( node.m_field.c_str() ); -                            ASSERT_BUG(sp, idx < se.size(), "Index out of range in tuple struct"); -                            m_rv_type = monomorphise_type_with(sp, se[idx].ent, monomorph_cb); -                            ), -                        (Named, -                            idx = ::std::find_if(se.begin(), se.end(), [&](const auto&x){return x.first==node.m_field;}) - se.begin(); -                            ASSERT_BUG(sp, idx < se.size(), "Field no found in struct"); -                            m_rv_type = monomorphise_type_with(sp, se[idx].second.ent, monomorph_cb); -                            ) -                        ) -                        ASSERT_BUG(sp, idx < vals.size(), "Index out of range in literal"); -                        m_rv = mv$( vals[idx] ); +                (Deref, +                    auto& val = get_lval(*e.val); +                    TU_MATCH_DEF( ::HIR::Literal, (val), (ve), +                    ( +                        MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }");                          ), -                    (Enum, -                        TODO(sp, "Field access on enum variant - " << ty); +                    (BorrowData, +                        return *ve;                          ), -                    (Union, -                        TODO(sp, "Field access on union - " << ty); +                    (String, +                        // Just clone the string (hack) +                        // - TODO: Create a list? +                        return val;                          )                      )                      ), -                (Tuple, -                    unsigned int idx = ::std::atoi( node.m_field.c_str() ); -                    ASSERT_BUG(sp, idx < e.size(), "Index out of range in tuple"); -                    ASSERT_BUG(sp, idx < vals.size(), "Index out of range in literal"); - -                    m_rv = mv$( vals[idx] ); -                    m_rv_type = mv$( e[idx] ); -                    ) -                ) -            } - -            void visit(::HIR::ExprNode_Literal& node) override { -                TRACE_FUNCTION_FR("_Literal", m_rv); -                TU_MATCH(::HIR::ExprNode_Literal::Data, (node.m_data), (e), -                (Integer, -                    m_rv = ::HIR::Literal(e.m_value); -                    m_rv_type = mv$(m_exp_type); -                    ), -                (Float, -                    m_rv = ::HIR::Literal(e.m_value); -                    m_rv_type = mv$(m_exp_type); -                    ), -                (Boolean, -                    m_rv = ::HIR::Literal(static_cast<uint64_t>(e)); -                    m_rv_type = ::HIR::CoreType::Bool; +                (Index, +                    auto& val = get_lval(*e.val); +                    MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv); +                    auto& idx = get_lval(*e.idx); +                    MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv); +                    auto& vals = val.as_List(); +                    auto idx_v = static_cast<size_t>( idx.as_Integer() ); +                    MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range"); +                    return vals[ idx_v ];                      ), -                (String, -                    m_rv = ::HIR::Literal(e); -                    m_rv_type = ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ::HIR::CoreType::Str ); -                    ), -                (ByteString, -                    m_rv = ::HIR::Literal::make_String({e.begin(), e.end()}); -                    m_rv_type = ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ::HIR::TypeRef::new_array(::HIR::CoreType::U8, e.size()) ); +                (Downcast, +                    MIR_TODO(state, "LValue::Downcast - " << lv);                      )                  ) +                throw "";              } -            void visit(::HIR::ExprNode_UnitVariant& node) override { -                if( node.m_is_struct ) -                { -                    const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path); -                    ASSERT_BUG(node.span(), ent.is_Struct(), "_UnitVariant with m_is_struct set pointing to " << ent.tag_str()); -                    const auto& str = ent.as_Struct(); - -                    m_rv = ::HIR::Literal::make_List({}); -                    m_rv_type = ::HIR::TypeRef::new_path( node.m_path.clone(), ::HIR::TypeRef::TypePathBinding(&str) ); -                } -                else -                { -                    const auto& varname = node.m_path.m_path.m_components.back(); -                    auto tmp_path = node.m_path.m_path; -                    tmp_path.m_components.pop_back(); -                    const auto& ent = m_crate.get_typeitem_by_path(node.span(), tmp_path); -                    ASSERT_BUG(node.span(), ent.is_Enum(), "_UnitVariant with m_is_struct clear pointing to " << ent.tag_str()); -                    const auto& enm = ent.as_Enum(); - -                    auto var_idx = enm.find_variant(varname); -                    ASSERT_BUG(node.span(), var_idx != SIZE_MAX, "_UnitVariant points to unknown variant - " << node.m_path); - -                    m_rv = ::HIR::Literal::make_Variant({ static_cast<unsigned>(var_idx), box$(::HIR::Literal::make_List({})) }); -                    m_rv_type = ::HIR::TypeRef::new_path( mv$(tmp_path), ::HIR::TypeRef::TypePathBinding(&enm) ); -                } -            } -            void visit(::HIR::ExprNode_PathValue& node) override { -                TRACE_FUNCTION_FR("_PathValue - " << node.m_path, m_rv); -                auto ep = get_ent_fullpath(node.span(), m_crate, node.m_path, EntNS::Value); -                TU_MATCH_DEF( EntPtr, (ep), (e), +            ::HIR::Literal read_lval(const ::MIR::LValue& lv) +            { +                auto& v = get_lval(lv); +                DEBUG(lv << " = " << v); +                TU_MATCH_DEF(::HIR::Literal, (v), (e),                  ( -                    BUG(node.span(), "Path value with unsupported value type - " << ep.tag_str()); -                    ), -                (Static, -                    // TODO: Should be a more complex path to support associated paths -                    ASSERT_BUG(node.span(), node.m_path.m_data.is_Generic(), "Static path not Path::Generic - " << node.m_path); -                    m_rv = ::HIR::Literal(node.m_path.m_data.as_Generic().m_path); -                    m_rv_type = e->m_type.clone(); +                    return mv$(v);                      ), -                (Function, -                    // TODO: Should be a more complex path to support associated paths -                    ASSERT_BUG(node.span(), node.m_path.m_data.is_Generic(), "Function path not Path::Generic - " << node.m_path); -                    m_rv = ::HIR::Literal(node.m_path.m_data.as_Generic().m_path); -                    ::HIR::FunctionType fcn; -                    fcn.m_rettype = box$( e->m_return.clone() ); -                    m_rv_type = ::HIR::TypeRef( mv$(fcn) );   // TODO: Better type +                (Invalid, +                    MIR_BUG(state, "Read of " << lv << " yielded Invalid");                      ), -                (Constant, -                    // TODO: Associated constants -                    const auto& c = *e; -                    if( c.m_value_res.is_Invalid() ) { -                        const_cast<HIR::ExprNode&>(*c.m_value).visit(*this); -                    } -                    else { -                        m_rv = clone_literal(c.m_value_res); -                    } -                    m_rv_type = e->m_type.clone(); -                    ) -                ) -            } -            void visit(::HIR::ExprNode_Variable& node) override { -                TRACE_FUNCTION_FR("_Variable - " << node.m_name, m_rv); -                // TODO: use the binding? -                if( node.m_slot >= m_values.size() ) { -                    ERROR(node.span(), E0000, "Couldn't find variable #" << node.m_slot << " " << node.m_name); -                } -                auto& v = m_values.at( node.m_slot ); -                TU_MATCH_DEF(::HIR::Literal, (v), (e), -                ( -                    m_rv = mv$(v); +                (BorrowPath, +                    return ::HIR::Literal(e.clone());                      ),                  (Integer, -                    m_rv = ::HIR::Literal(e); +                    return ::HIR::Literal(e);                      ),                  (Float, -                    m_rv = ::HIR::Literal(e); -                    ) -                ) -                m_rv_type = ::HIR::TypeRef();    // TODO: -            } - -            void visit(::HIR::ExprNode_StructLiteral& node) override { -                TRACE_FUNCTION_FR("_StructLiteral - " << node.m_path, m_rv); - -                if( node.m_is_struct ) -                { -                    const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path); -                    ASSERT_BUG(node.span(), ent.is_Struct(), "_StructLiteral with m_is_struct set pointing to a " << ent.tag_str()); -                    const auto& str = ent.as_Struct(); -                    const auto& fields = str.m_data.as_Named(); - -                    auto rv_type = ::HIR::TypeRef::new_path( node.m_path.clone(), ::HIR::TypeRef::TypePathBinding(&str) ); - -                    ::std::vector< ::HIR::Literal>  vals; -                    if( node.m_base_value ) -                    { -                        m_exp_type = rv_type.clone(); - -                        node.m_base_value->visit(*this); -                        auto base_val = mv$(m_rv); -                        if( !base_val.is_List() || base_val.as_List().size() != fields.size() ) { -                            BUG(node.span(), "Struct literal base value had an incorrect field count"); -                        } -                        vals = mv$(base_val.as_List()); -                    } -                    else { -                        vals.resize( fields.size() ); -                    } -                    for( const auto& val_set : node.m_values ) { -                        unsigned int idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& v) { return v.first == val_set.first; } ) - fields.begin(); -                        if( idx == fields.size() ) { -                            ERROR(node.span(), E0000, "Field name " << val_set.first << " isn't a member of " << node.m_path); -                        } - -                        if( monomorphise_type_needed(fields[idx].second.ent) ) { -                            m_exp_type = ::HIR::TypeRef(); -                        } -                        else { -                            m_exp_type = fields[idx].second.ent.clone(); -                        } - -                        val_set.second->visit(*this); -                        vals[idx] = mv$(m_rv); -                    } -                    for( unsigned int i = 0; i < vals.size(); i ++ ) { -                        const auto& val = vals[i]; -                        if( val.is_Invalid() ) { -                            ERROR(node.span(), E0000, "Field " << fields[i].first << " wasn't set"); -                        } -                    } - -                    m_rv = ::HIR::Literal::make_List(mv$(vals)); -                    m_rv_type = mv$(rv_type); -                } -                else -                { -                    const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path); -                    ASSERT_BUG(node.span(), ent.is_Enum(), "_StructLiteral with m_is_struct clear pointing to a " << ent.tag_str()); - -                    TODO(node.span(), "Handle Enum _UnitVariant - " << node.m_path); -                } -            } -            void visit(::HIR::ExprNode_UnionLiteral& node) override { -                TRACE_FUNCTION_FR("_UnionLiteral - " << node.m_path, m_rv); -                TODO(node.span(), "_UnionLiteral"); -            } -            void visit(::HIR::ExprNode_Tuple& node) override -            { -                TRACE_FUNCTION_FR("_Tuple", m_rv); -                ::std::vector< ::HIR::TypeRef> exp_tys; -                TU_MATCH_DEF(::HIR::TypeRef::Data, (m_exp_type.m_data), (te), -                ( -                    ), -                (Infer, -                    ), -                (Tuple, -                    exp_tys = mv$( te ); -                    ASSERT_BUG(node.span(), exp_tys.size() == node.m_vals.size(), "Tuple literal size mismatches with expected type"); -                    ) -                ) - -                ::std::vector< ::HIR::Literal>  vals; -                ::std::vector< ::HIR::TypeRef>  tys; -                for(unsigned int i = 0; i < node.m_vals.size(); i ++) -                { -                    if( exp_tys.size() > 0 ) -                        m_exp_type = mv$(exp_tys[i]); - -                    node.m_vals[i]->visit(*this); -                    assert( !m_rv.is_Invalid() ); - -                    vals.push_back( mv$(m_rv) ); -                    tys.push_back( mv$(m_rv_type) ); -                } - -                m_rv = ::HIR::Literal::make_List(mv$(vals)); -                m_rv_type = ::HIR::TypeRef( mv$(tys) ); -            } -            void visit(::HIR::ExprNode_ArrayList& node) override -            { -                TRACE_FUNCTION_F("_ArrayList: " << m_exp_type); -                ::HIR::TypeRef  exp_inner_ty; -                TU_MATCH_DEF(::HIR::TypeRef::Data, (m_exp_type.m_data), (te), -                ( -                    ), -                (Infer, -                    ), -                (Array, -                    exp_inner_ty = mv$(*te.inner); -                    // TODO: Check size? -                    ), -                (Slice, -                    exp_inner_ty = mv$(*te.inner); -                    ) -                ) - -                ::std::vector< ::HIR::Literal>  vals; -                for(const auto& vn : node.m_vals ) -                { -                    m_exp_type = exp_inner_ty.clone(); -                    vn->visit(*this); -                    assert( !m_rv.is_Invalid() ); -                    vals.push_back( mv$(m_rv) ); -                } - -                m_rv_type = ::HIR::TypeRef::new_array( mv$(m_rv_type), vals.size() ); -                m_rv = ::HIR::Literal::make_List(mv$(vals)); -            } -            void visit(::HIR::ExprNode_ArraySized& node) override -            { -                ::HIR::TypeRef  exp_inner_ty; -                TU_MATCH_DEF(::HIR::TypeRef::Data, (m_exp_type.m_data), (te), -                ( -                    ), -                (Infer, -                    ), -                (Array, -                    exp_inner_ty = mv$(*te.inner); -                    // TODO: Check size? -                    ), -                (Slice, -                    exp_inner_ty = mv$(*te.inner); +                    return ::HIR::Literal(e);                      )                  ) - -                m_exp_type = ::HIR::CoreType::Usize; -                node.m_size->visit(*this); -                assert( m_rv.is_Integer() ); -                unsigned int count = static_cast<unsigned int>(m_rv.as_Integer()); - -                ::std::vector< ::HIR::Literal>  vals; -                vals.reserve( count ); -                if( count > 0 ) -                { -                    m_exp_type = mv$(exp_inner_ty); -                    node.m_val->visit(*this); -                    assert( !m_rv.is_Invalid() ); -                    for(unsigned int i = 0; i < count-1; i ++) -                    { -                        vals.push_back( clone_literal(m_rv) ); -                    } -                    vals.push_back( mv$(m_rv) ); -                } -                m_rv = ::HIR::Literal::make_List(mv$(vals)); -                m_rv_type = ::HIR::TypeRef::new_array( mv$(m_rv_type), count ); -            } - -            void visit(::HIR::ExprNode_Closure& node) override { -                badnode(node);              }          }; +        LocalState  local_state( state, retval, args, locals ); -        Visitor v { crate, newval_state, mv$(exp_type) }; -        for(auto& arg : args) -            v.m_values.push_back( mv$(arg) ); -        const_cast<::HIR::ExprNode&>(expr).visit(v); - -        if( v.m_rv.is_Invalid() ) { -            // NOTE: Removed, because of tricks serde_derive does -            //BUG(sp, "Expression did not yeild a literal"); -        } - -        return mv$(v.m_rv); -    } - -    ::HIR::Literal evaluate_constant_mir(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::MIR::Function& fcn, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args) -    { -        // TODO: Full-blown miri -        TRACE_FUNCTION_F("exp=" << exp << ", args=" << args); - -        StaticTraitResolve  resolve { crate }; -        ::MIR::TypeResolve  state { sp, resolve, FMT_CB(,), exp, {}, fcn }; - -        ::HIR::Literal  retval; -        ::std::vector< ::HIR::Literal>  locals( fcn.locals.size() ); - -        auto get_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal& { -            TU_MATCHA( (lv), (e), -            (Return, -                return retval; -                ), -            (Argument, -                ASSERT_BUG(sp, e.idx < args.size(), "Argument index out of range - " << e.idx << " >= " << args.size()); -                return args[e.idx]; -                ), -            (Local, -                if( e >= locals.size() ) -                    BUG(sp, "Local index out of range - " << e << " >= " << locals.size()); -                return locals[e]; -                ), -            (Static, -                TODO(sp, "LValue::Static"); -                ), -            (Field, -                TODO(sp, "LValue::Field"); -                ), -            (Deref, -                TODO(sp, "LValue::Deref"); -                ), -            (Index, -                TODO(sp, "LValue::Index"); -                ), -            (Downcast, -                TODO(sp, "LValue::Downcast"); -                ) -            ) -            throw ""; -            }; -        auto read_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal { -            auto& v = get_lval(lv); -            TU_MATCH_DEF(::HIR::Literal, (v), (e), -            ( -                return mv$(v); -                ), -            (Invalid, -                BUG(sp, "Read of invalid lvalue - " << lv); -                ), -            (BorrowPath, -                return ::HIR::Literal(e.clone()); -                ), -            (Integer, -                return ::HIR::Literal(e); -                ), -            (Float, -                return ::HIR::Literal(e); -                ) -            ) -            };          auto const_to_lit = [&](const ::MIR::Constant& c)->::HIR::Literal {              TU_MATCH(::MIR::Constant, (c), (e2),              (Int, @@ -1105,26 +397,42 @@ namespace {                  return ::HIR::Literal(e2);                  ),              (Const, -                auto ent = get_ent_fullpath(sp, crate, e2.p, EntNS::Value); -                ASSERT_BUG(sp, ent.is_Constant(), "MIR Constant::Const("<<e2.p<<") didn't point to a Constant - " << ent.tag_str()); -                return clone_literal( ent.as_Constant()->m_value_res ); +                auto p = ms.monomorph(state.sp, e2.p); +                MonomorphState  const_ms; +                auto ent = get_ent_fullpath(state.sp, this->resolve.m_crate, p, EntNS::Value,  const_ms); +                MIR_ASSERT(state, ent.is_Constant(), "MIR Constant::Const(" << p << ") didn't point to a Constant - " << ent.tag_str()); +                const auto& c = *ent.as_Constant(); +                if( c.m_value_res.is_Invalid() ) +                { +                    auto& item = const_cast<::HIR::Constant&>(c); +                    // Challenge: Adding items to the module might invalidate an iterator. +                    ::HIR::ItemPath mod_ip { item.m_value.m_state->m_mod_path }; +                    auto eval = Evaluator { item.m_value->span(), resolve.m_crate, NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") } }; +                    DEBUG("- Evaluate " << p); +                    DEBUG("- " << ::HIR::ItemPath(p)); +                    item.m_value_res = eval.evaluate_constant(::HIR::ItemPath(p), item.m_value, item.m_type.clone()); + +                    //check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); +                } +                return clone_literal( c.m_value_res );                  ),              (ItemAddr, -                return ::HIR::Literal::make_BorrowPath( e2.clone() ); +                return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, e2) );                  )              )              throw "";              }; -        auto read_param = [&](const ::MIR::Param& p) ->::HIR::Literal { -            TU_MATCH(::MIR::Param, (p), (e), -            (LValue, -                return read_lval(e); -                ), -            (Constant, -                return const_to_lit(e); +        auto read_param = [&](const ::MIR::Param& p) -> ::HIR::Literal +            { +                TU_MATCH(::MIR::Param, (p), (e), +                (LValue, +                    return local_state.read_lval(e); +                    ), +                (Constant, +                    return const_to_lit(e); +                    )                  ) -            ) -            throw ""; +                throw "";              };          unsigned int cur_block = 0; @@ -1135,9 +443,10 @@ namespace {              for(const auto& stmt : block.statements)              {                  state.set_cur_stmt(cur_block, next_stmt_idx++); +                DEBUG(state << stmt);                  if( ! stmt.is_Assign() ) { -                    //BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot); +                    //MIR_BUG(state, "Non-assign statement - drop " << stmt.as_Drop().slot);                      continue ;                  } @@ -1145,7 +454,7 @@ namespace {                  const auto& sa = stmt.as_Assign();                  TU_MATCHA( (sa.src), (e),                  (Use, -                    val = read_lval(e); +                    val = local_state.read_lval(e);                      ),                  (Constant,                      val = const_to_lit(e); @@ -1167,17 +476,38 @@ namespace {                          MIR_BUG(state, "Only shared borrows are allowed in constants");                      } -                    auto inner_val = read_lval(e.val); +                    if( e.type != ::HIR::BorrowType::Shared ) { +                        MIR_BUG(state, "Only shared borrows are allowed in constants"); +                    } +                    if( const auto* p = e.val.opt_Deref() ) { +                        if( p->val->is_Deref() ) +                            MIR_TODO(state, "Undo nested deref coercion - " << *p->val); +                        val = local_state.read_lval(*p->val); +                    } +                    else if( const auto* p = e.val.opt_Static() ) { +                        // Borrow of a static, emit BorrowPath with the same path +                        val = ::HIR::Literal::make_BorrowPath( p->clone() ); +                    } +                    else { +                        auto inner_val = local_state.read_lval(e.val); + +                        ::HIR::TypeRef  inner_ty; +                        const auto& inner_ty_r = state.get_lvalue_type(inner_ty, e.val); +                        if( &inner_ty_r != &inner_ty ) +                            inner_ty = inner_ty_r.clone(); -                    // Create new static containing borrowed data -                    val = ::HIR::Literal::make_BorrowData( box$(inner_val) ); +                        // Create new static containing borrowed data +                        // NOTE: Doesn't use BorrowData +                        auto item_path = this->nvs.new_static( mv$(inner_ty), mv$(inner_val) ); +                        val = ::HIR::Literal::make_BorrowPath( mv$(item_path) ); +                    }                      ),                  (Cast, -                    auto inval = read_lval(e.val); +                    auto inval = local_state.read_lval(e.val);                      TU_MATCH_DEF(::HIR::TypeRef::Data, (e.type.m_data), (te),                      (                          // NOTE: Can be an unsizing! -                        TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval); +                        MIR_TODO(state, "RValue::Cast to " << e.type << ", val = " << inval);                          ),                      (Primitive,                          uint64_t mask; @@ -1211,7 +541,7 @@ namespace {                                  val = ::HIR::Literal( static_cast<uint64_t>(i) & mask);                              )                              else { -                                BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); +                                MIR_BUG(state, "Invalid cast of " << inval.tag_str() << " to " << e.type);                              }                              break;                          case ::HIR::CoreType::F32: @@ -1223,11 +553,11 @@ namespace {                                  val = ::HIR::Literal( i );                              )                              else { -                                BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); +                                MIR_BUG(state, "Invalid cast of " << inval.tag_str() << " to " << e.type);                              }                              break;                          default: -                            TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval); +                            MIR_TODO(state, "RValue::Cast to " << e.type << ", val = " << inval);                          }                          ),                      // Allow casting any integer value to a pointer (TODO: Ensure that the pointer is sized?) @@ -1239,7 +569,15 @@ namespace {                              val = mv$(inval);                          }                          else { -                            BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); +                            MIR_BUG(state, "Invalid cast of " << inval.tag_str() << " to " << e.type); +                        } +                        ), +                    (Borrow, +                        if( inval.is_BorrowData() || inval.is_BorrowPath() ) { +                            val = mv$(inval); +                        } +                        else { +                            MIR_BUG(state, "Invalid cast of " << inval.tag_str() << " to " << e.type);                          }                          )                      ) @@ -1247,10 +585,10 @@ namespace {                  (BinOp,                      auto inval_l = read_param(e.val_l);                      auto inval_r = read_param(e.val_r); -                    ASSERT_BUG(sp, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r); +                    MIR_ASSERT(state, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r);                      TU_MATCH_DEF( ::HIR::Literal, (inval_l, inval_r), (l, r),                      ( -                        TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); +                        MIR_TODO(state, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);                          ),                      (Float,                          switch(e.op) @@ -1264,14 +602,14 @@ namespace {                          case ::MIR::eBinOp::SUB_OV:                          case ::MIR::eBinOp::MUL_OV:                          case ::MIR::eBinOp::DIV_OV: -                            TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); +                            MIR_TODO(state, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);                          case ::MIR::eBinOp::BIT_OR :                          case ::MIR::eBinOp::BIT_AND:                          case ::MIR::eBinOp::BIT_XOR:                          case ::MIR::eBinOp::BIT_SHL:                          case ::MIR::eBinOp::BIT_SHR: -                            TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); +                            MIR_TODO(state, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);                          // TODO: GT/LT are incorrect for signed integers                          case ::MIR::eBinOp::EQ: val = ::HIR::Literal( static_cast<uint64_t>(l == r) );  break;                          case ::MIR::eBinOp::NE: val = ::HIR::Literal( static_cast<uint64_t>(l != r) );  break; @@ -1293,7 +631,7 @@ namespace {                          case ::MIR::eBinOp::SUB_OV:                          case ::MIR::eBinOp::MUL_OV:                          case ::MIR::eBinOp::DIV_OV: -                            TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); +                            MIR_TODO(state, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);                          case ::MIR::eBinOp::BIT_OR : val = ::HIR::Literal( l | r );  break;                          case ::MIR::eBinOp::BIT_AND: val = ::HIR::Literal( l & r );  break; @@ -1312,7 +650,7 @@ namespace {                      )                      ),                  (UniOp, -                    auto inval = read_lval(e.val); +                    auto inval = local_state.read_lval(e.val);                      TU_IFLET( ::HIR::Literal, inval, Integer, i,                          switch( e.op )                          { @@ -1328,7 +666,7 @@ namespace {                          switch( e.op )                          {                          case ::MIR::eUniOp::INV: -                            BUG(sp, "Invalid invert of Float"); +                            MIR_BUG(state, "Invalid invert of Float");                              break;                          case ::MIR::eUniOp::NEG:                              val = ::HIR::Literal( -i ); @@ -1336,20 +674,20 @@ namespace {                          }                      )                      else { -                        BUG(sp, "Invalid invert of " << inval.tag_str()); +                        MIR_BUG(state, "Invalid invert of " << inval.tag_str());                      }                      ),                  (DstMeta, -                    TODO(sp, "RValue::DstMeta"); +                    MIR_TODO(state, "RValue::DstMeta");                      ),                  (DstPtr, -                    TODO(sp, "RValue::DstPtr"); +                    MIR_TODO(state, "RValue::DstPtr");                      ),                  (MakeDst,                      auto ptr = read_param(e.ptr_val);                      auto meta = read_param(e.meta_val);                      if( ! meta.is_Integer() ) { -                        TODO(sp, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta); +                        MIR_TODO(state, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta);                      }                      else {                          val = mv$(ptr); @@ -1370,7 +708,8 @@ namespace {                      val = ::HIR::Literal::make_List( mv$(vals) );                      ),                  (Variant, -                    TODO(sp, "MIR _Variant"); +                    auto ival = read_param(e.val); +                    val = ::HIR::Literal::make_Variant({ e.index, box$(ival) });                      ),                  (Struct,                      ::std::vector< ::HIR::Literal>  vals; @@ -1381,13 +720,13 @@ namespace {                      )                  ) -                auto& dst = get_lval(sa.dst); +                auto& dst = local_state.get_lval(sa.dst);                  dst = mv$(val);              }              state.set_cur_stmt_term(cur_block);              TU_MATCH_DEF( ::MIR::Terminator, (block.terminator), (e),              ( -                BUG(sp, "Unexpected terminator - " << block.terminator); +                MIR_BUG(state, "Unexpected terminator - " << block.terminator);                  ),              (Goto,                  cur_block = e; @@ -1430,18 +769,20 @@ namespace {                      case ::HIR::CoreType::Bool:                          break;                      case ::HIR::CoreType::Str: -                        BUG(sp, "Bare str return type"); +                        MIR_BUG(state, "Bare str return type");                      }                  }                  return retval;                  ),              (Call,                  if( !e.fcn.is_Path() ) -                    BUG(sp, "Unexpected terminator - " << block.terminator); -                const auto& fcnp = e.fcn.as_Path(); +                    MIR_BUG(state, "Unexpected terminator - " << block.terminator); +                const auto& fcnp_raw = e.fcn.as_Path(); +                auto fcnp = ms.monomorph(state.sp, fcnp_raw); -                auto& dst = get_lval(e.ret_val); -                auto& fcn = get_function(sp, crate, fcnp); +                auto& dst = local_state.get_lval(e.ret_val); +                MonomorphState  fcn_ms; +                auto& fcn = get_function(this->root_span, this->resolve.m_crate, fcnp, fcn_ms);                  ::std::vector< ::HIR::Literal>  call_args;                  call_args.reserve( e.args.size() ); @@ -1452,7 +793,9 @@ namespace {                  // Call by invoking evaluate_constant on the function                  {                      TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }"); -                    dst = evaluate_constant(sp, crate, newval_state,  fcn.m_code, fcn.m_return.clone(), mv$(call_args)); +                    const auto* mir = this->resolve.m_crate.get_or_gen_mir( ::HIR::ItemPath(fcnp.clone()), fcn ); +                    MIR_ASSERT(state, mir, "No MIR for function " << fcnp); +                    dst = evaluate_constant_mir(*mir, mv$(fcn_ms), fcn.m_return.clone(), mv$(call_args));                  }                  cur_block = e.ret_block; @@ -1461,16 +804,16 @@ namespace {          }      } -    ::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args) +    ::HIR::Literal Evaluator::evaluate_constant(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp)      { -        if( expr.m_mir ) { -            return evaluate_constant_mir(sp, crate, mv$(newval_state), *expr.m_mir, mv$(exp), mv$(args)); -        } -        else if( expr ) { -            return evaluate_constant_hir(sp, crate, mv$(newval_state), *expr, mv$(exp), mv$(args)); +        TRACE_FUNCTION_F(ip); +        const auto* mir = this->resolve.m_crate.get_or_gen_mir(ip, expr, exp); + +        if( mir ) { +            return evaluate_constant_mir(*mir, {}, mv$(exp), {});          }          else { -            BUG(sp, "Attempting to evaluate constant expression with no associated code"); +            BUG(this->root_span, "Attempting to evaluate constant expression with no associated code");          }      } @@ -1553,30 +896,26 @@ namespace {          public ::HIR::Visitor      {          const ::HIR::Crate& m_crate; +        const ::HIR::Module*  m_mod;          const ::HIR::ItemPath*  m_mod_path; -        t_new_values    m_new_values;      public:          Expander(const ::HIR::Crate& crate): -            m_crate(crate) +            m_crate(crate), +            m_mod(nullptr), +            m_mod_path(nullptr)          {}          void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override          {              auto saved_mp = m_mod_path; +            auto saved_m = m_mod; +            m_mod = &mod;              m_mod_path = &p; -            auto saved = mv$( m_new_values );              ::HIR::Visitor::visit_module(p, mod); -            for( auto& item : m_new_values ) -            { -                mod.m_value_items.insert( ::std::make_pair( -                    mv$(item.first), -                    box$(::HIR::VisEnt<::HIR::ValueItem> { false, ::HIR::ValueItem(mv$(item.second)) }) -                    ) ); -            } -            m_new_values = mv$(saved); +            m_mod = saved_m;              m_mod_path = saved_mp;          } @@ -1590,8 +929,10 @@ namespace {                      assert(e.size);                      assert(*e.size);                      const auto& expr_ptr = *e.size; -                    auto nvs = NewvalState { m_new_values, *m_mod_path, FMT("ty_" << &ty << "$") }; -                    auto val = evaluate_constant(expr_ptr->span(), m_crate, nvs, expr_ptr, ::HIR::CoreType::Usize); +                    auto ty_name = FMT("ty_" << &ty << "$"); + +                    auto eval = Evaluator { expr_ptr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, ty_name } }; +                    auto val = eval.evaluate_constant(::HIR::ItemPath(*m_mod_path, ty_name.c_str()), expr_ptr, ::HIR::CoreType::Usize);                      if( !val.is_Integer() )                          ERROR(expr_ptr->span(), E0000, "Array size isn't an integer");                      e.size_val = static_cast<size_t>(val.as_Integer()); @@ -1599,7 +940,6 @@ namespace {                  DEBUG("Array " << ty << " - size = " << e.size_val);              )          } -        // TODO: Needs to be visited for MIR match generation to work          void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override          {              ::HIR::Visitor::visit_constant(p, item); @@ -1607,30 +947,39 @@ namespace {              // NOTE: Consteval needed here for MIR match generation to work              if( item.m_value )              { -                //if( item.m_type.m_data.is_Primitive() ) -                //    ; -                //else if( item.m_type.m_data.is_Borrow() && *item.m_type.m_data.as_Borrow().inner == ::HIR::CoreType::Str ) -                //    ; -                //else -                //    return ; - -                auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }; -                item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, nvs, item.m_value, item.m_type.clone(), {}); +                auto eval = Evaluator { item.m_value->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; +                item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone());                  check_lit_type(item.m_value->span(), item.m_type, item.m_value_res);                  DEBUG("constant: " << item.m_type <<  " = " << item.m_value_res);              }          } +        void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override +        { +            ::HIR::Visitor::visit_static(p, item); + +            if( item.m_value ) +            { +                auto eval = Evaluator { item.m_value->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; +                item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone()); + +                check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); + +                DEBUG("static: " << item.m_type <<  " = " << item.m_value_res); +            } +        }          void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {              if( auto* e = item.m_data.opt_Value() )              { +                ::HIR::TypeRef  ty = ::HIR::CoreType::Isize;                  uint64_t i = 0;                  for(auto& var : e->variants)                  {                      if( var.expr )                      { -                        auto val = evaluate_constant(var.expr->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") }, var.expr, {}); +                        auto eval = Evaluator { var.expr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") } }; +                        auto val = eval.evaluate_constant(p, var.expr, ty.clone());                          DEBUG("enum variant: " << p << "::" << var.name << " = " << val);                          i = val.as_Integer();                      } @@ -1663,8 +1012,9 @@ namespace {                  void visit(::HIR::ExprNode_ArraySized& node) override {                      assert( node.m_size ); -                    NewvalState nvs { m_exp.m_new_values, *m_exp.m_mod_path, FMT("array_" << &node << "$") }; -                    auto val = evaluate_constant_hir(node.span(), m_exp.m_crate, mv$(nvs), *node.m_size, ::HIR::CoreType::Usize, {}); +                    auto name = FMT("array_" << &node << "$"); +                    auto eval = Evaluator { node.span(), m_exp.m_crate, NewvalState { *m_exp.m_mod, *m_exp.m_mod_path, name } }; +                    auto val = eval.evaluate_constant( ::HIR::ItemPath(*m_exp.m_mod_path, name.c_str()), node.m_size, ::HIR::CoreType::Usize );                      if( !val.is_Integer() )                          ERROR(node.span(), E0000, "Array size isn't an integer");                      node.m_size_val = static_cast<size_t>(val.as_Integer()); @@ -1679,10 +1029,40 @@ namespace {              }          }      }; + +    class ExpanderApply: +        public ::HIR::Visitor +    { + +    public: +        ExpanderApply() +        { +        } + +        void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override +        { +            if( ! mod.m_inline_statics.empty() ) +            { +                for(auto& v : mod.m_inline_statics) +                { +                    // ::std::unique_ptr<VisEnt<ValueItem>> +                    ::std::unique_ptr<::HIR::VisEnt<::HIR::ValueItem>>  iv; +                    iv.reset( new ::HIR::VisEnt<::HIR::ValueItem> { false, ::HIR::ValueItem::make_Static(mv$(v.second)) } ); +                    mod.m_value_items.insert(::std::make_pair( v.first, mv$(iv) )); +                } +                mod.m_inline_statics.clear(); +            } + +            ::HIR::Visitor::visit_module(p, mod); + +        } +    };  }   // namespace  void ConvertHIR_ConstantEvaluate(::HIR::Crate& crate)  {      Expander    exp { crate };      exp.visit_crate( crate ); + +    ExpanderApply().visit_crate(crate);  } diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index 17a61776..55fbf593 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -146,6 +146,12 @@ namespace {                      ::HIR::ExprVisitorDef::visit(node);                  } +                void visit(::HIR::ExprNode_ArraySized& node) override +                { +                    upper_visitor.visit_expr(node.m_size); +                    ::HIR::ExprVisitorDef::visit(node); +                } +                  void visit(::HIR::ExprNode_PathValue& node) override                  {                      upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE); diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp index 58a4604a..693c7745 100644 --- a/src/hir_expand/annotate_value_usage.cpp +++ b/src/hir_expand/annotate_value_usage.cpp @@ -10,6 +10,7 @@  #include <hir_typeck/static.hpp>  #include <algorithm>  #include "main_bindings.hpp" +#include <hir/expr_state.hpp>  namespace { @@ -654,6 +655,16 @@ namespace {      };  } +void HIR_Expand_AnnotateUsage_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp) +{ +    assert(exp); +    StaticTraitResolve   resolve { crate }; +    if(exp.m_state->m_impl_generics)   resolve.set_impl_generics(*exp.m_state->m_impl_generics); +    if(exp.m_state->m_item_generics)   resolve.set_item_generics(*exp.m_state->m_item_generics); +    ExprVisitor_Mark    ev { resolve }; +    ev.visit_root(exp); +} +  void HIR_Expand_AnnotateUsage(::HIR::Crate& crate)  {      OuterVisitor    ov(crate); diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index a0814e49..51b2c638 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -1169,6 +1169,11 @@ namespace {      };  } +void HIR_Expand_Closures_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp) +{ +    // TODO: +} +  void HIR_Expand_Closures(::HIR::Crate& crate)  {      OuterVisitor    ov(crate); diff --git a/src/hir_expand/const_eval_full.cpp b/src/hir_expand/const_eval_full.cpp deleted file mode 100644 index 9cfd83b0..00000000 --- a/src/hir_expand/const_eval_full.cpp +++ /dev/null @@ -1,952 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * hir_expand/const_eval_full.cpp - * - More-complete constant evaluation - * - * NOTE: This is run _after_ MIR lowering (not before, as the rest of this - * folder is) - */ -#include "main_bindings.hpp" -#include <hir/hir.hpp> -#include <hir/expr.hpp> -#include <hir/visitor.hpp> -#include <algorithm> -#include <mir/mir.hpp> -#include <hir_typeck/common.hpp>    // Monomorph -#include <mir/helpers.hpp> - -namespace { -    typedef ::std::vector< ::std::pair< ::std::string, ::HIR::Static> > t_new_values; - -    struct NewvalState { -        t_new_values&   newval_output; -        const ::HIR::ItemPath&  mod_path; -        ::std::string   name_prefix; -        unsigned int next_item_idx; - -        NewvalState(t_new_values& newval_output, const ::HIR::ItemPath& mod_path, ::std::string prefix): -            newval_output(newval_output), -            mod_path(mod_path), -            name_prefix(prefix), -            next_item_idx(0) -        { -        } -        NewvalState(const NewvalState&) = delete; -        NewvalState(NewvalState&&) = default; - -        ::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value) -        { -            auto name = FMT(name_prefix << next_item_idx); -            next_item_idx ++; -            auto rv = (mod_path + name.c_str()).get_simple_path(); -            newval_output.push_back( ::std::make_pair( mv$(name), ::HIR::Static { -                ::HIR::Linkage(), -                false, -                mv$(type), -                ::HIR::ExprPtr(), -                mv$(value) -                } ) ); -            return rv; -        } -    }; - -    ::HIR::Literal evaluate_constant(const Span& sp, const ::StaticTraitResolve& resolve, NewvalState& newval_state, FmtLambda name, const ::HIR::ExprPtr& expr, MonomorphState ms, ::std::vector< ::HIR::Literal> args); - -    ::HIR::Literal clone_literal(const ::HIR::Literal& v) -    { -        TU_MATCH(::HIR::Literal, (v), (e), -        (Invalid, -            return ::HIR::Literal(); -            ), -        (List, -            ::std::vector< ::HIR::Literal>  vals; -            for(const auto& val : e) { -                vals.push_back( clone_literal(val) ); -            } -            return ::HIR::Literal( mv$(vals) ); -            ), -        (Variant, -            return ::HIR::Literal::make_Variant({ e.idx, box$(clone_literal(*e.val)) }); -            ), -        (Integer, -            return ::HIR::Literal(e); -            ), -        (Float, -            return ::HIR::Literal(e); -            ), -        (BorrowPath, -            return ::HIR::Literal(e.clone()); -            ), -        (BorrowData, -            return ::HIR::Literal(box$(clone_literal(*e))); -            ), -        (String, -            return ::HIR::Literal(e); -            ) -        ) -        throw ""; -    } - -    void monomorph_literal_inplace(const Span& sp, ::HIR::Literal& lit, const MonomorphState& ms) -    { -        TU_MATCH(::HIR::Literal, (lit), (e), -        (Invalid, -            ), -        (List, -            for(auto& val : e) { -                monomorph_literal_inplace(sp, val, ms); -            } -            ), -        (Variant, -            monomorph_literal_inplace(sp, *e.val, ms); -            ), -        (Integer, -            ), -        (Float, -            ), -        (BorrowPath, -            DEBUG(e); -            e = ms.monomorph(sp, e); -            // TODO: expand associated types -            ), -        (BorrowData, -            monomorph_literal_inplace(sp, *e, ms); -            ), -        (String, -            ) -        ) -    } - -    TAGGED_UNION(EntPtr, NotFound, -        (NotFound, struct{}), -        (Function, const ::HIR::Function*), -        (Static, const ::HIR::Static*), -        (Constant, const ::HIR::Constant*), -        (Struct, const ::HIR::Struct*) -        ); -    enum class EntNS { -        Type, -        Value -    }; -    EntPtr get_ent_simplepath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::SimplePath& path, EntNS ns) -    { -        const ::HIR::Module& mod = crate.get_mod_by_path(sp, path, /*ignore_last_node=*/true); - -        switch( ns ) -        { -        case EntNS::Value: { -            auto it = mod.m_value_items.find( path.m_components.back() ); -            if( it == mod.m_value_items.end() ) { -                return EntPtr {}; -            } - -            TU_MATCH( ::HIR::ValueItem, (it->second->ent), (e), -            (Import, -                ), -            (StructConstant, -                ), -            (StructConstructor, -                ), -            (Function, -                return EntPtr { &e }; -                ), -            (Constant, -                return EntPtr { &e }; -                ), -            (Static, -                return EntPtr { &e }; -                ) -            ) -            BUG(sp, "Path " << path << " pointed to a invalid item - " << it->second->ent.tag_str()); -            } break; -        case EntNS::Type: { -            auto it = mod.m_mod_items.find( path.m_components.back() ); -            if( it == mod.m_mod_items.end() ) { -                return EntPtr {}; -            } - -            TU_MATCH( ::HIR::TypeItem, (it->second->ent), (e), -            (Import, -                ), -            (Module, -                ), -            (Trait, -                ), -            (Struct, -                return &e; -                ), -            (Union, -                ), -            (Enum, -                ), -            (TypeAlias, -                ) -            ) -            BUG(sp, "Path " << path << " pointed to an invalid item - " << it->second->ent.tag_str()); -            } break; -        } -        throw ""; -    } -    EntPtr get_ent_fullpath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, EntNS ns, MonomorphState& out_ms) -    { -        TU_MATCH(::HIR::Path::Data, (path.m_data), (e), -        (Generic, -            out_ms = MonomorphState {}; -            out_ms.pp_method = &e.m_params; -            return get_ent_simplepath(sp, crate, e.m_path, ns); -            ), -        (UfcsInherent, -            // Easy (ish) -            EntPtr rv; -            crate.find_type_impls(*e.type, [](const auto&x)->const auto& { return x; }, [&](const auto& impl) { -                switch( ns ) -                { -                case EntNS::Value: -                    { -                        auto fit = impl.m_methods.find(e.item); -                        if( fit != impl.m_methods.end() ) -                        { -                            DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type); -                            rv = EntPtr { &fit->second.data }; -                            return true; -                        } -                    } -                    { -                        auto it = impl.m_constants.find(e.item); -                        if( it != impl.m_constants.end() ) -                        { -                            rv = EntPtr { &it->second.data }; -                            return true; -                        } -                    } -                    break; -                case EntNS::Type: -                    break; -                } -                return false; -                }); -            out_ms = MonomorphState {}; -            out_ms.pp_method = &e.params; -            out_ms.pp_impl = &e.impl_params; -            return rv; -            ), -        (UfcsKnown, -            EntPtr rv; -            crate.find_trait_impls(e.trait.m_path, *e.type, [](const auto&x)->const auto& { return x; }, [&](const auto& impl) { -                // Hacky selection of impl. -                // - TODO: Specialisation -                // - TODO: Inference? (requires full typeck) -                switch( ns ) -                { -                case EntNS::Value: -                    { -                        auto fit = impl.m_methods.find(e.item); -                        if( fit != impl.m_methods.end() ) -                        { -                            DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type); -                            rv = EntPtr { &fit->second.data }; -                            return true; -                        } -                    } -                    { -                        auto it = impl.m_constants.find(e.item); -                        if( it != impl.m_constants.end() ) -                        { -                            rv = EntPtr { &it->second.data }; -                            return true; -                        } -                    } -                    break; -                case EntNS::Type: -                    break; -                } -                return false; -                }); -            out_ms = MonomorphState {}; -            out_ms.pp_method = &e.params; -            // TODO: How to get pp_impl here? Needs specialisation magic. -            return rv; -            ), -        (UfcsUnknown, -            // TODO: Are these valid at this point in compilation? -            TODO(sp, "get_ent_fullpath(path = " << path << ")"); -            ) -        ) -        throw ""; -    } -    const ::HIR::Function& get_function(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, MonomorphState& out_ms) -    { -        auto rv = get_ent_fullpath(sp, crate, path, EntNS::Value, out_ms); -        TU_IFLET( EntPtr, rv, Function, e, -            return *e; -        ) -        else { -            TODO(sp, "Could not find function for " << path << " - " << rv.tag_str()); -        } -    } - -    ::HIR::Literal evaluate_constant_mir(const Span& sp, const StaticTraitResolve& resolve, NewvalState& newval_state, FmtLambda name, const ::MIR::Function& fcn, MonomorphState ms, ::std::vector< ::HIR::Literal> args) -    { -        TRACE_FUNCTION; - -        ::MIR::TypeResolve  state { sp, resolve, name, ::HIR::TypeRef(), {}, fcn }; - -        ::HIR::Literal  retval; -        ::std::vector< ::HIR::Literal>  locals( fcn.locals.size() ); - -        struct LocalState { -            typedef ::std::vector< ::HIR::Literal>  t_vec_lit; -            ::MIR::TypeResolve& state; -            ::HIR::Literal&  retval; -            ::std::vector< ::HIR::Literal>&  args; -            ::std::vector< ::HIR::Literal>&  locals; - -            LocalState(::MIR::TypeResolve& state, ::HIR::Literal& retval, t_vec_lit& args, t_vec_lit& locals): -                state(state), -                retval(retval), -                args(args), -                locals(locals) -            {} - -            ::HIR::Literal& get_lval(const ::MIR::LValue& lv) -            { -                TU_MATCHA( (lv), (e), -                (Return, -                    return retval; -                    ), -                (Local, -                    if( e >= locals.size() ) -                        MIR_BUG(state, "Local index out of range - " << e << " >= " << locals.size()); -                    return locals[e]; -                    ), -                (Argument, -                    if( e.idx >= args.size() ) -                        MIR_BUG(state, "Local index out of range - " << e.idx << " >= " << args.size()); -                    return args[e.idx]; -                    ), -                (Static, -                    MIR_TODO(state, "LValue::Static - " << e); -                    ), -                (Field, -                    auto& val = get_lval(*e.val); -                    MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv); -                    auto& vals = val.as_List(); -                    MIR_ASSERT(state, e.field_index < vals.size(), "LValue::Field index out of range"); -                    return vals[ e.field_index ]; -                    ), -                (Deref, -                    auto& val = get_lval(*e.val); -                    TU_MATCH_DEF( ::HIR::Literal, (val), (ve), -                    ( -                        MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }"); -                        ), -                    (String, -                        // Just clone the string (hack) -                        // - TODO: Create a list? -                        return val; -                        ) -                    ) -                    ), -                (Index, -                    auto& val = get_lval(*e.val); -                    MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv); -                    auto& idx = get_lval(*e.idx); -                    MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv); -                    auto& vals = val.as_List(); -                    auto idx_v = static_cast<size_t>( idx.as_Integer() ); -                    MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range"); -                    return vals[ idx_v ]; -                    ), -                (Downcast, -                    MIR_TODO(state, "LValue::Downcast - " << lv); -                    ) -                ) -                throw ""; -            } -        }; -        LocalState  local_state( state, retval, args, locals ); - -        auto get_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal& { return local_state.get_lval(lv); }; -        auto read_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal { -            auto& v = get_lval(lv); -            TU_MATCH_DEF(::HIR::Literal, (v), (e), -            ( -                return mv$(v); -                ), -            (Invalid, -                BUG(sp, "Read of lvalue with Literal::Invalid - " << lv); -                ), -            (BorrowPath, -                return ::HIR::Literal(e.clone()); -                ), -            (Integer, -                return ::HIR::Literal(e); -                ), -            (Float, -                return ::HIR::Literal(e); -                ) -            ) -            }; -        auto const_to_lit = [&](const ::MIR::Constant& c)->::HIR::Literal { -            TU_MATCH(::MIR::Constant, (c), (e2), -            (Int, -                return ::HIR::Literal(static_cast<uint64_t>(e2.v)); -                ), -            (Uint, -                return ::HIR::Literal(e2.v); -                ), -            (Float, -                return ::HIR::Literal(e2.v); -                ), -            (Bool, -                return ::HIR::Literal(static_cast<uint64_t>(e2.v)); -                ), -            (Bytes, -                return ::HIR::Literal::make_String({e2.begin(), e2.end()}); -                ), -            (StaticString, -                return ::HIR::Literal(e2); -                ), -            (Const, -                MonomorphState  const_ms; -                // TODO: Monomorph the path? (Not needed... yet) -                auto ent = get_ent_fullpath(sp, resolve.m_crate, e2.p, EntNS::Value,  const_ms); -                ASSERT_BUG(sp, ent.is_Constant(), "MIR Constant::Const("<<e2.p<<") didn't point to a Constant - " << ent.tag_str()); -                const auto& c = *ent.as_Constant(); -                // Prefer re-evaluating the MIR. -                // - Constants insert themselves directly, so this is -                //   effectively the same thing. -                // Avoids _BorrowData leftovers. -                if( c.m_value ) { -                    return evaluate_constant(sp, resolve, newval_state, FMT_CB(ss, ss << e2.p;), ent.as_Constant()->m_value, {}, {}); -                } -                else { -                    auto val = clone_literal( ent.as_Constant()->m_value_res ); -                    ASSERT_BUG(sp, !val.is_Invalid(), "MIR Constant::Const("<<e2.p<<") pointed to invalid Constant - (no mir, no literal)"); -                    // Monomorphise the value according to `const_ms` -                    monomorph_literal_inplace(sp, val, const_ms); -                    return val; -                } -                ), -            (ItemAddr, -                return ::HIR::Literal::make_BorrowPath( ms.monomorph(sp, e2) ); -                ) -            ) -            throw ""; -            }; -        auto read_param = [&](const ::MIR::Param& p) ->::HIR::Literal { -            TU_MATCH(::MIR::Param, (p), (e), -            (LValue, -                return read_lval(e); -                ), -            (Constant, -                return const_to_lit(e); -                ) -            ) -            throw ""; -            }; - -        unsigned int cur_block = 0; -        for(;;) -        { -            const auto& block = fcn.blocks[cur_block]; -            unsigned int next_stmt_idx = 0; -            for(const auto& stmt : block.statements) -            { -                state.set_cur_stmt(cur_block, next_stmt_idx++); - -                if( ! stmt.is_Assign() ) { -                    //BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot); -                    continue ; -                } -                const auto& sa = stmt.as_Assign(); - -                DEBUG(sa.dst << " = " << sa.src); -                ::HIR::Literal  val; -                TU_MATCHA( (sa.src), (e), -                (Use, -                    val = read_lval(e); -                    ), -                (Constant, -                    val = const_to_lit(e); -                    ), -                (SizedArray, -                    ::std::vector< ::HIR::Literal>  vals; -                    if( e.count > 0 ) -                    { -                        vals.reserve( e.count ); -                        val = read_param(e.val); -                        for(unsigned int i = 1; i < e.count; i++) -                            vals.push_back( clone_literal(val) ); -                        vals.push_back( mv$(val) ); -                    } -                    val = ::HIR::Literal::make_List( mv$(vals) ); -                    ), -                (Borrow, -                    if( e.type != ::HIR::BorrowType::Shared ) { -                        MIR_BUG(state, "Only shared borrows are allowed in constants"); -                    } -                    if( const auto* p = e.val.opt_Deref() ) { -                        if( p->val->is_Deref() ) -                            MIR_TODO(state, "Undo nested deref coercion - " << *p->val); -                        val = read_lval(*p->val); -                    } -                    else if( const auto* p = e.val.opt_Static() ) { -                        // Borrow of a static, emit BorrowPath with the same path -                        val = ::HIR::Literal::make_BorrowPath( p->clone() ); -                    } -                    else { -                        auto inner_val = read_lval(e.val); - -                        ::HIR::TypeRef  inner_ty; -                        const auto& inner_ty_r = state.get_lvalue_type(inner_ty, e.val); -                        if( &inner_ty_r != &inner_ty ) -                            inner_ty = inner_ty_r.clone(); - -                        // Create new static containing borrowed data -                        // NOTE: Doesn't use BorrowData -                        auto item_path = newval_state.new_static( mv$(inner_ty), mv$(inner_val) ); -                        val = ::HIR::Literal::make_BorrowPath( mv$(item_path) ); -                    } -                    ), -                (Cast, -                    auto inval = read_lval(e.val); -                    TU_MATCH_DEF(::HIR::TypeRef::Data, (e.type.m_data), (te), -                    ( -                        // NOTE: Can be an unsizing! -                        TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval); -                        ), -                    (Primitive, -                        auto cast_to_int = [&inval,&e,&sp](bool is_signed, unsigned bits) { -                            uint64_t mask = (bits >= 64 ? ~0ull : (1ull << bits) - 1); -                            uint64_t outval; -                            TU_IFLET( ::HIR::Literal, inval, Integer, i, -                                outval = i & mask; -                                if( bits < 64 && is_signed && (outval >> (bits-1)) ) -                                    outval |= ~mask; -                            ) -                            else TU_IFLET( ::HIR::Literal, inval, Float, i, -                                outval = static_cast<uint64_t>(i) & mask; -                                if( is_signed && i < 0 ) -                                    outval |= ~mask; -                            ) -                            else { -                                BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); -                            } -                            return ::HIR::Literal(outval); -                            }; -                        switch(te) -                        { -                        // Integers mask down -                        case ::HIR::CoreType::I8:   val = cast_to_int(true , 8);    break; -                        case ::HIR::CoreType::U8:   val = cast_to_int(false, 8);    break; -                        case ::HIR::CoreType::I16:  val = cast_to_int(true , 16);   break; -                        case ::HIR::CoreType::U16:  val = cast_to_int(false, 16);   break; -                        case ::HIR::CoreType::I32:  val = cast_to_int(true , 32);   break; -                        case ::HIR::CoreType::U32:  val = cast_to_int(false, 32);   break; - -                        case ::HIR::CoreType::I64:  val = cast_to_int(true , 64);   break; -                        case ::HIR::CoreType::U64:  val = cast_to_int(false, 64);   break; -                        case ::HIR::CoreType::I128: val = cast_to_int(true , 64);   break; -                        case ::HIR::CoreType::U128: val = cast_to_int(false, 64);   break; -                        case ::HIR::CoreType::Isize: val = cast_to_int(true , 64);   break; -                        case ::HIR::CoreType::Usize: val = cast_to_int(false, 64);   break; - -                        case ::HIR::CoreType::F32: -                        case ::HIR::CoreType::F64: -                            TU_IFLET( ::HIR::Literal, inval, Integer, i, -                                val = ::HIR::Literal( static_cast<double>(i) ); -                            ) -                            else TU_IFLET( ::HIR::Literal, inval, Float, i, -                                val = ::HIR::Literal( i ); -                            ) -                            else { -                                BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); -                            } -                            break; -                        default: -                            TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval); -                        } -                        ), -                    // Allow casting any integer value to a pointer (TODO: Ensure that the pointer is sized?) -                    (Pointer, -                        TU_IFLET( ::HIR::Literal, inval, Integer, i, -                            val = ::HIR::Literal(i); -                        ) -                        else if( inval.is_BorrowData() || inval.is_BorrowPath() ) { -                            val = mv$(inval); -                        } -                        else { -                            BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); -                        } -                        ), -                    (Borrow, -                        if( inval.is_BorrowData() || inval.is_BorrowPath() ) { -                            val = mv$(inval); -                        } -                        else { -                            BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); -                        } -                        ) -                    ) -                    ), -                (BinOp, -                    auto inval_l = read_param(e.val_l); -                    auto inval_r = read_param(e.val_r); -                    ASSERT_BUG(sp, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r); -                    TU_MATCH_DEF( ::HIR::Literal, (inval_l, inval_r), (l, r), -                    ( -                        TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); -                        ), -                    (Float, -                        switch(e.op) -                        { -                        case ::MIR::eBinOp::ADD:    val = ::HIR::Literal( l + r );  break; -                        case ::MIR::eBinOp::SUB:    val = ::HIR::Literal( l - r );  break; -                        case ::MIR::eBinOp::MUL:    val = ::HIR::Literal( l * r );  break; -                        case ::MIR::eBinOp::DIV:    val = ::HIR::Literal( l / r );  break; -                        case ::MIR::eBinOp::MOD: -                        case ::MIR::eBinOp::ADD_OV: -                        case ::MIR::eBinOp::SUB_OV: -                        case ::MIR::eBinOp::MUL_OV: -                        case ::MIR::eBinOp::DIV_OV: -                            TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); - -                        case ::MIR::eBinOp::BIT_OR : -                        case ::MIR::eBinOp::BIT_AND: -                        case ::MIR::eBinOp::BIT_XOR: -                        case ::MIR::eBinOp::BIT_SHL: -                        case ::MIR::eBinOp::BIT_SHR: -                            TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); -                        // TODO: GT/LT are incorrect for signed integers -                        case ::MIR::eBinOp::EQ: val = ::HIR::Literal( static_cast<uint64_t>(l == r) );  break; -                        case ::MIR::eBinOp::NE: val = ::HIR::Literal( static_cast<uint64_t>(l != r) );  break; -                        case ::MIR::eBinOp::GT: val = ::HIR::Literal( static_cast<uint64_t>(l >  r) );  break; -                        case ::MIR::eBinOp::GE: val = ::HIR::Literal( static_cast<uint64_t>(l >= r) );  break; -                        case ::MIR::eBinOp::LT: val = ::HIR::Literal( static_cast<uint64_t>(l <  r) );  break; -                        case ::MIR::eBinOp::LE: val = ::HIR::Literal( static_cast<uint64_t>(l <= r) );  break; -                        } -                        ), -                    (Integer, -                        switch(e.op) -                        { -                        case ::MIR::eBinOp::ADD:    val = ::HIR::Literal( l + r );  break; -                        case ::MIR::eBinOp::SUB:    val = ::HIR::Literal( l - r );  break; -                        case ::MIR::eBinOp::MUL:    val = ::HIR::Literal( l * r );  break; -                        case ::MIR::eBinOp::DIV:    val = ::HIR::Literal( l / r );  break; -                        case ::MIR::eBinOp::MOD:    val = ::HIR::Literal( l % r );  break; -                        case ::MIR::eBinOp::ADD_OV: -                        case ::MIR::eBinOp::SUB_OV: -                        case ::MIR::eBinOp::MUL_OV: -                        case ::MIR::eBinOp::DIV_OV: -                            TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); - -                        case ::MIR::eBinOp::BIT_OR : val = ::HIR::Literal( l | r );  break; -                        case ::MIR::eBinOp::BIT_AND: val = ::HIR::Literal( l & r );  break; -                        case ::MIR::eBinOp::BIT_XOR: val = ::HIR::Literal( l ^ r );  break; -                        case ::MIR::eBinOp::BIT_SHL: val = ::HIR::Literal( l << r );  break; -                        case ::MIR::eBinOp::BIT_SHR: val = ::HIR::Literal( l >> r );  break; -                        // TODO: GT/LT are incorrect for signed integers -                        case ::MIR::eBinOp::EQ: val = ::HIR::Literal( static_cast<uint64_t>(l == r) );  break; -                        case ::MIR::eBinOp::NE: val = ::HIR::Literal( static_cast<uint64_t>(l != r) );  break; -                        case ::MIR::eBinOp::GT: val = ::HIR::Literal( static_cast<uint64_t>(l >  r) );  break; -                        case ::MIR::eBinOp::GE: val = ::HIR::Literal( static_cast<uint64_t>(l >= r) );  break; -                        case ::MIR::eBinOp::LT: val = ::HIR::Literal( static_cast<uint64_t>(l <  r) );  break; -                        case ::MIR::eBinOp::LE: val = ::HIR::Literal( static_cast<uint64_t>(l <= r) );  break; -                        } -                        ) -                    ) -                    ), -                (UniOp, -                    auto inval = read_lval(e.val); -                    TU_IFLET( ::HIR::Literal, inval, Integer, i, -                        switch( e.op ) -                        { -                        case ::MIR::eUniOp::INV: -                            val = ::HIR::Literal( ~i ); -                            break; -                        case ::MIR::eUniOp::NEG: -                            val = ::HIR::Literal( -i ); -                            break; -                        } -                    ) -                    else TU_IFLET( ::HIR::Literal, inval, Float, i, -                        switch( e.op ) -                        { -                        case ::MIR::eUniOp::INV: -                            BUG(sp, "Invalid invert of Float"); -                            break; -                        case ::MIR::eUniOp::NEG: -                            val = ::HIR::Literal( -i ); -                            break; -                        } -                    ) -                    else { -                        BUG(sp, "Invalid invert of " << inval.tag_str()); -                    } -                    ), -                (DstMeta, -                    TODO(sp, "RValue::DstMeta"); -                    ), -                (DstPtr, -                    TODO(sp, "RValue::DstPtr"); -                    ), -                (MakeDst, -                    auto ptr = read_param(e.ptr_val); -                    auto meta = read_param(e.meta_val); -                    if( ! meta.is_Integer() ) { -                        TODO(sp, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta); -                    } -                    else { -                        val = mv$(ptr); -                    } -                    ), -                (Tuple, -                    ::std::vector< ::HIR::Literal>  vals; -                    vals.reserve( e.vals.size() ); -                    for(const auto& v : e.vals) -                        vals.push_back( read_param(v) ); -                    val = ::HIR::Literal::make_List( mv$(vals) ); -                    ), -                (Array, -                    ::std::vector< ::HIR::Literal>  vals; -                    vals.reserve( e.vals.size() ); -                    for(const auto& v : e.vals) -                        vals.push_back( read_param(v) ); -                    val = ::HIR::Literal::make_List( mv$(vals) ); -                    ), -                (Variant, -                    auto ival = read_param(e.val); -                    val = ::HIR::Literal::make_Variant({ e.index, box$(ival) }); -                    ), -                (Struct, -                    ::std::vector< ::HIR::Literal>  vals; -                    vals.reserve( e.vals.size() ); -                    for(const auto& v : e.vals) -                        vals.push_back( read_param(v) ); -                    val = ::HIR::Literal::make_List( mv$(vals) ); -                    ) -                ) - -                auto& dst = get_lval(sa.dst); -                DEBUG("= " << val); -                dst = mv$(val); -            } -            state.set_cur_stmt_term(cur_block); -            DEBUG("> " << block.terminator); -            TU_MATCH_DEF( ::MIR::Terminator, (block.terminator), (e), -            ( -                BUG(sp, "Unexpected terminator - " << block.terminator); -                ), -            (Goto, -                cur_block = e; -                ), -            (Return, -                return retval; -                ), -            (Call, -                if( !e.fcn.is_Path() ) -                    BUG(sp, "Unexpected terminator - " << block.terminator); -                const auto& fcnp_raw = e.fcn.as_Path(); -                auto fcnp = ms.monomorph(sp, fcnp_raw); - -                auto& dst = get_lval(e.ret_val); -                MonomorphState  fcn_ms; -                auto& fcn = get_function(sp, resolve.m_crate, fcnp, fcn_ms); - -                ::std::vector< ::HIR::Literal>  call_args; -                call_args.reserve( e.args.size() ); -                for(const auto& a : e.args) -                    call_args.push_back( read_param(a) ); -                // TODO: Set m_const during parse and check here - -                // Call by invoking evaluate_constant on the function -                { -                    TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }"); -                    dst = evaluate_constant(sp, resolve, newval_state, FMT_CB(ss, ss << fcnp;),  fcn.m_code, mv$(fcn_ms), mv$(call_args)); -                } - -                DEBUG("= " << dst); -                cur_block = e.ret_block; -                ) -            ) -        } -    } - -    ::HIR::Literal evaluate_constant(const Span& sp, const StaticTraitResolve& resolve, NewvalState& newval_state, FmtLambda name, const ::HIR::ExprPtr& expr, MonomorphState ms, ::std::vector< ::HIR::Literal> args) -    { -        if( expr.m_mir ) { -            return evaluate_constant_mir(sp, resolve, newval_state, name, *expr.m_mir, mv$(ms), mv$(args)); -        } -        else { -            BUG(sp, "Attempting to evaluate constant expression with no associated code"); -        } -    } - -    void check_lit_type(const Span& sp, const ::HIR::TypeRef& type,  ::HIR::Literal& lit) -    { -        // TODO: Mask down limited size integers -        TU_MATCHA( (type.m_data), (te), -        (Infer, -            ), -        (Diverge, -            ), -        (Generic, -            ), -        (Slice, -            ), -        (TraitObject, -            ), -        (ErasedType, -            ), -        (Closure, -            ), - -        (Path, -            // List -            ), -        (Array, -            // List -            ), -        (Tuple, -            // List -            ), - -        (Borrow, -            // A whole host of things -            ), -        (Pointer, -            // Integer, or itemaddr? -            ), -        (Function, -            // ItemAddr -            ), - -        (Primitive, -            switch(te) -            { -            case ::HIR::CoreType::Str: -                BUG(sp, "Direct str literal not valid"); -            case ::HIR::CoreType::F32: -            case ::HIR::CoreType::F64: -                ASSERT_BUG(sp, lit.is_Float(), "Bad literal type for " << type << " - " << lit); -                break; -            default: -                ASSERT_BUG(sp, lit.is_Integer(), "Bad literal type for " << type << " - " << lit); -                switch(te) -                { -                case ::HIR::CoreType::U8:   lit.as_Integer() &= (1ull<<8)-1;  break; -                case ::HIR::CoreType::U16:  lit.as_Integer() &= (1ull<<16)-1; break; -                case ::HIR::CoreType::U32:  lit.as_Integer() &= (1ull<<32)-1; break; - -                //case ::HIR::CoreType::I8:   lit.as_Integer() &= (1ull<<8)-1;  break; -                //case ::HIR::CoreType::I16:  lit.as_Integer() &= (1ull<<16)-1; break; -                //case ::HIR::CoreType::I32:  lit.as_Integer() &= (1ull<<32)-1; break; -                default: -                    break; -                } -                break; -            } -            ) -        ) -    } - -    class Expander: -        public ::HIR::Visitor -    { -        const ::HIR::Crate& m_crate; -        StaticTraitResolve  m_resolve; - -        const ::HIR::ItemPath*  m_mod_path; -        t_new_values    m_new_values; - -    public: -        Expander(const ::HIR::Crate& crate): -            m_crate(crate), -            m_resolve(crate) -        {} - -        void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override -        { -            auto saved_mp = m_mod_path; -            m_mod_path = &p; -            auto saved = mv$( m_new_values ); - -            ::HIR::Visitor::visit_module(p, mod); - -            for( auto& item : m_new_values ) -            { -                auto boxed_ent = box$(::HIR::VisEnt<::HIR::ValueItem> { false, ::HIR::ValueItem(mv$(item.second)) }); -                auto it = mod.m_value_items.find( item.first ); -                if( it != mod.m_value_items.end() ) -                { -                    it->second = mv$(boxed_ent); -                } -                else -                { -                    mod.m_value_items.insert( ::std::make_pair( mv$(item.first), mv$(boxed_ent) ) ); -                } -            } -            m_new_values = mv$(saved); -            m_mod_path = saved_mp; -        } - -        void visit_type(::HIR::TypeRef& ty) override -        { -            ::HIR::Visitor::visit_type(ty); - -            TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e, -                assert( e.size_val != ~0u ); -            ) -        } -        void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override -        { -            visit_type(item.m_type); -            if( item.m_value ) -            { -                auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }; -                item.m_value_res = evaluate_constant(item.m_value->span(), m_resolve, nvs, FMT_CB(ss, ss << p;), item.m_value, {}, {}); - -                check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); -                DEBUG("constant: " << item.m_type <<  " = " << item.m_value_res); -                visit_expr(item.m_value); -            } -        } -        void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override -        { -            visit_type(item.m_type); -            if( item.m_value ) -            { -                auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }; -                item.m_value_res = evaluate_constant(item.m_value->span(), m_resolve, nvs, FMT_CB(ss, ss << p;), item.m_value, {}, {}); -                DEBUG("static: " << item.m_type <<  " = " << item.m_value_res); -                visit_expr(item.m_value); -            } -        } -        void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override { -            if(auto* e = item.m_data.opt_Value()) -            { -                for(auto& var : e->variants) -                { -                    if( var.expr ) -                    { -                        auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") }; -                        auto val = evaluate_constant(var.expr->span(), m_resolve, nvs, FMT_CB(ss, ss << p;), var.expr, {}, {}); -                        DEBUG("Enum value " << p << " - " << var.name << " = " << val); -                        // TODO: Save this value? Or just do the above to -                        // validate? -                    } -                } -            } -            ::HIR::Visitor::visit_enum(p, item); -        } -    }; -}   // namespace - -void ConvertHIR_ConstantEvaluateFull(::HIR::Crate& crate) -{ -    Expander    exp { crate }; -    exp.visit_crate( crate ); -} diff --git a/src/hir_expand/main_bindings.hpp b/src/hir_expand/main_bindings.hpp index 6b9d5bab..5971e714 100644 --- a/src/hir_expand/main_bindings.hpp +++ b/src/hir_expand/main_bindings.hpp @@ -9,6 +9,7 @@  namespace HIR {      class Crate; +    class ExprPtr;  };  extern void HIR_Expand_AnnotateUsage(::HIR::Crate& crate); @@ -18,3 +19,8 @@ extern void HIR_Expand_UfcsEverything(::HIR::Crate& crate);  extern void HIR_Expand_Reborrows(::HIR::Crate& crate);  extern void HIR_Expand_ErasedType(::HIR::Crate& crate);  extern void ConvertHIR_ConstantEvaluateFull(::HIR::Crate& crate); + +extern void HIR_Expand_AnnotateUsage_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp); +extern void HIR_Expand_Closures_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp); +extern void HIR_Expand_UfcsEverything_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp); +extern void HIR_Expand_Reborrows_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp); diff --git a/src/hir_expand/reborrow.cpp b/src/hir_expand/reborrow.cpp index d276f57d..cb466f6f 100644 --- a/src/hir_expand/reborrow.cpp +++ b/src/hir_expand/reborrow.cpp @@ -226,6 +226,11 @@ namespace {      };  }   // namespace +void HIR_Expand_Reborrows_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp) +{ +    ExprVisitor_Mutate  ev(crate); +    ev.visit_node_ptr( exp ); +}  void HIR_Expand_Reborrows(::HIR::Crate& crate)  {      OuterVisitor    ov(crate); diff --git a/src/hir_expand/ufcs_everything.cpp b/src/hir_expand/ufcs_everything.cpp index 629dd284..ffdc0a77 100644 --- a/src/hir_expand/ufcs_everything.cpp +++ b/src/hir_expand/ufcs_everything.cpp @@ -812,6 +812,11 @@ namespace {      };  }   // namespace +void HIR_Expand_UfcsEverything_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp) +{ +    ExprVisitor_Mutate  ev { crate }; +    ev.visit_node_ptr(exp); +}  void HIR_Expand_UfcsEverything(::HIR::Crate& crate)  {      OuterVisitor    ov(crate); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 4f698c15..62f50ed9 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1534,7 +1534,6 @@ namespace {          {              TRACE_FUNCTION_F(&node << " [...; "<<node.m_size_val<<"]");              this->context.add_ivars( node.m_val->m_res_type ); -            this->context.add_ivars( node.m_size->m_res_type );              // Create result type (can't be known until after const expansion)              // - Should it be created in const expansion? @@ -1547,7 +1546,6 @@ namespace {              this->context.equate_types(node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), node.m_size->m_res_type);              node.m_val->visit( *this ); -            node.m_size->visit( *this );          }          void visit(::HIR::ExprNode_Literal& node) override diff --git a/src/hir_typeck/expr_visit.cpp b/src/hir_typeck/expr_visit.cpp index 123f51b3..1a153aaf 100644 --- a/src/hir_typeck/expr_visit.cpp +++ b/src/hir_typeck/expr_visit.cpp @@ -9,12 +9,17 @@  #include <hir/expr.hpp>  #include <hir/visitor.hpp>  #include "expr_visit.hpp" +#include <hir/expr_state.hpp> -namespace { -    void Typecheck_Code(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr) { +void Typecheck_Code(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr) { +    if( expr.m_state->stage < ::HIR::ExprState::Stage::Typecheck ) +    {          //Typecheck_Code_Simple(ms, args, result_type, expr);          Typecheck_Code_CS(ms, args, result_type, expr);      } +} + +namespace {      class OuterVisitor: diff --git a/src/hir_typeck/expr_visit.hpp b/src/hir_typeck/expr_visit.hpp index 2263a66f..21a775dc 100644 --- a/src/hir_typeck/expr_visit.hpp +++ b/src/hir_typeck/expr_visit.hpp @@ -9,14 +9,14 @@  namespace typeck {      struct ModuleState      { -        ::HIR::Crate& m_crate; +        const ::HIR::Crate& m_crate;          ::HIR::GenericParams*   m_impl_generics;          ::HIR::GenericParams*   m_item_generics;          ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > >   m_traits; -        ModuleState(::HIR::Crate& crate): +        ModuleState(const ::HIR::Crate& crate):              m_crate(crate),              m_impl_generics(nullptr),              m_item_generics(nullptr) @@ -65,5 +65,7 @@ namespace typeck {  typedef ::std::vector< ::std::pair<::HIR::Pattern, ::HIR::TypeRef> >    t_args; +// Needs to mutate the pattern +extern void Typecheck_Code(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr);  extern void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr);  extern void Typecheck_Code_Simple(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr); diff --git a/src/main.cpp b/src/main.cpp index 0e37f4a3..2dd05a05 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -513,7 +513,10 @@ int main(int argc, char *argv[])              HIR_Expand_Closures(*hir_crate);              });          // - Construct VTables for all traits and impls. -        CompilePhaseV("Expand HIR VTables", [&]() { HIR_Expand_VTables(*hir_crate); }); +        //  TODO: How early can this be done? +        CompilePhaseV("Expand HIR VTables", [&]() { +            HIR_Expand_VTables(*hir_crate); +            });          // - And calls can be turned into UFCS          CompilePhaseV("Expand HIR Calls", [&]() {              HIR_Expand_UfcsEverything(*hir_crate); @@ -560,11 +563,6 @@ int main(int argc, char *argv[])              MIR_CheckCrate(*hir_crate);              }); -        // Second shot of constant evaluation (with full type information) -        CompilePhaseV("Constant Evaluate Full", [&]() { -            ConvertHIR_ConstantEvaluateFull(*hir_crate); -            }); -          if( params.debug.dump_hir )          {              // DUMP after consteval (full HIR again) diff --git a/src/mir/check.cpp b/src/mir/check.cpp index cfcc52d4..b2d86590 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -285,6 +285,8 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn      };      ::std::vector<ToVisit> to_visit_blocks; +    // TODO: Check that all used locals are also set (anywhere at all) +      auto add_to_visit = [&](unsigned int idx, ::std::vector<unsigned int> src_path, auto vs) {          for(const auto& b : to_visit_blocks)              if( b.bb == idx && b.state == vs) diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 78939f78..37d256df 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -1219,7 +1219,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,  void MIR_CleanupCrate(::HIR::Crate& crate)  {      ::MIR::OuterVisitor    ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){ -            MIR_Cleanup(res, p, *expr_ptr.m_mir, args, ty); +            MIR_Cleanup(res, p, expr_ptr.get_mir_or_error_mut(Span()), args, ty);          } };      ov.visit_crate(crate);  } diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index c390f5b6..90b81d5d 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -515,7 +515,7 @@ namespace {              {                  m_os << indent() << "{\n";                  inc_indent(); -                dump_mir(m_os, m_indent_level, *item.m_code.m_mir); +                dump_mir(m_os, m_indent_level, item.m_code.get_mir_or_error(Span()));                  dec_indent();                  m_os << indent() << "}\n";              } @@ -538,7 +538,7 @@ namespace {                  inc_indent();                  m_os << " = {\n";                  inc_indent(); -                dump_mir(m_os, m_indent_level, *item.m_value.m_mir); +                dump_mir(m_os, m_indent_level, item.m_value.get_mir_or_error(Span()));                  dec_indent();                  m_os << indent() << "} /* = " << item.m_value_res << "*/;\n";                  dec_indent(); @@ -562,7 +562,7 @@ namespace {                  inc_indent();                  m_os << " = {\n";                  inc_indent(); -                dump_mir(m_os, m_indent_level, *item.m_value.m_mir); +                dump_mir(m_os, m_indent_level, item.m_value.get_mir_or_error(Span()));                  dec_indent();                  m_os << indent() << "} /* = " << item.m_value_res << "*/;\n";                  dec_indent(); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 66347879..5a629233 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -17,7 +17,7 @@  #include "from_hir.hpp"  #include "operations.hpp"  #include <mir/visit_crate_mir.hpp> - +#include <hir/expr_state.hpp>  namespace { @@ -1037,9 +1037,8 @@ namespace {              // Short-circuiting boolean operations              if( node.m_op == ::HIR::ExprNode_BinOp::Op::BoolAnd || node.m_op == ::HIR::ExprNode_BinOp::Op::BoolOr )              { -                // TODO: Generate a SplitScope to handle the early breaks. -                auto split_scope = m_builder.new_scope_split(node.span()); +                DEBUG("- ShortCircuit Left");                  this->visit_node_ptr(node.m_left);                  auto left = m_builder.get_result_in_lvalue(node.m_left->span(), ty_l); @@ -1048,12 +1047,16 @@ namespace {                  auto bb_false = m_builder.new_bb_unlinked();                  m_builder.end_block( ::MIR::Terminator::make_If({ mv$(left), bb_true, bb_false }) ); +                // Generate a SplitScope to handle the conditional nature of the next code +                auto split_scope = m_builder.new_scope_split(node.span()); +                  if( node.m_op == ::HIR::ExprNode_BinOp::Op::BoolOr )                  { +                    DEBUG("- ShortCircuit ||");                      // If left is true, assign result true and return                      m_builder.set_cur_block( bb_true );                      m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool({true}) )); -                    m_builder.end_split_arm(node.m_left->span(), split_scope, true); +                    m_builder.end_split_arm(node.m_left->span(), split_scope, /*reachable=*/true);                      m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );                      // If left is false, assign result to right @@ -1061,22 +1064,24 @@ namespace {                  }                  else                  { +                    DEBUG("- ShortCircuit &&");                      // If left is false, assign result false and return                      m_builder.set_cur_block( bb_false );                      m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool({false}) )); -                    m_builder.end_split_arm(node.m_left->span(), split_scope, true); +                    m_builder.end_split_arm(node.m_left->span(), split_scope, /*reachable=*/true);                      m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );                      // If left is true, assign result to right                      m_builder.set_cur_block( bb_true );                  } +                DEBUG("- ShortCircuit Right");                  auto tmp_scope = m_builder.new_scope_temp(node.m_right->span());                  this->visit_node_ptr(node.m_right);                  m_builder.push_stmt_assign(node.span(), res.clone(), m_builder.get_result(node.m_right->span()));                  m_builder.terminate_scope(node.m_right->span(), mv$(tmp_scope)); -                m_builder.end_split_arm(node.m_left->span(), split_scope, true); +                m_builder.end_split_arm(node.m_right->span(), split_scope, /*reachable=*/true);                  m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );                  m_builder.set_cur_block( bb_next ); @@ -2409,10 +2414,24 @@ namespace {  // -------------------------------------------------------------------- +void HIR_GenerateMIR_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& path, ::HIR::ExprPtr& expr_ptr, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& res_ty) +{ +    if( !expr_ptr.m_mir ) +    { +        StaticTraitResolve  resolve { crate }; +        if(expr_ptr.m_state->m_impl_generics)   resolve.set_impl_generics(*expr_ptr.m_state->m_impl_generics); +        if(expr_ptr.m_state->m_item_generics)   resolve.set_item_generics(*expr_ptr.m_state->m_item_generics); +        expr_ptr.set_mir( LowerMIR(resolve, path, expr_ptr, res_ty, args) ); +    } +} +  void HIR_GenerateMIR(::HIR::Crate& crate)  {      ::MIR::OuterVisitor    ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){ -            expr_ptr.m_mir = LowerMIR(res, p, expr_ptr, ty, args); +            if( !expr_ptr.get_mir_opt() ) +            { +                expr_ptr.set_mir( LowerMIR(res, p, expr_ptr, ty, args) ); +            }          } };      ov.visit_crate(crate);  } diff --git a/src/mir/main_bindings.hpp b/src/mir/main_bindings.hpp index cb4f3232..69d5fd90 100644 --- a/src/mir/main_bindings.hpp +++ b/src/mir/main_bindings.hpp @@ -7,10 +7,8 @@   */  #pragma once  #include <iostream> +#include <hir/hir.hpp> -namespace HIR { -class Crate; -}  class TransList;  extern void HIR_GenerateMIR(::HIR::Crate& crate); @@ -21,3 +19,5 @@ extern void MIR_CheckCrate_Full(/*const*/ ::HIR::Crate& crate);  extern void MIR_CleanupCrate(::HIR::Crate& crate);  extern void MIR_OptimiseCrate(::HIR::Crate& crate, bool minimal_optimisations);  extern void MIR_OptimiseCrate_Inlining(const ::HIR::Crate& crate, TransList& list); + +extern void HIR_GenerateMIR_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& path, ::HIR::ExprPtr& expr_ptr, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& res_ty); diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index f2b3a246..3e14ce66 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -2193,6 +2193,7 @@ void MirBuilder::moved_lvalue(const Span& sp, const ::MIR::LValue& lv)  {      if( !lvalue_is_copy(sp, lv) ) {          auto& vs = get_val_state_mut(sp, lv); +        // TODO: If the current state is Optional, set the drop flag to 0          vs = VarState::make_Invalid(InvalidType::Moved);      }  } diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 06a8e3dd..80bca08d 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -27,7 +27,7 @@  #define CHECK_AFTER_ALL     1  #define DUMP_AFTER_PASS     1 -#define DUMP_AFTER_DONE     0 +#define DUMP_AFTER_DONE     1  #define CHECK_AFTER_DONE    2   // 1 = Check before GC, 2 = check before and after GC  // ---- @@ -106,12 +106,14 @@ bool MIR_OptimiseInline(const StaticTraitResolve& resolve, const ::HIR::ItemPath          // - Constant propagation (inlining may have lead to some more constant information          MIR_Optimise_ConstPropagte(state, fcn);          // - Unify non-overlapping locals +#if 0          if(MIR_Optimise_UnifyTemporaries(state, fcn))          {  #if CHECK_AFTER_ALL              MIR_Validate(resolve, path, fcn, args, ret_type);  #endif          } +#endif          // - Remove no-op statements          MIR_Optimise_NoopRemoval(state, fcn); @@ -238,6 +240,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path      // Run UnifyTemporaries last, then unify blocks, then run some      // optimisations that might be affected +#if 0      if(MIR_Optimise_UnifyTemporaries(state, fcn))      {  #if CHECK_AFTER_ALL @@ -247,6 +250,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path          //MIR_Optimise_ConstPropagte(state, fcn);          MIR_Optimise_NoopRemoval(state, fcn);      } +#endif      #if DUMP_AFTER_DONE @@ -536,10 +540,10 @@ namespace {              if( it->second->monomorphised.code ) {                  return &*it->second->monomorphised.code;              } -            else if( hir_fcn.m_code.m_mir ) { +            else if( const auto* mir = hir_fcn.m_code.get_mir_opt() ) {                  MIR_ASSERT(state, hir_fcn.m_params.m_types.empty(), "Enumeration failure - Function had params, but wasn't monomorphised - " << path);                  // TODO: Check for trait methods too? -                return &*hir_fcn.m_code.m_mir; +                return mir;              }              else {                  MIR_ASSERT(state, !hir_fcn.m_code, "LowerMIR failure - No MIR but HIR is present?! - " << path); @@ -551,10 +555,10 @@ namespace {          TU_MATCHA( (path.m_data), (pe),          (Generic,              const auto& fcn = state.m_crate.get_function_by_path(state.sp, pe.m_path); -            if( fcn.m_code.m_mir ) +            if( const auto* mir = fcn.m_code.get_mir_opt() )              {                  params.fcn_params = &pe.m_params; -                return &*fcn.m_code.m_mir; +                return mir;              }              ),          (UfcsKnown, @@ -626,14 +630,14 @@ namespace {              {                  params.impl_params.m_types = mv$(best_impl_params);                  DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type); -                if( fit->second.data.m_code.m_mir ) -                    return &*fit->second.data.m_code.m_mir; +                if( const auto* mir = fit->second.data.m_code.get_mir_opt() ) +                    return mir;              }              else              {                  params.impl_params = pe.trait.m_params.clone(); -                if( ve.m_code.m_mir ) -                    return &*ve.m_code.m_mir; +                if( const auto* mir = ve.m_code.get_mir_opt() ) +                    return mir;              }              return nullptr;              ), @@ -653,12 +657,12 @@ namespace {              MIR_ASSERT(state, best_impl, "Couldn't find an impl for " << path);              auto fit = best_impl->m_methods.find(pe.item);              MIR_ASSERT(state, fit != best_impl->m_methods.end(), "Couldn't find method in best inherent impl"); -            if( fit->second.data.m_code.m_mir ) +            if( const auto* mir = fit->second.data.m_code.get_mir_opt() )              {                  params.self_ty = &*pe.type;                  params.fcn_params = &pe.params;                  params.impl_params = pe.impl_params.clone(); -                return &*fit->second.data.m_code.m_mir; +                return mir;              }              return nullptr;              ), @@ -3243,36 +3247,97 @@ bool MIR_Optimise_DeadDropFlags(::MIR::TypeResolve& state, ::MIR::Function& fcn)  {      bool removed_statement = false;      TRACE_FUNCTION_FR("", removed_statement); -    ::std::vector<bool> read_drop_flags( fcn.drop_flags.size() ); -    visit_blocks(state, fcn, [&read_drop_flags](auto , const ::MIR::BasicBlock& block) { -            for(const auto& stmt : block.statements) -            { -                if( const auto* e = stmt.opt_SetDropFlag() ) +    ::std::vector<bool> used_drop_flags( fcn.drop_flags.size() ); +    { +        ::std::vector<bool> read_drop_flags( fcn.drop_flags.size() ); +        visit_blocks(state, fcn, [&read_drop_flags,&used_drop_flags](auto , const ::MIR::BasicBlock& block) { +                for(const auto& stmt : block.statements)                  { -                    if(e->other != ~0u) { -                        read_drop_flags[e->other] = true; +                    if( const auto* e = stmt.opt_SetDropFlag() ) +                    { +                        if(e->other != ~0u) { +                            read_drop_flags[e->other] = true; +                            used_drop_flags[e->other] = true; +                        } +                        used_drop_flags[e->idx] = true; +                    } +                    else if( const auto* e = stmt.opt_Drop() ) +                    { +                        if(e->flag_idx != ~0u) { +                            read_drop_flags[e->flag_idx] = true; +                            used_drop_flags[e->flag_idx] = true; +                        }                      }                  } -                else if( const auto* e = stmt.opt_Drop() ) +                }); +        DEBUG("Un-read drop flags:" << FMT_CB(ss, +            for(size_t i = 0; i < read_drop_flags.size(); i ++) +                if( ! read_drop_flags[i] && used_drop_flags[i] ) +                    ss << " " << i; +            )); +        visit_blocks_mut(state, fcn, [&read_drop_flags,&removed_statement](auto _id, auto& block) { +                for(auto it = block.statements.begin(); it != block.statements.end(); )                  { -                    if(e->flag_idx != ~0u) { -                        read_drop_flags[e->flag_idx] = true; +                    if(it->is_SetDropFlag() && ! read_drop_flags[it->as_SetDropFlag().idx] ) { +                        removed_statement = true; +                        it = block.statements.erase(it); +                    } +                    else { +                        ++ it;                      }                  } -            } -            }); -    visit_blocks_mut(state, fcn, [&read_drop_flags,&removed_statement](auto _id, auto& block) { -            for(auto it = block.statements.begin(); it != block.statements.end(); ) -            { -                if(it->is_SetDropFlag() && ! read_drop_flags[it->as_SetDropFlag().idx] ) { -                    removed_statement = true; -                    it = block.statements.erase(it); +                }); +    } + +    // Find any drop flags that are never assigned with a value other than their default, then remove those dead assignments. +    { +        ::std::vector<bool> edited_drop_flags( fcn.drop_flags.size() ); +        visit_blocks(state, fcn, [&edited_drop_flags,&fcn](auto , const ::MIR::BasicBlock& block) { +                for(const auto& stmt : block.statements) +                { +                    if( const auto* e = stmt.opt_SetDropFlag() ) +                    { +                        if(e->other != ~0u) { +                            // If the drop flag is set based on another, assume it's changed +                            edited_drop_flags[e->idx] = true; +                        } +                        else if( e->new_val != fcn.drop_flags[e->idx] ) { +                            // If the new value is not the default, it's changed +                            edited_drop_flags[e->idx] = true; +                        } +                        else { +                            // Set to the default, doesn't change the 'edited' state +                        } +                    }                  } -                else { -                    ++ it; +                }); +        DEBUG("Un-edited drop flags:" << FMT_CB(ss, +            for(size_t i = 0; i < edited_drop_flags.size(); i ++) +                if( ! edited_drop_flags[i] && used_drop_flags[i] ) +                    ss << " " << i; +            )); +        visit_blocks_mut(state, fcn, [&edited_drop_flags,&removed_statement,&fcn](auto _id, auto& block) { +                for(auto it = block.statements.begin(); it != block.statements.end(); ) +                { +                    // If this is a SetDropFlag and the target flag isn't edited, remove +                    if(const auto* e = it->opt_SetDropFlag()) +                    { +                        if( ! edited_drop_flags[e->idx] ) { +                            assert( e->new_val == fcn.drop_flags[e->idx] ); +                            removed_statement = true; +                            it = block.statements.erase(it); +                        } +                        else { +                            ++ it; +                        } +                    } +                    else { +                        ++ it; +                    }                  } -            } -            }); +                }); +    } +      return removed_statement;  } @@ -3414,7 +3479,11 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn          visited[bb] = true;          auto assigned_lval = [&](const ::MIR::LValue& lv) { -            if(const auto* le = lv.opt_Local() ) +            const auto* lvp = &lv; +            // TODO: Consume through indexing/field accesses +            while(lvp->is_Field()) +                lvp = &*lvp->as_Field().val; +            if(const auto* le = lvp->opt_Local() )                  used_locals[*le] = true;              }; @@ -3732,11 +3801,12 @@ void MIR_OptimiseCrate(::HIR::Crate& crate, bool do_minimal_optimisation)              if( ! dynamic_cast<::HIR::ExprNode_Block*>(expr.get()) ) {                  return ;              } +            auto& mir = expr.get_mir_or_error_mut(Span());              if( do_minimal_optimisation ) { -                MIR_OptimiseMin(res, p, *expr.m_mir, args, ty); +                MIR_OptimiseMin(res, p, mir, args, ty);              }              else { -                MIR_Optimise(res, p, *expr.m_mir, args, ty); +                MIR_Optimise(res, p, mir, args, ty);              }          }          }; @@ -3769,9 +3839,10 @@ void MIR_OptimiseCrate_Inlining(const ::HIR::Crate& crate, TransList& list)              {                  did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, *mono_fcn.code, mono_fcn.arg_tys, mono_fcn.ret_ty, list);              } -            else if( hir_fcn.m_code.m_mir) +            else if( hir_fcn.m_code )              { -                did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, *hir_fcn.m_code.m_mir, hir_fcn.m_args, hir_fcn.m_return, list); +                auto& mir = hir_fcn.m_code.get_mir_or_error_mut(Span()); +                did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, mir, hir_fcn.m_args, hir_fcn.m_return, list);              }              else              { diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 322846e8..0ced3150 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1460,7 +1460,7 @@ namespace {                          var_lv.as_Downcast().variant_index = var_idx;                          m_of << "\tcase " << e->values[var_idx] << ":\n";                          emit_destructor_call(var_lv, repr->fields[var_idx].ty, /*unsized_valid=*/false, /*indent=*/2); -                        m_of << "\tbreak;\n"; +                        m_of << "\t\tbreak;\n";                      }                      m_of << "\t}\n";                  } @@ -4999,9 +4999,14 @@ namespace {                  {                  case MetadataType::None: -                    if( this->type_is_bad_zst(ty) && slot.is_Field() ) +                    if( this->type_is_bad_zst(ty) && (slot.is_Field() || slot.is_Downcast()) )                      { -                        m_of << indent << Trans_Mangle(p) << "((void*)&"; emit_lvalue(*slot.as_Field().val); m_of << ");\n"; +                        m_of << indent << Trans_Mangle(p) << "((void*)&"; +                        if( slot.is_Field() ) +                            emit_lvalue(*slot.as_Field().val); +                        else +                            emit_lvalue(*slot.as_Downcast().val); +                        m_of << ");\n";                      }                      else                      { diff --git a/tools/testrunner/main.cpp b/tools/testrunner/main.cpp index 5c21937d..3823215a 100644 --- a/tools/testrunner/main.cpp +++ b/tools/testrunner/main.cpp @@ -103,7 +103,8 @@ bool run_compiler(const ::helpers::path& source_file, const ::helpers::path& out      // Force optimised and debuggable      args.push_back("-O"); -    args.push_back("-g"); +    // TODO: Only turn debug on when requested by the caller +    //args.push_back("-g");      args.push_back("-L");      args.push_back("output"); @@ -386,14 +387,6 @@ int main(int argc, const char* argv[])                      else                          continue;                  } - -#ifdef __linux__ -                // Run `strip` on the test (if on linux) -                // XXX: Make this cleaner, or remove the need for it (by dynamic linking libstd) -                if( !run_executable("/usr/bin/strip", { "strip",  outfile.str().c_str() }, "/dev/null") ) -                { -                } -#endif              }              else              { | 
