summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/mir/check.cpp287
-rw-r--r--src/mir/cleanup.cpp96
-rw-r--r--src/mir/from_hir.cpp72
-rw-r--r--src/mir/helpers.cpp18
-rw-r--r--src/mir/helpers.hpp43
-rw-r--r--src/mir/operations.hpp12
-rw-r--r--src/trans/codegen.cpp12
-rw-r--r--src/trans/codegen_c.cpp5
9 files changed, 187 insertions, 360 deletions
diff --git a/Makefile b/Makefile
index e13b4a64..efe0ffea 100644
--- a/Makefile
+++ b/Makefile
@@ -93,7 +93,7 @@ OBJ += hir_expand/reborrow.o hir_expand/erased_types.o hir_expand/vtable.o
OBJ += mir/mir.o mir/mir_ptr.o
OBJ += mir/dump.o mir/helpers.o
OBJ += mir/from_hir.o mir/from_hir_match.o mir/mir_builder.o
-OBJ += mir/check.o
+OBJ += mir/check.o mir/cleanup.o
OBJ += hir/serialise.o hir/deserialise.o hir/serialise_lowlevel.o
OBJ += trans/trans_list.o trans/mangling.o
OBJ += trans/enumerate.o trans/monomorphise.o trans/codegen.o trans/codegen_c.o
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index aa76139f..24157f41 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -9,293 +9,12 @@
#include "mir.hpp"
#include <hir/visitor.hpp>
#include <hir_typeck/static.hpp>
+#include <mir/helpers.hpp>
-namespace {
- const unsigned int STMT_TERM = ~0u;
-
- #define MIR_BUG(state, ...) ( (state).print_bug( [&](auto& _os){_os << __VA_ARGS__; } ) )
- #define MIR_ASSERT(state, cnd, ...) do { if( !(cnd) ) (state).print_bug( [&](auto& _os){_os << "ASSERT " #cnd " failed - " << __VA_ARGS__; } ); } while(0)
- #define MIR_TODO(state, ...) ( (state).print_todo( [&](auto& _os){_os << __VA_ARGS__; } ) )
-
- struct MirCheckFailure {
- };
-
- struct State {
- typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > t_args;
-
- const StaticTraitResolve& resolve;
- const ::HIR::ItemPath& path;
- const ::MIR::Function& fcn;
- const t_args& args;
- const ::HIR::TypeRef& ret_type;
-
- unsigned int bb_idx = 0;
- unsigned int stmt_idx = 0;
- const ::HIR::SimplePath* m_lang_Box;
-
- Span sp;
-
- State(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const t_args& args, const ::HIR::TypeRef& ret_type):
- resolve(resolve),
- path(path),
- fcn(fcn),
- args(args),
- ret_type(ret_type)
- {
- if( resolve.m_crate.m_lang_items.count("owned_box") > 0 ) {
- m_lang_Box = &resolve.m_crate.m_lang_items.at("owned_box");
- }
- }
-
- void set_cur_stmt(unsigned int bb_idx, unsigned int stmt_idx) {
- this->bb_idx = bb_idx;
- this->stmt_idx = stmt_idx;
- }
- void set_cur_stmt_term(unsigned int bb_idx) {
- this->bb_idx = bb_idx;
- this->stmt_idx = STMT_TERM;
- }
-
- void print_bug(::std::function<void(::std::ostream& os)> cb) const {
- print_msg("ERROR", cb);
- }
- void print_todo(::std::function<void(::std::ostream& os)> cb) const {
- print_msg("TODO", cb);
- }
- void print_msg(const char* tag, ::std::function<void(::std::ostream& os)> cb) const
- {
- auto& os = ::std::cerr;
- os << "MIR " << tag << ": " << this->path << " BB" << this->bb_idx << "/";
- if( this->stmt_idx == STMT_TERM ) {
- os << "TERM";
- }
- else {
- os << this->stmt_idx;
- }
- os << ": ";
- cb(os);
- os << ::std::endl;
- // TODO: Throw something? Or mark an error so the rest of the function can be checked.
- throw MirCheckFailure {};
- }
-
- const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const
- {
- TU_MATCH(::MIR::LValue, (val), (e),
- (Variable,
- return this->fcn.named_variables.at(e);
- ),
- (Temporary,
- return this->fcn.temporaries.at(e.idx);
- ),
- (Argument,
- return this->args.at(e.idx).second;
- ),
- (Static,
- TU_MATCHA( (e.m_data), (pe),
- (Generic,
- MIR_ASSERT(*this, pe.m_params.m_types.empty(), "Path params on static");
- const auto& s = resolve.m_crate.get_static_by_path(sp, pe.m_path);
- return s.m_type;
- ),
- (UfcsKnown,
- MIR_TODO(*this, "LValue::Static - UfcsKnown - " << e);
- ),
- (UfcsUnknown,
- MIR_BUG(*this, "Encountered UfcsUnknown in LValue::Static - " << e);
- ),
- (UfcsInherent,
- MIR_TODO(*this, "LValue::Static - UfcsInherent - " << e);
- )
- )
- ),
- (Return,
- return this->ret_type;
- ),
- (Field,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Field access on unexpected type - " << ty);
- ),
- // Array and Slice use LValue::Field when the index is constant and known-good
- (Array,
- return *te.inner;
- ),
- (Slice,
- return *te.inner;
- ),
- (Tuple,
- MIR_ASSERT(*this, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size());
- return te[e.field_index];
- ),
- (Path,
- MIR_ASSERT(*this, te.binding.is_Struct(), "Field on non-Struct - " << ty);
- const auto& str = *te.binding.as_Struct();
- TU_MATCHA( (str.m_data), (se),
- (Unit,
- MIR_BUG(*this, "Field on unit-like struct - " << ty);
- ),
- (Tuple,
- MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct");
- const auto& fld = se[e.field_index];
- if( monomorphise_type_needed(fld.ent) ) {
- tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent);
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- }
- else {
- return fld.ent;
- }
- ),
- (Named,
- MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct");
- const auto& fld = se[e.field_index].second;
- if( monomorphise_type_needed(fld.ent) ) {
- tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent);
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- }
- else {
- return fld.ent;
- }
- )
- )
- )
- )
- ),
- (Deref,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Deref on unexpected type - " << ty);
- ),
- (Path,
- if( const auto* inner_ptr = this->is_type_owned_box(ty) )
- {
- return *inner_ptr;
- }
- else {
- MIR_BUG(*this, "Deref on unexpected type - " << ty);
- }
- ),
- (Pointer,
- return *te.inner;
- ),
- (Borrow,
- return *te.inner;
- )
- )
- ),
- (Index,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Index on unexpected type - " << ty);
- ),
- (Slice,
- return *te.inner;
- ),
- (Array,
- return *te.inner;
- )
- )
- ),
- (Downcast,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Downcast on unexpected type - " << ty);
- ),
- (Path,
- MIR_ASSERT(*this, te.binding.is_Enum() || te.binding.is_Union(), "Downcast on non-Enum");
- if( te.binding.is_Enum() )
- {
- const auto& enm = *te.binding.as_Enum();
- const auto& variants = enm.m_variants;
- MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range");
- const auto& variant = variants[e.variant_index];
- // TODO: Make data variants refer to associated types (unify enum and struct handling)
- TU_MATCHA( (variant.second), (ve),
- (Value,
- ),
- (Unit,
- ),
- (Tuple,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.ent) );
- tmp = ::HIR::TypeRef( mv$(tys) );
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- ),
- (Struct,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.second.ent) );
- tmp = ::HIR::TypeRef( mv$(tys) );
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- )
- )
- }
- else
- {
- const auto& unm = *te.binding.as_Union();
- MIR_ASSERT(*this, e.variant_index < unm.m_variants.size(), "Variant index out of range");
- const auto& variant = unm.m_variants[e.variant_index];
- const auto& var_ty = variant.second.ent;
-
- if( monomorphise_type_needed(var_ty) ) {
- tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, variant.second.ent);
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- }
- else {
- return var_ty;
- }
- }
- )
- )
- )
- )
- throw "";
- }
-
- const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const
- {
- if( m_lang_Box )
- {
- if( ! ty.m_data.is_Path() ) {
- return nullptr;
- }
- const auto& te = ty.m_data.as_Path();
-
- if( ! te.path.m_data.is_Generic() ) {
- return nullptr;
- }
- const auto& pe = te.path.m_data.as_Generic();
-
- if( pe.m_path != *m_lang_Box ) {
- return nullptr;
- }
- // TODO: Properly assert?
- return &pe.m_params.m_types.at(0);
- }
- else
- {
- return nullptr;
- }
- }
- };
-}
-
-void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const State::t_args& args, const ::HIR::TypeRef& ret_type)
+void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type)
{
Span sp;
- State state { resolve, path, fcn, args, ret_type };
+ ::MIR::TypeResolve state { sp, resolve, FMT_CB(ss, ss << path;), ret_type, args, fcn };
// Validation rules:
// [CFA] = Control Flow Analysis
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
new file mode 100644
index 00000000..9948a3b3
--- /dev/null
+++ b/src/mir/cleanup.cpp
@@ -0,0 +1,96 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * mir/cleanup.cpp
+ * - MIR Cleanup
+ *
+ * Removes artefacts left after monomorphisation
+ * - Converts <Trait as Trait>::method() into a vtable call
+ * - Replaces constants by their value
+ */
+#include "main_bindings.hpp"
+#include "mir.hpp"
+#include <hir/visitor.hpp>
+#include <hir_typeck/static.hpp>
+#include <mir/helpers.hpp>
+
+void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type)
+{
+ Span sp;
+ ::MIR::TypeResolve state { sp, resolve, FMT_CB(ss, ss << path;), ret_type, args, fcn };
+
+ for(auto& block : fcn.blocks)
+ {
+ for(auto& stmt : block.statements)
+ {
+ if( stmt.is_Assign() )
+ {
+ auto& se = stmt.as_Assign();
+
+ TU_IFLET( ::MIR::RValue, se.src, Constant, e,
+ // TODO: Replace `Const` with actual values
+ )
+ }
+ }
+
+ TU_IFLET( ::MIR::Terminator, block.terminator, CallPath, e,
+
+ // Detect calling `<Trait as Trait>::method()` and replace with vtable call
+ if( e.fcn_path.m_data.is_UfcsKnown() && e.fcn_path.m_data.as_UfcsKnown().type->m_data.is_TraitObject() )
+ {
+ const auto& pe = e.fcn_path.m_data.as_UfcsKnown();
+ const auto& te = pe.type->m_data.as_TraitObject();
+ // TODO: What if the method is from a supertrait?
+ if( pe.trait == te.m_trait.m_path )
+ {
+ assert( te.m_trait.m_trait_ptr );
+ const auto& trait = *te.m_trait.m_trait_ptr;
+
+ // 1. Get the vtable index for this function
+ if( trait.m_value_indexes.count(pe.item) == 0 )
+ BUG(sp, "Calling method '" << pe.item << "' of " << pe.trait << " which isn't in the vtable");
+ unsigned int vtable_idx = trait.m_value_indexes.at( pe.item );
+
+ // 2. Load from the vtable
+ auto vtable_ty_spath = pe.trait.m_path;
+ vtable_ty_spath.m_components.back() += "#vtable";
+ const auto& vtable_ref = resolve.m_crate.get_struct_by_path(sp, vtable_ty_spath);
+ // Copy the param set from the trait in the trait object
+ ::HIR::PathParams vtable_params = te.m_trait.m_path.m_params.clone();
+ // - Include associated types on bound
+ for(const auto& ty_b : te.m_trait.m_type_bounds) {
+ auto idx = trait.m_type_indexes.at(ty_b.first);
+ if(vtable_params.m_types.size() <= idx)
+ vtable_params.m_types.resize(idx+1);
+ vtable_params.m_types[idx] = ty_b.second.clone();
+ }
+ auto vtable_ty = ::HIR::TypeRef::new_pointer(
+ ::HIR::BorrowType::Shared,
+ ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref )
+ );
+
+ // Allocate a temporary for the vtable pointer itself
+ auto vtable_lv = ::MIR::LValue::make_Temporary({ static_cast<unsigned int>(fcn.temporaries.size()) });
+ fcn.temporaries.push_back( mv$(vtable_ty) );
+ // - Load the vtable and store it
+ auto vtable_rval = ::MIR::RValue::make_DstMeta({
+ ::MIR::LValue::make_Deref({ box$(e.args.front().clone()) })
+ });
+ block.statements.push_back( ::MIR::Statement::make_Assign({ vtable_lv.clone(), mv$(vtable_rval) }) );
+
+ // Update the terminator with the new information.
+ auto vtable_fcn = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(vtable_lv) })), vtable_idx });
+ auto new_term = ::MIR::Terminator::make_CallValue({
+ e.ret_block, e.panic_block,
+ mv$(e.ret_val), mv$(vtable_fcn),
+ mv$(e.args)
+ });
+
+ block.terminator = mv$(new_term);
+ }
+ }
+ )
+ }
+}
+
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 4792d793..cedbb5f5 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -15,6 +15,7 @@
#include <hir_typeck/common.hpp> // monomorphise_type
#include "main_bindings.hpp"
#include "from_hir.hpp"
+#include "operations.hpp"
namespace {
@@ -1355,7 +1356,6 @@ namespace {
void visit(::HIR::ExprNode_CallPath& node) override
{
- const Span& sp = node.span();
TRACE_FUNCTION_F("_CallPath " << node.m_path);
::std::vector< ::MIR::LValue> values;
values.reserve( node.m_args.size() );
@@ -1371,68 +1371,11 @@ namespace {
auto next_block = m_builder.new_bb_unlinked();
auto res = m_builder.new_temporary( node.m_res_type );
- // If the call was to a TraitObject function, get it from the vtable.
- // TODO: Should this be a later pass?
- bool was_virtual = false;
- if( node.m_path.m_data.is_UfcsKnown() && node.m_path.m_data.as_UfcsKnown().type->m_data.is_TraitObject() )
- {
- const auto& pe = node.m_path.m_data.as_UfcsKnown();
- const auto& te = pe.type->m_data.as_TraitObject();
- if( pe.trait == te.m_trait.m_path )
- {
- assert( te.m_trait.m_trait_ptr );
- const auto& trait = *te.m_trait.m_trait_ptr;
-
- // 1. Get the vtable index for this function
- if( trait.m_value_indexes.count(pe.item) == 0 )
- BUG(sp, "Calling method '" << pe.item << "' of " << pe.trait << " which isn't in the vtable");
- unsigned int vtable_idx = trait.m_value_indexes.at( pe.item );
-
- // 2. Load from the vtable
- auto vtable_rval = ::MIR::RValue::make_DstMeta({
- ::MIR::LValue::make_Deref({ box$(values.front().clone()) })
- });
- auto vtable_ty_spath = pe.trait.m_path;
- vtable_ty_spath.m_components.back() += "#vtable";
- const auto& vtable_ref = m_builder.crate().get_struct_by_path(sp, vtable_ty_spath);
- // Copy the param set from the trait in the trait object
- ::HIR::PathParams vtable_params = te.m_trait.m_path.m_params.clone();
- // - Include associated types on bound
- for(const auto& ty_b : te.m_trait.m_type_bounds) {
- auto idx = trait.m_type_indexes.at(ty_b.first);
- if(vtable_params.m_types.size() <= idx)
- vtable_params.m_types.resize(idx+1);
- vtable_params.m_types[idx] = ty_b.second.clone();
- }
- auto vtable_ty = ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref );
-
- auto vtable = m_builder.lvalue_or_temp(sp, mv$(vtable_ty), mv$(vtable_rval));
- auto vtable_fcn = ::MIR::LValue::make_Field({ box$(vtable), vtable_idx });
-
- ::MIR::LValue fcn_val;
- m_builder.with_val_type(sp, vtable_fcn, [&](const auto& ty){
- fcn_val = m_builder.new_temporary(ty);
- });
-
- m_builder.push_stmt_assign( sp, fcn_val.clone(), ::MIR::RValue( mv$(vtable_fcn) ) );
-
- was_virtual = true;
- m_builder.end_block(::MIR::Terminator::make_CallValue({
- next_block, panic_block,
- res.clone(), mv$(fcn_val),
- mv$(values)
- }));
- }
- }
-
- if( ! was_virtual )
- {
- m_builder.end_block(::MIR::Terminator::make_CallPath({
- next_block, panic_block,
- res.clone(), node.m_path.clone(),
- mv$(values)
- }));
- }
+ m_builder.end_block(::MIR::Terminator::make_CallPath({
+ next_block, panic_block,
+ res.clone(), node.m_path.clone(),
+ mv$(values)
+ }));
m_builder.set_cur_block(panic_block);
// TODO: Proper panic handling, including scope destruction
@@ -1904,6 +1847,9 @@ namespace {
root_node.visit( ev );
}
+ ::HIR::TypeRef ret;
+ MIR_Cleanup(resolve, ::HIR::ItemPath(), fcn, args, ret);
+
return ::MIR::FunctionPointer(new ::MIR::Function(mv$(fcn)));
}
diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp
index 59aa3420..e0721549 100644
--- a/src/mir/helpers.cpp
+++ b/src/mir/helpers.cpp
@@ -11,9 +11,21 @@
#include <hir/type.hpp>
#include <mir/mir.hpp>
-#define MIR_ASSERT(...) do{}while(0)
-#define MIR_BUG(...) do{}while(0)
-#define MIR_TODO(_, v...) TODO(sp, v)
+void ::MIR::TypeResolve::print_msg(const char* tag, ::std::function<void(::std::ostream& os)> cb) const
+{
+ auto& os = ::std::cerr;
+ os << "MIR " << tag << ": " << this->m_path << " BB" << this->bb_idx << "/";
+ if( this->stmt_idx == STMT_TERM ) {
+ os << "TERM";
+ }
+ else {
+ os << this->stmt_idx;
+ }
+ os << ": ";
+ cb(os);
+ os << ::std::endl;
+ throw CheckFailure {};
+}
const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const
{
diff --git a/src/mir/helpers.hpp b/src/mir/helpers.hpp
index 884cafa7..a986a3ae 100644
--- a/src/mir/helpers.hpp
+++ b/src/mir/helpers.hpp
@@ -22,33 +22,66 @@ namespace MIR {
class Function;
class LValue;
+struct CheckFailure:
+ public ::std::exception
+{
+};
+
+#define MIR_BUG(state, ...) ( (state).print_bug( [&](auto& _os){_os << __VA_ARGS__; } ) )
+#define MIR_ASSERT(state, cnd, ...) do { if( !(cnd) ) (state).print_bug( [&](auto& _os){_os << "ASSERT " #cnd " failed - " << __VA_ARGS__; } ); } while(0)
+#define MIR_TODO(state, ...) ( (state).print_todo( [&](auto& _os){_os << __VA_ARGS__; } ) )
+
class TypeResolve
{
public:
typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > args_t;
private:
+ const unsigned int STMT_TERM = ~0u;
+
const Span& sp;
+ const ::StaticTraitResolve& m_resolve;
const ::HIR::Crate& m_crate;
+ ::FmtLambda m_path;
const ::HIR::TypeRef& m_ret_type;
const args_t& m_args;
const ::MIR::Function& m_fcn;
- ::StaticTraitResolve m_resolve;
const ::HIR::SimplePath* m_lang_Box = nullptr;
+
+ unsigned int bb_idx = 0;
+ unsigned int stmt_idx = 0;
public:
- TypeResolve(const Span& sp, const ::HIR::Crate& crate, const ::HIR::TypeRef& ret_type, const args_t& args, const ::MIR::Function& fcn):
+ TypeResolve(const Span& sp, const ::StaticTraitResolve& resolve, ::FmtLambda path, const ::HIR::TypeRef& ret_type, const args_t& args, const ::MIR::Function& fcn):
sp(sp),
- m_crate(crate),
+ m_resolve(resolve),
+ m_crate(resolve.m_crate),
+ m_path(path),
m_ret_type(ret_type),
m_args(args),
- m_fcn(fcn),
- m_resolve(crate)
+ m_fcn(fcn)
{
if( m_crate.m_lang_items.count("owned_box") > 0 ) {
m_lang_Box = &m_crate.m_lang_items.at("owned_box");
}
}
+ void set_cur_stmt(unsigned int bb_idx, unsigned int stmt_idx) {
+ this->bb_idx = bb_idx;
+ this->stmt_idx = stmt_idx;
+ }
+ void set_cur_stmt_term(unsigned int bb_idx) {
+ this->bb_idx = bb_idx;
+ this->stmt_idx = STMT_TERM;
+ }
+
+ void print_bug(::std::function<void(::std::ostream& os)> cb) const {
+ print_msg("ERROR", cb);
+ }
+ void print_todo(::std::function<void(::std::ostream& os)> cb) const {
+ print_msg("TODO", cb);
+ }
+ void print_msg(const char* tag, ::std::function<void(::std::ostream& os)> cb) const;
+
const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const;
private:
diff --git a/src/mir/operations.hpp b/src/mir/operations.hpp
new file mode 100644
index 00000000..a32531e9
--- /dev/null
+++ b/src/mir/operations.hpp
@@ -0,0 +1,12 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * mir/operations.hpp
+ * - Common header for operations performed on MIR functions
+ */
+#include <hir_typeck/static.hpp>
+#include <hir/item_path.hpp>
+
+extern void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type);
+extern void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type);
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp
index 9256054f..bda64d02 100644
--- a/src/trans/codegen.cpp
+++ b/src/trans/codegen.cpp
@@ -9,6 +9,7 @@
#include "trans_list.hpp"
#include <hir/hir.hpp>
#include <mir/mir.hpp>
+#include <mir/operations.hpp>
#include "codegen.hpp"
#include "monomorphise.hpp"
@@ -236,9 +237,18 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons
const auto& fcn = *ent.second->ptr;
// TODO: If this is a provided trait method, it needs to be monomorphised too.
bool is_method = ( fcn.m_args.size() > 0 && visit_ty_with(fcn.m_args[0].second, [&](const auto& x){return x == ::HIR::TypeRef("Self",0xFFFF);}) );
- if( ent.second->pp.has_types() || is_method ) {
+ if( ent.second->pp.has_types() || is_method )
+ {
+ ::StaticTraitResolve resolve { crate };
+ auto ret_type = ent.second->pp.monomorph(crate, fcn.m_return);
+ ::HIR::Function::args_t args;
+ for(const auto& a : fcn.m_args)
+ args.push_back(::std::make_pair( ::HIR::Pattern{}, ent.second->pp.monomorph(crate, a.second) ));
auto mir = Trans_Monomorphise(crate, ent.second->pp, fcn.m_code.m_mir);
+ MIR_Validate(resolve, ::HIR::ItemPath(), *mir, args, ret_type);
+ MIR_Cleanup(resolve, ::HIR::ItemPath(), *mir, args, ret_type);
// TODO: MIR Optimisation
+ MIR_Validate(resolve, ::HIR::ItemPath(), *mir, args, ret_type);
codegen->emit_function_code(ent.first, fcn, ent.second->pp, mir);
}
else {
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index d7199b98..ee0719ef 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -273,7 +273,7 @@ namespace {
arg_types.push_back(::std::make_pair( ::HIR::Pattern{}, params.monomorph(m_crate, ent.second) ));
::HIR::TypeRef ret_type = params.monomorph(m_crate, item.m_return);
- ::MIR::TypeResolve mir_res { sp, m_crate, ret_type, arg_types, *code };
+ ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << p;), ret_type, arg_types, *code };
m_mir_res = &mir_res;
m_of << "// " << p << "\n";
@@ -294,7 +294,6 @@ namespace {
m_of << "\t// " << code->temporaries[i];
m_of << "\n";
}
- // TODO: Code.
for(unsigned int i = 0; i < code->blocks.size(); i ++)
{
TRACE_FUNCTION_F(p << " bb" << i);
@@ -305,6 +304,7 @@ namespace {
{
assert( stmt.is_Drop() || stmt.is_Assign() );
if( stmt.is_Drop() ) {
+ // TODO: Emit destructor calls
}
else {
const auto& e = stmt.as_Assign();
@@ -338,7 +338,6 @@ namespace {
m_of << " = ";
m_of << (c ? "true" : "false");
),
- // TODO: These need to be arrays, not strings! (strings are NUL terminated)
(Bytes,
emit_lvalue(e.dst);
m_of << ".PTR = ";