diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/static.cpp | 230 | ||||
-rw-r--r-- | src/hir_typeck/static.hpp | 10 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 94 | ||||
-rw-r--r-- | src/trans/target.cpp | 29 |
4 files changed, 187 insertions, 176 deletions
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index ff085ac6..fd2e2a76 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -1647,107 +1647,13 @@ bool StaticTraitResolve::type_is_clone(const Span& sp, const ::HIR::TypeRef& ty) bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) const { - TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e), - (Generic, - if( e.binding == 0xFFFF ) { - // TODO: Self: Sized? - return true; - } - else if( (e.binding >> 8) == 0 ) { - auto idx = e.binding & 0xFF; - assert( m_impl_generics ); - assert( idx < m_impl_generics->m_types.size() ); - return m_impl_generics->m_types[idx].m_is_sized; - } - else if( (e.binding >> 8) == 1 ) { - auto idx = e.binding & 0xFF; - assert( m_item_generics ); - assert( idx < m_item_generics->m_types.size() ); - return m_item_generics->m_types[idx].m_is_sized; - } - else { - BUG(sp, ""); - } - ), - (Path, - TU_MATCHA( (e.binding), (pbe), - (Unbound, - ), - (Opaque, - //auto pp = ::HIR::PathParams(); - //return this->find_impl(sp, m_lang_Sized, &pp, ty, [&](auto , bool){ return true; }, true); - // TODO: This can only be with UfcsKnown, so check if the trait specifies ?Sized - return true; - ), - (Struct, - // TODO: Destructure? - switch( pbe->m_struct_markings.dst_type ) - { - case ::HIR::StructMarkings::DstType::None: - return true; - case ::HIR::StructMarkings::DstType::Possible: - return type_is_sized( sp, e.path.m_data.as_Generic().m_params.m_types.at(pbe->m_struct_markings.unsized_param) ); - case ::HIR::StructMarkings::DstType::Slice: - case ::HIR::StructMarkings::DstType::TraitObject: - return false; - } - ), - (ExternType, - // Extern types aren't Sized - return false; - ), - (Enum, - ), - (Union, - ) - ) - return true; - ), - (Diverge, - // The ! type is kinda Sized ... - return true; - ), - (Closure, - return true; - ), - (Infer, - // Shouldn't be hit - return false; - ), - (Borrow, - return true; - ), - (Pointer, - return true; - ), - (Function, - return true; - ), - (Primitive, - // All primitives (except the unsized `str`) are Sized - return e != ::HIR::CoreType::Str; - ), - (Array, + switch( this->metadata_type(sp, ty) ) + { + case MetadataType::None: return true; - ), - (Slice, - return false; - ), - (TraitObject, + default: return false; - ), - (ErasedType, - // NOTE: All erased types are implicitly Sized - return true; - ), - (Tuple, - for(const auto& ty : e) - if( !type_is_sized(sp, ty) ) - return false; - return true; - ) - ) - throw ""; + } } bool StaticTraitResolve::type_is_impossible(const Span& sp, const ::HIR::TypeRef& ty) const { @@ -2018,7 +1924,133 @@ bool StaticTraitResolve::can_unsize(const Span& sp, const ::HIR::TypeRef& dst_ty DEBUG("Can't unsize, no rules matched"); return false; +} +MetadataType StaticTraitResolve::metadata_type(const Span& sp, const ::HIR::TypeRef& ty, bool err_on_unknown/*=false*/) const +{ + TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e), + (Generic, + if( e.binding == 0xFFFF ) { + // TODO: Self: Sized? + return MetadataType::None; + } + else if( (e.binding >> 8) == 0 ) { + auto idx = e.binding & 0xFF; + assert( m_impl_generics ); + assert( idx < m_impl_generics->m_types.size() ); + if( m_impl_generics->m_types[idx].m_is_sized ) { + return MetadataType::None; + } + else { + return MetadataType::Unknown; + } + } + else if( (e.binding >> 8) == 1 ) { + auto idx = e.binding & 0xFF; + assert( m_item_generics ); + assert( idx < m_item_generics->m_types.size() ); + if( m_item_generics->m_types[idx].m_is_sized ) { + return MetadataType::None; + } + else { + return MetadataType::Unknown; + } + } + else { + BUG(sp, "Unknown generic binding on " << ty); + } + ), + (Path, + TU_MATCHA( (e.binding), (pbe), + (Unbound, + // TODO: Should this return something else? + return MetadataType::Unknown; + ), + (Opaque, + //auto pp = ::HIR::PathParams(); + //return this->find_impl(sp, m_lang_Sized, &pp, ty, [&](auto , bool){ return true; }, true); + // TODO: This can only be with UfcsKnown, so check if the trait specifies ?Sized + //return MetadataType::Unknown; + return MetadataType::None; + ), + (Struct, + // TODO: Destructure? + switch( pbe->m_struct_markings.dst_type ) + { + case ::HIR::StructMarkings::DstType::None: + return MetadataType::None; + case ::HIR::StructMarkings::DstType::Possible: + return this->metadata_type( sp, e.path.m_data.as_Generic().m_params.m_types.at(pbe->m_struct_markings.unsized_param) ); + case ::HIR::StructMarkings::DstType::Slice: + return MetadataType::Slice; + case ::HIR::StructMarkings::DstType::TraitObject: + return MetadataType::TraitObject; + } + ), + (ExternType, + // Extern types aren't Sized, but have no metadata + return MetadataType::Zero; + ), + (Enum, + ), + (Union, + ) + ) + return MetadataType::None; + ), + (Diverge, + // The ! type is kinda Sized ... + return MetadataType::None; + ), + (Closure, + return MetadataType::None; + ), + (Infer, + // Shouldn't be hit + BUG(sp, "Found ivar? " << ty); + ), + (Borrow, + return MetadataType::None; + ), + (Pointer, + return MetadataType::None; + ), + (Function, + return MetadataType::None; + ), + (Primitive, + // All primitives (except the unsized `str`) are Sized + if( e == ::HIR::CoreType::Str ) + { + return MetadataType::Slice; + } + else + { + return MetadataType::None; + } + ), + (Array, + return MetadataType::None; + ), + (Slice, + return MetadataType::Slice; + ), + (TraitObject, + return MetadataType::TraitObject; + ), + (ErasedType, + // NOTE: All erased types are implicitly Sized + return MetadataType::None; + ), + (Tuple, + // TODO: Unsized tuples? are they a thing? + //for(const auto& ty : e) + // if( !type_is_sized(sp, ty) ) + // return false; + return MetadataType::None; + ) + ) + throw "bug"; } bool StaticTraitResolve::type_needs_drop_glue(const Span& sp, const ::HIR::TypeRef& ty) const diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index 4ed72ce6..0d9449b1 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -11,6 +11,14 @@ #include "common.hpp" #include "impl_ref.hpp" +enum class MetadataType { + Unknown, // Unknown still + None, // Sized pointer + Zero, // No metadata, but still unsized + Slice, // usize metadata + TraitObject, // VTable pointer metadata +}; + class StaticTraitResolve { public: @@ -204,6 +212,8 @@ public: bool type_is_impossible(const Span& sp, const ::HIR::TypeRef& ty) const; bool can_unsize(const Span& sp, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) const; + MetadataType metadata_type(const Span& sp, const ::HIR::TypeRef& ty, bool err_on_unknown=false) const; + /// Returns `true` if the passed type either implements Drop, or contains a type that implements Drop bool type_needs_drop_glue(const Span& sp, const ::HIR::TypeRef& ty) const; diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index e844a701..8b3b43ba 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -162,11 +162,6 @@ namespace { class CodeGenerator_C: public CodeGenerator { - enum class MetadataType { - None, - Slice, - TraitObject, - }; enum class Mode { //FullStd, Gcc, // Use GCC/Clang extensions @@ -916,6 +911,8 @@ namespace { case CodegenOutput::DynamicLibrary: args.push_back("/LD"); break; + default: + throw "bug"; } args.push_back(FMT("/Fe" << m_outfile_path)); @@ -4338,13 +4335,14 @@ namespace { } }; if( name == "size_of" ) { - // TODO: Target_GetSizeOf - emit_lvalue(e.ret_val); m_of << " = sizeof("; emit_ctype(params.m_types.at(0)); m_of << ")"; + size_t size = 0; + MIR_ASSERT(mir_res, Target_GetSizeOf(sp, m_resolve, params.m_types.at(0), size), "Can't get size of " << params.m_types.at(0)); + emit_lvalue(e.ret_val); m_of << " = " << size; } - else if( name == "min_align_of" ) { - // TODO: Target_GetAlignOf - //emit_lvalue(e.ret_val); m_of << " = alignof("; emit_ctype(params.m_types.at(0)); m_of << ")"; - emit_lvalue(e.ret_val); m_of << " = ALIGNOF("; emit_ctype(params.m_types.at(0)); m_of << ")"; + else if( name == "min_align_of" || name == "align_of" ) { + size_t align = 0; + MIR_ASSERT(mir_res, Target_GetAlignOf(sp, m_resolve, params.m_types.at(0), align), "Can't get alignment of " << params.m_types.at(0)); + emit_lvalue(e.ret_val); m_of << " = " << align; } else if( name == "size_of_val" ) { emit_lvalue(e.ret_val); m_of << " = "; @@ -4473,7 +4471,9 @@ namespace { emit_lvalue(e.ret_val); m_of << ".META = "; switch(dst_meta) { + case MetadataType::Unknown: assert(!"Impossible"); case MetadataType::None: assert(!"Impossible"); + case MetadataType::Zero: assert(!"Impossible"); case MetadataType::Slice: m_of << "(size_t)"; break; case MetadataType::TraitObject: m_of << "(const void*)"; break; } @@ -5286,8 +5286,10 @@ namespace { const char* make_fcn = nullptr; switch( metadata_type(ty) ) { + case MetadataType::Unknown: + MIR_BUG(*m_mir_res, ty << " unknown metadata"); case MetadataType::None: - + case MetadataType::Zero: if( this->type_is_bad_zst(ty) && (slot.is_Field() || slot.is_Downcast()) ) { m_of << indent << Trans_Mangle(p) << "((void*)&"; @@ -5575,7 +5577,10 @@ namespace { const auto& ity = *ty.m_data.as_Borrow().inner; switch( metadata_type(ity) ) { + case MetadataType::Unknown: + MIR_BUG(*m_mir_res, ity << " - Unknown meta"); case MetadataType::None: + case MetadataType::Zero: emit_dst(); m_of << " = &" << Trans_Mangle(e); break; case MetadataType::Slice: @@ -6071,61 +6076,9 @@ namespace { return ::HIR::TypeRef(); } } - // TODO: Move this to a more common location - MetadataType metadata_type(const ::HIR::TypeRef& ty) const - { - if( ty == ::HIR::CoreType::Str || ty.m_data.is_Slice() ) { - return MetadataType::Slice; - } - else if( ty.m_data.is_TraitObject() ) { - return MetadataType::TraitObject; - } - else if( ty.m_data.is_Path() ) - { - 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, - switch( tpb->m_struct_markings.dst_type ) - { - case ::HIR::StructMarkings::DstType::None: - return MetadataType::None; - case ::HIR::StructMarkings::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) { - 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 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::StructMarkings::DstType::Slice: - return MetadataType::Slice; - case ::HIR::StructMarkings::DstType::TraitObject: - return MetadataType::TraitObject; - } - ), - (Union, - return MetadataType::None; - ), - (Enum, - return MetadataType::None; - ) - ) - throw ""; - } - else { - return MetadataType::None; - } + + MetadataType metadata_type(const ::HIR::TypeRef& ty) const { + return m_resolve.metadata_type(m_mir_res ? m_mir_res->sp : sp, ty); } void emit_ctype_ptr(const ::HIR::TypeRef& inner_ty, ::FmtLambda inner) { @@ -6134,9 +6087,12 @@ namespace { //} //else { - switch( metadata_type(inner_ty) ) + switch( this->metadata_type(inner_ty) ) { + case MetadataType::Unknown: + BUG(sp, inner_ty << " unknown metadata type"); case MetadataType::None: + case MetadataType::Zero: emit_ctype(inner_ty, FMT_CB(ss, ss << "*" << inner;)); break; case MetadataType::Slice: @@ -6151,7 +6107,7 @@ namespace { bool is_dst(const ::HIR::TypeRef& ty) const { - return metadata_type(ty) != MetadataType::None; + return this->metadata_type(ty) != MetadataType::None; } }; Span CodeGenerator_C::sp; diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 141f5b78..126f71fb 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -659,26 +659,39 @@ bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve, // - Alignment is machine native out_align = g_target.m_arch.m_pointer_bits / 8; // - Size depends on Sized-nes of the parameter - if( resolve.type_is_sized(sp, *te.inner) ) + // TODO: Handle different types of Unsized (ones with different pointer sizes) + switch(resolve.metadata_type(sp, *te.inner)) { + case MetadataType::Unknown: + return false; + case MetadataType::None: + case MetadataType::Zero: out_size = g_target.m_arch.m_pointer_bits / 8; - return true; + break; + case MetadataType::Slice: + case MetadataType::TraitObject: + out_size = g_target.m_arch.m_pointer_bits / 8 * 2; + break; } - // TODO: Handle different types of Unsized (ones with different pointer sizes) - out_size = g_target.m_arch.m_pointer_bits / 8 * 2; return true; ), (Pointer, // - Alignment is machine native out_align = g_target.m_arch.m_pointer_bits / 8; // - Size depends on Sized-nes of the parameter - if( resolve.type_is_sized(sp, *te.inner) ) + switch(resolve.metadata_type(sp, *te.inner)) { + case MetadataType::Unknown: + return false; + case MetadataType::None: + case MetadataType::Zero: out_size = g_target.m_arch.m_pointer_bits / 8; - return true; + break; + case MetadataType::Slice: + case MetadataType::TraitObject: + out_size = g_target.m_arch.m_pointer_bits / 8 * 2; + break; } - // TODO: Handle different types of Unsized (ones with different pointer sizes) - out_size = g_target.m_arch.m_pointer_bits / 8 * 2; return true; ), (Function, |