From 6bfa68684d38b86236fd308250fd93ebd8ad22f9 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 7 Oct 2016 15:16:33 +0800 Subject: MIR Gen Match - Signed integer branch generation --- src/mir/from_hir_match.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'src') diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 8219e518..1ad207a3 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -767,6 +767,13 @@ struct DecisionTreeGen void generate_branch(const DecisionTreeNode::Branch& branch, ::std::function cb); + void generate_branches_Signed( + const Span& sp, + const DecisionTreeNode::Branch& default_branch, + const DecisionTreeNode::Values::Data_Signed& branches, + const ::HIR::TypeRef& ty, ::MIR::LValue val, + ::std::function and_then + ); void generate_branches_Unsigned( const Span& sp, const DecisionTreeNode::Branch& default_branch, @@ -2297,6 +2304,14 @@ void DecisionTreeGen::generate_tree_code( ASSERT_BUG(sp, node.m_branches.is_Unsigned(), "Tree for unsigned isn't a _Unsigned - node="<generate_branches_Unsigned(sp, node.m_default, node.m_branches.as_Unsigned(), ty, mv$(val), mv$(and_then)); break; + case ::HIR::CoreType::I8: + case ::HIR::CoreType::I16: + case ::HIR::CoreType::I32: + case ::HIR::CoreType::I64: + case ::HIR::CoreType::Isize: + ASSERT_BUG(sp, node.m_branches.is_Signed(), "Tree for unsigned isn't a _Signed - node="<generate_branches_Signed(sp, node.m_default, node.m_branches.as_Signed(), ty, mv$(val), mv$(and_then)); + break; case ::HIR::CoreType::Char: ASSERT_BUG(sp, node.m_branches.is_Unsigned(), "Tree for char isn't a _Unsigned - node="<generate_branches_Char(sp, node.m_default, node.m_branches.as_Unsigned(), ty, mv$(val), mv$(and_then)); @@ -2395,6 +2410,53 @@ void DecisionTreeGen::generate_branch(const DecisionTreeNode::Branch& branch, :: } } +void DecisionTreeGen::generate_branches_Signed( + const Span& sp, + const DecisionTreeNode::Branch& default_branch, + const DecisionTreeNode::Values::Data_Signed& branches, + const ::HIR::TypeRef& ty, ::MIR::LValue val, + ::std::function and_then + ) +{ + auto default_block = m_builder.new_bb_unlinked(); + + // TODO: Convert into an integer switch w/ offset instead of chained comparisons + + for( const auto& branch : branches ) + { + auto next_block = (&branch == &branches.back() ? default_block : m_builder.new_bb_unlinked()); + + auto val_start = m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.start)); + auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.end))); + + auto cmp_gt_block = m_builder.new_bb_unlinked(); + auto val_cmp_lt = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({ + val.clone(), ::MIR::eBinOp::LT, mv$(val_start) + }) ); + m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_lt), default_block, cmp_gt_block }) ); + m_builder.set_cur_block( cmp_gt_block ); + auto success_block = m_builder.new_bb_unlinked(); + auto val_cmp_gt = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({ + val.clone(), ::MIR::eBinOp::GT, mv$(val_end) + }) ); + m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) ); + + m_builder.set_cur_block( success_block ); + this->generate_branch(branch.second, and_then); + + m_builder.set_cur_block( next_block ); + } + assert( m_builder.block_active() ); + + if( default_branch.is_Unset() ) { + // TODO: Emit error if non-exhaustive + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); + } + else { + this->generate_branch(default_branch, and_then); + } +} + void DecisionTreeGen::generate_branches_Unsigned( const Span& sp, const DecisionTreeNode::Branch& default_branch, -- cgit v1.2.3