summaryrefslogtreecommitdiff
path: root/src/trans/codegen_c.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/trans/codegen_c.cpp')
-rw-r--r--src/trans/codegen_c.cpp144
1 files changed, 142 insertions, 2 deletions
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: