summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-01-04 19:20:12 +0800
committerJohn Hodge <tpg@mutabah.net>2017-01-04 19:20:12 +0800
commit622e52e7d4bd5bc5dc71dfaa84884a3a1cd0a750 (patch)
tree1833dece4daf57c48c4fd38815f1e99e4607d04f
parenta8c40b454e57866656edeff731bab67f0d96e6d9 (diff)
downloadmrust-622e52e7d4bd5bc5dc71dfaa84884a3a1cd0a750.tar.gz
Codegen C - DST fixes, diverging UfcsInherent
-rw-r--r--src/include/tagged_union.hpp9
-rw-r--r--src/mir/check.cpp34
-rw-r--r--src/trans/codegen_c.cpp144
3 files changed, 178 insertions, 9 deletions
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index bb9c537e..9bd060d6 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -133,13 +133,12 @@
// Internals of TU_CONS
#define TU_CONS_I(__name, __tag, __type) \
__name(__type v): m_tag(TAG_##__tag) { new (&m_data.__tag) __type( ::std::move(v) ); } \
- static self_t make_##__tag(__type v) \
- {\
- return __name( ::std::move(v) );\
- }\
+ static self_t make_##__tag(__type v) { return __name( ::std::move(v) ); }\
bool is_##__tag() const { return m_tag == TAG_##__tag; } \
+ const __type* opt_##__tag() const { if(m_tag == TAG_##__tag) return &m_data.__tag; return nullptr; } \
+ __type* opt_##__tag() { if(m_tag == TAG_##__tag) return &m_data.__tag; return nullptr; } \
const __type& as_##__tag() const { assert(m_tag == TAG_##__tag); return m_data.__tag; } \
- __type& as_##__tag() { assert(m_tag == TAG_##__tag); return m_data.__tag; } \
+ __type& as_##__tag() { assert(m_tag == TAG_##__tag); return m_data.__tag; } \
__type unwrap_##__tag() { return ::std::move(this->as_##__tag()); } \
// Define a tagged union constructor
#define TU_CONS(__name, name, ...) TU_CONS_I(__name, name, TU_DATANAME(name))
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index d6fcb1b9..8a350f3c 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -12,6 +12,38 @@
#include <mir/helpers.hpp>
#include <mir/visit_crate_mir.hpp>
+namespace {
+ ::HIR::TypeRef get_metadata_type(const StaticTraitResolve& resolve, const ::HIR::TypeRef& unsized_ty)
+ {
+ TU_MATCH_DEF(::HIR::TypeRef::Data, (unsized_ty.m_data), (te),
+ (
+ return ::HIR::TypeRef();
+ ),
+ (TraitObject,
+ const auto& trait_path = te.m_trait;
+ const auto& trait = *te.m_trait.m_trait_ptr;
+
+ auto vtable_ty_spath = trait_path.m_path.m_path;
+ vtable_ty_spath.m_components.back() += "#vtable";
+ const auto& vtable_ref = resolve.m_crate.get_struct_by_path(Span(), vtable_ty_spath);
+ // Copy the param set from the trait in the trait object
+ ::HIR::PathParams vtable_params = trait_path.m_path.m_params.clone();
+ // - Include associated types
+ for(const auto& ty_b : trait_path.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();
+ }
+ return ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref );
+ ),
+ (Slice,
+ return ::HIR::CoreType::Usize;
+ )
+ )
+ }
+}
+
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)
{
TRACE_FUNCTION_F(path);
@@ -604,7 +636,6 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
// TODO: Check return type
),
(MakeDst,
- #if 0
::HIR::TypeRef tmp;
const auto& ty = state.get_lvalue_type(tmp, a.dst);
const ::HIR::TypeRef* ity_p = nullptr;
@@ -619,7 +650,6 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
{
MIR_BUG(state, "DstMeta requires a pointer to an unsized type as output, got " << ty);
}
- #endif
// TODO: Check metadata type?
),
(Tuple,
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 9580f7f5..a59d947a 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -68,6 +68,8 @@ namespace {
<< "\treturn 0;\n"
<< "}\n"
<< "\n"
+ << "size_t max(size_t a, size_t b) { return a < b ? b : a; }\n"
+ << "\n"
;
}
@@ -1488,6 +1490,18 @@ namespace {
),
(UfcsInherent,
// TODO: Check if the return type is !
+ is_diverge |= m_resolve.m_crate.find_type_impls(*pe.type, [&](const auto& ty)->const auto& { return ty; },
+ [&](const auto& impl) {
+ // Associated functions
+ {
+ auto it = impl.m_methods.find(pe.item);
+ if( it != impl.m_methods.end() ) {
+ return it->second.data.m_return.m_data.is_Diverge();
+ }
+ }
+ // Associated static (undef)
+ return false;
+ });
),
(UfcsKnown,
// TODO: Check if the return type is !
@@ -1622,6 +1636,34 @@ namespace {
else if( name == "size_of_val" ) {
emit_lvalue(e.ret_val); m_of << " = ";
const auto& ty = params.m_types.at(0);
+ //TODO: Get the unsized type and use that in place of MetadataType
+ #if 1
+ auto inner_ty = get_inner_unsized_type(ty);
+ if( inner_ty == ::HIR::TypeRef() ) {
+ m_of << "sizeof("; emit_ctype(ty); m_of << ")";
+ }
+ else if( const auto* te = inner_ty.m_data.opt_Slice() ) {
+ if( ! ty.m_data.is_Slice() ) {
+ m_of << "sizeof("; emit_ctype(ty); m_of << ") + ";
+ }
+ emit_lvalue(e.args.at(0)); m_of << ".META * sizeof("; emit_ctype(*te->inner); m_of << ")";
+ }
+ else if( inner_ty == ::HIR::CoreType::Str ) {
+ if( ! ty.m_data.is_Slice() ) {
+ m_of << "sizeof("; emit_ctype(ty); m_of << ") + ";
+ }
+ emit_lvalue(e.args.at(0)); m_of << ".META";
+ }
+ else if( inner_ty.m_data.is_TraitObject() ) {
+ if( ! ty.m_data.is_TraitObject() ) {
+ m_of << "sizeof("; emit_ctype(ty); m_of << ") + ";
+ }
+ m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->size";
+ }
+ else {
+ MIR_BUG(mir_res, "Unknown inner unsized type " << inner_ty << " for " << ty);
+ }
+ #else
switch( metadata_type(ty) )
{
case MetadataType::None:
@@ -1636,10 +1678,46 @@ namespace {
m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->size";
break;
}
+ #endif
}
else if( name == "min_align_of_val" ) {
emit_lvalue(e.ret_val); m_of << " = ";
const auto& ty = params.m_types.at(0);
+ #if 1
+ auto inner_ty = get_inner_unsized_type(ty);
+ if( inner_ty == ::HIR::TypeRef() ) {
+ m_of << "__alignof__("; emit_ctype(ty); m_of << ")";
+ }
+ else if( const auto* te = inner_ty.m_data.opt_Slice() ) {
+ if( ! ty.m_data.is_Slice() ) {
+ m_of << "max( __alignof__("; emit_ctype(ty); m_of << "), ";
+ }
+ m_of << "__alignof__("; emit_ctype(*te->inner); m_of << ")";
+ if( ! ty.m_data.is_Slice() ) {
+ m_of << " )";
+ }
+ }
+ else if( inner_ty == ::HIR::CoreType::Str ) {
+ if( ! ty.m_data.is_Primitive() ) {
+ m_of << "__alignof__("; emit_ctype(ty); m_of << ")";
+ }
+ else {
+ m_of << "1";
+ }
+ }
+ else if( inner_ty.m_data.is_TraitObject() ) {
+ if( ! ty.m_data.is_TraitObject() ) {
+ m_of << "max( __alignof__("; emit_ctype(ty); m_of << "), ";
+ }
+ m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->align";
+ if( ! ty.m_data.is_TraitObject() ) {
+ m_of << " )";
+ }
+ }
+ else {
+ MIR_BUG(mir_res, "Unknown inner unsized type " << inner_ty << " for " << ty);
+ }
+ #else
switch( metadata_type(ty) )
{
case MetadataType::None:
@@ -1654,6 +1732,7 @@ namespace {
m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->align";
break;
}
+ #endif
}
else if( name == "type_id" ) {
emit_lvalue(e.ret_val); m_of << " = (uintptr_t)&__typeid_" << Trans_Mangle(params.m_types.at(0));
@@ -2300,6 +2379,56 @@ namespace {
)
}
+ ::HIR::TypeRef get_inner_unsized_type(const ::HIR::TypeRef& ty)
+ {
+ if( ty == ::HIR::CoreType::Str || ty.m_data.is_Slice() ) {
+ return ty.clone();
+ }
+ else if( ty.m_data.is_TraitObject() ) {
+ return ty.clone();
+ }
+ else if( ty.m_data.is_Path() )
+ {
+ const ::HIR::TraitMarkings* markings;
+ TU_MATCH_DEF( ::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (tpb),
+ (
+ MIR_BUG(*m_mir_res, "Unbound/opaque path in trans - " << ty);
+ ),
+ (Struct, markings = &tpb->m_markings; ),
+ (Union, markings = &tpb->m_markings; ),
+ (Enum, markings = &tpb->m_markings; )
+ )
+ switch( markings->dst_type )
+ {
+ case ::HIR::TraitMarkings::DstType::None:
+ return ::HIR::TypeRef();
+ case ::HIR::TraitMarkings::DstType::Slice:
+ case ::HIR::TraitMarkings::DstType::TraitObject:
+ case ::HIR::TraitMarkings::DstType::Possible: {
+ // TODO: How to figure out? Lazy way is to check the monomorpised type of the last field (structs only)
+ const auto& path = ty.m_data.as_Path().path.m_data.as_Generic();
+ const auto& str = *ty.m_data.as_Path().binding.as_Struct();
+ auto monomorph = [&](const auto& tpl) {
+ // TODO: expand_associated_types
+ auto rv = monomorphise_type(sp, str.m_params, path.m_params, tpl);
+ m_resolve.expand_associated_types(sp, rv);
+ return rv;
+ };
+ TU_MATCHA( (str.m_data), (se),
+ (Unit, MIR_BUG(*m_mir_res, "Unit-like struct with DstType::Possible"); ),
+ (Tuple, return get_inner_unsized_type( monomorph(se.back().ent) ); ),
+ (Named, return get_inner_unsized_type( monomorph(se.back().second.ent) ); )
+ )
+ throw "";
+ }
+ }
+ throw "";
+ }
+ else
+ {
+ return ::HIR::TypeRef();
+ }
+ }
MetadataType metadata_type(const ::HIR::TypeRef& ty)
{
if( ty == ::HIR::CoreType::Str || ty.m_data.is_Slice() ) {
@@ -2323,10 +2452,21 @@ namespace {
{
case ::HIR::TraitMarkings::DstType::None:
return MetadataType::None;
- case ::HIR::TraitMarkings::DstType::Possible:
- // TODO: How to figure out?
+ case ::HIR::TraitMarkings::DstType::Possible: {
+ // TODO: How to figure out? Lazy way is to check the monomorpised type of the last field (structs only)
+ const auto& path = ty.m_data.as_Path().path.m_data.as_Generic();
+ const auto& str = *ty.m_data.as_Path().binding.as_Struct();
+ auto monomorph = [&](const auto& tpl) {
+ return monomorphise_type(sp, str.m_params, path.m_params, tpl);
+ };
+ TU_MATCHA( (str.m_data), (se),
+ (Unit, MIR_BUG(*m_mir_res, "Unit-like struct with DstType::Possible"); ),
+ (Tuple, return metadata_type( monomorph(se.back().ent) ); ),
+ (Named, return metadata_type( monomorph(se.back().second.ent) ); )
+ )
//MIR_TODO(*m_mir_res, "Determine DST type when ::Possible - " << ty);
return MetadataType::None;
+ }
case ::HIR::TraitMarkings::DstType::Slice:
return MetadataType::Slice;
case ::HIR::TraitMarkings::DstType::TraitObject: