diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-02-22 13:27:28 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-02-22 13:27:28 +0800 |
commit | e4d8415f346e7067c3f060649c577b947a249e51 (patch) | |
tree | 8af7cd07650aaac7a53cd5d560134c0990d82ba0 /src | |
parent | a4ec506e3f3c23c7818c3ce2d020b25966c420d8 (diff) | |
download | mrust-e4d8415f346e7067c3f060649c577b947a249e51.tar.gz |
MIR - add Param type for places where a lvalue is read
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/deserialise.cpp | 29 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 9 | ||||
-rw-r--r-- | src/hir_conv/bind.cpp | 40 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 87 | ||||
-rw-r--r-- | src/hir_expand/const_eval_full.cpp | 105 | ||||
-rw-r--r-- | src/mir/check.cpp | 9 | ||||
-rw-r--r-- | src/mir/cleanup.cpp | 47 | ||||
-rw-r--r-- | src/mir/dump.cpp | 65 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 45 | ||||
-rw-r--r-- | src/mir/mir.cpp | 77 | ||||
-rw-r--r-- | src/mir/mir.hpp | 54 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 41 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 104 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 508 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 86 | ||||
-rw-r--r-- | src/trans/monomorphise.cpp | 113 |
16 files changed, 851 insertions, 568 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 19786eb1..fd6cbbf2 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -317,6 +317,16 @@ namespace { ::MIR::Terminator deserialise_mir_terminator(); ::MIR::CallTarget deserialise_mir_calltarget(); + ::MIR::Param deserialise_mir_param() + { + switch(auto tag = m_in.read_tag()) + { + case ::MIR::Param::TAG_LValue: return deserialise_mir_lvalue(); + case ::MIR::Param::TAG_Constant: return deserialise_mir_constant(); + default: + throw ::std::runtime_error(FMT("Invalid MIR LValue tag - " << tag)); + } + } ::MIR::LValue deserialise_mir_lvalue() { ::MIR::LValue rv; TRACE_FUNCTION_FR("", rv); @@ -361,7 +371,7 @@ namespace { _(Use, deserialise_mir_lvalue() ) _(Constant, deserialise_mir_constant() ) _(SizedArray, { - deserialise_mir_lvalue(), + deserialise_mir_param(), static_cast<unsigned int>(m_in.read_u64c()) }) _(Borrow, { @@ -374,9 +384,9 @@ namespace { deserialise_type() }) _(BinOp, { - deserialise_mir_lvalue(), + deserialise_mir_param(), static_cast< ::MIR::eBinOp>( m_in.read_tag() ), - deserialise_mir_lvalue() + deserialise_mir_param() }) _(UniOp, { deserialise_mir_lvalue(), @@ -390,23 +400,23 @@ namespace { }) _(MakeDst, { deserialise_mir_lvalue(), - deserialise_mir_lvalue() + deserialise_mir_param() }) _(Tuple, { - deserialise_vec_c< ::MIR::LValue>([&](){ return deserialise_mir_lvalue(); }) + deserialise_vec< ::MIR::Param>() }) _(Array, { - deserialise_vec_c< ::MIR::LValue>([&](){ return deserialise_mir_lvalue(); }) + deserialise_vec< ::MIR::Param>() }) _(Variant, { deserialise_genericpath(), static_cast<unsigned int>( m_in.read_count() ), - deserialise_mir_lvalue() + deserialise_mir_param() }) _(Struct, { deserialise_genericpath(), static_cast<unsigned int>( m_in.read_count() ), - deserialise_vec_c< ::MIR::LValue>([&](){ return deserialise_mir_lvalue(); }) + deserialise_vec< ::MIR::Param>() }) #undef _ default: @@ -642,6 +652,7 @@ namespace { template<> DEF_D( ::HIR::AssociatedType, return d.deserialise_associatedtype(); ) template<> DEF_D( ::HIR::TraitValueItem, return d.deserialise_traitvalueitem(); ) + template<> DEF_D( ::MIR::Param, return d.deserialise_mir_param(); ) 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(); ) @@ -1017,7 +1028,7 @@ namespace { static_cast<unsigned int>(m_in.read_count()), deserialise_mir_lvalue(), deserialise_mir_calltarget(), - deserialise_vec< ::MIR::LValue>() + deserialise_vec< ::MIR::Param>() }) #undef _ default: diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index dede23a4..5a74e798 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -552,6 +552,15 @@ namespace { ) ) } + void serialise(const ::MIR::Param& p) + { + TRACE_FUNCTION_F("Param = "<<p); + m_out.write_tag( static_cast<int>(p.tag()) ); + TU_MATCHA( (p), (e), + (LValue, serialise(e);), + (Constant, serialise(e);) + ) + } void serialise(const ::MIR::LValue& lv) { TRACE_FUNCTION_F("LValue = "<<lv); diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 686c71d2..53d97fb0 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -499,6 +499,28 @@ namespace { ) ) } + 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, + // TODO: Should this trigger anything? + ), + (ItemAddr, + upper_visitor.visit_path(ce, ::HIR::Visitor::PathContext::VALUE); + ) + ) + ) + ) + } }; for(auto& ty : expr.m_mir->named_variables) this->visit_type(ty); @@ -531,7 +553,7 @@ namespace { ) ), (SizedArray, - H::visit_lvalue(*this, e.val); + H::visit_param(*this, e.val); ), (Borrow, H::visit_lvalue(*this, e.val); @@ -541,8 +563,8 @@ namespace { this->visit_type(e.type); ), (BinOp, - H::visit_lvalue(*this, e.val_l); - H::visit_lvalue(*this, e.val_r); + H::visit_param(*this, e.val_l); + H::visit_param(*this, e.val_r); ), (UniOp, H::visit_lvalue(*this, e.val); @@ -554,23 +576,23 @@ namespace { H::visit_lvalue(*this, e.val); ), (MakeDst, - H::visit_lvalue(*this, e.meta_val); H::visit_lvalue(*this, e.ptr_val); + H::visit_param(*this, e.meta_val); ), (Tuple, for(auto& val : e.vals) - H::visit_lvalue(*this, val); + H::visit_param(*this, val); ), (Array, for(auto& val : e.vals) - H::visit_lvalue(*this, val); + H::visit_param(*this, val); ), (Variant, - H::visit_lvalue(*this, e.val); + H::visit_param(*this, e.val); ), (Struct, for(auto& val : e.vals) - H::visit_lvalue(*this, val); + H::visit_param(*this, val); ) ) ) @@ -606,7 +628,7 @@ namespace { ) ) for(auto& arg : te.args) - H::visit_lvalue(*this, arg); + H::visit_param(*this, arg); ) ) } diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 1baa48ac..b604b510 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -1083,6 +1083,48 @@ namespace { ) ) }; + auto const_to_lit = [&](const ::MIR::Constant& c)->::HIR::Literal { + TU_MATCH(::MIR::Constant, (c), (e2), + (Int, + return ::HIR::Literal(static_cast<uint64_t>(e2)); + ), + (Uint, + return ::HIR::Literal(e2); + ), + (Float, + return ::HIR::Literal(e2); + ), + (Bool, + return ::HIR::Literal(static_cast<uint64_t>(e2)); + ), + (Bytes, + return ::HIR::Literal::make_String({e2.begin(), e2.end()}); + ), + (StaticString, + return ::HIR::Literal(e2); + ), + (Const, + auto ent = get_ent_fullpath(sp, crate, e2.p, EntNS::Value); + ASSERT_BUG(sp, ent.is_Constant(), "MIR Constant::Const("<<e2.p<<") didn't point to a Constant - " << ent.tag_str()); + return clone_literal( ent.as_Constant()->m_value_res ); + ), + (ItemAddr, + return ::HIR::Literal::make_BorrowOf( e2.clone() ); + ) + ) + throw ""; + }; + auto read_param = [&](const ::MIR::Param& p) ->::HIR::Literal { + TU_MATCH(::MIR::Param, (p), (e), + (LValue, + return read_lval(e); + ), + (Constant, + return const_to_lit(e); + ) + ) + throw ""; + }; unsigned int cur_block = 0; for(;;) @@ -1105,41 +1147,14 @@ namespace { val = read_lval(e); ), (Constant, - TU_MATCH(::MIR::Constant, (e), (e2), - (Int, - val = ::HIR::Literal(static_cast<uint64_t>(e2)); - ), - (Uint, - val = ::HIR::Literal(e2); - ), - (Float, - val = ::HIR::Literal(e2); - ), - (Bool, - val = ::HIR::Literal(static_cast<uint64_t>(e2)); - ), - (Bytes, - val = ::HIR::Literal::make_String({e2.begin(), e2.end()}); - ), - (StaticString, - val = ::HIR::Literal(e2); - ), - (Const, - auto ent = get_ent_fullpath(sp, crate, e2.p, EntNS::Value); - ASSERT_BUG(sp, ent.is_Constant(), "MIR Constant::Const("<<e2.p<<") didn't point to a Constant - " << ent.tag_str()); - val = clone_literal( ent.as_Constant()->m_value_res ); - ), - (ItemAddr, - val = ::HIR::Literal::make_BorrowOf( e2.clone() ); - ) - ) + val = const_to_lit(e); ), (SizedArray, ::std::vector< ::HIR::Literal> vals; if( e.count > 0 ) { vals.reserve( e.count ); - val = read_lval(e.val); + val = read_param(e.val); for(unsigned int i = 1; i < e.count; i++) vals.push_back( clone_literal(val) ); vals.push_back( mv$(val) ); @@ -1235,8 +1250,8 @@ namespace { ) ), (BinOp, - auto inval_l = read_lval(e.val_l); - auto inval_r = read_lval(e.val_r); + auto inval_l = read_param(e.val_l); + auto inval_r = read_param(e.val_r); ASSERT_BUG(sp, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r); TU_MATCH_DEF( ::HIR::Literal, (inval_l, inval_r), (l, r), ( @@ -1337,7 +1352,7 @@ namespace { ), (MakeDst, auto ptr = read_lval(e.ptr_val); - auto meta = read_lval(e.meta_val); + auto meta = read_param(e.meta_val); if( ! meta.is_Integer() ) { TODO(sp, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta); } @@ -1349,14 +1364,14 @@ namespace { ::std::vector< ::HIR::Literal> vals; vals.reserve( e.vals.size() ); for(const auto& v : e.vals) - vals.push_back( read_lval(v) ); + vals.push_back( read_param(v) ); val = ::HIR::Literal::make_List( mv$(vals) ); ), (Array, ::std::vector< ::HIR::Literal> vals; vals.reserve( e.vals.size() ); for(const auto& v : e.vals) - vals.push_back( read_lval(v) ); + vals.push_back( read_param(v) ); val = ::HIR::Literal::make_List( mv$(vals) ); ), (Variant, @@ -1366,7 +1381,7 @@ namespace { ::std::vector< ::HIR::Literal> vals; vals.reserve( e.vals.size() ); for(const auto& v : e.vals) - vals.push_back( read_lval(v) ); + vals.push_back( read_param(v) ); val = ::HIR::Literal::make_List( mv$(vals) ); ) ) @@ -1436,7 +1451,7 @@ namespace { ::std::vector< ::HIR::Literal> call_args; call_args.reserve( e.args.size() ); for(const auto& a : e.args) - call_args.push_back( read_lval(a) ); + call_args.push_back( read_param(a) ); // TODO: Set m_const during parse and check here // Call by invoking evaluate_constant on the function diff --git a/src/hir_expand/const_eval_full.cpp b/src/hir_expand/const_eval_full.cpp index 35ddcb66..4a6fec21 100644 --- a/src/hir_expand/const_eval_full.cpp +++ b/src/hir_expand/const_eval_full.cpp @@ -4,6 +4,9 @@ * * hir_expand/const_eval_full.cpp * - More-complete constant evaluation + * + * NOTE: This is run _after_ MIR lowering (not before, as the rest of this + * folder is) */ #include "main_bindings.hpp" #include <hir/hir.hpp> @@ -382,6 +385,56 @@ namespace { ) ) }; + auto const_to_lit = [&](const ::MIR::Constant& c)->::HIR::Literal { + TU_MATCH(::MIR::Constant, (c), (e2), + (Int, + return ::HIR::Literal(static_cast<uint64_t>(e2)); + ), + (Uint, + return ::HIR::Literal(e2); + ), + (Float, + return ::HIR::Literal(e2); + ), + (Bool, + return ::HIR::Literal(static_cast<uint64_t>(e2)); + ), + (Bytes, + return ::HIR::Literal::make_String({e2.begin(), e2.end()}); + ), + (StaticString, + return ::HIR::Literal(e2); + ), + (Const, + MonomorphState const_ms; + // TODO: Monomorph the path? (Not needed... yet) + auto ent = get_ent_fullpath(sp, resolve.m_crate, e2.p, EntNS::Value, const_ms); + ASSERT_BUG(sp, ent.is_Constant(), "MIR Constant::Const("<<e2.p<<") didn't point to a Constant - " << ent.tag_str()); + auto val = clone_literal( ent.as_Constant()->m_value_res ); + if( val.is_Invalid() ) { + return evaluate_constant(sp, resolve, newval_state, FMT_CB(ss, ss << e2.p;), ent.as_Constant()->m_value, {}, {}); + } + // Monomorphise the value according to `const_ms` + monomorph_literal_inplace(sp, val, const_ms); + return val; + ), + (ItemAddr, + return ::HIR::Literal::make_BorrowOf( ms.monomorph(sp, e2) ); + ) + ) + throw ""; + }; + auto read_param = [&](const ::MIR::Param& p) ->::HIR::Literal { + TU_MATCH(::MIR::Param, (p), (e), + (LValue, + return read_lval(e); + ), + (Constant, + return const_to_lit(e); + ) + ) + throw ""; + }; unsigned int cur_block = 0; for(;;) @@ -405,48 +458,14 @@ namespace { val = read_lval(e); ), (Constant, - TU_MATCH(::MIR::Constant, (e), (e2), - (Int, - val = ::HIR::Literal(static_cast<uint64_t>(e2)); - ), - (Uint, - val = ::HIR::Literal(e2); - ), - (Float, - val = ::HIR::Literal(e2); - ), - (Bool, - val = ::HIR::Literal(static_cast<uint64_t>(e2)); - ), - (Bytes, - val = ::HIR::Literal::make_String({e2.begin(), e2.end()}); - ), - (StaticString, - val = ::HIR::Literal(e2); - ), - (Const, - MonomorphState const_ms; - // TODO: Monomorph the path? (Not needed... yet) - auto ent = get_ent_fullpath(sp, resolve.m_crate, e2.p, EntNS::Value, const_ms); - ASSERT_BUG(sp, ent.is_Constant(), "MIR Constant::Const("<<e2.p<<") didn't point to a Constant - " << ent.tag_str()); - val = clone_literal( ent.as_Constant()->m_value_res ); - if( val.is_Invalid() ) { - val = evaluate_constant(sp, resolve, newval_state, FMT_CB(ss, ss << e2.p;), ent.as_Constant()->m_value, {}, {}); - } - // Monomorphise the value according to `const_ms` - monomorph_literal_inplace(sp, val, const_ms); - ), - (ItemAddr, - val = ::HIR::Literal::make_BorrowOf( ms.monomorph(sp, e2) ); - ) - ) + val = const_to_lit(e); ), (SizedArray, ::std::vector< ::HIR::Literal> vals; if( e.count > 0 ) { vals.reserve( e.count ); - val = read_lval(e.val); + val = read_param(e.val); for(unsigned int i = 1; i < e.count; i++) vals.push_back( clone_literal(val) ); vals.push_back( mv$(val) ); @@ -557,8 +576,8 @@ namespace { ) ), (BinOp, - auto inval_l = read_lval(e.val_l); - auto inval_r = read_lval(e.val_r); + auto inval_l = read_param(e.val_l); + auto inval_r = read_param(e.val_r); ASSERT_BUG(sp, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r); TU_MATCH_DEF( ::HIR::Literal, (inval_l, inval_r), (l, r), ( @@ -659,7 +678,7 @@ namespace { ), (MakeDst, auto ptr = read_lval(e.ptr_val); - auto meta = read_lval(e.meta_val); + auto meta = read_param(e.meta_val); if( ! meta.is_Integer() ) { TODO(sp, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta); } @@ -671,14 +690,14 @@ namespace { ::std::vector< ::HIR::Literal> vals; vals.reserve( e.vals.size() ); for(const auto& v : e.vals) - vals.push_back( read_lval(v) ); + vals.push_back( read_param(v) ); val = ::HIR::Literal::make_List( mv$(vals) ); ), (Array, ::std::vector< ::HIR::Literal> vals; vals.reserve( e.vals.size() ); for(const auto& v : e.vals) - vals.push_back( read_lval(v) ); + vals.push_back( read_param(v) ); val = ::HIR::Literal::make_List( mv$(vals) ); ), (Variant, @@ -688,7 +707,7 @@ namespace { ::std::vector< ::HIR::Literal> vals; vals.reserve( e.vals.size() ); for(const auto& v : e.vals) - vals.push_back( read_lval(v) ); + vals.push_back( read_param(v) ); if( e.variant_idx == ~0u ) val = ::HIR::Literal::make_List( mv$(vals) ); else @@ -725,7 +744,7 @@ namespace { ::std::vector< ::HIR::Literal> call_args; call_args.reserve( e.args.size() ); for(const auto& a : e.args) - call_args.push_back( read_lval(a) ); + call_args.push_back( read_param(a) ); // TODO: Set m_const during parse and check here // Call by invoking evaluate_constant on the function diff --git a/src/mir/check.cpp b/src/mir/check.cpp index ae2887e0..62e06d51 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -301,6 +301,13 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn mark_validity(state, lv, false); } } + void move_val(const ::MIR::TypeResolve& state, const ::MIR::Param& p) + { + if( const auto* e = p.opt_LValue() ) + { + move_val(state, *e); + } + } private: static bool merge_state(State& a, State& b) { @@ -720,6 +727,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path // TODO: Check suitability of source type (COMPLEX) ), (BinOp, + #if 0 ::HIR::TypeRef tmp_l, tmp_r; const auto& ty_l = state.get_lvalue_type(tmp_l, e.val_l); const auto& ty_r = state.get_lvalue_type(tmp_r, e.val_r); @@ -734,6 +742,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path if( ty_l != ty_r ) MIR_BUG(state, "Type mismatch in binop, " << ty_l << " != " << ty_r); } + #endif // TODO: Check return type ), (UniOp, diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 53d1c17b..c9dba9bd 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -207,7 +207,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR const auto& vals = lit.as_List(); MIR_ASSERT(state, vals.size() == te.size(), "Literal size mismatched with tuple size"); - ::std::vector< ::MIR::LValue> lvals; + ::std::vector< ::MIR::Param> lvals; lvals.reserve( vals.size() ); for(unsigned int i = 0; i < vals.size(); i ++) @@ -245,7 +245,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR } else { - ::std::vector< ::MIR::LValue> lvals; + ::std::vector< ::MIR::Param> lvals; lvals.reserve( vals.size() ); for(const auto& val: vals) @@ -265,7 +265,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR auto monomorph = [&](const auto& tpl) { return monomorphise_type(state.sp, str.m_params, te.path.m_data.as_Generic().m_params, tpl); }; - ::std::vector< ::MIR::LValue> lvals; + ::std::vector< ::MIR::Param> lvals; TU_MATCHA( (str.m_data), (se), (Unit, MIR_ASSERT(state, vals.size() == 0, "Values passed for unit struct"); @@ -298,7 +298,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR auto monomorph = [&](const auto& tpl) { return monomorphise_type(state.sp, enm.m_params, te.path.m_data.as_Generic().m_params, tpl); }; - ::std::vector< ::MIR::LValue> lvals; + ::std::vector< ::MIR::Param> lvals; MIR_ASSERT(state, lit_var.idx < enm.m_variants.size(), "Variant index out of range"); TU_MATCHA( (enm.m_variants[lit_var.idx].second), (ve), (Unit, @@ -487,7 +487,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR const auto& str = *te.binding.as_Struct(); ::HIR::TypeRef tmp; auto monomorph = [&](const auto& t) { return monomorphise_type(Span(), str.m_params, ty_path.m_params, t); }; - ::std::vector< ::MIR::LValue> vals; + ::std::vector< ::MIR::Param> vals; TU_MATCHA( (str.m_data), (se), (Unit, ), @@ -732,7 +732,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& auto monomorph_cb_s = monomorphise_type_get_cb(state.sp, nullptr, &ste.path.m_data.as_Generic().m_params, nullptr); // - Destructure and restrucure with the unsized fields - ::std::vector<::MIR::LValue> ents; + ::std::vector<::MIR::Param> ents; TU_MATCHA( (str.m_data), (se), (Unit, MIR_BUG(state, "Unit-like struct CoerceUnsized is impossible - " << src_ty); @@ -904,6 +904,17 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, :: } } } +void MIR_Cleanup_Param(const ::MIR::TypeResolve& state, MirMutator& mutator, ::MIR::Param& p) +{ + TU_MATCHA( (p), (e), + (LValue, + MIR_Cleanup_LValue(state, mutator, e); + ), + (Constant, + // NOTE: No cleanup + ) + ) +} void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type) { @@ -941,7 +952,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, (Constant, ), (SizedArray, - MIR_Cleanup_LValue(state, mutator, re.val); + MIR_Cleanup_Param(state, mutator, re.val); ), (Borrow, MIR_Cleanup_LValue(state, mutator, re.val); @@ -950,8 +961,8 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, MIR_Cleanup_LValue(state, mutator, re.val); ), (BinOp, - MIR_Cleanup_LValue(state, mutator, re.val_l); - MIR_Cleanup_LValue(state, mutator, re.val_r); + MIR_Cleanup_Param(state, mutator, re.val_l); + MIR_Cleanup_Param(state, mutator, re.val_r); ), (UniOp, MIR_Cleanup_LValue(state, mutator, re.val); @@ -987,22 +998,22 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ), (MakeDst, MIR_Cleanup_LValue(state, mutator, re.ptr_val); - MIR_Cleanup_LValue(state, mutator, re.meta_val); + MIR_Cleanup_Param(state, mutator, re.meta_val); ), (Tuple, for(auto& lv : re.vals) - MIR_Cleanup_LValue(state, mutator, lv); + MIR_Cleanup_Param(state, mutator, lv); ), (Array, for(auto& lv : re.vals) - MIR_Cleanup_LValue(state, mutator, lv); + MIR_Cleanup_Param(state, mutator, lv); ), (Variant, - MIR_Cleanup_LValue(state, mutator, re.val); + MIR_Cleanup_Param(state, mutator, re.val); ), (Struct, for(auto& lv : re.vals) - MIR_Cleanup_LValue(state, mutator, lv); + MIR_Cleanup_Param(state, mutator, lv); ) ) ) @@ -1103,7 +1114,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, MIR_Cleanup_LValue(state, mutator, e.fcn.as_Value()); } for(auto& lv : e.args) - MIR_Cleanup_LValue(state, mutator, lv); + MIR_Cleanup_Param(state, mutator, lv); ) ) @@ -1125,7 +1136,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ) ) { - auto tgt_lvalue = MIR_Cleanup_Virtualize(sp, state, mutator, e.args.front(), te, pe); + auto tgt_lvalue = MIR_Cleanup_Virtualize(sp, state, mutator, e.args.front().as_LValue(), te, pe); e.fcn = mv$(tgt_lvalue); } } @@ -1137,8 +1148,8 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, if( pe.trait.m_path == resolve.m_lang_Fn || pe.trait.m_path == resolve.m_lang_FnMut || pe.trait.m_path == resolve.m_lang_FnOnce ) { MIR_ASSERT(state, e.args.size() == 2, "Fn* call requires two arguments"); - auto fcn_lvalue = mv$(e.args[0]); - auto args_lvalue = mv$(e.args[1]); + auto fcn_lvalue = mv$(e.args[0].as_LValue()); + auto args_lvalue = mv$(e.args[1].as_LValue()); DEBUG("Convert function pointer call"); diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index bbacbbf3..1342e086 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -193,38 +193,51 @@ namespace { ) ) } + void fmt_val(::std::ostream& os, const ::MIR::Constant& e) { + TU_MATCHA( (e), (ce), + (Int, + os << ce; + ), + (Uint, + os << "0x" << ::std::hex << ce << ::std::dec; + ), + (Float, + os << ce; + ), + (Bool, + os << (ce ? "true" : "false"); + ), + (Bytes, + os << "b\"" << ce << "\""; + ), + (StaticString, + os << "\"" << ce << "\""; + ), + (Const, + os << ce.p; + ), + (ItemAddr, + os << "addr " << ce; + ) + ) + } + void fmt_val(::std::ostream& os, const ::MIR::Param& param) { + TU_MATCHA( (param), (e), + (LValue, + fmt_val(os, e); + ), + (Constant, + fmt_val(os, e); + ) + ) + } void fmt_val(::std::ostream& os, const ::MIR::RValue& rval) { TU_MATCHA( (rval), (e), (Use, fmt_val(os, e); ), (Constant, - TU_MATCHA( (e), (ce), - (Int, - os << ce; - ), - (Uint, - os << "0x" << ::std::hex << ce << ::std::dec; - ), - (Float, - os << ce; - ), - (Bool, - os << (ce ? "true" : "false"); - ), - (Bytes, - os << "b\"" << ce << "\""; - ), - (StaticString, - os << "\"" << ce << "\""; - ), - (Const, - os << ce.p; - ), - (ItemAddr, - os << "addr " << ce; - ) - ) + fmt_val(os, e); ), (SizedArray, os << "["; diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 40e43f3b..36d3adc4 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -1434,7 +1434,7 @@ namespace { m_builder.end_block(::MIR::Terminator::make_Call({ place_raw__ok, place_raw__panic, place_raw.clone(), mv$(fcn_path), - ::make_vec1( mv$(place_refmut) ) + ::make_vec1( ::MIR::Param(mv$(place_refmut)) ) })); } @@ -1471,7 +1471,7 @@ namespace { m_builder.end_block(::MIR::Terminator::make_Call({ res__ok, res__panic, res.clone(), mv$(finalize_path), - ::make_vec1( mv$(place) ) + ::make_vec1( ::MIR::Param(mv$(place)) ) })); // TODO: Proper panic handling, including scope destruction @@ -1488,7 +1488,7 @@ namespace { { const Span& sp = node.span(); TRACE_FUNCTION_F("_TupleVariant"); - ::std::vector< ::MIR::LValue> values; + ::std::vector< ::MIR::Param> values; values.reserve( node.m_args.size() ); for(auto& arg : node.m_args) { @@ -1517,16 +1517,15 @@ namespace { }) ); } - void visit(::HIR::ExprNode_CallPath& node) override + ::std::vector< ::MIR::Param> get_args(/*const*/ ::std::vector<::HIR::ExprNodeP>& args) { - TRACE_FUNCTION_F("_CallPath " << node.m_path); - ::std::vector< ::MIR::LValue> values; - values.reserve( node.m_args.size() ); - for(auto& arg : node.m_args) + ::std::vector< ::MIR::Param> values; + values.reserve( args.size() ); + for(auto& arg : args) { this->visit_node_ptr(arg); - if( node.m_args.size() == 1 ) + if( args.size() == 1 ) { values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type, /*allow_missing_value=*/true) ); } @@ -1541,9 +1540,18 @@ namespace { values.push_back( mv$(tmp) ); } - m_builder.moved_lvalue( arg->span(), values.back() ); + if(const auto* e = values.back().opt_LValue() ) + { + m_builder.moved_lvalue( arg->span(), *e ); + } } + return values; + } + void visit(::HIR::ExprNode_CallPath& node) override + { + TRACE_FUNCTION_F("_CallPath " << node.m_path); + auto values = get_args(node.m_args); auto panic_block = m_builder.new_bb_unlinked(); auto next_block = m_builder.new_bb_unlinked(); @@ -1616,14 +1624,7 @@ namespace { this->visit_node_ptr(node.m_value); auto fcn_val = m_builder.get_result_in_lvalue( node.m_value->span(), node.m_value->m_res_type ); - ::std::vector< ::MIR::LValue> values; - values.reserve( node.m_args.size() ); - for(auto& arg : node.m_args) - { - this->visit_node_ptr(arg); - values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) ); - m_builder.moved_lvalue( arg->span(), values.back() ); - } + auto values = get_args(node.m_args); auto panic_block = m_builder.new_bb_unlinked(); @@ -1924,7 +1925,7 @@ namespace { const ::HIR::t_struct_fields& fields = *fields_ptr; ::std::vector<bool> values_set; - ::std::vector< ::MIR::LValue> values; + ::std::vector< ::MIR::Param> values; values.resize( fields.size() ); values_set.resize( fields.size() ); @@ -1982,7 +1983,7 @@ namespace { void visit(::HIR::ExprNode_Tuple& node) override { TRACE_FUNCTION_F("_Tuple"); - ::std::vector< ::MIR::LValue> values; + ::std::vector< ::MIR::Param> values; values.reserve( node.m_vals.size() ); for(auto& arg : node.m_vals) { @@ -1998,7 +1999,7 @@ namespace { void visit(::HIR::ExprNode_ArrayList& node) override { TRACE_FUNCTION_F("_ArrayList"); - ::std::vector< ::MIR::LValue> values; + ::std::vector< ::MIR::Param> values; values.reserve( node.m_vals.size() ); for(auto& arg : node.m_vals) { @@ -2027,7 +2028,7 @@ namespace { { TRACE_FUNCTION_F("_Closure - " << node.m_obj_path); - ::std::vector< ::MIR::LValue> vals; + ::std::vector< ::MIR::Param> vals; vals.reserve( node.m_captures.size() ); for(auto& arg : node.m_captures) { diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 157071c7..aab0c53f 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -50,11 +50,11 @@ namespace MIR { ) return os; } - bool operator==(const Constant& a, const Constant& b) + bool Constant::operator==(const Constant& b) const { - if( a.tag() != b.tag() ) + if( this->tag() != b.tag() ) return false; - TU_MATCHA( (a,b), (ae,be), + TU_MATCHA( (*this,b), (ae,be), (Int, return ae == be; ), @@ -207,6 +207,33 @@ namespace MIR { throw ""; } + ::std::ostream& operator<<(::std::ostream& os, const Param& x) + { + TU_MATCHA( (x), (e), + (LValue, + os << e; + ), + (Constant, + os << e; + ) + ) + return os; + } + bool Param::operator==(const Param& x) const + { + if( this->tag() != x.tag() ) + return false; + TU_MATCHA( (*this, x), (ea, eb), + (LValue, + return ea == eb; + ), + (Constant, + return ea == eb; + ) + ) + throw ""; + } + ::std::ostream& operator<<(::std::ostream& os, const RValue& x) { TU_MATCHA( (x), (e), @@ -445,6 +472,33 @@ namespace MIR { ) throw ""; } +::MIR::Constant MIR::Constant::clone() const +{ + TU_MATCHA( (*this), (e2), + (Int, return ::MIR::Constant(e2); ), + (Uint, return ::MIR::Constant(e2); ), + (Float, return ::MIR::Constant(e2); ), + (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()); ) + ) + throw ""; +} + +::MIR::Param MIR::Param::clone() const +{ + TU_MATCHA( (*this), (e), + (LValue, + return e.clone(); + ), + (Constant, + return e.clone(); + ) + ) + throw ""; +} ::MIR::RValue MIR::RValue::clone() const { @@ -453,16 +507,7 @@ namespace MIR { return ::MIR::RValue(e.clone()); ), (Constant, - TU_MATCHA( (e), (e2), - (Int, return ::MIR::Constant(e2); ), - (Uint, return ::MIR::Constant(e2); ), - (Float, return ::MIR::Constant(e2); ), - (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()); ) - ) + return e.clone(); ), (SizedArray, return ::MIR::RValue::make_SizedArray({ e.val.clone(), e.count }); @@ -490,7 +535,7 @@ namespace MIR { return ::MIR::RValue::make_MakeDst({ e.ptr_val.clone(), e.meta_val.clone() }); ), (Tuple, - ::std::vector<::MIR::LValue> ret; + decltype(e.vals) ret; ret.reserve(e.vals.size()); for(const auto& v : e.vals) ret.push_back( v.clone() ); @@ -498,7 +543,7 @@ namespace MIR { ), // Array literal (Array, - ::std::vector<::MIR::LValue> ret; + decltype(e.vals) ret; ret.reserve(e.vals.size()); for(const auto& v : e.vals) ret.push_back( v.clone() ); @@ -510,7 +555,7 @@ namespace MIR { ), // Create a new instance of a struct (or enum) (Struct, - ::std::vector<::MIR::LValue> ret; + decltype(e.vals) ret; ret.reserve(e.vals.size()); for(const auto& v : e.vals) ret.push_back( v.clone() ); diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 00cfcf8f..94eaa973 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -90,7 +90,7 @@ enum class eUniOp }; // Compile-time known values -TAGGED_UNION(Constant, Int, +TAGGED_UNION_EX(Constant, (), Int, ( (Int, ::std::int64_t), (Uint, ::std::uint64_t), (Float, double), @@ -99,18 +99,36 @@ TAGGED_UNION(Constant, Int, (StaticString, ::std::string), // String (Const, struct { ::HIR::Path p; }), // `const` (ItemAddr, ::HIR::Path) // address of a value - ); -extern ::std::ostream& operator<<(::std::ostream& os, const Constant& v); -extern bool operator==(const Constant& a, const Constant& b); -static inline bool operator!=(const Constant& a, const Constant& b) { - return !(a == b); -} + ), (), (), ( + friend ::std::ostream& operator<<(::std::ostream& os, const Constant& v); + bool operator==(const Constant& b) const; + inline bool operator!=(const Constant& b) const { + return !(*this == b); + } + Constant clone() const; + ) +); + +/// 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, ( + (LValue, LValue), + (Constant, Constant) + ), (), (), ( + Param clone() const; + friend ::std::ostream& operator<<(::std::ostream& os, const Param& v); + bool operator==(const Param& b) const; + inline bool operator!=(const Param& b) const { + return !(*this == b); + } + ) +); TAGGED_UNION_EX(RValue, (), Use, ( (Use, LValue), (Constant, Constant), (SizedArray, struct { - LValue val; + Param val; unsigned int count; }), (Borrow, struct { @@ -125,13 +143,13 @@ TAGGED_UNION_EX(RValue, (), Use, ( }), // Binary operation on primitives (BinOp, struct { - LValue val_l; + Param val_l; eBinOp op; - LValue val_r; + Param val_r; }), // Unary operation on primitives (UniOp, struct { - LValue val; + LValue val; // NOTE: Not a param, because UniOps can be const propagated eUniOp op; }), // Extract the metadata from a DST pointer @@ -145,27 +163,27 @@ TAGGED_UNION_EX(RValue, (), Use, ( }), // Construct a DST pointer from a thin pointer and metadata (MakeDst, struct { - LValue ptr_val; - LValue meta_val; + LValue ptr_val; // NOTE: Not a Param, becuase the pointer is a borrow + Param meta_val; }), (Tuple, struct { - ::std::vector<LValue> vals; + ::std::vector<Param> vals; }), // Array literal (Array, struct { - ::std::vector<LValue> vals; + ::std::vector<Param> vals; }), // Create a new instance of a union (and eventually enum) (Variant, struct { ::HIR::GenericPath path; unsigned int index; - LValue val; + Param val; }), // Create a new instance of a struct (or enum) (Struct, struct { ::HIR::GenericPath path; unsigned int variant_idx; // if ~0, it's a struct - ::std::vector<LValue> vals; + ::std::vector<Param> vals; }) ), (),(), ( RValue clone() const; @@ -206,7 +224,7 @@ TAGGED_UNION(Terminator, Incomplete, BasicBlockId panic_block; LValue ret_val; CallTarget fcn; - ::std::vector<LValue> args; + ::std::vector<Param> args; }) ); extern ::std::ostream& operator<<(::std::ostream& os, const Terminator& x); diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 16b0fd80..110d87e3 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -186,6 +186,11 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal 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()) { + this->moved_lvalue(sp, *e); + } + }; TU_MATCHA( (val), (e), (Use, this->moved_lvalue(sp, e); @@ -193,7 +198,7 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal (Constant, ), (SizedArray, - this->moved_lvalue(sp, e.val); + moved_param(e.val); ), (Borrow, if( e.type == ::HIR::BorrowType::Owned ) { @@ -220,8 +225,8 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal // Takes an implicit borrow... and only works on copy, so why is this block here? break; default: - this->moved_lvalue(sp, e.val_l); - this->moved_lvalue(sp, e.val_r); + moved_param(e.val_l); + moved_param(e.val_r); break; } ), @@ -236,22 +241,22 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal ), (MakeDst, // Doesn't move ptr_val - this->moved_lvalue(sp, e.meta_val); + moved_param(e.meta_val); ), (Tuple, for(const auto& val : e.vals) - this->moved_lvalue(sp, val); + moved_param(val); ), (Array, for(const auto& val : e.vals) - this->moved_lvalue(sp, val); + moved_param(val); ), (Variant, - this->moved_lvalue(sp, e.val); + moved_param(e.val); ), (Struct, for(const auto& val : e.vals) - this->moved_lvalue(sp, val); + moved_param(val); ) ) @@ -453,6 +458,10 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const } void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, const ScopeHandle& scope) { + auto raise_vars = [&](const ::MIR::Param& p) { + if( const auto* e = p.opt_LValue() ) + this->raise_variables(sp, *e, scope); + }; TU_MATCHA( (rval), (e), (Use, this->raise_variables(sp, e, scope); @@ -460,7 +469,7 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, cons (Constant, ), (SizedArray, - this->raise_variables(sp, e.val, scope); + raise_vars(e.val); ), (Borrow, // TODO: Wait, is this valid? @@ -470,8 +479,8 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, cons this->raise_variables(sp, e.val, scope); ), (BinOp, - this->raise_variables(sp, e.val_l, scope); - this->raise_variables(sp, e.val_r, scope); + raise_vars(e.val_l); + raise_vars(e.val_r); ), (UniOp, this->raise_variables(sp, e.val, scope); @@ -484,22 +493,22 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, cons ), (MakeDst, this->raise_variables(sp, e.ptr_val, scope); - this->raise_variables(sp, e.meta_val, scope); + raise_vars(e.meta_val); ), (Tuple, for(const auto& val : e.vals) - this->raise_variables(sp, val, scope); + raise_vars(val); ), (Array, for(const auto& val : e.vals) - this->raise_variables(sp, val, scope); + raise_vars(val); ), (Variant, - this->raise_variables(sp, e.val, scope); + raise_vars(e.val); ), (Struct, for(const auto& val : e.vals) - this->raise_variables(sp, val, scope); + raise_vars(val); ) ) } diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index a60d2e32..c7c4e6d7 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -82,6 +82,29 @@ namespace { return visit_mir_lvalue_mut( const_cast<::MIR::LValue&>(lv), u, [&](auto& v, auto u) { return cb(v,u); } ); } + bool visit_mir_lvalue_mut(::MIR::Param& p, ValUsage u, ::std::function<bool(::MIR::LValue& , ValUsage)> cb) + { + if( auto* e = p.opt_LValue() ) + { + return visit_mir_lvalue_mut(*e, u, cb); + } + else + { + return false; + } + } + bool visit_mir_lvalue(const ::MIR::Param& p, ValUsage u, ::std::function<bool(const ::MIR::LValue& , ValUsage)> cb) + { + if( const auto* e = p.opt_LValue() ) + { + return visit_mir_lvalue(*e, u, cb); + } + else + { + return false; + } + } + bool visit_mir_lvalues_mut(::MIR::RValue& rval, ::std::function<bool(::MIR::LValue& , ValUsage)> cb) { bool rv = false; @@ -751,7 +774,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) this->bb_base + se.panic_block, this->clone_lval(se.ret_val), mv$(tgt), - this->clone_lval_vec(se.args) + this->clone_param_vec(se.args) }); ) ) @@ -773,6 +796,14 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) rv.push_back( this->clone_lval(lv) ); return rv; } + ::std::vector<::MIR::Param> clone_param_vec(const ::std::vector<::MIR::Param>& src) const + { + ::std::vector<::MIR::Param> rv; + rv.reserve(src.size()); + for(const auto& lv : src) + rv.push_back( this->clone_param(lv) ); + return rv; + } ::MIR::LValue clone_lval(const ::MIR::LValue& src) const { TU_MATCHA( (src), (se), @@ -783,7 +814,9 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) return ::MIR::LValue::make_Temporary({se.idx + this->tmp_base}); ), (Argument, - return this->te.args.at(se.idx).clone(); + // TODO: If this argument is a literal, need to allocate a + // tmep for it + return this->te.args.at(se.idx).as_LValue().clone(); ), (Return, return this->te.ret_val.clone(); @@ -791,7 +824,6 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) (Static, return this->monomorph( se ); ), - (Deref, return ::MIR::LValue::make_Deref({ box$(this->clone_lval(*se.val)) }); ), @@ -810,6 +842,32 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) ) throw ""; } + ::MIR::Constant clone_constant(const ::MIR::Constant& src) const + { + TU_MATCHA( (src), (ce), + (Int , return ::MIR::Constant(ce);), + (Uint , return ::MIR::Constant(ce);), + (Float, return ::MIR::Constant(ce);), + (Bool , return ::MIR::Constant(ce);), + (Bytes, return ::MIR::Constant(ce);), + (StaticString, return ::MIR::Constant(ce);), + (Const, + return ::MIR::Constant::make_Const({ this->monomorph(ce.p) }); + ), + (ItemAddr, + return ::MIR::Constant::make_ItemAddr(this->monomorph(ce)); + ) + ) + throw ""; + } + ::MIR::Param clone_param(const ::MIR::Param& src) const + { + TU_MATCHA( (src), (se), + (LValue, return clone_lval(se);), + (Constant, return clone_constant(se); ) + ) + throw ""; + } ::MIR::RValue clone_rval(const ::MIR::RValue& src) const { TU_MATCHA( (src), (se), @@ -817,23 +875,10 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) return ::MIR::RValue( this->clone_lval(se) ); ), (Constant, - TU_MATCHA( (se), (ce), - (Int , return ::MIR::Constant(ce);), - (Uint , return ::MIR::Constant(ce);), - (Float, return ::MIR::Constant(ce);), - (Bool , return ::MIR::Constant(ce);), - (Bytes, return ::MIR::Constant(ce);), - (StaticString, return ::MIR::Constant(ce);), - (Const, - return ::MIR::Constant::make_Const({ this->monomorph(ce.p) }); - ), - (ItemAddr, - return ::MIR::Constant::make_ItemAddr(this->monomorph(ce)); - ) - ) + return this->clone_constant(se); ), (SizedArray, - return ::MIR::RValue::make_SizedArray({ this->clone_lval(se.val), se.count }); + return ::MIR::RValue::make_SizedArray({ this->clone_param(se.val), se.count }); ), (Borrow, // TODO: Region IDs @@ -843,7 +888,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) return ::MIR::RValue::make_Cast({ this->clone_lval(se.val), this->monomorph(se.type) }); ), (BinOp, - return ::MIR::RValue::make_BinOp({ this->clone_lval(se.val_l), se.op, this->clone_lval(se.val_r) }); + return ::MIR::RValue::make_BinOp({ this->clone_param(se.val_l), se.op, this->clone_param(se.val_r) }); ), (UniOp, return ::MIR::RValue::make_UniOp({ this->clone_lval(se.val), se.op }); @@ -855,19 +900,19 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) return ::MIR::RValue::make_DstPtr({ this->clone_lval(se.val) }); ), (MakeDst, - return ::MIR::RValue::make_MakeDst({ this->clone_lval(se.ptr_val), this->clone_lval(se.meta_val) }); + return ::MIR::RValue::make_MakeDst({ this->clone_lval(se.ptr_val), this->clone_param(se.meta_val) }); ), (Tuple, - return ::MIR::RValue::make_Tuple({ this->clone_lval_vec(se.vals) }); + return ::MIR::RValue::make_Tuple({ this->clone_param_vec(se.vals) }); ), (Array, - return ::MIR::RValue::make_Array({ this->clone_lval_vec(se.vals) }); + return ::MIR::RValue::make_Array({ this->clone_param_vec(se.vals) }); ), (Variant, - return ::MIR::RValue::make_Variant({ this->monomorph(se.path), se.index, this->clone_lval(se.val) }); + return ::MIR::RValue::make_Variant({ this->monomorph(se.path), se.index, this->clone_param(se.val) }); ), (Struct, - return ::MIR::RValue::make_Struct({ this->monomorph(se.path), se.variant_idx, this->clone_lval_vec(se.vals) }); + return ::MIR::RValue::make_Struct({ this->monomorph(se.path), se.variant_idx, this->clone_param_vec(se.vals) }); ) ) throw ""; @@ -1055,6 +1100,12 @@ bool MIR_Optimise_UnifyTemporaries(::MIR::TypeResolve& state, ::MIR::Function& f mark_validity(mir_res, lv, false); } } + void move_val(const ::MIR::TypeResolve& mir_res, const ::MIR::Param& p) { + if(const auto* e = p.opt_LValue()) + { + move_val(mir_res, *e); + } + } }; ::std::vector<State> block_states( fcn.blocks.size() ); ::std::vector< ::std::pair<unsigned int, State> > to_visit; @@ -1486,7 +1537,10 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn) else if( tef.name == "bswap" && tef.params.m_types.at(0) == ::HIR::CoreType::U8 ) { DEBUG("bswap<u8> is a no-op"); - bb.statements.push_back(::MIR::Statement::make_Assign({ mv$(te.ret_val), mv$(te.args.at(0)) })); + if( auto* e = te.args.at(0).opt_LValue() ) + bb.statements.push_back(::MIR::Statement::make_Assign({ mv$(te.ret_val), mv$(*e) })); + else + bb.statements.push_back(::MIR::Statement::make_Assign({ mv$(te.ret_val), mv$(te.args.at(0).as_Constant()) })); bb.terminator = ::MIR::Terminator::make_Goto(te.ret_block); changed = true; } diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 3ae69ba7..4b7d6a72 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1398,178 +1398,28 @@ namespace { emit_lvalue(ve); ), (Constant, - TU_MATCHA( (ve), (c), - (Int, - emit_lvalue(e.dst); - m_of << " = "; - if( c == INT64_MIN ) - m_of << "INT64_MIN"; - else - m_of << c; - ), - (Uint, - ::HIR::TypeRef tmp; - const auto& ty = mir_res.get_lvalue_type(tmp, e.dst); - emit_lvalue(e.dst); - m_of << " = "; - switch(ty.m_data.as_Primitive()) - { - case ::HIR::CoreType::U8: - m_of << ::std::hex << "0x" << (c & 0xFF) << ::std::dec; - break; - case ::HIR::CoreType::U16: - m_of << ::std::hex << "0x" << (c & 0xFFFF) << ::std::dec; - break; - case ::HIR::CoreType::U32: - m_of << ::std::hex << "0x" << (c & 0xFFFFFFFF) << ::std::dec; - break; - case ::HIR::CoreType::U64: - case ::HIR::CoreType::U128: - case ::HIR::CoreType::Usize: - m_of << ::std::hex << "0x" << c << ::std::dec; - break; - case ::HIR::CoreType::Char: - assert(0 <= c && c <= 0x10FFFF); - if( c < 256 ) { - m_of << c; - } - else { - m_of << ::std::hex << "0x" << c << ::std::dec; - } - break; - default: - MIR_BUG(*m_mir_res, "Invalid type for UInt literal - " << ty); - } - ), - (Float, - emit_lvalue(e.dst); - m_of << " = "; - if( ::std::isnan(c) ) { - m_of << "NAN"; - } - else if( ::std::isinf(c) ) { - m_of << "INFINITY"; - } - else { - m_of << c; - } - ), - (Bool, - emit_lvalue(e.dst); - m_of << " = "; - m_of << (c ? "true" : "false"); - ), - (Bytes, - ::HIR::TypeRef tmp; - const auto& ty = mir_res.get_lvalue_type(tmp, e.dst); - MIR_ASSERT(mir_res, ty.m_data.is_Borrow(), "Const::Bytes returning non-borrow - " << ty); - if( ty.m_data.as_Borrow().inner->m_data.is_Array() ) { - // Array borrow : Cast the C string to the array - emit_lvalue(e.dst); - m_of << " = "; - // - Laziness - m_of << "(void*)\"" << ::std::oct; - for(const auto& v : c) { - if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' ) - m_of << v; - else - m_of << "\\" << (unsigned int)v; - } - m_of << "\"" << ::std::dec; - } - else { - // Slice borrow (asumed), pointer and metadata - emit_lvalue(e.dst); - m_of << ".PTR = "; - m_of << "\"" << ::std::oct; - for(const auto& v : c) { - if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' ) - m_of << v; - else - m_of << "\\" << (unsigned int)v; - } - m_of << "\"" << ::std::dec; - m_of << ";\n\t"; - emit_lvalue(e.dst); - m_of << ".META = " << c.size(); - } - ), - (StaticString, - emit_lvalue(e.dst); - m_of << ".PTR = "; - m_of << "\"" << ::std::oct; - for(const auto& v : c) { - if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' ) - m_of << v; - else - m_of << "\\" << (unsigned int)v; - } - m_of << "\"" << ::std::dec; - - m_of << ";\n\t"; - emit_lvalue(e.dst); - m_of << ".META = " << c.size(); - ), - (Const, - // TODO: This should have been eliminated? - ::HIR::TypeRef tmp; - const auto& ty = mir_res.get_lvalue_type(tmp, e.dst); - const auto& lit = get_literal_for_const(c.p); - assign_from_literal([&](){ emit_lvalue(e.dst); }, ty, lit); - ), - (ItemAddr, - emit_lvalue(e.dst); - m_of << " = "; - 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() ) - ; - else - { - const auto& vi = m_crate.get_valitem_by_path(sp, pe.m_path); - if( vi.is_Function() || vi.is_StructConstructor() ) - { - } - else - { - m_of << "&"; - } - } - ), - (UfcsUnknown, - MIR_BUG(*m_mir_res, "UfcsUnknown in trans " << c); - ), - (UfcsInherent, - // TODO: If the target is a function, don't emit the & - m_of << "&"; - ), - (UfcsKnown, - // TODO: If the target is a function, don't emit the & - m_of << "&"; - ) - ) - m_of << Trans_Mangle(c); - ) - ) + emit_lvalue(e.dst); + m_of << " = "; + emit_constant(ve, &e.dst); ), (SizedArray, if( ve.count == 0 ) { } else if( ve.count == 1 ) { - emit_lvalue(e.dst); m_of << ".DATA[0] = "; emit_lvalue(ve.val); + emit_lvalue(e.dst); m_of << ".DATA[0] = "; emit_param(ve.val); } else if( ve.count == 2 ) { - emit_lvalue(e.dst); m_of << ".DATA[0] = "; emit_lvalue(ve.val); m_of << ";\n\t"; - emit_lvalue(e.dst); m_of << ".DATA[1] = "; emit_lvalue(ve.val); + emit_lvalue(e.dst); m_of << ".DATA[0] = "; emit_param(ve.val); m_of << ";\n\t"; + emit_lvalue(e.dst); m_of << ".DATA[1] = "; emit_param(ve.val); } else if( ve.count == 3 ) { - emit_lvalue(e.dst); m_of << ".DATA[0] = "; emit_lvalue(ve.val); m_of << ";\n\t"; - emit_lvalue(e.dst); m_of << ".DATA[1] = "; emit_lvalue(ve.val); m_of << ";\n\t"; - emit_lvalue(e.dst); m_of << ".DATA[2] = "; emit_lvalue(ve.val); + emit_lvalue(e.dst); m_of << ".DATA[0] = "; emit_param(ve.val); m_of << ";\n\t"; + emit_lvalue(e.dst); m_of << ".DATA[1] = "; emit_param(ve.val); m_of << ";\n\t"; + emit_lvalue(e.dst); m_of << ".DATA[2] = "; emit_param(ve.val); } else { m_of << "for(unsigned int i = 0; i < " << ve.count << "; i ++)\n"; - m_of << "\t\t"; emit_lvalue(e.dst); m_of << ".DATA[i] = "; emit_lvalue(ve.val); + m_of << "\t\t"; emit_lvalue(e.dst); m_of << ".DATA[i] = "; emit_param(ve.val); } ), (Borrow, @@ -1648,10 +1498,11 @@ namespace { (BinOp, emit_lvalue(e.dst); m_of << " = "; + MIR_ASSERT(mir_res, ve.val_l.is_LValue() || ve.val_r.is_LValue(), ""); ::HIR::TypeRef tmp; - const auto& ty = mir_res.get_lvalue_type(tmp, ve.val_l); + const auto& ty = mir_res.get_lvalue_type(tmp, ve.val_l.is_LValue() ? ve.val_l.as_LValue() : ve.val_r.as_LValue()); if( ty.m_data.is_Borrow() ) { - m_of << "(slice_cmp("; emit_lvalue(ve.val_l); m_of << ", "; emit_lvalue(ve.val_r); m_of << ")"; + m_of << "(slice_cmp("; emit_param(ve.val_l); m_of << ", "; emit_param(ve.val_r); m_of << ")"; switch(ve.op) { case ::MIR::eBinOp::EQ: m_of << " == 0"; break; @@ -1672,12 +1523,12 @@ namespace { switch(ve.op) { case ::MIR::eBinOp::EQ: - emit_lvalue(ve.val_l); m_of << ".PTR == "; emit_lvalue(ve.val_r); m_of << ".PTR && "; - emit_lvalue(ve.val_l); m_of << ".META == "; emit_lvalue(ve.val_r); m_of << ".META"; + emit_param(ve.val_l); m_of << ".PTR == "; emit_param(ve.val_r); m_of << ".PTR && "; + emit_param(ve.val_l); m_of << ".META == "; emit_param(ve.val_r); m_of << ".META"; break; case ::MIR::eBinOp::NE: - emit_lvalue(ve.val_l); m_of << ".PTR != "; emit_lvalue(ve.val_r); m_of << ".PTR || "; - emit_lvalue(ve.val_l); m_of << ".META != "; emit_lvalue(ve.val_r); m_of << ".META"; + emit_param(ve.val_l); m_of << ".PTR != "; emit_param(ve.val_r); m_of << ".PTR || "; + emit_param(ve.val_l); m_of << ".META != "; emit_param(ve.val_r); m_of << ".META"; break; default: MIR_BUG(mir_res, "Unknown comparison of a *-ptr - " << e.src << " with " << ty); @@ -1685,7 +1536,7 @@ namespace { } else { - emit_lvalue(ve.val_l); + emit_param(ve.val_l); switch(ve.op) { case ::MIR::eBinOp::EQ: m_of << " == "; break; @@ -1697,7 +1548,7 @@ namespace { default: MIR_BUG(mir_res, "Unknown comparison of a *-ptr - " << e.src << " with " << ty); } - emit_lvalue(ve.val_r); + emit_param(ve.val_r); } break; } @@ -1706,13 +1557,13 @@ namespace { m_of << "remainderf"; else m_of << "remainder"; - m_of << "("; emit_lvalue(ve.val_l); m_of << ", "; emit_lvalue(ve.val_r); m_of << ")"; + m_of << "("; emit_param(ve.val_l); m_of << ", "; emit_param(ve.val_r); m_of << ")"; break; } else { } - emit_lvalue(ve.val_l); + emit_param(ve.val_l); switch(ve.op) { case ::MIR::eBinOp::ADD: m_of << " + "; break; @@ -1740,7 +1591,7 @@ namespace { MIR_TODO(mir_res, "Overflow"); break; } - emit_lvalue(ve.val_r); + emit_param(ve.val_r); ), (UniOp, ::HIR::TypeRef tmp; @@ -1777,21 +1628,21 @@ namespace { m_of << ";\n\t"; emit_lvalue(e.dst); m_of << ".META = "; - emit_lvalue(ve.meta_val); + emit_param(ve.meta_val); ), (Tuple, for(unsigned int j = 0; j < ve.vals.size(); j ++) { if( j != 0 ) m_of << ";\n\t"; emit_lvalue(e.dst); m_of << "._" << j << " = "; - emit_lvalue(ve.vals[j]); + emit_param(ve.vals[j]); } ), (Array, for(unsigned int j = 0; j < ve.vals.size(); j ++) { if( j != 0 ) m_of << ";\n\t"; emit_lvalue(e.dst); m_of << ".DATA[" << j << "] = "; - emit_lvalue(ve.vals[j]); + emit_param(ve.vals[j]); } ), (Variant, @@ -1805,7 +1656,7 @@ namespace { emit_lvalue(e.dst); m_of << ".TAG = " << ve.index << ";\n\t"; emit_lvalue(e.dst); m_of << ".DATA"; } - m_of << ".var_" << ve.index << " = "; emit_lvalue(ve.val); + m_of << ".var_" << ve.index << " = "; emit_param(ve.val); ), (Struct, if(ve.variant_idx != ~0u) { @@ -1822,7 +1673,7 @@ namespace { else if( ve.variant_idx == 1 ) { emit_lvalue(e.dst); m_of << "._0 = "; - emit_lvalue(ve.vals[0]); + emit_param(ve.vals[0]); } else { } @@ -1840,7 +1691,7 @@ namespace { { // HACK: Don't emit assignment of PhantomData ::HIR::TypeRef tmp; - if( m_resolve.is_type_phantom_data( mir_res.get_lvalue_type(tmp, ve.vals[j])) ) + if( ve.vals[j].is_LValue() && m_resolve.is_type_phantom_data( mir_res.get_lvalue_type(tmp, ve.vals[j].as_LValue())) ) continue ; if( j != 0 ) m_of << ";\n\t"; @@ -1848,7 +1699,7 @@ namespace { if(ve.variant_idx != ~0u) m_of << ".DATA.var_" << ve.variant_idx; m_of << "._" << j << " = "; - emit_lvalue(ve.vals[j]); + emit_param(ve.vals[j]); } ) ) @@ -1971,7 +1822,7 @@ namespace { m_of << "("; for(unsigned int j = 0; j < e.args.size(); j ++) { if(j != 0) m_of << ","; - m_of << " "; emit_lvalue(e.args[j]); + m_of << " "; emit_param(e.args[j]); } m_of << " );\n"; m_of << "\tgoto bb" << e.ret_block << ";\n"; @@ -2063,17 +1914,17 @@ namespace { } }; auto emit_atomic_cxchg = [&](const auto& e, const char* o_succ, const char* o_fail, bool is_weak) { - emit_lvalue(e.ret_val); m_of << "._0 = "; emit_lvalue(e.args.at(1)); m_of << ";\n\t"; + emit_lvalue(e.ret_val); m_of << "._0 = "; emit_param(e.args.at(1)); m_of << ";\n\t"; emit_lvalue(e.ret_val); m_of << "._1 = atomic_compare_exchange_" << (is_weak ? "weak" : "strong") << "_explicit("; - m_of << "(_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_lvalue(e.args.at(0)); + m_of << "(_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0"; - m_of << ", "; emit_lvalue(e.args.at(2)); + m_of << ", "; emit_param(e.args.at(2)); m_of << ", "<<o_succ<<", "<<o_fail<<")"; }; auto emit_atomic_arith = [&](const char* name, const char* ordering) { emit_lvalue(e.ret_val); m_of << " = atomic_" << name << "_explicit"; - m_of <<"((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); + m_of <<"((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")"; }; if( name == "size_of" ) { @@ -2096,19 +1947,19 @@ namespace { if( ! ty.m_data.is_Slice() ) { m_of << "sizeof("; emit_ctype(ty); m_of << ") + "; } - emit_lvalue(e.args.at(0)); m_of << ".META * sizeof("; emit_ctype(*te->inner); m_of << ")"; + emit_param(e.args.at(0)); m_of << ".META * sizeof("; emit_ctype(*te->inner); m_of << ")"; } else if( inner_ty == ::HIR::CoreType::Str ) { if( ! ty.m_data.is_Primitive() ) { m_of << "sizeof("; emit_ctype(ty); m_of << ") + "; } - emit_lvalue(e.args.at(0)); m_of << ".META"; + emit_param(e.args.at(0)); m_of << ".META"; } else if( inner_ty.m_data.is_TraitObject() ) { if( ! ty.m_data.is_TraitObject() ) { m_of << "sizeof("; emit_ctype(ty); m_of << ") + "; } - m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->size"; + m_of << "((VTABLE_HDR*)"; emit_param(e.args.at(0)); m_of << ".META)->size"; } else { MIR_BUG(mir_res, "Unknown inner unsized type " << inner_ty << " for " << ty); @@ -2122,10 +1973,10 @@ namespace { case MetadataType::Slice: { // TODO: Have a function that fetches the inner type for types like `Path` or `str` const auto& ity = *ty.m_data.as_Slice().inner; - emit_lvalue(e.args.at(0)); m_of << ".META * sizeof("; emit_ctype(ity); m_of << ")"; + emit_param(e.args.at(0)); m_of << ".META * sizeof("; emit_ctype(ity); m_of << ")"; break; } case MetadataType::TraitObject: - m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->size"; + m_of << "((VTABLE_HDR*)"; emit_param(e.args.at(0)); m_of << ".META)->size"; break; } #endif @@ -2159,7 +2010,7 @@ namespace { if( ! ty.m_data.is_TraitObject() ) { m_of << "max( __alignof__("; emit_ctype(ty); m_of << "), "; } - m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->align"; + m_of << "((VTABLE_HDR*)"; emit_param(e.args.at(0)); m_of << ".META)->align"; if( ! ty.m_data.is_TraitObject() ) { m_of << " )"; } @@ -2179,7 +2030,7 @@ namespace { m_of << "__alignof__("; emit_ctype(ity); m_of << ")"; break; } case MetadataType::TraitObject: - m_of << "((VTABLE_HDR*)"; emit_lvalue(e.args.at(0)); m_of << ".META)->align"; + m_of << "((VTABLE_HDR*)"; emit_param(e.args.at(0)); m_of << ".META)->align"; break; } #endif @@ -2195,7 +2046,7 @@ namespace { emit_lvalue(e.ret_val); m_of << ".META = " << s.size() << ""; } else if( name == "transmute" ) { - m_of << "memcpy( &"; emit_lvalue(e.ret_val); m_of << ", &"; emit_lvalue(e.args.at(0)); m_of << ", sizeof("; emit_ctype(params.m_types.at(0)); m_of << "))"; + m_of << "memcpy( &"; emit_lvalue(e.ret_val); m_of << ", &"; emit_param(e.args.at(0)); m_of << ", sizeof("; emit_ctype(params.m_types.at(0)); m_of << "))"; } else if( name == "copy_nonoverlapping" || name == "copy" ) { if( name == "copy" ) { @@ -2205,23 +2056,23 @@ namespace { m_of << "memcpy"; } // 0: Source, 1: Destination, 2: Count - m_of << "( "; emit_lvalue(e.args.at(1)); - m_of << ", "; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(2)); m_of << " * sizeof("; emit_ctype(params.m_types.at(0)); m_of << ")"; + m_of << "( "; emit_param(e.args.at(1)); + m_of << ", "; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(2)); m_of << " * sizeof("; emit_ctype(params.m_types.at(0)); m_of << ")"; m_of << ")"; } else if( name == "write_bytes" ) { // 0: Destination, 1: Value, 2: Count - m_of << "memset( "; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); - m_of << ", "; emit_lvalue(e.args.at(2)); m_of << " * sizeof("; emit_ctype(params.m_types.at(0)); m_of << ")"; + m_of << "memset( "; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); + m_of << ", "; emit_param(e.args.at(2)); m_of << " * sizeof("; emit_ctype(params.m_types.at(0)); m_of << ")"; m_of << ")"; } else if( name == "forget" ) { // Nothing needs to be done, this just stops the destructor from running. } else if( name == "drop_in_place" ) { - emit_destructor_call( ::MIR::LValue::make_Deref({ box$(e.args.at(0).clone()) }), params.m_types.at(0), true ); + emit_destructor_call( ::MIR::LValue::make_Deref({ box$(e.args.at(0).as_LValue().clone()) }), params.m_types.at(0), true ); } else if( name == "needs_drop" ) { // Returns `true` if the actual type given as `T` requires drop glue; @@ -2244,19 +2095,19 @@ namespace { m_of << "memset( &"; emit_lvalue(e.ret_val); m_of << ", 0, sizeof("; emit_ctype(params.m_types.at(0)); m_of << "))"; } else if( name == "move_val_init" ) { - m_of << "*"; emit_lvalue(e.args.at(0)); m_of << " = "; emit_lvalue(e.args.at(1)); + m_of << "*"; emit_param(e.args.at(0)); m_of << " = "; emit_param(e.args.at(1)); } else if( name == "abort" ) { m_of << "abort()"; } else if( name == "try" ) { - emit_lvalue(e.args.at(0)); m_of << "("; emit_lvalue(e.args.at(1)); m_of << ")"; + emit_param(e.args.at(0)); m_of << "("; emit_param(e.args.at(1)); m_of << ")"; } else if( name == "offset" ) { - emit_lvalue(e.ret_val); m_of << " = "; emit_lvalue(e.args.at(0)); m_of << " + "; emit_lvalue(e.args.at(1)); + emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " + "; emit_param(e.args.at(1)); } else if( name == "arith_offset" ) { - emit_lvalue(e.ret_val); m_of << " = "; emit_lvalue(e.args.at(0)); m_of << " + "; emit_lvalue(e.args.at(1)); + emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " + "; emit_param(e.args.at(1)); } else if( name == "bswap" ) { const auto& ty = params.m_types.at(0); @@ -2264,19 +2115,19 @@ namespace { switch( ty.m_data.as_Primitive() ) { case ::HIR::CoreType::U8: - emit_lvalue(e.ret_val); m_of << " = "; emit_lvalue(e.args.at(0)); + emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); break; case ::HIR::CoreType::U16: - emit_lvalue(e.ret_val); m_of << " = __builtin_bswap16("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = __builtin_bswap16("; emit_param(e.args.at(0)); m_of << ")"; break; case ::HIR::CoreType::U32: - emit_lvalue(e.ret_val); m_of << " = __builtin_bswap32("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = __builtin_bswap32("; emit_param(e.args.at(0)); m_of << ")"; break; case ::HIR::CoreType::U64: - emit_lvalue(e.ret_val); m_of << " = __builtin_bswap64("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = __builtin_bswap64("; emit_param(e.args.at(0)); m_of << ")"; break; case ::HIR::CoreType::U128: - emit_lvalue(e.ret_val); m_of << " = __builtin_bswap128("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = __builtin_bswap128("; emit_param(e.args.at(0)); m_of << ")"; break; default: MIR_TODO(mir_res, "bswap<" << ty << ">"); @@ -2290,11 +2141,11 @@ namespace { auto it = m_enum_repr_cache.find( ty.m_data.as_Path().path.m_data.as_Generic() ); if( it != m_enum_repr_cache.end() ) { - emit_lvalue(e.args.at(0)); emit_nonzero_path(it->second); m_of << " != 0"; + emit_param(e.args.at(0)); emit_nonzero_path(it->second); m_of << " != 0"; } else { - emit_lvalue(e.args.at(0)); m_of << "->TAG"; + emit_param(e.args.at(0)); m_of << "->TAG"; } } else { @@ -2315,56 +2166,56 @@ namespace { // Overflowing Arithmatic // HACK: Uses GCC intrinsics else if( name == "add_with_overflow" ) { - emit_lvalue(e.ret_val); m_of << "._1 = __builtin_add_overflow("; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); + emit_lvalue(e.ret_val); m_of << "._1 = __builtin_add_overflow("; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0)"; } else if( name == "sub_with_overflow" ) { - emit_lvalue(e.ret_val); m_of << "._1 = __builtin_sub_overflow("; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); + emit_lvalue(e.ret_val); m_of << "._1 = __builtin_sub_overflow("; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0)"; } else if( name == "mul_with_overflow" ) { - emit_lvalue(e.ret_val); m_of << "._1 = __builtin_mul_overflow("; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); + emit_lvalue(e.ret_val); m_of << "._1 = __builtin_mul_overflow("; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0)"; } else if( name == "overflowing_add" ) { - m_of << "__builtin_add_overflow("; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << "__builtin_add_overflow("; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); m_of << ", &"; emit_lvalue(e.ret_val); m_of << ")"; } else if( name == "overflowing_sub" ) { - m_of << "__builtin_sub_overflow("; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << "__builtin_sub_overflow("; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); m_of << ", &"; emit_lvalue(e.ret_val); m_of << ")"; } else if( name == "overflowing_mul" ) { - m_of << "__builtin_mul_overflow("; emit_lvalue(e.args.at(0)); - m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << "__builtin_mul_overflow("; emit_param(e.args.at(0)); + m_of << ", "; emit_param(e.args.at(1)); m_of << ", &"; emit_lvalue(e.ret_val); m_of << ")"; } // Unchecked Arithmatic else if( name == "unchecked_div" ) { - emit_lvalue(e.ret_val); m_of << " = "; emit_lvalue(e.args.at(0)); m_of << " / "; emit_lvalue(e.args.at(1)); + emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " / "; emit_param(e.args.at(1)); } else if( name == "unchecked_rem" ) { - emit_lvalue(e.ret_val); m_of << " = "; emit_lvalue(e.args.at(0)); m_of << " % "; emit_lvalue(e.args.at(1)); + emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " % "; emit_param(e.args.at(1)); } // Bit Twiddling // - CounT Leading Zeroes // - CounT Trailing Zeroes else if( name == "ctlz" || name == "cttz" ) { - auto emit_arg0 = [&](){ emit_lvalue(e.args.at(0)); }; + auto emit_arg0 = [&](){ emit_param(e.args.at(0)); }; const auto& ty = params.m_types.at(0); - emit_lvalue(e.ret_val); m_of << " = ("; emit_lvalue(e.args.at(0)); m_of << " != 0 ? "; + emit_lvalue(e.ret_val); m_of << " = ("; emit_param(e.args.at(0)); m_of << " != 0 ? "; if( ty == ::HIR::CoreType::U128 ) { if( name == "ctlz" ) { - m_of << "__builtin_clz128("; emit_lvalue(e.args.at(0)); m_of << ")"; + m_of << "__builtin_clz128("; emit_param(e.args.at(0)); m_of << ")"; } else { - m_of << "__builtin_ctz128("; emit_lvalue(e.args.at(0)); m_of << ")"; + m_of << "__builtin_ctz128("; emit_param(e.args.at(0)); m_of << ")"; } } else if( ty == ::HIR::CoreType::U64 || (ty == ::HIR::CoreType::Usize /*&& target_is_64_bit */) ) @@ -2379,74 +2230,74 @@ namespace { else { if( name == "ctlz" ) { - m_of << "__builtin_clz("; emit_lvalue(e.args.at(0)); m_of << ")"; + m_of << "__builtin_clz("; emit_param(e.args.at(0)); m_of << ")"; } else { - m_of << "__builtin_ctz("; emit_lvalue(e.args.at(0)); m_of << ")"; + m_of << "__builtin_ctz("; emit_param(e.args.at(0)); m_of << ")"; } } m_of << " : sizeof("; emit_ctype(ty); m_of << ")*8)"; } // - CounT POPulated else if( name == "ctpop" ) { - emit_lvalue(e.ret_val); m_of << " = __builtin_popcount("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = __builtin_popcount("; emit_param(e.args.at(0)); m_of << ")"; } // --- Floating Point // > Round to nearest integer, half-way rounds away from zero else if( name == "roundf32" && name == "roundf64" ) { - emit_lvalue(e.ret_val); m_of << " = round" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = round" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "fabsf32" || name == "fabsf64" ) { - emit_lvalue(e.ret_val); m_of << " = fabs" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = fabs" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "copysignf32" || name == "copysignf64" ) { - emit_lvalue(e.ret_val); m_of << " = copysign" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = copysign" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")"; } // > Returns the integer part of an `f32`. else if( name == "truncf32" || name == "truncf64" ) { - emit_lvalue(e.ret_val); m_of << " = trunc" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = trunc" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "powif32" || name == "powif64" ) { - emit_lvalue(e.ret_val); m_of << " = pow" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = pow" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")"; } else if( name == "powf32" || name == "powf64" ) { - emit_lvalue(e.ret_val); m_of << " = pow" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = pow" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")"; } else if( name == "expf32" || name == "expf64" ) { - emit_lvalue(e.ret_val); m_of << " = exp" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = exp" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "exp2f32" || name == "exp2f64" ) { - emit_lvalue(e.ret_val); m_of << " = exp2" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = exp2" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "logf32" || name == "logf64" ) { - emit_lvalue(e.ret_val); m_of << " = log" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = log" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "log10f32" || name == "log10f64" ) { - emit_lvalue(e.ret_val); m_of << " = log10" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = log10" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "log2f32" || name == "log2f64" ) { - emit_lvalue(e.ret_val); m_of << " = log2" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = log2" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "sqrtf32" || name == "sqrtf64" ) { - emit_lvalue(e.ret_val); m_of << " = sqrt" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = sqrt" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "ceilf32" || name == "ceilf64" ) { - emit_lvalue(e.ret_val); m_of << " = ceil" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = ceil" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "floorf32" || name == "floorf64" ) { - emit_lvalue(e.ret_val); m_of << " = floor" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = floor" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "roundf32" || name == "roundf64" ) { - emit_lvalue(e.ret_val); m_of << " = round" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = round" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "cosf32" || name == "cosf64" ) { - emit_lvalue(e.ret_val); m_of << " = cos" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = cos" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "sinf32" || name == "sinf64" ) { - emit_lvalue(e.ret_val); m_of << " = sin" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = sin" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ")"; } else if( name == "fmaf32" || name == "fmaf64" ) { - emit_lvalue(e.ret_val); m_of << " = fma" << (name.back()=='2'?"f":"") << "("; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = fma" << (name.back()=='2'?"f":"") << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")"; } // --- Atomics! // > Single-ordering atomics @@ -2472,11 +2323,11 @@ namespace { } else if( name == "atomic_load" || name.compare(0, 7+4+1, "atomic_load_") == 0 ) { auto ordering = H::get_atomic_ordering(mir_res, name, 7+4+1); - emit_lvalue(e.ret_val); m_of << " = atomic_load_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_lvalue(e.args.at(0)); m_of << ", " << ordering << ")"; + emit_lvalue(e.ret_val); m_of << " = atomic_load_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << ", " << ordering << ")"; } else if( name == "atomic_store" || name.compare(0, 7+5+1, "atomic_store_") == 0 ) { auto ordering = H::get_atomic_ordering(mir_res, name, 7+5+1); - m_of << "atomic_store_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ", " << ordering << ")"; + m_of << "atomic_store_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")"; } // Comare+Exchange (has two orderings) else if( name == "atomic_cxchg_acq_failrelaxed" ) { @@ -2517,7 +2368,7 @@ namespace { } else if( name == "atomic_xchg" || name.compare(0, 7+5, "atomic_xchg_") == 0 ) { auto ordering = H::get_atomic_ordering(mir_res, name, 7+5); - emit_lvalue(e.ret_val); m_of << " = atomic_exchange_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ", " << ordering << ")"; + emit_lvalue(e.ret_val); m_of << " = atomic_exchange_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")"; } else if( name == "atomic_fence" || name.compare(0, 7+6, "atomic_fence_") == 0 ) { auto ordering = H::get_atomic_ordering(mir_res, name, 7+6); @@ -2614,13 +2465,15 @@ namespace { ) } - const ::HIR::Literal& get_literal_for_const(const ::HIR::Path& path) + const ::HIR::Literal& get_literal_for_const(const ::HIR::Path& path, ::HIR::TypeRef& ty) { TU_MATCHA( (path.m_data), (pe), (Generic, if( pe.m_params.m_types.size() > 0 ) MIR_TODO(*m_mir_res, "get_literal_for_const - Paths with generics " << path); - return m_crate.get_constant_by_path(Span(), pe.m_path).m_value_res; + const auto& c = m_crate.get_constant_by_path(Span(), pe.m_path); + ty = c.m_type.clone(); + return c.m_value_res; ), (UfcsUnknown, MIR_BUG(*m_mir_res, "get_literal_for_const - UfcsUnknown " << path); @@ -2931,6 +2784,153 @@ namespace { ) ) } + void emit_constant(const ::MIR::Constant& ve, const ::MIR::LValue* dst_ptr=nullptr) + { + TU_MATCHA( (ve), (c), + (Int, + if( c == INT64_MIN ) + m_of << "INT64_MIN"; + else + m_of << c; + ), + (Uint, + ::HIR::TypeRef tmp; + const auto& ty = dst_ptr ? m_mir_res->get_lvalue_type(tmp, *dst_ptr) : tmp = ::HIR::CoreType::U128; + switch(ty.m_data.as_Primitive()) + { + case ::HIR::CoreType::U8: + m_of << ::std::hex << "0x" << (c & 0xFF) << ::std::dec; + break; + case ::HIR::CoreType::U16: + m_of << ::std::hex << "0x" << (c & 0xFFFF) << ::std::dec; + break; + case ::HIR::CoreType::U32: + m_of << ::std::hex << "0x" << (c & 0xFFFFFFFF) << ::std::dec; + break; + case ::HIR::CoreType::U64: + case ::HIR::CoreType::U128: + case ::HIR::CoreType::Usize: + m_of << ::std::hex << "0x" << c << ::std::dec; + break; + case ::HIR::CoreType::Char: + assert(0 <= c && c <= 0x10FFFF); + if( c < 256 ) { + m_of << c; + } + else { + m_of << ::std::hex << "0x" << c << ::std::dec; + } + break; + default: + MIR_BUG(*m_mir_res, "Invalid type for UInt literal - " << ty); + } + ), + (Float, + if( ::std::isnan(c) ) { + m_of << "NAN"; + } + else if( ::std::isinf(c) ) { + m_of << "INFINITY"; + } + else { + m_of << c; + } + ), + (Bool, + m_of << (c ? "true" : "false"); + ), + (Bytes, + // TODO: Need to know the desired value for this + // - Ideally, Bytes would always return a thin pointer (and + // be combined with a MakeDST to make a fat pointer) + ::HIR::TypeRef tmp; + const auto& ty = dst_ptr ? m_mir_res->get_lvalue_type(tmp, *dst_ptr) : tmp = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ::HIR::CoreType::U8); + MIR_ASSERT(*m_mir_res, ty.m_data.is_Borrow(), "Const::Bytes returning non-borrow - " << ty); + if( !dst_ptr || ty.m_data.as_Borrow().inner->m_data.is_Array() ) { + // Array borrow : Cast the C string to the array + // - Laziness + m_of << "(void*)\"" << ::std::oct; + for(const auto& v : c) { + if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' ) + m_of << v; + else + m_of << "\\" << (unsigned int)v; + } + m_of << "\"" << ::std::dec; + } + else { + // Slice borrow (asumed), pointer and metadata + m_of << "make_sliceptr(\"" << ::std::oct; + for(const auto& v : c) { + if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' ) + m_of << v; + else + m_of << "\\" << (unsigned int)v; + } + m_of << "\", " << ::std::dec << c.size() << ")"; + } + ), + (StaticString, + m_of << "make_sliceptr(\"" << ::std::oct; + for(const auto& v : c) { + if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' ) + m_of << v; + else + m_of << "\\" << (unsigned int)v; + } + m_of << "\", " << ::std::dec << c.size() << ")"; + ), + (Const, + // TODO: This should have been eliminated? + ::HIR::TypeRef ty; + const auto& lit = get_literal_for_const(c.p, ty); + m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << ";"; + assign_from_literal([&](){ m_of << "v"; }, ty, lit); + m_of << "v})"; + ), + (ItemAddr, + 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() ) + ; + else + { + const auto& vi = m_crate.get_valitem_by_path(sp, pe.m_path); + if( vi.is_Function() || vi.is_StructConstructor() ) + { + } + else + { + m_of << "&"; + } + } + ), + (UfcsUnknown, + MIR_BUG(*m_mir_res, "UfcsUnknown in trans " << c); + ), + (UfcsInherent, + // TODO: If the target is a function, don't emit the & + m_of << "&"; + ), + (UfcsKnown, + // TODO: If the target is a function, don't emit the & + m_of << "&"; + ) + ) + m_of << Trans_Mangle(c); + ) + ) + } + void emit_param(const ::MIR::Param& p) { + TU_MATCHA( (p), (e), + (LValue, + emit_lvalue(e); + ), + (Constant, + emit_constant(e); + ) + ) + } void emit_ctype(const ::HIR::TypeRef& ty) { emit_ctype(ty, FMT_CB(_,)); } diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 8b9fd93b..fceddfbf 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -848,6 +848,17 @@ void Trans_Enumerate_Types(EnumState& state) ) return blank; } + + static void visit_param(TypeVisitor& tv, const Trans_Params& pp, const ::HIR::Function& fcn, const ::MIR::Param& p) + { + TU_MATCHA( (p), (e), + (LValue, + H::visit_lvalue(tv, pp, fcn, e); + ), + (Constant, + ) + ) + } }; for(const auto& stmt : block.statements) { @@ -872,7 +883,7 @@ void Trans_Enumerate_Types(EnumState& state) (Constant, ), (SizedArray, - H::visit_lvalue(tv,pp,fcn, re.val); + H::visit_param(tv,pp,fcn, re.val); ), (Borrow, H::visit_lvalue(tv,pp,fcn, re.val); @@ -881,8 +892,8 @@ void Trans_Enumerate_Types(EnumState& state) H::visit_lvalue(tv,pp,fcn, re.val); ), (BinOp, - H::visit_lvalue(tv,pp,fcn, re.val_l); - H::visit_lvalue(tv,pp,fcn, re.val_l); + H::visit_param(tv,pp,fcn, re.val_l); + H::visit_param(tv,pp,fcn, re.val_l); ), (UniOp, H::visit_lvalue(tv,pp,fcn, re.val); @@ -895,22 +906,22 @@ void Trans_Enumerate_Types(EnumState& state) ), (MakeDst, H::visit_lvalue(tv,pp,fcn, re.ptr_val); - H::visit_lvalue(tv,pp,fcn, re.meta_val); + H::visit_param(tv,pp,fcn, re.meta_val); ), (Tuple, for(const auto& v : re.vals) - H::visit_lvalue(tv,pp,fcn, v); + H::visit_param(tv,pp,fcn, v); ), (Array, for(const auto& v : re.vals) - H::visit_lvalue(tv,pp,fcn, v); + H::visit_param(tv,pp,fcn, v); ), (Variant, - H::visit_lvalue(tv,pp,fcn, re.val); + H::visit_param(tv,pp,fcn, re.val); ), (Struct, for(const auto& v : re.vals) - H::visit_lvalue(tv,pp,fcn, v); + H::visit_param(tv,pp,fcn, v); ) ) ) @@ -938,7 +949,7 @@ void Trans_Enumerate_Types(EnumState& state) } H::visit_lvalue(tv,pp,fcn, te.ret_val); for(const auto& arg : te.args) - H::visit_lvalue(tv,pp,fcn, arg); + H::visit_param(tv,pp,fcn, arg); ) ) } @@ -1353,6 +1364,30 @@ void Trans_Enumerate_FillFrom_MIR_LValue(EnumState& state, const ::MIR::LValue& ) ) } +void Trans_Enumerate_FillFrom_MIR_Constant(EnumState& state, const ::MIR::Constant& c, const Trans_Params& pp) +{ + TU_MATCHA( (c), (ce), + (Int, ), + (Uint,), + (Float, ), + (Bool, ), + (Bytes, ), + (StaticString, ), // String + (Const, + //Trans_Enumerate_FillFrom_Path(state, ce.p, pp); + ), + (ItemAddr, + Trans_Enumerate_FillFrom_Path(state, ce, pp); + ) + ) +} +void Trans_Enumerate_FillFrom_MIR_Param(EnumState& state, const ::MIR::Param& p, const Trans_Params& pp) +{ + TU_MATCHA( (p), (e), + (LValue, Trans_Enumerate_FillFrom_MIR_LValue(state, e, pp); ), + (Constant, Trans_Enumerate_FillFrom_MIR_Constant(state, e, pp); ) + ) +} void Trans_Enumerate_FillFrom_MIR(EnumState& state, const ::MIR::Function& code, const Trans_Params& pp) { for(const auto& bb : code.blocks) @@ -1368,23 +1403,10 @@ void Trans_Enumerate_FillFrom_MIR(EnumState& state, const ::MIR::Function& code, Trans_Enumerate_FillFrom_MIR_LValue(state, e, pp); ), (Constant, - TU_MATCHA( (e), (ce), - (Int, ), - (Uint,), - (Float, ), - (Bool, ), - (Bytes, ), - (StaticString, ), // String - (Const, - //Trans_Enumerate_FillFrom_Path(state, ce.p, pp); - ), - (ItemAddr, - Trans_Enumerate_FillFrom_Path(state, ce, pp); - ) - ) + Trans_Enumerate_FillFrom_MIR_Constant(state, e, pp); ), (SizedArray, - Trans_Enumerate_FillFrom_MIR_LValue(state, e.val, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, e.val, pp); ), (Borrow, Trans_Enumerate_FillFrom_MIR_LValue(state, e.val, pp); @@ -1393,8 +1415,8 @@ void Trans_Enumerate_FillFrom_MIR(EnumState& state, const ::MIR::Function& code, Trans_Enumerate_FillFrom_MIR_LValue(state, e.val, pp); ), (BinOp, - Trans_Enumerate_FillFrom_MIR_LValue(state, e.val_l, pp); - Trans_Enumerate_FillFrom_MIR_LValue(state, e.val_r, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, e.val_l, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, e.val_r, pp); ), (UniOp, Trans_Enumerate_FillFrom_MIR_LValue(state, e.val, pp); @@ -1407,22 +1429,22 @@ void Trans_Enumerate_FillFrom_MIR(EnumState& state, const ::MIR::Function& code, ), (MakeDst, Trans_Enumerate_FillFrom_MIR_LValue(state, e.ptr_val, pp); - Trans_Enumerate_FillFrom_MIR_LValue(state, e.meta_val, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, e.meta_val, pp); ), (Tuple, for(const auto& val : e.vals) - Trans_Enumerate_FillFrom_MIR_LValue(state, val, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, val, pp); ), (Array, for(const auto& val : e.vals) - Trans_Enumerate_FillFrom_MIR_LValue(state, val, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, val, pp); ), (Variant, - Trans_Enumerate_FillFrom_MIR_LValue(state, e.val, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, e.val, pp); ), (Struct, for(const auto& val : e.vals) - Trans_Enumerate_FillFrom_MIR_LValue(state, val, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, val, pp); ) ) ), @@ -1472,7 +1494,7 @@ void Trans_Enumerate_FillFrom_MIR(EnumState& state, const ::MIR::Function& code, ) ) for(const auto& arg : e.args) - Trans_Enumerate_FillFrom_MIR_LValue(state, arg, pp); + Trans_Enumerate_FillFrom_MIR_Param(state, arg, pp); ) ) } diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index 3e52dfaf..13819c18 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -46,12 +46,68 @@ namespace { ) throw ""; } - ::std::vector<::MIR::LValue> monomorph_LValue_list(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::std::vector<::MIR::LValue>& tpl) + ::MIR::Constant monomorph_Constant(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::MIR::Constant& tpl) { - ::std::vector<::MIR::LValue> rv; + TU_MATCHA( (tpl), (ce), + (Int, + return ::MIR::Constant::make_Int(ce); + ), + (Uint, + return ::MIR::Constant::make_Uint(ce); + ), + (Float, + return ::MIR::Constant::make_Float(ce); + ), + (Bool, + return ::MIR::Constant::make_Bool(ce); + ), + (Bytes, + return ::MIR::Constant(ce); + ), + (StaticString, + return ::MIR::Constant(ce); + ), + (Const, + return ::MIR::Constant::make_Const({ + params.monomorph(resolve, ce.p) + }); + ), + (ItemAddr, + 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) ); + ) + ) + throw ""; + } + ::MIR::Param monomorph_Param(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::MIR::Param& tpl) + { + TU_MATCHA( (tpl), (e), + (LValue, + return monomorph_LValue(resolve, params, e); + ), + (Constant, + return monomorph_Constant(resolve, params, e); + ) + ) + throw ""; + } + //::std::vector<::MIR::LValue> monomorph_LValue_list(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::std::vector<::MIR::LValue>& tpl) + //{ + // ::std::vector<::MIR::LValue> rv; + // rv.reserve( tpl.size() ); + // for(const auto& v : tpl) + // rv.push_back( monomorph_LValue(resolve, params, v) ); + // return rv; + //} + ::std::vector<::MIR::Param> monomorph_Param_list(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::std::vector<::MIR::Param>& tpl) + { + ::std::vector<::MIR::Param> rv; rv.reserve( tpl.size() ); for(const auto& v : tpl) - rv.push_back( monomorph_LValue(resolve, params, v) ); + rv.push_back( monomorph_Param(resolve, params, v) ); return rv; } } @@ -113,42 +169,11 @@ namespace { rval = ::MIR::RValue( monomorph_LValue(resolve, params, se) ); ), (Constant, - TU_MATCHA( (se), (ce), - (Int, - rval = ::MIR::Constant::make_Int(ce); - ), - (Uint, - rval = ::MIR::Constant::make_Uint(ce); - ), - (Float, - rval = ::MIR::Constant::make_Float(ce); - ), - (Bool, - rval = ::MIR::Constant::make_Bool(ce); - ), - (Bytes, - rval = ::MIR::Constant(ce); - ), - (StaticString, - rval = ::MIR::Constant(ce); - ), - (Const, - rval = ::MIR::Constant::make_Const({ - params.monomorph(resolve, ce.p) - }); - ), - (ItemAddr, - 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. - rval = ::MIR::Constant( mv$(p) ); - ) - ) + rval = monomorph_Constant(resolve, params, se); ), (SizedArray, rval = ::MIR::RValue::make_SizedArray({ - monomorph_LValue(resolve, params, se.val), + monomorph_Param(resolve, params, se.val), se.count }); ), @@ -166,9 +191,9 @@ namespace { ), (BinOp, rval = ::MIR::RValue::make_BinOp({ - monomorph_LValue(resolve, params, se.val_l), + monomorph_Param(resolve, params, se.val_l), se.op, - monomorph_LValue(resolve, params, se.val_r) + monomorph_Param(resolve, params, se.val_r) }); ), (UniOp, @@ -188,17 +213,17 @@ namespace { (MakeDst, rval = ::MIR::RValue::make_MakeDst({ monomorph_LValue(resolve, params, se.ptr_val), - monomorph_LValue(resolve, params, se.meta_val) + monomorph_Param(resolve, params, se.meta_val) }); ), (Tuple, rval = ::MIR::RValue::make_Tuple({ - monomorph_LValue_list(resolve, params, se.vals) + monomorph_Param_list(resolve, params, se.vals) }); ), (Array, rval = ::MIR::RValue::make_Array({ - monomorph_LValue_list(resolve, params, se.vals) + monomorph_Param_list(resolve, params, se.vals) }); ), // Create a new instance of a union (and eventually enum) @@ -206,7 +231,7 @@ namespace { rval = ::MIR::RValue::make_Variant({ params.monomorph(resolve, se.path), se.index, - monomorph_LValue(resolve, params, se.val) + monomorph_Param(resolve, params, se.val) }); ), // Create a new instance of a struct (or enum) @@ -214,7 +239,7 @@ namespace { rval = ::MIR::RValue::make_Struct({ params.monomorph(resolve, se.path), se.variant_idx, - monomorph_LValue_list(resolve, params, se.vals) + monomorph_Param_list(resolve, params, se.vals) }); ) ) @@ -283,7 +308,7 @@ namespace { e.ret_block, e.panic_block, monomorph_LValue(resolve, params, e.ret_val), H::monomorph_calltarget(resolve, params, e.fcn), - monomorph_LValue_list(resolve, params, e.args) + monomorph_Param_list(resolve, params, e.args) }); ) ) |