diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-11 22:32:12 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-11 22:32:12 +0800 |
commit | f54b532f00e183dc0250435acdff3beec5d7ae51 (patch) | |
tree | f7f13ae7ce5d9c8969d2923afdc57296671e5763 /src/hir_conv/constant_evaluation.cpp | |
parent | 577fe1d0c3d891ec1b3fd60db2a6675917c98be0 (diff) | |
download | mrust-f54b532f00e183dc0250435acdff3beec5d7ae51.tar.gz |
HIR Const Eval - Split into two passes to have correct types in literals
Diffstat (limited to 'src/hir_conv/constant_evaluation.cpp')
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 150 |
1 files changed, 126 insertions, 24 deletions
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 38b24f64..4e15f2d5 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -1,7 +1,9 @@ /* - * Evaluate constants + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) * - * HACK - Should be replaced with a reentrant typeck/mir pass + * hir_conv/constant_evaluation.cpp + * - Minimal (integer only) constant evaluation */ #include "main_bindings.hpp" #include <hir/hir.hpp> @@ -10,6 +12,7 @@ #include <algorithm> #include <mir/mir.hpp> #include <hir_typeck/common.hpp> // Monomorph +#include <mir/helpers.hpp> namespace { typedef ::std::vector< ::std::pair< ::std::string, ::HIR::Static> > t_new_values; @@ -18,13 +21,29 @@ namespace { t_new_values& newval_output; const ::HIR::ItemPath& mod_path; ::std::string name_prefix; + unsigned int next_item_idx; NewvalState(t_new_values& newval_output, const ::HIR::ItemPath& mod_path, ::std::string prefix): newval_output(newval_output), mod_path(mod_path), - name_prefix(prefix) + name_prefix(prefix), + next_item_idx(0) { } + + ::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value) + { + auto name = FMT(name_prefix << next_item_idx); + next_item_idx ++; + auto rv = (mod_path + name.c_str()).get_simple_path(); + newval_output.push_back( ::std::make_pair( mv$(name), ::HIR::Static { + false, + mv$(type), + ::HIR::ExprPtr(), + mv$(value) + } ) ); + return rv; + } }; ::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args={}); @@ -434,6 +453,8 @@ namespace { } void visit(::HIR::ExprNode_Borrow& node) override { + badnode(node); + TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_exp_type.m_data), (te), ( ERROR(node.span(), E0000, "Invalid expected type for a &-ptr - " << m_exp_type); @@ -1011,6 +1032,9 @@ namespace { { TRACE_FUNCTION; + StaticTraitResolve resolve { crate }; + ::MIR::TypeResolve state { sp, resolve, FMT_CB(), exp, {}, fcn }; + ::HIR::Literal retval; ::std::vector< ::HIR::Literal> locals; ::std::vector< ::HIR::Literal> temps; @@ -1078,10 +1102,14 @@ namespace { for(;;) { const auto& block = fcn.blocks[cur_block]; + unsigned int next_stmt_idx = 0; for(const auto& stmt : block.statements) { + state.set_cur_stmt(cur_block, next_stmt_idx++); + if( ! stmt.is_Assign() ) { - BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot); + //BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot); + continue ; } ::HIR::Literal val; @@ -1133,7 +1161,20 @@ namespace { val = ::HIR::Literal::make_List( mv$(vals) ); ), (Borrow, - TODO(sp, "RValue::Borrow"); + if( e.type != ::HIR::BorrowType::Shared ) { + MIR_BUG(state, "Only shared borrows are allowed in constants"); + } + + auto inner_val = read_lval(e.val); + + ::HIR::TypeRef inner_ty; + const auto& inner_ty_r = state.get_lvalue_type(inner_ty, e.val); + if( &inner_ty_r != &inner_ty ) + inner_ty = inner_ty_r.clone(); + + // Create new static containing borrowed data + auto item_path = newval_state.new_static( mv$(inner_ty), mv$(inner_val) ); + val = ::HIR::Literal::make_BorrowOf( mv$(item_path) ); ), (Cast, auto inval = read_lval(e.val); @@ -1161,6 +1202,8 @@ namespace { if(0) case ::HIR::CoreType::I64: case ::HIR::CoreType::U64: + case ::HIR::CoreType::Usize: + case ::HIR::CoreType::Isize: mask = 0xFFFFFFFFFFFFFFFF; TU_IFLET( ::HIR::Literal, inval, Integer, i, @@ -1173,6 +1216,18 @@ namespace { BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); } break; + case ::HIR::CoreType::F32: + case ::HIR::CoreType::F64: + TU_IFLET( ::HIR::Literal, inval, Integer, i, + val = ::HIR::Literal( static_cast<double>(i) ); + ) + else TU_IFLET( ::HIR::Literal, inval, Float, i, + val = ::HIR::Literal( i ); + ) + else { + BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); + } + break; default: TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval); } @@ -1182,6 +1237,9 @@ namespace { TU_IFLET( ::HIR::Literal, inval, Integer, i, val = ::HIR::Literal(i); ) + else TU_IFLET( ::HIR::Literal, inval, BorrowOf, i, + val = mv$(inval); + ) else { BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); } @@ -1196,6 +1254,35 @@ namespace { ( TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); ), + (Float, + switch(e.op) + { + case ::MIR::eBinOp::ADD: val = ::HIR::Literal( l + r ); break; + case ::MIR::eBinOp::SUB: val = ::HIR::Literal( l - r ); break; + case ::MIR::eBinOp::MUL: val = ::HIR::Literal( l * r ); break; + case ::MIR::eBinOp::DIV: val = ::HIR::Literal( l / r ); break; + case ::MIR::eBinOp::MOD: + case ::MIR::eBinOp::ADD_OV: + case ::MIR::eBinOp::SUB_OV: + case ::MIR::eBinOp::MUL_OV: + case ::MIR::eBinOp::DIV_OV: + TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); + + case ::MIR::eBinOp::BIT_OR : + case ::MIR::eBinOp::BIT_AND: + case ::MIR::eBinOp::BIT_XOR: + case ::MIR::eBinOp::BIT_SHL: + case ::MIR::eBinOp::BIT_SHR: + TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r); + // TODO: GT/LT are incorrect for signed integers + case ::MIR::eBinOp::EQ: val = ::HIR::Literal( static_cast<uint64_t>(l == r) ); break; + case ::MIR::eBinOp::NE: val = ::HIR::Literal( static_cast<uint64_t>(l != r) ); break; + case ::MIR::eBinOp::GT: val = ::HIR::Literal( static_cast<uint64_t>(l > r) ); break; + case ::MIR::eBinOp::GE: val = ::HIR::Literal( static_cast<uint64_t>(l >= r) ); break; + case ::MIR::eBinOp::LT: val = ::HIR::Literal( static_cast<uint64_t>(l < r) ); break; + case ::MIR::eBinOp::LE: val = ::HIR::Literal( static_cast<uint64_t>(l <= r) ); break; + } + ), (Integer, switch(e.op) { @@ -1233,7 +1320,18 @@ namespace { { case ::MIR::eUniOp::INV: val = ::HIR::Literal( ~i ); - break; + break; + case ::MIR::eUniOp::NEG: + val = ::HIR::Literal( -i ); + break; + } + ) + else TU_IFLET( ::HIR::Literal, inval, Float, i, + switch( e.op ) + { + case ::MIR::eUniOp::INV: + BUG(sp, "Invalid invert of Float"); + break; case ::MIR::eUniOp::NEG: val = ::HIR::Literal( -i ); break; @@ -1250,7 +1348,14 @@ namespace { TODO(sp, "RValue::DstPtr"); ), (MakeDst, - TODO(sp, "RValue::MakeDst"); + auto ptr = read_lval(e.ptr_val); + auto meta = read_lval(e.meta_val); + if( ! meta.is_Integer() ) { + TODO(sp, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta); + } + else { + val = mv$(ptr); + } ), (Tuple, ::std::vector< ::HIR::Literal> vals; @@ -1281,6 +1386,7 @@ namespace { auto& dst = get_lval(sa.dst); dst = mv$(val); } + state.set_cur_stmt_term(cur_block); TU_MATCH_DEF( ::MIR::Terminator, (block.terminator), (e), ( BUG(sp, "Unexpected terminator - " << block.terminator); @@ -1319,12 +1425,12 @@ namespace { ::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args) { - if( expr ) { - return evaluate_constant_hir(sp, crate, mv$(newval_state), *expr, mv$(exp), mv$(args)); - } - else if( expr.m_mir ) { + if( expr.m_mir ) { return evaluate_constant_mir(sp, crate, mv$(newval_state), *expr.m_mir, mv$(exp), mv$(args)); } + else if( expr ) { + return evaluate_constant_hir(sp, crate, mv$(newval_state), *expr, mv$(exp), mv$(args)); + } else { BUG(sp, "Attempting to evaluate constant expression with no associated code"); } @@ -1446,26 +1552,21 @@ namespace { } void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override { - visit_type(item.m_type); + ::HIR::Visitor::visit_constant(p, item); + + //visit_type(item.m_type); if( item.m_value ) { + if( ! item.m_type.m_data.is_Primitive() ) + return ; + auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }; item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, nvs, item.m_value, item.m_type.clone(), {}); check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); DEBUG("constant: " << item.m_type << " = " << item.m_value_res); - visit_expr(item.m_value); - } - } - void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override - { - visit_type(item.m_type); - if( item.m_value ) - { - item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }, item.m_value, item.m_type.clone(), {}); - DEBUG("static: " << item.m_type << " = " << item.m_value_res); - visit_expr(item.m_value); + //visit_expr(item.m_value); } } void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override { @@ -1512,7 +1613,8 @@ namespace { void visit(::HIR::ExprNode_ArraySized& node) override { assert( node.m_size ); - auto val = evaluate_constant_hir(node.span(), m_exp.m_crate, NewvalState { m_exp.m_new_values, *m_exp.m_mod_path, FMT("array_" << &node << "$") }, *node.m_size, ::HIR::CoreType::Usize, {}); + NewvalState nvs { m_exp.m_new_values, *m_exp.m_mod_path, FMT("array_" << &node << "$") }; + auto val = evaluate_constant_hir(node.span(), m_exp.m_crate, mv$(nvs), *node.m_size, ::HIR::CoreType::Usize, {}); if( !val.is_Integer() ) ERROR(node.span(), E0000, "Array size isn't an integer"); node.m_size_val = val.as_Integer(); |