diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-05-01 09:50:58 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-05-01 09:50:58 +0800 |
commit | bc62d7864a0820bb612d00db605ec65fc542cbad (patch) | |
tree | f85ca4c87e85bc20499f7674c97c522abab52f81 | |
parent | a67157ddbbe91e089ad4bee572fb364acd9b3e75 (diff) | |
download | mrust-bc62d7864a0820bb612d00db605ec65fc542cbad.tar.gz |
HIR - Rough support for enum variant values (trans only, no consteval)
-rw-r--r-- | src/hir/dump.cpp | 8 | ||||
-rw-r--r-- | src/hir/hir.cpp | 24 | ||||
-rw-r--r-- | src/hir/hir.hpp | 5 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 91 |
4 files changed, 98 insertions, 30 deletions
diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp index 7e877a4f..614e95eb 100644 --- a/src/hir/dump.cpp +++ b/src/hir/dump.cpp @@ -165,7 +165,13 @@ namespace { (Unit, ), (Value, - m_os << " = ?";// << + m_os << " = "; + if( e.val.is_Invalid() ) { + m_os << "?"; + } + else { + m_os << e.val; + } ), (Tuple, m_os << "("; diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 66dc0e0b..ce80e43c 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -93,6 +93,30 @@ const ::HIR::Enum::Variant* ::HIR::Enum::get_variant(const ::std::string& name) return nullptr; return &it->second; } +bool HIR::Enum::is_value() const +{ + return this->m_repr != ::HIR::Enum::Repr::Rust || ::std::all_of(m_variants.begin(), m_variants.end(), [](const auto& x){return x.second.is_Unit() || x.second.is_Value();}); +} +uint32_t HIR::Enum::get_value(size_t idx) const +{ + assert(idx < m_variants.size()); + + if( const auto* e = m_variants[idx].second.opt_Value() ) + { + return e->val.as_Integer(); + } + + uint32_t val = 0; + for(size_t i = 0; i < idx; i ++) + { + if( const auto* e = m_variants[i].second.opt_Value() ) + { + val = e->val.as_Integer(); + } + val ++; + } + return val; +} namespace { bool matches_genericpath(const ::HIR::GenericParams& params, const ::HIR::GenericPath& left, const ::HIR::GenericPath& right, ::HIR::t_cb_resolve_type ty_res, bool expand_generic); diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index b87385a0..b7d116e3 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -218,6 +218,11 @@ public: TraitMarkings m_markings; const Variant* get_variant(const ::std::string& ) const; + + /// Returns true if this enum is a C-like enum (has values only) + bool is_value() const; + /// Returns the value for the given variant + uint32_t get_value(size_t variant) const; }; class Struct { diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 1ca8c4ae..0c9f7805 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -987,10 +987,10 @@ namespace { m_of << "}"; } } - else if( enm.m_repr != ::HIR::Enum::Repr::Rust || ::std::all_of(enm.m_variants.begin(), enm.m_variants.end(), [](const auto& x){return x.second.is_Unit() || x.second.is_Value();}) ) + else if( enm.is_value() ) { MIR_ASSERT(*m_mir_res, e.vals.empty(), "Value-only enum with fields"); - m_of << "{" << e.idx << "}"; + m_of << "{" << enm.get_value(e.idx) << "}"; } else { @@ -1675,43 +1675,65 @@ namespace { } ), (Variant, - if( m_crate.get_typeitem_by_path(sp, ve.path.m_path).is_Union() ) + const auto& tyi = m_crate.get_typeitem_by_path(sp, ve.path.m_path); + if( tyi.is_Union() ) { emit_lvalue(e.dst); + m_of << ".var_" << ve.index << " = "; emit_param(ve.val); } - else + else if( const auto* enm_p = tyi.opt_Enum() ) { MIR_TODO(mir_res, "Construct enum with RValue::Variant"); - emit_lvalue(e.dst); m_of << ".TAG = " << ve.index << ";\n\t"; - emit_lvalue(e.dst); m_of << ".DATA"; + if( enm_p->is_value() ) + { + emit_lvalue(e.dst); m_of << ".TAG = " << enm_p->get_value(ve.index) << ""; + } + else + { + emit_lvalue(e.dst); m_of << ".TAG = " << ve.index << ";\n\t"; + emit_lvalue(e.dst); m_of << ".DATA"; + m_of << ".var_" << ve.index << " = "; emit_param(ve.val); + } + } + else + { + BUG(mir_res.sp, "Unexpected type in Variant"); } - m_of << ".var_" << ve.index << " = "; emit_param(ve.val); ), (Struct, - if(ve.variant_idx != ~0u) { + if(ve.variant_idx != ~0u) + { ::HIR::TypeRef tmp; const auto& ty = mir_res.get_lvalue_type(tmp, e.dst); - 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() ) - { - if( ve.variant_idx == 0 ) { - // TODO: Use nonzero_path - m_of << "memset(&"; emit_lvalue(e.dst); m_of << ", 0, sizeof("; emit_ctype(ty); m_of << "))"; - } - else if( ve.variant_idx == 1 ) { - emit_lvalue(e.dst); - m_of << "._0 = "; - emit_param(ve.vals[0]); - } - else { - } - break; + const auto* enm_p = 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( ve.variant_idx == 0 ) { + // TODO: Use nonzero_path + m_of << "memset(&"; emit_lvalue(e.dst); m_of << ", 0, sizeof("; emit_ctype(ty); m_of << "))"; + } + else if( ve.variant_idx == 1 ) { + emit_lvalue(e.dst); + m_of << "._0 = "; + emit_param(ve.vals[0]); + } + else { } + break; + } + else if( enm_p->is_value() ) + { + emit_lvalue(e.dst); + m_of << ".TAG = " << enm_p->get_value(ve.variant_idx); + assert(ve.vals.size() == 0); + } + else + { + emit_lvalue(e.dst); + m_of << ".TAG = " << ve.variant_idx; } - - emit_lvalue(e.dst); - m_of << ".TAG = " << ve.variant_idx; if(ve.vals.size() > 0) m_of << ";\n\t"; } @@ -1765,6 +1787,7 @@ namespace { const auto& ty = mir_res.get_lvalue_type(tmp, e.val); MIR_ASSERT(mir_res, ty.m_data.is_Path(), ""); MIR_ASSERT(mir_res, ty.m_data.as_Path().binding.is_Enum(), ""); + 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() ) { @@ -1774,6 +1797,16 @@ namespace { m_of << "\telse\n"; m_of << "\t\tgoto bb" << e.targets[0] << ";\n"; } + else if( enm->is_value() ) + { + m_of << "\tswitch("; emit_lvalue(e.val); m_of << ".TAG) {\n"; + for(unsigned int j = 0; j < e.targets.size(); j ++) + { + m_of << "\t\tcase " << enm->get_value(j) << ": goto bb" << e.targets[j] << ";\n"; + } + m_of << "\t\tdefault: abort();\n"; + m_of << "\t}\n"; + } else { m_of << "\tswitch("; emit_lvalue(e.val); m_of << ".TAG) {\n"; @@ -2659,10 +2692,10 @@ namespace { assign_from_literal([&](){ emit_dst(); m_of << "._0"; }, get_inner_type(e.idx, 0), e.vals[0]); } } - else if( enm.m_repr != ::HIR::Enum::Repr::Rust || ::std::all_of(enm.m_variants.begin(), enm.m_variants.end(), [](const auto& x){return x.second.is_Unit() || x.second.is_Value();}) ) + else if( enm.is_value() ) { MIR_ASSERT(*m_mir_res, e.vals.empty(), "Value-only enum with fields"); - emit_dst(); m_of << ".TAG = " << e.idx; + emit_dst(); m_of << ".TAG = " << enm.get_value(e.idx); } else { |