summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/static.cpp230
-rw-r--r--src/hir_typeck/static.hpp10
-rw-r--r--src/trans/codegen_c.cpp94
-rw-r--r--src/trans/target.cpp29
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,