summaryrefslogtreecommitdiff
path: root/Notes
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-11-02 11:03:09 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-11-02 11:03:09 +0800
commitd73beca6906a014370551e5de95f9b56538c45dc (patch)
tree33e8a932ce3bf6f1a324deee38ca06e7fdc1ba88 /Notes
parent35a8ebae9d90f1a82c1df2bfd4c2b119e9865797 (diff)
downloadmrust-d73beca6906a014370551e5de95f9b56538c45dc.tar.gz
Notes - Aborted attempt at inline enum tags (problems with static initialisation)
Diffstat (limited to 'Notes')
-rw-r--r--Notes/CodegenCEmbeddedTags.diff168
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.