summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-05-01 09:50:58 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-05-01 09:50:58 +0800
commitbc62d7864a0820bb612d00db605ec65fc542cbad (patch)
treef85ca4c87e85bc20499f7674c97c522abab52f81
parenta67157ddbbe91e089ad4bee572fb364acd9b3e75 (diff)
downloadmrust-bc62d7864a0820bb612d00db605ec65fc542cbad.tar.gz
HIR - Rough support for enum variant values (trans only, no consteval)
-rw-r--r--src/hir/dump.cpp8
-rw-r--r--src/hir/hir.cpp24
-rw-r--r--src/hir/hir.hpp5
-rw-r--r--src/trans/codegen_c.cpp91
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
{