diff options
Diffstat (limited to 'src/trans/codegen_c.cpp')
-rw-r--r-- | src/trans/codegen_c.cpp | 96 |
1 files changed, 79 insertions, 17 deletions
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 37acb33b..8836af54 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -50,6 +50,7 @@ namespace { << "typedef struct { } tTYPEID;\n" << "typedef struct { void* PTR; size_t META; } SLICE_PTR;\n" << "typedef struct { void* PTR; void* META; } TRAITOBJ_PTR;\n" + << "typedef struct { size_t size; size_t align; } VTABLE_HDR;\n" << "\n" << "extern void _Unwind_Resume(void);\n" << "\n" @@ -134,7 +135,17 @@ namespace { emit_ctype( monomorph(ty), inner ); } }; + m_of << "// struct " << p << "\n"; m_of << "struct s_" << Trans_Mangle(p) << " {\n"; + + // HACK: For vtables, insert the alignment and size at the start + { + const auto& lc = p.m_path.m_components.back(); + if( lc.size() > 7 && ::std::strcmp(lc.c_str() + lc.size() - 7, "#vtable") == 0 ) { + m_of << "\tVTABLE_HDR hdr;\n"; + } + } + TU_MATCHA( (item.m_data), (e), (Unit, ), @@ -190,14 +201,32 @@ namespace { if( item.m_markings.has_drop_impl ) { m_of << "tUNIT " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(struct s_" << Trans_Mangle(p) << "*rv);\n"; } - + else if( const auto* ity = m_resolve.is_type_owned_box(struct_ty) ) + { + ::HIR::TypeRef inner_ptr = ::HIR::TypeRef::new_pointer( ::HIR::BorrowType::Unique, ity->clone() ); + ::HIR::GenericPath box_free { m_crate.get_lang_item_path(sp, "box_free"), { ity->clone() } }; + m_of << "tUNIT " << Trans_Mangle(box_free) << "("; emit_ctype(inner_ptr, FMT_CB(ss, ss << "tmp0"; )); m_of << ");\n"; + } + m_of << "void " << Trans_Mangle(drop_glue_path) << "(struct s_" << Trans_Mangle(p) << "* rv) {\n"; // If this type has an impl of Drop, call that impl if( item.m_markings.has_drop_impl ) { m_of << "\t" << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(rv);\n"; } - + else if( const auto* ity = m_resolve.is_type_owned_box(struct_ty) ) + { + // Obtain inner pointer + // TODO: This is very specific to the structure of the official liballoc's Box. + ::HIR::TypeRef inner_ptr = ::HIR::TypeRef::new_pointer( ::HIR::BorrowType::Unique, ity->clone() ); + m_of << "\t"; emit_ctype(inner_ptr, FMT_CB(ss, ss << "tmp0"; )); m_of << " = rv->_0._0._0;\n"; + // Call destructor of inner data + emit_destructor_call( ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Temporary({0})) }), *ity, true); + // Emit a call to box_free for the type + ::HIR::GenericPath box_free { m_crate.get_lang_item_path(sp, "box_free"), { ity->clone() } }; + m_of << "\t" << Trans_Mangle(box_free) << "(tmp0);\n"; + } + auto self = ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) }); auto fld_lv = ::MIR::LValue::make_Field({ box$(self), 0 }); TU_MATCHA( (item.m_data), (e), @@ -506,11 +535,16 @@ namespace { auto monomorph_cb_trait = monomorphise_type_get_cb(sp, &type, &trait_path.m_params, nullptr); - // TODO: Alignment and destructor + // Size, Alignment, and destructor + m_of << "{ "; + m_of << "sizeof("; emit_ctype(type); m_of << "),"; + m_of << "__alignof__("; emit_ctype(type); m_of << "),"; + // TODO: Drop glue + m_of << "}"; // No newline, added below + for(unsigned int i = 0; i < trait.m_value_indexes.size(); i ++ ) { - if( i != 0 ) - m_of << ",\n"; + m_of << ",\n"; for(const auto& m : trait.m_value_indexes) { if( m.second.first != i ) @@ -585,7 +619,7 @@ namespace { if( code->blocks[i].statements.size() == 0 && code->blocks[i].terminator.is_Diverge() ) { DEBUG("- Diverge only, omitting"); - m_of << "bb" << i << ": _Unwind_Resume(); // Diverge\n"; + m_of << "bb" << i << ": _Unwind_Resume(); // Diverge\n"; continue ; } @@ -602,10 +636,26 @@ namespace { ::HIR::TypeRef tmp; const auto& ty = mir_res.get_lvalue_type(tmp, e.slot); - if( e.kind == ::MIR::eDropKind::SHALLOW ) { - // TODO: Shallow drops are only valid on owned_box + switch( e.kind ) + { + case ::MIR::eDropKind::SHALLOW: + // Shallow drops are only valid on owned_box + if( const auto* ity = m_resolve.is_type_owned_box(ty) ) + { + // Emit a call to box_free for the type + ::HIR::GenericPath box_free { m_crate.get_lang_item_path(sp, "box_free"), { ity->clone() } }; + // TODO: This is specific to the official liballoc's owned_box + m_of << "\t" << Trans_Mangle(box_free) << "("; emit_lvalue(e.slot); m_of << "._0._0._0);\n"; + } + else + { + MIR_BUG(mir_res, "Shallow drop on non-Box - " << ty); + } + break; + case ::MIR::eDropKind::DEEP: + emit_destructor_call(e.slot, ty, false); + break; } - emit_destructor_call(e.slot, ty, false); } else { const auto& e = stmt.as_Assign(); @@ -959,11 +1009,13 @@ namespace { case MetadataType::None: m_of << "sizeof("; emit_ctype(ty); m_of << ")"; break; - case MetadataType::Slice: - MIR_TODO(mir_res, "size_of_val - " << ty); - break; + case MetadataType::Slice: { + // TODO: Have a function that fetches the inner type for types like `Path` or `str` + const auto& ity = *ty.m_data.as_Slice().inner; + emit_lvalue(e.args.at(0)); m_of << ".META * sizeof("; emit_ctype(ity); m_of << ")"; + break; } case MetadataType::TraitObject: - MIR_TODO(mir_res, "size_of_val - " << ty); + m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->size"; break; } } @@ -974,11 +1026,13 @@ namespace { case MetadataType::None: m_of << "__alignof__("; emit_ctype(ty); m_of << ")"; break; - case MetadataType::Slice: - MIR_TODO(mir_res, "min_align_of_val - " << ty); - break; + case MetadataType::Slice: { + // TODO: Have a function that fetches the inner type for types like `Path` or `str` + const auto& ity = *ty.m_data.as_Slice().inner; + m_of << "__alignof__("; emit_ctype(ity); m_of << ")"; + break; } case MetadataType::TraitObject: - MIR_TODO(mir_res, "min_align_of_val - " << ty); + m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->align"; break; } } @@ -1097,6 +1151,14 @@ namespace { else if( name == "atomic_cxchg_acqrel_failrelaxed" ) { emit_atomic_cxchg(e, "memory_order_acq_rel", "memory_order_relaxed"); } + // _rel = Release, Relaxed (not Release,Release) + else if( name == "atomic_cxchg_rel" ) { + emit_atomic_cxchg(e, "memory_order_release", "memory_order_relaxed"); + } + // _acqrel = Release, Acquire (not AcqRel,AcqRel) + else if( name == "atomic_cxchg_acqrel" ) { + emit_atomic_cxchg(e, "memory_order_acq_rel", "memory_order_acquire"); + } else if( name.compare(0, 7+6+4, "atomic_cxchg_fail") == 0 ) { auto fail_ordering = H::get_atomic_ordering(mir_res, name, 7+6+4); emit_atomic_cxchg(e, "memory_order_seq_cst", fail_ordering); |