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