From 883cf34da3e273cd3878026d855b9579055c09c0 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 22 Dec 2018 18:31:15 +0800 Subject: Constant Evaluation - Evaluate missing associated constants with trait impl versions --- src/hir_conv/bind.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 227ccd9f..37a6e494 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -140,6 +140,9 @@ namespace { TU_MATCH(::HIR::Literal, (lit), (e), (Invalid, ), + (Defer, + // Shouldn't happen here, but ... + ), (List, for(auto& val : e) { visit_literal(sp, val); -- cgit v1.2.3 From c0267e165eca49583ac6ba7c3b48ba68ec4eee49 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 5 Jan 2019 10:52:48 +0800 Subject: HIR Bind - Handle cross-referencing default type params --- src/hir_conv/bind.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 37a6e494..9d15da18 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -317,6 +317,8 @@ namespace { return ; } + TRACE_FUNCTION_F(path); + if( params.m_types.size() == 0 && fill_infer ) { for(const auto& typ : param_defs.m_types) { (void)typ; @@ -337,9 +339,20 @@ namespace { auto ty = clone_ty_with(sp, typ.m_default, [&](const auto& ty, auto& out){ if(const auto* te = ty.m_data.opt_Generic() ) { - if( te->binding != GENERIC_Self || !self_ty ) + if( te->binding == GENERIC_Self ) { + if( !self_ty ) + TODO(sp, "Self enountered in default params, but no Self available - " << ty << " in " << typ.m_default << " for " << path); + out = self_ty->clone(); + } + // NOTE: Should only be seeing impl-level params here. Method-level ones are only seen in expression context. + else if( (te->binding >> 8) == 0 ) { + auto idx = te->binding & 0xFF; + ASSERT_BUG(sp, idx < params.m_types.size(), "TODO: Handle use of latter types in defaults"); + out = params.m_types[idx].clone(); + } + else { TODO(sp, "Monomorphise in fix_param_count - encountered " << ty << " in " << typ.m_default); - out = self_ty->clone(); + } return true; } return false; -- cgit v1.2.3 From e0181acd038e516f4dc61be4afb7906366c1fa80 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 20 Jan 2019 19:28:25 +0800 Subject: HIR Bind - Handle `Enum::Foo { .. }` patterns for everything --- src/hir_conv/bind.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 5 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 9d15da18..c979b2e6 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -266,6 +266,15 @@ namespace { this->visit_pattern_Value(sp, pat, e.start); this->visit_pattern_Value(sp, pat, e.end); ), + (StructValue, + const auto& str = get_struct_ptr(sp, m_crate, e.path); + TU_IFLET(::HIR::Struct::Data, str.m_data, Unit, _, + e.binding = &str; + ) + else { + ERROR(sp, E0000, "Struct value pattern on non-unit struct " << e.path); + } + ), (StructTuple, const auto& str = get_struct_ptr(sp, m_crate, e.path); TU_IFLET(::HIR::Struct::Data, str.m_data, Tuple, _, @@ -288,6 +297,17 @@ namespace { } e.binding = &str; ), + (EnumValue, + auto p = get_enum_ptr(sp, m_crate, e.path); + if( p.first->m_data.is_Data() ) + { + const auto& var = p.first->m_data.as_Data()[p.second]; + if( var.is_struct || var.type != ::HIR::TypeRef::new_unit() ) + ERROR(sp, E0000, "Enum value pattern on non-unit variant " << e.path); + } + e.binding_ptr = p.first; + e.binding_idx = p.second; + ), (EnumTuple, auto p = get_enum_ptr(sp, m_crate, e.path); if( !p.first->m_data.is_Data() ) @@ -300,11 +320,54 @@ namespace { ), (EnumStruct, auto p = get_enum_ptr(sp, m_crate, e.path); - if( !p.first->m_data.is_Data() ) - ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path); - const auto& var = p.first->m_data.as_Data()[p.second]; - if( !var.is_struct ) - ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path); + if( !e.is_exhaustive && e.sub_patterns.empty() ) + { + if( !p.first->m_data.is_Data() ) { + pat.m_data = ::HIR::Pattern::Data::make_EnumValue({ + ::std::move(e.path), p.first, p.second + }); + } + else { + const auto& var = p.first->m_data.as_Data()[p.second]; + if( var.type == ::HIR::TypeRef::new_unit() ) + { + pat.m_data = ::HIR::Pattern::Data::make_EnumValue({ + ::std::move(e.path), p.first, p.second + }); + } + else if( !var.is_struct ) + { + ASSERT_BUG(sp, var.type.m_data.is_Path(), ""); + ASSERT_BUG(sp, var.type.m_data.as_Path().binding.is_Struct(), ""); + const auto& str = *var.type.m_data.as_Path().binding.as_Struct(); + ASSERT_BUG(sp, str.m_data.is_Tuple(), ""); + const auto& flds = str.m_data.as_Tuple(); + ::std::vector subpats; + for(size_t i = 0; i < flds.size(); i ++) + subpats.push_back(::HIR::Pattern { }); + pat.m_data = ::HIR::Pattern::Data::make_EnumTuple({ + ::std::move(e.path), p.first, p.second, mv$(subpats) + }); + } + else + { + // Keep as a struct pattern + } + } + } + else + { + if( !p.first->m_data.is_Data() ) + { + ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path); + } + else + { + const auto& var = p.first->m_data.as_Data()[p.second]; + if( !var.is_struct ) + ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path); + } + } e.binding_ptr = p.first; e.binding_idx = p.second; ) -- cgit v1.2.3 From 4960edb7d948e43efc58a28ecd05fa9237c8d240 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 3 Feb 2019 13:42:13 +0800 Subject: HIR Expr - Have _StructLiteral take a HIR::Path (to allow associated types to be used) --- src/hir/expr.cpp | 2 +- src/hir/expr.hpp | 4 ++-- src/hir/from_ast.cpp | 12 ++++++++++- src/hir/from_ast_expr.cpp | 2 +- src/hir_conv/bind.cpp | 2 +- src/hir_conv/expand_type.cpp | 5 +++-- src/hir_expand/annotate_value_usage.cpp | 6 ++++-- src/hir_typeck/expr_check.cpp | 6 ++++-- src/hir_typeck/expr_cs.cpp | 15 ++++++++------ src/mir/from_hir.cpp | 35 +++++++++++++++++++-------------- 10 files changed, 56 insertions(+), 33 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index 6b7c2e1a..589e2811 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -158,7 +158,7 @@ DEF_VISIT(ExprNode_PathValue, node, ) DEF_VISIT(ExprNode_Variable, , ) DEF_VISIT(ExprNode_StructLiteral, node, - visit_generic_path(::HIR::Visitor::PathContext::VALUE, node.m_path); + visit_path(::HIR::Visitor::PathContext::VALUE, node.m_path); if( node.m_base_value ) visit_node_ptr(node.m_base_value); for(auto& val : node.m_values) diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 15c0a489..140ba817 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -694,7 +694,7 @@ struct ExprNode_StructLiteral: { typedef ::std::vector< ::std::pair< ::std::string, ExprNodeP > > t_values; - ::HIR::GenericPath m_path; + ::HIR::Path m_path; bool m_is_struct; ::HIR::ExprNodeP m_base_value; t_values m_values; @@ -702,7 +702,7 @@ struct ExprNode_StructLiteral: /// Monomorphised types of each field. ::std::vector< ::HIR::TypeRef> m_value_types; - ExprNode_StructLiteral(Span sp, ::HIR::GenericPath path, bool is_struct, ::HIR::ExprNodeP base_value, t_values values): + ExprNode_StructLiteral(Span sp, ::HIR::Path path, bool is_struct, ::HIR::ExprNodeP base_value, t_values values): ExprNode( mv$(sp) ), m_path( mv$(path) ), m_is_struct( is_struct ), diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 899d0b0c..768593c4 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -628,7 +628,17 @@ const ::AST::Crate* g_ast_crate_ptr; return ::HIR::Path( LowerHIR_GenericPath(sp, path) ); ), (UFCS, - if( e.nodes.size() != 1 ) + if( e.nodes.size() == 0 ) + { + if( !e.trait ) + TODO(sp, "Handle UFCS inherent and no nodes - " << path); + if( e.trait->is_valid() ) + TODO(sp, "Handle UFCS w/ trait and no nodes - " << path); + auto type = LowerHIR_Type(*e.type); + ASSERT_BUG(sp, type.m_data.is_Path(), "No nodes and non-Path type - " << path); + return mv$(type.m_data.as_Path().path); + } + if( e.nodes.size() > 1 ) TODO(sp, "Handle UFCS with multiple nodes - " << path); // - No associated type bounds allowed in UFCS paths auto params = LowerHIR_PathParams(sp, e.nodes.front().args(), false); diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 55c742ad..23797382 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -528,7 +528,7 @@ struct LowerHIR_ExprNode_Visitor: values.push_back( ::std::make_pair(val.name, LowerHIR_ExprNode_Inner(*val.value)) ); // TODO: What if `v.m_path` is an associated type (that's known to be a struct) m_rv.reset( new ::HIR::ExprNode_StructLiteral( v.span(), - LowerHIR_GenericPath(v.span(), v.m_path), + LowerHIR_Path(v.span(), v.m_path), ! v.m_path.m_bindings.type.is_EnumVar(), LowerHIR_ExprNode_Inner_Opt(v.m_base_value.get()), mv$(values) diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index c979b2e6..9b5043f4 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -645,7 +645,7 @@ namespace { void visit(::HIR::ExprNode_StructLiteral& node) override { - upper_visitor.visit_generic_path(node.m_path, ::HIR::Visitor::PathContext::TYPE); + upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::TYPE); ::HIR::ExprVisitorDef::visit(node); } void visit(::HIR::ExprNode_ArraySized& node) override diff --git a/src/hir_conv/expand_type.cpp b/src/hir_conv/expand_type.cpp index dcdf79bd..6b06a748 100644 --- a/src/hir_conv/expand_type.cpp +++ b/src/hir_conv/expand_type.cpp @@ -255,9 +255,10 @@ public: { if( node.m_is_struct ) { - auto new_path = upper_visitor.expand_alias_gp(node.span(), node.m_path); - if( new_path.m_path.m_components.size() != 0 ) + auto new_type = ConvertHIR_ExpandAliases_GetExpansion(upper_visitor.m_crate, node.m_path, /*in_expr=*/true); + if( new_type != ::HIR::TypeRef() ) { + auto new_path = mv$(new_type.m_data.as_Path().path); DEBUG("Replacing " << node.m_path << " with " << new_path); node.m_path = mv$(new_path); } diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp index 491ab4c7..1754bdac 100644 --- a/src/hir_expand/annotate_value_usage.cpp +++ b/src/hir_expand/annotate_value_usage.cpp @@ -356,13 +356,15 @@ namespace { void visit(::HIR::ExprNode_StructLiteral& node) override { const auto& sp = node.span(); + ASSERT_BUG(sp, node.m_path.m_data.is_Generic(), "Struct literal with non-Generic path - " << node.m_path); + auto& ty_path = node.m_path.m_data.as_Generic(); if( node.m_base_value ) { bool is_moved = false; const auto& tpb = node.m_base_value->m_res_type.m_data.as_Path().binding; const ::HIR::Struct* str; if( tpb.is_Enum() ) { const auto& enm = *tpb.as_Enum(); - auto idx = enm.find_variant(node.m_path.m_path.m_components.back()); + auto idx = enm.find_variant(ty_path.m_path.m_components.back()); ASSERT_BUG(sp, idx != SIZE_MAX, ""); const auto& var_ty = enm.m_data.as_Data()[idx].type; str = var_ty.m_data.as_Path().binding.as_Struct(); @@ -379,7 +381,7 @@ namespace { provided_mask[idx] = true; } - const auto monomorph_cb = monomorphise_type_get_cb(node.span(), nullptr, &node.m_path.m_params, nullptr); + const auto monomorph_cb = monomorphise_type_get_cb(node.span(), nullptr, &ty_path.m_params, nullptr); for( unsigned int i = 0; i < fields.size(); i ++ ) { if( ! provided_mask[i] ) { const auto& ty_o = fields[i].second.ent; diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index cd57c471..adb3c426 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -496,6 +496,8 @@ namespace { if( node.m_base_value) { check_types_equal( node.m_base_value->span(), node.m_res_type, node.m_base_value->m_res_type ); } + ASSERT_BUG(sp, node.m_path.m_data.is_Generic(), "_StructLiteral with non-Generic path - " << node.m_path); + auto& ty_path = node.m_path.m_data.as_Generic(); // - Create ivars in path, and set result type const auto& ty = node.m_res_type; @@ -506,7 +508,7 @@ namespace { (Unbound, ), (Opaque, ), (Enum, - const auto& var_name = node.m_path.m_path.m_components.back(); + const auto& var_name = ty_path.m_path.m_components.back(); const auto& enm = *e; auto idx = enm.find_variant(var_name); ASSERT_BUG(sp, idx != SIZE_MAX, ""); @@ -536,7 +538,7 @@ namespace { const ::HIR::t_struct_fields& fields = *fields_ptr; #if 1 - const auto& ty_params = node.m_path.m_params.m_types; + const auto& ty_params = ty_path.m_params.m_types; auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& { const auto& ge = gt.m_data.as_Generic(); if( ge.binding == 0xFFFF ) { diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 8b0eedb3..4a53bd4d 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1193,7 +1193,10 @@ namespace { { const auto& sp = node.span(); TRACE_FUNCTION_F(&node << " " << node.m_path << "{...} [" << (node.m_is_struct ? "struct" : "enum") << "]"); - this->add_ivars_generic_path(node.span(), node.m_path); + ASSERT_BUG(sp, node.m_path.m_data.is_Generic(), "Struct literal with non-Generic path - " << node.m_path); + auto& ty_path = node.m_path.m_data.as_Generic(); + + this->add_ivars_generic_path(node.span(), ty_path); for( auto& val : node.m_values ) { this->context.add_ivars( val.second->m_res_type ); } @@ -1202,7 +1205,7 @@ namespace { } // - Create ivars in path, and set result type - const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path); + const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, ty_path); this->context.equate_types(node.span(), node.m_res_type, ty); if( node.m_base_value ) { this->context.equate_types(node.span(), node.m_base_value->m_res_type, ty); @@ -1214,7 +1217,7 @@ namespace { (Unbound, ), (Opaque, ), (Enum, - const auto& var_name = node.m_path.m_path.m_components.back(); + const auto& var_name = ty_path.m_path.m_components.back(); const auto& enm = *e; auto idx = enm.find_variant(var_name); ASSERT_BUG(sp, idx != SIZE_MAX, ""); @@ -1257,7 +1260,7 @@ namespace { ASSERT_BUG(node.span(), fields_ptr, ""); const ::HIR::t_struct_fields& fields = *fields_ptr; - const auto& ty_params = node.m_path.m_params.m_types; + const auto& ty_params = ty_path.m_params.m_types; auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& { const auto& ge = gt.m_data.as_Generic(); if( ge.binding == 0xFFFF ) { @@ -1281,7 +1284,7 @@ namespace { { const auto& name = val.first; auto it = ::std::find_if(fields.begin(), fields.end(), [&](const auto& v)->bool{ return v.first == name; }); - ASSERT_BUG(node.span(), it != fields.end(), "Field '" << name << "' not found in struct " << node.m_path); + ASSERT_BUG(node.span(), it != fields.end(), "Field '" << name << "' not found in struct " << ty_path); const auto& des_ty_r = it->second.ent; auto& des_ty_cache = node.m_value_types[it - fields.begin()]; const auto* des_ty = &des_ty_r; @@ -3164,7 +3167,7 @@ namespace { this->check_type_resolved_genericpath(node.span(), node.m_path); } void visit(::HIR::ExprNode_StructLiteral& node) override { - this->check_type_resolved_pp(node.span(), node.m_path.m_params, ::HIR::TypeRef()); + this->check_type_resolved_path(node.span(), node.m_path); for(auto& ty : node.m_value_types) { if( ty != ::HIR::TypeRef() ) { this->check_type_resolved_top(node.span(), ty); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index ee4cf474..9ce40a74 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -2365,13 +2365,18 @@ namespace { { TRACE_FUNCTION_F("_StructLiteral"); - TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e), - (Unbound, ), - (Opaque, ), - (Enum, - auto enum_path = node.m_path.clone(); + ASSERT_BUG(node.span(), node.m_path.m_data.is_Generic(), "_StructLiteral with non-Generic path - " << node.m_path); + const auto& ty_path = node.m_path.m_data.as_Generic(); + + TU_MATCH_HDRA( (node.m_res_type.m_data.as_Path().binding), {) + TU_ARMA(Unbound, _e) { + } + TU_ARMA(Opaque, _e) { + } + TU_ARMA(Enum, e) { + auto enum_path = ty_path.clone(); enum_path.m_path.m_components.pop_back(); - const auto& var_name = node.m_path.m_path.m_components.back(); + const auto& var_name = ty_path.m_path.m_components.back(); const auto& enm = *e; size_t idx = enm.find_variant(var_name); @@ -2381,7 +2386,7 @@ namespace { const auto& str = *var_ty.m_data.as_Path().binding.as_Struct(); // Take advantage of the identical generics to cheaply clone/monomorph the path. - ::HIR::GenericPath struct_path = node.m_path.clone(); + ::HIR::GenericPath struct_path = ty_path.clone(); struct_path.m_path = var_ty.m_data.as_Path().path.m_data.as_Generic().m_path; this->visit_sl_inner(node, str, struct_path); @@ -2396,22 +2401,22 @@ namespace { static_cast(idx), mv$(v) }) ); - ), - (Union, + } + TU_ARMA(Union, e) { BUG(node.span(), "_StructLiteral Union isn't valid?"); - ), - (Struct, + } + TU_ARMA(Struct, e) { if(e->m_data.is_Unit()) { m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ - node.m_path.clone(), + ty_path.clone(), {} }) ); return ; } - this->visit_sl_inner(node, *e, node.m_path); - ) - ) + this->visit_sl_inner(node, *e, ty_path); + } + } } void visit(::HIR::ExprNode_UnionLiteral& node) override { -- cgit v1.2.3 From 42b9c8704fe4aab25e8f9d0cca15a74b025eee43 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 3 Feb 2019 17:48:32 +0800 Subject: HIR - Minimally-tested support for `extern { type }` --- src/hir/from_ast.cpp | 10 ++++++++ src/hir/hir.hpp | 8 +++++++ src/hir/serialise.cpp | 9 ++++++++ src/hir/type.cpp | 2 ++ src/hir/type.hpp | 2 ++ src/hir/visitor.cpp | 3 +++ src/hir_conv/bind.cpp | 4 ++++ src/hir_conv/constant_evaluation.cpp | 2 ++ src/hir_conv/markings.cpp | 1 + src/hir_typeck/expr_check.cpp | 9 ++++++++ src/hir_typeck/expr_cs.cpp | 18 +++++++++++++++ src/hir_typeck/helpers.cpp | 13 +++++++++++ src/hir_typeck/outer.cpp | 4 ++++ src/hir_typeck/static.cpp | 15 ++++++++++++ src/mir/from_hir.cpp | 3 +++ src/mir/from_hir_match.cpp | 15 ++++++++++++ src/resolve/absolute.cpp | 44 +++++++++++++++++------------------- src/resolve/index.cpp | 13 ++++++++++- src/resolve/use.cpp | 3 +++ src/trans/auto_impls.cpp | 6 ++--- src/trans/codegen.cpp | 3 +++ src/trans/codegen_c.cpp | 11 +++++++++ src/trans/enumerate.cpp | 16 ++++++------- 23 files changed, 178 insertions(+), 36 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 768593c4..fb8096f7 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -1187,6 +1187,7 @@ namespace { ::std::vector< ::HIR::TraitPath> trait_bounds; ::std::string lifetime_bound; auto gps = LowerHIR_GenericParams(i.params(), &is_sized); + for(auto& b : gps.m_bounds) { TU_MATCH(::HIR::GenericBound, (b), (be), @@ -1463,6 +1464,15 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H _add_mod_ns_item( mod, item.name, item.is_pub, ::HIR::TypeItem::make_Import({ ::HIR::SimplePath(e.name, {}), false, 0} ) ); ), (Type, + if( e.type().m_data.is_Any() ) + { + if( !e.params().lft_params().empty() || !e.params().ty_params().empty() || !e.params().bounds().empty() ) + { + ERROR(item.data.span, E0000, "Generics on extern type"); + } + _add_mod_ns_item(mod, item.name, item.is_pub, ::HIR::ExternType {}); + break; + } _add_mod_ns_item( mod, item.name, item.is_pub, ::HIR::TypeItem::make_TypeAlias( LowerHIR_TypeAlias(e) ) ); ), (Struct, diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index fc4a19e8..48787583 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -215,6 +215,13 @@ struct StructMarkings unsigned int coerce_param = ~0u; }; +class ExternType +{ +public: + // TODO: do extern types need any associated data? + TraitMarkings m_markings; +}; + class Enum { public: @@ -367,6 +374,7 @@ TAGGED_UNION(TypeItem, Import, (Import, struct { ::HIR::SimplePath path; bool is_variant; unsigned int idx; }), (Module, Module), (TypeAlias, TypeAlias), // NOTE: These don't introduce new values + (ExternType, ExternType), (Enum, Enum), (Struct, Struct), (Union, Union), diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index c91cf93f..e5fe8ed5 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -834,6 +834,10 @@ (Union, m_out.write_tag(6); serialise(e); + ), + (ExternType, + m_out.write_tag(7); + serialise(e); ) ) } @@ -1020,6 +1024,11 @@ serialise(item.m_markings); } + void serialise(const ::HIR::ExternType& item) + { + TRACE_FUNCTION_F("ExternType"); + serialise(item.m_markings); + } void serialise(const ::HIR::Trait& item) { TRACE_FUNCTION_F("_trait:"); diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 2c24e3e1..981ed0b3 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -85,6 +85,7 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be), (Unbound, os << "/*?*/";), (Opaque, os << "/*O*/";), + (ExternType, os << "/*X*/";), (Struct, os << "/*S*/";), (Union, os << "/*U*/";), (Enum, os << "/*E*/";) @@ -782,6 +783,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x TU_MATCH(::HIR::TypeRef::TypePathBinding, (*this), (e), (Unbound, return ::HIR::TypeRef::TypePathBinding::make_Unbound({}); ), (Opaque , return ::HIR::TypeRef::TypePathBinding::make_Opaque({}); ), + (ExternType, return ::HIR::TypeRef::TypePathBinding(e); ), (Struct, return ::HIR::TypeRef::TypePathBinding(e); ), (Union , return ::HIR::TypeRef::TypePathBinding(e); ), (Enum , return ::HIR::TypeRef::TypePathBinding(e); ) diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 480b32c4..0c98773f 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -19,6 +19,7 @@ namespace HIR { +class ExternType; class Struct; class Union; class Enum; @@ -152,6 +153,7 @@ public: TAGGED_UNION_EX(TypePathBinding, (), Unbound, ( (Unbound, struct {}), // Not yet bound, either during lowering OR during resolution (when associated and still being resolved) (Opaque, struct {}), // Opaque, i.e. An associated type of a generic (or Self in a trait) + (ExternType, const ::HIR::ExternType*), (Struct, const ::HIR::Struct*), (Union, const ::HIR::Union*), (Enum, const ::HIR::Enum*) diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index 5c9c0dfa..f23bae88 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -47,6 +47,9 @@ void ::HIR::Visitor::visit_module(::HIR::ItemPath p, ::HIR::Module& mod) DEBUG("type " << name); this->visit_type_alias(p + name, e); ), + (ExternType, + DEBUG("extern type " << name); + ), (Enum, DEBUG("enum " << name); this->visit_enum(p + name, e); diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 9b5043f4..b616a64f 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -456,6 +456,10 @@ namespace { (TypeAlias, BUG(sp, "TypeAlias encountered after `Resolve Type Aliases` - " << ty); ), + (ExternType, + e.binding = ::HIR::TypeRef::TypePathBinding::make_ExternType(&e3); + DEBUG("- " << ty); + ), (Struct, fix_param_count(sp, pe, e3.m_params, pe.m_params); e.binding = ::HIR::TypeRef::TypePathBinding::make_Struct(&e3); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 43a64bbb..3d1bf4a5 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -169,6 +169,8 @@ namespace { ), (Enum, ), + (ExternType, + ), (TypeAlias, ) ) diff --git a/src/hir_conv/markings.cpp b/src/hir_conv/markings.cpp index df7fbd36..d43db2b5 100644 --- a/src/hir_conv/markings.cpp +++ b/src/hir_conv/markings.cpp @@ -333,6 +333,7 @@ public: TU_MATCHA( (te.binding), (tpb), (Unbound, ), (Opaque, ), + (ExternType, markings_ptr = &tpb->m_markings; ), (Struct, markings_ptr = &tpb->m_markings; ), (Union , markings_ptr = &tpb->m_markings; ), (Enum , markings_ptr = &tpb->m_markings; ) diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index adb3c426..7d5a9c6f 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -462,6 +462,9 @@ namespace { (Union, BUG(sp, "Union in TupleVariant"); ), + (ExternType, + BUG(sp, "ExternType in TupleVariant"); + ), (Struct, ASSERT_BUG(sp, e->m_data.is_Tuple(), "Pointed struct in TupleVariant (" << node.m_path << ") isn't a Tuple"); fields_ptr = &e->m_data.as_Tuple(); @@ -522,6 +525,9 @@ namespace { (Union, TODO(sp, "Union in StructLiteral"); ), + (ExternType, + BUG(sp, "ExternType in StructLiteral"); + ), (Struct, if( e->m_data.is_Unit() ) { @@ -611,6 +617,9 @@ namespace { (Union, BUG(sp, "Union with _UnitVariant"); ), + (ExternType, + BUG(sp, "ExternType with _UnitVariant"); + ), (Struct, assert( e->m_data.is_Unit() ); ) diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 4a53bd4d..291dcd84 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1144,6 +1144,9 @@ namespace { ), (Union, BUG(sp, "TupleVariant pointing to a union"); + ), + (ExternType, + BUG(sp, "TupleVariant pointing to a extern type"); ) ) assert(fields_ptr); @@ -1216,6 +1219,7 @@ namespace { TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e), (Unbound, ), (Opaque, ), + (ExternType, ), // Error? (Enum, const auto& var_name = ty_path.m_path.m_components.back(); const auto& enm = *e; @@ -4900,6 +4904,10 @@ void Context::require_sized(const Span& sp, const ::HIR::TypeRef& ty_) // Already checked by type_is_sized params_def = nullptr; ), + (ExternType, + static ::HIR::GenericParams empty_params; + params_def = &empty_params; + ), (Enum, params_def = &pb->m_params; ), @@ -5551,6 +5559,13 @@ namespace { (Opaque, // Handled above in bounded ), + (ExternType, + // Must be equal + if( sbe == dbe ) + { + return CoerceResult::Equality; + } + ), (Enum, // Must be equal if( sbe == dbe ) @@ -6474,6 +6489,9 @@ namespace { // TODO: Check bounds? return false; ), + (ExternType, + return false; + ), (Struct, if(pbe_a != pbe_b) return false; if( !pbe_a->m_struct_markings.can_unsize ) diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 1af269ad..5c0696e3 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -2477,6 +2477,9 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, ), (Opaque, ), + (ExternType, + markings = &tpb->m_markings; + ), (Struct, markings = &tpb->m_markings; ), @@ -2710,6 +2713,9 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, ), (Union, TODO(sp, "Check auto trait destructure on union " << type); + ), + (ExternType, + TODO(sp, "Check auto trait destructure on extern type " << type); ) ) DEBUG("- Nothing failed, calling callback"); @@ -3141,6 +3147,10 @@ bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPa (Opaque, // TODO: Check bounds ), + (ExternType, + // Is it sized? No. + return ::HIR::Compare::Unequal; + ), (Enum, // HAS to be Sized ), @@ -4323,6 +4333,9 @@ bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const (Enum, // No fields on enums either ), + (ExternType, + // No fields on extern types + ), (Union, const auto& unm = *be; const auto& params = e.path.m_data.as_Generic().m_params; diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 63e92d8b..6a8e8b35 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -52,6 +52,10 @@ namespace { (TypeAlias, BUG(sp, "Type path pointed to type alias - " << path); ), + (ExternType, + static ::HIR::GenericParams empty_params; + return empty_params; + ), (Module, BUG(sp, "Type path pointed to module - " << path); ), diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 457bd44e..ce7faf6c 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -851,6 +851,9 @@ bool StaticTraitResolve::find_impl__check_crate( ), (Union, TODO(sp, "Check auto trait destructure on union " << type); + ), + (ExternType, + TODO(sp, "Check auto trait destructure on extern type " << type); ) ) DEBUG("- Nothing failed, calling callback"); @@ -1629,6 +1632,10 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) return false; } ), + (ExternType, + // Extern types aren't Sized + return false; + ), (Enum, ), (Union, @@ -1732,6 +1739,10 @@ bool StaticTraitResolve::type_is_impossible(const Span& sp, const ::HIR::TypeRef (Union, // TODO: Check all variants? Or just one? TODO(sp, "type_is_impossible for union " << ty); + ), + (ExternType, + // Extern types are possible, just not usable + return false; ) ) return true; @@ -2032,6 +2043,10 @@ bool StaticTraitResolve::type_needs_drop_glue(const Span& sp, const ::HIR::TypeR (Union, // Unions don't have drop glue unless they impl Drop return false; + ), + (ExternType, + // Extern types don't have drop glue + return false; ) ) ), diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 9ce40a74..fb214dda 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -2405,6 +2405,9 @@ namespace { TU_ARMA(Union, e) { BUG(node.span(), "_StructLiteral Union isn't valid?"); } + TU_ARMA(ExternType, e) { + BUG(node.span(), "_StructLiteral ExternType isn't valid?"); + } TU_ARMA(Struct, e) { if(e->m_data.is_Unit()) { m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 264c74c5..6fb77a3b 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -802,6 +802,9 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal ) ) ), + (ExternType, + TODO(sp, "Match extern type"); + ), (Union, TODO(sp, "Match union"); ), @@ -1217,6 +1220,9 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa (Union, TODO(sp, "Match over union - " << ty); ), + (ExternType, + TODO(sp, "Match over extern type - " << ty); + ), (Enum, auto monomorph = [&](const auto& ty) { auto rv = monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty); @@ -1738,6 +1744,9 @@ namespace { (Opaque, BUG(sp, "Destructuring an opaque type - " << *cur_ty); ), + (ExternType, + BUG(sp, "Destructuring an extern type - " << *cur_ty); + ), (Struct, // TODO: Should this do a call to expand_associated_types? auto monomorph = [&](const auto& ty) { @@ -2173,6 +2182,9 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& (Union, TODO(sp, "Match over Union"); ), + (ExternType, + TODO(sp, "Match over ExternType"); + ), (Enum, auto monomorph = [&](const auto& ty) { auto rv = monomorphise_type(sp, pbe->m_params, te.path.m_data.as_Generic().m_params, ty); @@ -2827,6 +2839,9 @@ void MatchGenGrouped::gen_dispatch(const ::std::vector& rules, s (Union, TODO(sp, "Match over Union"); ), + (ExternType, + TODO(sp, "Match over ExternType - " << ty); + ), (Enum, ) ) diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index d2609e9e..75a0857f 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -350,7 +350,7 @@ namespace auto v = mod.m_value_items.find(name); if( v != mod.m_value_items.end() ) { const auto& b = v->second.path.m_bindings.value; - if( const auto* be = b.opt_EnumVar() ) { + if( /*const auto* be =*/ b.opt_EnumVar() ) { DEBUG("- TY: Enum variant " << v->second.path); path = ::AST::Path( v->second.path ); return true; @@ -832,6 +832,9 @@ namespace { (TypeAlias, pb.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); ), + (ExternType, + pb.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); + ), (Struct, pb.type = ::AST::PathBinding_Type::make_Struct({nullptr, &e}); ), @@ -880,8 +883,8 @@ namespace { if( it == hmod->m_mod_items.end() ) ERROR(sp, E0000, "Couldn't find path component '" << n.name() << "' of " << path); - TU_MATCH(::HIR::TypeItem, (it->second->ent), (e), - (Import, + TU_MATCH_HDRA( (it->second->ent), {) + TU_ARMA(Import, e) { // - Update path then restart auto newpath = AST::Path(e.path.m_crate_name, {}); for(const auto& n : e.path.m_components) @@ -892,11 +895,11 @@ namespace { // TODO: Recursion limit Resolve_Absolute_Path_BindAbsolute(context, sp, mode, path); return ; - ), - (Module, + } + TU_ARMA(Module, e) { hmod = &e; - ), - (Trait, + } + TU_ARMA(Trait, e) { auto trait_path = ::AST::Path( crate.m_name, {} ); for(unsigned int j = start; j <= i; j ++) trait_path.nodes().push_back( path_abs.nodes[j].name() ); @@ -940,23 +943,15 @@ namespace { path = mv$(new_path); return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (TypeAlias, - path = split_into_crate(sp, mv$(path), start, crate.m_name); - path = split_into_ufcs_ty(sp, mv$(path), i-start); - return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (Struct, - path = split_into_crate(sp, mv$(path), start, crate.m_name); - path = split_into_ufcs_ty(sp, mv$(path), i-start); - return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (Union, + } + case ::HIR::TypeItem::TAG_ExternType: + case ::HIR::TypeItem::TAG_TypeAlias: + case ::HIR::TypeItem::TAG_Struct: + case ::HIR::TypeItem::TAG_Union: path = split_into_crate(sp, mv$(path), start, crate.m_name); path = split_into_ufcs_ty(sp, mv$(path), i-start); return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (Enum, + TU_ARMA(Enum, e) { const auto& last_node = path_abs.nodes.back(); // If this refers to an enum variant, return the full path auto idx = e.find_variant(last_node.name()); @@ -982,8 +977,8 @@ namespace { path = split_into_crate(sp, mv$(path), start, crate.m_name); path = split_into_ufcs_ty(sp, mv$(path), i-start); return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ) - ) + } + } } const auto& name = path_abs.nodes.back().name(); @@ -1007,6 +1002,9 @@ namespace { (Module, path.m_bindings.type = ::AST::PathBinding_Type::make_Module({nullptr, &e}); ), + (ExternType, + path.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); + ), (TypeAlias, path.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); ), diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp index ec1fcd8d..ddeffa0c 100644 --- a/src/resolve/index.cpp +++ b/src/resolve/index.cpp @@ -241,7 +241,15 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod) i.is_pub, i_data.name, mv$(path), e.mac }); } - // TODO: Other imports (e.g. derives, which have different naming structures) + TU_ARMA(ProcMacro, e) { + TODO(sp, "ProcMacro import"); + } + TU_ARMA(ProcMacroAttribute, e) { + TODO(sp, "ProcMacroAttribute import"); + } + TU_ARMA(ProcMacroDerive, e) { + TODO(sp, "ProcMacroDerive import"); + } }} } else @@ -318,6 +326,9 @@ void Resolve_Index_Module_Wildcard__glob_in_hir_mod(const Span& sp, const AST::C p.m_bindings.type = ::AST::PathBinding_Type::make_Enum({nullptr}); ), (TypeAlias, + p.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); + ), + (ExternType, p.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); ) ) diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp index 8c9266a2..95e6d2c1 100644 --- a/src/resolve/use.cpp +++ b/src/resolve/use.cpp @@ -645,6 +645,9 @@ namespace { (TypeAlias, rv.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); ), + (ExternType, + rv.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); // Lazy. + ), (Enum, rv.type = ::AST::PathBinding_Type::make_Enum({nullptr, &e}); ), diff --git a/src/trans/auto_impls.cpp b/src/trans/auto_impls.cpp index 418a338b..877659b2 100644 --- a/src/trans/auto_impls.cpp +++ b/src/trans/auto_impls.cpp @@ -74,7 +74,7 @@ void Trans_AutoImpl_Clone(State& state, ::HIR::TypeRef ty) // For each field of the tuple, create a clone (either using Copy if posible, or calling Clone::clone) for(const auto& subty : te) { - auto fld_lvalue = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Argument({ 0 })) })), values.size() }); + auto fld_lvalue = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Argument({ 0 })) })), static_cast(values.size()) }); if( state.resolve.type_is_copy(sp, subty) ) { values.push_back( ::std::move(fld_lvalue) ); @@ -94,8 +94,8 @@ void Trans_AutoImpl_Clone(State& state, ::HIR::TypeRef ty) ::MIR::RValue::make_Borrow({ 0, ::HIR::BorrowType::Shared, mv$(fld_lvalue) }) })); bb.terminator = ::MIR::Terminator::make_Call({ - mir_fcn.blocks.size() + 2, // return block (after the panic block below) - mir_fcn.blocks.size() + 1, // panic block (next block) + static_cast(mir_fcn.blocks.size() + 2), // return block (after the panic block below) + static_cast(mir_fcn.blocks.size() + 1), // panic block (next block) res_lv.clone(), ::MIR::CallTarget( ::HIR::Path(subty.clone(), lang_Clone, "clone") ), ::make_vec1<::MIR::Param>( ::std::move(borrow_lv) ) diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp index 9e93caba..b2b614a9 100644 --- a/src/trans/codegen.cpp +++ b/src/trans/codegen.cpp @@ -43,6 +43,9 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const TU_MATCHA( (te.binding), (tpb), (Unbound, throw ""; ), (Opaque, throw ""; ), + (ExternType, + //codegen->emit_extern_type(sp, te.path.m_data.as_Generic(), *tpb); + ), (Struct, codegen->emit_struct(sp, te.path.m_data.as_Generic(), *tpb); ), diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 2c40c991..979da88d 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1013,6 +1013,9 @@ namespace { (Struct, m_of << "struct s_" << Trans_Mangle(te.path) << ";\n"; ), + (ExternType, + m_of << "struct x_" << Trans_Mangle(te.path) << ";\n"; + ), (Union, m_of << "union u_" << Trans_Mangle(te.path) << ";\n"; ), @@ -1837,6 +1840,7 @@ namespace { TU_MATCHA((te.binding), (pbe), (Unbound, MIR_BUG(*m_mir_res, "Unbound type path " << ty); ), (Opaque, MIR_BUG(*m_mir_res, "Opaque type path " << ty); ), + (ExternType, MIR_BUG(*m_mir_res, "Extern type literal " << ty); ), (Struct, TU_MATCHA( (pbe->m_data), (se), (Unit, @@ -5351,6 +5355,9 @@ namespace { TU_MATCHA((te.binding), (pbe), (Unbound, MIR_BUG(*m_mir_res, "Unbound type path " << ty); ), (Opaque, MIR_BUG(*m_mir_res, "Opaque type path " << ty); ), + (ExternType, + MIR_BUG(*m_mir_res, "Extern type literal"); + ), (Struct, TU_MATCHA( (pbe->m_data), (se), (Unit, @@ -5835,6 +5842,10 @@ namespace { (Enum, m_of << "struct e_" << Trans_Mangle(te.path); ), + (ExternType, + m_of << "struct x_" << Trans_Mangle(te.path); + //return ; + ), (Unbound, MIR_BUG(*m_mir_res, "Unbound type path in trans - " << ty); ), diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 6aeb3485..c326d125 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -570,6 +570,9 @@ namespace { (Opaque, BUG(Span(), "Opaque type hit in enumeration - " << ty); ), + (ExternType, + // No innards to visit + ), (Struct, visit_struct(te.path.m_data.as_Generic(), *tpb); ), @@ -1064,15 +1067,10 @@ void Trans_Enumerate_Types(EnumState& state) TU_MATCHA( (te.binding), (tpb), (Unbound, ), (Opaque, ), - (Struct, - markings_ptr = &tpb->m_markings; - ), - (Union, - markings_ptr = &tpb->m_markings; - ), - (Enum, - markings_ptr = &tpb->m_markings; - ) + (ExternType, markings_ptr = &tpb->m_markings; ), + (Struct, markings_ptr = &tpb->m_markings; ), + (Union, markings_ptr = &tpb->m_markings; ), + (Enum, markings_ptr = &tpb->m_markings; ) ) ASSERT_BUG(Span(), markings_ptr, "Path binding not set correctly - " << ty); -- cgit v1.2.3 From 413fcf4f318e1530dcbdd8abb879bf77b714a91c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 4 Mar 2019 13:54:42 +0800 Subject: HIR Conv Bind - Minor tweak to ordering --- src/hir_conv/bind.cpp | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index b616a64f..c26ae03f 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -256,17 +256,17 @@ namespace { ::HIR::Visitor::visit_pattern(pat); - TU_MATCH_DEF(::HIR::Pattern::Data, (pat.m_data), (e), - ( - ), - (Value, + TU_MATCH_HDRA( (pat.m_data), {) + default: + // Nothing + TU_ARMA(Value, e) { this->visit_pattern_Value(sp, pat, e.val); - ), - (Range, + } + TU_ARMA(Range, e) { this->visit_pattern_Value(sp, pat, e.start); this->visit_pattern_Value(sp, pat, e.end); - ), - (StructValue, + } + TU_ARMA(StructValue, e) { const auto& str = get_struct_ptr(sp, m_crate, e.path); TU_IFLET(::HIR::Struct::Data, str.m_data, Unit, _, e.binding = &str; @@ -274,8 +274,8 @@ namespace { else { ERROR(sp, E0000, "Struct value pattern on non-unit struct " << e.path); } - ), - (StructTuple, + } + TU_ARMA(StructTuple, e) { const auto& str = get_struct_ptr(sp, m_crate, e.path); TU_IFLET(::HIR::Struct::Data, str.m_data, Tuple, _, e.binding = &str; @@ -283,8 +283,8 @@ namespace { else { ERROR(sp, E0000, "Struct tuple pattern on non-tuple struct " << e.path); } - ), - (Struct, + } + TU_ARMA(Struct, e) { const auto& str = get_struct_ptr(sp, m_crate, e.path); if(str.m_data.is_Named() ) { } @@ -296,8 +296,8 @@ namespace { ERROR(sp, E0000, "Struct pattern `" << pat << "` on field-less struct " << e.path); } e.binding = &str; - ), - (EnumValue, + } + TU_ARMA(EnumValue, e) { auto p = get_enum_ptr(sp, m_crate, e.path); if( p.first->m_data.is_Data() ) { @@ -307,8 +307,8 @@ namespace { } e.binding_ptr = p.first; e.binding_idx = p.second; - ), - (EnumTuple, + } + TU_ARMA(EnumTuple, e) { auto p = get_enum_ptr(sp, m_crate, e.path); if( !p.first->m_data.is_Data() ) ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); @@ -317,8 +317,8 @@ namespace { ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); e.binding_ptr = p.first; e.binding_idx = p.second; - ), - (EnumStruct, + } + TU_ARMA(EnumStruct, e) { auto p = get_enum_ptr(sp, m_crate, e.path); if( !e.is_exhaustive && e.sub_patterns.empty() ) { @@ -338,7 +338,7 @@ namespace { else if( !var.is_struct ) { ASSERT_BUG(sp, var.type.m_data.is_Path(), ""); - ASSERT_BUG(sp, var.type.m_data.as_Path().binding.is_Struct(), ""); + ASSERT_BUG(sp, var.type.m_data.as_Path().binding.is_Struct(), "EnumStruct pattern on unexpected variant " << e.path << " with " << var.type.m_data.as_Path().binding.tag_str()); const auto& str = *var.type.m_data.as_Path().binding.as_Struct(); ASSERT_BUG(sp, str.m_data.is_Tuple(), ""); const auto& flds = str.m_data.as_Tuple(); @@ -370,8 +370,8 @@ namespace { } e.binding_ptr = p.first; e.binding_idx = p.second; - ) - ) + } + } } static void fix_param_count(const Span& sp, const ::HIR::GenericPath& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params, bool fill_infer=true, const ::HIR::TypeRef* self_ty=nullptr) { @@ -862,11 +862,12 @@ namespace { void ConvertHIR_Bind(::HIR::Crate& crate) { Visitor exp { crate }; - exp.visit_crate( crate ); // Also visit extern crates to update their pointers for(auto& ec : crate.m_ext_crates) { exp.visit_crate( *ec.second.m_data ); } + + exp.visit_crate( crate ); } -- cgit v1.2.3 From 7a1a685ef5e0d831f6762f1bc9171de66d933e32 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 25 Apr 2019 12:38:17 +0800 Subject: HIR - Add more complete privacy handling (allowing for autoderef to skip private fields) --- src/hir/deserialise.cpp | 10 +++-- src/hir/dump.cpp | 4 +- src/hir/expr_ptr.cpp | 6 +++ src/hir/expr_state.hpp | 3 +- src/hir/from_ast.cpp | 78 +++++++++++++++++++++++------------- src/hir/hir.hpp | 64 ++++++++++++++++++++++++++++- src/hir/hir_ops.cpp | 1 + src/hir/serialise.cpp | 6 +-- src/hir_conv/bind.cpp | 28 +++++++++---- src/hir_conv/constant_evaluation.cpp | 3 +- src/hir_expand/closures.cpp | 8 ++-- src/hir_expand/vtable.cpp | 10 ++--- src/hir_typeck/expr_cs.cpp | 7 ++-- src/hir_typeck/expr_visit.cpp | 8 ++-- src/hir_typeck/expr_visit.hpp | 6 ++- src/hir_typeck/helpers.cpp | 10 ++--- src/hir_typeck/helpers.hpp | 4 +- src/resolve/index.cpp | 4 +- src/trans/enumerate.cpp | 4 +- 19 files changed, 189 insertions(+), 75 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index cc376474..9933255f 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -101,10 +101,14 @@ rv.push_back( cb() ); return rv; } + ::HIR::Publicity deserialise_pub() + { + return (m_in.read_bool() ? ::HIR::Publicity::new_global() : ::HIR::Publicity::new_none()); + } template ::HIR::VisEnt deserialise_visent() { - return ::HIR::VisEnt { m_in.read_bool(), D::des(*this) }; + return ::HIR::VisEnt { deserialise_pub(), D::des(*this) }; } template @@ -153,7 +157,7 @@ { auto name = m_in.read_string(); rv.m_methods.insert( ::std::make_pair( mv$(name), ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { - m_in.read_bool(), m_in.read_bool(), deserialise_function() + deserialise_pub(), m_in.read_bool(), deserialise_function() } ) ); } size_t const_count = m_in.read_count(); @@ -161,7 +165,7 @@ { auto name = m_in.read_string(); rv.m_constants.insert( ::std::make_pair( mv$(name), ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> { - m_in.read_bool(), m_in.read_bool(), deserialise_constant() + deserialise_pub(), m_in.read_bool(), deserialise_constant() } ) ); } // m_src_module doesn't matter after typeck diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp index a60ec643..3b981e26 100644 --- a/src/hir/dump.cpp +++ b/src/hir/dump.cpp @@ -152,7 +152,7 @@ namespace { m_os << "("; for(const auto& fld : flds) { - m_os << (fld.is_public ? "pub " : "") << fld.ent << ", "; + m_os << fld.publicity << " " << fld.ent << ", "; } if( item.m_params.m_bounds.empty() ) { @@ -175,7 +175,7 @@ namespace { inc_indent(); for(const auto& fld : flds) { - m_os << indent() << (fld.second.is_public ? "pub " : "") << fld.first << ": " << fld.second.ent << ",\n"; + m_os << indent() << fld.second.publicity << " " << fld.first << ": " << fld.second.ent << ",\n"; } dec_indent(); m_os << indent() << "}\n"; diff --git a/src/hir/expr_ptr.cpp b/src/hir/expr_ptr.cpp index 7b3a6811..0c219e0f 100644 --- a/src/hir/expr_ptr.cpp +++ b/src/hir/expr_ptr.cpp @@ -90,6 +90,12 @@ void HIR::ExprPtr::set_mir(::MIR::FunctionPointer mir) { assert( !this->m_mir ); m_mir = ::std::move(mir); + // Reset the HIR tree to be a placeholder node (thus freeing the backing memory) + //if( node ) + //{ + // auto sp = node->span(); + // node = ExprPtrInner(::std::unique_ptr(new ::HIR::ExprNode_Tuple(sp, {}))); + //} } diff --git a/src/hir/expr_state.hpp b/src/hir/expr_state.hpp index 5491b4d3..11fffe67 100644 --- a/src/hir/expr_state.hpp +++ b/src/hir/expr_state.hpp @@ -10,8 +10,9 @@ namespace HIR { -struct ExprState +class ExprState { +public: ::HIR::SimplePath m_mod_path; const ::HIR::Module& m_module; diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 014b744c..af6bc9cb 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -868,9 +868,20 @@ const ::AST::Crate* g_ast_crate_ptr; namespace { template - ::HIR::VisEnt new_visent(bool pub, T v) { + ::HIR::VisEnt new_visent(HIR::Publicity pub, T v) { return ::HIR::VisEnt { pub, mv$(v) }; } + + ::HIR::SimplePath get_parent_module(const ::HIR::ItemPath& p) { + const ::HIR::ItemPath* parent_ip = p.parent; + assert(parent_ip); + while(parent_ip->name && parent_ip->name[0] == '#') + { + parent_ip = parent_ip->parent; + assert(parent_ip); + } + return parent_ip->get_simple_path(); + } } ::HIR::Struct LowerHIR_Struct(::HIR::ItemPath path, const ::AST::Struct& ent, const ::AST::AttributeList& attrs) @@ -878,6 +889,9 @@ namespace { TRACE_FUNCTION_F(path); ::HIR::Struct::Data data; + auto priv_path = ::HIR::Publicity::new_priv( get_parent_module(path) ); + auto get_pub = [&](bool is_pub){ return is_pub ? ::HIR::Publicity::new_global() : priv_path; }; + TU_MATCH(::AST::StructData, (ent.m_data), (e), (Unit, data = ::HIR::Struct::Data::make_Unit({}); @@ -886,14 +900,14 @@ namespace { ::HIR::Struct::Data::Data_Tuple fields; for(const auto& field : e.ents) - fields.push_back( { field.m_is_public, LowerHIR_Type(field.m_type) } ); + fields.push_back( { get_pub(field.m_is_public), LowerHIR_Type(field.m_type) } ); data = ::HIR::Struct::Data::make_Tuple( mv$(fields) ); ), (Struct, ::HIR::Struct::Data::Data_Named fields; for(const auto& field : e.ents) - fields.push_back( ::std::make_pair( field.m_name, new_visent(field.m_is_public, LowerHIR_Type(field.m_type)) ) ); + fields.push_back( ::std::make_pair( field.m_name, new_visent( get_pub(field.m_is_public), LowerHIR_Type(field.m_type)) ) ); data = ::HIR::Struct::Data::make_Named( mv$(fields) ); ) ) @@ -956,7 +970,6 @@ namespace { ::HIR::Enum LowerHIR_Enum(::HIR::ItemPath path, const ::AST::Enum& ent, const ::AST::AttributeList& attrs, ::std::function push_struct) { - // 1. Figure out what sort of enum this is (value or data) bool has_value = false; bool has_data = false; @@ -1053,14 +1066,14 @@ namespace { { ::HIR::Struct::Data::Data_Tuple fields; for(const auto& field : ve->m_sub_types) - fields.push_back( new_visent(true, LowerHIR_Type(field)) ); + fields.push_back( new_visent(::HIR::Publicity::new_global(), LowerHIR_Type(field)) ); data = ::HIR::Struct::Data::make_Tuple( mv$(fields) ); } else if( const auto* ve = var.m_data.opt_Struct() ) { ::HIR::Struct::Data::Data_Named fields; for(const auto& field : ve->m_fields) - fields.push_back( ::std::make_pair( field.m_name, new_visent(true, LowerHIR_Type(field.m_type)) ) ); + fields.push_back( ::std::make_pair( field.m_name, new_visent(::HIR::Publicity::new_global(), LowerHIR_Type(field.m_type)) ) ); data = ::HIR::Struct::Data::make_Named( mv$(fields) ); } else @@ -1106,6 +1119,9 @@ namespace { } ::HIR::Union LowerHIR_Union(::HIR::ItemPath path, const ::AST::Union& f, const ::AST::AttributeList& attrs) { + auto priv_path = ::HIR::Publicity::new_priv( get_parent_module(path) ); + auto get_pub = [&](bool is_pub){ return is_pub ? ::HIR::Publicity::new_global() : priv_path; }; + auto repr = ::HIR::Union::Repr::Rust; if( const auto* attr_repr = attrs.get("repr") ) @@ -1124,7 +1140,7 @@ namespace { ::HIR::Struct::Data::Data_Named variants; for(const auto& field : f.m_variants) - variants.push_back( ::std::make_pair( field.m_name, new_visent(field.m_is_public, LowerHIR_Type(field.m_type)) ) ); + variants.push_back( ::std::make_pair( field.m_name, new_visent(get_pub(field.m_is_public), LowerHIR_Type(field.m_type)) ) ); return ::HIR::Union { LowerHIR_GenericParams(f.m_params, nullptr), @@ -1369,10 +1385,10 @@ namespace { }; } -void _add_mod_ns_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::HIR::TypeItem ti) { +void _add_mod_ns_item(::HIR::Module& mod, ::std::string name, ::HIR::Publicity is_pub, ::HIR::TypeItem ti) { mod.m_mod_items.insert( ::std::make_pair( mv$(name), ::make_unique_ptr(::HIR::VisEnt< ::HIR::TypeItem> { is_pub, mv$(ti) }) ) ); } -void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::HIR::ValueItem ti) { +void _add_mod_val_item(::HIR::Module& mod, ::std::string name, ::HIR::Publicity is_pub, ::HIR::ValueItem ti) { mod.m_value_items.insert( ::std::make_pair( mv$(name), ::make_unique_ptr(::HIR::VisEnt< ::HIR::ValueItem> { is_pub, mv$(ti) }) ) ); } @@ -1383,6 +1399,9 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H mod.m_traits = mv$(traits); + auto priv_path = ::HIR::Publicity::new_priv( path.get_simple_path() ); + auto get_pub = [&](bool is_pub)->::HIR::Publicity{ return (is_pub ? ::HIR::Publicity::new_global() : priv_path); }; + // Populate trait list for(const auto& item : ast_mod.m_type_items) { @@ -1402,7 +1421,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H ::std::string name = FMT("#" << i); auto item_path = ::HIR::ItemPath(path, name.c_str()); auto ti = ::HIR::TypeItem::make_Module( LowerHIR_Module(submod, item_path, mod.m_traits) ); - _add_mod_ns_item( mod, mv$(name), false, mv$(ti) ); + _add_mod_ns_item( mod, mv$(name), get_pub(false), mv$(ti) ); } } @@ -1456,12 +1475,12 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H // Ignore - The index is used to add `Import`s ), (Module, - _add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Module(e, mv$(item_path)) ); + _add_mod_ns_item( mod, item.name, get_pub(item.is_pub), LowerHIR_Module(e, mv$(item_path)) ); ), (Crate, // All 'extern crate' items should be normalised into a list in the crate root // - If public, add a namespace import here referring to the root of the imported crate - _add_mod_ns_item( mod, item.name, item.is_pub, ::HIR::TypeItem::make_Import({ ::HIR::SimplePath(e.name, {}), false, 0} ) ); + _add_mod_ns_item( mod, item.name, get_pub(item.is_pub), ::HIR::TypeItem::make_Import({ ::HIR::SimplePath(e.name, {}), false, 0} ) ); ), (Type, if( e.type().m_data.is_Any() ) @@ -1470,39 +1489,39 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H { ERROR(item.data.span, E0000, "Generics on extern type"); } - _add_mod_ns_item(mod, item.name, item.is_pub, ::HIR::ExternType {}); + _add_mod_ns_item(mod, item.name, get_pub(item.is_pub), ::HIR::ExternType {}); break; } - _add_mod_ns_item( mod, item.name, item.is_pub, ::HIR::TypeItem::make_TypeAlias( LowerHIR_TypeAlias(e) ) ); + _add_mod_ns_item( mod, item.name, get_pub(item.is_pub), ::HIR::TypeItem::make_TypeAlias( LowerHIR_TypeAlias(e) ) ); ), (Struct, /// Add value reference if( e.m_data.is_Unit() ) { - _add_mod_val_item( mod, item.name, item.is_pub, ::HIR::ValueItem::make_StructConstant({item_path.get_simple_path()}) ); + _add_mod_val_item( mod, item.name, get_pub(item.is_pub), ::HIR::ValueItem::make_StructConstant({item_path.get_simple_path()}) ); } else if( e.m_data.is_Tuple() ) { - _add_mod_val_item( mod, item.name, item.is_pub, ::HIR::ValueItem::make_StructConstructor({item_path.get_simple_path()}) ); + _add_mod_val_item( mod, item.name, get_pub(item.is_pub), ::HIR::ValueItem::make_StructConstructor({item_path.get_simple_path()}) ); } else { } - _add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Struct(item_path, e, item.data.attrs) ); + _add_mod_ns_item( mod, item.name, get_pub(item.is_pub), LowerHIR_Struct(item_path, e, item.data.attrs) ); ), (Enum, - auto enm = LowerHIR_Enum(item_path, e, item.data.attrs, [&](auto name, auto str){ _add_mod_ns_item(mod, name, item.is_pub, mv$(str)); }); - _add_mod_ns_item( mod, item.name, item.is_pub, mv$(enm) ); + auto enm = LowerHIR_Enum(item_path, e, item.data.attrs, [&](auto name, auto str){ _add_mod_ns_item(mod, name, get_pub(item.is_pub), mv$(str)); }); + _add_mod_ns_item( mod, item.name, get_pub(item.is_pub), mv$(enm) ); ), (Union, - _add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Union(item_path, e, item.data.attrs) ); + _add_mod_ns_item( mod, item.name, get_pub(item.is_pub), LowerHIR_Union(item_path, e, item.data.attrs) ); ), (Trait, - _add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Trait(item_path.get_simple_path(), e) ); + _add_mod_ns_item( mod, item.name, get_pub(item.is_pub), LowerHIR_Trait(item_path.get_simple_path(), e) ); ), (Function, - _add_mod_val_item(mod, item.name, item.is_pub, LowerHIR_Function(item_path, item.data.attrs, e, ::HIR::TypeRef{})); + _add_mod_val_item(mod, item.name, get_pub(item.is_pub), LowerHIR_Function(item_path, item.data.attrs, e, ::HIR::TypeRef{})); ), (Static, if( e.s_class() == ::AST::Static::CONST ) - _add_mod_val_item(mod, item.name, item.is_pub, ::HIR::ValueItem::make_Constant(::HIR::Constant { + _add_mod_val_item(mod, item.name, get_pub(item.is_pub), ::HIR::ValueItem::make_Constant(::HIR::Constant { ::HIR::GenericParams {}, LowerHIR_Type( e.type() ), LowerHIR_Expr( e.value() ) @@ -1516,7 +1535,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H linkage.name = item.name; } - _add_mod_val_item(mod, item.name, item.is_pub, ::HIR::ValueItem::make_Static(::HIR::Static { + _add_mod_val_item(mod, item.name, get_pub(item.is_pub), ::HIR::ValueItem::make_Static(::HIR::Static { mv$(linkage), (e.s_class() == ::AST::Static::MUT), LowerHIR_Type( e.type() ), @@ -1542,7 +1561,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H DEBUG("Import NS " << ie.first << " = " << hir_path); ti = ::HIR::TypeItem::make_Import({ mv$(hir_path), false, 0 }); } - _add_mod_ns_item(mod, ie.first, ie.second.is_pub, mv$(ti)); + _add_mod_ns_item(mod, ie.first, get_pub(ie.second.is_pub), mv$(ti)); } } for( const auto& ie : ast_mod.m_value_items ) @@ -1561,7 +1580,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H vi = ::HIR::ValueItem::make_Import({ mv$(hir_path), true, pb.idx }); } } - _add_mod_val_item(mod, ie.first, ie.second.is_pub, mv$(vi)); + _add_mod_val_item(mod, ie.first, get_pub(ie.second.is_pub), mv$(vi)); } } @@ -1687,6 +1706,9 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat auto type = LowerHIR_Type(impl.def().type()); ::HIR::ItemPath path(type); + auto priv_path = ::HIR::Publicity::new_priv( LowerHIR_SimplePath(Span(), ast_mod.path()) ); // TODO: Does this need to consume anon modules? + auto get_pub = [&](bool is_pub){ return is_pub ? ::HIR::Publicity::new_global() : priv_path; }; + ::std::map< ::std::string, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> > methods; ::std::map< ::std::string, ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> > constants; @@ -1703,7 +1725,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat ), (Static, if( e.s_class() == ::AST::Static::CONST ) { - constants.insert( ::std::make_pair(item.name, ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> { item.is_pub, item.is_specialisable, ::HIR::Constant { + constants.insert( ::std::make_pair(item.name, ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> { get_pub(item.is_pub), item.is_specialisable, ::HIR::Constant { ::HIR::GenericParams {}, LowerHIR_Type( e.type() ), LowerHIR_Expr( e.value() ) @@ -1715,7 +1737,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat ), (Function, methods.insert( ::std::make_pair(item.name, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { - item.is_pub, item.is_specialisable, LowerHIR_Function(item_path, item.data->attrs, e, type) + get_pub(item.is_pub), item.is_specialisable, LowerHIR_Function(item_path, item.data->attrs, e, type) } ) ); ) ) diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index 48787583..f0844580 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -41,10 +41,70 @@ class TypeItem; class ItemPath; +class Publicity +{ + ::std::shared_ptr<::HIR::SimplePath> vis_path; + + Publicity(::std::shared_ptr<::HIR::SimplePath> p) + :vis_path(p) + { + } +public: + + static Publicity new_global() { + return Publicity({}); + } + static Publicity new_none() { + static ::std::shared_ptr<::HIR::SimplePath> none_path = ::std::make_shared(); + return Publicity(none_path); + } + static Publicity new_priv(::HIR::SimplePath p) { + return Publicity(::std::make_shared(::std::move(p))); + } + + bool is_global() const { + return !vis_path; + } + bool is_visible(const ::HIR::SimplePath& p) const { + // No path = global public + if( !vis_path ) + return true; + // Empty simple path = full private + if( *vis_path == ::HIR::SimplePath() ) { + return false; + } + // Crate names must match + if(p.m_crate_name != vis_path->m_crate_name) + return false; + // `p` must be a child of vis_path + if(p.m_components.size() < vis_path->m_components.size()) + return false; + for(size_t i = 0; i < vis_path->m_components.size(); i ++) + { + if(p.m_components[i] != vis_path->m_components[i]) + return false; + } + return true; + } + + friend ::std::ostream& operator<<(::std::ostream& os, const Publicity& x) { + if( !x.vis_path ) { + os << "pub"; + } + else if( *x.vis_path == ::HIR::SimplePath() ) { + os << "priv"; + } + else { + os << "pub(" << *x.vis_path << ")"; + } + return os; + } +}; + template struct VisEnt { - bool is_public; + Publicity publicity; Ent ent; }; @@ -396,7 +456,7 @@ class TypeImpl public: template struct VisImplEnt { - bool is_pub; + Publicity publicity; bool is_specialisable; T data; }; diff --git a/src/hir/hir_ops.cpp b/src/hir/hir_ops.cpp index b09dbdf7..89e48c80 100644 --- a/src/hir/hir_ops.cpp +++ b/src/hir/hir_ops.cpp @@ -1036,6 +1036,7 @@ const ::MIR::Function* HIR::Crate::get_or_gen_mir(const ::HIR::ItemPath& ip, con ms.m_impl_generics = ep.m_state->m_impl_generics; ms.m_item_generics = ep.m_state->m_item_generics; ms.m_traits = ep.m_state->m_traits; + ms.m_mod_paths.push_back(ep.m_state->m_mod_path); Typecheck_Code(ms, const_cast<::HIR::Function::args_t&>(args), ret_ty, ep_mut); //Debug_SetStagePre("Expand HIR Annotate"); HIR_Expand_AnnotateUsage_Expr(*this, ep_mut); diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index 0d01ed25..dd81596f 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -60,7 +60,7 @@ template void serialise(const ::HIR::VisEnt& e) { - m_out.write_bool(e.is_public); + m_out.write_bool(e.publicity.is_global()); // At this stage, we only care if the item is visible outside the crate or not serialise(e.ent); } template @@ -322,14 +322,14 @@ m_out.write_count(impl.m_methods.size()); for(const auto& v : impl.m_methods) { m_out.write_string(v.first); - m_out.write_bool(v.second.is_pub); + m_out.write_bool(v.second.publicity.is_global()); m_out.write_bool(v.second.is_specialisable); serialise(v.second.data); } m_out.write_count(impl.m_constants.size()); for(const auto& v : impl.m_constants) { m_out.write_string(v.first); - m_out.write_bool(v.second.is_pub); + m_out.write_bool(v.second.publicity.is_global()); m_out.write_bool(v.second.is_specialisable); serialise(v.second.data); } diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index c26ae03f..a3b0041b 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -120,7 +120,7 @@ namespace { m_cur_module.ptr = &mod; m_cur_module.path = &p; - m_ms.push_traits(mod); + m_ms.push_traits(p, mod); ::HIR::Visitor::visit_module(p, mod); m_ms.pop_traits(mod); @@ -512,12 +512,16 @@ namespace { void visit_type_impl(::HIR::TypeImpl& impl) override { - TRACE_FUNCTION_F("impl " << impl.m_type); + TRACE_FUNCTION_F("impl " << impl.m_type << " - from " << impl.m_src_module); auto _ = this->m_ms.set_impl_generics(impl.m_params); + auto mod_ip = ::HIR::ItemPath(impl.m_src_module); const auto* mod = (impl.m_src_module != ::HIR::SimplePath() ? &this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module) : nullptr); - if(mod) - m_ms.push_traits(*mod); + if(mod) { + m_ms.push_traits(impl.m_src_module, *mod); + m_cur_module.ptr = mod; + m_cur_module.path = &mod_ip; + } ::HIR::Visitor::visit_type_impl(impl); if(mod) m_ms.pop_traits(*mod); @@ -527,9 +531,13 @@ namespace { TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type); auto _ = this->m_ms.set_impl_generics(impl.m_params); + auto mod_ip = ::HIR::ItemPath(impl.m_src_module); const auto* mod = (impl.m_src_module != ::HIR::SimplePath() ? &this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module) : nullptr); - if(mod) - m_ms.push_traits(*mod); + if(mod) { + m_ms.push_traits(impl.m_src_module, *mod); + m_cur_module.ptr = mod; + m_cur_module.path = &mod_ip; + } m_ms.m_traits.push_back( ::std::make_pair( &trait_path, &this->m_ms.m_crate.get_trait_by_path(Span(), trait_path) ) ); ::HIR::Visitor::visit_trait_impl(trait_path, impl); m_ms.m_traits.pop_back( ); @@ -541,9 +549,13 @@ namespace { TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type << " { }"); auto _ = this->m_ms.set_impl_generics(impl.m_params); + auto mod_ip = ::HIR::ItemPath(impl.m_src_module); const auto* mod = (impl.m_src_module != ::HIR::SimplePath() ? &this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module) : nullptr); - if(mod) - m_ms.push_traits(*mod); + if(mod) { + m_ms.push_traits(impl.m_src_module, *mod); + m_cur_module.ptr = mod; + m_cur_module.path = &mod_ip; + } ::HIR::Visitor::visit_marker_impl(trait_path, impl); if(mod) m_ms.pop_traits(*mod); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 3d1bf4a5..6049056c 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -1035,6 +1035,7 @@ namespace { tp.pp_impl = ms.pp_impl->clone(); ep.m_mir = Trans_Monomorphise(resolve, mv$(tp), template_const.m_value.m_mir); ep.m_state = ::HIR::ExprStatePtr( ::HIR::ExprState(*m_mod, m_mod_path->get_simple_path()) ); + DEBUG("TMP TMP " << trait_path << " - " << ep.m_state->m_mod_path); ep.m_state->stage = ::HIR::ExprState::Stage::Mir; impl.m_constants.insert(::std::make_pair( vi.first, @@ -1211,7 +1212,7 @@ namespace { { // ::std::unique_ptr> ::std::unique_ptr<::HIR::VisEnt<::HIR::ValueItem>> iv; - iv.reset( new ::HIR::VisEnt<::HIR::ValueItem> { false, ::HIR::ValueItem::make_Static(mv$(v.second)) } ); + iv.reset( new ::HIR::VisEnt<::HIR::ValueItem> { ::HIR::Publicity::new_none(), ::HIR::ValueItem::make_Static(mv$(v.second)) } ); mod.m_value_items.insert(::std::make_pair( v.first, mv$(iv) )); } mod.m_inline_statics.clear(); diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index ee0cff08..d7d476e5 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -720,7 +720,7 @@ namespace { // - Fix type to replace closure types with known paths ExprVisitor_Fixup fixup { m_resolve.m_crate, ¶ms, monomorph_cb }; fixup.visit_type(ty_mono); - capture_types.push_back( ::HIR::VisEnt< ::HIR::TypeRef> { false, mv$(ty_mono) } ); + capture_types.push_back( ::HIR::VisEnt< ::HIR::TypeRef> { ::HIR::Publicity::new_none(), mv$(ty_mono) } ); } auto closure_struct_path = m_new_type( ::HIR::Struct { @@ -1182,7 +1182,7 @@ namespace { m_new_type = [&](auto s)->auto { auto name = FMT("closure#I_" << closure_count); closure_count += 1; - auto boxed = box$(( ::HIR::VisEnt< ::HIR::TypeItem> { false, ::HIR::TypeItem( mv$(s) ) } )); + auto boxed = box$(( ::HIR::VisEnt< ::HIR::TypeItem> { ::HIR::Publicity::new_none(), ::HIR::TypeItem( mv$(s) ) } )); crate.m_root_module.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) ); return ::HIR::SimplePath(crate.m_crate_name, {}) + name; }; @@ -1209,7 +1209,7 @@ namespace { crate.m_type_impls.push_back( ::HIR::TypeImpl { mv$(impl.second.m_params), mv$(impl.second.m_type), - make_map1(impl.second.m_methods.begin()->first, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { true, false, mv$(impl.second.m_methods.begin()->second.data) }), + make_map1(impl.second.m_methods.begin()->first, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { ::HIR::Publicity::new_global(), false, mv$(impl.second.m_methods.begin()->second.data) }), {}, mv$(impl.second.m_src_module) } ); @@ -1233,7 +1233,7 @@ namespace { m_new_type = [&](auto s)->auto { auto name = FMT("closure#" << closure_count); closure_count += 1; - auto boxed = box$( (::HIR::VisEnt< ::HIR::TypeItem> { false, ::HIR::TypeItem( mv$(s) ) }) ); + auto boxed = box$( (::HIR::VisEnt< ::HIR::TypeItem> { ::HIR::Publicity::new_none(), ::HIR::TypeItem( mv$(s) ) }) ); mod.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) ); return (p + name).get_simple_path(); }; diff --git a/src/hir_expand/vtable.cpp b/src/hir_expand/vtable.cpp index 79e163ac..2b3dcfb4 100644 --- a/src/hir_expand/vtable.cpp +++ b/src/hir_expand/vtable.cpp @@ -32,7 +32,7 @@ namespace { ::std::vector< decltype(mod.m_mod_items)::value_type> new_types; m_new_type = [&](bool pub, auto name, auto s)->auto { - auto boxed = box$( (::HIR::VisEnt< ::HIR::TypeItem> { pub, ::HIR::TypeItem( mv$(s) ) }) ); + auto boxed = box$( (::HIR::VisEnt< ::HIR::TypeItem> { (pub ? ::HIR::Publicity::new_global() : ::HIR::Publicity::new_none()), ::HIR::TypeItem( mv$(s) ) }) ); auto ret = (p + name).get_simple_path(); new_types.push_back( ::std::make_pair( mv$(name), mv$(boxed)) ); return ret; @@ -173,7 +173,7 @@ namespace { DEBUG("- '" << vi.first << "' is @" << fields.size()); fields.push_back( ::std::make_pair( vi.first, - ::HIR::VisEnt< ::HIR::TypeRef> { true, mv$(fcn_type) } + ::HIR::VisEnt< ::HIR::TypeRef> { ::HIR::Publicity::new_global(), mv$(fcn_type) } ) ); ), (Static, @@ -204,11 +204,11 @@ namespace { ft.m_abi = ABI_RUST; ft.m_rettype.reset( new ::HIR::TypeRef(::HIR::TypeRef::new_unit()) ); ft.m_arg_types.push_back( ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Owned, ::HIR::TypeRef::new_unit()) ); - vtc.fields.push_back(::std::make_pair( "#drop_glue", ::HIR::VisEnt<::HIR::TypeRef> { false, ::HIR::TypeRef(mv$(ft)) } )); + vtc.fields.push_back(::std::make_pair( "#drop_glue", ::HIR::VisEnt<::HIR::TypeRef> { ::HIR::Publicity::new_none(), ::HIR::TypeRef(mv$(ft)) } )); // - Size of data - vtc.fields.push_back(::std::make_pair( "#size", ::HIR::VisEnt<::HIR::TypeRef> { false, ::HIR::CoreType::Usize } )); + vtc.fields.push_back(::std::make_pair( "#size", ::HIR::VisEnt<::HIR::TypeRef> { ::HIR::Publicity::new_none(), ::HIR::CoreType::Usize } )); // - Alignment of data - vtc.fields.push_back(::std::make_pair( "#align", ::HIR::VisEnt<::HIR::TypeRef> { false, ::HIR::CoreType::Usize } )); + vtc.fields.push_back(::std::make_pair( "#align", ::HIR::VisEnt<::HIR::TypeRef> { ::HIR::Publicity::new_none(), ::HIR::CoreType::Usize } )); // - Add methods if( ! vtc.add_ents_from_trait(tr, trait_path) ) { diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 762adf5a..1fd44698 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -156,9 +156,9 @@ struct Context const ::HIR::SimplePath m_lang_Box; - Context(const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params): + Context(const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params, const ::HIR::SimplePath& mod_path): m_crate(crate), - m_resolve(m_ivars, crate, impl_params, item_params) + m_resolve(m_ivars, crate, impl_params, item_params, mod_path) ,next_rule_idx( 0 ) ,m_lang_Box( crate.get_lang_item_path_opt("owned_box") ) { @@ -8062,7 +8062,8 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: TRACE_FUNCTION; auto root_ptr = expr.into_unique(); - Context context { ms.m_crate, ms.m_impl_generics, ms.m_item_generics }; + assert(!ms.m_mod_paths.empty()); + Context context { ms.m_crate, ms.m_impl_generics, ms.m_item_generics, ms.m_mod_paths.back() }; for( auto& arg : args ) { context.handle_pattern( Span(), arg.first, arg.second ); diff --git a/src/hir_typeck/expr_visit.cpp b/src/hir_typeck/expr_visit.cpp index 1a153aaf..d713c135 100644 --- a/src/hir_typeck/expr_visit.cpp +++ b/src/hir_typeck/expr_visit.cpp @@ -36,7 +36,7 @@ namespace { public: void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override { - m_ms.push_traits(mod); + m_ms.push_traits(p, mod); ::HIR::Visitor::visit_module(p, mod); m_ms.pop_traits(mod); } @@ -58,7 +58,7 @@ namespace { auto _ = this->m_ms.set_impl_generics(impl.m_params); const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module); - m_ms.push_traits(mod); + m_ms.push_traits(impl.m_src_module, mod); ::HIR::Visitor::visit_type_impl(impl); m_ms.pop_traits(mod); } @@ -68,7 +68,7 @@ namespace { auto _ = this->m_ms.set_impl_generics(impl.m_params); const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module); - m_ms.push_traits(mod); + m_ms.push_traits(impl.m_src_module, mod); m_ms.m_traits.push_back( ::std::make_pair( &trait_path, &this->m_ms.m_crate.get_trait_by_path(Span(), trait_path) ) ); ::HIR::Visitor::visit_trait_impl(trait_path, impl); m_ms.m_traits.pop_back( ); @@ -80,7 +80,7 @@ namespace { auto _ = this->m_ms.set_impl_generics(impl.m_params); const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module); - m_ms.push_traits(mod); + m_ms.push_traits(impl.m_src_module, mod); ::HIR::Visitor::visit_marker_impl(trait_path, impl); m_ms.pop_traits(mod); } diff --git a/src/hir_typeck/expr_visit.hpp b/src/hir_typeck/expr_visit.hpp index 21a775dc..9388b1dd 100644 --- a/src/hir_typeck/expr_visit.hpp +++ b/src/hir_typeck/expr_visit.hpp @@ -5,6 +5,7 @@ * hir_typeck/expr_visit.hpp * - Helpers for the HIR typecheck expression visiting */ +#include namespace typeck { struct ModuleState @@ -15,6 +16,7 @@ namespace typeck { ::HIR::GenericParams* m_item_generics; ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits; + ::std::vector m_mod_paths; ModuleState(const ::HIR::Crate& crate): m_crate(crate), @@ -44,8 +46,9 @@ namespace typeck { return NullOnDrop< ::HIR::GenericParams>(m_item_generics); } - void push_traits(const ::HIR::Module& mod) { + void push_traits(::HIR::ItemPath p, const ::HIR::Module& mod) { auto sp = Span(); + m_mod_paths.push_back( p.get_simple_path() ); DEBUG("Module has " << mod.m_traits.size() << " in-scope traits"); // - Push a NULL entry to prevent parent module import lists being searched m_traits.push_back( ::std::make_pair(nullptr, nullptr) ); @@ -59,6 +62,7 @@ namespace typeck { for(unsigned int i = 0; i < mod.m_traits.size(); i ++ ) m_traits.pop_back(); m_traits.pop_back(); + m_mod_paths.pop_back(); } }; } diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index f94cdf26..0ebb9c07 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -4334,8 +4334,8 @@ bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const (Tuple, for( unsigned int i = 0; i < se.size(); i ++ ) { - // TODO: Privacy - if( FMT(i) == name ) { + DEBUG(i << ": " << se[i].publicity); + if( se[i].publicity.is_visible(this->m_vis_path) && FMT(i) == name ) { field_ty = monomorphise_type_with(sp, se[i].ent, monomorph); return true; } @@ -4344,8 +4344,8 @@ bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const (Named, for( const auto& fld : se ) { - // TODO: Privacy - if( fld.first == name ) { + DEBUG(fld.first << ": " << fld.second.publicity << ", " << this->m_vis_path); + if( fld.second.publicity.is_visible(this->m_vis_path) && fld.first == name ) { field_ty = monomorphise_type_with(sp, fld.second.ent, monomorph); return true; } @@ -4379,7 +4379,7 @@ bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const for( const auto& fld : unm.m_variants ) { // TODO: Privacy - if( fld.first == name ) { + if( fld.second.publicity.is_visible(this->m_vis_path) && fld.first == name ) { field_ty = monomorphise_type_with(sp, fld.second.ent, monomorph); return true; } diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 651a36c8..dd9a1581 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -150,17 +150,19 @@ class TraitResolution const ::HIR::Crate& m_crate; const ::HIR::GenericParams* m_impl_params; const ::HIR::GenericParams* m_item_params; + const ::HIR::SimplePath& m_vis_path; ::std::map< ::HIR::TypeRef, ::HIR::TypeRef> m_type_equalities; ::HIR::SimplePath m_lang_Box; mutable ::std::vector< ::HIR::TypeRef> m_eat_active_stack; public: - TraitResolution(const HMTypeInferrence& ivars, const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params): + TraitResolution(const HMTypeInferrence& ivars, const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params, const ::HIR::SimplePath& vis_path): m_ivars(ivars), m_crate(crate), m_impl_params( impl_params ), m_item_params( item_params ) + ,m_vis_path(vis_path) { prep_indexes(); m_lang_Box = crate.get_lang_item_path_opt("owned_box"); diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp index f010b420..f38219ef 100644 --- a/src/resolve/index.cpp +++ b/src/resolve/index.cpp @@ -286,7 +286,7 @@ void Resolve_Index_Module_Wildcard__glob_in_hir_mod(const Span& sp, const AST::C { for(const auto& it : hmod.m_mod_items) { const auto& ve = *it.second; - if( ve.is_public ) { + if( ve.publicity.is_global() ) { const auto* vep = &ve.ent; AST::Path p; if( vep->is_Import() ) { @@ -346,7 +346,7 @@ void Resolve_Index_Module_Wildcard__glob_in_hir_mod(const Span& sp, const AST::C } for(const auto& it : hmod.m_value_items) { const auto& ve = *it.second; - if( ve.is_public ) { + if( ve.publicity.is_global() ) { AST::Path p; const auto* vep = &ve.ent; if( ve.ent.is_Import() ) { diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index e1e2bbd5..afdbd626 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -152,14 +152,14 @@ namespace { const bool EMIT_ALL = true; for(auto& vi : mod.m_value_items) { - Trans_Enumerate_ValItem(state, vi.second->ent, EMIT_ALL || (is_visible && vi.second->is_public), [&](){ return mod_path + vi.first; }); + Trans_Enumerate_ValItem(state, vi.second->ent, EMIT_ALL || (is_visible && vi.second->publicity.is_global()), [&](){ return mod_path + vi.first; }); } for(auto& ti : mod.m_mod_items) { if(auto* e = ti.second->ent.opt_Module() ) { - Trans_Enumerate_Public_Mod(state, *e, mod_path + ti.first, ti.second->is_public); + Trans_Enumerate_Public_Mod(state, *e, mod_path + ti.first, ti.second->publicity.is_global()); } } } -- cgit v1.2.3 From 967a76859749ecb602cd2c343e28888514f827bd Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 25 Apr 2019 13:56:11 +0800 Subject: MIR - Reduce size of LValue::Static by putting the HIR::Path behind a pointer --- src/hir/deserialise.cpp | 2 +- src/hir/serialise.cpp | 2 +- src/hir_conv/bind.cpp | 2 +- src/hir_conv/constant_evaluation.cpp | 4 +-- src/mir/dump.cpp | 2 +- src/mir/from_hir.cpp | 2 +- src/mir/helpers.cpp | 2 +- src/mir/mir.cpp | 4 +-- src/mir/mir.hpp | 58 +++++++++++++++++++++++++++++++++++- src/mir/mir_builder.cpp | 8 ++--- src/mir/optimise.cpp | 2 +- src/trans/codegen_c.cpp | 2 +- src/trans/codegen_mmir.cpp | 2 +- src/trans/enumerate.cpp | 4 +-- src/trans/monomorphise.cpp | 2 +- 15 files changed, 77 insertions(+), 21 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 9933255f..cd25a3cb 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -423,7 +423,7 @@ _(Return, {}) _(Argument, { static_cast(m_in.read_count()) } ) _(Local, static_cast(m_in.read_count()) ) - _(Static, deserialise_path() ) + _(Static, box$(deserialise_path()) ) _(Field, { box$( deserialise_mir_lvalue() ), static_cast(m_in.read_count()) diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index dd81596f..e90cf995 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -689,7 +689,7 @@ m_out.write_count(e); ), (Static, - serialise_path(e); + serialise_path(*e); ), (Field, serialise(e.val); diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index a3b0041b..940b2cab 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -712,7 +712,7 @@ namespace { (Argument, ), (Static, - upper_visitor.visit_path(e, ::HIR::Visitor::PathContext::VALUE); + upper_visitor.visit_path(*e, ::HIR::Visitor::PathContext::VALUE); ), (Field, H::visit_lvalue(upper_visitor, *e.val); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 6049056c..6838e186 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -319,7 +319,7 @@ namespace { return args[e.idx]; ), (Static, - MIR_TODO(state, "LValue::Static - " << e); + MIR_TODO(state, "LValue::Static - " << *e); ), (Field, auto& val = get_lval(*e.val); @@ -495,7 +495,7 @@ namespace { } else if( const auto* p = e.val.opt_Static() ) { // Borrow of a static, emit BorrowPath with the same path - val = ::HIR::Literal::make_BorrowPath( p->clone() ); + val = ::HIR::Literal::make_BorrowPath( (*p)->clone() ); } else { auto inner_val = local_state.read_lval(e.val); diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index 90b81d5d..ffce8abb 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -187,7 +187,7 @@ namespace { os << "_$" << e; ), (Static, - os << e; + os << *e; ), (Field, os << "("; diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index a2d0c790..912b8c78 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -2195,7 +2195,7 @@ namespace { m_builder.set_result( node.span(), mv$(tmp) ); ), (Static, - m_builder.set_result( node.span(), ::MIR::LValue::make_Static(node.m_path.clone()) ); + m_builder.set_result( node.span(), ::MIR::LValue::make_Static(box$(node.m_path.clone())) ); ), (StructConstant, // TODO: Why is this still a PathValue? diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 38380fed..38388aed 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -82,7 +82,7 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return m_fcn.locals.at(e); ), (Static, - return get_static_type(tmp, e); + return get_static_type(tmp, *e); ), (Field, const auto& ty = this->get_lvalue_type(tmp, *e.val); diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index ee6c1a6c..657e695d 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -104,7 +104,7 @@ namespace MIR { os << "Local(" << e << ")"; ), (Static, - os << "Static(" << e << ")"; + os << "Static(" << *e << ")"; ), (Field, os << "Field(" << e.field_index << ", " << *e.val << ")"; @@ -543,7 +543,7 @@ namespace MIR { (Return, return LValue(e); ), (Argument, return LValue(e); ), (Local, return LValue(e); ), - (Static, return LValue(e.clone()); ), + (Static, return LValue(box$(e->clone())); ), (Field, return LValue::make_Field({ box$( e.val->clone() ), e.field_index diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 31eb9cd7..6969225d 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -17,6 +17,62 @@ namespace MIR { typedef unsigned int RegionId; typedef unsigned int BasicBlockId; +#if 0 +// TODO: Store LValues as: +// - A packed root value (one word, using the low bits as an enum descriminator) +// - A list of (inner to outer) wrappers +struct LValue +{ + class Storage + { + uintptr_t val; + public: + ~Storage() + { + if( is_Static() ) { + delete reinterpret_cast<::HIR::Path*>(val & ~3u); + val = 0; + } + } + bool is_Argument() const { return val != (MAX_ARG << 2) && (val & 3) == 0; } + bool is_Return() const { return val == (MAX_ARG << 2); } + bool is_Local() const { return (val & 3) == 1; } + bool is_Static() const { return (val & 3) == 2; } + + const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3u); } + }; + class Wrapper + { + uintptr_t val; + public: + bool is_Deref() const { return (val & 3) == 0; } + // Stores the field index + bool is_Field() const { return (val & 3) == 1; } + // Stores the variant index + bool is_Downcast() const { return (val & 3) == 2; } + // Stores a Local index + bool is_Index() const { return (val & 3) == 3; } + + const unsigned as_Field() const { assert(is_Field()); return (val >> 2); } + const unsigned as_Index() const { assert(is_Index()); return (val >> 2); } + }; + + Storage m_root; + ::std::vector m_wrappers; + + LValue clone() const; + + class Ref + { + LValue& r; + size_t wrapper_idx; + public:: + LValue clone() const; + void replace(LValue x) const; + }; +}; +#endif + // "LVALUE" - Assignable values TAGGED_UNION_EX(LValue, (), Return, ( // Function return @@ -26,7 +82,7 @@ TAGGED_UNION_EX(LValue, (), Return, ( // Variable/Temporary (Local, unsigned int), // `static` or `static mut` - (Static, ::HIR::Path), + (Static, ::std::unique_ptr<::HIR::Path>), // Field access (tuple, struct, tuple struct, enum field, ...) // NOTE: Also used to index an array/slice by a compile-time known index (e.g. in destructuring) (Field, struct { diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index ac1b7650..81816535 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -1622,20 +1622,20 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: cb( m_output.locals.at(e) ); ), (Static, - TU_MATCHA( (e.m_data), (pe), + TU_MATCHA( (e->m_data), (pe), (Generic, ASSERT_BUG(sp, pe.m_params.m_types.empty(), "Path params on static"); const auto& s = m_resolve.m_crate.get_static_by_path(sp, pe.m_path); cb( s.m_type ); ), (UfcsKnown, - TODO(sp, "Static - UfcsKnown - " << e); + TODO(sp, "Static - UfcsKnown - " << *e); ), (UfcsUnknown, - BUG(sp, "Encountered UfcsUnknown in Static - " << e); + BUG(sp, "Encountered UfcsUnknown in Static - " << *e); ), (UfcsInherent, - TODO(sp, "Static - UfcsInherent - " << e); + TODO(sp, "Static - UfcsInherent - " << *e); ) ) ), diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 67a5d4a4..b7e63deb 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -1159,7 +1159,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool return ::MIR::LValue::make_Local(this->var_base + se); ), (Static, - return this->monomorph( se ); + return box$(this->monomorph( *se )); ), (Deref, return ::MIR::LValue::make_Deref({ box$(this->clone_lval(*se.val)) }); diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 98d0d3de..373a36a8 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -5522,7 +5522,7 @@ namespace { m_of << "var" << e; ), (Static, - m_of << Trans_Mangle(e); + m_of << Trans_Mangle(*e); ), (Field, ::HIR::TypeRef tmp; diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index b2c5282a..4867cf6f 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -52,7 +52,7 @@ namespace os << "arg" << e.idx; break; TU_ARM(x.e, Static, e) - os << e; + os << *e; break; TU_ARM(x.e, Deref, e) os << "*" << fmt(*e.val); diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index afdbd626..da11386c 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -735,7 +735,7 @@ void Trans_Enumerate_Types(EnumState& state) ), (Static, if( tmp_ty_ptr ) { - const auto& path = e; + const auto& path = *e; TU_MATCHA( (path.m_data), (pe), (Generic, ASSERT_BUG(Span(), pe.m_params.m_types.empty(), "Path params on static - " << path); @@ -1495,7 +1495,7 @@ void Trans_Enumerate_FillFrom_MIR_LValue(EnumState& state, const ::MIR::LValue& (Local, ), (Static, - Trans_Enumerate_FillFrom_Path(state, e, pp); + Trans_Enumerate_FillFrom_Path(state, *e, pp); ), (Field, Trans_Enumerate_FillFrom_MIR_LValue(state, *e.val, pp); diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index 3b958fec..0a0b43b5 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -19,7 +19,7 @@ namespace { (Argument, return e; ), (Local, return e; ), (Static, - return params.monomorph(resolve, e); + return box$(params.monomorph(resolve, *e)); ), (Field, return ::MIR::LValue::make_Field({ -- cgit v1.2.3 From 4c4a7b88914861b644ec56738ced8cfc179f93f9 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 5 May 2019 12:42:57 +0800 Subject: MIR - Wrap HIR::Path-s in MIR::Constant in unique_ptr --- src/hir/deserialise.cpp | 4 +-- src/hir/expr_ptr.cpp | 13 ++++--- src/hir/serialise.cpp | 4 +-- src/hir_conv/bind.cpp | 47 ++++++++++--------------- src/hir_conv/constant_evaluation.cpp | 6 ++-- src/mir/cleanup.cpp | 18 +++++----- src/mir/dump.cpp | 4 +-- src/mir/from_hir.cpp | 20 ++++++----- src/mir/helpers.cpp | 10 +++--- src/mir/mir.cpp | 12 +++---- src/mir/mir.hpp | 67 ++++++++++++++++++++++++++++++------ src/mir/optimise.cpp | 4 +-- src/trans/codegen_c.cpp | 8 ++--- src/trans/codegen_mmir.cpp | 2 +- src/trans/enumerate.cpp | 4 +-- src/trans/monomorphise.cpp | 6 ++-- 16 files changed, 135 insertions(+), 94 deletions(-) (limited to 'src/hir_conv/bind.cpp') diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index cd25a3cb..c5350b55 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -532,8 +532,8 @@ return ::MIR::Constant::make_Bytes( mv$(bytes) ); } _(StaticString, m_in.read_string() ) - _(Const, { deserialise_path() } ) - _(ItemAddr, deserialise_path() ) + _(Const, { box$(deserialise_path()) } ) + _(ItemAddr, box$(deserialise_path()) ) #undef _ default: BUG(Span(), "Bad tag for MIR::Const - " << tag); diff --git a/src/hir/expr_ptr.cpp b/src/hir/expr_ptr.cpp index 0c219e0f..7f493a0d 100644 --- a/src/hir/expr_ptr.cpp +++ b/src/hir/expr_ptr.cpp @@ -91,11 +91,14 @@ void HIR::ExprPtr::set_mir(::MIR::FunctionPointer mir) assert( !this->m_mir ); m_mir = ::std::move(mir); // Reset the HIR tree to be a placeholder node (thus freeing the backing memory) - //if( node ) - //{ - // auto sp = node->span(); - // node = ExprPtrInner(::std::unique_ptr(new ::HIR::ExprNode_Tuple(sp, {}))); - //} + if( false && node ) + { + auto sp = node->span(); + node = ExprPtrInner(::std::unique_ptr(new ::HIR::ExprNode_Loop( + sp, "", + ::std::unique_ptr(new ::HIR::ExprNode_Tuple(sp, {})) + ))); + } } diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index e90cf995..2c72c801 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -795,10 +795,10 @@ m_out.write_string(e); ), (Const, - serialise_path(e.p); + serialise_path(*e.p); ), (ItemAddr, - serialise_path(e); + serialise_path(*e); ) ) } diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 940b2cab..84854315 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -729,25 +729,29 @@ namespace { ) ) } + static void visit_constant(Visitor& upper_visitor, ::MIR::Constant& e) + { + TU_MATCHA( (e), (ce), + (Int, ), + (Uint,), + (Float, ), + (Bool, ), + (Bytes, ), + (StaticString, ), // String + (Const, + upper_visitor.visit_path(*ce.p, ::HIR::Visitor::PathContext::VALUE); + ), + (ItemAddr, + upper_visitor.visit_path(*ce, ::HIR::Visitor::PathContext::VALUE); + ) + ) + } static void visit_param(Visitor& upper_visitor, ::MIR::Param& p) { TU_MATCHA( (p), (e), (LValue, H::visit_lvalue(upper_visitor, e);), (Constant, - TU_MATCHA( (e), (ce), - (Int, ), - (Uint,), - (Float, ), - (Bool, ), - (Bytes, ), - (StaticString, ), // String - (Const, - upper_visitor.visit_path(ce.p, ::HIR::Visitor::PathContext::VALUE); - ), - (ItemAddr, - upper_visitor.visit_path(ce, ::HIR::Visitor::PathContext::VALUE); - ) - ) + H::visit_constant(upper_visitor, e); ) ) } @@ -765,20 +769,7 @@ namespace { H::visit_lvalue(*this, e); ), (Constant, - TU_MATCHA( (e), (ce), - (Int, ), - (Uint,), - (Float, ), - (Bool, ), - (Bytes, ), - (StaticString, ), // String - (Const, - this->visit_path(ce.p, ::HIR::Visitor::PathContext::VALUE); - ), - (ItemAddr, - this->visit_path(ce, ::HIR::Visitor::PathContext::VALUE); - ) - ) + H::visit_constant(*this, e); ), (SizedArray, H::visit_param(*this, e.val); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 6067b32f..0ccb6e6f 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -390,11 +390,11 @@ namespace HIR { TU_ARM(c, StaticString, e2) return ::HIR::Literal(e2); TU_ARM(c, Const, e2) { - auto p = ms.monomorph(state.sp, e2.p); + auto p = ms.monomorph(state.sp, *e2.p); // If there's any mention of generics in this path, then return Literal::Defer if( visit_path_tys_with(p, [&](const auto& ty)->bool { return ty.m_data.is_Generic(); }) ) { - DEBUG("Return Literal::Defer for constant " << e2.p << " which references a generic parameter"); + DEBUG("Return Literal::Defer for constant " << *e2.p << " which references a generic parameter"); return ::HIR::Literal::make_Defer({}); } MonomorphState const_ms; @@ -417,7 +417,7 @@ namespace HIR { return clone_literal( c.m_value_res ); } TU_ARM(c, ItemAddr, e2) - return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, e2) ); + return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, *e2) ); } throw ""; }; diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index fdc0f3d4..dd5332b6 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -216,7 +216,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con if( path == ::HIR::GenericPath() ) MIR_TODO(state, "Literal of type " << ty << " - " << lit); DEBUG("Unknown type " << ty << ", but a path was provided - Return ItemAddr " << path); - return ::MIR::Constant( mv$(path) ); + return ::MIR::Constant::make_ItemAddr( box$(path) ); ), (Tuple, MIR_ASSERT(state, lit.is_List(), "Non-list literal for Tuple - " << lit); @@ -378,7 +378,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con if( const auto* pp = lit.opt_BorrowPath() ) { const auto& path = *pp; - auto ptr_val = ::MIR::Constant::make_ItemAddr(path.clone()); + auto ptr_val = ::MIR::Constant::make_ItemAddr(box$(path.clone())); // TODO: Get the metadata type (for !Sized wrapper types) if( te.inner->m_data.is_Slice() ) { @@ -397,7 +397,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con auto vtable_path = ::HIR::Path(&ty == &tmp ? mv$(tmp) : ty.clone(), tep->m_trait.m_path.clone(), "vtable#"); - auto vtable_val = ::MIR::Param( ::MIR::Constant::make_ItemAddr(mv$(vtable_path)) ); + auto vtable_val = ::MIR::Param( ::MIR::Constant::make_ItemAddr(box$(vtable_path)) ); return ::MIR::RValue::make_MakeDst({ ::MIR::Param(mv$(ptr_val)), mv$(vtable_val) }); } @@ -458,7 +458,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con (Function, //MIR_TODO(state, "Const function pointer " << lit << " w/ type " << ty); MIR_ASSERT(state, lit.is_BorrowPath(), ""); - return ::MIR::Constant::make_ItemAddr( lit.as_BorrowPath().clone() ); + return ::MIR::Constant::make_ItemAddr( box$( lit.as_BorrowPath().clone() ) ); ) ) } @@ -703,7 +703,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& MIR_ASSERT(state, state.m_resolve.type_is_sized(state.sp, src_ty), "Attempting to get vtable for unsized type - " << src_ty); ::HIR::Path vtable { src_ty.clone(), trait_path.m_path.clone(), "vtable#" }; - out_meta_val = ::MIR::Constant::make_ItemAddr(mv$(vtable)); + out_meta_val = ::MIR::Constant::make_ItemAddr(box$(vtable)); } } return true; @@ -1092,18 +1092,18 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, TU_IFLET( ::MIR::Constant, e, Const, ce, // 1. Find the constant ::HIR::TypeRef ty; - const auto* lit_ptr = MIR_Cleanup_GetConstant(state, ce.p, ty); + const auto* lit_ptr = MIR_Cleanup_GetConstant(state, *ce.p, ty); if( lit_ptr && !lit_ptr->is_Defer() ) { - DEBUG("Replace constant " << ce.p << " with " << *lit_ptr); - se.src = MIR_Cleanup_LiteralToRValue(state, mutator, *lit_ptr, mv$(ty), mv$(ce.p)); + DEBUG("Replace constant " << *ce.p << " with " << *lit_ptr); + se.src = MIR_Cleanup_LiteralToRValue(state, mutator, *lit_ptr, mv$(ty), mv$(*ce.p)); if( auto* p = se.src.opt_Constant() ) { MIR_Cleanup_Constant(state, mutator, *p); } } else { - DEBUG("No replacement for constant " << ce.p); + DEBUG("No replacement for constant " << *ce.p); } ) ) diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index ffce8abb..b02c1e5b 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -244,10 +244,10 @@ namespace { os << "\"" << ce << "\""; ), (Const, - os << ce.p; + os << *ce.p; ), (ItemAddr, - os << "addr " << ce; + os << "addr " << *ce; ) ) } diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 8d51bf55..b8549f8a 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -162,6 +162,7 @@ namespace { void destructure_from_ex(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval, int allow_refutable=0) // 1 : yes, 2 : disallow binding { + TRACE_FUNCTION_F(pat << ", allow_refutable=" << allow_refutable); if( allow_refutable != 3 && pat.m_binding.is_valid() ) { if( allow_refutable == 2 ) { BUG(sp, "Binding when not expected"); @@ -425,9 +426,10 @@ namespace { // 2. Obtain pointer to element ::HIR::BorrowType bt = H::get_borrow_type(sp, e.extra_bind); ::MIR::LValue ptr_val = m_builder.lvalue_or_temp(sp, - ::HIR::TypeRef::new_pointer( bt, inner_type.clone() ), + ::HIR::TypeRef::new_borrow( bt, inner_type.clone() ), ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::make_Field({ box$(lval.clone()), static_cast(e.leading.size()) }) }) ); + // TODO: Cast to raw pointer? Or keep as a borrow? // Construct fat pointer m_builder.push_stmt_assign( sp, m_builder.get_variable(sp, e.extra_bind.m_slot), ::MIR::RValue::make_MakeDst({ mv$(ptr_val), mv$(len_val) }) ); @@ -2185,7 +2187,7 @@ namespace { // TODO: Ideally, the creation of the wrapper function would happen somewhere before trans? auto tmp = m_builder.new_temporary( node.m_res_type ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); m_builder.set_result( sp, mv$(tmp) ); return ; } @@ -2196,7 +2198,7 @@ namespace { ), (Constant, auto tmp = m_builder.new_temporary( e.m_type ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_Const({node.m_path.clone()}) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_Const({box$(node.m_path.clone())}) ); m_builder.set_result( node.span(), mv$(tmp) ); ), (Static, @@ -2245,13 +2247,13 @@ namespace { fcn_ty_data.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) ); } auto tmp = m_builder.new_temporary( ::HIR::TypeRef( mv$(fcn_ty_data) ) ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); m_builder.set_result( sp, mv$(tmp) ); ), (StructConstructor, // TODO: Ideally, the creation of the wrapper function would happen somewhere before this? auto tmp = m_builder.new_temporary( node.m_res_type ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); m_builder.set_result( sp, mv$(tmp) ); ) ) @@ -2263,13 +2265,13 @@ namespace { ASSERT_BUG(sp, it != tr.m_values.end(), "Cannot find trait item for " << node.m_path); TU_MATCHA( (it->second), (e), (Constant, - m_builder.set_result( sp, ::MIR::Constant::make_Const({node.m_path.clone()}) ); + m_builder.set_result( sp, ::MIR::Constant::make_Const({box$(node.m_path.clone())}) ); ), (Static, TODO(sp, "Associated statics (non-rustc) - " << node.m_path); ), (Function, - m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); ) ) ), @@ -2285,7 +2287,7 @@ namespace { { auto it = impl.m_methods.find(pe.item); if( it != impl.m_methods.end() ) { - m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); return true; } } @@ -2293,7 +2295,7 @@ namespace { { auto it = impl.m_constants.find(pe.item); if( it != impl.m_constants.end() ) { - m_builder.set_result( sp, ::MIR::Constant::make_Const({node.m_path.clone()}) ); + m_builder.set_result( sp, ::MIR::Constant::make_Const({box$(node.m_path.clone())}) ); return true; } } diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 38388aed..1453acb3 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -270,7 +270,7 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons ), (Const, MonomorphState p; - auto v = m_resolve.get_value(this->sp, e.p, p, /*signature_only=*/true); + auto v = m_resolve.get_value(this->sp, *e.p, p, /*signature_only=*/true); if( const auto* ve = v.opt_Constant() ) { const auto& ty = (*ve)->m_type; if( monomorphise_type_needed(ty) ) { @@ -282,12 +282,12 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons return ty.clone(); } else { - MIR_BUG(*this, "get_const_type - Not a constant " << e.p); + MIR_BUG(*this, "get_const_type - Not a constant " << *e.p); } ), (ItemAddr, MonomorphState p; - auto v = m_resolve.get_value(this->sp, e, p, /*signature_only=*/true); + auto v = m_resolve.get_value(this->sp, *e, p, /*signature_only=*/true); TU_MATCHA( (v), (ve), (NotFound, MIR_BUG(*this, "get_const_type - ItemAddr points to unknown value - " << c); @@ -325,7 +325,7 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons ::HIR::FunctionType ft; ft.is_unsafe = false; ft.m_abi = ABI_RUST; - auto enum_path = e.clone(); + auto enum_path = e->clone(); enum_path.m_data.as_Generic().m_path.m_components.pop_back(); ft.m_rettype = box$( ::HIR::TypeRef::new_path(mv$(enum_path), ve.e) ); ft.m_arg_types.reserve(str_data.size()); @@ -348,7 +348,7 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons ::HIR::FunctionType ft; ft.is_unsafe = false; ft.m_abi = ABI_RUST; - ft.m_rettype = box$( ::HIR::TypeRef::new_path( ::HIR::GenericPath(*ve.p, e.m_data.as_Generic().m_params.clone()), &str) ); + ft.m_rettype = box$( ::HIR::TypeRef::new_path( ::HIR::GenericPath(*ve.p, e->m_data.as_Generic().m_params.clone()), &str) ); ft.m_arg_types.reserve(str_data.size()); for(const auto& fld : str_data) ft.m_arg_types.push_back( p.monomorph(this->sp, fld.ent) ); diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 657e695d..638b8e46 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -44,10 +44,10 @@ namespace MIR { os << "\"" << FmtEscaped(e) << "\""; ), (Const, - os << e.p; + os << *e.p; ), (ItemAddr, - os << "&" << e; + os << "&" << *e; ) ) return os; @@ -82,10 +82,10 @@ namespace MIR { return ::ord(ae, be); ), (Const, - return ::ord(ae.p, be.p); + return ::ord(*ae.p, *be.p); ), (ItemAddr, - return ::ord(ae, be); + return ::ord(*ae, *be); ) ) throw ""; @@ -571,8 +571,8 @@ namespace MIR { (Bool, return ::MIR::Constant(e2); ), (Bytes, return ::MIR::Constant(e2); ), (StaticString, return ::MIR::Constant(e2); ), - (Const, return ::MIR::Constant::make_Const({e2.p.clone()}); ), - (ItemAddr, return ::MIR::Constant(e2.clone()); ) + (Const, return ::MIR::Constant::make_Const({box$(e2.p->clone())}); ), + (ItemAddr, return ::MIR::Constant(box$(e2->clone())); ) ) throw ""; } diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 7100d4aa..c24aac51 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -26,7 +26,21 @@ struct LValue class Storage { uintptr_t val; + static uintptr_t MAX_ARG = (1 << 30) - 1; // max value of 30 bits public: + Storage(const Storage&) = delete; + Storage& operator=(const Storage&) = delete; + Storage(Storage&& x) + :val(x.val) + { + x.val = 0; + } + Storage& operator=(Storage&& x) + { + this->~Storage(); + this->val = x.val; + x.val = 0; + } ~Storage() { if( is_Static() ) { @@ -34,32 +48,64 @@ struct LValue val = 0; } } + + static Storage new_Return() { return Storage { MAX_ARG << 2 }; } + static Storage new_Argument(unsigned idx) { assert(idx < MAX_ARG); return Storage { idx << 2 }; ) + static Storage new_Local(unsigned idx) { assert(idx <= MAX_ARG); return Storage { (idx << 2) | 1 } }; + static Storage new_Static(::HIR::Path p) { + ::HIR::Path* ptr = new ::HIR::Path(::std::move(p)); + return Storage { static_cast(ptr) | 2; } + } + + bool is_Return() const { return val == (MAX_ARG << 2) /*&& (val & 3) == 0*/; } bool is_Argument() const { return val != (MAX_ARG << 2) && (val & 3) == 0; } - bool is_Return() const { return val == (MAX_ARG << 2); } - bool is_Local() const { return (val & 3) == 1; } - bool is_Static() const { return (val & 3) == 2; } + bool is_Local() const { return (val & 3) == 1; } + bool is_Static() const { return (val & 3) == 2; } + // No as_Return + unsigned as_Argument() const { assert(is_Argument()); return val >> 2; } + unsigned as_Local() const { assert(is_Local()); return val >> 2; } const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3u); } }; class Wrapper { uintptr_t val; public: - bool is_Deref() const { return (val & 3) == 0; } + static Wrapper new_Deref() { return Wrapper { 0 }; } + static Wrapepr new_Field (unsigned idx) { return Wrapper { (idx << 2) | 1 }; } + static Wrapepr new_Downcast(unsigned idx) { return Wrapper { (idx << 2) | 2 }; } + static Wrapepr new_Index (unsigned idx) { return Wrapper { (idx << 2) | 3 }; } + + bool is_Deref () const { return (val & 3) == 0; } // Stores the field index - bool is_Field() const { return (val & 3) == 1; } + bool is_Field () const { return (val & 3) == 1; } // Stores the variant index bool is_Downcast() const { return (val & 3) == 2; } // Stores a Local index - bool is_Index() const { return (val & 3) == 3; } + bool is_Index () const { return (val & 3) == 3; } + // no as_Deref() const unsigned as_Field() const { assert(is_Field()); return (val >> 2); } + const unsigned as_Downcast() const { assert(is_Downcast()); return (val >> 2); } + // TODO: Should this return a LValue? const unsigned as_Index() const { assert(is_Index()); return (val >> 2); } }; Storage m_root; ::std::vector m_wrappers; + static LValue new_Return() { return LValue { Storage::new_Return(), {} }; } + static LValue new_Argument(unsigned idx) { return LValue { Storage::new_Argument(idx), {} }; } + static LValue new_Local(unsigned idx) { return LValue { Storage::new_Local(idx), {} }; } + static LValue new_Static(::HIR::Path p) { return LValue { Storage::new_Static(::std::move(p)), {} }; } + + static LValue new_Deref(LValue lv) { lv.m_wrappers.push_back(Wrapper::new_Deref()); } + static LValue new_Field(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Field(idx)); } + static LValue new_Downcast(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Downcast(idx)); } + static LValue new_Index(LValue lv, unsigned local_idx) { lv.m_wrappers.push_back(Wrapper::new_Index(local_idx)); } + + LValue monomorphise(const MonomorphState& ms, unsigned local_offset=0); + //LValue monomorphise(const TransParams& ms, unsigned local_offset=0); LValue clone() const; class Ref @@ -159,11 +205,10 @@ TAGGED_UNION_EX(Constant, (), Int, ( }), (Bytes, ::std::vector< ::std::uint8_t>), // Byte string (StaticString, ::std::string), // String - // TODO: Should these ::HIR::Path structures be behind pointers? - // - HIR::Path is ~11 words long, without it MIR::Constant is 4 instead of 12 - // - MIR::Param is quite common, potential large space saving. - (Const, struct { ::HIR::Path p; }), // `const` - (ItemAddr, ::HIR::Path) // address of a value + // NOTE: These are behind pointers to save inline space (HIR::Path is ~11 + // words, compared to 4 for MIR::Constant without it) + (Const, struct { ::std::unique_ptr<::HIR::Path> p; }), // `const` + (ItemAddr, ::std::unique_ptr<::HIR::Path>) // address of a value ), (), (), ( friend ::std::ostream& operator<<(::std::ostream& os, const Constant& v); ::Ordering ord(const Constant& b) const; diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 7c284546..a45b1c05 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -1213,10 +1213,10 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool (Bytes, return ::MIR::Constant(ce);), (StaticString, return ::MIR::Constant(ce);), (Const, - return ::MIR::Constant::make_Const({ this->monomorph(ce.p) }); + return ::MIR::Constant::make_Const({ box$(this->monomorph(*ce.p)) }); ), (ItemAddr, - return ::MIR::Constant::make_ItemAddr(this->monomorph(ce)); + return ::MIR::Constant::make_ItemAddr(box$(this->monomorph(*ce))); ) ) throw ""; diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 08b4f2de..d238a523 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -5743,7 +5743,7 @@ namespace { (Const, // TODO: This should have been eliminated? ("MIR Cleanup" should have removed all inline Const references) ::HIR::TypeRef ty; - const auto& lit = get_literal_for_const(c.p, ty); + const auto& lit = get_literal_for_const(*c.p, ty); if(lit.is_Integer() || lit.is_Float()) { emit_literal(ty, lit, {}); @@ -5764,7 +5764,7 @@ namespace { } ), (ItemAddr, - TU_MATCHA( (c.m_data), (pe), + TU_MATCHA( (c->m_data), (pe), (Generic, if( pe.m_path.m_components.size() > 1 && m_crate.get_typeitem_by_path(sp, pe.m_path, false, true).is_Enum() ) ; @@ -5781,7 +5781,7 @@ namespace { } ), (UfcsUnknown, - MIR_BUG(*m_mir_res, "UfcsUnknown in trans " << c); + MIR_BUG(*m_mir_res, "UfcsUnknown in trans " << *c); ), (UfcsInherent, // TODO: If the target is a function, don't emit the & @@ -5792,7 +5792,7 @@ namespace { m_of << "&"; ) ) - m_of << Trans_Mangle(c); + m_of << Trans_Mangle(*c); ) ) } diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index 4867cf6f..51b8aac3 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -104,7 +104,7 @@ namespace os << " " << v.t; } break; TU_ARM(e, ItemAddr, v) { - os << "ADDROF " << v; + os << "ADDROF " << *v; } break; default: os << e; diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 00b938ff..934f40a2 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -1541,10 +1541,10 @@ void Trans_Enumerate_FillFrom_MIR_Constant(EnumState& state, const ::MIR::Consta (StaticString, ), // String (Const, // - Check if this constant has a value of Defer - Trans_Enumerate_FillFrom_Path(state, ce.p, pp); + Trans_Enumerate_FillFrom_Path(state, *ce.p, pp); ), (ItemAddr, - Trans_Enumerate_FillFrom_Path(state, ce, pp); + Trans_Enumerate_FillFrom_Path(state, *ce, pp); ) ) } diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index cf101443..50924e2f 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -71,15 +71,15 @@ namespace { ), (Const, return ::MIR::Constant::make_Const({ - params.monomorph(resolve, ce.p) + box$(params.monomorph(resolve, *ce.p)) }); ), (ItemAddr, - auto p = params.monomorph(resolve, ce); + auto p = params.monomorph(resolve, *ce); // TODO: If this is a pointer to a function on a trait object, replace with the address loaded from the vtable. // - Requires creating a new temporary for the vtable pointer. // - Also requires knowing what the receiver is. - return ::MIR::Constant( mv$(p) ); + return ::MIR::Constant( box$(p) ); ) ) throw ""; -- cgit v1.2.3 From dab72ad78160ecd2a4d1759174cee837a5bedcbc Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 2 Jun 2019 11:55:02 +0800 Subject: MIR - Refactor LValue to reduce size and linked-list-ness (seems to have had a ~10% reduction in memory usage) --- Notes/MIR-PackedLValue.txt | 65 ++++ src/hir/deserialise.cpp | 32 +- src/hir/serialise.cpp | 41 +-- src/hir_conv/bind.cpp | 27 +- src/hir_conv/constant_evaluation.cpp | 112 +++---- src/include/tagged_union.hpp | 7 +- src/mir/check.cpp | 173 +++++----- src/mir/check_full.cpp | 230 ++++++-------- src/mir/cleanup.cpp | 82 +++-- src/mir/dump.cpp | 35 +- src/mir/from_hir.cpp | 76 ++--- src/mir/from_hir.hpp | 15 +- src/mir/from_hir_match.cpp | 112 +++---- src/mir/helpers.cpp | 135 ++++---- src/mir/helpers.hpp | 11 +- src/mir/mir.cpp | 189 ++++------- src/mir/mir.hpp | 402 ++++++++++++++++++----- src/mir/mir_builder.cpp | 597 ++++++++++++++++------------------- src/mir/optimise.cpp | 587 ++++++++++++++++++---------------- src/trans/auto_impls.cpp | 20 +- src/trans/codegen_c.cpp | 287 +++++++++-------- src/trans/codegen_mmir.cpp | 103 +++--- src/trans/enumerate.cpp | 340 ++++++-------------- src/trans/monomorphise.cpp | 40 +-- 24 files changed, 1863 insertions(+), 1855 deletions(-) create mode 100644 Notes/MIR-PackedLValue.txt (limited to 'src/hir_conv/bind.cpp') diff --git a/Notes/MIR-PackedLValue.txt b/Notes/MIR-PackedLValue.txt new file mode 100644 index 00000000..ce889aee --- /dev/null +++ b/Notes/MIR-PackedLValue.txt @@ -0,0 +1,65 @@ +Problem statement: +- MIR LValues are very common, and suffer from excessive indirection when + dereferences and field accesses are present +- Many MIR analysis passes care most about the inner values +- Pointer chasing ruins cache locality + +Solution: Replace the tagged union tree with a flatteded structure + +Quirk: Indexing takes two LValues to produce one BUT one of those is of a +lesser class, so doesn't need to be treated the same. + + + +Structure proposal: +---- +A LValue is made up of: +- A root value (referencing a local, argument, static, or the return value) +- And a list of wrappers (dereference, field, downcast, index) + +Root values are encoded as a packed pointer/value and tag, with the tag stored in the low 2 bits of the pointer +- This allows a 32-bit pointer to a word to be stored, using the alignment bits as tag +- Arguments and locals are encoded with the argument/local index in the "data" bits +- Return value is encoded as argument `-1` (all 1 bits in data) +- Statics are encoded as a pointer to a `::HIR::Path` + - This adds a new pointer access and allocation vs the existing LValue structure + - HIR::Path already has a bunch of pointers in it, may not hurt that much (and may help by keeping the normal size + of the LValue down) + +Wrappers are stored as a vector of words, packed in a similar way to root values +- Dereference is stored just as an entry (could pack multiple derefs into one, but that would make handling more + difficult) +- Field/Downcast is stored with the field/variant index in the "data" bits +- Indexing is stored as a pointer to a LValue + - ALTERNATIVE: Could require that indexing always uses a local, and just store the local index + - This would vastly reduce complexity in handling the Index wrapper, BUT would add a new statement in some cases + - A quick scan of the MMIR output of libstd crates, shows that the vast majority of indexing cases are with a local + directly. + - Doing so would simplify monomorph/clone/serialise (no need to clone the wrapper list, just copy it). + - Would also improve comparison times + + + +Usecase comparisons +------ +(Using 32-bit architecture) + +NOTES: +- Existing `LValue` structure is 3 words long (1 tag, plus 2 pointers for largest variant) + - WRONG. It's actually far larger due to the ::HIR::Path embedded in it (estimate at least 8 pointers, very likely + more). That should be fixed given the number of LValue-s that exist + - Fixed now, had a slight improvement in compile times (and memory usage?) +- New structure is 4 words long (root value, plus len/cap/ptr for vector) + +- Field access via `&self` + - Old: Field(Deref(Argument(0)), 0) + - 12 + 12 + 12 = 36 bytes w/ 2 pointers + - New: LValue( Argument(0), { Deref, Field(0) } ) + - 16 + 8 = 24 bytes w/ 1 pointer + +- Array stored in `&self` (common in librand) + - `(*arg0).2[var16].0` + - Old: Field( Index(Field(Deref(Argument(0)), 2), Local(16)), 0 ) + - 12 * 5 + 12 = 72 bytes 2/ 5 pointers + - New: LValue( Argument(0), { Deref, Field(2), Index(16), Field(0) } ) + - 16 + 16 = 32 bytes w/ 1 pointer diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 56671a04..35aeacca 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -464,32 +464,15 @@ rv = deserialise_mir_lvalue_(); return rv; } + ::MIR::LValue::Wrapper deserialise_mir_lvalue_wrapper() + { + return ::MIR::LValue::Wrapper::from_inner(m_in.read_count()); + } ::MIR::LValue deserialise_mir_lvalue_() { - switch(auto tag = m_in.read_tag()) - { - #define _(x, ...) case ::MIR::LValue::TAG_##x: return ::MIR::LValue::make_##x( __VA_ARGS__ ); - _(Return, {}) - _(Argument, { static_cast(m_in.read_count()) } ) - _(Local, static_cast(m_in.read_count()) ) - _(Static, box$(deserialise_path()) ) - _(Field, { - box$( deserialise_mir_lvalue() ), - static_cast(m_in.read_count()) - } ) - _(Deref, { box$( deserialise_mir_lvalue() ) }) - _(Index, { - box$( deserialise_mir_lvalue() ), - box$( deserialise_mir_lvalue() ) - } ) - _(Downcast, { - box$( deserialise_mir_lvalue() ), - static_cast(m_in.read_count()) - } ) - #undef _ - default: - BUG(Span(), "Bad tag for MIR::LValue - " << tag); - } + auto root_v = m_in.read_count(); + auto root = (root_v == 3 ? ::MIR::LValue::Storage::new_Static(deserialise_path()) : ::MIR::LValue::Storage::from_inner(root_v)); + return ::MIR::LValue( mv$(root), deserialise_vec<::MIR::LValue::Wrapper>() ); } ::MIR::RValue deserialise_mir_rvalue() { @@ -827,6 +810,7 @@ template<> DEF_D( ::HIR::TraitValueItem, return d.deserialise_traitvalueitem(); ) template<> DEF_D( ::MIR::Param, return d.deserialise_mir_param(); ) + template<> DEF_D( ::MIR::LValue::Wrapper, return d.deserialise_mir_lvalue_wrapper(); ) template<> DEF_D( ::MIR::LValue, return d.deserialise_mir_lvalue(); ) template<> DEF_D( ::MIR::Statement, return d.deserialise_mir_statement(); ) template<> DEF_D( ::MIR::BasicBlock, return d.deserialise_mir_basicblock(); ) diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index c15630d9..fc53e245 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -722,35 +722,18 @@ void serialise(const ::MIR::LValue& lv) { TRACE_FUNCTION_F("LValue = "<(lv.tag()) ); - TU_MATCHA( (lv), (e), - (Return, - ), - (Argument, - m_out.write_count(e.idx); - ), - (Local, - m_out.write_count(e); - ), - (Static, - serialise_path(*e); - ), - (Field, - serialise(e.val); - m_out.write_count(e.field_index); - ), - (Deref, - serialise(e.val); - ), - (Index, - serialise(e.val); - serialise(e.idx); - ), - (Downcast, - serialise(e.val); - m_out.write_count(e.variant_index); - ) - ) + if( lv.m_root.is_Static() ) { + m_out.write_count(3); + serialise_path(lv.m_root.as_Static()); + } + else { + m_out.write_count( lv.m_root.get_inner() ); + } + serialise_vec(lv.m_wrappers); + } + void serialise(const ::MIR::LValue::Wrapper& w) + { + m_out.write_count(w.get_inner()); } void serialise(const ::MIR::RValue& val) { diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 84854315..e3441157 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -704,30 +704,9 @@ namespace { struct H { static void visit_lvalue(Visitor& upper_visitor, ::MIR::LValue& lv) { - TU_MATCHA( (lv), (e), - (Return, - ), - (Local, - ), - (Argument, - ), - (Static, - upper_visitor.visit_path(*e, ::HIR::Visitor::PathContext::VALUE); - ), - (Field, - H::visit_lvalue(upper_visitor, *e.val); - ), - (Deref, - H::visit_lvalue(upper_visitor, *e.val); - ), - (Index, - H::visit_lvalue(upper_visitor, *e.val); - H::visit_lvalue(upper_visitor, *e.idx); - ), - (Downcast, - H::visit_lvalue(upper_visitor, *e.val); - ) - ) + if( lv.m_root.is_Static() ) { + upper_visitor.visit_path(lv.m_root.as_Static(), ::HIR::Visitor::PathContext::VALUE); + } } static void visit_constant(Visitor& upper_visitor, ::MIR::Constant& e) { diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index b97a6ae0..500ac490 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -293,61 +293,66 @@ namespace HIR { ::HIR::Literal& get_lval(const ::MIR::LValue& lv) { - TU_MATCHA( (lv), (e), + ::HIR::Literal* lit_ptr; + TRACE_FUNCTION_FR(lv, *lit_ptr); + TU_MATCHA( (lv.m_root), (e), (Return, - return retval; + lit_ptr = &retval; ), (Local, - if( e >= locals.size() ) - MIR_BUG(state, "Local index out of range - " << e << " >= " << locals.size()); - return locals[e]; + MIR_ASSERT(state, e < locals.size(), "Local index out of range - " << e << " >= " << locals.size()); + lit_ptr = &locals[e]; ), (Argument, - if( e.idx >= args.size() ) - MIR_BUG(state, "Local index out of range - " << e.idx << " >= " << args.size()); - return args[e.idx]; + MIR_ASSERT(state, e < args.size(), "Argument index out of range - " << e << " >= " << args.size()); + lit_ptr = &args[e]; ), (Static, - MIR_TODO(state, "LValue::Static - " << *e); - ), - (Field, - auto& val = get_lval(*e.val); - MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv); - auto& vals = val.as_List(); - MIR_ASSERT(state, e.field_index < vals.size(), "LValue::Field index out of range"); - return vals[ e.field_index ]; - ), - (Deref, - auto& val = get_lval(*e.val); - TU_MATCH_DEF( ::HIR::Literal, (val), (ve), - ( - MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }"); - ), - (BorrowData, - return *ve; - ), - (String, - // Just clone the string (hack) - // - TODO: Create a list? - return val; - ) - ) - ), - (Index, - auto& val = get_lval(*e.val); - MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv); - auto& idx = get_lval(*e.idx); - MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv); - auto& vals = val.as_List(); - auto idx_v = static_cast( idx.as_Integer() ); - MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range"); - return vals[ idx_v ]; - ), - (Downcast, - MIR_TODO(state, "LValue::Downcast - " << lv); + MIR_TODO(state, "LValue::Static - " << e); ) ) - throw ""; + + for(const auto& w : lv.m_wrappers) + { + auto& val = *lit_ptr; + TU_MATCH_HDRA( (w), {) + TU_ARMA(Field, e) { + MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv); + auto& vals = val.as_List(); + MIR_ASSERT(state, e < vals.size(), "LValue::Field index out of range"); + lit_ptr = &vals[ e ]; + } + TU_ARMA(Deref, e) { + TU_MATCH_DEF( ::HIR::Literal, (val), (ve), + ( + MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }"); + ), + (BorrowData, + lit_ptr = &*ve; + ), + (String, + // Just clone the string (hack) + // - TODO: Create a list? + lit_ptr = &val; + ) + ) + } + TU_ARMA(Index, e) { + MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv); + MIR_ASSERT(state, e < locals.size(), "LValue::Index index local out of range"); + auto& idx = locals[e]; + MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv); + auto& vals = val.as_List(); + auto idx_v = static_cast( idx.as_Integer() ); + MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range"); + lit_ptr = &vals[ idx_v ]; + } + TU_ARMA(Downcast, e) { + MIR_TODO(state, "LValue::Downcast - " << lv); + } + } + } + return *lit_ptr; } ::HIR::Literal read_lval(const ::MIR::LValue& lv) { @@ -481,17 +486,14 @@ namespace HIR { MIR_BUG(state, "Only shared borrows are allowed in constants"); } - if( e.type != ::HIR::BorrowType::Shared ) { - MIR_BUG(state, "Only shared borrows are allowed in constants"); - } - if( const auto* p = e.val.opt_Deref() ) { - if( p->val->is_Deref() ) - MIR_TODO(state, "Undo nested deref coercion - " << *p->val); - val = local_state.read_lval(*p->val); + if( !e.val.m_wrappers.empty() && e.val.m_wrappers.back().is_Deref() ) { + //if( p->val->is_Deref() ) + // MIR_TODO(state, "Undo nested deref coercion - " << *p->val); + val = local_state.read_lval(e.val.clone_unwrapped()); } - else if( const auto* p = e.val.opt_Static() ) { + else if( e.val.m_wrappers.empty() && e.val.m_root.is_Static() ){ // Borrow of a static, emit BorrowPath with the same path - val = ::HIR::Literal::make_BorrowPath( (*p)->clone() ); + val = ::HIR::Literal::make_BorrowPath( e.val.m_root.as_Static().clone() ); } else { auto inner_val = local_state.read_lval(e.val); diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index dab7f8ea..5a3359b8 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -28,7 +28,6 @@ #define TU_CASE(mod, class, var, name,src, ...) TU_CASE_BODY(mod,class,var, TU_CASE_ITEM(src,mod,var,name) __VA_ARGS__) #define TU_CASE2(mod, class, var, n1,s1, n2,s2, ...) TU_CASE_BODY(mod,class,var, TU_CASE_ITEM(s1,mod,var,n1) TU_CASE_ITEM(s2,mod,var,n2) __VA_ARGS__) - // Argument iteration #define TU_DISP0(n) #define TU_DISP1(n, _1) n _1 @@ -105,7 +104,7 @@ */ TU_MATCH_ARMS(CLASS, VAR, NAME, __VA_ARGS__)/* */ default: {TU_EXP DEF;} break;/* */} -#define TU_MATCH_BIND1(TAG, VAR, NAME) /*MATCH_BIND*/ auto& NAME = (VAR).as_##TAG(); (void)&NAME; +#define TU_MATCH_BIND1(TAG, VAR, NAME) /*MATCH_BIND*/ decltype((VAR).as_##TAG()) NAME = (VAR).as_##TAG(); (void)&NAME; #define TU_MATCH_BIND2_(TAG, v1,v2, n1,n2) TU_MATCH_BIND1(TAG, v1, n1) TU_MATCH_BIND1(TAG, v2, n2) #define TU_MATCH_BIND2(...) TU_EXP1( TU_MATCH_BIND2_(__VA_ARGS__) ) // << Exists to cause expansion of the vars #define TU_MATCH_ARM(CLASS, VAR, NAME, TAG, ...) case CLASS::TAG_##TAG: {/* @@ -119,12 +118,12 @@ #define TU_MATCH_HDR(VARS, brace) TU_MATCH_HDR_(::std::remove_reference::type, VARS, brace) #define TU_MATCH_HDR_(CLASS, VARS, brace) switch( (TU_FIRST VARS).tag() ) brace case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used"); // Evil hack: two for loops, the inner stops the outer after it's done. -#define TU_ARM(VAR, TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = (VAR).as_##TAG(); (void)NAME, tu_lc; tu_lc=false) +#define TU_ARM(VAR, TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(decltype((VAR).as_##TAG()) NAME = (VAR).as_##TAG(); (void)NAME, tu_lc; tu_lc=false) #define TU_MATCH_HDRA(VARS, brace) TU_MATCH_HDRA_(::std::remove_reference::type, VARS, brace) #define TU_MATCH_HDRA_(CLASS, VARS, brace) auto& tu_match_hdr2_v = (TU_FIRST VARS); switch( tu_match_hdr2_v.tag() ) brace case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used"); // Evil hack: two for loops, the inner stops the outer after it's done. -#define TU_ARMA(TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = tu_match_hdr2_v.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) +#define TU_ARMA(TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(decltype(tu_match_hdr2_v.as_##TAG()) NAME = tu_match_hdr2_v.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) //#define TU_TEST(VAL, ...) (VAL.is_##TAG() && VAL.as_##TAG() TEST) #define TU_TEST1(VAL, TAG1, TEST) (VAL.is_##TAG1() && VAL.as_##TAG1() TEST) diff --git a/src/mir/check.cpp b/src/mir/check.cpp index 0b032bbc..6ed34563 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -116,6 +116,11 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn { } + explicit ValStates(const ValStates& v) = default; + ValStates(ValStates&& v) = default; + ValStates& operator=(const ValStates& v) = delete; + ValStates& operator=(ValStates&& v) = default; + void fmt(::std::ostream& os) { os << "ValStates { "; switch(ret_state) @@ -159,12 +164,13 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn return locals.empty() && args.empty(); } + // NOTE: Moves if this state is empty bool merge(unsigned bb_idx, ValStates& other) { DEBUG("bb" << bb_idx << " this=" << FMT_CB(ss,this->fmt(ss);) << ", other=" << FMT_CB(ss,other.fmt(ss);)); if( this->empty() ) { - *this = other; + *this = ValStates(other); return true; } else if( *this == other ) @@ -183,34 +189,38 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn void mark_validity(const ::MIR::TypeResolve& state, const ::MIR::LValue& lv, bool is_valid) { - TU_MATCH_DEF( ::MIR::LValue, (lv), (e), - ( - ), + if( !lv.m_wrappers.empty()) + { + return ; + } + TU_MATCHA( (lv.m_root), (e), (Return, ret_state = is_valid ? State::Valid : State::Invalid; ), (Argument, - MIR_ASSERT(state, e.idx < this->args.size(), "Argument index out of range"); - DEBUG("arg$" << e.idx << " = " << (is_valid ? "Valid" : "Invalid")); - this->args[e.idx] = is_valid ? State::Valid : State::Invalid; + MIR_ASSERT(state, e < this->args.size(), "Argument index out of range " << lv); + DEBUG("arg$" << e << " = " << (is_valid ? "Valid" : "Invalid")); + this->args[e] = is_valid ? State::Valid : State::Invalid; ), (Local, - MIR_ASSERT(state, e < this->locals.size(), "Local index out of range"); + MIR_ASSERT(state, e < this->locals.size(), "Local index out of range - " << lv); DEBUG("_" << e << " = " << (is_valid ? "Valid" : "Invalid")); this->locals[e] = is_valid ? State::Valid : State::Invalid; + ), + (Static, ) ) } void ensure_valid(const ::MIR::TypeResolve& state, const ::MIR::LValue& lv) { - TU_MATCH( ::MIR::LValue, (lv), (e), + TU_MATCHA( (lv.m_root), (e), (Return, if( this->ret_state != State::Valid ) MIR_BUG(state, "Use of non-valid lvalue - " << lv); ), (Argument, - MIR_ASSERT(state, e.idx < this->args.size(), "Arg index out of range"); - if( this->args[e.idx] != State::Valid ) + MIR_ASSERT(state, e < this->args.size(), "Arg index out of range"); + if( this->args[e] != State::Valid ) MIR_BUG(state, "Use of non-valid lvalue - " << lv); ), (Local, @@ -219,27 +229,22 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn MIR_BUG(state, "Use of non-valid lvalue - " << lv); ), (Static, - ), - (Field, - ensure_valid(state, *e.val); - ), - (Deref, - ensure_valid(state, *e.val); - ), - (Index, - ensure_valid(state, *e.val); - ensure_valid(state, *e.idx); - ), - (Downcast, - ensure_valid(state, *e.val); ) ) + + for(const auto& w : lv.m_wrappers) + { + if( w.is_Index() ) + { + if( this->locals[w.as_Index()] != State::Valid ) + MIR_BUG(state, "Use of non-valid lvalue - " << ::MIR::LValue::new_Local(w.as_Index())); + } + } } void move_val(const ::MIR::TypeResolve& state, const ::MIR::LValue& lv) { ensure_valid(state, lv); - ::HIR::TypeRef tmp; - if( ! state.m_resolve.type_is_copy( state.sp, state.get_lvalue_type(tmp, lv) ) ) + if( ! state.lvalue_is_copy(lv) ) { mark_validity(state, lv, false); } @@ -284,20 +289,29 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn ::std::vector path; ValStates state; }; + // TODO: Remove this? The path is useful, but the cloned states are really expensive + // - Option: Keep the paths, but only ever use the pre-set entry state? ::std::vector to_visit_blocks; // TODO: Check that all used locals are also set (anywhere at all) - auto add_to_visit = [&](unsigned int idx, ::std::vector src_path, auto vs) { + auto add_to_visit = [&](unsigned int idx, ::std::vector src_path, ValStates& vs, bool can_move) { for(const auto& b : to_visit_blocks) if( b.bb == idx && b.state == vs) return ; if( block_start_states.at(idx) == vs ) return ; src_path.push_back(idx); - to_visit_blocks.push_back( ToVisit { idx, mv$(src_path), mv$(vs) } ); + // TODO: Update the target block, and only visit if we've induced a change + to_visit_blocks.push_back( ToVisit { idx, mv$(src_path), (can_move ? mv$(vs) : ValStates(vs)) } ); + }; + auto add_to_visit_move = [&](unsigned int idx, ::std::vector src_path, ValStates vs) { + add_to_visit(idx, mv$(src_path), vs, true); + }; + auto add_to_visit_copy = [&](unsigned int idx, ::std::vector src_path, ValStates& vs) { + add_to_visit(idx, mv$(src_path), vs, false); }; - add_to_visit( 0, {}, ValStates { state.m_args.size(), fcn.locals.size() } ); + add_to_visit_move( 0, {}, ValStates { state.m_args.size(), fcn.locals.size() } ); while( to_visit_blocks.size() > 0 ) { auto block = to_visit_blocks.back().bb; @@ -311,7 +325,8 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn if( ! block_start_states.at(block).merge(block, val_state) ) { continue ; } - DEBUG("BB" << block << " via [" << path << "]"); + ASSERT_BUG(Span(), val_state.locals.size() == fcn.locals.size(), ""); + DEBUG("BB" << block << " via [" << path << "] " << FMT_CB(ss,val_state.fmt(ss);)); // 2. Using the newly merged state, iterate statements checking the usage and updating state. const auto& bb = fcn.blocks[block]; @@ -411,13 +426,13 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn // 3. Pass new state on to destination blocks state.set_cur_stmt_term(block); DEBUG(state << bb.terminator); - TU_MATCH(::MIR::Terminator, (bb.terminator), (e), - (Incomplete, + TU_MATCH_HDRA( (bb.terminator), { ) + TU_ARMA(Incomplete, e) { // Should be impossible here. - ), - (Return, + } + TU_ARMA(Return, e) { // Check if the return value has been set - val_state.ensure_valid( state, ::MIR::LValue::make_Return({}) ); + val_state.ensure_valid( state, ::MIR::LValue::new_Return() ); // Ensure that no other non-Copy values are valid for(unsigned int i = 0; i < val_state.locals.size(); i ++) { @@ -432,51 +447,51 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn // TODO: Error, becuase this has just been leaked } } - ), - (Diverge, + } + TU_ARMA(Diverge, e) { // TODO: Ensure that cleanup has been performed. - ), - (Goto, + } + TU_ARMA(Goto, e) { // Push block with the new state - add_to_visit( e, mv$(path), mv$(val_state) ); - ), - (Panic, + add_to_visit_move( e, mv$(path), mv$(val_state) ); + } + TU_ARMA(Panic, e) { // What should be done here? - ), - (If, + } + TU_ARMA(If, e) { // Push blocks val_state.ensure_valid( state, e.cond ); - add_to_visit( e.bb0, path, val_state ); - add_to_visit( e.bb1, mv$(path), mv$(val_state) ); - ), - (Switch, + add_to_visit_copy( e.bb0, path, val_state ); + add_to_visit_move( e.bb1, mv$(path), mv$(val_state) ); + } + TU_ARMA(Switch, e) { val_state.ensure_valid( state, e.val ); for(const auto& tgt : e.targets) { - add_to_visit( tgt, path, val_state ); + add_to_visit( tgt, path, val_state, (&tgt == &e.targets.back()) ); } - ), - (SwitchValue, + } + TU_ARMA(SwitchValue, e) { val_state.ensure_valid( state, e.val ); for(const auto& tgt : e.targets) { - add_to_visit( tgt, path, val_state ); + add_to_visit_copy( tgt, path, val_state ); + } + add_to_visit_move( e.def_target, path, mv$(val_state) ); } - add_to_visit( e.def_target, path, val_state ); - ), - (Call, + TU_ARMA(Call, e) { if( e.fcn.is_Value() ) val_state.ensure_valid( state, e.fcn.as_Value() ); for(const auto& arg : e.args) val_state.move_val( state, arg ); // Push blocks (with return valid only in one) - add_to_visit(e.panic_block, path, val_state); + add_to_visit_copy(e.panic_block, path, val_state); // TODO: If the function returns !, don't follow the ret_block val_state.mark_validity( state, e.ret_val, true ); - add_to_visit(e.ret_block, mv$(path), mv$(val_state)); - ) - ) + add_to_visit_move(e.ret_block, mv$(path), mv$(val_state)); + } + } } } @@ -838,33 +853,33 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path state.set_cur_stmt_term(bb_idx); DEBUG(state << bb.terminator); - TU_MATCH(::MIR::Terminator, (bb.terminator), (e), - (Incomplete, - ), - (Return, + TU_MATCH_HDRA( (bb.terminator), {) + TU_ARMA(Incomplete, e) { + } + TU_ARMA(Return, e) { // TODO: Check if the function can return (i.e. if its return type isn't an empty type) - ), - (Diverge, - ), - (Goto, - ), - (Panic, - ), - (If, + } + TU_ARMA(Diverge, e) { + } + TU_ARMA(Goto, e) { + } + TU_ARMA(Panic, e) { + } + TU_ARMA(If, e) { // Check that condition lvalue is a bool ::HIR::TypeRef tmp; const auto& ty = state.get_lvalue_type(tmp, e.cond); if( ty != ::HIR::CoreType::Bool ) { MIR_BUG(state, "Type mismatch in `If` - expected bool, got " << ty); } - ), - (Switch, + } + TU_ARMA(Switch, e) { // Check that the condition is an enum - ), - (SwitchValue, + } + TU_ARMA(SwitchValue, e) { // Check that the condition's type matches the values - ), - (Call, + } + TU_ARMA(Call, e) { if( e.fcn.is_Value() ) { ::HIR::TypeRef tmp; @@ -875,8 +890,8 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path } } // Typecheck arguments and return value - ) - ) + } + } } } diff --git a/src/mir/check_full.cpp b/src/mir/check_full.cpp index 24a4930a..0cc83c6f 100644 --- a/src/mir/check_full.cpp +++ b/src/mir/check_full.cpp @@ -446,68 +446,54 @@ namespace } const State& get_lvalue_state(const ::MIR::TypeResolve& mir_res, const ::MIR::LValue& lv) const { - TU_MATCHA( (lv), (e), + const State* state_p = nullptr; + TU_MATCHA( (lv.m_root), (e), (Return, - return return_value; + state_p = &return_value; ), (Argument, - return args.at(e.idx); + state_p = &args.at(e); ), (Local, - return locals.at(e); + state_p = &locals.at(e); ), (Static, static State state_of_static(true); return state_of_static; - ), - (Field, - const auto& vs = get_lvalue_state(mir_res, *e.val); - if( vs.is_composite() ) - { - const auto& states = this->get_composite(mir_res, vs); - MIR_ASSERT(mir_res, e.field_index < states.size(), "Field index out of range"); - return states[e.field_index]; - } - else - { - return vs; + ) + ) + + for(const auto& w : lv.m_wrappers) + { + if( state_p->is_composite() ) { + break; } - ), - (Deref, - const auto& vs = get_lvalue_state(mir_res, *e.val); - if( vs.is_composite() ) - { + const auto& vs = *state_p; + state_p = nullptr; + + TU_MATCHA( (w), (e), + (Field, + const auto& states = this->get_composite(mir_res, vs); + MIR_ASSERT(mir_res, e < states.size(), "Field index out of range"); + state_p = &states[e]; + ), + (Deref, MIR_TODO(mir_res, "Deref with composite state"); - } - else - { - return vs; - } - ), - (Index, - const auto& vs_v = get_lvalue_state(mir_res, *e.val); - const auto& vs_i = get_lvalue_state(mir_res, *e.idx); - MIR_ASSERT(mir_res, !vs_v.is_composite(), ""); - MIR_ASSERT(mir_res, !vs_i.is_composite(), ""); - //return State(vs_v.is_valid() && vs_i.is_valid()); - MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalidated value"); - return vs_v; - ), - (Downcast, - const auto& vs_v = get_lvalue_state(mir_res, *e.val); - if( vs_v.is_composite() ) - { - const auto& states = this->get_composite(mir_res, vs_v); - MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << StateFmt(*this, vs_v)); - return states[0]; - } - else - { - return vs_v; - } + ), + (Index, + const auto& vs_i = get_lvalue_state(mir_res, ::MIR::LValue::new_Local(e)); + MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalidated value"); + MIR_BUG(mir_res, "Indexing a composite state"); + ), + (Downcast, + const auto& states = this->get_composite(mir_res, vs); + MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << StateFmt(*this, vs)); + state_p = &states[0]; + ) ) - ) - throw ""; + assert(state_p); + } + return *state_p; } void clear_state(const ::MIR::TypeResolve& mir_res, State& s) { @@ -522,42 +508,47 @@ namespace void set_lvalue_state(const ::MIR::TypeResolve& mir_res, const ::MIR::LValue& lv, State new_vs) { TRACE_FUNCTION_F(lv << " = " << StateFmt(*this, new_vs) << " (from " << StateFmt(*this, get_lvalue_state(mir_res, lv)) << ")"); - TU_MATCHA( (lv), (e), + State* state_p = nullptr; + TU_MATCHA( (lv.m_root), (e), (Return, - this->clear_state(mir_res, return_value); - return_value = mv$(new_vs); + state_p = &return_value; ), (Argument, - auto& slot = args.at(e.idx); - this->clear_state(mir_res, slot); - slot = mv$(new_vs); + state_p = &args.at(e); ), (Local, - auto& slot = locals.at(e); - this->clear_state(mir_res, slot); - slot = mv$(new_vs); + state_p = &locals.at(e); ), (Static, - // Ignore. - ), - (Field, - const auto& cur_vs = get_lvalue_state(mir_res, *e.val); + return ; + ) + ) + + for(const auto& w : lv.m_wrappers) + { + auto& cur_vs = *state_p; + + // If this is not a composite, and it matches the new state if( !cur_vs.is_composite() && cur_vs == new_vs ) { - // Not a composite, and no state change + // Early return + return; } - else - { - ::std::vector* states_p; + + state_p = nullptr; + TU_MATCHA( (w), (e), + (Field, + // Current isn't a composite, we need to change that if( !cur_vs.is_composite() ) { ::HIR::TypeRef tmp; - const auto& ty = mir_res.get_lvalue_type(tmp, *e.val); + const auto& ty = mir_res.get_lvalue_type(tmp, lv, /*wrapper_skip_count=*/(&lv.m_wrappers.back() - &w)); unsigned int n_fields = 0; if( const auto* e = ty.m_data.opt_Tuple() ) { n_fields = e->size(); } + // TODO: Fixed-size arrays else if( ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Struct() ) { const auto& e = ty.m_data.as_Path().binding.as_Struct(); @@ -573,94 +564,59 @@ namespace ) ) } - else { + else + { MIR_BUG(mir_res, "Unknown type being accessed with Field - " << ty); } - auto new_cur_vs = this->allocate_composite(n_fields, cur_vs); - set_lvalue_state(mir_res, *e.val, State(new_cur_vs)); - states_p = &this->get_composite(mir_res, new_cur_vs); - } - else - { - states_p = &this->get_composite(mir_res, cur_vs); + cur_vs = State(this->allocate_composite(n_fields, cur_vs)); } // Get composite state and assign into it - auto& states = *states_p; - MIR_ASSERT(mir_res, e.field_index < states.size(), "Field index out of range"); - this->clear_state(mir_res, states[e.field_index]); - states[e.field_index] = mv$(new_vs); - } - ), - (Deref, - const auto& cur_vs = get_lvalue_state(mir_res, *e.val); - if( !cur_vs.is_composite() && cur_vs == new_vs ) - { - // Not a composite, and no state change - } - else - { - ::std::vector* states_p; + auto& states = this->get_composite(mir_res, cur_vs); + MIR_ASSERT(mir_res, e< states.size(), "Field index out of range"); + state_p = &states[e]; + ), + (Deref, if( !cur_vs.is_composite() ) { + // TODO: Should this check if the type is Box? //::HIR::TypeRef tmp; //const auto& ty = mir_res.get_lvalue_type(tmp, *e.val); - // TODO: Should this check if the type is Box? - auto new_cur_vs = this->allocate_composite(2, cur_vs); - set_lvalue_state(mir_res, *e.val, State(new_cur_vs)); - states_p = &this->get_composite(mir_res, new_cur_vs); - } - else - { - states_p = &this->get_composite(mir_res, cur_vs); + cur_vs = State(this->allocate_composite(2, cur_vs)); } // Get composite state and assign into it - auto& states = *states_p; + auto& states = this->get_composite(mir_res, cur_vs); MIR_ASSERT(mir_res, states.size() == 2, "Deref with invalid state list size"); - this->clear_state(mir_res, states[1]); - states[1] = mv$(new_vs); - } - ), - (Index, - const auto& vs_v = get_lvalue_state(mir_res, *e.val); - const auto& vs_i = get_lvalue_state(mir_res, *e.idx); - MIR_ASSERT(mir_res, !vs_v.is_composite(), ""); - MIR_ASSERT(mir_res, !vs_i.is_composite(), ""); + state_p = &states[1]; + ), + (Index, + const auto& vs_i = get_lvalue_state(mir_res, ::MIR::LValue::new_Local(e)); + MIR_ASSERT(mir_res, !cur_vs.is_composite(), ""); + MIR_ASSERT(mir_res, !vs_i.is_composite(), ""); - MIR_ASSERT(mir_res, vs_v.is_valid(), "Indexing an invalid value"); - MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalid index"); + MIR_ASSERT(mir_res, cur_vs.is_valid(), "Indexing an invalid value"); + MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalid index"); - // NOTE: Ignore - ), - (Downcast, - const auto& cur_vs = get_lvalue_state(mir_res, *e.val); - if( !cur_vs.is_composite() && cur_vs == new_vs ) - { - // Not a composite, and no state change - } - else - { - ::std::vector* states_p; + // NOTE: Ignore + return ; + ), + (Downcast, if( !cur_vs.is_composite() ) { - auto new_cur_vs = this->allocate_composite(1, cur_vs); - set_lvalue_state(mir_res, *e.val, State(new_cur_vs)); - states_p = &this->get_composite(mir_res, new_cur_vs); + cur_vs = State(this->allocate_composite(1, cur_vs)); } - else - { - states_p = &this->get_composite(mir_res, cur_vs); - } - // Get composite state and assign into it - auto& states = *states_p; - MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << *e.val << " - " << this->fmt_state(mir_res, *e.val)); + auto& states = this->get_composite(mir_res, cur_vs); + MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << lv << " - " << StateFmt(*this, cur_vs)); this->clear_state(mir_res, states[0]); states[0] = mv$(new_vs); - } + ) ) - ) + assert(state_p); + } + this->clear_state(mir_res, *state_p); + *state_p = mv$(new_vs); } }; @@ -939,7 +895,7 @@ void MIR_Validate_FullValState(::MIR::TypeResolve& mir_res, const ::MIR::Functio (Incomplete, ), (Return, - state.ensure_lvalue_valid(mir_res, ::MIR::LValue::make_Return({})); + state.ensure_lvalue_valid(mir_res, ::MIR::LValue::new_Return()); if( ENABLE_LEAK_DETECTOR ) { auto ensure_dropped = [&](const State& s, const ::MIR::LValue& lv) { @@ -955,10 +911,10 @@ void MIR_Validate_FullValState(::MIR::TypeResolve& mir_res, const ::MIR::Functio } }; for(unsigned i = 0; i < state.locals.size(); i ++ ) { - ensure_dropped(state.locals[i], ::MIR::LValue::make_Local(i)); + ensure_dropped(state.locals[i], ::MIR::LValue::new_Local(i)); } for(unsigned i = 0; i < state.args.size(); i ++ ) { - ensure_dropped(state.args[i], ::MIR::LValue::make_Argument({i})); + ensure_dropped(state.args[i], ::MIR::LValue::new_Argument(i)); } } ), diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 5d32d0c8..b535c7ce 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -33,7 +33,7 @@ struct MirMutator ::MIR::LValue new_temporary(::HIR::TypeRef ty) { - auto rv = ::MIR::LValue::make_Local( static_cast(m_fcn.locals.size()) ); + auto rv = ::MIR::LValue::new_Local( static_cast(m_fcn.locals.size()) ); m_fcn.locals.push_back( mv$(ty) ); return rv; } @@ -493,12 +493,13 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con // Allocate a temporary for the vtable pointer itself auto vtable_lv = mutator.new_temporary( mv$(vtable_ty) ); // - Load the vtable and store it - auto ptr_lv = ::MIR::LValue::make_Deref({ box$(receiver_lvp.clone()) }); + auto ptr_lv = ::MIR::LValue::new_Deref( receiver_lvp.clone() ); MIR_Cleanup_LValue(state, mutator, ptr_lv); - auto vtable_rval = ::MIR::RValue::make_DstMeta({ mv$(*ptr_lv.as_Deref().val) }); + ptr_lv.m_wrappers.pop_back(); + auto vtable_rval = ::MIR::RValue::make_DstMeta({ mv$(ptr_lv) }); mutator.push_statement( ::MIR::Statement::make_Assign({ vtable_lv.clone(), mv$(vtable_rval) }) ); - auto fcn_lval = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(vtable_lv) })), vtable_idx }); + auto fcn_lval = ::MIR::LValue::new_Field( ::MIR::LValue::new_Deref( mv$(vtable_lv) ), vtable_idx ); ::HIR::TypeRef tmp; const auto& ty = state.get_lvalue_type(tmp, fcn_lval); @@ -526,23 +527,23 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con ), (Tuple, for(unsigned int i = 0; i < se.size(); i ++ ) { - auto val = (i == se.size() - 1 ? mv$(lv) : lv.clone()); + auto val = ::MIR::LValue::new_Field( (i == se.size() - 1 ? mv$(lv) : lv.clone()), i ); if( i == str.m_struct_markings.coerce_unsized_index ) { - vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].ent), ::MIR::LValue::make_Field({ box$(val), i }) ) ); + vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].ent), mv$(val)) ); } else { - vals.push_back( ::MIR::LValue::make_Field({ box$(val), i }) ); + vals.push_back( mv$(val) ); } } ), (Named, for(unsigned int i = 0; i < se.size(); i ++ ) { - auto val = (i == se.size() - 1 ? mv$(lv) : lv.clone()); + auto val = ::MIR::LValue::new_Field( (i == se.size() - 1 ? mv$(lv) : lv.clone()), i ); if( i == str.m_struct_markings.coerce_unsized_index ) { - vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].second.ent), ::MIR::LValue::make_Field({ box$(val), i }) ) ); + vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].second.ent), mv$(val) ) ); } else { - vals.push_back( ::MIR::LValue::make_Field({ box$(val), i }) ); + vals.push_back( mv$(val) ); } } ) @@ -777,7 +778,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& auto ty_d = monomorphise_type_with(state.sp, se[i].ent, monomorph_cb_d, false); auto ty_s = monomorphise_type_with(state.sp, se[i].ent, monomorph_cb_s, false); - auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::make_Field({ box$(value.clone()), i })); + auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::new_Field(value.clone(), i)); auto new_lval = mutator.in_temporary( mv$(ty_d), mv$(new_rval) ); ents.push_back( mv$(new_lval) ); @@ -793,7 +794,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& } else { - ents.push_back( ::MIR::LValue::make_Field({ box$(value.clone()), i}) ); + ents.push_back( ::MIR::LValue::new_Field(value.clone(), i) ); } } ), @@ -806,7 +807,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& auto ty_d = monomorphise_type_with(state.sp, se[i].second.ent, monomorph_cb_d, false); auto ty_s = monomorphise_type_with(state.sp, se[i].second.ent, monomorph_cb_s, false); - auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::make_Field({ box$(value.clone()), i })); + auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::new_Field(value.clone(), i)); auto new_lval = mutator.new_temporary( mv$(ty_d) ); mutator.push_statement( ::MIR::Statement::make_Assign({ new_lval.clone(), mv$(new_rval) }) ); @@ -823,7 +824,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& } else { - ents.push_back( ::MIR::LValue::make_Field({ box$(value.clone()), i}) ); + ents.push_back( ::MIR::LValue::new_Field(value.clone(), i) ); } } ) @@ -865,7 +866,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, ::MIR::LValue& lval) { - TU_MATCHA( (lval), (le), + TU_MATCHA( (lval.m_root), (le), (Return, ), (Argument, @@ -873,30 +874,22 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, :: (Local, ), (Static, - ), - (Field, - MIR_Cleanup_LValue(state, mutator, *le.val); - ), - (Deref, - MIR_Cleanup_LValue(state, mutator, *le.val); - ), - (Index, - MIR_Cleanup_LValue(state, mutator, *le.val); - MIR_Cleanup_LValue(state, mutator, *le.idx); - ), - (Downcast, - MIR_Cleanup_LValue(state, mutator, *le.val); ) ) - // If this is a deref of Box, unpack and deref the inner pointer - if( lval.is_Deref() ) + for(size_t i = 0; i < lval.m_wrappers.size(); i ++) { - auto& le = lval.as_Deref(); + if( !lval.m_wrappers[i].is_Deref() ) { + continue ; + } + + // If this is a deref of Box, unpack and deref the inner pointer ::HIR::TypeRef tmp; - const auto& ty = state.get_lvalue_type(tmp, *le.val); + const auto& ty = state.get_lvalue_type(tmp, lval, lval.m_wrappers.size() - i); if( state.m_resolve.is_type_owned_box(ty) ) { + unsigned num_injected_fld_zeros = 0; + // Handle Box by extracting it to its pointer. // - Locate (or remember) which field in Box is the pointer, and replace the inner by that field // > Dumb idea, assume it's always the first field. Keep accessing until located. @@ -924,11 +917,16 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, :: tmp = monomorphise_type(state.sp, str.m_params, te.path.m_data.as_Generic().m_params, *ty_tpl); typ = &tmp; - auto new_lval = ::MIR::LValue::make_Field({ mv$(le.val), 0 }); - le.val = box$(new_lval); + num_injected_fld_zeros ++; } MIR_ASSERT(state, typ->m_data.is_Pointer(), "First non-path field in Box wasn't a pointer - " << *typ); // We have reached the pointer. Good. + + // Inject all of the field zero accesses (before the deref) + while(num_injected_fld_zeros--) + { + lval.m_wrappers.insert( lval.m_wrappers.begin() + i, ::MIR::LValue::Wrapper::new_Field(0) ); + } } } } @@ -1030,9 +1028,9 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ), (DstMeta, // HACK: Ensure that the box Deref conversion fires here. - auto v = ::MIR::LValue::make_Deref({ box$(re.val) }); - MIR_Cleanup_LValue(state, mutator, v); - re.val = mv$( *v.as_Deref().val ); + re.val.m_wrappers.push_back( ::MIR::LValue::Wrapper::new_Deref() ); + MIR_Cleanup_LValue(state, mutator, re.val); + re.val.m_wrappers.pop_back(); // If the type is an array (due to a monomorpised generic?) then replace. ::HIR::TypeRef tmp; @@ -1053,9 +1051,9 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ), (DstPtr, // HACK: Ensure that the box Deref conversion fires here. - auto v = ::MIR::LValue::make_Deref({ box$(re.val) }); - MIR_Cleanup_LValue(state, mutator, v); - re.val = mv$( *v.as_Deref().val ); + re.val.m_wrappers.push_back( ::MIR::LValue::Wrapper::new_Deref() ); + MIR_Cleanup_LValue(state, mutator, re.val); + re.val.m_wrappers.pop_back(); ), (MakeDst, MIR_Cleanup_Param(state, mutator, re.ptr_val); @@ -1218,13 +1216,13 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, e.args.reserve( fcn_ty.m_arg_types.size() ); for(unsigned int i = 0; i < fcn_ty.m_arg_types.size(); i ++) { - e.args.push_back( ::MIR::LValue::make_Field({ box$(args_lvalue.clone()), i }) ); + e.args.push_back( ::MIR::LValue::new_Field(args_lvalue.clone(), i) ); } // If the trait is Fn/FnMut, dereference the input value. if( pe.trait.m_path == resolve.m_lang_FnOnce ) e.fcn = mv$(fcn_lvalue); else - e.fcn = ::MIR::LValue::make_Deref({ box$(fcn_lvalue) }); + e.fcn = ::MIR::LValue::new_Deref( mv$(fcn_lvalue) ); } } ) diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index b02c1e5b..69ffa850 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -176,40 +176,7 @@ namespace { #undef FMT } void fmt_val(::std::ostream& os, const ::MIR::LValue& lval) { - TU_MATCHA( (lval), (e), - (Return, - os << "RETURN"; - ), - (Argument, - os << "arg$" << e.idx; - ), - (Local, - os << "_$" << e; - ), - (Static, - os << *e; - ), - (Field, - os << "("; - fmt_val(os, *e.val); - os << ")." << e.field_index; - ), - (Deref, - os << "*"; - fmt_val(os, *e.val); - ), - (Index, - os << "("; - fmt_val(os, *e.val); - os << ")["; - fmt_val(os, *e.idx); - os << "]"; - ), - (Downcast, - fmt_val(os, *e.val); - os << " as variant" << e.variant_index; - ) - ) + os << lval; } void fmt_val(::std::ostream& os, const ::MIR::Constant& e) { TU_MATCHA( (e), (ce), diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 9e749811..d511a32a 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -177,7 +177,7 @@ namespace { for(size_t i = 0; i < pat.m_binding.m_implicit_deref_count; i ++) { - lval = ::MIR::LValue::make_Deref({ box$(lval) }); + lval = ::MIR::LValue::new_Deref(mv$(lval)); } switch( pat.m_binding.m_type ) @@ -215,35 +215,35 @@ namespace { for(size_t i = 0; i < pat.m_implicit_deref_count; i ++) { - lval = ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }); + lval = ::MIR::LValue::new_Deref(mv$(lval)); } TU_MATCH_HDRA( (pat.m_data), {) TU_ARMA(Any, e) { } TU_ARMA(Box, e) { - destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); + destructure_from_ex(sp, *e.sub, ::MIR::LValue::new_Deref(mv$(lval)), allow_refutable); } TU_ARMA(Ref, e) { - destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); + destructure_from_ex(sp, *e.sub, ::MIR::LValue::new_Deref(mv$(lval)), allow_refutable); } TU_ARMA(Tuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { - destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable); } } TU_ARMA(SplitTuple, e) { assert(e.total_size >= e.leading.size() + e.trailing.size()); for(unsigned int i = 0; i < e.leading.size(); i ++ ) { - destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable); } // TODO: Is there a binding in the middle? unsigned int ofs = e.total_size - e.trailing.size(); for(unsigned int i = 0; i < e.trailing.size(); i ++ ) { - destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), ofs+i}), allow_refutable); + destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Field(lval.clone(), ofs+i), allow_refutable); } } TU_ARMA(StructValue, e) { @@ -252,7 +252,7 @@ namespace { TU_ARMA(StructTuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { - destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable); } } TU_ARMA(Struct, e) { @@ -264,7 +264,7 @@ namespace { for(const auto& fld_pat : e.sub_patterns) { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); - destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval.clone() ), idx}), allow_refutable); + destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable); } } } @@ -302,10 +302,10 @@ namespace { ERROR(sp, E0000, "Variant " << variants[i].name << " not handled"); } } - auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); + auto lval_var = ::MIR::LValue::new_Downcast(mv$(lval), e.binding_idx); for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { - destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval_var.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval_var.clone(), i), allow_refutable); } } TU_ARMA(EnumStruct, e) { @@ -316,11 +316,11 @@ namespace { const auto& str = *var.type.m_data.as_Path().binding.as_Struct(); ASSERT_BUG(sp, str.m_data.is_Named(), "Struct pattern on non-Named struct - " << e.path); const auto& fields = str.m_data.as_Named(); - auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); + auto lval_var = ::MIR::LValue::new_Downcast(mv$(lval), e.binding_idx); for(const auto& fld_pat : e.sub_patterns) { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); - destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval_var.clone() ), idx}), allow_refutable); + destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::new_Field(lval_var.clone(), idx), allow_refutable); } } TU_ARMA(Slice, e) { @@ -335,7 +335,7 @@ namespace { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++) { const auto& subpat = e.sub_patterns[i]; - destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable ); + destructure_from_ex(sp, subpat, ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable ); } } else @@ -346,7 +346,7 @@ namespace { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++) { const auto& subpat = e.sub_patterns[i]; - destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable ); + destructure_from_ex(sp, subpat, ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable ); } } } @@ -374,7 +374,7 @@ namespace { for(unsigned int i = 0; i < e.leading.size(); i ++) { unsigned int idx = 0 + i; - destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); + destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable ); } if( e.extra_bind.is_valid() ) { @@ -383,7 +383,7 @@ namespace { for(unsigned int i = 0; i < e.trailing.size(); i ++) { unsigned int idx = array_size - e.trailing.size() + i; - destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); + destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable ); } } else @@ -409,13 +409,13 @@ namespace { ::MIR::LValue len_lval; if( e.extra_bind.is_valid() || e.trailing.size() > 0 ) { - len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, lval).clone() })); + len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, lval) })); } for(unsigned int i = 0; i < e.leading.size(); i ++) { unsigned int idx = i; - destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); + destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable ); } if( e.extra_bind.is_valid() ) { @@ -427,7 +427,7 @@ namespace { ::HIR::BorrowType bt = H::get_borrow_type(sp, e.extra_bind); ::MIR::LValue ptr_val = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef::new_borrow( bt, inner_type.clone() ), - ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::make_Field({ box$(lval.clone()), static_cast(e.leading.size()) }) }) + ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::new_Field( lval.clone(), static_cast(e.leading.size()) ) }) ); // TODO: Cast to raw pointer? Or keep as a borrow? @@ -442,7 +442,7 @@ namespace { auto sub_val = ::MIR::Param(::MIR::Constant::make_Uint({ e.trailing.size() - i, ::HIR::CoreType::Usize })); ::MIR::LValue ofs_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ len_lval.clone(), ::MIR::eBinOp::SUB, mv$(sub_val) }) ); // Recurse with the indexed value - destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Index({ box$(lval.clone()), box$(ofs_val) }), allow_refutable); + destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Index( lval.clone(), ofs_val.m_root.as_Local() ), allow_refutable); } } } @@ -574,7 +574,7 @@ namespace { TRACE_FUNCTION_F("_Return"); this->visit_node_ptr(node.m_value); - m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Return({}), m_builder.get_result(node.span()) ); + m_builder.push_stmt_assign( node.span(), ::MIR::LValue::new_Return(), m_builder.get_result(node.span()) ); m_builder.terminate_scope_early( node.span(), m_builder.fcn_scope() ); m_builder.end_block( ::MIR::Terminator::make_Return({}) ); } @@ -1474,7 +1474,7 @@ namespace { limit_val = ::MIR::Constant::make_Uint({ e.size_val, ::HIR::CoreType::Usize }); ), (Slice, - limit_val = ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(node.m_value->span(), value).clone() }); + limit_val = ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(node.m_value->span(), value) }); ) ) @@ -1508,7 +1508,13 @@ namespace { m_builder.set_cur_block( arm_continue ); } - m_builder.set_result( node.span(), ::MIR::LValue::make_Index({ box$(value), box$(index) }) ); + if( !index.is_Local()) + { + auto local_idx = m_builder.new_temporary(::HIR::CoreType::Usize); + m_builder.push_stmt_assign(node.span(), local_idx.clone(), mv$(index)); + index = mv$(local_idx); + } + m_builder.set_result( node.span(), ::MIR::LValue::new_Index( mv$(value), index.m_root.as_Local() ) ); } void visit(::HIR::ExprNode_Deref& node) override @@ -1591,7 +1597,7 @@ namespace { } } - m_builder.set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Deref( mv$(val) ) ); } void visit(::HIR::ExprNode_Emplace& node) override @@ -1702,7 +1708,7 @@ namespace { // 3. Get the value and assign it into `place_raw` node.m_value->visit(*this); auto val = m_builder.get_result(node.span()); - m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Deref({ box$(place_raw.clone()) }), mv$(val) ); + m_builder.push_stmt_assign( node.span(), ::MIR::LValue::new_Deref(place_raw.clone()), mv$(val), /*drop_destination=*/false ); // 3. Return a call to `finalize` ::HIR::Path finalize_path(::HIR::GenericPath {}); @@ -1806,9 +1812,7 @@ namespace { auto place = m_builder.new_temporary( place_type ); m_builder.push_stmt_assign(node.span(), place.clone(), ::MIR::RValue::make_Cast({ mv$(place_raw), place_type.clone() })); // 3. Do a non-dropping write into the target location (i.e. just a MIR assignment) - // TODO: This should indicate that the destination shouldn't be dropped, but since drops don't happen on - // reassign currently, that's not yet an issue. - m_builder.push_stmt_assign(node.span(), ::MIR::LValue::make_Deref({box$(place.clone())}), mv$(val)); + m_builder.push_stmt_assign(node.span(), ::MIR::LValue::new_Deref(place.clone()), mv$(val), /*drop_destination=*/false); // 4. Convert the pointer into an `owned_box` auto res_type = ::HIR::TypeRef::new_path(::HIR::GenericPath(lang_owned_box, mv$(trait_params_data)), &m_builder.crate().get_struct_by_path(node.span(), lang_owned_box)); auto res = m_builder.new_temporary(res_type); @@ -2056,20 +2060,20 @@ namespace { unsigned int idx; if( ::std::isdigit(node.m_field.c_str()[0]) ) { ::std::stringstream(node.m_field.c_str()) >> idx; - m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Field( mv$(val), idx ) ); } else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Struct() ) { const auto& str = **bep; const auto& fields = str.m_data.as_Named(); idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin(); - m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Field( mv$(val), idx ) ); } else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Union() ) { const auto& unm = **bep; const auto& fields = unm.m_variants; idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin(); - m_builder.set_result( node.span(), ::MIR::LValue::make_Downcast({ box$(val), idx }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Downcast( mv$(val), idx ) ); } else { BUG(node.span(), "Field access on non-union/struct - " << val_ty); @@ -2202,7 +2206,7 @@ namespace { m_builder.set_result( node.span(), mv$(tmp) ); ), (Static, - m_builder.set_result( node.span(), ::MIR::LValue::make_Static(box$(node.m_path.clone())) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Static(node.m_path.clone()) ); ), (StructConstant, // TODO: Why is this still a PathValue? @@ -2321,7 +2325,7 @@ namespace { ASSERT_BUG(sp, str.m_data.is_Named(), ""); const ::HIR::t_struct_fields& fields = str.m_data.as_Named(); - ::MIR::LValue base_val; + auto base_val = ::MIR::LValue::new_Return(); if( node.m_base_value ) { DEBUG("_StructLiteral - base"); @@ -2362,7 +2366,7 @@ namespace { if( !node.m_base_value) { ERROR(node.span(), E0000, "Field '" << fields[i].first << "' not specified"); } - values[i] = ::MIR::LValue::make_Field({ box$( base_val.clone() ), i }); + values[i] = ::MIR::LValue::new_Field( base_val.clone(), i ); } else { // Partial move support will handle dropping the rest? @@ -2545,7 +2549,7 @@ namespace { else { ev.define_vars_from(ptr->span(), arg.first); - ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::make_Argument({i})); + ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::new_Argument(i)); } i ++; } diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index 194fd0e0..a1f9a10f 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -188,13 +188,10 @@ public: // - Values ::MIR::LValue get_variable(const Span& sp, unsigned idx) const { - // DIASBLED: State tracking doesn't support arguments in loops/splits -#if 1 auto it = m_var_arg_mappings.find(idx); if(it != m_var_arg_mappings.end()) - return ::MIR::LValue::make_Argument({ it->second }); -#endif - return ::MIR::LValue::make_Local( idx ); + return ::MIR::LValue::new_Argument(it->second); + return ::MIR::LValue::new_Local(idx); } ::MIR::LValue new_temporary(const ::HIR::TypeRef& ty); ::MIR::LValue lvalue_or_temp(const Span& sp, const ::HIR::TypeRef& ty, ::MIR::RValue val); @@ -224,7 +221,7 @@ public: // - Statements // Push an assignment. NOTE: This also marks the rvalue as moved - void push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val); + void push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val, bool drop_destination=true); // Push a drop (likely only used by scope cleanup) void push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int drop_flag=~0u); // Push a shallow drop (for Box) @@ -296,7 +293,7 @@ private: const VarState& get_slot_state(const Span& sp, unsigned int idx, SlotType type, unsigned int skip_count=0) const; VarState& get_slot_state_mut(const Span& sp, unsigned int idx, SlotType type); - const VarState& get_val_state(const Span& sp, const ::MIR::LValue& lv, unsigned int skip_count=0); + VarState* get_val_state_mut_p(const Span& sp, const ::MIR::LValue& lv); VarState& get_val_state_mut(const Span& sp, const ::MIR::LValue& lv); void terminate_loop_early(const Span& sp, ScopeType::Data_Loop& sd_loop); @@ -306,11 +303,11 @@ private: void complete_scope(ScopeDef& sd); public: - void with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb) const; + void with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb, const ::MIR::LValue::Wrapper* stop_wrapper=nullptr) const; bool lvalue_is_copy(const Span& sp, const ::MIR::LValue& lv) const; // Obtain the base fat poiner for a dst reference. Errors if it wasn't via a fat pointer - const ::MIR::LValue& get_ptr_to_dst(const Span& sp, const ::MIR::LValue& lv) const; + ::MIR::LValue get_ptr_to_dst(const Span& sp, const ::MIR::LValue& lv) const; }; class MirConverter: diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index e3ddce30..2bfb1a27 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -1732,13 +1732,13 @@ namespace { ), (Tuple, ASSERT_BUG(sp, idx < e.size(), "Tuple index out of range"); - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); cur_ty = &e[idx]; ), (Path, if( idx == FIELD_DEREF ) { // TODO: Check that the path is Box - lval = ::MIR::LValue::make_Deref({ box$(lval) }); + lval = ::MIR::LValue::new_Deref( mv$(lval) ); cur_ty = &e.path.m_data.as_Generic().m_params.m_types.at(0); break; } @@ -1773,7 +1773,7 @@ namespace { else { cur_ty = &fld.ent; } - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); ), (Named, assert( idx < fields.size() ); @@ -1785,7 +1785,7 @@ namespace { else { cur_ty = &fld.ent; } - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); ) ) ), @@ -1804,7 +1804,7 @@ namespace { else { cur_ty = &fld.second.ent; } - lval = ::MIR::LValue::make_Downcast({ box$(lval), idx }); + lval = ::MIR::LValue::new_Downcast(mv$(lval), idx); ), (Enum, auto monomorph_to_ptr = [&](const auto& ty)->const auto* { @@ -1824,7 +1824,7 @@ namespace { const auto& var = variants[idx]; cur_ty = monomorph_to_ptr(var.type); - lval = ::MIR::LValue::make_Downcast({ box$(lval), idx }); + lval = ::MIR::LValue::new_Downcast(mv$(lval), idx); ) ) ), @@ -1841,7 +1841,7 @@ namespace { assert(idx < e.size_val); cur_ty = &*e.inner; if( idx < FIELD_INDEX_MAX ) - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); else { idx -= FIELD_INDEX_MAX; idx = FIELD_INDEX_MAX - idx; @@ -1851,16 +1851,16 @@ namespace { (Slice, cur_ty = &*e.inner; if( idx < FIELD_INDEX_MAX ) - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); else { idx -= FIELD_INDEX_MAX; idx = FIELD_INDEX_MAX - idx; // 1. Create an LValue containing the size of this slice subtract `idx` - auto len_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, lval).clone() })); + auto len_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, lval) })); auto sub_val = ::MIR::Param(::MIR::Constant::make_Uint({ idx, ::HIR::CoreType::Usize })); auto ofs_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ mv$(len_lval), ::MIR::eBinOp::SUB, mv$(sub_val) }) ); // 2. Return _Index with that value - lval = ::MIR::LValue::make_Index({ box$(lval), box$(ofs_val) }); + lval = ::MIR::LValue::new_Index(mv$(lval), ofs_val.as_Local()); } ), (Borrow, @@ -1874,7 +1874,7 @@ namespace { cur_ty = &*e.inner; } DEBUG(i << " " << *cur_ty); - lval = ::MIR::LValue::make_Deref({ box$(lval) }); + lval = ::MIR::LValue::new_Deref(mv$(lval)); ), (Pointer, ERROR(sp, E0000, "Attempting to match over a pointer"); @@ -1978,14 +1978,14 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& DEBUG("ty = " << ity << ", val = " << val); const auto& ty = ity; - TU_MATCHA( (ty.m_data), (te), - (Infer, + TU_MATCH_HDRA( (ty.m_data), {) + TU_ARMA(Infer, _te) { BUG(sp, "Hit _ in type - " << ty); - ), - (Diverge, + } + TU_ARMA(Diverge, _te) { BUG(sp, "Matching over !"); - ), - (Primitive, + } + TU_ARMA(Primitive, te) { switch(te) { case ::HIR::CoreType::Bool: { @@ -2152,17 +2152,20 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& case ::HIR::CoreType::Str: { ASSERT_BUG(sp, rule.is_Value() && rule.as_Value().is_StaticString(), ""); const auto& v = rule.as_Value(); + ASSERT_BUG(sp, val.is_Deref(), ""); + val.m_wrappers.pop_back(); + auto str_val = mv$(val); auto succ_bb = builder.new_bb_unlinked(); auto test_val = ::MIR::Param(::MIR::Constant( v.as_StaticString() )); - auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(*val.as_Deref().val), ::MIR::eBinOp::EQ, mv$(test_val) })); + auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(str_val), ::MIR::eBinOp::EQ, mv$(test_val) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) ); builder.set_cur_block(succ_bb); } break; } - ), - (Path, + } + TU_ARMA(Path, te) { TU_MATCHA( (te.binding), (pbe), (Unbound, BUG(sp, "Encounterd unbound path - " << te.path); @@ -2221,26 +2224,26 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& // Recurse with the new ruleset MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, re.sub_rules.data(), re.sub_rules.size(), - var_ty_m, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1, + var_ty_m, ::MIR::LValue::new_Downcast(val.clone(), var_idx), rule.field_path.size()+1, fail_bb ); } ) // TypePathBinding::Enum ) - ), // Type::Data::Path - (Generic, + } // Type::Data::Path + TU_ARMA(Generic, _te) { BUG(sp, "Attempting to match a generic"); - ), - (TraitObject, + } + TU_ARMA(TraitObject, te) { BUG(sp, "Attempting to match a trait object"); - ), - (ErasedType, + } + TU_ARMA(ErasedType, te) { BUG(sp, "Attempting to match an erased type"); - ), - (Array, + } + TU_ARMA(Array, te) { TODO(sp, "Match directly on array?"); - ), - (Slice, + } + TU_ARMA(Slice, te) { ASSERT_BUG(sp, rule.is_Slice() || rule.is_SplitSlice() || (rule.is_Value() && rule.as_Value().is_Bytes()), "Can only match slice with Bytes or Slice rules - " << rule); if( rule.is_Value() ) { ASSERT_BUG(sp, *te.inner == ::HIR::CoreType::U8, "Bytes pattern on non-&[u8]"); @@ -2249,7 +2252,8 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& auto succ_bb = builder.new_bb_unlinked(); - auto inner_val = val.as_Deref().val->clone(); + ASSERT_BUG(sp, val.is_Deref(), "Slice pattern on non-Deref - " << val); + auto inner_val = val.clone_unwrapped(); auto slice_rval = ::MIR::RValue::make_MakeDst({ mv$(cloned_val), mv$(size_val) }); auto test_lval = builder.lvalue_or_temp(sp, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone()), mv$(slice_rval)); @@ -2262,7 +2266,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& // Compare length auto test_val = ::MIR::Param( ::MIR::Constant::make_Uint({ re.len, ::HIR::CoreType::Usize }) ); - auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val).clone() })); + auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val) })); auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::EQ, mv$(test_val) })); auto len_succ_bb = builder.new_bb_unlinked(); @@ -2281,7 +2285,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& // Compare length auto test_val = ::MIR::Param( ::MIR::Constant::make_Uint({ re.min_len, ::HIR::CoreType::Usize}) ); - auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val).clone() })); + auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val) })); auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::LT, mv$(test_val) })); auto len_succ_bb = builder.new_bb_unlinked(); @@ -2302,23 +2306,23 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& else { BUG(sp, "Invalid rule type for slice - " << rule); } - ), - (Tuple, + } // Type::Data::Array + TU_ARMA(Tuple, te) { TODO(sp, "Match directly on tuple?"); - ), - (Borrow, + } + TU_ARMA(Borrow, te) { TODO(sp, "Match directly on borrow?"); - ), // Type::Data::Borrow - (Pointer, + } // Type::Data::Borrow + TU_ARMA(Pointer, te) { BUG(sp, "Attempting to match a pointer - " << rule << " against " << ty); - ), - (Function, + } + TU_ARMA(Function, te) { BUG(sp, "Attempting to match a function pointer - " << rule << " against " << ty); - ), - (Closure, + } + TU_ARMA(Closure, te) { BUG(sp, "Attempting to match a closure"); - ) - ) + } + } } return 0; } @@ -3035,10 +3039,10 @@ void MatchGenGrouped::gen_dispatch__primitive(::HIR::TypeRef ty, ::MIR::LValue v } m_builder.end_block( ::MIR::Terminator::make_Goto(def_blk) ); } break; - case ::HIR::CoreType::Str: + case ::HIR::CoreType::Str: { // Remove the deref on the &str - auto oval = mv$(val); - auto val = mv$(*oval.as_Deref().val); + ASSERT_BUG(sp, !val.m_wrappers.empty() && val.m_wrappers.back().is_Deref(), "&str match on non-Deref lvalue - " << val); + val.m_wrappers.pop_back(); ::std::vector< ::MIR::BasicBlockId> targets; ::std::vector< ::std::string> values; @@ -3062,7 +3066,7 @@ void MatchGenGrouped::gen_dispatch__primitive(::HIR::TypeRef ty, ::MIR::LValue v m_builder.end_block( ::MIR::Terminator::make_SwitchValue({ mv$(val), def_blk, mv$(targets), ::MIR::SwitchValues(mv$(values)) }) ); - break; + } break; } } @@ -3100,7 +3104,7 @@ void MatchGenGrouped::gen_dispatch__enum(::HIR::TypeRef ty, ::MIR::LValue val, c void MatchGenGrouped::gen_dispatch__slice(::HIR::TypeRef ty, ::MIR::LValue val, const ::std::vector& rules, size_t ofs, const ::std::vector<::MIR::BasicBlockId>& arm_targets, ::MIR::BasicBlockId def_blk) { - auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val).clone() })); + auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val) })); // TODO: Re-sort the rules list to interleve Constant::Bytes and Slice @@ -3162,8 +3166,8 @@ void MatchGenGrouped::gen_dispatch__slice(::HIR::TypeRef ty, ::MIR::LValue val, m_builder.set_cur_block(succ_blk); // TODO: What if `val` isn't a Deref? - ASSERT_BUG(sp, val.is_Deref(), "TODO: Handle non-Deref matches of byte strings"); - cmp_lval_eq = this->push_compare( val.as_Deref().val->clone(), ::MIR::eBinOp::EQ, mv$(cmp_slice_val) ); + ASSERT_BUG(sp, !val.m_wrappers.empty() && val.m_wrappers.back().is_Deref(), "TODO: Handle non-Deref matches of byte strings - " << val); + cmp_lval_eq = this->push_compare( val.clone_unwrapped(), ::MIR::eBinOp::EQ, mv$(cmp_slice_val) ); m_builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval_eq), arm_targets[tgt_ofs], def_blk }) ); m_builder.set_cur_block(next_cmp_blk); @@ -3273,7 +3277,7 @@ void MatchGenGrouped::gen_dispatch_splitslice(const field_path_t& field_path, co ASSERT_BUG(sp, ty.m_data.is_Slice(), "SplitSlice pattern on non-slice - " << ty); // Obtain slice length - auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val).clone() })); + auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val) })); // 1. Check that length is sufficient for the pattern to be used // `IF len < min_len : def_blk, next diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 1453acb3..6f0ef891 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -12,9 +12,12 @@ #include #include // ::std::find -void ::MIR::TypeResolve::fmt_pos(::std::ostream& os) const +void ::MIR::TypeResolve::fmt_pos(::std::ostream& os, bool include_path/*=false*/) const { - os << this->m_path << " BB" << this->bb_idx << "/"; + if( include_path ) { + os << this->m_path << " "; + } + os << "BB" << this->bb_idx << "/"; if( this->stmt_idx == STMT_TERM ) { os << "TERM"; } @@ -27,7 +30,7 @@ void ::MIR::TypeResolve::print_msg(const char* tag, ::std::functionget_lvalue_type(tmp, *e.val); + rv = &get_static_type(tmp, e); + ) + ) + assert(wrapper_skip_count <= val.m_wrappers.size()); + const auto* stop_wrapper = &val.m_wrappers[ val.m_wrappers.size() - wrapper_skip_count ]; + for(const auto& w : val.m_wrappers) + { + if( &w == stop_wrapper ) + break; + rv = &this->get_unwrapped_type(tmp, w, *rv); + } + return *rv; +} +const ::HIR::TypeRef& ::MIR::TypeResolve::get_unwrapped_type(::HIR::TypeRef& tmp, const ::MIR::LValue::Wrapper& w, const ::HIR::TypeRef& ty) const +{ + TU_MATCH_HDRA( (w), {) + TU_ARMA(Field, field_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Field access on unexpected type - " << ty); @@ -98,14 +115,14 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return *te.inner; ), (Tuple, - MIR_ASSERT(*this, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size()); - return te[e.field_index]; + MIR_ASSERT(*this, field_index < te.size(), "Field index out of range in tuple " << field_index << " >= " << te.size()); + return te[field_index]; ), (Path, if( const auto* tep = te.binding.opt_Struct() ) { const auto& str = **tep; - auto monomorph = [&](const auto& ty)->const auto& { + auto maybe_monomorph = [&](const auto& ty)->const auto& { if( monomorphise_type_needed(ty) ) { tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, ty); m_resolve.expand_associated_types(sp, tmp); @@ -120,12 +137,12 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c MIR_BUG(*this, "Field on unit-like struct - " << ty); ), (Tuple, - MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct " << te.path); - return monomorph(se[e.field_index].ent); + MIR_ASSERT(*this, field_index < se.size(), "Field index out of range in tuple-struct " << te.path); + return maybe_monomorph(se[field_index].ent); ), (Named, - MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct " << te.path); - return monomorph(se[e.field_index].second.ent); + MIR_ASSERT(*this, field_index < se.size(), "Field index out of range in struct " << te.path); + return maybe_monomorph(se[field_index].second.ent); ) ) } @@ -142,8 +159,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return t; } }; - MIR_ASSERT(*this, e.field_index < unm.m_variants.size(), "Field index out of range for union"); - return maybe_monomorph(unm.m_variants.at(e.field_index).second.ent); + MIR_ASSERT(*this, field_index < unm.m_variants.size(), "Field index out of range for union"); + return maybe_monomorph(unm.m_variants.at(field_index).second.ent); } else { @@ -151,9 +168,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c } ) ) - ), - (Deref, - const auto& ty = this->get_lvalue_type(tmp, *e.val); + } + TU_ARMA(Deref, _e) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Deref on unexpected type - " << ty); @@ -174,9 +190,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return *te.inner; ) ) - ), - (Index, - const auto& ty = this->get_lvalue_type(tmp, *e.val); + } + TU_ARMA(Index, index_local) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Index on unexpected type - " << ty); @@ -188,9 +203,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return *te.inner; ) ) - ), - (Downcast, - const auto& ty = this->get_lvalue_type(tmp, *e.val); + } + TU_ARMA(Downcast, variant_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Downcast on unexpected type - " << ty); @@ -202,8 +216,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c const auto& enm = *te.binding.as_Enum(); MIR_ASSERT(*this, enm.m_data.is_Data(), "Downcast on non-data enum - " << ty); const auto& variants = enm.m_data.as_Data(); - MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range for " << ty); - const auto& variant = variants[e.variant_index]; + MIR_ASSERT(*this, variant_index < variants.size(), "Variant index out of range for " << ty); + const auto& variant = variants[variant_index]; const auto& var_ty = variant.type; if( monomorphise_type_needed(var_ty) ) { @@ -218,12 +232,13 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c else { const auto& unm = *te.binding.as_Union(); - MIR_ASSERT(*this, e.variant_index < unm.m_variants.size(), "Variant index out of range"); - const auto& variant = unm.m_variants[e.variant_index]; + MIR_ASSERT(*this, variant_index < unm.m_variants.size(), "Variant index out of range"); + const auto& variant = unm.m_variants[variant_index]; const auto& var_ty = variant.second.ent; + //return m_resolve.maybe_monomorph(sp, tmp, unm.m_params, te.path.m_data.as_Generic().m_params, var_ty); if( monomorphise_type_needed(var_ty) ) { - tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, variant.second.ent); + tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, var_ty); m_resolve.expand_associated_types(sp, tmp); return tmp; } @@ -233,8 +248,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c } ) ) - ) - ) + } + } throw ""; } const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, const ::MIR::Param& val) const @@ -383,6 +398,15 @@ namespace visit { { if( cb(lv, u) ) return true; +#if 1 + for(const auto& w : lv.m_wrappers) + { + if( w.is_Index() ) + { + cb(LValue::new_Local(w.as_Index()), ValUsage::Read); + } + } +#else TU_MATCHA( (lv), (e), (Return, ), @@ -408,6 +432,7 @@ namespace visit { return visit_mir_lvalue(*e.val, u, cb); ) ) +#endif return false; } @@ -625,32 +650,15 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime(::MIR::TypeResolve& state, c { auto assigned_lvalue = [&](size_t bb_idx, size_t stmt_idx, const ::MIR::LValue& lv) { // NOTE: Fills the first statement after running, just to ensure that any assigned value has _a_ lifetime - if( const auto* de = lv.opt_Local() ) + if( lv.m_root.is_Local() ) { - if( !mask || mask->at(*de) ) + auto de = lv.m_root.as_Local(); + if( !mask || mask->at(de) ) { - MIR_Helper_GetLifetimes_DetermineValueLifetime(state, fcn, bb_idx, stmt_idx, lv, block_offsets, slot_lifetimes[*de]); - slot_lifetimes[*de].fill(block_offsets, bb_idx, stmt_idx, stmt_idx); + MIR_Helper_GetLifetimes_DetermineValueLifetime(state, fcn, bb_idx, stmt_idx, lv, block_offsets, slot_lifetimes[de]); + slot_lifetimes[de].fill(block_offsets, bb_idx, stmt_idx, stmt_idx); } } - else - { - // Not a direct assignment of a slot. But check if a slot is mutated as part of this. - ::MIR::visit::visit_mir_lvalue(lv, ValUsage::Write, [&](const auto& ilv, ValUsage vu) { - if( const auto* de = ilv.opt_Local() ) - { - if( vu == ValUsage::Write ) - { - if( !mask || mask->at(*de) ) - { - MIR_Helper_GetLifetimes_DetermineValueLifetime(state, fcn, bb_idx, stmt_idx, lv, block_offsets, slot_lifetimes[*de]); - slot_lifetimes[*de].fill(block_offsets, bb_idx, stmt_idx, stmt_idx); - } - } - } - return false; - }); - } }; const auto& bb = fcn.blocks[bb_idx]; @@ -673,11 +681,12 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime(::MIR::TypeResolve& state, c else if( const auto* se = stmt.opt_Drop() ) { // HACK: Mark values as valid wherever there's a drop (prevents confusion by simple validator) - if( const auto* de = se->slot.opt_Local() ) + if( se->slot.m_wrappers.empty() && se->slot.m_root.is_Local() ) { - if( !mask || mask->at(*de) ) + auto de = se->slot.m_root.as_Local(); + if( !mask || mask->at(de) ) { - slot_lifetimes[*de].fill(block_offsets, bb_idx, stmt_idx,stmt_idx); + slot_lifetimes[de].fill(block_offsets, bb_idx, stmt_idx,stmt_idx); } } } diff --git a/src/mir/helpers.hpp b/src/mir/helpers.hpp index 58eee9b9..0296a1c4 100644 --- a/src/mir/helpers.hpp +++ b/src/mir/helpers.hpp @@ -104,7 +104,7 @@ public: } unsigned int get_cur_stmt_ofs() const; - void fmt_pos(::std::ostream& os) const; + void fmt_pos(::std::ostream& os, bool include_path=false) const; void print_bug(::std::function cb) const { print_msg("ERROR", cb); } @@ -116,7 +116,14 @@ public: const ::MIR::BasicBlock& get_block(::MIR::BasicBlockId id) const; const ::HIR::TypeRef& get_static_type(::HIR::TypeRef& tmp, const ::HIR::Path& path) const; - const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const; + const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val, unsigned wrapper_skip_count=0) const; + const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue::CRef& val) const { + return get_lvalue_type(tmp, val.lv(), val.lv().m_wrappers.size() - val.wrapper_count()); + } + const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue::MRef& val) const { + return get_lvalue_type(tmp, val.lv(), val.lv().m_wrappers.size() - val.wrapper_count()); + } + const ::HIR::TypeRef& get_unwrapped_type(::HIR::TypeRef& tmp, const ::MIR::LValue::Wrapper& w, const ::HIR::TypeRef& ty) const; const ::HIR::TypeRef& get_param_type(::HIR::TypeRef& tmp, const ::MIR::Param& val) const; ::HIR::TypeRef get_const_type(const ::MIR::Constant& c) const; diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 83f7e1f0..8e3045d6 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -91,119 +91,86 @@ namespace MIR { throw ""; } - ::std::ostream& operator<<(::std::ostream& os, const LValue& x) + void LValue::RefCommon::fmt(::std::ostream& os) const { - TU_MATCHA( (x), (e), + TU_MATCHA( (m_lv->m_root), (e), (Return, os << "retval"; ), (Argument, - os << "a" << e.idx; + os << "a" << e; ), (Local, os << "_" << e; ), (Static, - os << "(" << *e << ")"; - ), - (Field, - os << *e.val << "." << e.field_index; - ), - (Deref, - os << *e.val << "*"; - ), - (Index, - os << *e.val << "[" << *e.idx << "]"; - ), - (Downcast, - os << *e.val << "#" << e.variant_index; + os << "(" << e << ")"; ) ) + for(size_t i = 0; i < m_wrapper_count; i ++) + { + const LValue::Wrapper& w = m_lv->m_wrappers.at(i); + TU_MATCHA( (w), (e), + (Field, + os << "." << e; + ), + (Deref, + os << "*"; + ), + (Index, + os << "[_" << e << "]"; + ), + (Downcast, + os << "#" << e; + ) + ) + } + } + + ::std::ostream& operator<<(::std::ostream& os, const LValue& x) + { + LValue::CRef(x).fmt(os); return os; } - bool operator<(const LValue& a, const LValue& b) + + Ordering LValue::Storage::ord(const LValue::Storage& x) const { - if( a.tag() != b.tag() ) - return a.tag() < b.tag(); - TU_MATCHA( (a, b), (ea, eb), - (Return, - return false; - ), - (Argument, - return ea.idx < eb.idx; - ), - (Local, - return ea < eb; - ), - (Static, - return ea < eb; - ), - (Field, - if( *ea.val != *eb.val ) - return *ea.val < *eb.val; - if( ea.field_index != eb.field_index ) - return ea.field_index < eb.field_index; - return true; - ), - (Deref, - return *ea.val < *eb.val; - ), - (Index, - if( *ea.val != *eb.val ) - return *ea.val < *eb.val; - return *ea.idx < *eb.idx; - ), - (Downcast, - if( *ea.val != *eb.val ) - return *ea.val < *eb.val; - return ea.variant_index < eb.variant_index; - ) - ) - throw ""; + if( x.is_Static() ) + { + if( this->is_Static() ) + return this->as_Static().ord( x.as_Static() ); + else + return OrdLess; + } + else + { + if( this->is_Static() ) + return OrdGreater; + } + + return ::ord(this->val, x.val); } - bool operator==(const LValue& a, const LValue& b) + Ordering LValue::ord(const LValue& x) const { - if( a.tag() != b.tag() ) - return false; - TU_MATCHA( (a, b), (ea, eb), - (Return, - return true; - ), - (Argument, - return ea.idx == eb.idx; - ), - (Local, - return ea == eb; - ), - (Static, - return ea == eb; - ), - (Field, - if( *ea.val != *eb.val ) - return false; - if( ea.field_index != eb.field_index ) - return false; - return true; - ), - (Deref, - return *ea.val == *eb.val; - ), - (Index, - if( *ea.val != *eb.val ) - return false; - if( *ea.idx != *eb.idx ) - return false; - return true; - ), - (Downcast, - if( *ea.val != *eb.val ) - return false; - if( ea.variant_index != eb.variant_index ) - return false; - return true; - ) - ) - throw ""; + auto rv = m_root.ord(x.m_root); + if( rv != OrdEqual ) + return rv; + return ::ord(m_wrappers, x.m_wrappers); + } + Ordering LValue::RefCommon::ord(const LValue::RefCommon& x) const + { + Ordering rv; + //TRACE_FUNCTION_FR(FMT_CB(ss, this->fmt(ss); ss << " ? "; x.fmt(ss);), rv); + rv = m_lv->m_root.ord(x.m_lv->m_root); + if( rv != OrdEqual ) + return rv; + for(size_t i = 0; i < ::std::min(m_wrapper_count, x.m_wrapper_count); i ++) + { + rv = m_lv->m_wrappers[i].ord(x.m_lv->m_wrappers[i]); + if( rv != OrdEqual ) + return rv; + } + return (rv = ::ord(m_wrapper_count, x.m_wrapper_count)); } ::std::ostream& operator<<(::std::ostream& os, const Param& x) @@ -537,30 +504,14 @@ namespace MIR { } } -::MIR::LValue MIR::LValue::clone() const +::MIR::LValue::Storage MIR::LValue::Storage::clone() const { - TU_MATCHA( (*this), (e), - (Return, return LValue(e); ), - (Argument, return LValue(e); ), - (Local, return LValue(e); ), - (Static, return LValue(box$(e->clone())); ), - (Field, return LValue::make_Field({ - box$( e.val->clone() ), - e.field_index - }); ), - (Deref, return LValue::make_Deref({ - box$( e.val->clone() ) - }); ), - (Index, return LValue::make_Index({ - box$( e.val->clone() ), - box$( e.idx->clone() ) - }); ), - (Downcast, return LValue::make_Downcast({ - box$( e.val->clone() ), - e.variant_index - }); ) - ) - throw ""; + if( is_Static() ) { + return new_Static(as_Static().clone()); + } + else { + return Storage(this->val); + } } ::MIR::Constant MIR::Constant::clone() const { diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 63acf89d..f3d61dfa 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -12,21 +12,27 @@ #include // std::unique_ptr #include +class MonomorphState; + namespace MIR { typedef unsigned int RegionId; typedef unsigned int BasicBlockId; -#if 0 -// TODO: Store LValues as: +// Store LValues as: // - A packed root value (one word, using the low bits as an enum descriminator) // - A list of (inner to outer) wrappers struct LValue { class Storage { + public: + const static uintptr_t MAX_ARG = (1 << 30) - 1; // max value of 30 bits + private: + uintptr_t val; - static uintptr_t MAX_ARG = (1 << 30) - 1; // max value of 30 bits + + Storage(uintptr_t v): val(v) {} public: Storage(const Storage&) = delete; Storage& operator=(const Storage&) = delete; @@ -40,41 +46,89 @@ struct LValue this->~Storage(); this->val = x.val; x.val = 0; + return *this; } ~Storage() { if( is_Static() ) { - delete reinterpret_cast<::HIR::Path*>(val & ~3u); + delete reinterpret_cast<::HIR::Path*>(val & ~3ull); val = 0; } } - static Storage new_Return() { return Storage { MAX_ARG << 2 }; } - static Storage new_Argument(unsigned idx) { assert(idx < MAX_ARG); return Storage { idx << 2 }; ) - static Storage new_Local(unsigned idx) { assert(idx <= MAX_ARG); return Storage { (idx << 2) | 1 } }; + static Storage new_Return() { return Storage(0 << 2); } + static Storage new_Argument(unsigned idx) { assert(idx < MAX_ARG); return Storage((idx+1) << 2); } + static Storage new_Local(unsigned idx) { assert(idx <= MAX_ARG); return Storage((idx << 2) | 1); } static Storage new_Static(::HIR::Path p) { ::HIR::Path* ptr = new ::HIR::Path(::std::move(p)); - return Storage { static_cast(ptr) | 2; } + return Storage(reinterpret_cast(ptr) | 2); + } + + Storage clone() const; + + uintptr_t get_inner() const { + assert(!is_Static()); + return val; + } + static Storage from_inner(uintptr_t v) { + assert( (v & 3) < 2 ); + return Storage(v); + } + + enum Tag { + TAG_Argument, + TAG_Local, + TAG_Static, + TAG_Return, + TAGDEAD, + }; + Tag tag() const { + if(val == 0) + return TAG_Return; + return static_cast(val & 3); } - bool is_Return() const { return val == (MAX_ARG << 2) /*&& (val & 3) == 0*/; } - bool is_Argument() const { return val != (MAX_ARG << 2) && (val & 3) == 0; } + bool is_Return() const { return val == 0; } + bool is_Argument() const { return val != 0 && (val & 3) == 0; } bool is_Local() const { return (val & 3) == 1; } bool is_Static() const { return (val & 3) == 2; } - // No as_Return - unsigned as_Argument() const { assert(is_Argument()); return val >> 2; } - unsigned as_Local() const { assert(is_Local()); return val >> 2; } - const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3u); } + const char as_Return () const { assert(is_Return()); return 0; } + const unsigned as_Argument() const { assert(is_Argument()); return (val >> 2) - 1; } + const unsigned as_Local () const { assert(is_Local()); return val >> 2; } + + const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3llu); } + ::HIR::Path& as_Static() { assert(is_Static()); return *reinterpret_cast< ::HIR::Path*>(val & ~3llu); } + + Ordering ord(const Storage& x) const; + bool operator==(const Storage& x) const { return this->ord(x) == OrdEqual; } + bool operator!=(const Storage& x) const { return this->ord(x) != OrdEqual; } }; class Wrapper { - uintptr_t val; + uint32_t val; + Wrapper(uint32_t v): val(v) {} public: - static Wrapper new_Deref() { return Wrapper { 0 }; } - static Wrapepr new_Field (unsigned idx) { return Wrapper { (idx << 2) | 1 }; } - static Wrapepr new_Downcast(unsigned idx) { return Wrapper { (idx << 2) | 2 }; } - static Wrapepr new_Index (unsigned idx) { return Wrapper { (idx << 2) | 3 }; } + static Wrapper new_Deref() { return Wrapper( 0 ); } + static Wrapper new_Field (unsigned idx) { return Wrapper( (idx << 2) | 1 ); } + static Wrapper new_Downcast(unsigned idx) { return Wrapper( (idx << 2) | 2 ); } + static Wrapper new_Index (unsigned idx) { if(idx == ~0u) idx = Storage::MAX_ARG; return Wrapper( (idx << 2) | 3 ); } + + uint32_t get_inner() const { return val; } + static Wrapper from_inner(uint32_t v) { + return Wrapper(v); + } + + enum Tag { + TAG_Deref, + TAG_Field, + TAG_Downcast, + TAG_Index, + TAGDEAD, + }; + Tag tag() const { + return static_cast(val & 3); + } bool is_Deref () const { return (val & 3) == 0; } // Stores the field index @@ -84,79 +138,269 @@ struct LValue // Stores a Local index bool is_Index () const { return (val & 3) == 3; } - // no as_Deref() - const unsigned as_Field() const { assert(is_Field()); return (val >> 2); } + const char as_Deref () const { assert(is_Deref()); return 0; } + const unsigned as_Field () const { assert(is_Field()); return (val >> 2); } const unsigned as_Downcast() const { assert(is_Downcast()); return (val >> 2); } // TODO: Should this return a LValue? - const unsigned as_Index() const { assert(is_Index()); return (val >> 2); } + const unsigned as_Index () const { assert(is_Index()); unsigned rv = (val >> 2); return rv; } + + void inc_Field () { assert(is_Field ()); *this = Wrapper::new_Field (as_Field () + 1); } + void inc_Downcast() { assert(is_Downcast()); *this = Wrapper::new_Downcast(as_Downcast() + 1); } + + Ordering ord(const Wrapper& x) const { return ::ord(val, x.val); } }; Storage m_root; ::std::vector m_wrappers; - static LValue new_Return() { return LValue { Storage::new_Return(), {} }; } - static LValue new_Argument(unsigned idx) { return LValue { Storage::new_Argument(idx), {} }; } - static LValue new_Local(unsigned idx) { return LValue { Storage::new_Local(idx), {} }; } - static LValue new_Static(::HIR::Path p) { return LValue { Storage::new_Static(::std::move(p)), {} }; } + LValue() + :m_root( Storage::new_Return() ) + { + } + LValue(Storage root, ::std::vector wrappers) + :m_root( ::std::move(root) ) + ,m_wrappers( ::std::move(wrappers) ) + { + } + + static LValue new_Return () { return LValue(Storage::new_Return(), {}); } + static LValue new_Argument(unsigned idx ) { return LValue(Storage::new_Argument(idx), {}); } + static LValue new_Local (unsigned idx ) { return LValue(Storage::new_Local(idx), {}); } + static LValue new_Static (::HIR::Path p) { return LValue(Storage::new_Static(::std::move(p)), {}); } + + static LValue new_Deref(LValue lv) { lv.m_wrappers.push_back(Wrapper::new_Deref()); return lv; } + static LValue new_Field(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Field(idx)); return lv; } + static LValue new_Downcast(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Downcast(idx)); return lv; } + static LValue new_Index(LValue lv, unsigned local_idx) { lv.m_wrappers.push_back(Wrapper::new_Index(local_idx)); return lv; } - static LValue new_Deref(LValue lv) { lv.m_wrappers.push_back(Wrapper::new_Deref()); } - static LValue new_Field(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Field(idx)); } - static LValue new_Downcast(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Downcast(idx)); } - static LValue new_Index(LValue lv, unsigned local_idx) { lv.m_wrappers.push_back(Wrapper::new_Index(local_idx)); } + bool is_Return() const { return m_wrappers.empty() && m_root.is_Return(); } + bool is_Local () const { return m_wrappers.empty() && m_root.is_Local(); } + const unsigned as_Local() const { assert(m_wrappers.empty()); return m_root.as_Local(); } + + bool is_Deref () const { return m_wrappers.size() > 0 && m_wrappers.back().is_Deref(); } + bool is_Field () const { return m_wrappers.size() > 0 && m_wrappers.back().is_Field(); } + bool is_Downcast() const { return m_wrappers.size() > 0 && m_wrappers.back().is_Downcast(); } + const unsigned as_Field() const { assert(!m_wrappers.empty()); return m_wrappers.back().as_Field(); } + + void inc_Field () { assert(m_wrappers.size() > 0); m_wrappers.back().inc_Field (); } + void inc_Downcast() { assert(m_wrappers.size() > 0); m_wrappers.back().inc_Downcast(); } + + Ordering ord(const LValue& x) const; LValue monomorphise(const MonomorphState& ms, unsigned local_offset=0); //LValue monomorphise(const TransParams& ms, unsigned local_offset=0); - LValue clone() const; + LValue clone() const { + return LValue(m_root.clone(), m_wrappers); + } + LValue clone_wrapped(::std::vector wrappers) const { + if( this->m_wrappers.empty() ) { + return LValue(m_root.clone(), ::std::move(wrappers)); + } + else { + return clone_wrapped(wrappers.begin(), wrappers.end()); + } + } + template + LValue clone_wrapped(It begin_it, It end_it) const { + ::std::vector wrappers; + wrappers.reserve(m_wrappers.size() + ::std::distance(begin_it, end_it)); + wrappers.insert(wrappers.end(), m_wrappers.begin(), m_wrappers.end()); + wrappers.insert(wrappers.end(), begin_it, end_it); + return LValue(m_root.clone(), ::std::move(wrappers)); + } + + LValue clone_unwrapped(unsigned count=1) const { + assert(count > 0); + assert(count <= m_wrappers.size()); + return LValue(m_root.clone(), ::std::vector(m_wrappers.begin(), m_wrappers.end() - count)); + } + + /// Helper class that represents a LValue unwrapped to a certain degree + class RefCommon + { + protected: + const LValue* m_lv; + size_t m_wrapper_count; + + RefCommon(const LValue& lv, size_t wrapper_count) + :m_lv(&lv) + ,m_wrapper_count(wrapper_count) + { + assert(wrapper_count <= lv.m_wrappers.size()); + } + + public: + LValue clone() const { + return ::MIR::LValue( m_lv->m_root.clone(), ::std::vector(m_lv->m_wrappers.begin(), m_lv->m_wrappers.begin() + m_wrapper_count) ); + } + + const LValue& lv() const { return *m_lv; } + size_t wrapper_count() const { return m_wrapper_count; } + + /// Unwrap one level, returning false if already at the root + bool try_unwrap() { + if( m_wrapper_count == 0 ) { + return false; + } + else { + m_wrapper_count --; + return true; + } + } + + enum Tag { + TAGDEAD, + TAG_Return, + TAG_Argument, + TAG_Local, + TAG_Static, + TAG_Deref, + TAG_Field, + TAG_Downcast, + TAG_Index, + }; + Tag tag() const { + if( m_wrapper_count == 0 ) + { + switch(m_lv->m_root.tag()) + { + case Storage::TAGDEAD: return TAGDEAD; + case Storage::TAG_Return: return TAG_Return; + case Storage::TAG_Argument: return TAG_Argument; + case Storage::TAG_Local: return TAG_Local; + case Storage::TAG_Static: return TAG_Static; + } + } + else + { + switch(m_lv->m_wrappers[m_wrapper_count-1].tag()) + { + case Wrapper::TAGDEAD: return TAGDEAD; + case Wrapper::TAG_Deref: return TAG_Deref; + case Wrapper::TAG_Field: return TAG_Field; + case Wrapper::TAG_Downcast: return TAG_Downcast; + case Wrapper::TAG_Index: return TAG_Index; + } + } + return TAGDEAD; + } + + bool is_Local () const { return m_wrapper_count == 0 && m_lv->m_root.is_Local (); } + bool is_Return () const { return m_wrapper_count == 0 && m_lv->m_root.is_Return (); } + bool is_Argument() const { return m_wrapper_count == 0 && m_lv->m_root.is_Argument(); } + bool is_Static () const { return m_wrapper_count == 0 && m_lv->m_root.is_Static (); } + bool is_Deref () const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Deref (); } + bool is_Field () const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Field (); } + bool is_Downcast() const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Downcast(); } + bool is_Index () const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Index (); } + + const unsigned as_Local () const { assert(is_Local ()); return m_lv->m_root.as_Local (); } + const char as_Return () const { assert(is_Return ()); return m_lv->m_root.as_Return (); } + const unsigned as_Argument() const { assert(is_Argument()); return m_lv->m_root.as_Argument(); } + const HIR::Path& as_Static () const { assert(is_Static ()); return m_lv->m_root.as_Static (); } + const char as_Deref () const { assert(is_Deref ()); return m_lv->m_wrappers[m_wrapper_count-1].as_Deref (); } + const unsigned as_Field () const { assert(is_Field ()); return m_lv->m_wrappers[m_wrapper_count-1].as_Field (); } + const unsigned as_Downcast() const { assert(is_Downcast()); return m_lv->m_wrappers[m_wrapper_count-1].as_Downcast(); } + const unsigned as_Index () const { assert(is_Index ()); return m_lv->m_wrappers[m_wrapper_count-1].as_Index (); } - class Ref + void fmt(::std::ostream& os) const; + Ordering ord(const RefCommon& b) const; + }; + + class CRef: public RefCommon { - LValue& r; - size_t wrapper_idx; - public:: - LValue clone() const; - void replace(LValue x) const; + public: + CRef(const LValue& lv) + :RefCommon(lv, lv.m_wrappers.size()) + { + } + CRef(const LValue& lv, size_t wc) + :RefCommon(lv, wc) + { + } + + /// Unwrap one level + const CRef inner_ref() const { + assert(m_wrapper_count > 0); + auto rv = *this; + rv.m_wrapper_count--; + return rv; + } + + friend ::std::ostream& operator<<(::std::ostream& os, const CRef& x) { + x.fmt(os); + return os; + } + + bool operator<(const CRef& b) const { + return this->ord(b) == OrdLess; + } + bool operator==(const CRef& b) const { + return this->ord(b) == OrdEqual; + } }; + class MRef: public RefCommon + { + public: + MRef(LValue& lv) + :RefCommon(lv, lv.m_wrappers.size()) + { + } + + operator CRef() const { + return CRef(*m_lv, m_wrapper_count); + } + + MRef inner_ref() { + assert(m_wrapper_count > 0); + auto rv = *this; + rv.m_wrapper_count--; + return rv; + } + void replace(LValue x) { + auto& mut_lv = const_cast(*m_lv); + // Shortcut: No wrappers on source/destination (just assign the slot/root) + if( m_wrapper_count == 0 && x.m_wrappers.empty() ) { + mut_lv.m_root = ::std::move(x.m_root); + return ; + } + // If there's wrappers on this value (assigning over inner portion) + if( m_wrapper_count < m_lv->m_wrappers.size() ) { + // Add those wrappers to the end of the new value + x.m_wrappers.insert(x.m_wrappers.end(), m_lv->m_wrappers.begin() + m_wrapper_count, m_lv->m_wrappers.end()); + } + // Overwrite + mut_lv = ::std::move(x); + } + + friend ::std::ostream& operator<<(::std::ostream& os, const MRef& x) { + x.fmt(os); + return os; + } + }; + + Ordering ord(const LValue::CRef& x) const; + Ordering ord(const LValue::MRef& x) const; }; -#endif - -// "LVALUE" - Assignable values -TAGGED_UNION_EX(LValue, (), Return, ( - // Function return - (Return, struct{}), - // Function argument (input) - (Argument, struct { unsigned int idx; }), - // Variable/Temporary - (Local, unsigned int), - // `static` or `static mut` - (Static, ::std::unique_ptr<::HIR::Path>), - // Field access (tuple, struct, tuple struct, enum field, ...) - // NOTE: Also used to index an array/slice by a compile-time known index (e.g. in destructuring) - (Field, struct { - ::std::unique_ptr val; - unsigned int field_index; - }), - // Dereference a value - (Deref, struct { - ::std::unique_ptr val; - }), - // Index an array or slice (typeof(val) == [T; n] or [T]) - // NOTE: This is not bounds checked! - (Index, struct { - ::std::unique_ptr val; - ::std::unique_ptr idx; - }), - // Interpret an enum as a particular variant - (Downcast, struct { - ::std::unique_ptr val; - unsigned int variant_index; - }) - ), (),(), ( - LValue clone() const; - ) - ); extern ::std::ostream& operator<<(::std::ostream& os, const LValue& x); -extern bool operator<(const LValue& a, const LValue& b); -extern bool operator==(const LValue& a, const LValue& b); +static inline bool operator<(const LValue& a, const LValue::CRef& b) { + return a.ord(b) == OrdLess; +} +static inline bool operator<(const LValue& a, const LValue::MRef& b) { + return a.ord(b) == OrdLess; +} +static inline bool operator<(const LValue::CRef& a, const LValue& b) { + return b.ord(a) == OrdGreater; +} +static inline bool operator<(const LValue::MRef& a, const LValue& b) { + return b.ord(a) == OrdGreater; +} +static inline bool operator<(const LValue& a, const LValue& b) { + return a.ord(b) == OrdLess; +} +static inline bool operator==(const LValue& a, const LValue& b) { + return a.ord(b) == OrdEqual; +} static inline bool operator!=(const LValue& a, const LValue& b) { return !(a == b); } @@ -224,7 +468,7 @@ TAGGED_UNION_EX(Constant, (), Int, ( /// Parameter - A value used when a rvalue just reads (doesn't require a lvalue) /// Can be either a lvalue (memory address), or a constant -TAGGED_UNION_EX(Param, (), LValue, ( +TAGGED_UNION_EX(Param, (), Constant, ( (LValue, LValue), (Constant, Constant) ), (), (), ( @@ -237,7 +481,7 @@ TAGGED_UNION_EX(Param, (), LValue, ( ) ); -TAGGED_UNION_EX(RValue, (), Use, ( +TAGGED_UNION_EX(RValue, (), Tuple, ( (Use, LValue), (Constant, Constant), (SizedArray, struct { @@ -359,7 +603,7 @@ enum class eDropKind { SHALLOW, DEEP, }; -TAGGED_UNION(Statement, Assign, +TAGGED_UNION(Statement, Asm, // Value assigment (Assign, struct { LValue dst; diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 8d534314..a064b67d 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -68,7 +68,7 @@ MirBuilder::~MirBuilder() { if( has_result() ) { - push_stmt_assign( sp, ::MIR::LValue::make_Return({}), get_result(sp) ); + push_stmt_assign( sp, ::MIR::LValue::new_Return(), get_result(sp) ); } terminate_scope_early(sp, fcn_scope()); @@ -176,7 +176,7 @@ void MirBuilder::define_variable(unsigned int idx) auto& tmp_scope = top_scope->data.as_Owning(); assert(tmp_scope.is_temporary); tmp_scope.slots.push_back( rv ); - return ::MIR::LValue::make_Local(rv); + return ::MIR::LValue::new_Local(rv); } ::MIR::LValue MirBuilder::lvalue_or_temp(const Span& sp, const ::HIR::TypeRef& ty, ::MIR::RValue val) { @@ -258,12 +258,10 @@ void MirBuilder::set_result(const Span& sp, ::MIR::RValue val) m_result_valid = true; } -void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val) +void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val, bool drop_destination/*=true*/) { DEBUG(dst << " = " << val); ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - ASSERT_BUG(sp, dst.tag() != ::MIR::LValue::TAGDEAD, ""); - ASSERT_BUG(sp, val.tag() != ::MIR::RValue::TAGDEAD, ""); auto moved_param = [&](const ::MIR::Param& p) { if(const auto* e = p.opt_LValue()) { @@ -344,13 +342,15 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal ) // Drop target if populated - mark_value_assigned(sp, dst); + if( drop_destination ) + { + mark_value_assigned(sp, dst); + } this->push_stmt( sp, ::MIR::Statement::make_Assign({ mv$(dst), mv$(val) }) ); } void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int flag/*=~0u*/) { ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, ""); if( lvalue_is_copy(sp, val) ) { // Don't emit a drop for Copy values @@ -362,7 +362,6 @@ void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int void MirBuilder::push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val, unsigned int flag/*=~0u*/) { ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, ""); // TODO: Ensure that the type is a Box? @@ -400,22 +399,12 @@ void MirBuilder::push_stmt(const Span& sp, ::MIR::Statement stmt) void MirBuilder::mark_value_assigned(const Span& sp, const ::MIR::LValue& dst) { - VarState* state_p = nullptr; - // TODO: Tracking of complex asignment states (e.g. assignment of a field) - TU_MATCH_DEF(::MIR::LValue, (dst), (e), - ( - ), - (Return, - // Don't drop. - // No state tracking for the return value - ), - (Argument, - state_p = &get_slot_state_mut(sp, e.idx, SlotType::Argument); - ), - (Local, - state_p = &get_slot_state_mut(sp, e, SlotType::Local); - ) - ) + if( dst.m_root.is_Return() ) + { + ASSERT_BUG(sp, dst.m_wrappers.empty(), "Assignment to a component of the return value should be impossible."); + return ; + } + VarState* state_p = get_val_state_mut_p(sp, dst);; if( state_p ) { @@ -425,42 +414,28 @@ void MirBuilder::mark_value_assigned(const Span& sp, const ::MIR::LValue& dst) drop_value_from_state(sp, *state_p, dst.clone()); *state_p = VarState::make_Valid({}); } - // TODO: What about assigning into non-tracked locations? Should still cause a drop + else + { + // Assigning into non-tracked locations still causes a drop + drop_value_from_state(sp, VarState::make_Valid({}), dst.clone()); + } } void MirBuilder::raise_temporaries(const Span& sp, const ::MIR::LValue& val, const ScopeHandle& scope, bool to_above/*=false*/) { TRACE_FUNCTION_F(val); - TU_MATCH_DEF(::MIR::LValue, (val), (e), - ( + for(const auto& w : val.m_wrappers) + { + if( w.is_Index() ) { + // Raise index temporary + raise_temporaries(sp, ::MIR::LValue::new_Local(w.as_Index()), scope, to_above); + } + } + if( !val.m_root.is_Local() ) { // No raising of these source values? return ; - ), - // TODO: This may not be correct, because it can change the drop points and ordering - // HACK: Working around cases where values are dropped while the result is not yet used. - (Index, - raise_temporaries(sp, *e.val, scope, to_above); - raise_temporaries(sp, *e.idx, scope, to_above); - return ; - ), - (Deref, - raise_temporaries(sp, *e.val, scope, to_above); - return ; - ), - (Field, - raise_temporaries(sp, *e.val, scope, to_above); - return ; - ), - (Downcast, - raise_temporaries(sp, *e.val, scope, to_above); - return ; - ), - // Actual value types - (Local, - ) - ) - ASSERT_BUG(sp, val.is_Local(), "Hit value raising code with non-variable value - " << val); - const auto idx = val.as_Local(); + } + const auto idx = val.m_root.as_Local(); bool is_temp = (idx >= m_first_temp_idx); /* if( !is_temp ) { @@ -833,13 +808,12 @@ void MirBuilder::raise_all(const Span& sp, ScopeHandle source, const ScopeHandle } auto& src_scope_def = m_scopes.at(source.idx); -#if 1 ASSERT_BUG(sp, src_scope_def.data.is_Owning(), "Rasising scopes can only be done on temporaries (source)"); ASSERT_BUG(sp, src_scope_def.data.as_Owning().is_temporary, "Rasising scopes can only be done on temporaries (source)"); auto& src_list = src_scope_def.data.as_Owning().slots; for(auto idx : src_list) { - DEBUG("> Raising " << ::MIR::LValue::make_Local(idx)); + DEBUG("> Raising " << ::MIR::LValue::new_Local(idx)); assert(idx >= m_first_temp_idx); } @@ -910,13 +884,6 @@ void MirBuilder::raise_all(const Span& sp, ScopeHandle source, const ScopeHandle // Move all defined variables from one to the other auto& tgt_list = tgt_scope_def.data.as_Owning().slots; tgt_list.insert( tgt_list.end(), src_list.begin(), src_list.end() ); -#else - auto list = src_scope_def.data.as_Temporaries().temporaries; - for(auto idx : list) - { - this->raise_temporaries(sp, ::MIR::LValue::make_Temporary({ idx }), target); - } -#endif // Scope completed m_scope_stack.pop_back(); @@ -979,7 +946,7 @@ void MirBuilder::terminate_scope_early(const Span& sp, const ScopeHandle& scope, for(size_t i = 0; i < m_arg_states.size(); i ++) { const auto& state = get_slot_state(sp, i, SlotType::Argument); - this->drop_value_from_state(sp, state, ::MIR::LValue::make_Argument({ static_cast(i) })); + this->drop_value_from_state(sp, state, ::MIR::LValue::new_Argument(static_cast(i))); } } } @@ -1060,7 +1027,7 @@ namespace }); if( is_box ) { - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, *nse.inner_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, *nse.inner_state); } else { @@ -1086,13 +1053,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], nse.inner_states[i]); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], nse.inner_states[i]); } } } return; @@ -1168,7 +1135,7 @@ namespace }); if( is_box ) { - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, *nse.inner_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, *nse.inner_state); } else { BUG(sp, "MovedOut on non-Box"); @@ -1192,19 +1159,19 @@ namespace } auto& ose = old_state.as_Partial(); if( is_enum ) { - auto ilv = ::MIR::LValue::make_Downcast({ box$(lv.clone()), 0 }); + auto ilv = ::MIR::LValue::new_Downcast(lv.clone(), 0); for(size_t i = 0; i < ose.inner_states.size(); i ++) { merge_state(sp, builder, ilv, ose.inner_states[i], nse.inner_states[i]); - ilv.as_Downcast().variant_index ++; + ilv.inc_Downcast(); } } else { - auto ilv = ::MIR::LValue::make_Field({ box$(lv.clone()), 0 }); + auto ilv = ::MIR::LValue::new_Field(lv.clone(), 0); for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { merge_state(sp, builder, ilv, ose.inner_states[i], nse.inner_states[i]); - ilv.as_Field().field_index ++; + ilv.inc_Field(); } } } return; @@ -1268,13 +1235,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], nse.inner_states[i]); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], nse.inner_states[i]); } } return; } @@ -1309,7 +1276,7 @@ namespace builder.push_stmt_set_dropflag_val(sp, ose.outer_flag, is_valid); } - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, new_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, new_state); return ; } case VarState::TAG_Optional: { const auto& nse = new_state.as_Optional(); @@ -1334,7 +1301,7 @@ namespace builder.push_stmt_set_dropflag_other(sp, ose.outer_flag, nse); builder.push_stmt_set_dropflag_default(sp, nse); } - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, new_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, new_state); return; } case VarState::TAG_MovedOut: { const auto& nse = new_state.as_MovedOut(); @@ -1342,7 +1309,7 @@ namespace { TODO(sp, "Handle mismatched flags in MovedOut"); } - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, *nse.inner_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, *nse.inner_state); return; } case VarState::TAG_Partial: BUG(sp, "MovedOut->Partial not valid"); @@ -1366,13 +1333,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], new_state); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], new_state); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], new_state); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], new_state); } } return ; @@ -1384,13 +1351,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], nse.inner_states[i]); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], nse.inner_states[i]); } } } return ; @@ -1419,8 +1386,8 @@ void MirBuilder::terminate_loop_early(const Span& sp, ScopeType::Data_Loop& sd_l merge_state(sp, *this, val_cb(idx), old_state, get_slot_state(sp, idx, type)); } }; - merge_list(sd_loop.changed_slots, sd_loop.exit_state.states, ::MIR::LValue::make_Local, SlotType::Local); - merge_list(sd_loop.changed_args, sd_loop.exit_state.arg_states, [](auto v){ return ::MIR::LValue::make_Argument({v}); }, SlotType::Argument); + merge_list(sd_loop.changed_slots, sd_loop.exit_state.states, ::MIR::LValue::new_Local, SlotType::Local); + merge_list(sd_loop.changed_args, sd_loop.exit_state.arg_states, [](auto v){ return ::MIR::LValue::new_Argument(v); }, SlotType::Argument); } else { @@ -1475,7 +1442,7 @@ void MirBuilder::end_split_arm(const Span& sp, const ScopeHandle& handle, bool r auto it = states.find(idx); const auto& src_state = (it != states.end() ? it->second : get_slot_state(sp, idx, type, 1)); - auto lv = (type == SlotType::Local ? ::MIR::LValue::make_Local(idx) : ::MIR::LValue::make_Argument({idx})); + auto lv = (type == SlotType::Local ? ::MIR::LValue::new_Local(idx) : ::MIR::LValue::new_Argument(idx)); merge_state(sp, *this, mv$(lv), out_state, src_state); } }; @@ -1565,7 +1532,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) auto& vs = builder.get_slot_state_mut(sp, ent.first, SlotType::Local); if( vs != ent.second ) { - DEBUG(::MIR::LValue::make_Local(ent.first) << " " << vs << " => " << ent.second); + DEBUG(::MIR::LValue::new_Local(ent.first) << " " << vs << " => " << ent.second); vs = ::std::move(ent.second); } } @@ -1574,7 +1541,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) auto& vs = builder.get_slot_state_mut(sp, ent.first, SlotType::Argument); if( vs != ent.second ) { - DEBUG(::MIR::LValue::make_Argument({ent.first}) << " " << vs << " => " << ent.second); + DEBUG(::MIR::LValue::new_Argument(ent.first) << " " << vs << " => " << ent.second); vs = ::std::move(ent.second); } } @@ -1612,7 +1579,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) for(auto& ent : e->changed_slots) { auto& vs = this->get_slot_state_mut(sd.span, ent.first, SlotType::Local); - auto lv = ::MIR::LValue::make_Local(ent.first); + auto lv = ::MIR::LValue::new_Local(ent.first); DEBUG(lv << " " << vs << " => " << ent.second); if( vs != ent.second ) { @@ -1630,97 +1597,96 @@ void MirBuilder::complete_scope(ScopeDef& sd) } } -void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb) const +void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb, const ::MIR::LValue::Wrapper* stop_wrapper/*=nullptr*/) const { - TU_MATCH(::MIR::LValue, (val), (e), + ::HIR::TypeRef tmp; + const ::HIR::TypeRef* ty_p = nullptr; + TU_MATCHA( (val.m_root), (e), (Return, TODO(sp, "Return"); ), (Argument, - cb( m_args.at(e.idx).second ); + ty_p = &m_args.at(e).second; ), (Local, - cb( m_output.locals.at(e) ); + ty_p = &m_output.locals.at(e); ), (Static, - TU_MATCHA( (e->m_data), (pe), + TU_MATCHA( (e.m_data), (pe), (Generic, ASSERT_BUG(sp, pe.m_params.m_types.empty(), "Path params on static"); const auto& s = m_resolve.m_crate.get_static_by_path(sp, pe.m_path); - cb( s.m_type ); + ty_p = &s.m_type; ), (UfcsKnown, - TODO(sp, "Static - UfcsKnown - " << *e); + TODO(sp, "Static - UfcsKnown - " << e); ), (UfcsUnknown, - BUG(sp, "Encountered UfcsUnknown in Static - " << *e); + BUG(sp, "Encountered UfcsUnknown in Static - " << e); ), (UfcsInherent, - TODO(sp, "Static - UfcsInherent - " << *e); + TODO(sp, "Static - UfcsInherent - " << e); ) ) - ), - (Field, - with_val_type(sp, *e.val, [&](const auto& ty){ + ) + ) + assert(ty_p); + for(const auto& w : val.m_wrappers) + { + if( &w == stop_wrapper ) + { + stop_wrapper = nullptr; // Reset so the below bugcheck can work + break; + } + const auto& ty = *ty_p; + ty_p = nullptr; + auto maybe_monomorph = [&](const ::HIR::GenericParams& params_def, const ::HIR::Path& p, const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { + if( monomorphise_type_needed(t) ) { + tmp = monomorphise_type(sp, params_def, p.m_data.as_Generic().m_params, t); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return t; + } + }; + TU_MATCH_HDRA( (w), {) + TU_ARMA(Field, field_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Field access on unexpected type - " << ty); ), (Array, - cb( *te.inner ); + ty_p = &*te.inner; ), (Slice, - cb( *te.inner ); + ty_p = &*te.inner; ), (Path, - ::HIR::TypeRef tmp; if( const auto* tep = te.binding.opt_Struct() ) { const auto& str = **tep; - auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { - if( monomorphise_type_needed(t) ) { - tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, t); - m_resolve.expand_associated_types(sp, tmp); - return tmp; - } - else { - return t; - } - }; TU_MATCHA( (str.m_data), (se), (Unit, BUG(sp, "Field on unit-like struct - " << ty); ), (Tuple, - ASSERT_BUG(sp, e.field_index < se.size(), - "Field index out of range in tuple-struct " << ty << " - " << e.field_index << " > " << se.size()); - const auto& fld = se[e.field_index]; - cb( maybe_monomorph(fld.ent) ); + ASSERT_BUG(sp, field_index < se.size(), + "Field index out of range in tuple-struct " << ty << " - " << field_index << " > " << se.size()); + const auto& fld = se[field_index]; + ty_p = &maybe_monomorph(str.m_params, te.path, fld.ent); ), (Named, - ASSERT_BUG(sp, e.field_index < se.size(), - "Field index out of range in struct " << ty << " - " << e.field_index << " > " << se.size()); - const auto& fld = se[e.field_index].second; - cb( maybe_monomorph(fld.ent) ); + ASSERT_BUG(sp, field_index < se.size(), + "Field index out of range in struct " << ty << " - " << field_index << " > " << se.size()); + const auto& fld = se[field_index].second; + ty_p = &maybe_monomorph(str.m_params, te.path, fld.ent); ) ) } - else if( const auto* tep = te.binding.opt_Union() ) + else if( /*const auto* tep =*/ te.binding.opt_Union() ) { BUG(sp, "Field access on a union isn't valid, use Downcast instead - " << ty); - const auto& unm = **tep; - auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { - if( monomorphise_type_needed(t) ) { - tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, t); - m_resolve.expand_associated_types(sp, tmp); - return tmp; - } - else { - return t; - } - }; - ASSERT_BUG(sp, e.field_index < unm.m_variants.size(), "Field index out of range for union"); - cb( maybe_monomorph(unm.m_variants.at(e.field_index).second.ent) ); } else { @@ -1728,14 +1694,12 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: } ), (Tuple, - ASSERT_BUG(sp, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size()); - cb( te[e.field_index] ); + ASSERT_BUG(sp, field_index < te.size(), "Field index out of range in tuple " << field_index << " >= " << te.size()); + ty_p = &te[field_index]; ) ) - }); - ), - (Deref, - with_val_type(sp, *e.val, [&](const auto& ty){ + } + TU_ARMA(Deref, _e) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Deref on unexpected type - " << ty); @@ -1743,38 +1707,34 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: (Path, if( const auto* inner_ptr = this->is_type_owned_box(ty) ) { - cb( *inner_ptr ); + ty_p = &*inner_ptr; } else { BUG(sp, "Deref on unexpected type - " << ty); } ), (Pointer, - cb(*te.inner); + ty_p = &*te.inner; ), (Borrow, - cb(*te.inner); + ty_p = &*te.inner; ) ) - }); - ), - (Index, - with_val_type(sp, *e.val, [&](const auto& ty){ + } + TU_ARMA(Index, _index_val) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Index on unexpected type - " << ty); ), (Slice, - cb(*te.inner); + ty_p = &*te.inner; ), (Array, - cb(*te.inner); + ty_p = &*te.inner; ) ) - }); - ), - (Downcast, - with_val_type(sp, *e.val, [&](const auto& ty){ + } + TU_ARMA(Downcast, variant_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Downcast on unexpected type - " << ty); @@ -1785,33 +1745,19 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: const auto& enm = **pbe; ASSERT_BUG(sp, enm.m_data.is_Data(), "Downcast on non-data enum"); const auto& variants = enm.m_data.as_Data(); - ASSERT_BUG(sp, e.variant_index < variants.size(), "Variant index out of range"); - const auto& variant = variants[e.variant_index]; + ASSERT_BUG(sp, variant_index < variants.size(), "Variant index out of range"); + const auto& variant = variants[variant_index]; - if( monomorphise_type_needed(variant.type) ) { - auto tmp = monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, variant.type); - m_resolve.expand_associated_types(sp, tmp); - cb(tmp); - } - else { - cb(variant.type); - } + ty_p = &maybe_monomorph(enm.m_params, te.path, variant.type); } else if( const auto* pbe = te.binding.opt_Union() ) { const auto& unm = **pbe; - ASSERT_BUG(sp, e.variant_index < unm.m_variants.size(), "Variant index out of range"); - const auto& variant = unm.m_variants.at(e.variant_index); + ASSERT_BUG(sp, variant_index < unm.m_variants.size(), "Variant index out of range"); + const auto& variant = unm.m_variants.at(variant_index); const auto& fld = variant.second; - if( monomorphise_type_needed(fld.ent) ) { - auto sty = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, fld.ent); - m_resolve.expand_associated_types(sp, sty); - cb(sty); - } - else { - cb(fld.ent); - } + ty_p = &maybe_monomorph(unm.m_params, te.path, fld.ent); } else { @@ -1819,9 +1765,12 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: } ) ) - }); - ) - ) + } + } + assert(ty_p); + } + ASSERT_BUG(sp, !stop_wrapper, "A stop wrapper was passed, but not found"); + cb(*ty_p); } bool MirBuilder::lvalue_is_copy(const Span& sp, const ::MIR::LValue& val) const @@ -1998,165 +1947,177 @@ VarState& MirBuilder::get_slot_state_mut(const Span& sp, unsigned int idx, SlotT } } -const VarState& MirBuilder::get_val_state(const Span& sp, const ::MIR::LValue& lv, unsigned int skip_count) -{ - TODO(sp, ""); -} -VarState& MirBuilder::get_val_state_mut(const Span& sp, const ::MIR::LValue& lv) +VarState* MirBuilder::get_val_state_mut_p(const Span& sp, const ::MIR::LValue& lv) { TRACE_FUNCTION_F(lv); - TU_MATCHA( (lv), (e), + VarState* vs; + TU_MATCHA( (lv.m_root), (e), (Return, BUG(sp, "Move of return value"); - return get_slot_state_mut(sp, ~0u, SlotType::Local); + vs = &get_slot_state_mut(sp, ~0u, SlotType::Local); ), (Argument, - return get_slot_state_mut(sp, e.idx, SlotType::Argument); + vs = &get_slot_state_mut(sp, e, SlotType::Argument); ), (Local, - return get_slot_state_mut(sp, e, SlotType::Local); + vs = &get_slot_state_mut(sp, e, SlotType::Local); ), (Static, - BUG(sp, "Attempting to mutate state of a static"); - ), - (Field, - auto& ivs = get_val_state_mut(sp, *e.val); - VarState tpl; - TU_MATCHA( (ivs), (ivse), - (Invalid, - //BUG(sp, "Mutating inner state of an invalidated composite - " << lv); - tpl = VarState::make_Valid({}); - ), - (MovedOut, - BUG(sp, "Field on value with MovedOut state - " << lv); - ), - (Partial, - ), - (Optional, - tpl = ivs.clone(); - ), - (Valid, - tpl = VarState::make_Valid({}); - ) + return nullptr; + //BUG(sp, "Attempting to mutate state of a static"); ) - if( !ivs.is_Partial() ) - { - size_t n_flds = 0; - with_val_type(sp, *e.val, [&](const auto& ty) { - DEBUG("ty = " << ty); - if(const auto* e = ty.m_data.opt_Path()) { - ASSERT_BUG(sp, e->binding.is_Struct(), ""); - const auto& str = *e->binding.as_Struct(); - TU_MATCHA( (str.m_data), (se), - (Unit, - BUG(sp, "Field access of unit-like struct"); - ), - (Tuple, - n_flds = se.size(); - ), - (Named, - n_flds = se.size(); - ) - ) - } - else if(const auto* e = ty.m_data.opt_Tuple()) { - n_flds = e->size(); - } - else if(const auto* e = ty.m_data.opt_Array()) { - n_flds = e->size_val; - } - else { - TODO(sp, "Determine field count for " << ty); - } - }); - ::std::vector inner_vs; inner_vs.reserve(n_flds); - for(size_t i = 0; i < n_flds; i++) - inner_vs.push_back( tpl.clone() ); - ivs = VarState::make_Partial({ mv$(inner_vs) }); - } - return ivs.as_Partial().inner_states.at(e.field_index); - ), - (Deref, - // HACK: If the dereferenced type is a Box ("owned_box") then hack in move and shallow drop - bool is_box = false; - if( this->m_lang_Box ) - { - with_val_type(sp, *e.val, [&](const auto& ty){ - DEBUG("ty = " << ty); - is_box = this->is_type_owned_box(ty); - }); - } - + ) - if( is_box ) - { - auto& ivs = get_val_state_mut(sp, *e.val); - if( ! ivs.is_MovedOut() ) + for(const auto& w : lv.m_wrappers) + { + auto& ivs = *vs; + vs = nullptr; + TU_MATCH_HDRA( (w), { ) + TU_ARMA(Field, field_index) { + VarState tpl; + TU_MATCHA( (ivs), (ivse), + (Invalid, + //BUG(sp, "Mutating inner state of an invalidated composite - " << lv); + tpl = VarState::make_Valid({}); + ), + (MovedOut, + BUG(sp, "Field on value with MovedOut state - " << lv); + ), + (Partial, + ), + (Optional, + tpl = ivs.clone(); + ), + (Valid, + tpl = VarState::make_Valid({}); + ) + ) + if( !ivs.is_Partial() ) { - ::std::vector inner; - inner.push_back(VarState::make_Valid({})); - unsigned int drop_flag = (ivs.is_Optional() ? ivs.as_Optional() : ~0u); - ivs = VarState::make_MovedOut({ box$(VarState::make_Valid({})), drop_flag }); + size_t n_flds = 0; + with_val_type(sp, lv, [&](const auto& ty) { + DEBUG("ty = " << ty); + if(const auto* e = ty.m_data.opt_Path()) { + ASSERT_BUG(sp, e->binding.is_Struct(), ""); + const auto& str = *e->binding.as_Struct(); + TU_MATCHA( (str.m_data), (se), + (Unit, + BUG(sp, "Field access of unit-like struct"); + ), + (Tuple, + n_flds = se.size(); + ), + (Named, + n_flds = se.size(); + ) + ) + } + else if(const auto* e = ty.m_data.opt_Tuple()) { + n_flds = e->size(); + } + else if(const auto* e = ty.m_data.opt_Array()) { + n_flds = e->size_val; + } + else { + TODO(sp, "Determine field count for " << ty); + } + }, &w); + ::std::vector inner_vs; inner_vs.reserve(n_flds); + for(size_t i = 0; i < n_flds; i++) + inner_vs.push_back( tpl.clone() ); + ivs = VarState::make_Partial({ mv$(inner_vs) }); + } + vs = &ivs.as_Partial().inner_states.at(field_index); + } + TU_ARMA(Deref, _e) { + // HACK: If the dereferenced type is a Box ("owned_box") then hack in move and shallow drop + bool is_box = false; + if( this->m_lang_Box ) + { + with_val_type(sp, lv, [&](const auto& ty){ + DEBUG("ty = " << ty); + is_box = this->is_type_owned_box(ty); + }, &w); } - return *ivs.as_MovedOut().inner_state; - } - else - { - BUG(sp, "Move out of deref with non-Copy values - &move? - " << lv << " : " << FMT_CB(ss, this->with_val_type(sp, lv, [&](const auto& ty){ss<