diff options
author | John Hodge <tpg@mutabah.net> | 2017-01-04 19:20:12 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2017-01-04 19:20:12 +0800 |
commit | 622e52e7d4bd5bc5dc71dfaa84884a3a1cd0a750 (patch) | |
tree | 1833dece4daf57c48c4fd38815f1e99e4607d04f | |
parent | a8c40b454e57866656edeff731bab67f0d96e6d9 (diff) | |
download | mrust-622e52e7d4bd5bc5dc71dfaa84884a3a1cd0a750.tar.gz |
Codegen C - DST fixes, diverging UfcsInherent
-rw-r--r-- | src/include/tagged_union.hpp | 9 | ||||
-rw-r--r-- | src/mir/check.cpp | 34 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 144 |
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: |