summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-04 17:05:03 +0800
committerJohn Hodge <tpg@mutabah.net>2016-12-04 17:05:03 +0800
commit0fa897c376084e2719c00af35bc3d8b6c0c02da9 (patch)
tree0dfcc38937c1ae27f7a0ee28b59bf310cc2a0cf9 /src
parent30f37248ed90edd2a8102f4d7365d785ba4fd587 (diff)
downloadmrust-0fa897c376084e2719c00af35bc3d8b6c0c02da9.tar.gz
Trans C - Some special cases
Diffstat (limited to 'src')
-rw-r--r--src/mir/helpers.cpp226
-rw-r--r--src/mir/helpers.hpp59
-rw-r--r--src/trans/codegen_c.cpp64
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;
+ }
};
}