diff options
-rw-r--r-- | rust_src.patch | 3 | ||||
-rw-r--r-- | src/hir_expand/ufcs_everything.cpp | 2 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 234 |
3 files changed, 136 insertions, 103 deletions
diff --git a/rust_src.patch b/rust_src.patch index d782d16b..ac479382 100644 --- a/rust_src.patch +++ b/rust_src.patch @@ -1,9 +1,10 @@ --- rustc-nightly/src/libcore/intrinsics.rs +++ rustc-nightly/src/libcore/intrinsics.rs -@@ -643,5 +643,8 @@ +@@ -643,5 +643,9 @@ pub fn drop_in_place<T: ?Sized>(to_drop: *mut T); + /// Obtain the length of a slice pointer ++ #[cfg(rust_compiler="mrustc")] + pub fn mrustc_slice_len<T>(pointer: *const [T]) -> usize; + /// Gets a static string slice containing the name of a type. diff --git a/src/hir_expand/ufcs_everything.cpp b/src/hir_expand/ufcs_everything.cpp index 00e7eee1..925543eb 100644 --- a/src/hir_expand/ufcs_everything.cpp +++ b/src/hir_expand/ufcs_everything.cpp @@ -414,7 +414,7 @@ namespace { break; case ::HIR::ExprNode_BinOp::Op::Shr: langitem = method = "shr"; if(0) - case ::HIR::ExprNode_BinOp::Op::Shl: langitem = method = "shr"; + case ::HIR::ExprNode_BinOp::Op::Shl: langitem = method = "shl"; if( is_op_valid_shift(ty_l, ty_r) ) { return ; } diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index ec720d8a..46331ca6 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -39,7 +39,7 @@ TAGGED_UNION_EX(PatternRule, (), Any,( (Slice, struct { unsigned int len; ::std::vector<PatternRule> sub_rules; }), // SplitSlice // TODO: How can the negative offsets in the `trailing` be handled correctly? (both here and in the destructure) - (SplitSlice, struct { unsigned int min_len; ::std::vector<PatternRule> leading, trailing; }), + (SplitSlice, struct { unsigned int min_len; unsigned int trailing_len; ::std::vector<PatternRule> leading, trailing; }), // Boolean (different to Constant because of how restricted it is) (Bool, bool), // General value @@ -809,6 +809,7 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal PatternRulesetBuilder sub_builder { this->m_resolve }; sub_builder.m_field_path = m_field_path; + sub_builder.m_field_path.push_back(var_idx); sub_builder.m_field_path.push_back(0); TU_MATCH( ::HIR::Enum::Variant, (var_def.second), (fields_def), @@ -1248,6 +1249,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa const auto& fields_def = var_def.second.as_Tuple(); PatternRulesetBuilder sub_builder { this->m_resolve }; sub_builder.m_field_path = m_field_path; + sub_builder.m_field_path.push_back(pe.binding_idx); sub_builder.m_field_path.push_back(0); for( unsigned int i = 0; i < pe.sub_patterns.size(); i ++ ) { @@ -1281,6 +1283,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa // 2. Iterate this list and recurse on the patterns PatternRulesetBuilder sub_builder { this->m_resolve }; sub_builder.m_field_path = m_field_path; + sub_builder.m_field_path.push_back(pe.binding_idx); sub_builder.m_field_path.push_back(0); for( unsigned int i = 0; i < tmp.size(); i ++ ) { @@ -1393,6 +1396,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa this->push_rule( PatternRule::make_SplitSlice({ static_cast<unsigned int>(pe.leading.size() + pe.trailing.size()), + static_cast<unsigned int>(pe.trailing.size()), mv$(leading), mv$(trailing) }) ); ) @@ -1692,7 +1696,7 @@ namespace { ASSERT_BUG(sp, field_path_ofs <= field_path.size(), "Field path offset " << field_path_ofs << " is larger than the path [" << field_path << "]"); for(unsigned int i = field_path_ofs; i < field_path.size(); i ++ ) { - auto idx = field_path.data[i]; + unsigned idx = field_path.data[i]; TU_MATCHA( (cur_ty->m_data), (e), (Infer, BUG(sp, "Ivar for in match type"); ), @@ -1774,7 +1778,43 @@ namespace { lval = ::MIR::LValue::make_Downcast({ box$(lval), idx }); ), (Enum, - BUG(sp, "Destructuring an enum - " << *cur_ty); + auto monomorph_to_ptr = [&](const auto& ty)->const auto* { + if( monomorphise_type_needed(ty) ) { + auto rv = monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty); + resolve.expand_associated_types(sp, rv); + tmp_ty = mv$(rv); + return &tmp_ty; + } + else { + return &ty; + } + }; + ASSERT_BUG(sp, idx < pbe->m_variants.size(), "Variant index (" << idx << ") out of range (" << pbe->m_variants.size() << ") for enum " << *cur_ty); + const auto& var = pbe->m_variants[idx]; + + i++; + assert(i < field_path.data.size()); + unsigned fld_idx = field_path.data[i]; + + TU_MATCHA( (var.second), (e), + (Unit, + BUG(sp, "Unit variant being destructured"); + ), + (Value, + BUG(sp, "Value variant being destructured"); + ), + (Tuple, + ASSERT_BUG(sp, fld_idx < e.size(), "Variant field index (" << fld_idx << ") out of range (" << e.size() << ") for enum " << *cur_ty << "::" << var.first); + cur_ty = monomorph_to_ptr(e[fld_idx].ent); + ), + (Struct, + ASSERT_BUG(sp, fld_idx < e.size(), "Variant field index (" << fld_idx << ") out of range (" << e.size() << ") for enum " << *cur_ty << "::" << var.first); + cur_ty = monomorph_to_ptr(e[fld_idx].second.ent); + ) + ) + DEBUG("*cur_ty = " << *cur_ty); + lval = ::MIR::LValue::make_Downcast({ box$(lval), idx }); + lval = ::MIR::LValue::make_Field({ box$(lval), fld_idx }); ) ) ), @@ -1798,12 +1838,15 @@ namespace { ), (Borrow, ASSERT_BUG(sp, idx == FIELD_DEREF, "Destructure of borrow doesn't correspond to a deref in the path"); + DEBUG(i << " " << *cur_ty << " - " << cur_ty << " " << &tmp_ty); if( cur_ty == &tmp_ty ) { - tmp_ty = mv$(*tmp_ty.m_data.as_Borrow().inner); + auto ip = mv$(tmp_ty.m_data.as_Borrow().inner); + tmp_ty = mv$(*ip); } else { cur_ty = &*e.inner; } + DEBUG(i << " " << *cur_ty); lval = ::MIR::LValue::make_Deref({ box$(lval) }); ), (Pointer, @@ -2160,7 +2203,7 @@ 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(), - fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size(), + fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1, fail_bb ); ), @@ -2177,7 +2220,7 @@ 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(), - fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size(), + fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1, fail_bb ); ) @@ -2441,13 +2484,78 @@ public: } }; +namespace { + void push_flat_rules(::std::vector<PatternRule>& out_rules, PatternRule rule) + { + TU_MATCHA( (rule), (e), + (Variant, + auto sub_rules = mv$(e.sub_rules); + out_rules.push_back( mv$(rule) ); + for(auto& sr : sub_rules) + push_flat_rules(out_rules, mv$(sr)); + ), + (Slice, + auto sub_rules = mv$(e.sub_rules); + out_rules.push_back( mv$(rule) ); + for(auto& sr : sub_rules) + push_flat_rules(out_rules, mv$(sr)); + ), + (SplitSlice, + auto leading = mv$(e.leading); + auto trailing = mv$(e.trailing); + out_rules.push_back( mv$(rule) ); + for(auto& sr : leading) + push_flat_rules(out_rules, mv$(sr)); + // TODO: the trailing rules need a special path format. + ASSERT_BUG(Span(), trailing.size() == 0, "TODO: Handle SplitSlice with trailing"); + for(auto& sr : trailing) + push_flat_rules(out_rules, mv$(sr)); + ), + (Bool, + out_rules.push_back( mv$(rule) ); + ), + (Value, + out_rules.push_back( mv$(rule) ); + ), + (ValueRange, + out_rules.push_back( mv$(rule) ); + ), + (Any, + out_rules.push_back( mv$(rule) ); + ) + ) + } + t_arm_rules flatten_rules(t_arm_rules rules) + { + t_arm_rules rv; + rv.reserve(rules.size()); + for(auto& ruleset : rules) + { + ::std::vector<PatternRule> pattern_rules; + for( auto& r : ruleset.m_rules ) + { + push_flat_rules(pattern_rules, mv$(r)); + } + rv.push_back(PatternRuleset { ruleset.arm_idx, ruleset.pat_idx, mv$(pattern_rules) }); + } + return rv; + } +} + void MIR_LowerHIR_Match_Grouped( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNode_Match& node, ::MIR::LValue match_val, t_arm_rules arm_rules, ::std::vector<ArmCode> arms_code, ::MIR::BasicBlockId first_cmp_block ) { + // TEMPORARY HACK: Grouped fails in complex matches (e.g. librustc_const_math Int::infer) + //MIR_LowerHIR_Match_Simple( builder, conv, node, mv$(match_val), mv$(arm_rules), mv$(arms_code), first_cmp_block ); + //return; + TRACE_FUNCTION_F(""); + // Flatten ruleset completely (remove grouping of enum/slice rules) + arm_rules = flatten_rules( mv$(arm_rules) ); + // - Create a "slice" of the passed rules, suitable for passing to the recursive part of the algo t_rules_subset rules { arm_rules.size(), /*is_arm_indexes=*/true }; for(const auto& r : arm_rules) @@ -2470,7 +2578,7 @@ void MIR_LowerHIR_Match_Grouped( } void MatchGenGrouped::gen_for_slice(t_rules_subset arm_rules, size_t ofs, ::MIR::BasicBlockId default_arm) { - TRACE_FUNCTION_F("arm_rules=" << arm_rules << ", ofs="<<ofs); + TRACE_FUNCTION_F("arm_rules=" << arm_rules << ", ofs="<<ofs << ", default_arm=" << default_arm); ASSERT_BUG(sp, arm_rules.size() > 0, ""); // Quick hack: Skip any layers entirely made up of PatternRule::Any @@ -2615,37 +2723,17 @@ void MatchGenGrouped::gen_for_slice(t_rules_subset arm_rules, size_t ofs, ::MIR: // > Get type of match, generate dispatch list. for(size_t i = 0; i < slices.size(); i ++) { - // If rules are actually different, split here. (handles Enum and Slice) auto cur_block = m_builder.new_bb_unlinked(); m_builder.set_cur_block(cur_block); - auto cur_start = 0; + for(size_t j = 0; j < slices[i].size(); j ++) { - if(slices[i][j][ofs] != slices[i][cur_start][ofs]) - { - DEBUG("- Equal range : " << cur_start << "+" << (j - cur_start)); - // Package up previous rules and generate dispatch code - auto ns = slices[i].sub_slice(cur_start, j - cur_start); - this->gen_for_slice(mv$(ns), ofs+1, next); - - cur_block = m_builder.new_bb_unlinked(); - m_builder.set_cur_block(cur_block); - - cur_start = j; - } + if(j > 0) + ASSERT_BUG(sp, slices[i][0][ofs] == slices[i][j][ofs], "Mismatched rules - " << slices[i][0][ofs] << " and " << slices[i][j][ofs]); arm_blocks.push_back(cur_block); } - if( cur_start != 0 ) - { - DEBUG("- Equal range : " << cur_start << "+" << (slices[i].size() - cur_start)); - auto ns = slices[i].sub_slice(cur_start, slices[i].size() - cur_start); - this->gen_for_slice( mv$(ns), ofs+1, next); - } - else - { - this->gen_for_slice(slices[i], ofs+1, next); - } + this->gen_for_slice(slices[i], ofs+1, next); } m_builder.set_cur_block(cur_blk); @@ -2981,70 +3069,24 @@ void MatchGenGrouped::gen_dispatch__enum(::HIR::TypeRef ty, ::MIR::LValue val, c auto decison_arm = m_builder.pause_cur_block(); - auto monomorph = [&](const auto& ty) { - auto rv = monomorphise_type(sp, pbe->m_params, te.path.m_data.as_Generic().m_params, ty); - m_builder.resolve().expand_associated_types(sp, rv); - return rv; - }; auto var_count = pbe->m_variants.size(); - size_t arm_idx = 0; ::std::vector< ::MIR::BasicBlockId> arms(var_count, def_blk); + size_t arm_idx = 0; for(size_t i = 0; i < rules.size(); i ++) { ASSERT_BUG(sp, rules[i][0][ofs].is_Variant(), "Rule for enum isn't Any or Variant - " << rules[i][0][ofs].tag_str()); const auto& re = rules[i][0][ofs].as_Variant(); unsigned int var_idx = re.idx; - arms[var_idx] = m_builder.new_bb_unlinked(); DEBUG("Variant " << var_idx); - // Create new rule collection based on the variants - t_rules_subset inner_set { rules[i].size(), /*is_arm_indexes=*/false }; + ASSERT_BUG(sp, re.sub_rules.size() == 0, "Sub-rules in MatchGenGrouped"); + + arms[var_idx] = arm_targets[arm_idx]; for(size_t j = 0; j < rules[i].size(); j ++) { - const auto& r = rules[i][j]; - inner_set.push_bb(r[ofs].as_Variant().sub_rules, arm_targets[arm_idx]); + assert(arms[var_idx] == arm_targets[arm_idx]); arm_idx ++; } - ::HIR::TypeRef fake_tup; - - const auto& var_data = pbe->m_variants.at(re.idx).second; - TU_MATCHA( (var_data), (ve), - (Unit, - // Nothing to recurse - ), - (Value, - // Nothing to recurse - ), - (Tuple, - // Create a dummy tuple to contain the inner types. - ::std::vector< ::HIR::TypeRef> fake_ty_ents; - fake_ty_ents.reserve( ve.size() ); - for(unsigned int i = 0; i < ve.size(); i ++) - { - fake_ty_ents.push_back( monomorph(ve[i].ent) ); - } - fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) ); - ), - (Struct, - // Create a dummy tuple to contain the inner types. - ::std::vector< ::HIR::TypeRef> fake_ty_ents; - fake_ty_ents.reserve( ve.size() ); - for(unsigned int i = 0; i < ve.size(); i ++) - { - fake_ty_ents.push_back( monomorph(ve[i].second.ent) ); - } - fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) ); - ) - ) - - m_builder.set_cur_block(arms[var_idx]); - // Recurse with the new ruleset - // - On success, these should jump to targets[i] - - auto new_lval = ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }); - auto inst = MatchGenGrouped { m_builder, sp, fake_tup, new_lval, {}, rules[0][0][ofs].field_path.size() }; - inst.gen_for_slice(inner_set, 0, def_blk); - ASSERT_BUG(sp, ! m_builder.block_active(), "Block still active after enum match generation"); } m_builder.set_cur_block(decison_arm); @@ -3061,14 +3103,15 @@ void MatchGenGrouped::gen_dispatch__slice(::HIR::TypeRef ty, ::MIR::LValue val, size_t tgt_ofs = 0; for(size_t i = 0; i < rules.size(); i++) { - //for(size_t j = 1; j < rules[i].size(); j ++) - // ASSERT_BUG(sp, arm_targets[tgt_ofs] == arm_targets[tgt_ofs+j], "Mismatched target blocks for Slice match"); - const auto& r = rules[i][0][ofs]; if(const auto* re = r.opt_Slice()) { + ASSERT_BUG(sp, re->sub_rules.size() == 0, "Sub-rules in MatchGenGrouped"); auto val_tst = ::MIR::Constant::make_Uint({ re->len, ::HIR::CoreType::Usize }); + for(size_t j = 0; j < rules[i].size(); j ++) + assert(arm_targets[tgt_ofs] == arm_targets[tgt_ofs+j]); + // IF v < tst : target if( re->len > 0 ) { @@ -3080,22 +3123,9 @@ void MatchGenGrouped::gen_dispatch__slice(::HIR::TypeRef ty, ::MIR::LValue val, // IF v == tst : target { - auto succ_blk = m_builder.new_bb_unlinked(); auto next_cmp_blk = m_builder.new_bb_unlinked(); auto cmp_lval_eq = this->push_compare( val_len.clone(), ::MIR::eBinOp::EQ, mv$(val_tst) ); - m_builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval_eq), succ_blk, next_cmp_blk }) ); - m_builder.set_cur_block(succ_blk); - - // - t_rules_subset inner_set { rules[i].size(), /*is_arm_indexes=*/false }; - for(size_t j = 0; j < rules[i].size(); j ++) - { - const auto& r = rules[i][j]; - inner_set.push_bb(r[ofs].as_Slice().sub_rules, arm_targets[tgt_ofs + j]); - } - auto inst = MatchGenGrouped { m_builder, sp, ty, val, {}, rules[0][0][ofs].field_path.size() }; - inst.gen_for_slice(inner_set, 0, def_blk); - + m_builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval_eq), arm_targets[tgt_ofs], next_cmp_blk }) ); m_builder.set_cur_block(next_cmp_blk); } } @@ -3233,6 +3263,8 @@ void MatchGenGrouped::gen_dispatch_splitslice(const field_path_t& field_path, co get_ty_and_val(sp, m_builder.resolve(), m_top_ty, m_top_val, field_path, m_field_path_ofs, ty, val); DEBUG("ty = " << ty << ", val = " << val); + ASSERT_BUG(sp, e.leading.size() == 0, "Sub-rules in MatchGenGrouped"); + ASSERT_BUG(sp, e.trailing.size() == 0, "Sub-rules in MatchGenGrouped"); ASSERT_BUG(sp, ty.m_data.is_Slice(), "SplitSlice pattern on non-slice - " << ty); // Obtain slice length @@ -3248,7 +3280,7 @@ void MatchGenGrouped::gen_dispatch_splitslice(const field_path_t& field_path, co } // 2. Recurse into leading patterns. - if( !e.leading.empty() ) + if( e.min_len > e.trailing_len ) { auto next = m_builder.new_bb_unlinked(); auto inner_set = t_rules_subset { 1, /*is_arm_indexes=*/false }; @@ -3259,7 +3291,7 @@ void MatchGenGrouped::gen_dispatch_splitslice(const field_path_t& field_path, co m_builder.set_cur_block(next); } - if( !e.trailing.empty() ) + if( e.trailing_len != 0 ) { TODO(sp, "Handle trailing rules in SplitSlice - " << e.trailing); } |