diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-04 17:05:03 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-04 17:05:03 +0800 |
commit | 0fa897c376084e2719c00af35bc3d8b6c0c02da9 (patch) | |
tree | 0dfcc38937c1ae27f7a0ee28b59bf310cc2a0cf9 /src | |
parent | 30f37248ed90edd2a8102f4d7365d785ba4fd587 (diff) | |
download | mrust-0fa897c376084e2719c00af35bc3d8b6c0c02da9.tar.gz |
Trans C - Some special cases
Diffstat (limited to 'src')
-rw-r--r-- | src/mir/helpers.cpp | 226 | ||||
-rw-r--r-- | src/mir/helpers.hpp | 59 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 64 |
3 files changed, 345 insertions, 4 deletions
diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp new file mode 100644 index 00000000..59aa3420 --- /dev/null +++ b/src/mir/helpers.cpp @@ -0,0 +1,226 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * mir/helpers.hpp + * - MIR Manipulation helpers + */ +#include "helpers.hpp" + +#include <hir/hir.hpp> +#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) + +const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const +{ + TU_MATCH(::MIR::LValue, (val), (e), + (Variable, + return m_fcn.named_variables.at(e); + ), + (Temporary, + return m_fcn.temporaries.at(e.idx); + ), + (Argument, + return m_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 = 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 m_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); + m_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); + m_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) ); + m_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) ); + m_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); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return var_ty; + } + } + ) + ) + ) + ) + throw ""; +} +const ::HIR::TypeRef* ::MIR::TypeResolve::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; + } +} diff --git a/src/mir/helpers.hpp b/src/mir/helpers.hpp new file mode 100644 index 00000000..884cafa7 --- /dev/null +++ b/src/mir/helpers.hpp @@ -0,0 +1,59 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * mir/helpers.hpp + * - MIR Manipulation helpers + */ +#pragma once +#include <vector> +#include <functional> +#include <hir_typeck/static.hpp> + +namespace HIR { +class Crate; +class TypeRef; +class Pattern; +class SimplePath; +} + +namespace MIR { + +class Function; +class LValue; + +class TypeResolve +{ +public: + typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > args_t; +private: + const Span& sp; + const ::HIR::Crate& m_crate; + 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; + +public: + TypeResolve(const Span& sp, const ::HIR::Crate& crate, const ::HIR::TypeRef& ret_type, const args_t& args, const ::MIR::Function& fcn): + sp(sp), + m_crate(crate), + m_ret_type(ret_type), + m_args(args), + m_fcn(fcn), + m_resolve(crate) + { + if( m_crate.m_lang_items.count("owned_box") > 0 ) { + m_lang_Box = &m_crate.m_lang_items.at("owned_box"); + } + } + + const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const; + +private: + const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const; +}; + + +} // namespace MIR diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 05d4105a..fc7310a0 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -11,6 +11,8 @@ #include <hir/hir.hpp> #include <mir/mir.hpp> #include <hir_typeck/static.hpp> +#include <mir/helpers.hpp> + namespace { class CodeGenerator_C: @@ -34,6 +36,7 @@ namespace { << "#include <stdbool.h>\n" << "typedef uint32_t CHAR;\n" << "typedef struct { } tUNIT;\n" + << "typedef struct { } tBANG;\n" << "typedef struct { char* PTR; size_t META; } STR_PTR;\n" << "typedef struct { void* PTR; size_t META; } SLICE_PTR;\n" << "typedef struct { void* PTR; void* META; } TRAITOBJ_PTR;\n" @@ -202,6 +205,13 @@ namespace { { static Span sp; TRACE_FUNCTION_F(p); + + ::MIR::TypeResolve::args_t arg_types; + for(const auto& ent : item.m_args) + 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 }; m_of << "// " << p << "\n"; emit_function_header(p, item, params); @@ -318,12 +328,44 @@ namespace { (Borrow, emit_lvalue(e.dst); m_of << " = "; - m_of << "& "; emit_lvalue(ve.val); + bool special = false; + // If the inner value has type [T] or str, just assign. + TU_IFLET(::MIR::LValue, ve.val, Deref, e, + ::HIR::TypeRef tmp; + const auto& ty = mir_res.get_lvalue_type(tmp, ve.val); // NOTE: Checks the result of the deref + if( is_dst(ty) ) { + emit_lvalue(*e.val); + special = true; + } + ) + if( !special ) + { + m_of << "& "; emit_lvalue(ve.val); + } ), (Cast, emit_lvalue(e.dst); m_of << " = "; - m_of << "("; emit_ctype(ve.type); m_of << ")"; emit_lvalue(ve.val); + m_of << "("; emit_ctype(ve.type); m_of << ")"; + // TODO: If the source is an unsized borrow, then extract the pointer + bool special = false; + if( ve.type.m_data.is_Pointer() && !is_dst( *ve.type.m_data.as_Pointer().inner ) ) + { + ::HIR::TypeRef tmp; + const auto& ty = mir_res.get_lvalue_type(tmp, ve.val); // NOTE: Checks the result of the deref + if( (ty.m_data.is_Borrow() && is_dst(*ty.m_data.as_Borrow().inner)) + || (ty.m_data.is_Pointer() && is_dst(*ty.m_data.as_Pointer().inner)) + ) + { + emit_lvalue(ve.val); + m_of << ".PTR"; + special = true; + } + } + if( !special ) + { + emit_lvalue(ve.val); + } ), (BinOp, emit_lvalue(e.dst); @@ -417,7 +459,9 @@ namespace { } ) ) - m_of << ";\n"; + m_of << ";"; + m_of << "\t// " << e.dst << " = " << e.src; + m_of << "\n"; } } TU_MATCHA( (code->blocks[i].terminator), (e), @@ -535,7 +579,7 @@ namespace { m_of << "@" << ty << "@"; ), (Diverge, - m_of << "void"; + m_of << "tBANG"; ), (Primitive, switch(te) @@ -641,6 +685,18 @@ namespace { ) ) } + + int is_dst(const ::HIR::TypeRef& ty) const + { + if( ty == ::HIR::CoreType::Str ) + return 1; + if( ty.m_data.is_Slice() ) + return 1; + if( ty.m_data.is_TraitObject() ) + return 2; + // TODO: Unsized named types. + return 0; + } }; } |