diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | src/mir/check.cpp | 287 | ||||
| -rw-r--r-- | src/mir/cleanup.cpp | 96 | ||||
| -rw-r--r-- | src/mir/from_hir.cpp | 72 | ||||
| -rw-r--r-- | src/mir/helpers.cpp | 18 | ||||
| -rw-r--r-- | src/mir/helpers.hpp | 43 | ||||
| -rw-r--r-- | src/mir/operations.hpp | 12 | ||||
| -rw-r--r-- | src/trans/codegen.cpp | 12 | ||||
| -rw-r--r-- | src/trans/codegen_c.cpp | 5 | 
9 files changed, 187 insertions, 360 deletions
| @@ -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 = "; | 
