diff options
author | John Hodge <tpg@ucc.asn.au> | 2019-11-02 11:03:09 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2019-11-02 11:03:09 +0800 |
commit | d73beca6906a014370551e5de95f9b56538c45dc (patch) | |
tree | 33e8a932ce3bf6f1a324deee38ca06e7fdc1ba88 /Notes | |
parent | 35a8ebae9d90f1a82c1df2bfd4c2b119e9865797 (diff) | |
download | mrust-d73beca6906a014370551e5de95f9b56538c45dc.tar.gz |
Notes - Aborted attempt at inline enum tags (problems with static initialisation)
Diffstat (limited to 'Notes')
-rw-r--r-- | Notes/CodegenCEmbeddedTags.diff | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/Notes/CodegenCEmbeddedTags.diff b/Notes/CodegenCEmbeddedTags.diff new file mode 100644 index 00000000..62fea1cb --- /dev/null +++ b/Notes/CodegenCEmbeddedTags.diff @@ -0,0 +1,168 @@ +diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp +index 9af87d47..bcf296db 100644 +--- a/src/trans/codegen_c.cpp ++++ b/src/trans/codegen_c.cpp +@@ -1385,12 +1385,22 @@ namespace { + + void emit_enum_path(const TypeRepr* repr, const TypeRepr::FieldPath& path) + { +- if( TU_TEST1(repr->variants, Values, .field.index == path.index) ) ++ if( TU_TEST1(repr->variants, Values, .field.index == path.index) || path.index == ~0u ) + { +- m_of << ".TAG"; ++ // TODO: The tag can be within the union ++ if( repr->fields.size() >= 2 ) ++ { ++ m_of << ".DATA.var_tag.TAG"; ++ } ++ else ++ { ++ m_of << ".TAG"; ++ } ++ return ; + } + else + { ++ // TODO: Support for non-zero offsets? + m_of << ".DATA.var_" << path.index; + } + const auto* ty = &repr->fields[path.index].ty; +@@ -1458,55 +1468,44 @@ namespace { + assert(1 + union_fields.size() + 1 >= repr->fields.size()); + // Make the union! + // NOTE: The way the structure generation works is that enum variants are always first, so the field index = the variant index +- // TODO: +- if( !this->type_is_bad_zst(repr->fields[0].ty) || ::std::any_of(union_fields.begin(), union_fields.end(), [this,repr](auto x){ return !this->type_is_bad_zst(repr->fields[x].ty); }) ) ++ m_of << "\tunion {\n"; ++ bool is_tagged = (1 + union_fields.size() < repr->fields.size()); ++ // > First field ++ for(size_t idx = 0; idx < repr->fields.size()-(is_tagged ? 1 : 0); idx ++) + { +- m_of << "\tunion {\n"; +- // > First field +- { +- m_of << "\t\t"; +- const auto& ty = repr->fields[0].ty; +- if( this->type_is_bad_zst(ty) ) { +- m_of << "// ZST: " << ty << "\n"; +- } +- else { +- emit_ctype( ty, FMT_CB(ss, ss << "var_0") ); +- m_of << ";\n"; +- //sized_fields ++; +- } ++ m_of << "\t\tstruct {"; ++ const auto& ty = repr->fields[idx].ty; ++ if( this->type_is_bad_zst(ty) ) { ++ m_of << "/* ZST: " << ty << "*/"; + } +- // > All others +- for(auto idx : union_fields) ++ else { ++ emit_ctype( ty, FMT_CB(os, os << "d") ); ++ m_of << ";"; ++ //sized_fields ++; ++ } ++ if( is_tagged ) + { +- m_of << "\t\t"; +- +- const auto& ty = repr->fields[idx].ty; +- if( this->type_is_bad_zst(ty) ) { +- m_of << "// ZST: " << ty << "\n"; +- } +- else { +- emit_ctype( ty, FMT_CB(ss, ss << "var_" << idx) ); +- m_of << ";\n"; +- //sized_fields ++; ++ auto padbytes = repr->fields.back().offset - Target_GetSizeOf(ty); ++ if( padbytes > 0 ) ++ { ++ m_of << "char pad[" << padbytes << "];"; + } ++ emit_ctype(repr->fields.back().ty, FMT_CB(os, os << "TAG")); m_of << ";"; + } +- m_of << "\t} DATA;\n"; ++ m_of << "} var_" << idx << "\n"; + } +- +- if( repr->fields.size() == 1 + union_fields.size() ) ++ // NOTE: The tag can be placed within variants (overlapping with padding bytes) ++ if( !is_tagged ) + { + // No tag, the tag is in one of the fields. + DEBUG("Untagged, nonzero or other"); + } + else + { +- //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"; +- emit_ctype(repr->fields.back().ty, FMT_CB(os, os << "TAG")); +- m_of << ";\n"; ++ m_of << "\t\tstruct { char pad[" << repr->fields.back().offset << "]; "; emit_ctype(repr->fields.back().ty, FMT_CB(os, os << "TAG")); m_of << "; } var_tag;\n"; + } ++ m_of << "\t} DATA;\n"; + } + else if( repr->fields.size() == 1 ) + { +@@ -1591,7 +1590,7 @@ namespace { + { + auto var_lv =::MIR::LValue::new_Downcast(mv$(self), 0); + +- m_of << "\tswitch(rv->TAG) {\n"; ++ m_of << "\tswitch((*rv)";emit_enum_path(repr, {~0u}); m_of << ") {\n"; + for(unsigned int var_idx = 0; var_idx < e->values.size(); var_idx ++) + { + m_of << "\tcase " << e->values[var_idx] << ":\n"; +@@ -1652,7 +1651,7 @@ namespace { + { + case TypeRepr::VariantMode::TAGDEAD: throw ""; + TU_ARM(repr->variants, Values, ve) { +- m_of << " .TAG = "; emit_enum_variant_val(repr, var_idx); m_of << ","; ++ m_of << " .DATA = { .var_tag = { .TAG = "; emit_enum_variant_val(repr, var_idx); m_of << " }},"; + } break; + TU_ARM(repr->variants, NonZero, ve) { + } break; +@@ -1949,7 +1948,7 @@ namespace { + emit_literal(ity, *e.val, params); + m_of << " }, "; + } +- m_of << ".TAG = "; emit_enum_variant_val(repr, e.idx); ++ emit_enum_path(repr, {~0u}); m_of << " = "; emit_enum_variant_val(repr, e.idx); + m_of << "}"; + } + ), +@@ -3292,11 +3291,11 @@ namespace { + } + else if( enm_p->is_value() ) + { +- emit_lvalue(e.dst); m_of << ".TAG = "; emit_enum_variant_val(repr, ve.index); ++ emit_lvalue(e.dst); emit_enum_path(repr, {~0u}); m_of << " = "; emit_enum_variant_val(repr, ve.index); + } + else + { +- emit_lvalue(e.dst); m_of << ".TAG = "; emit_enum_variant_val(repr, ve.index); ++ emit_lvalue(e.dst); emit_enum_path(repr, {~0u}); m_of << " = "; emit_enum_variant_val(repr, ve.index); + + ::HIR::TypeRef tmp; + const auto& vty = mir_res.get_param_type(tmp, ve.val); +@@ -3542,7 +3541,7 @@ namespace { + if (ve.type.m_data.is_Primitive() && ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Enum()) + { + emit_lvalue(ve.val); +- m_of << ".TAG"; ++ m_of << ".TAG"; // TODO: Fix for tag locations? (may not be needed for value-only enums) + special = true; + } + if (!special) +@@ -3605,7 +3604,7 @@ namespace { + case ::HIR::CoreType::Str: + MIR_BUG(mir_res, "Unsized tag?!"); + } +- m_of << indent << "switch("; emit_lvalue(val); m_of << ".TAG) {\n"; ++ m_of << indent << "switch("; emit_lvalue(val); emit_enum_path(repr, {~0u}); m_of << ") {\n"; + for(size_t j = 0; j < n_arms; j ++) + { + // TODO: Get type of this field and check if it's signed. |