diff options
Diffstat (limited to 'src/trans/codegen_c.cpp')
-rw-r--r-- | src/trans/codegen_c.cpp | 139 |
1 files changed, 75 insertions, 64 deletions
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 9b4f7c84..b7bdfec4 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -195,8 +195,6 @@ namespace { bool disallow_empty_structs = false; } m_options; - ::std::map<::HIR::GenericPath, ::std::vector<unsigned>> m_enum_repr_cache; - ::std::vector< ::std::pair< ::HIR::GenericPath, const ::HIR::Struct*> > m_box_glue_todo; public: CodeGenerator_C(const ::HIR::Crate& crate, const ::std::string& outfile): @@ -910,6 +908,10 @@ namespace { break; } } + else + { + m_of << ";\n"; + } auto struct_ty = ::HIR::TypeRef(p.clone(), &item); auto drop_glue_path = ::HIR::Path(struct_ty.clone(), "#drop_glue"); @@ -998,7 +1000,7 @@ namespace { void emit_enum_path(const TypeRepr* repr, const TypeRepr::FieldPath& path) { - if( path.index == repr->fields.size() - 1 ) + if( path.index == repr->fields.size() - 1 && !repr->variants.is_NonZero() ) { m_of << ".TAG"; } @@ -1006,10 +1008,19 @@ namespace { { m_of << ".DATA.var_" << path.index; } + const auto* ty = &repr->fields[path.index].ty; for(auto fld : path.sub_fields) { + repr = Target_GetTypeRepr(sp, m_resolve, *ty); + ty = &repr->fields[fld].ty; m_of << "._" << fld; } + if( const auto* te = ty->m_data.opt_Borrow() ) + { + if( metadata_type(*te->inner) != MetadataType::None ) { + m_of << ".PTR"; + } + } } void emit_enum(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Enum& item) override @@ -1023,9 +1034,13 @@ namespace { const auto* repr = Target_GetTypeRepr(sp, m_resolve, item_ty); // 1. Enumerate fields with the same offset as the first (these go into a union) + // TODO: What if all data variants are zero-sized? ::std::vector<unsigned> union_fields; for(size_t i = 1; i < repr->fields.size(); i ++) { + // Avoid placing the tag in the union + if( repr->variants.is_Values() && i == repr->variants.as_Values().field.index ) + continue ; if( repr->fields[i].offset == repr->fields[0].offset ) { union_fields.push_back(i); @@ -1063,7 +1078,7 @@ namespace { } else { - assert(repr->fields.back().offset != repr->fields.front().offset); + //assert(repr->fields.back().offset != repr->fields.front().offset); DEBUG("Tag present at offset " << repr->fields.back().offset << " - " << repr->fields.back().ty); m_of << "\t"; @@ -1079,6 +1094,15 @@ namespace { emit_ctype(repr->fields.back().ty, FMT_CB(os, os << "TAG")); m_of << ";\n"; } + else if( repr->fields.size() == 0 ) + { + // Empty/un-constructable + // - Shouldn't be emitted really? + if( m_options.disallow_empty_structs ) + { + m_of << "\tchar _d;\n"; + } + } else { // One data field and a tag (or all different offsets) @@ -1115,11 +1139,11 @@ namespace { { unsigned idx = 1 - e->zero_variant; // TODO: Fat pointers? - m_of << "\tif( rv"; emit_enum_path(repr, e->field); m_of << "!= 0 ) {\n"; - emit_destructor_call( ::MIR::LValue::make_Field({ box$(self), idx }), repr->fields[idx].ty, false, 2 ); + m_of << "\tif( (*rv)"; emit_enum_path(repr, e->field); m_of << " != 0 ) {\n"; + emit_destructor_call( ::MIR::LValue::make_Downcast({ box$(self), idx }), repr->fields[idx].ty, false, 2 ); m_of << "\t}\n"; } - else if( repr->fields.size() == 1 ) + else if( repr->fields.size() <= 1 ) { // Value enum // Glue does nothing (except call the destructor, if there is one) @@ -1159,6 +1183,7 @@ namespace { auto p = path.clone(); p.m_path.m_components.pop_back(); + const auto* repr = Target_GetTypeRepr(sp, m_resolve, ::HIR::TypeRef::new_path(p.clone(), &item)); ASSERT_BUG(sp, item.m_data.is_Data(), ""); const auto& var = item.m_data.as_Data().at(var_idx); @@ -1176,39 +1201,33 @@ namespace { emit_ctype( monomorph(e[i].ent), FMT_CB(ss, ss << "_" << i;) ); } m_of << ") {\n"; - auto it = m_enum_repr_cache.find(p); - if( it != m_enum_repr_cache.end() ) - { - m_of << "\tstruct e_" << Trans_Mangle(p) << " rv = { _0 };\n"; - } - else - { - m_of << "\tstruct e_" << Trans_Mangle(p) << " rv = { .TAG = " << var_idx; - if( e.empty() ) + //if( repr->variants. + m_of << "\tstruct e_" << Trans_Mangle(p) << " rv = { .TAG = " << var_idx; + + if( e.empty() ) + { + if( m_options.disallow_empty_structs ) { - if( m_options.disallow_empty_structs ) - { - m_of << ", .DATA = { .var_" << var_idx << " = {0} }"; - } - else - { - // No fields, don't initialise - } + m_of << ", .DATA = { .var_" << var_idx << " = {0} }"; } else { - m_of << ", .DATA = { .var_" << var_idx << " = {"; - for(unsigned int i = 0; i < e.size(); i ++) - { - if(i != 0) - m_of << ","; - m_of << "\n\t\t_" << i; - } - m_of << "\n\t\t}"; + // No fields, don't initialise + } + } + else + { + m_of << ", .DATA = { .var_" << var_idx << " = {"; + for(unsigned int i = 0; i < e.size(); i ++) + { + if(i != 0) + m_of << ","; + m_of << "\n\t\t_" << i; } - m_of << " }};\n"; + m_of << "\n\t\t}"; } + m_of << " }};\n"; m_of << "\treturn rv;\n"; m_of << "}\n"; } @@ -1369,7 +1388,7 @@ namespace { MIR_TODO(*m_mir_res, "Union literals"); ), (Enum, - MIR_ASSERT(*m_mir_res, pbe->m_data.is_Data(), ""); + MIR_ASSERT(*m_mir_res, pbe->m_data.is_Data(), "Getting inner type of a non-Data enum"); const auto& evar = pbe->m_data.as_Data().at(var); return monomorph_with(pp, evar.type); ) @@ -1403,15 +1422,19 @@ namespace { (Variant, MIR_ASSERT(*m_mir_res, ty.m_data.is_Path(), ""); MIR_ASSERT(*m_mir_res, ty.m_data.as_Path().binding.is_Enum(), ""); + const auto* repr = Target_GetTypeRepr(sp, m_resolve, ty); const auto& enm = *ty.m_data.as_Path().binding.as_Enum(); - auto it = m_enum_repr_cache.find(ty.m_data.as_Path().path.m_data.as_Generic()); - if( it != m_enum_repr_cache.end() ) + if( const auto* ve = repr->variants.opt_NonZero() ) { - if( e.idx == 0 ) { + if( e.idx == ve->zero_variant ) + { m_of << "{0}"; } - else { + else + { + m_of << "{ { .var_" << e.idx << " = "; emit_literal(get_inner_type(e.idx, 0), *e.val, params); + m_of << " } }"; } } else if( enm.is_value() ) @@ -1421,10 +1444,10 @@ namespace { } else { - m_of << "{" << e.idx; - m_of << ", { .var_" << e.idx << " = "; + m_of << "{"; + m_of << " { .var_" << e.idx << " = "; emit_literal(get_inner_type(e.idx, 0), *e.val, params); - m_of << " }"; + m_of << " }, .TAG = " << e.idx; m_of << "}"; } ), @@ -1747,7 +1770,7 @@ namespace { else if( item.m_linkage.name == "CopyFileExW" ) { // Not field access to undo an Option<fn()> - m_of << "\treturn CopyFileExW(arg0, arg1, arg2._1._0, arg3, arg4, arg5);\n"; + m_of << "\treturn CopyFileExW(arg0, arg1, arg2.DATA.var_1._0, arg3, arg4, arg5);\n"; } // BUG: libtest defines this as returning an i32, but it's void else if( item.m_linkage.name == "GetSystemInfo" ) @@ -2489,21 +2512,20 @@ namespace { { ::HIR::TypeRef tmp; const auto& ty = mir_res.get_lvalue_type(tmp, e.dst); + auto* repr = Target_GetTypeRepr(sp, m_resolve, ty); - auto it = m_enum_repr_cache.find(ty.m_data.as_Path().path.m_data.as_Generic()); - if( it != m_enum_repr_cache.end() ) + if( const auto* re = repr->variants.opt_NonZero() ) { - if( ve.index == 0 ) { + MIR_ASSERT(*m_mir_res, ve.index < 2, ""); + if( ve.index == re->zero_variant ) { // TODO: Use nonzero_path m_of << "memset(&"; emit_lvalue(e.dst); m_of << ", 0, sizeof("; emit_ctype(ty); m_of << "))"; } - else if( ve.index == 1 ) { + else { emit_lvalue(e.dst); - m_of << "._1 = "; + m_of << ".DATA.var_" << ve.index << " = "; emit_param(ve.val); } - else { - } break; } else if( enm_p->is_value() ) @@ -2727,12 +2749,12 @@ namespace { if( const auto* e = repr->variants.opt_NonZero() ) { MIR_ASSERT(mir_res, n_arms == 2, "NonZero optimised switch without two arms"); - m_of << indent << "if( "; emit_lvalue(val); emit_enum_path(repr, e->field); m_of << " != 0)\n"; - m_of << indent; + m_of << indent << "if( "; emit_lvalue(val); emit_enum_path(repr, e->field); m_of << " != 0 )\n"; + m_of << indent << "\t"; cb(1 - e->zero_variant); m_of << "\n"; m_of << indent << "else\n"; - m_of << indent; + m_of << indent << "\t"; cb(e->zero_variant); m_of << "\n"; } @@ -4381,18 +4403,7 @@ namespace { MIR_ASSERT(*m_mir_res, ty.m_data.is_Path(), "Downcast on non-Path type - " << ty); if( ty.m_data.as_Path().binding.is_Enum() ) { - auto it = m_enum_repr_cache.find(ty.m_data.as_Path().path.m_data.as_Generic()); - if( it != m_enum_repr_cache.end() ) - { - MIR_ASSERT(*m_mir_res, e.variant_index == 1, ""); - // NOTE: Downcast returns a magic tuple - m_of << "._1"; - break ; - } - else - { - m_of << ".DATA"; - } + m_of << ".DATA"; } m_of << ".var_" << e.variant_index; ) |