summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--src/hir/expr.cpp2
-rw-r--r--src/hir/expr.hpp5
-rw-r--r--src/hir/expr_ptr.cpp54
-rw-r--r--src/hir/expr_ptr.hpp44
-rw-r--r--src/hir/expr_state.hpp42
-rw-r--r--src/hir/hir.cpp64
-rw-r--r--src/hir/hir.hpp13
-rw-r--r--src/hir/item_path.hpp20
-rw-r--r--src/hir_conv/bind.cpp133
-rw-r--r--src/hir_conv/constant_evaluation.cpp1168
-rw-r--r--src/hir_expand/annotate_value_usage.cpp11
-rw-r--r--src/hir_expand/closures.cpp5
-rw-r--r--src/hir_expand/const_eval_full.cpp952
-rw-r--r--src/hir_expand/main_bindings.hpp6
-rw-r--r--src/hir_expand/reborrow.cpp5
-rw-r--r--src/hir_expand/ufcs_everything.cpp5
-rw-r--r--src/hir_typeck/expr_visit.cpp9
-rw-r--r--src/hir_typeck/expr_visit.hpp6
-rw-r--r--src/main.cpp10
-rw-r--r--src/mir/check.cpp2
-rw-r--r--src/mir/cleanup.cpp2
-rw-r--r--src/mir/dump.cpp6
-rw-r--r--src/mir/from_hir.cpp33
-rw-r--r--src/mir/main_bindings.hpp6
-rw-r--r--src/mir/mir_builder.cpp1
-rw-r--r--src/mir/optimise.cpp141
27 files changed, 823 insertions, 1923 deletions
diff --git a/Makefile b/Makefile
index f006f1ff..1eda93dd 100644
--- a/Makefile
+++ b/Makefile
@@ -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_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_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..ef9c5fc9 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;
}
@@ -3732,11 +3797,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 +3835,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
{