From 9fe41ffb9bde218ad97c5430d6cc92051634357d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 4 Aug 2018 18:22:58 +0800 Subject: Codegen C - Fix a few bugs and add new/now-used intrinsics --- src/trans/codegen_c.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 7 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 2ab4ff35..3947de9b 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -303,6 +303,18 @@ namespace { << "\treturn ((v&0xFFFFFFFF) == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n" << "}\n" ; + // Atomic hackery + for(int sz = 8; sz <= 64; sz *= 2) + { + m_of + << "static inline uint"<>4]|(__mrustc_revmap[v&15]<<4); }\n" + << "static inline uint16_t __mrustc_bitrev16(uint16_t v) { if(v==0) return 0; uint16_t rv = ((uint16_t)__mrustc_bitrev8(v>>8))|((uint16_t)__mrustc_bitrev8(v)<<8); }\n" + << "static inline uint32_t __mrustc_bitrev32(uint32_t v) { if(v==0) return 0; uint32_t rv = ((uint32_t)__mrustc_bitrev16(v>>16))|((uint32_t)__mrustc_bitrev16(v)<<16); }\n" + << "static inline uint64_t __mrustc_bitrev64(uint64_t v) { if(v==0) return 0; uint64_t rv = ((uint64_t)__mrustc_bitrev32(v>>32))|((uint64_t)__mrustc_bitrev32(v)<<32); }\n" + // TODO: 128 ; + if( m_options.emulated_i128 ) + { + m_of << "static inline uint128_t __mrustc_bitrev128(uint128_t v) { uint128_t rv = { __mrustc_bitrev64(v>>64)), __mrustc_bitrev64(v) }; return rv; }\n"; + } + else + { + m_of << "static inline uint128_t __mrustc_bitrev128(uint128_t v) { if(v==0) return 0; uint128_t rv = ((uint128_t)__mrustc_bitrev64(v>>64))|((uint128_t)__mrustc_bitrev64(v)<<64); }\n"; + } + for(int sz = 8; sz <= 64; sz *= 2) + { + m_of + << "static inline uint"< b ? a : b); }\n" + << "static inline uint"< (int"<type_is_bad_zst(ty_dst) ) { @@ -4071,7 +4108,7 @@ namespace { } else if( e.args.at(0).is_Constant() ) { - m_of << "{ "; emit_ctype(ty_src, FMT_CB(s, s << "v";)); m_of << " = "; emit_param(e.args.at(0)); m_of << ";"; + m_of << "{ "; emit_ctype(ty_src, FMT_CB(s, s << "v";)); m_of << " = "; emit_param(e.args.at(0)); m_of << "; "; m_of << "memcpy( &"; emit_lvalue(e.ret_val); m_of << ", &v, sizeof("; emit_ctype(ty_dst); m_of << ")); "; m_of << "}"; } @@ -4103,7 +4140,7 @@ namespace { } else { - 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 << "))"; + m_of << "memcpy( &"; emit_lvalue(e.ret_val); m_of << ", &"; emit_param(e.args.at(0)); m_of << ", sizeof("; emit_ctype(ty_src); m_of << "))"; } } else if( name == "copy_nonoverlapping" || name == "copy" ) { @@ -4236,6 +4273,22 @@ namespace { m_of << "("; emit_param(e.args.at(0)); m_of << ")"; } } + else if( name == "bitreverse" ) { + const auto& ty = params.m_types.at(0); + MIR_ASSERT(mir_res, ty.m_data.is_Primitive(), "Invalid type passed to bitreverse. Must be a primitive, got " << ty); + emit_lvalue(e.ret_val); m_of << " = "; + switch(get_prim_size(ty)) + { + case 8: m_of << "__mrustc_bitrev8"; break; + case 16: m_of << "__mrustc_bitrev16"; break; + case 32: m_of << "__mrustc_bitrev32"; break; + case 64: m_of << "__mrustc_bitrev64"; break; + case 128: m_of << "__mrustc_bitrev128"; break; + default: + MIR_TODO(mir_res, "bswap<" << ty << ">"); + } + m_of << "("; emit_param(e.args.at(0)); m_of << ")"; + } // > Obtain the discriminane of a &T as u64 else if( name == "discriminant_value" ) { const auto& ty = params.m_types.at(0); @@ -4442,7 +4495,8 @@ namespace { } } // Unchecked Arithmatic - else if( name == "unchecked_div" ) { + // - exact_div is UB to call on a non-multiple + else if( name == "unchecked_div" || name == "exact_div") { emit_lvalue(e.ret_val); m_of << " = "; if( type_is_emulated_i128(params.m_types.at(0)) ) { @@ -4515,7 +4569,7 @@ namespace { // Bit Twiddling // - CounT Leading Zeroes // - CounT Trailing Zeroes - else if( name == "ctlz" || name == "ctlz_nonzero" || name == "cttz" ) { + else if( name == "ctlz" || name == "ctlz_nonzero" || name == "cttz" || name == "cttz_nonzero" ) { auto emit_arg0 = [&](){ emit_param(e.args.at(0)); }; const auto& ty = params.m_types.at(0); emit_lvalue(e.ret_val); m_of << " = ("; @@ -4647,6 +4701,11 @@ namespace { else if( name == "volatile_store" ) { m_of << "*(volatile "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << " = "; emit_param(e.args.at(1)); } + else if( name == "nontemporal_store" ) { + // TODO: Actually do a non-temporal store + // GCC: _mm_stream_* (depending on input type, which must be `repr(simd)`) + m_of << "*(volatile "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << " = "; emit_param(e.args.at(1)); + } // --- Atomics! // > Single-ordering atomics else if( name == "atomic_xadd" || name.compare(0, 7+4+1, "atomic_xadd_") == 0 ) { @@ -4661,6 +4720,13 @@ namespace { auto ordering = get_atomic_ordering(name, 7+3+1); emit_atomic_arith(AtomicOp::And, ordering); } + else if( name == "atomic_nand" || name.compare(0, 7+4+1, "atomic_nand_") == 0 ) { + auto ordering = get_atomic_ordering(name, 7+4+1); + const auto& ty = params.m_types.at(0); + emit_lvalue(e.ret_val); m_of << " = __mrustc_atomicloop" << get_prim_size(ty) << "("; + emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << get_atomic_ty_gcc(ordering) << ", __mrustc_op_and_not" << get_prim_size(ty); + m_of << ")"; + } else if( name == "atomic_or" || name.compare(0, 7+2+1, "atomic_or_") == 0 ) { auto ordering = get_atomic_ordering(name, 7+2+1); emit_atomic_arith(AtomicOp::Or, ordering); @@ -4669,6 +4735,24 @@ namespace { auto ordering = get_atomic_ordering(name, 7+3+1); emit_atomic_arith(AtomicOp::Xor, ordering); } + else if( name == "atomic_max" || name.compare(0, 7+3+1, "atomic_max_") == 0 + || name == "atomic_min" || name.compare(0, 7+3+1, "atomic_min_") == 0 ) { + auto ordering = get_atomic_ordering(name, 7+3+1); + const auto& ty = params.m_types.at(0); + const char* op = (name[7+1] == 'a' ? "imax" : "imin"); // m'a'x vs m'i'n + emit_lvalue(e.ret_val); m_of << " = __mrustc_atomicloop" << get_prim_size(ty) << "("; + emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << get_atomic_ty_gcc(ordering) << ", __mrustc_op_" << op << get_prim_size(ty); + m_of << ")"; + } + else if( name == "atomic_umax" || name.compare(0, 7+4+1, "atomic_umax_") == 0 + || name == "atomic_umin" || name.compare(0, 7+4+1, "atomic_umin_") == 0 ) { + auto ordering = get_atomic_ordering(name, 7+4+1); + const auto& ty = params.m_types.at(0); + const char* op = (name[7+2] == 'a' ? "umax" : "umin"); // m'a'x vs m'i'n + emit_lvalue(e.ret_val); m_of << " = __mrustc_atomicloop" << get_prim_size(ty) << "("; + emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << get_atomic_ty_gcc(ordering) << ", __mrustc_op_" << op << get_prim_size(ty); + m_of << ")"; + } else if( name == "atomic_load" || name.compare(0, 7+4+1, "atomic_load_") == 0 ) { auto ordering = get_atomic_ordering(name, 7+4+1); emit_lvalue(e.ret_val); m_of << " = "; @@ -4779,6 +4863,11 @@ namespace { else if( name == "atomic_singlethreadfence" || name.compare(0, 7+18, "atomic_singlethreadfence_") == 0 ) { // TODO: Does this matter? } + // -- Platform Intrinsics -- + else if( name.compare(0, 9, "platform:") == 0 ) { + // TODO: Platform intrinsics + m_of << "abort() /* TODO: Platform intrinsic \"" << name << "\" */"; + } else { MIR_BUG(mir_res, "Unknown intrinsic '" << name << "'"); } @@ -5339,10 +5428,16 @@ namespace { // TODO: This should have been eliminated? ("MIR Cleanup" should have removed all inline Const references) ::HIR::TypeRef ty; const auto& lit = get_literal_for_const(c.p, ty); - if(lit.is_Integer() || lit.is_Float() || lit.is_String()) + if(lit.is_Integer() || lit.is_Float()) { emit_literal(ty, lit, {}); } + else if( lit.is_String()) + { + m_of << "make_sliceptr("; + this->print_escaped_string( lit.as_String() ); + m_of << ", " << ::std::dec << lit.as_String().size() << ")"; + } else { // NOTE: GCC hack - statement expressions -- cgit v1.2.3 From 76757341622b747074be74cc75aa5f4f51665f15 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 3 Nov 2018 22:08:03 +0800 Subject: HIR Typecheck - Fixing holes from 1.29 compiler_builtins --- src/hir/hir.cpp | 2 +- src/hir/type.cpp | 60 +++++----- src/hir_typeck/expr_check.cpp | 4 +- src/hir_typeck/expr_cs.cpp | 7 +- src/hir_typeck/helpers.cpp | 260 ++++++++++++++++++++++++------------------ src/hir_typeck/helpers.hpp | 1 + src/hir_typeck/impl_ref.cpp | 19 +-- src/include/tagged_union.hpp | 5 +- src/trans/codegen_c.cpp | 6 + 9 files changed, 205 insertions(+), 159 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 9f9bc1c3..fb0cdbd3 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -344,7 +344,7 @@ bool ::HIR::TraitImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_reso { // NOTE: Don't return any impls when the type is an unbouned ivar. Wouldn't be able to pick anything anyway // TODO: For `Unbound`, it could be valid, if the target is a generic. - if( is_unbounded_infer(type) || TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) { + if( /*is_unbounded_infer(type) ||*/ TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) { return false; } return matches_type_int(m_params, m_type, type, ty_res, true); diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 6f826111..434d471b 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -58,8 +58,8 @@ namespace HIR { void ::HIR::TypeRef::fmt(::std::ostream& os) const { - TU_MATCH(::HIR::TypeRef::Data, (m_data), (e), - (Infer, + TU_MATCH_HDR( (m_data), { ) + TU_ARM(m_data, Infer, e) { os << "_"; if( e.index != ~0u || e.ty_class != ::HIR::InferClass::None ) { os << "/*"; @@ -73,14 +73,14 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const } os << "*/"; } - ), - (Diverge, + } + TU_ARM(m_data, Diverge, e) { os << "!"; - ), - (Primitive, + } + TU_ARM(m_data, Primitive, e) { os << e; - ), - (Path, + } + TU_ARM(m_data, Path, e) { os << e.path; TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be), (Unbound, os << "/*?*/";), @@ -89,8 +89,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const (Union, os << "/*U*/";), (Enum, os << "/*E*/";) ) - ), - (Generic, + } + TU_ARM(m_data, Generic, e) { os << e.name << "/*"; if( e.binding == 0xFFFF ) os << ""; @@ -103,8 +103,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const else os << e.binding; os << "*/"; - ), - (TraitObject, + } + TU_ARM(m_data, TraitObject, e) { os << "dyn ("; if( e.m_trait.m_path != ::HIR::GenericPath() ) { @@ -115,8 +115,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const if( e.m_lifetime != LifetimeRef::new_static() ) os << "+" << e.m_lifetime; os << ")"; - ), - (ErasedType, + } + TU_ARM(m_data, ErasedType, e) { os << "impl "; for(const auto& tr : e.m_traits) { if( &tr != &e.m_traits[0] ) @@ -126,25 +126,25 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const if( e.m_lifetime != LifetimeRef::new_static() ) os << "+ '" << e.m_lifetime; os << "/*" << e.m_origin << "#" << e.m_index << "*/"; - ), - (Array, + } + TU_ARM(m_data, Array, e) { os << "[" << *e.inner << "; "; if( e.size_val != ~0u ) os << e.size_val; else os << "/*sz*/"; os << "]"; - ), - (Slice, + } + TU_ARM(m_data, Slice, e) { os << "[" << *e.inner << "]"; - ), - (Tuple, + } + TU_ARM(m_data, Tuple, e) { os << "("; for(const auto& t : e) os << t << ", "; os << ")"; - ), - (Borrow, + } + TU_ARM(m_data, Borrow, e) { switch(e.type) { case ::HIR::BorrowType::Shared: os << "&"; break; @@ -152,8 +152,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const case ::HIR::BorrowType::Owned: os << "&move "; break; } os << *e.inner; - ), - (Pointer, + } + TU_ARM(m_data, Pointer, e) { switch(e.type) { case ::HIR::BorrowType::Shared: os << "*const "; break; @@ -161,8 +161,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const case ::HIR::BorrowType::Owned: os << "*move "; break; } os << *e.inner; - ), - (Function, + } + TU_ARM(m_data, Function, e) { if( e.is_unsafe ) { os << "unsafe "; } @@ -173,8 +173,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const for(const auto& t : e.m_arg_types) os << t << ", "; os << ") -> " << *e.m_rettype; - ), - (Closure, + } + TU_ARM(m_data, Closure, e) { os << "closure["< " << *e.m_rettype; */ - ) - ) + } + } } bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 8a199557..6d2feaba 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -177,8 +177,8 @@ namespace { case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break; case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break; case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break; } assert(lang_item); const auto& trait_path = this->get_lang_item_path(node.span(), lang_item); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index e7748115..a236c818 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -846,8 +846,8 @@ namespace { case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break; case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break; case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break; } assert(lang_item); const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item); @@ -5294,7 +5294,6 @@ namespace { auto out_ty_o = impl.get_type(v.name.c_str()); if( out_ty_o == ::HIR::TypeRef() ) { - //BUG(sp, "Getting associated type '" << v.name << "' which isn't in " << v.trait << " (" << ty << ")"); out_ty_o = ::HIR::TypeRef(::HIR::Path( v.impl_ty.clone(), ::HIR::GenericPath(v.trait, v.params.clone()), v.name, ::HIR::PathParams() )); } out_ty_o = context.m_resolve.expand_associated_types(sp, mv$(out_ty_o)); @@ -5450,6 +5449,8 @@ namespace { if( TU_TEST1(impl_ty.m_data, Infer, .is_lit() == false) ) { DEBUG("Unbounded ivar, waiting - TODO: Add possibility " << impl_ty << " == " << possible_impl_ty); + context.possible_equate_type_coerce_to(impl_ty.m_data.as_Infer().index, possible_impl_ty); + context.possible_equate_type_coerce_from(impl_ty.m_data.as_Infer().index, possible_impl_ty); return false; } // Only one possible impl diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 6860de41..4d3ea82d 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -914,8 +914,8 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe return pathparams_equal(le.m_trait.m_path.m_params, re.m_trait.m_path.m_params); ), (ErasedType, + ASSERT_BUG(Span(), le.m_origin != ::HIR::SimplePath(), "Erased type with unset origin"); return H::compare_path(*this, le.m_origin, re.m_origin); - //TODO(Span(), "ErasedType"); ), (Tuple, return type_list_equal(*this, le, re); @@ -932,12 +932,17 @@ void TraitResolution::prep_indexes() static Span sp_AAA; const Span& sp = sp_AAA; + // TODO: Create a list of all known type rules in this scope (recursively) + // - What if there's recursive bounds (e.g. on ATYs) + auto add_equality = [&](::HIR::TypeRef long_ty, ::HIR::TypeRef short_ty){ DEBUG("[prep_indexes] ADD " << long_ty << " => " << short_ty); // TODO: Sort the two types by "complexity" (most of the time long >= short) this->m_type_equalities.insert(::std::make_pair( mv$(long_ty), mv$(short_ty) )); }; + // Obtain type equality bounds. + // TODO: Also flatten the bounds list into known trait bounds? this->iterate_bounds([&](const auto& b)->bool { if(const auto* bep = b.opt_TraitBound()) { @@ -1047,6 +1052,31 @@ bool TraitResolution::iterate_bounds( ::std::function cb) const +{ + // Iterate all bounds, finding trait + return this->iterate_bounds([&](const auto& gb) { + if( const auto* be = gb.opt_TraitBound() ) + { + // TODO: Type filter (to avoid the cost of checking parent bounds) + if( cb(be->type, be->trait) ) + return true; + + assert(be->trait.m_trait_ptr); + const auto& trait_ref = *be->trait.m_trait_ptr; + auto monomorph_cb = monomorphise_type_get_cb(sp, &be->type, &be->trait.m_path.m_params, nullptr, nullptr); + for(const auto& parent_tp : trait_ref.m_all_parent_traits) + { + ::HIR::TraitPath tp_mono_o; + const auto& tp_mono = (monomorphise_traitpath_needed(parent_tp) ? tp_mono_o = monomorphise_traitpath_with(sp, parent_tp, monomorph_cb, false) : parent_tp); + // TODO: Monomorphise the bound + if( cb(be->type, tp_mono) ) + return true; + } + } + return false; + }); +} bool TraitResolution::iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function cb) const { ::HIR::GenericPath trait_path; @@ -2241,136 +2271,127 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple ) ) -#if 0 - if( m_ivars.get_type(type).m_data.is_Infer() ) - return false; - if( TU_TEST1(m_ivars.get_type(type).m_data, Path, .binding.is_Unbound()) ) - return false; -#endif + // NOTE: Even if the type is completely unknown (infer or unbound UFCS), search the bound list. // TODO: A bound can imply something via its associated types. How deep can this go? // E.g. `T: IntoIterator` implies `::IntoIter : Iterator` - return this->iterate_bounds([&](const auto& b)->bool { - DEBUG(b); - if( b.is_TraitBound() ) - { - const auto& e = b.as_TraitBound(); - const auto& b_params = e.trait.m_path.m_params; + // > Would maybe want a list of all explicit and implied bounds instead. + return this->iterate_bounds_traits(sp, [&](const auto& bound_ty, const ::HIR::TraitPath& bound_trait)->bool { + const auto& b_params = bound_trait.m_path.m_params; - auto cmp = e.type .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer()); - DEBUG("cmp = " << cmp); - if( cmp == ::HIR::Compare::Unequal ) - return false; + auto cmp = bound_ty .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer()); + DEBUG("cmp = " << cmp); + if( cmp == ::HIR::Compare::Unequal ) + return false; - if( e.trait.m_path.m_path == trait ) { - // Check against `params` - DEBUG("[find_trait_impls_bound] Checking params " << params << " vs " << b_params); - auto ord = cmp; - ord &= this->compare_pp(sp, b_params, params); - if( ord == ::HIR::Compare::Unequal ) - return false; - if( ord == ::HIR::Compare::Fuzzy ) { - DEBUG("Fuzzy match"); - } - DEBUG("[find_trait_impls_bound] Match " << b); - // Hand off to the closure, and return true if it does - // TODO: The type bounds are only the types that are specified. - if( callback( ImplRef(&e.type, &e.trait.m_path.m_params, &e.trait.m_type_bounds), ord) ) { - return true; - } + if( bound_trait.m_path.m_path == trait ) { + // Check against `params` + DEBUG("[find_trait_impls_bound] Checking params " << params << " vs " << b_params); + auto ord = cmp; + ord &= this->compare_pp(sp, b_params, params); + if( ord == ::HIR::Compare::Unequal ) + return false; + if( ord == ::HIR::Compare::Fuzzy ) { + DEBUG("Fuzzy match"); + } + DEBUG("[find_trait_impls_bound] Match " << bound_ty << " : " << bound_trait); + // Hand off to the closure, and return true if it does + // TODO: The type bounds are only the types that are specified. + auto b = bound_trait.clone(); + if( callback( ImplRef(bound_ty.clone(), mv$(b.m_path.m_params), mv$(b.m_type_bounds)), ord) ) { + return true; } + } - // TODO: Allow fuzzy equality? - if( cmp == ::HIR::Compare::Equal ) - { - // HACK: The wrapping closure takes associated types from this bound and applies them to the returned set - // - XXX: This is actually wrong (false-positive) in many cases. FIXME - bool rv = this->find_named_trait_in_trait(sp, - trait,params, - *e.trait.m_trait_ptr, e.trait.m_path.m_path,e.trait.m_path.m_params, - type, - [&](const auto& ty, const auto& params, const auto& assoc) { - // TODO: Avoid duplicating this map every time - ::std::map< ::std::string,::HIR::TypeRef> assoc2; - for(const auto& i : assoc) { + // TODO: Allow fuzzy equality? + if( cmp == ::HIR::Compare::Equal ) + { + // HACK: The wrapping closure takes associated types from this bound and applies them to the returned set + // - XXX: This is actually wrong (false-positive) in many cases. FIXME + bool rv = this->find_named_trait_in_trait(sp, + trait,params, + *bound_trait.m_trait_ptr, bound_trait.m_path.m_path,bound_trait.m_path.m_params, + type, + [&](const auto& ty, const auto& params, const auto& assoc) { + // TODO: Avoid duplicating this map every time + ::std::map< ::std::string,::HIR::TypeRef> assoc2; + for(const auto& i : assoc) { + assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); + } + for(const auto& i : bound_trait.m_type_bounds) { + // TODO: Only include from above when needed + //if( des_trait_ref.m_types.count(i.first) ) { assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); - } - for(const auto& i : e.trait.m_type_bounds) { - // TODO: Only include from above when needed - //if( des_trait_ref.m_types.count(i.first) ) { - assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); - //} - } - return callback( ImplRef(ty.clone(), params.clone(), mv$(assoc2)), ::HIR::Compare::Equal ); - }); - if( rv ) { - return true; - } + //} + } + return callback( ImplRef(ty.clone(), params.clone(), mv$(assoc2)), ::HIR::Compare::Equal ); + }); + if( rv ) { + return true; } + } - // If the input type is an associated type controlled by this trait bound, check for added bounds. - // TODO: This just checks a single layer, but it's feasable that there could be multiple layers - if( assoc_info && e.trait.m_path.m_path == assoc_info->trait.m_path && e.type == *assoc_info->type ) - { - // Check the trait params - auto ord = this->compare_pp(sp, b_params, assoc_info->trait.m_params); - if( ord == ::HIR::Compare::Fuzzy ) { - //TODO(sp, "Handle fuzzy matches searching for associated type bounds"); - } - else if( ord == ::HIR::Compare::Unequal ) { - return false; - } - auto outer_ord = ord; + // If the input type is an associated type controlled by this trait bound, check for added bounds. + // TODO: This just checks a single layer, but it's feasable that there could be multiple layers + if( assoc_info && bound_trait.m_path.m_path == assoc_info->trait.m_path && bound_ty == *assoc_info->type ) + { + // Check the trait params + auto ord = this->compare_pp(sp, b_params, assoc_info->trait.m_params); + if( ord == ::HIR::Compare::Fuzzy ) { + //TODO(sp, "Handle fuzzy matches searching for associated type bounds"); + } + else if( ord == ::HIR::Compare::Unequal ) { + return false; + } + auto outer_ord = ord; - const auto& trait_ref = *e.trait.m_trait_ptr; - const auto& at = trait_ref.m_types.at(assoc_info->item); - for(const auto& bound : at.m_trait_bounds) { - if( bound.m_path.m_path == trait ) - { - auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& { - const auto& ge = gt.m_data.as_Generic(); - if( ge.binding == 0xFFFF ) { - return *assoc_info->type; - } - else { - if( ge.binding >= assoc_info->trait.m_params.m_types.size() ) - BUG(sp, "find_trait_impls_bound - Generic #" << ge.binding << " " << ge.name << " out of range"); - return assoc_info->trait.m_params.m_types[ge.binding]; - } - }; - - DEBUG("- Found an associated type bound for this trait via another bound"); - ::HIR::Compare ord = outer_ord; - if( monomorphise_pathparams_needed(bound.m_path.m_params) ) { - // TODO: Use a compare+callback method instead - auto b_params_mono = monomorphise_path_params_with(sp, bound.m_path.m_params, monomorph_cb, false); - ord &= this->compare_pp(sp, b_params_mono, params); + const auto& trait_ref = *bound_trait.m_trait_ptr; + const auto& at = trait_ref.m_types.at(assoc_info->item); + for(const auto& bound : at.m_trait_bounds) { + if( bound.m_path.m_path == trait ) + { + auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& { + const auto& ge = gt.m_data.as_Generic(); + if( ge.binding == 0xFFFF ) { + return *assoc_info->type; } else { - ord &= this->compare_pp(sp, bound.m_path.m_params, params); - } - if( ord == ::HIR::Compare::Unequal ) - return false; - if( ord == ::HIR::Compare::Fuzzy ) { - DEBUG("Fuzzy match"); + if( ge.binding >= assoc_info->trait.m_params.m_types.size() ) + BUG(sp, "find_trait_impls_bound - Generic #" << ge.binding << " " << ge.name << " out of range"); + return assoc_info->trait.m_params.m_types[ge.binding]; } + }; - auto tp_mono = monomorphise_traitpath_with(sp, bound, monomorph_cb, false); - // - Expand associated types - for(auto& ty : tp_mono.m_type_bounds) { - ty.second = this->expand_associated_types(sp, mv$(ty.second)); - } - DEBUG("- tp_mono = " << tp_mono); - // TODO: Instead of using `type` here, build the real type - if( callback( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)), ord ) ) { - return true; - } + DEBUG("- Found an associated type bound for this trait via another bound"); + ::HIR::Compare ord = outer_ord; + if( monomorphise_pathparams_needed(bound.m_path.m_params) ) { + // TODO: Use a compare+callback method instead + auto b_params_mono = monomorphise_path_params_with(sp, bound.m_path.m_params, monomorph_cb, false); + ord &= this->compare_pp(sp, b_params_mono, params); + } + else { + ord &= this->compare_pp(sp, bound.m_path.m_params, params); + } + if( ord == ::HIR::Compare::Unequal ) + return false; + if( ord == ::HIR::Compare::Fuzzy ) { + DEBUG("Fuzzy match"); + } + + auto tp_mono = monomorphise_traitpath_with(sp, bound, monomorph_cb, false); + // - Expand associated types + for(auto& ty : tp_mono.m_type_bounds) { + ty.second = this->expand_associated_types(sp, mv$(ty.second)); + } + DEBUG("- tp_mono = " << tp_mono); + // TODO: Instead of using `type` here, build the real type + if( callback( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)), ord ) ) { + return true; } } } - - return false; } + return false; }); } @@ -3843,7 +3864,8 @@ bool TraitResolution::find_method(const Span& sp, // 2. Compare the receiver of the above to this type and the bound. if(const auto* self_ty = check_method_receiver(sp, *fcn_ptr, ty, access)) { - if( self_ty->m_data.is_Infer() ) + // If the type is an unbounded ivar, don't check. + if( TU_TEST1(self_ty->m_data, Infer, .is_lit() == false) ) return false; // TODO: Do a fuzzy match here? auto cmp = self_ty->compare_with_placeholders(sp, e.type, cb_infer); @@ -3864,7 +3886,17 @@ bool TraitResolution::find_method(const Span& sp, } else if( cmp == ::HIR::Compare::Fuzzy ) { - TODO(sp, "Fuzzy match checking bounded method - " << *self_ty << " != " << e.type); + DEBUG("Fuzzy match checking bounded method - " << *self_ty << " != " << e.type); + + // Found the method, return the UFCS path for it + possibilities.push_back(::std::make_pair( borrow_type, + ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ + box$( self_ty->clone() ), + mv$(final_trait_path), + method_name, + {} + }) ) )); + rv = true; } else { diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 7868b93f..cb95c94f 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -201,6 +201,7 @@ public: /// Iterate over in-scope bounds (function then top) bool iterate_bounds( ::std::function cb) const; + bool iterate_bounds_traits(const Span& sp, ::std::function cb) const; bool iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function cb) const; typedef ::std::function&)> t_cb_trait_impl; diff --git a/src/hir_typeck/impl_ref.cpp b/src/hir_typeck/impl_ref.cpp index e8966b38..d2dc9fe6 100644 --- a/src/hir_typeck/impl_ref.cpp +++ b/src/hir_typeck/impl_ref.cpp @@ -219,8 +219,8 @@ bool ImplRef::type_is_specialisable(const char* name) const ::std::ostream& operator<<(::std::ostream& os, const ImplRef& x) { - TU_MATCH(ImplRef::Data, (x.m_data), (e), - (TraitImpl, + TU_MATCH_HDR( (x.m_data), { ) + TU_ARM(x.m_data, TraitImpl, e) { if( e.impl == nullptr ) { os << "none"; } @@ -258,13 +258,16 @@ bool ImplRef::type_is_specialisable(const char* name) const } os << "}"; } - ), - (BoundedPtr, + } + TU_ARM(x.m_data, BoundedPtr, e) { + assert(e.type); + assert(e.trait_args); + assert(e.assoc); os << "bound (ptr) " << *e.type << " : ?" << *e.trait_args << " + {" << *e.assoc << "}"; - ), - (Bounded, + } + TU_ARM(x.m_data, Bounded, e) { os << "bound " << e.type << " : ?" << e.trait_args << " + {"<::type, VARS, brace) +#define TU_MATCH_HDR_(CLASS, VARS, brace) switch( (TU_FIRST VARS).tag() ) brace case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used"); + // Evil hack: two for loops, the inner stops the outer after it's done. -#define TU_ARM(VAR, TAG, NAME) case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = VAR.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) +#define TU_ARM(VAR, TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = VAR.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) //#define TU_TEST(VAL, ...) (VAL.is_##TAG() && VAL.as_##TAG() TEST) #define TU_TEST1(VAL, TAG1, TEST) (VAL.is_##TAG1() && VAL.as_##TAG1() TEST) diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 86bbdddc..1bbafcd2 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1776,6 +1776,9 @@ namespace { }; TU_MATCHA( (lit), (e), (Invalid, m_of << "/* INVALID */"; ), + (Defer, + MIR_BUG(*m_mir_res, "Defer literal encountered"); + ), (List, m_of << "{"; if( ty.m_data.is_Array() ) @@ -5285,6 +5288,9 @@ namespace { (Invalid, m_of << "/* INVALID */"; ), + (Defer, + MIR_BUG(*m_mir_res, "Defer literal encountered"); + ), (List, if( ty.m_data.is_Array() ) { -- cgit v1.2.3 From 998de6c1b99b44f6049f744c713657587f91e1ac Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 19 Oct 2018 07:40:53 +0800 Subject: Codegen C - Fix incorrect use of ZST in enum constructor shim (fixes #86) --- src/trans/codegen_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 1bbafcd2..a1b3d065 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1575,7 +1575,7 @@ namespace { { if( this->type_is_bad_zst(repr->fields[var_idx].ty) ) { - m_of << " .DATA = { /* ZST Variant */ }"; + //m_of << " .DATA = { /* ZST Variant */ }"; } else { -- cgit v1.2.3 From b141095b38ac0ea5a7ed58aa405afd1c318aa442 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 22 Dec 2018 14:19:37 +0800 Subject: Codegen C - Fix incorrect memory orderings --- src/trans/codegen_c.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index a1b3d065..8bbbd033 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -313,9 +313,10 @@ namespace { { m_of << "static inline uint"< Date: Sat, 29 Dec 2018 13:32:51 +0800 Subject: Lower MIR - Handing of irrefutable enum matches, some other tweaks --- src/hir_typeck/static.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++- src/hir_typeck/static.hpp | 1 + src/mir/cleanup.cpp | 9 +++-- src/mir/from_hir.cpp | 83 ++++++++++++++++++++++++++++------------------- src/trans/codegen_c.cpp | 1 + 5 files changed, 139 insertions(+), 36 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 64b04611..d40ee811 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -1600,7 +1600,7 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) return true; ), (Diverge, - // The ! type is kinda Copy ... + // The ! type is kinda Sized ... return true; ), (Closure, @@ -1645,6 +1645,85 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) ) throw ""; } +bool StaticTraitResolve::type_is_impossible(const Span& sp, const ::HIR::TypeRef& ty) const +{ + TU_MATCH_HDRA( (ty.m_data), {) + break; + default: + return false; + TU_ARMA(Diverge, _e) + return true; + TU_ARMA(Path, e) { + TU_MATCHA( (e.binding), (pbe), + (Unbound, + // BUG? + return false; + ), + (Opaque, + // TODO: This can only be with UfcsKnown, so check if the trait specifies ?Sized + return false; + ), + (Struct, + const auto& params = e.path.m_data.as_Generic().m_params; + // TODO: Check all fields, if one flags this, then it's impossible. + const auto& str = *pbe; + TU_MATCH_HDRA( (str.m_data), {) + TU_ARMA(Unit, e) + return false; + TU_ARMA(Tuple, e) { + for(const auto& fld : e) + { + const auto& tpl = fld.ent; + ::HIR::TypeRef tmp; + const auto& ty = (monomorphise_type_needed(tpl) ? tmp = monomorphise_type_with(sp, tpl, monomorphise_type_get_cb(sp, nullptr, ¶ms, nullptr)) : tpl); + if( type_is_impossible(sp, ty) ) + return true; + } + return false; + } + TU_ARMA(Named, e) + for(const auto& fld : e) + { + TODO(sp, "type_is_impossible for struct " << ty << " - " << fld.second.ent); + } + } + ), + (Enum, + // TODO: Check all variants. + TODO(sp, "type_is_impossible for enum " << ty); + ), + (Union, + // TODO: Check all variants? Or just one? + TODO(sp, "type_is_impossible for union " << ty); + ) + ) + return true; + } + TU_ARMA(Borrow, e) + return type_is_impossible(sp, *e.inner); + TU_ARMA(Pointer, e) { + return false; + //return type_is_impossible(sp, *e.inner); + } + TU_ARMA(Function, e) { + // TODO: Check all arguments? + return true; + } + TU_ARMA(Array, e) { + return type_is_impossible(sp, *e.inner); + } + TU_ARMA(Slice, e) { + return type_is_impossible(sp, *e.inner); + } + TU_ARMA(Tuple, e) { + for(const auto& ty : e) + if( type_is_impossible(sp, ty) ) + return true; + return false; + } + } + throw ""; +} bool StaticTraitResolve::can_unsize(const Span& sp, const ::HIR::TypeRef& dst_ty, const ::HIR::TypeRef& src_ty) const { diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index ae429a3f..f764f8f7 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -184,6 +184,7 @@ public: bool type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const; bool type_is_clone(const Span& sp, const ::HIR::TypeRef& ty) const; // 1.29 bool type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) const; + bool type_is_impossible(const Span& sp, const ::HIR::TypeRef& ty) const; bool can_unsize(const Span& sp, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) const; /// Returns `true` if the passed type either implements Drop, or contains a type that implements Drop diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 1a15ea22..f3e987d6 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -214,8 +214,8 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( if( path == ::HIR::GenericPath() ) - MIR_TODO(state, "Literal of type " << ty << " - " << path << " - " << lit); - DEBUG("Unknown type " << ty << " - Return BorrowOf"); + MIR_TODO(state, "Literal of type " << ty << " - " << lit); + DEBUG("Unknown type " << ty << ", but a path was provided - Return ItemAddr " << path); return ::MIR::Constant( mv$(path) ); ), (Tuple, @@ -454,6 +454,11 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con else { MIR_TODO(state, "Const with type " << ty); } + ), + (Function, + //MIR_TODO(state, "Const function pointer " << lit << " w/ type " << ty); + MIR_ASSERT(state, lit.is_BorrowPath(), ""); + return ::MIR::Constant::make_ItemAddr( lit.as_BorrowPath().clone() ); ) ) } diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 38d00a5a..2c45f5bb 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -207,22 +207,22 @@ namespace { allow_refutable = 2; } - TU_MATCHA( (pat.m_data), (e), - (Any, - ), - (Box, + TU_MATCH_HDRA( (pat.m_data), {) + TU_ARMA(Any, e) { + } + TU_ARMA(Box, e) { destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); - ), - (Ref, + } + TU_ARMA(Ref, e) { destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); - ), - (Tuple, + } + TU_ARMA(Tuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); } - ), - (SplitTuple, + } + TU_ARMA(SplitTuple, e) { assert(e.total_size >= e.leading.size() + e.trailing.size()); for(unsigned int i = 0; i < e.leading.size(); i ++ ) { @@ -234,17 +234,17 @@ namespace { { destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), ofs+i}), allow_refutable); } - ), - (StructValue, + } + TU_ARMA(StructValue, e) { // Nothing. - ), - (StructTuple, + } + TU_ARMA(StructTuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); } - ), - (Struct, + } + TU_ARMA(Struct, e) { const auto& str = *e.binding; const auto& fields = str.m_data.as_Named(); for(const auto& fld_pat : e.sub_patterns) @@ -252,31 +252,48 @@ namespace { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval.clone() ), idx}), allow_refutable); } - ), + } // Refutable - (Value, + TU_ARMA(Value, e) { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); - ), - (Range, + } + TU_ARMA(Range, e) { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); - ), - (EnumValue, + } + TU_ARMA(EnumValue, e) { const auto& enm = *e.binding_ptr; if( enm.num_variants() > 1 ) { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); } - ), - (EnumTuple, + } + TU_ARMA(EnumTuple, e) { const auto& enm = *e.binding_ptr; - ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat); + const auto& variants = enm.m_data.as_Data(); + // TODO: Check that this is the only non-impossible arm + if( !allow_refutable ) + { + for(size_t i = 0; i < variants.size(); i ++) + { + const auto& var_ty = variants[i].type; + if( i == e.binding_idx ) { + continue; + } + ::HIR::TypeRef tmp; + const auto& ty = (monomorphise_type_needed(var_ty) ? tmp = monomorphise_type_with(sp, var_ty, monomorphise_type_get_cb(sp, nullptr, &e.path.m_params, nullptr)) : var_ty); + if( m_builder.resolve().type_is_impossible(sp, ty) ) { + continue; + } + ERROR(sp, E0000, "Variant " << variants[i].name << " not handled"); + } + } auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval_var.clone() ), i}), allow_refutable); } - ), - (EnumStruct, + } + TU_ARMA(EnumStruct, e) { const auto& enm = *e.binding_ptr; ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat); ASSERT_BUG(sp, enm.m_data.is_Data(), "Expected struct variant - " << pat); @@ -289,8 +306,8 @@ namespace { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval_var.clone() ), idx}), allow_refutable); } - ), - (Slice, + } + TU_ARMA(Slice, e) { // These are only refutable if T is [T] bool ty_is_array = false; m_builder.with_val_type(sp, lval, [&ty_is_array](const auto& ty){ @@ -316,8 +333,8 @@ namespace { destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable ); } } - ), - (SplitSlice, + } + TU_ARMA(SplitSlice, e) { // These are only refutable if T is [T] bool ty_is_array = false; unsigned int array_size = 0; @@ -412,8 +429,8 @@ namespace { } } } - ) - ) + } + } // TU_MATCH_HDRA } // -- ExprVisitor diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 8bbbd033..0f2cd636 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -2730,6 +2730,7 @@ namespace { // Emit a call to box_free for the type ::HIR::GenericPath box_free { m_crate.get_lang_item_path(sp, "box_free"), { ity->clone() } }; // TODO: This is specific to the official liballoc's owned_box + // TODO: Shared logic with Box drop glue above. m_of << indent << Trans_Mangle(box_free) << "("; emit_lvalue(e.slot); m_of << "._0._0._0);\n"; } else -- cgit v1.2.3 From e8401bfcea28bef9151aea9a8bd9b1c2789b5f79 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 29 Dec 2018 14:55:15 +0800 Subject: Codegen C - Handle 1.29 box_free calling convention (hack) --- src/trans/codegen_c.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 0f2cd636..c6f072fd 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -856,6 +856,26 @@ namespace { } } + void emit_box_drop(unsigned indent_level, const ::HIR::TypeRef& inner_type, const ::MIR::LValue& slot, bool run_destructor) + { + auto indent = RepeatLitStr { "\t", static_cast(indent_level) }; + // Emit a call to box_free for the type + if( run_destructor ) + { + auto inner_ptr = ::HIR::TypeRef::new_pointer( ::HIR::BorrowType::Unique, inner_type.clone() ); + m_of << indent; emit_ctype(inner_ptr, FMT_CB(ss, ss << "i"; )); m_of << " = "; emit_lvalue(slot); m_of << "._0._0._0;\n"; + emit_destructor_call( ::MIR::LValue::make_Local(~0u), inner_type, true, indent_level ); + } + // TODO: This is specific to the official liballoc's owned_box + ::HIR::GenericPath box_free { m_crate.get_lang_item_path(sp, "box_free"), { inner_type.clone() } }; + if( TARGETVER_1_29 ) { + // In 1.29, `box_free` takes Unique, so pass the Unique within the Box + m_of << indent << Trans_Mangle(box_free) << "("; emit_lvalue(slot); m_of << "._0);\n"; + } + else { + m_of << indent << Trans_Mangle(box_free) << "("; emit_lvalue(slot); m_of << "._0._0._0);\n"; + } + } void emit_box_drop_glue(::HIR::GenericPath p, const ::HIR::Struct& item) { auto struct_ty = ::HIR::TypeRef( p.clone(), &item ); @@ -875,13 +895,7 @@ namespace { m_mir_res = &mir_res; m_of << "static void " << Trans_Mangle(drop_glue_path) << "(struct s_" << Trans_Mangle(p) << "* rv) {\n"; - // Obtain inner pointer - // TODO: This is very specific to the structure of the official liballoc's Box. - m_of << "\t"; emit_ctype(args[0].second, FMT_CB(ss, ss << "arg0"; )); m_of << " = rv->_0._0._0;\n"; - // Call destructor of inner data - emit_destructor_call( ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Argument({0})) }), *ity, true, 1); - // Emit a call to box_free for the type - m_of << "\t" << Trans_Mangle(box_free) << "(arg0);\n"; + emit_box_drop(1, *ity, ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) }), /*run_destructor=*/true); m_of << "}\n"; m_mir_res = nullptr; @@ -1068,6 +1082,7 @@ namespace { ::MIR::Function empty_fcn; ::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "struct " << p;), ::HIR::TypeRef(), {}, empty_fcn }; m_mir_res = &top_mir_res; + // TODO: repr(transparent) and repr(align(foo)) bool is_packed = item.m_repr == ::HIR::Struct::Repr::Packed; TRACE_FUNCTION_F(p); @@ -2727,11 +2742,7 @@ namespace { // Shallow drops are only valid on owned_box if( const auto* ity = m_resolve.is_type_owned_box(ty) ) { - // Emit a call to box_free for the type - ::HIR::GenericPath box_free { m_crate.get_lang_item_path(sp, "box_free"), { ity->clone() } }; - // TODO: This is specific to the official liballoc's owned_box - // TODO: Shared logic with Box drop glue above. - m_of << indent << Trans_Mangle(box_free) << "("; emit_lvalue(e.slot); m_of << "._0._0._0);\n"; + emit_box_drop(1, *ity, e.slot, /*run_destructor=*/false); } else { -- cgit v1.2.3 From 6fb11a5af19b91557dba1ca853599596622f56df Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 30 Dec 2018 07:36:38 +0800 Subject: Codegen C - Add hacky compiler-provided glue --- src/main.cpp | 2 ++ src/trans/allocator.cpp | 19 +++-------- src/trans/allocator.hpp | 10 ++---- src/trans/codegen_c.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 22 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/main.cpp b/src/main.cpp index 1af432b2..782e043f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -638,6 +638,8 @@ int main(int argc, char *argv[]) crate_type = ::AST::Crate::Type::Executable; } + // TODO: For 1.29 executables/dylibs, add oom/panic shims + // Enumerate items to be passed to codegen TransList items = CompilePhase("Trans Enumerate", [&]() { switch( crate_type ) diff --git a/src/trans/allocator.cpp b/src/trans/allocator.cpp index 5f61093d..9f5559ae 100644 --- a/src/trans/allocator.cpp +++ b/src/trans/allocator.cpp @@ -12,25 +12,14 @@ #define DEF_METHOD(name, ret) { #name, AllocatorDataTy::ret, sizeof(ALLOCATOR_METHODS_ARGS_##name)/sizeof(AllocatorDataTy), ALLOCATOR_METHODS_ARGS_##name } DEF_METHOD_ARGS(alloc, AllocatorDataTy::Layout) -DEF_METHOD_ARGS(oom, AllocatorDataTy::AllocError) DEF_METHOD_ARGS(dealloc, AllocatorDataTy::Ptr, AllocatorDataTy::Layout) -DEF_METHOD_ARGS(usable_size, AllocatorDataTy::LayoutRef) -DEF_METHOD_ARGS(realloc, AllocatorDataTy::Ptr, AllocatorDataTy::Layout, AllocatorDataTy::Layout) +DEF_METHOD_ARGS(realloc, AllocatorDataTy::Ptr, AllocatorDataTy::Layout, AllocatorDataTy::Usize) DEF_METHOD_ARGS(alloc_zeroed, AllocatorDataTy::Layout) -DEF_METHOD_ARGS(alloc_excess, AllocatorDataTy::Layout) -DEF_METHOD_ARGS(realloc_excess, AllocatorDataTy::Ptr, AllocatorDataTy::Layout, AllocatorDataTy::Layout) -DEF_METHOD_ARGS(grow_in_place, AllocatorDataTy::Ptr, AllocatorDataTy::Layout, AllocatorDataTy::Layout) -DEF_METHOD_ARGS(shrink_in_place, AllocatorDataTy::Ptr, AllocatorDataTy::Layout, AllocatorDataTy::Layout) -const AllocatorMethod ALLOCATOR_METHODS[10] = { +const AllocatorMethod ALLOCATOR_METHODS[4] = { DEF_METHOD(alloc, ResultPtr), - DEF_METHOD(oom, Never), DEF_METHOD(dealloc, Unit), - DEF_METHOD(usable_size, UsizePair), DEF_METHOD(realloc, ResultPtr), - DEF_METHOD(alloc_zeroed, ResultPtr), - DEF_METHOD(alloc_excess, ResultExcess), - DEF_METHOD(realloc_excess, ResultExcess), - DEF_METHOD(grow_in_place, ResultUnit), - DEF_METHOD(shrink_in_place, ResultUnit) + DEF_METHOD(alloc_zeroed, ResultPtr) }; +const size_t NUM_ALLOCATOR_METHODS = sizeof(ALLOCATOR_METHODS)/sizeof(ALLOCATOR_METHODS[0]); diff --git a/src/trans/allocator.hpp b/src/trans/allocator.hpp index 8a4e5186..c124ef57 100644 --- a/src/trans/allocator.hpp +++ b/src/trans/allocator.hpp @@ -9,17 +9,12 @@ enum class AllocatorDataTy { // - Return - Never, // ! Unit, // () ResultPtr, // (..., *mut i8) + *mut u8 - ResultExcess, // (..., *mut i8, *mut i8) + *mut u8 - UsizePair, // (..., *mut usize, *mut usize) + () - ResultUnit, // i8 // - Args Layout, // usize, usize - LayoutRef, // *const Layout [actually *const i8] - AllocError, // *const i8 Ptr, // *mut u8 + Usize, // usize }; struct AllocatorMethod { const char* name; @@ -33,5 +28,6 @@ enum class AllocatorKind { DefaultExe, }; -extern const AllocatorMethod ALLOCATOR_METHODS[10]; +extern const AllocatorMethod ALLOCATOR_METHODS[]; +extern const size_t NUM_ALLOCATOR_METHODS; diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index c6f072fd..710300ce 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -639,6 +639,84 @@ namespace { << "__thread void* mrustc_panic_value;\n" ; } + + // Allocator shims + if( TARGETVER_1_29 ) + { + const char* alloc_prefix = "__rdl_"; + for(size_t i = 0; i < NUM_ALLOCATOR_METHODS; i++) + { + struct H { + static void ty_args(::std::vector& out, AllocatorDataTy t) { + switch(t) + { + case AllocatorDataTy::Unit: + case AllocatorDataTy::ResultPtr: // (..., *mut i8) + *mut u8 + throw ""; + // - Args + case AllocatorDataTy::Layout: // usize, usize + out.push_back("uintptr_t"); + out.push_back("uintptr_t"); + break; + case AllocatorDataTy::Ptr: // *mut u8 + out.push_back("int8_t*"); + break; + case AllocatorDataTy::Usize: + out.push_back("uintptr_t"); + break; + } + } + static const char* ty_ret(AllocatorDataTy t) { + switch(t) + { + case AllocatorDataTy::Unit: + return "void"; + case AllocatorDataTy::ResultPtr: // (..., *mut i8) + *mut u8 + return "int8_t*"; + // - Args + case AllocatorDataTy::Layout: // usize, usize + case AllocatorDataTy::Ptr: // *mut u8 + case AllocatorDataTy::Usize: + throw ""; + } + throw ""; + } + static void emit_proto(::std::ostream& os, const AllocatorMethod& method, const char* name_prefix, const ::std::vector& args) { + os << H::ty_ret(method.ret) << " " << name_prefix << method.name << "("; + for(size_t j = 0; j < args.size(); j ++) + { + if( j != 0 ) + os << ", "; + os << args[j] << " a" << j; + } + os << ")"; + } + }; + const auto& method = ALLOCATOR_METHODS[i]; + ::std::vector args; + for(size_t j = 0; j < method.n_args; j ++) + H::ty_args(args, method.args[j]); + H::emit_proto(m_of, method, "__rust_", args); m_of << " {\n"; + m_of << "\textern "; H::emit_proto(m_of, method, alloc_prefix, args); m_of << ";\n"; + m_of << "\t" << alloc_prefix << method.name << "("; + for(size_t j = 0; j < args.size(); j ++) + { + if( j != 0 ) + m_of << ", "; + m_of << "a" << j; + } + m_of << ");\n"; + m_of << "}\n"; + } + + // TODO: Bind `panic_impl` lang item to the item tagged with `panic_implementation` + // TODO: Bind `oom` lang item to the item tagged with `alloc_error_handler` + // - Can do this in enumerate/auto_impls instead, for better iteraction with enum + // XXX: HACK HACK HACK - This only works with libcore/libstd's current layout + m_of << "uint32_t panic_impl(uintptr_t payload) { extern uint32_t __rust_start_panic(uintptr_t payload); return __rust_start_panic(payload); }\n"; + m_of << "struct s__ZN4core5alloc6Layout_A { uintptr_t a, b; };\n"; + m_of << "void oom_impl(struct s__ZN4core5alloc6Layout_A l) { extern void _ZN3std5alloc8rust_oom(struct s__ZN4core5alloc6Layout_A l); _ZN3std5alloc8rust_oom(l); }\n"; + } } m_of.flush(); @@ -2189,6 +2267,13 @@ namespace { m_of << "}\n"; return; } + else if( item.m_linkage.name.rfind("llvm.", 0) == 0 ) + { + emit_function_header(p, item, params); + m_of << " { abort(); }\n"; + m_mir_res = nullptr; + return ; + } else { m_of << "extern "; -- cgit v1.2.3 From c39ca5729eb2782e4286f3e582009e43482ebdc7 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 30 Dec 2018 09:45:13 +0800 Subject: Codegen C - Fix integer printing quirks --- src/trans/codegen_c.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 710300ce..2c40c991 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1965,10 +1965,10 @@ namespace { break; case ::HIR::CoreType::U64: case ::HIR::CoreType::Usize: - m_of << ::std::hex << "0x" << e << ::std::dec; + m_of << ::std::hex << "0x" << e << "ull" << ::std::dec; break; case ::HIR::CoreType::U128: - m_of << ::std::hex << "0x" << e << ::std::dec; + m_of << ::std::hex << "0x" << e << "ull" << ::std::dec; break; case ::HIR::CoreType::I8: m_of << static_cast( static_cast(e) ); @@ -1982,7 +1982,7 @@ namespace { case ::HIR::CoreType::I64: case ::HIR::CoreType::I128: case ::HIR::CoreType::Isize: - m_of << static_cast(e); + m_of << static_cast(e) << "ll"; break; case ::HIR::CoreType::Char: assert(0 <= e && e <= 0x10FFFF); @@ -5629,6 +5629,16 @@ namespace { { switch(c.t) { + // TODO: These should already have been truncated/reinterpreted, but just in case. + case ::HIR::CoreType::I8: + m_of << static_cast( static_cast(c.v) ); // cast to int, because `int8_t` is printed as a `char` + break; + case ::HIR::CoreType::I16: + m_of << static_cast(c.v); + break; + case ::HIR::CoreType::I32: + m_of << static_cast(c.v); + break; case ::HIR::CoreType::I64: case ::HIR::CoreType::Isize: m_of << c.v; -- cgit v1.2.3 From 42b9c8704fe4aab25e8f9d0cca15a74b025eee43 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 3 Feb 2019 17:48:32 +0800 Subject: HIR - Minimally-tested support for `extern { type }` --- src/hir/from_ast.cpp | 10 ++++++++ src/hir/hir.hpp | 8 +++++++ src/hir/serialise.cpp | 9 ++++++++ src/hir/type.cpp | 2 ++ src/hir/type.hpp | 2 ++ src/hir/visitor.cpp | 3 +++ src/hir_conv/bind.cpp | 4 ++++ src/hir_conv/constant_evaluation.cpp | 2 ++ src/hir_conv/markings.cpp | 1 + src/hir_typeck/expr_check.cpp | 9 ++++++++ src/hir_typeck/expr_cs.cpp | 18 +++++++++++++++ src/hir_typeck/helpers.cpp | 13 +++++++++++ src/hir_typeck/outer.cpp | 4 ++++ src/hir_typeck/static.cpp | 15 ++++++++++++ src/mir/from_hir.cpp | 3 +++ src/mir/from_hir_match.cpp | 15 ++++++++++++ src/resolve/absolute.cpp | 44 +++++++++++++++++------------------- src/resolve/index.cpp | 13 ++++++++++- src/resolve/use.cpp | 3 +++ src/trans/auto_impls.cpp | 6 ++--- src/trans/codegen.cpp | 3 +++ src/trans/codegen_c.cpp | 11 +++++++++ src/trans/enumerate.cpp | 16 ++++++------- 23 files changed, 178 insertions(+), 36 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 768593c4..fb8096f7 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -1187,6 +1187,7 @@ namespace { ::std::vector< ::HIR::TraitPath> trait_bounds; ::std::string lifetime_bound; auto gps = LowerHIR_GenericParams(i.params(), &is_sized); + for(auto& b : gps.m_bounds) { TU_MATCH(::HIR::GenericBound, (b), (be), @@ -1463,6 +1464,15 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H _add_mod_ns_item( mod, item.name, item.is_pub, ::HIR::TypeItem::make_Import({ ::HIR::SimplePath(e.name, {}), false, 0} ) ); ), (Type, + if( e.type().m_data.is_Any() ) + { + if( !e.params().lft_params().empty() || !e.params().ty_params().empty() || !e.params().bounds().empty() ) + { + ERROR(item.data.span, E0000, "Generics on extern type"); + } + _add_mod_ns_item(mod, item.name, item.is_pub, ::HIR::ExternType {}); + break; + } _add_mod_ns_item( mod, item.name, item.is_pub, ::HIR::TypeItem::make_TypeAlias( LowerHIR_TypeAlias(e) ) ); ), (Struct, diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index fc4a19e8..48787583 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -215,6 +215,13 @@ struct StructMarkings unsigned int coerce_param = ~0u; }; +class ExternType +{ +public: + // TODO: do extern types need any associated data? + TraitMarkings m_markings; +}; + class Enum { public: @@ -367,6 +374,7 @@ TAGGED_UNION(TypeItem, Import, (Import, struct { ::HIR::SimplePath path; bool is_variant; unsigned int idx; }), (Module, Module), (TypeAlias, TypeAlias), // NOTE: These don't introduce new values + (ExternType, ExternType), (Enum, Enum), (Struct, Struct), (Union, Union), diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index c91cf93f..e5fe8ed5 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -834,6 +834,10 @@ (Union, m_out.write_tag(6); serialise(e); + ), + (ExternType, + m_out.write_tag(7); + serialise(e); ) ) } @@ -1020,6 +1024,11 @@ serialise(item.m_markings); } + void serialise(const ::HIR::ExternType& item) + { + TRACE_FUNCTION_F("ExternType"); + serialise(item.m_markings); + } void serialise(const ::HIR::Trait& item) { TRACE_FUNCTION_F("_trait:"); diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 2c24e3e1..981ed0b3 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -85,6 +85,7 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be), (Unbound, os << "/*?*/";), (Opaque, os << "/*O*/";), + (ExternType, os << "/*X*/";), (Struct, os << "/*S*/";), (Union, os << "/*U*/";), (Enum, os << "/*E*/";) @@ -782,6 +783,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x TU_MATCH(::HIR::TypeRef::TypePathBinding, (*this), (e), (Unbound, return ::HIR::TypeRef::TypePathBinding::make_Unbound({}); ), (Opaque , return ::HIR::TypeRef::TypePathBinding::make_Opaque({}); ), + (ExternType, return ::HIR::TypeRef::TypePathBinding(e); ), (Struct, return ::HIR::TypeRef::TypePathBinding(e); ), (Union , return ::HIR::TypeRef::TypePathBinding(e); ), (Enum , return ::HIR::TypeRef::TypePathBinding(e); ) diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 480b32c4..0c98773f 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -19,6 +19,7 @@ namespace HIR { +class ExternType; class Struct; class Union; class Enum; @@ -152,6 +153,7 @@ public: TAGGED_UNION_EX(TypePathBinding, (), Unbound, ( (Unbound, struct {}), // Not yet bound, either during lowering OR during resolution (when associated and still being resolved) (Opaque, struct {}), // Opaque, i.e. An associated type of a generic (or Self in a trait) + (ExternType, const ::HIR::ExternType*), (Struct, const ::HIR::Struct*), (Union, const ::HIR::Union*), (Enum, const ::HIR::Enum*) diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index 5c9c0dfa..f23bae88 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -47,6 +47,9 @@ void ::HIR::Visitor::visit_module(::HIR::ItemPath p, ::HIR::Module& mod) DEBUG("type " << name); this->visit_type_alias(p + name, e); ), + (ExternType, + DEBUG("extern type " << name); + ), (Enum, DEBUG("enum " << name); this->visit_enum(p + name, e); diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 9b5043f4..b616a64f 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -456,6 +456,10 @@ namespace { (TypeAlias, BUG(sp, "TypeAlias encountered after `Resolve Type Aliases` - " << ty); ), + (ExternType, + e.binding = ::HIR::TypeRef::TypePathBinding::make_ExternType(&e3); + DEBUG("- " << ty); + ), (Struct, fix_param_count(sp, pe, e3.m_params, pe.m_params); e.binding = ::HIR::TypeRef::TypePathBinding::make_Struct(&e3); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 43a64bbb..3d1bf4a5 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -169,6 +169,8 @@ namespace { ), (Enum, ), + (ExternType, + ), (TypeAlias, ) ) diff --git a/src/hir_conv/markings.cpp b/src/hir_conv/markings.cpp index df7fbd36..d43db2b5 100644 --- a/src/hir_conv/markings.cpp +++ b/src/hir_conv/markings.cpp @@ -333,6 +333,7 @@ public: TU_MATCHA( (te.binding), (tpb), (Unbound, ), (Opaque, ), + (ExternType, markings_ptr = &tpb->m_markings; ), (Struct, markings_ptr = &tpb->m_markings; ), (Union , markings_ptr = &tpb->m_markings; ), (Enum , markings_ptr = &tpb->m_markings; ) diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index adb3c426..7d5a9c6f 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -462,6 +462,9 @@ namespace { (Union, BUG(sp, "Union in TupleVariant"); ), + (ExternType, + BUG(sp, "ExternType in TupleVariant"); + ), (Struct, ASSERT_BUG(sp, e->m_data.is_Tuple(), "Pointed struct in TupleVariant (" << node.m_path << ") isn't a Tuple"); fields_ptr = &e->m_data.as_Tuple(); @@ -522,6 +525,9 @@ namespace { (Union, TODO(sp, "Union in StructLiteral"); ), + (ExternType, + BUG(sp, "ExternType in StructLiteral"); + ), (Struct, if( e->m_data.is_Unit() ) { @@ -611,6 +617,9 @@ namespace { (Union, BUG(sp, "Union with _UnitVariant"); ), + (ExternType, + BUG(sp, "ExternType with _UnitVariant"); + ), (Struct, assert( e->m_data.is_Unit() ); ) diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 4a53bd4d..291dcd84 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1144,6 +1144,9 @@ namespace { ), (Union, BUG(sp, "TupleVariant pointing to a union"); + ), + (ExternType, + BUG(sp, "TupleVariant pointing to a extern type"); ) ) assert(fields_ptr); @@ -1216,6 +1219,7 @@ namespace { TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e), (Unbound, ), (Opaque, ), + (ExternType, ), // Error? (Enum, const auto& var_name = ty_path.m_path.m_components.back(); const auto& enm = *e; @@ -4900,6 +4904,10 @@ void Context::require_sized(const Span& sp, const ::HIR::TypeRef& ty_) // Already checked by type_is_sized params_def = nullptr; ), + (ExternType, + static ::HIR::GenericParams empty_params; + params_def = &empty_params; + ), (Enum, params_def = &pb->m_params; ), @@ -5551,6 +5559,13 @@ namespace { (Opaque, // Handled above in bounded ), + (ExternType, + // Must be equal + if( sbe == dbe ) + { + return CoerceResult::Equality; + } + ), (Enum, // Must be equal if( sbe == dbe ) @@ -6474,6 +6489,9 @@ namespace { // TODO: Check bounds? return false; ), + (ExternType, + return false; + ), (Struct, if(pbe_a != pbe_b) return false; if( !pbe_a->m_struct_markings.can_unsize ) diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 1af269ad..5c0696e3 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -2477,6 +2477,9 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, ), (Opaque, ), + (ExternType, + markings = &tpb->m_markings; + ), (Struct, markings = &tpb->m_markings; ), @@ -2710,6 +2713,9 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, ), (Union, TODO(sp, "Check auto trait destructure on union " << type); + ), + (ExternType, + TODO(sp, "Check auto trait destructure on extern type " << type); ) ) DEBUG("- Nothing failed, calling callback"); @@ -3141,6 +3147,10 @@ bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPa (Opaque, // TODO: Check bounds ), + (ExternType, + // Is it sized? No. + return ::HIR::Compare::Unequal; + ), (Enum, // HAS to be Sized ), @@ -4323,6 +4333,9 @@ bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const (Enum, // No fields on enums either ), + (ExternType, + // No fields on extern types + ), (Union, const auto& unm = *be; const auto& params = e.path.m_data.as_Generic().m_params; diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 63e92d8b..6a8e8b35 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -52,6 +52,10 @@ namespace { (TypeAlias, BUG(sp, "Type path pointed to type alias - " << path); ), + (ExternType, + static ::HIR::GenericParams empty_params; + return empty_params; + ), (Module, BUG(sp, "Type path pointed to module - " << path); ), diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 457bd44e..ce7faf6c 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -851,6 +851,9 @@ bool StaticTraitResolve::find_impl__check_crate( ), (Union, TODO(sp, "Check auto trait destructure on union " << type); + ), + (ExternType, + TODO(sp, "Check auto trait destructure on extern type " << type); ) ) DEBUG("- Nothing failed, calling callback"); @@ -1629,6 +1632,10 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) return false; } ), + (ExternType, + // Extern types aren't Sized + return false; + ), (Enum, ), (Union, @@ -1732,6 +1739,10 @@ bool StaticTraitResolve::type_is_impossible(const Span& sp, const ::HIR::TypeRef (Union, // TODO: Check all variants? Or just one? TODO(sp, "type_is_impossible for union " << ty); + ), + (ExternType, + // Extern types are possible, just not usable + return false; ) ) return true; @@ -2032,6 +2043,10 @@ bool StaticTraitResolve::type_needs_drop_glue(const Span& sp, const ::HIR::TypeR (Union, // Unions don't have drop glue unless they impl Drop return false; + ), + (ExternType, + // Extern types don't have drop glue + return false; ) ) ), diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 9ce40a74..fb214dda 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -2405,6 +2405,9 @@ namespace { TU_ARMA(Union, e) { BUG(node.span(), "_StructLiteral Union isn't valid?"); } + TU_ARMA(ExternType, e) { + BUG(node.span(), "_StructLiteral ExternType isn't valid?"); + } TU_ARMA(Struct, e) { if(e->m_data.is_Unit()) { m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 264c74c5..6fb77a3b 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -802,6 +802,9 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal ) ) ), + (ExternType, + TODO(sp, "Match extern type"); + ), (Union, TODO(sp, "Match union"); ), @@ -1217,6 +1220,9 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa (Union, TODO(sp, "Match over union - " << ty); ), + (ExternType, + TODO(sp, "Match over extern type - " << ty); + ), (Enum, auto monomorph = [&](const auto& ty) { auto rv = monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty); @@ -1738,6 +1744,9 @@ namespace { (Opaque, BUG(sp, "Destructuring an opaque type - " << *cur_ty); ), + (ExternType, + BUG(sp, "Destructuring an extern type - " << *cur_ty); + ), (Struct, // TODO: Should this do a call to expand_associated_types? auto monomorph = [&](const auto& ty) { @@ -2173,6 +2182,9 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& (Union, TODO(sp, "Match over Union"); ), + (ExternType, + TODO(sp, "Match over ExternType"); + ), (Enum, auto monomorph = [&](const auto& ty) { auto rv = monomorphise_type(sp, pbe->m_params, te.path.m_data.as_Generic().m_params, ty); @@ -2827,6 +2839,9 @@ void MatchGenGrouped::gen_dispatch(const ::std::vector& rules, s (Union, TODO(sp, "Match over Union"); ), + (ExternType, + TODO(sp, "Match over ExternType - " << ty); + ), (Enum, ) ) diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index d2609e9e..75a0857f 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -350,7 +350,7 @@ namespace auto v = mod.m_value_items.find(name); if( v != mod.m_value_items.end() ) { const auto& b = v->second.path.m_bindings.value; - if( const auto* be = b.opt_EnumVar() ) { + if( /*const auto* be =*/ b.opt_EnumVar() ) { DEBUG("- TY: Enum variant " << v->second.path); path = ::AST::Path( v->second.path ); return true; @@ -832,6 +832,9 @@ namespace { (TypeAlias, pb.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); ), + (ExternType, + pb.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); + ), (Struct, pb.type = ::AST::PathBinding_Type::make_Struct({nullptr, &e}); ), @@ -880,8 +883,8 @@ namespace { if( it == hmod->m_mod_items.end() ) ERROR(sp, E0000, "Couldn't find path component '" << n.name() << "' of " << path); - TU_MATCH(::HIR::TypeItem, (it->second->ent), (e), - (Import, + TU_MATCH_HDRA( (it->second->ent), {) + TU_ARMA(Import, e) { // - Update path then restart auto newpath = AST::Path(e.path.m_crate_name, {}); for(const auto& n : e.path.m_components) @@ -892,11 +895,11 @@ namespace { // TODO: Recursion limit Resolve_Absolute_Path_BindAbsolute(context, sp, mode, path); return ; - ), - (Module, + } + TU_ARMA(Module, e) { hmod = &e; - ), - (Trait, + } + TU_ARMA(Trait, e) { auto trait_path = ::AST::Path( crate.m_name, {} ); for(unsigned int j = start; j <= i; j ++) trait_path.nodes().push_back( path_abs.nodes[j].name() ); @@ -940,23 +943,15 @@ namespace { path = mv$(new_path); return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (TypeAlias, - path = split_into_crate(sp, mv$(path), start, crate.m_name); - path = split_into_ufcs_ty(sp, mv$(path), i-start); - return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (Struct, - path = split_into_crate(sp, mv$(path), start, crate.m_name); - path = split_into_ufcs_ty(sp, mv$(path), i-start); - return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (Union, + } + case ::HIR::TypeItem::TAG_ExternType: + case ::HIR::TypeItem::TAG_TypeAlias: + case ::HIR::TypeItem::TAG_Struct: + case ::HIR::TypeItem::TAG_Union: path = split_into_crate(sp, mv$(path), start, crate.m_name); path = split_into_ufcs_ty(sp, mv$(path), i-start); return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ), - (Enum, + TU_ARMA(Enum, e) { const auto& last_node = path_abs.nodes.back(); // If this refers to an enum variant, return the full path auto idx = e.find_variant(last_node.name()); @@ -982,8 +977,8 @@ namespace { path = split_into_crate(sp, mv$(path), start, crate.m_name); path = split_into_ufcs_ty(sp, mv$(path), i-start); return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path); - ) - ) + } + } } const auto& name = path_abs.nodes.back().name(); @@ -1007,6 +1002,9 @@ namespace { (Module, path.m_bindings.type = ::AST::PathBinding_Type::make_Module({nullptr, &e}); ), + (ExternType, + path.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); + ), (TypeAlias, path.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr/*, &e*/}); ), diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp index ec1fcd8d..ddeffa0c 100644 --- a/src/resolve/index.cpp +++ b/src/resolve/index.cpp @@ -241,7 +241,15 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod) i.is_pub, i_data.name, mv$(path), e.mac }); } - // TODO: Other imports (e.g. derives, which have different naming structures) + TU_ARMA(ProcMacro, e) { + TODO(sp, "ProcMacro import"); + } + TU_ARMA(ProcMacroAttribute, e) { + TODO(sp, "ProcMacroAttribute import"); + } + TU_ARMA(ProcMacroDerive, e) { + TODO(sp, "ProcMacroDerive import"); + } }} } else @@ -318,6 +326,9 @@ void Resolve_Index_Module_Wildcard__glob_in_hir_mod(const Span& sp, const AST::C p.m_bindings.type = ::AST::PathBinding_Type::make_Enum({nullptr}); ), (TypeAlias, + p.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); + ), + (ExternType, p.m_bindings.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); ) ) diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp index 8c9266a2..95e6d2c1 100644 --- a/src/resolve/use.cpp +++ b/src/resolve/use.cpp @@ -645,6 +645,9 @@ namespace { (TypeAlias, rv.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); ), + (ExternType, + rv.type = ::AST::PathBinding_Type::make_TypeAlias({nullptr}); // Lazy. + ), (Enum, rv.type = ::AST::PathBinding_Type::make_Enum({nullptr, &e}); ), diff --git a/src/trans/auto_impls.cpp b/src/trans/auto_impls.cpp index 418a338b..877659b2 100644 --- a/src/trans/auto_impls.cpp +++ b/src/trans/auto_impls.cpp @@ -74,7 +74,7 @@ void Trans_AutoImpl_Clone(State& state, ::HIR::TypeRef ty) // For each field of the tuple, create a clone (either using Copy if posible, or calling Clone::clone) for(const auto& subty : te) { - auto fld_lvalue = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Argument({ 0 })) })), values.size() }); + auto fld_lvalue = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Argument({ 0 })) })), static_cast(values.size()) }); if( state.resolve.type_is_copy(sp, subty) ) { values.push_back( ::std::move(fld_lvalue) ); @@ -94,8 +94,8 @@ void Trans_AutoImpl_Clone(State& state, ::HIR::TypeRef ty) ::MIR::RValue::make_Borrow({ 0, ::HIR::BorrowType::Shared, mv$(fld_lvalue) }) })); bb.terminator = ::MIR::Terminator::make_Call({ - mir_fcn.blocks.size() + 2, // return block (after the panic block below) - mir_fcn.blocks.size() + 1, // panic block (next block) + static_cast(mir_fcn.blocks.size() + 2), // return block (after the panic block below) + static_cast(mir_fcn.blocks.size() + 1), // panic block (next block) res_lv.clone(), ::MIR::CallTarget( ::HIR::Path(subty.clone(), lang_Clone, "clone") ), ::make_vec1<::MIR::Param>( ::std::move(borrow_lv) ) diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp index 9e93caba..b2b614a9 100644 --- a/src/trans/codegen.cpp +++ b/src/trans/codegen.cpp @@ -43,6 +43,9 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const TU_MATCHA( (te.binding), (tpb), (Unbound, throw ""; ), (Opaque, throw ""; ), + (ExternType, + //codegen->emit_extern_type(sp, te.path.m_data.as_Generic(), *tpb); + ), (Struct, codegen->emit_struct(sp, te.path.m_data.as_Generic(), *tpb); ), diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 2c40c991..979da88d 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1013,6 +1013,9 @@ namespace { (Struct, m_of << "struct s_" << Trans_Mangle(te.path) << ";\n"; ), + (ExternType, + m_of << "struct x_" << Trans_Mangle(te.path) << ";\n"; + ), (Union, m_of << "union u_" << Trans_Mangle(te.path) << ";\n"; ), @@ -1837,6 +1840,7 @@ namespace { TU_MATCHA((te.binding), (pbe), (Unbound, MIR_BUG(*m_mir_res, "Unbound type path " << ty); ), (Opaque, MIR_BUG(*m_mir_res, "Opaque type path " << ty); ), + (ExternType, MIR_BUG(*m_mir_res, "Extern type literal " << ty); ), (Struct, TU_MATCHA( (pbe->m_data), (se), (Unit, @@ -5351,6 +5355,9 @@ namespace { TU_MATCHA((te.binding), (pbe), (Unbound, MIR_BUG(*m_mir_res, "Unbound type path " << ty); ), (Opaque, MIR_BUG(*m_mir_res, "Opaque type path " << ty); ), + (ExternType, + MIR_BUG(*m_mir_res, "Extern type literal"); + ), (Struct, TU_MATCHA( (pbe->m_data), (se), (Unit, @@ -5835,6 +5842,10 @@ namespace { (Enum, m_of << "struct e_" << Trans_Mangle(te.path); ), + (ExternType, + m_of << "struct x_" << Trans_Mangle(te.path); + //return ; + ), (Unbound, MIR_BUG(*m_mir_res, "Unbound type path in trans - " << ty); ), diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 6aeb3485..c326d125 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -570,6 +570,9 @@ namespace { (Opaque, BUG(Span(), "Opaque type hit in enumeration - " << ty); ), + (ExternType, + // No innards to visit + ), (Struct, visit_struct(te.path.m_data.as_Generic(), *tpb); ), @@ -1064,15 +1067,10 @@ void Trans_Enumerate_Types(EnumState& state) TU_MATCHA( (te.binding), (tpb), (Unbound, ), (Opaque, ), - (Struct, - markings_ptr = &tpb->m_markings; - ), - (Union, - markings_ptr = &tpb->m_markings; - ), - (Enum, - markings_ptr = &tpb->m_markings; - ) + (ExternType, markings_ptr = &tpb->m_markings; ), + (Struct, markings_ptr = &tpb->m_markings; ), + (Union, markings_ptr = &tpb->m_markings; ), + (Enum, markings_ptr = &tpb->m_markings; ) ) ASSERT_BUG(Span(), markings_ptr, "Path binding not set correctly - " << ty); -- cgit v1.2.3 From b3eb51cb50f50db0ca81ff6e9f149143537dc60c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 3 Mar 2019 19:30:33 +0800 Subject: Codegen C - Don't emit extern types --- src/trans/codegen_c.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 979da88d..13421096 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1169,6 +1169,7 @@ namespace { TRACE_FUNCTION_F(p); auto item_ty = ::HIR::TypeRef::new_path(p.clone(), &item); const auto* repr = Target_GetTypeRepr(sp, m_resolve, item_ty); + MIR_ASSERT(*m_mir_res, repr, "No repr for struct " << p); ::std::vector fields; for(const auto& ent : repr->fields) @@ -5843,8 +5844,8 @@ namespace { m_of << "struct e_" << Trans_Mangle(te.path); ), (ExternType, - m_of << "struct x_" << Trans_Mangle(te.path); - //return ; + //m_of << "struct x_" << Trans_Mangle(te.path); + return ; ), (Unbound, MIR_BUG(*m_mir_res, "Unbound type path in trans - " << ty); -- cgit v1.2.3 From 90d82839a0d90845879f9df9314e408edf6ef419 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 3 Mar 2019 21:05:48 +0800 Subject: Codegen C - Cast to int128_t for literals --- src/trans/codegen_c.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 13421096..98d0d3de 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -5659,6 +5659,7 @@ namespace { } else { + m_of << "(int128_t)"; m_of << c.v; m_of << "ll"; } @@ -5692,6 +5693,7 @@ namespace { } else { + m_of << "(uint128_t)"; m_of << ::std::hex << "0x" << c.v << "ull" << ::std::dec; } break; -- cgit v1.2.3 From 967a76859749ecb602cd2c343e28888514f827bd Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 25 Apr 2019 13:56:11 +0800 Subject: MIR - Reduce size of LValue::Static by putting the HIR::Path behind a pointer --- src/hir/deserialise.cpp | 2 +- src/hir/serialise.cpp | 2 +- src/hir_conv/bind.cpp | 2 +- src/hir_conv/constant_evaluation.cpp | 4 +-- src/mir/dump.cpp | 2 +- src/mir/from_hir.cpp | 2 +- src/mir/helpers.cpp | 2 +- src/mir/mir.cpp | 4 +-- src/mir/mir.hpp | 58 +++++++++++++++++++++++++++++++++++- src/mir/mir_builder.cpp | 8 ++--- src/mir/optimise.cpp | 2 +- src/trans/codegen_c.cpp | 2 +- src/trans/codegen_mmir.cpp | 2 +- src/trans/enumerate.cpp | 4 +-- src/trans/monomorphise.cpp | 2 +- 15 files changed, 77 insertions(+), 21 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 9933255f..cd25a3cb 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -423,7 +423,7 @@ _(Return, {}) _(Argument, { static_cast(m_in.read_count()) } ) _(Local, static_cast(m_in.read_count()) ) - _(Static, deserialise_path() ) + _(Static, box$(deserialise_path()) ) _(Field, { box$( deserialise_mir_lvalue() ), static_cast(m_in.read_count()) diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index dd81596f..e90cf995 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -689,7 +689,7 @@ m_out.write_count(e); ), (Static, - serialise_path(e); + serialise_path(*e); ), (Field, serialise(e.val); diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index a3b0041b..940b2cab 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -712,7 +712,7 @@ namespace { (Argument, ), (Static, - upper_visitor.visit_path(e, ::HIR::Visitor::PathContext::VALUE); + upper_visitor.visit_path(*e, ::HIR::Visitor::PathContext::VALUE); ), (Field, H::visit_lvalue(upper_visitor, *e.val); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 6049056c..6838e186 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -319,7 +319,7 @@ namespace { return args[e.idx]; ), (Static, - MIR_TODO(state, "LValue::Static - " << e); + MIR_TODO(state, "LValue::Static - " << *e); ), (Field, auto& val = get_lval(*e.val); @@ -495,7 +495,7 @@ namespace { } else if( const auto* p = e.val.opt_Static() ) { // Borrow of a static, emit BorrowPath with the same path - val = ::HIR::Literal::make_BorrowPath( p->clone() ); + val = ::HIR::Literal::make_BorrowPath( (*p)->clone() ); } else { auto inner_val = local_state.read_lval(e.val); diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index 90b81d5d..ffce8abb 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -187,7 +187,7 @@ namespace { os << "_$" << e; ), (Static, - os << e; + os << *e; ), (Field, os << "("; diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index a2d0c790..912b8c78 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -2195,7 +2195,7 @@ namespace { m_builder.set_result( node.span(), mv$(tmp) ); ), (Static, - m_builder.set_result( node.span(), ::MIR::LValue::make_Static(node.m_path.clone()) ); + m_builder.set_result( node.span(), ::MIR::LValue::make_Static(box$(node.m_path.clone())) ); ), (StructConstant, // TODO: Why is this still a PathValue? diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 38380fed..38388aed 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -82,7 +82,7 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return m_fcn.locals.at(e); ), (Static, - return get_static_type(tmp, e); + return get_static_type(tmp, *e); ), (Field, const auto& ty = this->get_lvalue_type(tmp, *e.val); diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index ee6c1a6c..657e695d 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -104,7 +104,7 @@ namespace MIR { os << "Local(" << e << ")"; ), (Static, - os << "Static(" << e << ")"; + os << "Static(" << *e << ")"; ), (Field, os << "Field(" << e.field_index << ", " << *e.val << ")"; @@ -543,7 +543,7 @@ namespace MIR { (Return, return LValue(e); ), (Argument, return LValue(e); ), (Local, return LValue(e); ), - (Static, return LValue(e.clone()); ), + (Static, return LValue(box$(e->clone())); ), (Field, return LValue::make_Field({ box$( e.val->clone() ), e.field_index diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 31eb9cd7..6969225d 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -17,6 +17,62 @@ namespace MIR { typedef unsigned int RegionId; typedef unsigned int BasicBlockId; +#if 0 +// TODO: Store LValues as: +// - A packed root value (one word, using the low bits as an enum descriminator) +// - A list of (inner to outer) wrappers +struct LValue +{ + class Storage + { + uintptr_t val; + public: + ~Storage() + { + if( is_Static() ) { + delete reinterpret_cast<::HIR::Path*>(val & ~3u); + val = 0; + } + } + bool is_Argument() const { return val != (MAX_ARG << 2) && (val & 3) == 0; } + bool is_Return() const { return val == (MAX_ARG << 2); } + bool is_Local() const { return (val & 3) == 1; } + bool is_Static() const { return (val & 3) == 2; } + + const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3u); } + }; + class Wrapper + { + uintptr_t val; + public: + bool is_Deref() const { return (val & 3) == 0; } + // Stores the field index + bool is_Field() const { return (val & 3) == 1; } + // Stores the variant index + bool is_Downcast() const { return (val & 3) == 2; } + // Stores a Local index + bool is_Index() const { return (val & 3) == 3; } + + const unsigned as_Field() const { assert(is_Field()); return (val >> 2); } + const unsigned as_Index() const { assert(is_Index()); return (val >> 2); } + }; + + Storage m_root; + ::std::vector m_wrappers; + + LValue clone() const; + + class Ref + { + LValue& r; + size_t wrapper_idx; + public:: + LValue clone() const; + void replace(LValue x) const; + }; +}; +#endif + // "LVALUE" - Assignable values TAGGED_UNION_EX(LValue, (), Return, ( // Function return @@ -26,7 +82,7 @@ TAGGED_UNION_EX(LValue, (), Return, ( // Variable/Temporary (Local, unsigned int), // `static` or `static mut` - (Static, ::HIR::Path), + (Static, ::std::unique_ptr<::HIR::Path>), // Field access (tuple, struct, tuple struct, enum field, ...) // NOTE: Also used to index an array/slice by a compile-time known index (e.g. in destructuring) (Field, struct { diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index ac1b7650..81816535 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -1622,20 +1622,20 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: cb( m_output.locals.at(e) ); ), (Static, - TU_MATCHA( (e.m_data), (pe), + TU_MATCHA( (e->m_data), (pe), (Generic, ASSERT_BUG(sp, pe.m_params.m_types.empty(), "Path params on static"); const auto& s = m_resolve.m_crate.get_static_by_path(sp, pe.m_path); cb( s.m_type ); ), (UfcsKnown, - TODO(sp, "Static - UfcsKnown - " << e); + TODO(sp, "Static - UfcsKnown - " << *e); ), (UfcsUnknown, - BUG(sp, "Encountered UfcsUnknown in Static - " << e); + BUG(sp, "Encountered UfcsUnknown in Static - " << *e); ), (UfcsInherent, - TODO(sp, "Static - UfcsInherent - " << e); + TODO(sp, "Static - UfcsInherent - " << *e); ) ) ), diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 67a5d4a4..b7e63deb 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -1159,7 +1159,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool return ::MIR::LValue::make_Local(this->var_base + se); ), (Static, - return this->monomorph( se ); + return box$(this->monomorph( *se )); ), (Deref, return ::MIR::LValue::make_Deref({ box$(this->clone_lval(*se.val)) }); diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 98d0d3de..373a36a8 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -5522,7 +5522,7 @@ namespace { m_of << "var" << e; ), (Static, - m_of << Trans_Mangle(e); + m_of << Trans_Mangle(*e); ), (Field, ::HIR::TypeRef tmp; diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index b2c5282a..4867cf6f 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -52,7 +52,7 @@ namespace os << "arg" << e.idx; break; TU_ARM(x.e, Static, e) - os << e; + os << *e; break; TU_ARM(x.e, Deref, e) os << "*" << fmt(*e.val); diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index afdbd626..da11386c 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -735,7 +735,7 @@ void Trans_Enumerate_Types(EnumState& state) ), (Static, if( tmp_ty_ptr ) { - const auto& path = e; + const auto& path = *e; TU_MATCHA( (path.m_data), (pe), (Generic, ASSERT_BUG(Span(), pe.m_params.m_types.empty(), "Path params on static - " << path); @@ -1495,7 +1495,7 @@ void Trans_Enumerate_FillFrom_MIR_LValue(EnumState& state, const ::MIR::LValue& (Local, ), (Static, - Trans_Enumerate_FillFrom_Path(state, e, pp); + Trans_Enumerate_FillFrom_Path(state, *e, pp); ), (Field, Trans_Enumerate_FillFrom_MIR_LValue(state, *e.val, pp); diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index 3b958fec..0a0b43b5 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -19,7 +19,7 @@ namespace { (Argument, return e; ), (Local, return e; ), (Static, - return params.monomorph(resolve, e); + return box$(params.monomorph(resolve, *e)); ), (Field, return ::MIR::LValue::make_Field({ -- cgit v1.2.3 From 406fe84b2c663e5b1a31448baefe09b847cb635c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 28 Apr 2019 15:23:37 +0800 Subject: Trans Monomorph - Associated constants left as Defer --- src/hir/hir.hpp | 3 +++ src/hir_conv/constant_evaluation.cpp | 51 ++++++++++++++++++------------------ src/trans/codegen_c.cpp | 17 ++++++++++-- src/trans/enumerate.cpp | 39 ++++++++++++++++++++------- src/trans/monomorphise.cpp | 30 +++++++++++++++++++-- src/trans/trans_list.cpp | 15 +++++++++++ src/trans/trans_list.hpp | 1 + 7 files changed, 116 insertions(+), 40 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index f0844580..6c8385c4 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -173,6 +173,9 @@ public: TypeRef m_type; ExprPtr m_value; Literal m_value_res; + + // A cache of monomorphised versions when the `const` depends on generics for its value + mutable ::std::map< ::HIR::Path, Literal> m_monomorph_cache; }; class Function { diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 6838e186..6067b32f 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -16,12 +16,15 @@ #include #include +#include "constant_evaluation.hpp" #include // For handling monomorph of MIR in provided associated constants #define CHECK_DEFER(var) do { if( var.is_Defer() ) { m_rv = ::HIR::Literal::make_Defer({}); return ; } } while(0) namespace { - struct NewvalState { + struct NewvalState + : public HIR::Evaluator::Newval + { const ::HIR::Module& mod; const ::HIR::ItemPath& mod_path; ::std::string name_prefix; @@ -35,7 +38,7 @@ namespace { { } - ::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value) + virtual ::HIR::Path new_static(::HIR::TypeRef type, ::HIR::Literal value) override { auto name = FMT(name_prefix << next_item_idx); next_item_idx ++; @@ -51,23 +54,6 @@ namespace { return rv; } }; - struct Evaluator - { - const Span& root_span; - StaticTraitResolve resolve; - NewvalState nvs; - - Evaluator(const Span& sp, const ::HIR::Crate& crate, NewvalState nvs): - root_span(sp), - resolve(crate), - nvs( ::std::move(nvs) ) - { - } - - ::HIR::Literal evaluate_constant(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, MonomorphState ms={}); - - ::HIR::Literal evaluate_constant_mir(const ::HIR::ItemPath& ip, const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args); - }; ::HIR::Literal clone_literal(const ::HIR::Literal& v) { @@ -276,6 +262,9 @@ namespace { TODO(sp, "Could not find function for " << path << " - " << rv.tag_str()); } } +} // namespace + +namespace HIR { ::HIR::Literal Evaluator::evaluate_constant_mir(const ::HIR::ItemPath& ip, const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args) { @@ -417,7 +406,8 @@ namespace { auto& item = const_cast<::HIR::Constant&>(c); // Challenge: Adding items to the module might invalidate an iterator. ::HIR::ItemPath mod_ip { item.m_value.m_state->m_mod_path }; - auto eval = Evaluator { item.m_value.span(), resolve.m_crate, NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") } }; + auto nvs = NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") }; + auto eval = ::HIR::Evaluator { item.m_value.span(), resolve.m_crate, nvs }; DEBUG("- Evaluate " << p); DEBUG("- " << ::HIR::ItemPath(p)); item.m_value_res = eval.evaluate_constant(::HIR::ItemPath(p), item.m_value, item.m_type.clone()); @@ -875,6 +865,9 @@ namespace { BUG(this->root_span, "Attempting to evaluate constant expression with no associated code"); } } +} // namespace HIR + +namespace { void check_lit_type(const Span& sp, const ::HIR::TypeRef& type, ::HIR::Literal& lit) { @@ -1028,7 +1021,8 @@ namespace { }); const auto& template_const = vi.second.as_Constant(); if( template_const.m_value_res.is_Defer() ) { - auto eval = Evaluator { sp, m_crate, NewvalState { *m_mod, *m_mod_path, FMT("impl" << &impl << "$" << vi.first << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT("impl" << &impl << "$" << vi.first << "$") }; + auto eval = ::HIR::Evaluator { sp, m_crate, nvs }; ::HIR::ExprPtr ep; Trans_Params tp(sp); tp.self_type = ms.self_ty->clone(); @@ -1094,7 +1088,8 @@ namespace { const auto& expr_ptr = *e.size; auto ty_name = FMT("ty_" << &ty << "$"); - auto eval = Evaluator { expr_ptr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, ty_name } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, ty_name }; + auto eval = ::HIR::Evaluator { expr_ptr->span(), m_crate, nvs }; auto val = eval.evaluate_constant(::HIR::ItemPath(*m_mod_path, ty_name.c_str()), expr_ptr, ::HIR::CoreType::Usize); if( !val.is_Integer() ) ERROR(expr_ptr->span(), E0000, "Array size isn't an integer"); @@ -1110,7 +1105,8 @@ namespace { // NOTE: Consteval needed here for MIR match generation to work if( item.m_value || item.m_value.m_mir ) { - auto eval = Evaluator { item.m_value.span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") }; + auto eval = ::HIR::Evaluator { item.m_value.span(), m_crate, nvs }; item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone(), m_monomorph_state.clone()); check_lit_type(item.m_value.span(), item.m_type, item.m_value_res); @@ -1124,7 +1120,8 @@ namespace { if( item.m_value ) { - auto eval = Evaluator { item.m_value->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") }; + auto eval = ::HIR::Evaluator { item.m_value->span(), m_crate, nvs }; item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone()); check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); @@ -1142,7 +1139,8 @@ namespace { { if( var.expr ) { - auto eval = Evaluator { var.expr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") }; + auto eval = ::HIR::Evaluator { var.expr->span(), m_crate, nvs }; auto val = eval.evaluate_constant(p, var.expr, ty.clone()); DEBUG("enum variant: " << p << "::" << var.name << " = " << val); i = val.as_Integer(); @@ -1178,7 +1176,8 @@ namespace { void visit(::HIR::ExprNode_ArraySized& node) override { assert( node.m_size ); auto name = FMT("array_" << &node << "$"); - auto eval = Evaluator { node.span(), m_exp.m_crate, NewvalState { *m_exp.m_mod, *m_exp.m_mod_path, name } }; + auto nvs = NewvalState { *m_exp.m_mod, *m_exp.m_mod_path, name }; + auto eval = ::HIR::Evaluator { node.span(), m_exp.m_crate, nvs }; auto val = eval.evaluate_constant( ::HIR::ItemPath(*m_exp.m_mod_path, name.c_str()), node.m_size, ::HIR::CoreType::Usize ); if( !val.is_Integer() ) ERROR(node.span(), E0000, "Array size isn't an integer"); diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 373a36a8..08b4f2de 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -5288,8 +5288,21 @@ namespace { auto v = m_resolve.get_value(m_mir_res->sp, path, params); if( const auto* e = v.opt_Constant() ) { - ty = params.monomorph(m_mir_res->sp, (*e)->m_type); - return (*e)->m_value_res; + const auto& hir_const = **e; + ty = params.monomorph(m_mir_res->sp, hir_const.m_type); + if( hir_const.m_value_res.is_Defer() ) + { + // Do some form of lookup of a pre-cached evaluated monomorphised constant + // - Maybe on the `Constant` entry there can be a list of pre-monomorphised values + auto it = hir_const.m_monomorph_cache.find(path); + if( it == hir_const.m_monomorph_cache.end() ) + { + MIR_BUG(*m_mir_res, "Constant with Defer literal and no cached monomorphisation - " << path); + // TODO: Can do the consteval here? + } + return it->second; + } + return hir_const.m_value_res; } else { diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index da11386c..00b938ff 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -903,6 +903,10 @@ void Trans_Enumerate_Types(EnumState& state) return blank; } + static void visit_const(TypeVisitor& tv, const Trans_Params& pp, const ::HIR::Function& fcn, const ::MIR::Constant& p) + { + } + static void visit_param(TypeVisitor& tv, const Trans_Params& pp, const ::HIR::Function& fcn, const ::MIR::Param& p) { TU_MATCHA( (p), (e), @@ -910,6 +914,7 @@ void Trans_Enumerate_Types(EnumState& state) H::visit_lvalue(tv, pp, fcn, e); ), (Constant, + H::visit_const(tv, pp, fcn, e); ) ) } @@ -937,6 +942,7 @@ void Trans_Enumerate_Types(EnumState& state) H::visit_lvalue(tv,pp,fcn, re); ), (Constant, + H::visit_const(tv,pp,fcn, re); ), (SizedArray, H::visit_param(tv,pp,fcn, re.val); @@ -1182,14 +1188,14 @@ namespace { return true; } } - //{ - // auto it = impl.m_constants.find(e.item); - // if( it != impl.m_constants.end() ) - // { - // rv = EntPtr { &it->second.data }; - // return true; - // } - //} + { + auto it = impl.m_constants.find(pe->item); + if( it != impl.m_constants.end() ) + { + rv = EntPtr { &it->second.data }; + return true; + } + } return false; }); return rv; @@ -1481,7 +1487,19 @@ void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, co } } TU_ARMA(Constant, e) { - Trans_Enumerate_FillFrom_Literal(state, e->m_value_res, sub_pp); + if( e->m_value_res.is_Defer() ) + { + if( auto* slot = state.rv.add_const(mv$(path_mono)) ) + { + Trans_Enumerate_FillFrom_MIR(state, *e->m_value.m_mir, sub_pp); + slot->ptr = e; + slot->pp = ::std::move(sub_pp); + } + } + else + { + Trans_Enumerate_FillFrom_Literal(state, e->m_value_res, sub_pp); + } } } } @@ -1522,7 +1540,8 @@ void Trans_Enumerate_FillFrom_MIR_Constant(EnumState& state, const ::MIR::Consta (Bytes, ), (StaticString, ), // String (Const, - //Trans_Enumerate_FillFrom_Path(state, ce.p, pp); + // - Check if this constant has a value of Defer + Trans_Enumerate_FillFrom_Path(state, ce.p, pp); ), (ItemAddr, Trans_Enumerate_FillFrom_Path(state, ce, pp); diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index 0a0b43b5..cf101443 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -10,6 +10,7 @@ #include #include #include // Needed for post-monomorph checks and optimisations +#include namespace { ::MIR::LValue monomorph_LValue(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::MIR::LValue& tpl) @@ -361,8 +362,8 @@ void Trans_Monomorphise_List(const ::HIR::Crate& crate, TransList& list) for(const auto& a : fcn.m_args) args.push_back(::std::make_pair( ::HIR::Pattern{}, pp.monomorph(resolve, a.second) )); - ::std::string s = FMT(path); - ::HIR::ItemPath ip(s); + //::std::string s = FMT(path); + ::HIR::ItemPath ip(path); MIR_Validate(resolve, ip, *mir, args, ret_type); MIR_Cleanup(resolve, ip, *mir, args, ret_type); MIR_Optimise(resolve, ip, *mir, args, ret_type); @@ -373,5 +374,30 @@ void Trans_Monomorphise_List(const ::HIR::Crate& crate, TransList& list) fcn_ent.second->monomorphised.code = ::std::move(mir); } } + + // Also do constants and statics (stored in where?) + for(auto& ent : list.m_constants) + { + const auto& path = ent.first; + const auto& pp = ent.second->pp; + const auto& c = *ent.second->ptr; + TRACE_FUNCTION_FR(path, path); + auto ty = pp.monomorph(resolve, c.m_type); + // 1. Evaluate the constant + struct Nvs: public ::HIR::Evaluator::Newval + { + ::HIR::Path new_static(::HIR::TypeRef type, ::HIR::Literal value) override { + TODO(Span(), "Create new static in monomorph pass - " << value << " : " << type); + } + } nvs; + auto eval = ::HIR::Evaluator { pp.sp, crate, nvs }; + MonomorphState ms; + ms.self_ty = &pp.self_type; + ms.pp_impl = &pp.pp_impl; + ms.pp_method = &pp.pp_method; + auto new_lit = eval.evaluate_constant(path, c.m_value, ::std::move(ty), ::std::move(ms)); + // 2. Store evaluated HIR::Literal in c.m_monomorph_cache + c.m_monomorph_cache.insert(::std::make_pair( path.clone(), ::std::move(new_lit) )); + } } diff --git a/src/trans/trans_list.cpp b/src/trans/trans_list.cpp index 04e1e9a1..54ae8011 100644 --- a/src/trans/trans_list.cpp +++ b/src/trans/trans_list.cpp @@ -38,6 +38,21 @@ TransList_Static* TransList::add_static(::HIR::Path p) return nullptr; } } +TransList_Const* TransList::add_const(::HIR::Path p) +{ + auto rv = m_constants.insert( ::std::make_pair(mv$(p), nullptr) ); + if( rv.second ) + { + DEBUG("Const " << rv.first->first); + assert( !rv.first->second ); + rv.first->second.reset( new TransList_Const {} ); + return &*rv.first->second; + } + else + { + return nullptr; + } +} t_cb_generic Trans_Params::get_cb() const { diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index b58a241d..df550925 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -95,6 +95,7 @@ public: TransList_Function* add_function(::HIR::Path p); TransList_Static* add_static(::HIR::Path p); + TransList_Const* add_const(::HIR::Path p); bool add_vtable(::HIR::Path p, Trans_Params pp) { return m_vtables.insert( ::std::make_pair( mv$(p), mv$(pp) ) ).second; } -- cgit v1.2.3 From 4c4a7b88914861b644ec56738ced8cfc179f93f9 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 5 May 2019 12:42:57 +0800 Subject: MIR - Wrap HIR::Path-s in MIR::Constant in unique_ptr --- src/hir/deserialise.cpp | 4 +-- src/hir/expr_ptr.cpp | 13 ++++--- src/hir/serialise.cpp | 4 +-- src/hir_conv/bind.cpp | 47 ++++++++++--------------- src/hir_conv/constant_evaluation.cpp | 6 ++-- src/mir/cleanup.cpp | 18 +++++----- src/mir/dump.cpp | 4 +-- src/mir/from_hir.cpp | 20 ++++++----- src/mir/helpers.cpp | 10 +++--- src/mir/mir.cpp | 12 +++---- src/mir/mir.hpp | 67 ++++++++++++++++++++++++++++++------ src/mir/optimise.cpp | 4 +-- src/trans/codegen_c.cpp | 8 ++--- src/trans/codegen_mmir.cpp | 2 +- src/trans/enumerate.cpp | 4 +-- src/trans/monomorphise.cpp | 6 ++-- 16 files changed, 135 insertions(+), 94 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index cd25a3cb..c5350b55 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -532,8 +532,8 @@ return ::MIR::Constant::make_Bytes( mv$(bytes) ); } _(StaticString, m_in.read_string() ) - _(Const, { deserialise_path() } ) - _(ItemAddr, deserialise_path() ) + _(Const, { box$(deserialise_path()) } ) + _(ItemAddr, box$(deserialise_path()) ) #undef _ default: BUG(Span(), "Bad tag for MIR::Const - " << tag); diff --git a/src/hir/expr_ptr.cpp b/src/hir/expr_ptr.cpp index 0c219e0f..7f493a0d 100644 --- a/src/hir/expr_ptr.cpp +++ b/src/hir/expr_ptr.cpp @@ -91,11 +91,14 @@ void HIR::ExprPtr::set_mir(::MIR::FunctionPointer mir) assert( !this->m_mir ); m_mir = ::std::move(mir); // Reset the HIR tree to be a placeholder node (thus freeing the backing memory) - //if( node ) - //{ - // auto sp = node->span(); - // node = ExprPtrInner(::std::unique_ptr(new ::HIR::ExprNode_Tuple(sp, {}))); - //} + if( false && node ) + { + auto sp = node->span(); + node = ExprPtrInner(::std::unique_ptr(new ::HIR::ExprNode_Loop( + sp, "", + ::std::unique_ptr(new ::HIR::ExprNode_Tuple(sp, {})) + ))); + } } diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index e90cf995..2c72c801 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -795,10 +795,10 @@ m_out.write_string(e); ), (Const, - serialise_path(e.p); + serialise_path(*e.p); ), (ItemAddr, - serialise_path(e); + serialise_path(*e); ) ) } diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 940b2cab..84854315 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -729,25 +729,29 @@ namespace { ) ) } + static void visit_constant(Visitor& upper_visitor, ::MIR::Constant& e) + { + TU_MATCHA( (e), (ce), + (Int, ), + (Uint,), + (Float, ), + (Bool, ), + (Bytes, ), + (StaticString, ), // String + (Const, + upper_visitor.visit_path(*ce.p, ::HIR::Visitor::PathContext::VALUE); + ), + (ItemAddr, + upper_visitor.visit_path(*ce, ::HIR::Visitor::PathContext::VALUE); + ) + ) + } static void visit_param(Visitor& upper_visitor, ::MIR::Param& p) { TU_MATCHA( (p), (e), (LValue, H::visit_lvalue(upper_visitor, e);), (Constant, - TU_MATCHA( (e), (ce), - (Int, ), - (Uint,), - (Float, ), - (Bool, ), - (Bytes, ), - (StaticString, ), // String - (Const, - upper_visitor.visit_path(ce.p, ::HIR::Visitor::PathContext::VALUE); - ), - (ItemAddr, - upper_visitor.visit_path(ce, ::HIR::Visitor::PathContext::VALUE); - ) - ) + H::visit_constant(upper_visitor, e); ) ) } @@ -765,20 +769,7 @@ namespace { H::visit_lvalue(*this, e); ), (Constant, - TU_MATCHA( (e), (ce), - (Int, ), - (Uint,), - (Float, ), - (Bool, ), - (Bytes, ), - (StaticString, ), // String - (Const, - this->visit_path(ce.p, ::HIR::Visitor::PathContext::VALUE); - ), - (ItemAddr, - this->visit_path(ce, ::HIR::Visitor::PathContext::VALUE); - ) - ) + H::visit_constant(*this, e); ), (SizedArray, H::visit_param(*this, e.val); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 6067b32f..0ccb6e6f 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -390,11 +390,11 @@ namespace HIR { TU_ARM(c, StaticString, e2) return ::HIR::Literal(e2); TU_ARM(c, Const, e2) { - auto p = ms.monomorph(state.sp, e2.p); + auto p = ms.monomorph(state.sp, *e2.p); // If there's any mention of generics in this path, then return Literal::Defer if( visit_path_tys_with(p, [&](const auto& ty)->bool { return ty.m_data.is_Generic(); }) ) { - DEBUG("Return Literal::Defer for constant " << e2.p << " which references a generic parameter"); + DEBUG("Return Literal::Defer for constant " << *e2.p << " which references a generic parameter"); return ::HIR::Literal::make_Defer({}); } MonomorphState const_ms; @@ -417,7 +417,7 @@ namespace HIR { return clone_literal( c.m_value_res ); } TU_ARM(c, ItemAddr, e2) - return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, e2) ); + return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, *e2) ); } throw ""; }; diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index fdc0f3d4..dd5332b6 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -216,7 +216,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con if( path == ::HIR::GenericPath() ) MIR_TODO(state, "Literal of type " << ty << " - " << lit); DEBUG("Unknown type " << ty << ", but a path was provided - Return ItemAddr " << path); - return ::MIR::Constant( mv$(path) ); + return ::MIR::Constant::make_ItemAddr( box$(path) ); ), (Tuple, MIR_ASSERT(state, lit.is_List(), "Non-list literal for Tuple - " << lit); @@ -378,7 +378,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con if( const auto* pp = lit.opt_BorrowPath() ) { const auto& path = *pp; - auto ptr_val = ::MIR::Constant::make_ItemAddr(path.clone()); + auto ptr_val = ::MIR::Constant::make_ItemAddr(box$(path.clone())); // TODO: Get the metadata type (for !Sized wrapper types) if( te.inner->m_data.is_Slice() ) { @@ -397,7 +397,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con auto vtable_path = ::HIR::Path(&ty == &tmp ? mv$(tmp) : ty.clone(), tep->m_trait.m_path.clone(), "vtable#"); - auto vtable_val = ::MIR::Param( ::MIR::Constant::make_ItemAddr(mv$(vtable_path)) ); + auto vtable_val = ::MIR::Param( ::MIR::Constant::make_ItemAddr(box$(vtable_path)) ); return ::MIR::RValue::make_MakeDst({ ::MIR::Param(mv$(ptr_val)), mv$(vtable_val) }); } @@ -458,7 +458,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con (Function, //MIR_TODO(state, "Const function pointer " << lit << " w/ type " << ty); MIR_ASSERT(state, lit.is_BorrowPath(), ""); - return ::MIR::Constant::make_ItemAddr( lit.as_BorrowPath().clone() ); + return ::MIR::Constant::make_ItemAddr( box$( lit.as_BorrowPath().clone() ) ); ) ) } @@ -703,7 +703,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& MIR_ASSERT(state, state.m_resolve.type_is_sized(state.sp, src_ty), "Attempting to get vtable for unsized type - " << src_ty); ::HIR::Path vtable { src_ty.clone(), trait_path.m_path.clone(), "vtable#" }; - out_meta_val = ::MIR::Constant::make_ItemAddr(mv$(vtable)); + out_meta_val = ::MIR::Constant::make_ItemAddr(box$(vtable)); } } return true; @@ -1092,18 +1092,18 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, TU_IFLET( ::MIR::Constant, e, Const, ce, // 1. Find the constant ::HIR::TypeRef ty; - const auto* lit_ptr = MIR_Cleanup_GetConstant(state, ce.p, ty); + const auto* lit_ptr = MIR_Cleanup_GetConstant(state, *ce.p, ty); if( lit_ptr && !lit_ptr->is_Defer() ) { - DEBUG("Replace constant " << ce.p << " with " << *lit_ptr); - se.src = MIR_Cleanup_LiteralToRValue(state, mutator, *lit_ptr, mv$(ty), mv$(ce.p)); + DEBUG("Replace constant " << *ce.p << " with " << *lit_ptr); + se.src = MIR_Cleanup_LiteralToRValue(state, mutator, *lit_ptr, mv$(ty), mv$(*ce.p)); if( auto* p = se.src.opt_Constant() ) { MIR_Cleanup_Constant(state, mutator, *p); } } else { - DEBUG("No replacement for constant " << ce.p); + DEBUG("No replacement for constant " << *ce.p); } ) ) diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index ffce8abb..b02c1e5b 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -244,10 +244,10 @@ namespace { os << "\"" << ce << "\""; ), (Const, - os << ce.p; + os << *ce.p; ), (ItemAddr, - os << "addr " << ce; + os << "addr " << *ce; ) ) } diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 8d51bf55..b8549f8a 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -162,6 +162,7 @@ namespace { void destructure_from_ex(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval, int allow_refutable=0) // 1 : yes, 2 : disallow binding { + TRACE_FUNCTION_F(pat << ", allow_refutable=" << allow_refutable); if( allow_refutable != 3 && pat.m_binding.is_valid() ) { if( allow_refutable == 2 ) { BUG(sp, "Binding when not expected"); @@ -425,9 +426,10 @@ namespace { // 2. Obtain pointer to element ::HIR::BorrowType bt = H::get_borrow_type(sp, e.extra_bind); ::MIR::LValue ptr_val = m_builder.lvalue_or_temp(sp, - ::HIR::TypeRef::new_pointer( bt, inner_type.clone() ), + ::HIR::TypeRef::new_borrow( bt, inner_type.clone() ), ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::make_Field({ box$(lval.clone()), static_cast(e.leading.size()) }) }) ); + // TODO: Cast to raw pointer? Or keep as a borrow? // Construct fat pointer m_builder.push_stmt_assign( sp, m_builder.get_variable(sp, e.extra_bind.m_slot), ::MIR::RValue::make_MakeDst({ mv$(ptr_val), mv$(len_val) }) ); @@ -2185,7 +2187,7 @@ namespace { // TODO: Ideally, the creation of the wrapper function would happen somewhere before trans? auto tmp = m_builder.new_temporary( node.m_res_type ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); m_builder.set_result( sp, mv$(tmp) ); return ; } @@ -2196,7 +2198,7 @@ namespace { ), (Constant, auto tmp = m_builder.new_temporary( e.m_type ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_Const({node.m_path.clone()}) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_Const({box$(node.m_path.clone())}) ); m_builder.set_result( node.span(), mv$(tmp) ); ), (Static, @@ -2245,13 +2247,13 @@ namespace { fcn_ty_data.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) ); } auto tmp = m_builder.new_temporary( ::HIR::TypeRef( mv$(fcn_ty_data) ) ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); m_builder.set_result( sp, mv$(tmp) ); ), (StructConstructor, // TODO: Ideally, the creation of the wrapper function would happen somewhere before this? auto tmp = m_builder.new_temporary( node.m_res_type ); - m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); m_builder.set_result( sp, mv$(tmp) ); ) ) @@ -2263,13 +2265,13 @@ namespace { ASSERT_BUG(sp, it != tr.m_values.end(), "Cannot find trait item for " << node.m_path); TU_MATCHA( (it->second), (e), (Constant, - m_builder.set_result( sp, ::MIR::Constant::make_Const({node.m_path.clone()}) ); + m_builder.set_result( sp, ::MIR::Constant::make_Const({box$(node.m_path.clone())}) ); ), (Static, TODO(sp, "Associated statics (non-rustc) - " << node.m_path); ), (Function, - m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); ) ) ), @@ -2285,7 +2287,7 @@ namespace { { auto it = impl.m_methods.find(pe.item); if( it != impl.m_methods.end() ) { - m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); + m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) ); return true; } } @@ -2293,7 +2295,7 @@ namespace { { auto it = impl.m_constants.find(pe.item); if( it != impl.m_constants.end() ) { - m_builder.set_result( sp, ::MIR::Constant::make_Const({node.m_path.clone()}) ); + m_builder.set_result( sp, ::MIR::Constant::make_Const({box$(node.m_path.clone())}) ); return true; } } diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 38388aed..1453acb3 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -270,7 +270,7 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons ), (Const, MonomorphState p; - auto v = m_resolve.get_value(this->sp, e.p, p, /*signature_only=*/true); + auto v = m_resolve.get_value(this->sp, *e.p, p, /*signature_only=*/true); if( const auto* ve = v.opt_Constant() ) { const auto& ty = (*ve)->m_type; if( monomorphise_type_needed(ty) ) { @@ -282,12 +282,12 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons return ty.clone(); } else { - MIR_BUG(*this, "get_const_type - Not a constant " << e.p); + MIR_BUG(*this, "get_const_type - Not a constant " << *e.p); } ), (ItemAddr, MonomorphState p; - auto v = m_resolve.get_value(this->sp, e, p, /*signature_only=*/true); + auto v = m_resolve.get_value(this->sp, *e, p, /*signature_only=*/true); TU_MATCHA( (v), (ve), (NotFound, MIR_BUG(*this, "get_const_type - ItemAddr points to unknown value - " << c); @@ -325,7 +325,7 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons ::HIR::FunctionType ft; ft.is_unsafe = false; ft.m_abi = ABI_RUST; - auto enum_path = e.clone(); + auto enum_path = e->clone(); enum_path.m_data.as_Generic().m_path.m_components.pop_back(); ft.m_rettype = box$( ::HIR::TypeRef::new_path(mv$(enum_path), ve.e) ); ft.m_arg_types.reserve(str_data.size()); @@ -348,7 +348,7 @@ const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, cons ::HIR::FunctionType ft; ft.is_unsafe = false; ft.m_abi = ABI_RUST; - ft.m_rettype = box$( ::HIR::TypeRef::new_path( ::HIR::GenericPath(*ve.p, e.m_data.as_Generic().m_params.clone()), &str) ); + ft.m_rettype = box$( ::HIR::TypeRef::new_path( ::HIR::GenericPath(*ve.p, e->m_data.as_Generic().m_params.clone()), &str) ); ft.m_arg_types.reserve(str_data.size()); for(const auto& fld : str_data) ft.m_arg_types.push_back( p.monomorph(this->sp, fld.ent) ); diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 657e695d..638b8e46 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -44,10 +44,10 @@ namespace MIR { os << "\"" << FmtEscaped(e) << "\""; ), (Const, - os << e.p; + os << *e.p; ), (ItemAddr, - os << "&" << e; + os << "&" << *e; ) ) return os; @@ -82,10 +82,10 @@ namespace MIR { return ::ord(ae, be); ), (Const, - return ::ord(ae.p, be.p); + return ::ord(*ae.p, *be.p); ), (ItemAddr, - return ::ord(ae, be); + return ::ord(*ae, *be); ) ) throw ""; @@ -571,8 +571,8 @@ namespace MIR { (Bool, return ::MIR::Constant(e2); ), (Bytes, return ::MIR::Constant(e2); ), (StaticString, return ::MIR::Constant(e2); ), - (Const, return ::MIR::Constant::make_Const({e2.p.clone()}); ), - (ItemAddr, return ::MIR::Constant(e2.clone()); ) + (Const, return ::MIR::Constant::make_Const({box$(e2.p->clone())}); ), + (ItemAddr, return ::MIR::Constant(box$(e2->clone())); ) ) throw ""; } diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 7100d4aa..c24aac51 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -26,7 +26,21 @@ struct LValue class Storage { uintptr_t val; + static uintptr_t MAX_ARG = (1 << 30) - 1; // max value of 30 bits public: + Storage(const Storage&) = delete; + Storage& operator=(const Storage&) = delete; + Storage(Storage&& x) + :val(x.val) + { + x.val = 0; + } + Storage& operator=(Storage&& x) + { + this->~Storage(); + this->val = x.val; + x.val = 0; + } ~Storage() { if( is_Static() ) { @@ -34,32 +48,64 @@ struct LValue val = 0; } } + + static Storage new_Return() { return Storage { MAX_ARG << 2 }; } + static Storage new_Argument(unsigned idx) { assert(idx < MAX_ARG); return Storage { idx << 2 }; ) + static Storage new_Local(unsigned idx) { assert(idx <= MAX_ARG); return Storage { (idx << 2) | 1 } }; + static Storage new_Static(::HIR::Path p) { + ::HIR::Path* ptr = new ::HIR::Path(::std::move(p)); + return Storage { static_cast(ptr) | 2; } + } + + bool is_Return() const { return val == (MAX_ARG << 2) /*&& (val & 3) == 0*/; } bool is_Argument() const { return val != (MAX_ARG << 2) && (val & 3) == 0; } - bool is_Return() const { return val == (MAX_ARG << 2); } - bool is_Local() const { return (val & 3) == 1; } - bool is_Static() const { return (val & 3) == 2; } + bool is_Local() const { return (val & 3) == 1; } + bool is_Static() const { return (val & 3) == 2; } + // No as_Return + unsigned as_Argument() const { assert(is_Argument()); return val >> 2; } + unsigned as_Local() const { assert(is_Local()); return val >> 2; } const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3u); } }; class Wrapper { uintptr_t val; public: - bool is_Deref() const { return (val & 3) == 0; } + static Wrapper new_Deref() { return Wrapper { 0 }; } + static Wrapepr new_Field (unsigned idx) { return Wrapper { (idx << 2) | 1 }; } + static Wrapepr new_Downcast(unsigned idx) { return Wrapper { (idx << 2) | 2 }; } + static Wrapepr new_Index (unsigned idx) { return Wrapper { (idx << 2) | 3 }; } + + bool is_Deref () const { return (val & 3) == 0; } // Stores the field index - bool is_Field() const { return (val & 3) == 1; } + bool is_Field () const { return (val & 3) == 1; } // Stores the variant index bool is_Downcast() const { return (val & 3) == 2; } // Stores a Local index - bool is_Index() const { return (val & 3) == 3; } + bool is_Index () const { return (val & 3) == 3; } + // no as_Deref() const unsigned as_Field() const { assert(is_Field()); return (val >> 2); } + const unsigned as_Downcast() const { assert(is_Downcast()); return (val >> 2); } + // TODO: Should this return a LValue? const unsigned as_Index() const { assert(is_Index()); return (val >> 2); } }; Storage m_root; ::std::vector m_wrappers; + static LValue new_Return() { return LValue { Storage::new_Return(), {} }; } + static LValue new_Argument(unsigned idx) { return LValue { Storage::new_Argument(idx), {} }; } + static LValue new_Local(unsigned idx) { return LValue { Storage::new_Local(idx), {} }; } + static LValue new_Static(::HIR::Path p) { return LValue { Storage::new_Static(::std::move(p)), {} }; } + + static LValue new_Deref(LValue lv) { lv.m_wrappers.push_back(Wrapper::new_Deref()); } + static LValue new_Field(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Field(idx)); } + static LValue new_Downcast(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Downcast(idx)); } + static LValue new_Index(LValue lv, unsigned local_idx) { lv.m_wrappers.push_back(Wrapper::new_Index(local_idx)); } + + LValue monomorphise(const MonomorphState& ms, unsigned local_offset=0); + //LValue monomorphise(const TransParams& ms, unsigned local_offset=0); LValue clone() const; class Ref @@ -159,11 +205,10 @@ TAGGED_UNION_EX(Constant, (), Int, ( }), (Bytes, ::std::vector< ::std::uint8_t>), // Byte string (StaticString, ::std::string), // String - // TODO: Should these ::HIR::Path structures be behind pointers? - // - HIR::Path is ~11 words long, without it MIR::Constant is 4 instead of 12 - // - MIR::Param is quite common, potential large space saving. - (Const, struct { ::HIR::Path p; }), // `const` - (ItemAddr, ::HIR::Path) // address of a value + // NOTE: These are behind pointers to save inline space (HIR::Path is ~11 + // words, compared to 4 for MIR::Constant without it) + (Const, struct { ::std::unique_ptr<::HIR::Path> p; }), // `const` + (ItemAddr, ::std::unique_ptr<::HIR::Path>) // address of a value ), (), (), ( friend ::std::ostream& operator<<(::std::ostream& os, const Constant& v); ::Ordering ord(const Constant& b) const; diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 7c284546..a45b1c05 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -1213,10 +1213,10 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool (Bytes, return ::MIR::Constant(ce);), (StaticString, return ::MIR::Constant(ce);), (Const, - return ::MIR::Constant::make_Const({ this->monomorph(ce.p) }); + return ::MIR::Constant::make_Const({ box$(this->monomorph(*ce.p)) }); ), (ItemAddr, - return ::MIR::Constant::make_ItemAddr(this->monomorph(ce)); + return ::MIR::Constant::make_ItemAddr(box$(this->monomorph(*ce))); ) ) throw ""; diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 08b4f2de..d238a523 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -5743,7 +5743,7 @@ namespace { (Const, // TODO: This should have been eliminated? ("MIR Cleanup" should have removed all inline Const references) ::HIR::TypeRef ty; - const auto& lit = get_literal_for_const(c.p, ty); + const auto& lit = get_literal_for_const(*c.p, ty); if(lit.is_Integer() || lit.is_Float()) { emit_literal(ty, lit, {}); @@ -5764,7 +5764,7 @@ namespace { } ), (ItemAddr, - TU_MATCHA( (c.m_data), (pe), + TU_MATCHA( (c->m_data), (pe), (Generic, if( pe.m_path.m_components.size() > 1 && m_crate.get_typeitem_by_path(sp, pe.m_path, false, true).is_Enum() ) ; @@ -5781,7 +5781,7 @@ namespace { } ), (UfcsUnknown, - MIR_BUG(*m_mir_res, "UfcsUnknown in trans " << c); + MIR_BUG(*m_mir_res, "UfcsUnknown in trans " << *c); ), (UfcsInherent, // TODO: If the target is a function, don't emit the & @@ -5792,7 +5792,7 @@ namespace { m_of << "&"; ) ) - m_of << Trans_Mangle(c); + m_of << Trans_Mangle(*c); ) ) } diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index 4867cf6f..51b8aac3 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -104,7 +104,7 @@ namespace os << " " << v.t; } break; TU_ARM(e, ItemAddr, v) { - os << "ADDROF " << v; + os << "ADDROF " << *v; } break; default: os << e; diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 00b938ff..934f40a2 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -1541,10 +1541,10 @@ void Trans_Enumerate_FillFrom_MIR_Constant(EnumState& state, const ::MIR::Consta (StaticString, ), // String (Const, // - Check if this constant has a value of Defer - Trans_Enumerate_FillFrom_Path(state, ce.p, pp); + Trans_Enumerate_FillFrom_Path(state, *ce.p, pp); ), (ItemAddr, - Trans_Enumerate_FillFrom_Path(state, ce, pp); + Trans_Enumerate_FillFrom_Path(state, *ce, pp); ) ) } diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index cf101443..50924e2f 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -71,15 +71,15 @@ namespace { ), (Const, return ::MIR::Constant::make_Const({ - params.monomorph(resolve, ce.p) + box$(params.monomorph(resolve, *ce.p)) }); ), (ItemAddr, - auto p = params.monomorph(resolve, ce); + auto p = params.monomorph(resolve, *ce); // TODO: If this is a pointer to a function on a trait object, replace with the address loaded from the vtable. // - Requires creating a new temporary for the vtable pointer. // - Also requires knowing what the receiver is. - return ::MIR::Constant( mv$(p) ); + return ::MIR::Constant( box$(p) ); ) ) throw ""; -- cgit v1.2.3 From 54ca77e36c85934706d1f1bd387228182ef09950 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 6 May 2019 21:07:46 +0800 Subject: Codegen C - Mark llvm.* shims as static --- src/trans/codegen_c.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index d238a523..fe8bf881 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -2274,7 +2274,9 @@ namespace { } else if( item.m_linkage.name.rfind("llvm.", 0) == 0 ) { + m_of << "static "; emit_function_header(p, item, params); + // TODO: Hand off to compiler-specific intrinsics m_of << " { abort(); }\n"; m_mir_res = nullptr; return ; -- cgit v1.2.3 From 64933e013b3b9cf11f479a07cbe674de4f56ab7b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 12 May 2019 22:15:53 +0800 Subject: Codegen C - (minor) Commenting and extra assertions --- src/trans/codegen_c.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index fe8bf881..b229db8b 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -615,9 +615,12 @@ namespace { emit_box_drop_glue( mv$(e.first), *e.second ); } - // TODO: Define this function in MIR. + // TODO: Support dynamic libraries too + // - No main, but has the rest. + // - Well... for cdylibs that's the case, for rdylibs it's not if( is_executable ) { + // TODO: Define this function in MIR? m_of << "int main(int argc, const char* argv[]) {\n"; auto c_start_path = m_resolve.m_crate.get_lang_item_path_opt("mrustc-start"); if( c_start_path == ::HIR::SimplePath() ) @@ -789,7 +792,7 @@ namespace { args.push_back("-g"); } args.push_back("-o"); - args.push_back(m_outfile_path.c_str()); + args.push_back(m_outfile_path .c_str()); args.push_back(m_outfile_path_c.c_str()); if( is_executable ) { @@ -5302,6 +5305,7 @@ namespace { MIR_BUG(*m_mir_res, "Constant with Defer literal and no cached monomorphisation - " << path); // TODO: Can do the consteval here? } + MIR_ASSERT(*m_mir_res, !it->second.is_Defer(), "get_literal_for_const - Cached literal was Defer - " << path); return it->second; } return hir_const.m_value_res; @@ -5349,7 +5353,7 @@ namespace { void assign_from_literal(::std::function emit_dst, const ::HIR::TypeRef& ty, const ::HIR::Literal& lit) { - //TRACE_FUNCTION_F("ty=" << ty << ", lit=" << lit); + TRACE_FUNCTION_F("ty=" << ty << ", lit=" << lit); Span sp; ::HIR::TypeRef tmp; auto monomorph_with = [&](const ::HIR::PathParams& pp, const ::HIR::TypeRef& ty)->const ::HIR::TypeRef& { -- cgit v1.2.3 From b48167dec0c1c05b463991a8db5a8db70a5ae604 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 19 May 2019 22:15:02 +0800 Subject: All - Switch to using interned (de-duplicated) RcString-s instead of std::string for paths/identifiers --- src/ast/ast.cpp | 26 ++-- src/ast/ast.hpp | 59 ++++---- src/ast/attrs.hpp | 10 +- src/ast/crate.cpp | 23 +-- src/ast/crate.hpp | 18 +-- src/ast/dump.cpp | 4 +- src/ast/expr.hpp | 24 +-- src/ast/generics.hpp | 6 +- src/ast/item.hpp | 4 +- src/ast/macro.hpp | 10 +- src/ast/path.cpp | 4 +- src/ast/path.hpp | 39 ++--- src/ast/pattern.cpp | 2 +- src/ast/pattern.hpp | 4 +- src/ast/types.cpp | 7 +- src/ast/types.hpp | 11 +- src/coretypes.hpp | 2 +- src/expand/asm.cpp | 4 +- src/expand/assert.cpp | 8 +- src/expand/cfg.cpp | 12 +- src/expand/concat.cpp | 4 +- src/expand/derive.cpp | 276 ++++++++++++++++++----------------- src/expand/env.cpp | 20 +-- src/expand/file_line.cpp | 14 +- src/expand/format_args.cpp | 63 ++++---- src/expand/include.cpp | 15 +- src/expand/macro_rules.cpp | 15 +- src/expand/mod.cpp | 19 ++- src/expand/proc_macro.cpp | 16 +- src/expand/proc_macro.hpp | 8 +- src/expand/rustc_diagnostics.cpp | 14 +- src/expand/stringify.cpp | 2 +- src/expand/test.cpp | 2 +- src/expand/test_harness.cpp | 4 +- src/hir/crate_post_load.cpp | 2 +- src/hir/deserialise.cpp | 139 +++++++++++++----- src/hir/expr.hpp | 26 ++-- src/hir/from_ast.cpp | 55 +++---- src/hir/from_ast.hpp | 2 +- src/hir/from_ast_expr.cpp | 8 +- src/hir/generic_params.cpp | 2 +- src/hir/generic_params.hpp | 16 +- src/hir/hir.cpp | 2 +- src/hir/hir.hpp | 52 +++---- src/hir/hir_ops.cpp | 14 +- src/hir/item_path.hpp | 11 +- src/hir/main_bindings.hpp | 2 +- src/hir/path.cpp | 6 +- src/hir/path.hpp | 26 ++-- src/hir/pattern.cpp | 5 +- src/hir/pattern.hpp | 8 +- src/hir/serialise.cpp | 51 ++++++- src/hir/serialise_lowlevel.cpp | 56 ++++++- src/hir/serialise_lowlevel.hpp | 29 +++- src/hir/type.hpp | 8 +- src/hir_conv/constant_evaluation.cpp | 2 +- src/hir_expand/closures.cpp | 26 ++-- src/hir_expand/vtable.cpp | 11 +- src/hir_typeck/expr_check.cpp | 4 +- src/hir_typeck/expr_cs.cpp | 19 +-- src/hir_typeck/helpers.cpp | 49 +++---- src/hir_typeck/helpers.hpp | 14 +- src/hir_typeck/impl_ref.hpp | 8 +- src/hir_typeck/outer.cpp | 5 +- src/hir_typeck/static.cpp | 22 +-- src/hir_typeck/static.hpp | 4 +- src/include/ident.hpp | 12 +- src/include/rc_string.hpp | 81 +++++++--- src/include/synext_macro.hpp | 5 +- src/macro_rules/eval.cpp | 14 +- src/macro_rules/macro_rules.hpp | 12 +- src/macro_rules/parse.cpp | 14 +- src/main.cpp | 4 +- src/mir/check.cpp | 7 +- src/mir/cleanup.cpp | 6 +- src/mir/from_hir.cpp | 10 +- src/mir/mir.hpp | 4 +- src/parse/common.hpp | 2 +- src/parse/expr.cpp | 44 +++--- src/parse/lex.cpp | 14 +- src/parse/paths.cpp | 10 +- src/parse/pattern.cpp | 12 +- src/parse/root.cpp | 139 +++++++++--------- src/parse/token.cpp | 13 +- src/parse/token.hpp | 4 + src/parse/tokenstream.cpp | 4 +- src/parse/types.cpp | 9 +- src/rc_string.cpp | 113 ++++++++++++-- src/resolve/absolute.cpp | 26 ++-- src/resolve/index.cpp | 10 +- src/resolve/use.cpp | 19 ++- src/trans/auto_impls.cpp | 2 +- src/trans/codegen_c.cpp | 11 +- src/trans/codegen_mmir.cpp | 7 +- src/trans/enumerate.cpp | 10 +- src/trans/mangling.cpp | 15 +- 96 files changed, 1202 insertions(+), 864 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 03257fc6..f1a68680 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -107,16 +107,16 @@ Function Function::clone() const return rv; } -void Trait::add_type(::std::string name, AttributeList attrs, TypeRef type) { +void Trait::add_type(RcString name, AttributeList attrs, TypeRef type) { m_items.push_back( Named(mv$(name), Item::make_Type({TypeAlias(GenericParams(), mv$(type))}), true) ); m_items.back().data.attrs = mv$(attrs); } -void Trait::add_function(::std::string name, AttributeList attrs, Function fcn) { +void Trait::add_function(RcString name, AttributeList attrs, Function fcn) { DEBUG("trait fn " << name); m_items.push_back( Named(mv$(name), Item::make_Function({mv$(fcn)}), true) ); m_items.back().data.attrs = mv$(attrs); } -void Trait::add_static(::std::string name, AttributeList attrs, Static v) { +void Trait::add_static(RcString name, AttributeList attrs, Static v) { m_items.push_back( Named(mv$(name), Item::make_Static({mv$(v)}), true) ); m_items.back().data.attrs = mv$(attrs); } @@ -126,7 +126,7 @@ void Trait::set_is_marker() { bool Trait::is_marker() const { return m_is_marker; } -bool Trait::has_named_item(const ::std::string& name, bool& out_is_fcn) const +bool Trait::has_named_item(const RcString& name, bool& out_is_fcn) const { for( const auto& i : m_items ) { @@ -208,16 +208,16 @@ Union Union::clone() const return os << "impl<" << impl.m_params << "> " << impl.m_trait.ent << " for " << impl.m_type << ""; } -void Impl::add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn) +void Impl::add_function(bool is_public, bool is_specialisable, RcString name, Function fcn) { DEBUG("impl fn " << name); m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Function(mv$(fcn)) ) } ); } -void Impl::add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type) +void Impl::add_type(bool is_public, bool is_specialisable, RcString name, TypeRef type) { m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Type(TypeAlias(GenericParams(), mv$(type))) ) } ); } -void Impl::add_static(bool is_public, bool is_specialisable, ::std::string name, Static v) +void Impl::add_static(bool is_public, bool is_specialisable, RcString name, Static v) { m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Static(mv$(v)) ) } ); } @@ -225,7 +225,7 @@ void Impl::add_macro_invocation(MacroInvocation item) { m_items.push_back( ImplItem { false, false, "", box$( Item::make_MacroInv(mv$(item)) ) } ); } -bool Impl::has_named_item(const ::std::string& name) const +bool Impl::has_named_item(const RcString& name) const { for( const auto& it : this->items() ) { @@ -271,7 +271,7 @@ ExternBlock ExternBlock::clone() const } ::std::shared_ptr Module::add_anon() { - auto rv = ::std::shared_ptr( new Module(m_my_path + FMT("#" << m_anon_modules.size())) ); + auto rv = ::std::shared_ptr( new Module(m_my_path + RcString::new_interned(FMT("#" << m_anon_modules.size()))) ); DEBUG("New anon " << rv->m_my_path); rv->m_file_info = m_file_info; @@ -289,20 +289,20 @@ void Module::add_item( Named named_item ) { DEBUG(m_my_path << "::" << i.name << " = " << i.data.tag_str() << ", attrs = " << i.data.attrs); } } -void Module::add_item(bool is_pub, ::std::string name, Item it, AttributeList attrs) { +void Module::add_item(bool is_pub, RcString name, Item it, AttributeList attrs) { it.attrs = mv$(attrs); add_item( Named( mv$(name), mv$(it), is_pub ) ); } -void Module::add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, AttributeList attrs) { +void Module::add_ext_crate(bool is_public, RcString ext_name, RcString imp_name, AttributeList attrs) { this->add_item( is_public, imp_name, Item::make_Crate({mv$(ext_name)}), mv$(attrs) ); } void Module::add_macro_invocation(MacroInvocation item) { this->add_item( false, "", Item( mv$(item) ), ::AST::AttributeList {} ); } -void Module::add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro) { +void Module::add_macro(bool is_exported, RcString name, MacroRulesPtr macro) { m_macros.push_back( Named( mv$(name), mv$(macro), is_exported ) ); } -void Module::add_macro_import(::std::string name, const MacroRules& mr) { +void Module::add_macro_import(RcString name, const MacroRules& mr) { m_macro_import_res.push_back( Named( mv$(name), &mr, false ) ); } diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index f6f97fce..bfef9cff 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -58,12 +58,12 @@ struct StructItem { ::AST::AttributeList m_attrs; bool m_is_public; - ::std::string m_name; + RcString m_name; TypeRef m_type; //StructItem() {} - StructItem(::AST::AttributeList attrs, bool is_pub, ::std::string name, TypeRef ty): + StructItem(::AST::AttributeList attrs, bool is_pub, RcString name, TypeRef ty): m_attrs( mv$(attrs) ), m_is_public(is_pub), m_name( mv$(name) ), @@ -222,16 +222,16 @@ public: const NamedList& items() const { return m_items; } NamedList& items() { return m_items; } - void add_type(::std::string name, AttributeList attrs, TypeRef type); - void add_function(::std::string name, AttributeList attrs, Function fcn); - void add_static(::std::string name, AttributeList attrs, Static v); + void add_type(RcString name, AttributeList attrs, TypeRef type); + void add_function(RcString name, AttributeList attrs, Function fcn); + void add_static(RcString name, AttributeList attrs, Static v); void set_is_marker(); bool is_marker() const; void set_is_unsafe() { m_is_unsafe = true; } bool is_unsafe() const { return m_is_unsafe; } - bool has_named_item(const ::std::string& name, bool& out_is_fcn) const; + bool has_named_item(const RcString& name, bool& out_is_fcn) const; Trait clone() const; }; @@ -257,28 +257,28 @@ TAGGED_UNION_EX(EnumVariantData, (), Value, struct EnumVariant { AttributeList m_attrs; - ::std::string m_name; + RcString m_name; EnumVariantData m_data; EnumVariant() { } - EnumVariant(AttributeList attrs, ::std::string name, Expr&& value): + EnumVariant(AttributeList attrs, RcString name, Expr&& value): m_attrs( mv$(attrs) ), m_name( mv$(name) ), m_data( EnumVariantData::make_Value({mv$(value)}) ) { } - EnumVariant(AttributeList attrs, ::std::string name, ::std::vector sub_types): + EnumVariant(AttributeList attrs, RcString name, ::std::vector sub_types): m_attrs( mv$(attrs) ), m_name( ::std::move(name) ), m_data( EnumVariantData::make_Tuple( {mv$(sub_types)} ) ) { } - EnumVariant(AttributeList attrs, ::std::string name, ::std::vector fields): + EnumVariant(AttributeList attrs, RcString name, ::std::vector fields): m_attrs( mv$(attrs) ), m_name( ::std::move(name) ), m_data( EnumVariantData::make_Struct( {mv$(fields)} ) ) @@ -425,7 +425,7 @@ public: struct ImplItem { bool is_pub; // Ignored for trait impls bool is_specialisable; - ::std::string name; + RcString name; ::std::unique_ptr data; }; @@ -445,9 +445,9 @@ public: {} Impl& operator=(Impl&&) = default; - void add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn); - void add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type); - void add_static(bool is_public, bool is_specialisable, ::std::string name, Static v); + void add_function(bool is_public, bool is_specialisable, RcString name, Function fcn); + void add_type(bool is_public, bool is_specialisable, RcString name, TypeRef type); + void add_static(bool is_public, bool is_specialisable, RcString name, Static v); void add_macro_invocation( MacroInvocation inv ); const ImplDef& def() const { return m_def; } @@ -455,7 +455,7 @@ public: const ::std::vector& items() const { return m_items; } ::std::vector& items() { return m_items; } - bool has_named_item(const ::std::string& name) const; + bool has_named_item(const RcString& name) const; friend ::std::ostream& operator<<(::std::ostream& os, const Impl& impl); @@ -468,7 +468,7 @@ struct UseItem struct Ent { Span sp; // Span covering just the path (final component) ::AST::Path path; - ::std::string name; // If "", this is a glob/wildcard use + RcString name; // If "", this is a glob/wildcard use }; ::std::vector entries; @@ -533,23 +533,23 @@ public: }; // TODO: Document difference between namespace and Type - ::std::unordered_map< ::std::string, IndexEnt > m_namespace_items; - ::std::unordered_map< ::std::string, IndexEnt > m_type_items; - ::std::unordered_map< ::std::string, IndexEnt > m_value_items; + ::std::unordered_map< RcString, IndexEnt > m_namespace_items; + ::std::unordered_map< RcString, IndexEnt > m_type_items; + ::std::unordered_map< RcString, IndexEnt > m_value_items; // List of macros imported from other modules (via #[macro_use], includes proc macros) // - First value is an absolute path to the macro (including crate name) struct MacroImport { bool is_pub; - ::std::string name; // Can be different, if `use foo as bar` is used - ::std::vector<::std::string> path; // includes the crate name + RcString name; // Can be different, if `use foo as bar` is used + ::std::vector path; // includes the crate name const MacroRules* macro_ptr; }; ::std::vector m_macro_imports; struct Import { bool is_pub; - ::std::string name; + RcString name; ::AST::Path path; // If `name` is "", then this is a module/enum to glob }; ::std::vector m_item_imports; @@ -562,19 +562,19 @@ public: } bool is_anon() const { - return m_my_path.nodes().size() > 0 && m_my_path.nodes().back().name()[0] == '#'; + return m_my_path.nodes().size() > 0 && m_my_path.nodes().back().name().c_str()[0] == '#'; } /// Create an anon module (for use inside expressions) ::std::shared_ptr add_anon(); void add_item(Named item); - void add_item(bool is_pub, ::std::string name, Item it, AttributeList attrs); - void add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, AttributeList attrs); + void add_item(bool is_pub, RcString name, Item it, AttributeList attrs); + void add_ext_crate(bool is_public, RcString ext_name, RcString imp_name, AttributeList attrs); void add_macro_invocation(MacroInvocation item); - void add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro); - void add_macro_import(::std::string name, const MacroRules& mr); + void add_macro(bool is_exported, RcString name, MacroRulesPtr macro); + void add_macro_import(RcString name, const MacroRules& mr); @@ -590,9 +590,6 @@ public: NamedList& macros() { return m_macros; } const NamedList& macros() const { return m_macros; } const ::std::vector > macro_imports_res() const { return m_macro_import_res; } - -private: - void resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name); }; TAGGED_UNION_EX(Item, (), None, @@ -610,7 +607,7 @@ TAGGED_UNION_EX(Item, (), None, (Macro, MacroRulesPtr), (Module, Module), (Crate, struct { - ::std::string name; + RcString name; }), (Type, TypeAlias), diff --git a/src/ast/attrs.hpp b/src/ast/attrs.hpp index a15b4175..04328130 100644 --- a/src/ast/attrs.hpp +++ b/src/ast/attrs.hpp @@ -74,24 +74,24 @@ TAGGED_UNION(AttributeData, None, class Attribute { Span m_span; - ::std::string m_name; + RcString m_name; AttributeData m_data; mutable bool m_is_used; // TODO: Parse as a TT then expand? public: - Attribute(Span sp, ::std::string name): + Attribute(Span sp, RcString name): m_span(::std::move(sp)), m_name(name), m_data( AttributeData::make_None({}) ) { } - Attribute(Span sp, ::std::string name, ::std::string str_val): + Attribute(Span sp, RcString name, ::std::string str_val): m_span(::std::move(sp)), m_name(name), m_data( AttributeData::make_String({mv$(str_val)}) ) { } - Attribute(Span sp, ::std::string name, ::std::vector items): + Attribute(Span sp, RcString name, ::std::vector items): m_span(::std::move(sp)), m_name(name), m_data( AttributeData::make_List({mv$(items)}) ) @@ -123,7 +123,7 @@ public: bool is_used() const { return m_is_used; } const Span& span() const { return m_span; } - const ::std::string& name() const { return m_name; } + const RcString& name() const { return m_name; } const AttributeData& data() const { return m_data; } // Legacy accessors/checkers diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp index 5717cbdb..c9856781 100644 --- a/src/ast/crate.cpp +++ b/src/ast/crate.cpp @@ -64,7 +64,7 @@ void Crate::load_externs() TU_IFLET(AST::Item, it.data, Crate, c, if( check_item_cfg(it.data.attrs) ) { - c.name = load_extern_crate( it.data.span, c.name ); + c.name = load_extern_crate( it.data.span, c.name.c_str() ); } ) } @@ -109,12 +109,12 @@ void Crate::load_externs() } // TODO: Handle disambiguating crates with the same name (e.g. libc in std and crates.io libc) // - Crates recorded in rlibs should specify a hash/tag that's passed in to this function. -::std::string Crate::load_extern_crate(Span sp, const ::std::string& name, const ::std::string& basename/*=""*/) +RcString Crate::load_extern_crate(Span sp, const RcString& name, const ::std::string& basename/*=""*/) { DEBUG("Loading crate '" << name << "'"); ::std::string path; - auto it = g_crate_overrides.find(name); + auto it = g_crate_overrides.find(name.c_str()); if(basename == "" && it != g_crate_overrides.end()) { path = it->second; @@ -140,18 +140,19 @@ void Crate::load_externs() else { ::std::vector<::std::string> paths; - auto name_prefix = "lib"+name+"-"; + auto direct_filename = FMT("lib" << name.c_str() << ".hir"); + auto name_prefix = FMT("lib" << name.c_str() << "-"); // Search a list of load paths for the crate for(const auto& p : g_crate_load_dirs) { - path = p + "/lib" + name + ".hir"; - // TODO: Search for `p+"/lib"+name+"-*.hir" (which would match e.g. libnum-0.11.hir) + path = p + "/" + direct_filename; if( ::std::ifstream(path).good() ) { paths.push_back(path); } path = ""; + // Search for `p+"/lib"+name+"-*.hir" (which would match e.g. libnum-0.11.hir) auto dp = opendir(p.c_str()); if( !dp ) { continue ; @@ -187,7 +188,7 @@ void Crate::load_externs() // NOTE: Creating `ExternCrate` loads the crate from the specified path auto ec = ExternCrate { name, path }; auto real_name = ec.m_hir->m_crate_name; - assert(!real_name.empty()); + assert(real_name != ""); auto res = m_extern_crates.insert(::std::make_pair( real_name, mv$(ec) )); if( !res.second ) { // Crate already loaded? @@ -214,26 +215,26 @@ void Crate::load_externs() return real_name; } -ExternCrate::ExternCrate(const ::std::string& name, const ::std::string& path): +ExternCrate::ExternCrate(const RcString& name, const ::std::string& path): m_name(name), m_short_name(name), m_filename(path) { TRACE_FUNCTION_F("name=" << name << ", path='" << path << "'"); - m_hir = HIR_Deserialise(path, name); + m_hir = HIR_Deserialise(path); m_hir->post_load_update(name); m_name = m_hir->m_crate_name; } -void ExternCrate::with_all_macros(::std::function cb) const +void ExternCrate::with_all_macros(::std::function cb) const { for(const auto& m : m_hir->m_exported_macros) { cb(m.first, *m.second); } } -const MacroRules* ExternCrate::find_macro_rules(const ::std::string& name) const +const MacroRules* ExternCrate::find_macro_rules(const RcString& name) const { auto i = m_hir->m_exported_macros.find(name); if(i != m_hir->m_exported_macros.end()) diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp index 79cb9cd7..c4e1d5df 100644 --- a/src/ast/crate.hpp +++ b/src/ast/crate.hpp @@ -36,7 +36,7 @@ public: class ProcMacroDef { public: - ::std::string name; + RcString name; ::AST::Path path; ::std::vector<::std::string> attributes; }; @@ -49,9 +49,9 @@ public: ::std::map< ::std::string, ::AST::Path> m_lang_items; public: Module m_root_module; - ::std::map< ::std::string, ExternCrate> m_extern_crates; + ::std::map< RcString, ExternCrate> m_extern_crates; // Mapping filled by searching for (?visible) macros with is_pub=true - ::std::map< ::std::string, const MacroRules*> m_exported_macros; + ::std::map< RcString, const MacroRules*> m_exported_macros; // List of tests (populated in expand if --test is passed) bool m_test_harness = false; @@ -91,27 +91,27 @@ public: /// Load the named crate and returns the crate's unique name /// If the parameter `file` is non-empty, only that particular filename will be loaded (from any of the search paths) - ::std::string load_extern_crate(Span sp, const ::std::string& name, const ::std::string& file=""); + RcString load_extern_crate(Span sp, const RcString& name, const ::std::string& file=""); }; /// Representation of an imported crate class ExternCrate { public: - ::std::string m_name; - ::std::string m_short_name; + RcString m_name; + RcString m_short_name; ::std::string m_filename; ::HIR::CratePtr m_hir; - ExternCrate(const ::std::string& name, const ::std::string& path); + ExternCrate(const RcString& name, const ::std::string& path); ExternCrate(ExternCrate&&) = default; ExternCrate& operator=(ExternCrate&&) = default; ExternCrate(const ExternCrate&) = delete; ExternCrate& operator=(const ExternCrate& ) = delete; - void with_all_macros(::std::function cb) const; - const MacroRules* find_macro_rules(const ::std::string& name) const; + void with_all_macros(::std::function cb) const; + const MacroRules* find_macro_rules(const RcString& name) const; }; extern ::std::vector<::std::string> g_crate_load_dirs; diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp index 00848fb5..9fb34099 100644 --- a/src/ast/dump.cpp +++ b/src/ast/dump.cpp @@ -36,7 +36,7 @@ public: void handle_enum(const AST::Enum& s); void handle_trait(const AST::Trait& s); - void handle_function(bool is_pub, const ::std::string& name, const AST::Function& f); + void handle_function(bool is_pub, const RcString& name, const AST::Function& f); virtual bool is_const() const override { return true; } virtual void visit(AST::ExprNode_Block& n) override { @@ -1133,7 +1133,7 @@ void RustPrinter::handle_trait(const AST::Trait& s) m_os << "\n"; } -void RustPrinter::handle_function(bool is_pub, const ::std::string& name, const AST::Function& f) +void RustPrinter::handle_function(bool is_pub, const RcString& name, const AST::Function& f) { m_os << indent(); m_os << (is_pub ? "pub " : ""); diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 7675b29a..a9c82efa 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -90,11 +90,11 @@ struct ExprNode_Try: struct ExprNode_Macro: public ExprNode { - ::std::string m_name; - ::std::string m_ident; + RcString m_name; + RcString m_ident; ::TokenTree m_tokens; - ExprNode_Macro(::std::string name, ::std::string ident, ::TokenTree&& tokens): + ExprNode_Macro(RcString name, RcString ident, ::TokenTree&& tokens): m_name(name), m_ident(ident), m_tokens( move(tokens) ) @@ -140,10 +140,10 @@ struct ExprNode_Flow: CONTINUE, BREAK, } m_type; - ::std::string m_target; + RcString m_target; unique_ptr m_value; - ExprNode_Flow(Type type, ::std::string target, unique_ptr&& value): + ExprNode_Flow(Type type, RcString target, unique_ptr&& value): m_type(type), m_target( move(target) ), m_value( move(value) ) @@ -245,24 +245,24 @@ struct ExprNode_Loop: WHILELET, FOR, } m_type; - ::std::string m_label; + RcString m_label; AST::Pattern m_pattern; unique_ptr m_cond; // if NULL, loop is a 'loop' unique_ptr m_code; ExprNode_Loop(): m_type(LOOP) {} - ExprNode_Loop(::std::string label, unique_ptr code): + ExprNode_Loop(RcString label, unique_ptr code): m_type(LOOP), m_label( ::std::move(label) ), m_code( ::std::move(code) ) {} - ExprNode_Loop(::std::string label, unique_ptr cond, unique_ptr code): + ExprNode_Loop(RcString label, unique_ptr cond, unique_ptr code): m_type(WHILE), m_label( ::std::move(label) ), m_cond( ::std::move(cond) ), m_code( ::std::move(code) ) {} - ExprNode_Loop(::std::string label, Type type, AST::Pattern pattern, unique_ptr val, unique_ptr code): + ExprNode_Loop(RcString label, Type type, AST::Pattern pattern, unique_ptr val, unique_ptr code): m_type(type), m_label( ::std::move(label) ), m_pattern( ::std::move(pattern) ), @@ -430,7 +430,7 @@ struct ExprNode_StructLiteral: { struct Ent { AttributeList attrs; - ::std::string name; + RcString name; unique_ptr value; }; typedef ::std::vector t_values; @@ -493,9 +493,9 @@ struct ExprNode_Field: public ExprNode { ::std::unique_ptr m_obj; - ::std::string m_name; + RcString m_name; - ExprNode_Field(::std::unique_ptr&& obj, ::std::string name): + ExprNode_Field(::std::unique_ptr&& obj, RcString name): m_obj( ::std::move(obj) ), m_name( ::std::move(name) ) { diff --git a/src/ast/generics.hpp b/src/ast/generics.hpp index c222044c..bfc7080b 100644 --- a/src/ast/generics.hpp +++ b/src/ast/generics.hpp @@ -17,7 +17,7 @@ class TypeParam ::AST::AttributeList m_attrs; Span m_span; // TODO: use an Ident? - ::std::string m_name; + RcString m_name; ::TypeRef m_default; public: TypeParam(TypeParam&& x) = default; @@ -30,7 +30,7 @@ public: { } - TypeParam(Span sp, ::AST::AttributeList attrs, ::std::string name): + TypeParam(Span sp, ::AST::AttributeList attrs, RcString name): m_attrs( ::std::move(attrs) ), m_span( ::std::move(sp) ), m_name( ::std::move(name) ), @@ -44,7 +44,7 @@ public: const ::AST::AttributeList& attrs() const { return m_attrs; } const Span& span() const { return m_span; } - const ::std::string& name() const { return m_name; } + const RcString& name() const { return m_name; } const TypeRef& get_default() const { return m_default; } TypeRef& get_default() { return m_default; } diff --git a/src/ast/item.hpp b/src/ast/item.hpp index 0074ce9a..ee83a8db 100644 --- a/src/ast/item.hpp +++ b/src/ast/item.hpp @@ -15,7 +15,7 @@ namespace AST { template struct Named { - ::std::string name; + RcString name; T data; bool is_pub; @@ -25,7 +25,7 @@ struct Named Named(Named&&) = default; Named(const Named&) = default; Named& operator=(Named&&) = default; - Named(::std::string name, T data, bool is_pub): + Named(RcString name, T data, bool is_pub): name( ::std::move(name) ), data( ::std::move(data) ), is_pub( is_pub ) diff --git a/src/ast/macro.hpp b/src/ast/macro.hpp index 5b2223ce..e94de8f1 100644 --- a/src/ast/macro.hpp +++ b/src/ast/macro.hpp @@ -18,8 +18,8 @@ class MacroInvocation { Span m_span; - ::std::string m_macro_name; - ::std::string m_ident; + RcString m_macro_name; + RcString m_ident; TokenTree m_input; public: MacroInvocation(MacroInvocation&&) = default; @@ -31,7 +31,7 @@ public: { } - MacroInvocation(Span span, ::std::string macro, ::std::string ident, TokenTree input): + MacroInvocation(Span span, RcString macro, RcString ident, TokenTree input): m_span( mv$(span) ), m_macro_name( mv$(macro) ), m_ident( mv$(ident) ), @@ -48,9 +48,9 @@ public: } const Span& span() const { return m_span; } - const ::std::string& name() const { return m_macro_name; } + const RcString& name() const { return m_macro_name; } - const ::std::string& input_ident() const { return m_ident; } + const RcString& input_ident() const { return m_ident; } const TokenTree& input_tt() const { return m_input; } TokenTree& input_tt() { return m_input; } diff --git a/src/ast/path.cpp b/src/ast/path.cpp index d156f465..830e7372 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -148,7 +148,7 @@ Ordering PathParams::ord(const PathParams& x) const } // --- AST::PathNode -PathNode::PathNode(::std::string name, PathParams args): +PathNode::PathNode(RcString name, PathParams args): m_name( mv$(name) ), m_params( mv$(args) ) { @@ -256,7 +256,7 @@ void Path::bind_variable(unsigned int slot) { m_bindings.value = PathBinding_Value::make_Variable({slot}); } -void Path::bind_enum_var(const Enum& ent, const ::std::string& name) +void Path::bind_enum_var(const Enum& ent, const RcString& name) { auto it = ::std::find_if(ent.variants().begin(), ent.variants().end(), [&](const auto& x) { return x.m_name == name; }); if( it == ent.variants().end() ) diff --git a/src/ast/path.hpp b/src/ast/path.hpp index faa1ffe6..c611c819 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -127,15 +127,15 @@ TAGGED_UNION_EX(PathBinding_Macro, (), Unbound, ( }), (ProcMacroDerive, struct { const ExternCrate* crate_; - ::std::string mac_name; + RcString mac_name; }), (ProcMacroAttribute, struct { const ExternCrate* crate_; - ::std::string mac_name; + RcString mac_name; }), (ProcMacro, struct { const ExternCrate* crate_; - ::std::string mac_name; + RcString mac_name; }), (MacroRules, struct { const ExternCrate* crate_; // Can be NULL @@ -157,12 +157,12 @@ struct PathParams { ::std::vector< LifetimeRef > m_lifetimes; ::std::vector< TypeRef > m_types; - ::std::vector< ::std::pair< ::std::string, TypeRef> > m_assoc; + ::std::vector< ::std::pair< RcString, TypeRef> > m_assoc; PathParams(PathParams&& x) = default; PathParams(const PathParams& x); PathParams() {} - PathParams(::std::vector lfts, ::std::vector tys, ::std::vector<::std::pair<::std::string,TypeRef>> a): + PathParams(::std::vector lfts, ::std::vector tys, ::std::vector<::std::pair> a): m_lifetimes(mv$(lfts)), m_types(mv$(tys)), m_assoc(mv$(a)) @@ -182,12 +182,12 @@ struct PathParams class PathNode { - ::std::string m_name; + RcString m_name; PathParams m_params; public: PathNode() {} - PathNode(::std::string name, PathParams args = {}); - const ::std::string& name() const { return m_name; } + PathNode(RcString name, PathParams args = {}); + const RcString& name() const { return m_name; } const ::AST::PathParams& args() const { return m_params; } ::AST::PathParams& args() { return m_params; } @@ -205,7 +205,7 @@ public: TAGGED_UNION(Class, Invalid, (Invalid, struct {}), (Local, struct { // Variable / Type param (resolved) - ::std::string name; + RcString name; } ), (Relative, struct { // General relative Ident::Hygiene hygiene; @@ -219,7 +219,7 @@ public: ::std::vector nodes; } ), (Absolute, struct { // Absolute - ::std::string crate; + RcString crate; ::std::vector nodes; } ), (UFCS, struct { // Type-relative @@ -267,7 +267,7 @@ public: Path& operator=(const AST::Path&) = delete; // ABSOLUTE - Path(::std::string crate, ::std::vector nodes): + Path(RcString crate, ::std::vector nodes): m_class( Class::make_Absolute({ mv$(crate), mv$(nodes)}) ) {} @@ -278,10 +278,10 @@ public: // VARIABLE struct TagLocal {}; - Path(TagLocal, ::std::string name): + Path(TagLocal, RcString name): m_class( Class::make_Local({ mv$(name) }) ) {} - Path(::std::string name): + Path(RcString name): m_class( Class::make_Local({ mv$(name) }) ) {} @@ -301,14 +301,6 @@ public: m_class( Class::make_Super({ count, mv$(nodes) }) ) {} - //void set_crate(::std::string crate) { - // if( m_crate == "" ) { - // m_crate = crate; - // DEBUG("crate set to " << m_crate); - // } - //} - - Class::Tag class_tag() const { return m_class.tag(); } @@ -318,7 +310,7 @@ public: tmp.nodes().push_back( mv$(pn) ); return tmp; } - Path operator+(const ::std::string& s) const { + Path operator+(const RcString& s) const { Path tmp = Path(*this); tmp.append(PathNode(s, {})); return tmp; @@ -370,7 +362,6 @@ public: ) throw ::std::runtime_error("Path::nodes() fell off"); } - //const ::std::string& crate() const { return m_crate; } bool is_parent_of(const Path& x) const; @@ -407,7 +398,7 @@ private: void check_param_counts(const GenericParams& params, bool expect_params, PathNode& node); public: - void bind_enum_var(const Enum& ent, const ::std::string& name); + void bind_enum_var(const Enum& ent, const RcString& name); void bind_function(const Function& ent) { m_bindings.value = PathBinding_Value::make_Function({&ent}); } diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp index 72087d95..e13662fe 100644 --- a/src/ast/pattern.cpp +++ b/src/ast/pattern.cpp @@ -223,7 +223,7 @@ AST::Pattern AST::Pattern::clone() const rv.m_data = Data::make_StructTuple({ ::AST::Path(e.path), H::clone_tup(e.tup_pat) }); ), (Struct, - ::std::vector< ::std::pair< ::std::string, Pattern> > sps; + ::std::vector< ::std::pair< RcString, Pattern> > sps; for(const auto& sp : e.sub_patterns) sps.push_back( ::std::make_pair(sp.first, sp.second.clone()) ); rv.m_data = Data::make_Struct({ ::AST::Path(e.path), mv$(sps) }); diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index 40cfa927..81c1126a 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -88,7 +88,7 @@ public: (Value, struct { Value start; Value end; } ), (Tuple, TuplePat ), (StructTuple, struct { Path path; TuplePat tup_pat; } ), - (Struct, struct { Path path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; bool is_exhaustive; } ), + (Struct, struct { Path path; ::std::vector< ::std::pair< RcString, Pattern> > sub_patterns; bool is_exhaustive; } ), (Slice, struct { ::std::vector sub_pats; }), (SplitSlice, struct { ::std::vector leading; PatternBinding extra_bind; ::std::vector trailing; } ) ); @@ -171,7 +171,7 @@ public: {} struct TagStruct {}; - Pattern(TagStruct, Span sp, Path path, ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns, bool is_exhaustive): + Pattern(TagStruct, Span sp, Path path, ::std::vector< ::std::pair< RcString,Pattern> > sub_patterns, bool is_exhaustive): m_span( mv$(sp) ), m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns), is_exhaustive } ) ) {} diff --git a/src/ast/types.cpp b/src/ast/types.cpp index f9103b37..496cf694 100644 --- a/src/ast/types.cpp +++ b/src/ast/types.cpp @@ -40,13 +40,14 @@ static const struct { {"usize", CORETYPE_UINT}, }; -enum eCoreType coretype_fromstring(const ::std::string& name) +enum eCoreType coretype_fromstring(const char* name) { for(unsigned int i = 0; i < sizeof(CORETYPES)/sizeof(CORETYPES[0]); i ++) { - if( name < CORETYPES[i].name ) + int cmp = strcmp(name, CORETYPES[i].name); + if( cmp < 0 ) break; - if( name == CORETYPES[i].name ) + if( cmp == 0 ) return CORETYPES[i].type; } return CORETYPE_INVAL; diff --git a/src/ast/types.hpp b/src/ast/types.hpp index 0b0f205e..15cb1383 100644 --- a/src/ast/types.hpp +++ b/src/ast/types.hpp @@ -73,6 +73,7 @@ namespace AST { bool is_infer() const { return m_binding == BINDING_INFER; } const Ident& name() const { return m_name; } + uint16_t binding() const { return m_binding; } Ordering ord(const LifetimeRef& x) const { return ::ord(m_name.name, x.m_name.name); } bool operator==(const LifetimeRef& x) const { return ord(x) == OrdEqual; } bool operator!=(const LifetimeRef& x) const { return ord(x) != OrdEqual; } @@ -97,7 +98,7 @@ public: struct TypeArgRef { - ::std::string name; + RcString name; unsigned int level; const AST::GenericParams* params; }; @@ -165,7 +166,7 @@ TAGGED_UNION(TypeData, None, ::std::shared_ptr size; }), (Generic, struct { - ::std::string name; + RcString name; unsigned int index; }), (Path, struct { @@ -276,11 +277,11 @@ public: {} struct TagArg {}; - TypeRef(TagArg, Span sp, ::std::string name, unsigned int binding = ~0u): + TypeRef(TagArg, Span sp, RcString name, unsigned int binding = ~0u): m_span( mv$(sp) ), m_data(TypeData::make_Generic({ name, binding })) {} - TypeRef(Span sp, ::std::string name, unsigned int binding = ~0u): + TypeRef(Span sp, RcString name, unsigned int binding = ~0u): TypeRef(TagArg(), mv$(sp), mv$(name), binding) {} @@ -314,7 +315,7 @@ public: AST::Path& path() { return m_data.as_Path().path; } bool is_type_param() const { return m_data.is_Generic(); } - const ::std::string& type_param() const { return m_data.as_Generic().name; } + const RcString& type_param() const { return m_data.as_Generic().name; } bool is_reference() const { return m_data.is_Borrow(); } bool is_pointer() const { return m_data.is_Pointer(); } diff --git a/src/coretypes.hpp b/src/coretypes.hpp index 7665f5ba..692473e5 100644 --- a/src/coretypes.hpp +++ b/src/coretypes.hpp @@ -24,7 +24,7 @@ enum eCoreType CORETYPE_F64, }; -extern enum eCoreType coretype_fromstring(const ::std::string& name); +extern enum eCoreType coretype_fromstring(const char* name); extern const char* coretype_name(const eCoreType ct); #endif // CORETYPES_HPP_INCLUDED diff --git a/src/expand/asm.cpp b/src/expand/asm.cpp index d895c32d..f8b3984d 100644 --- a/src/expand/asm.cpp +++ b/src/expand/asm.cpp @@ -35,12 +35,10 @@ namespace class CAsmExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { Token tok; auto lex = TTStream(sp, tt); - if( ident != "" ) - ERROR(sp, E0000, "asm! doesn't take an ident"); auto template_text = get_string(sp, lex, crate, mod); ::std::vector<::AST::ExprNode_Asm::ValRef> outputs; diff --git a/src/expand/assert.cpp b/src/expand/assert.cpp index 5bb23bde..ffba7b98 100644 --- a/src/expand/assert.cpp +++ b/src/expand/assert.cpp @@ -15,14 +15,12 @@ class CExpander_assert: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { Token tok; auto lex = TTStream(sp, tt); lex.parse_state().module = &mod; - if( ident != "" ) - ERROR(sp, E0000, "format_args! doesn't take an ident"); // assertion condition auto n = Parse_Expr0(lex); @@ -39,7 +37,7 @@ class CExpander_assert: toks.push_back( Token(InterpolatedFragment(InterpolatedFragment::EXPR, n.release())) ); toks.push_back( Token(TOK_BRACE_OPEN) ); // User-provided message - toks.push_back( Token(TOK_IDENT, "panic") ); + toks.push_back( Token(TOK_IDENT, RcString::new_interned("panic")) ); toks.push_back( Token(TOK_EXCLAM) ); toks.push_back( Token(TOK_PAREN_OPEN) ); while(lex.lookahead(0) != TOK_EOF ) @@ -63,7 +61,7 @@ class CExpander_assert: toks.push_back( Token(TOK_BRACE_OPEN) ); // Auto-generated message - toks.push_back( Token(TOK_IDENT, "panic") ); + toks.push_back( Token(TOK_IDENT, RcString::new_interned("panic")) ); toks.push_back( Token(TOK_EXCLAM) ); toks.push_back( Token(TOK_PAREN_OPEN) ); toks.push_back( Token(TOK_STRING, ss.str()) ); diff --git a/src/expand/cfg.cpp b/src/expand/cfg.cpp index 773a38c4..7e922779 100644 --- a/src/expand/cfg.cpp +++ b/src/expand/cfg.cpp @@ -60,7 +60,7 @@ bool check_cfg(const Span& sp, const ::AST::Attribute& mi) { } else if( mi.has_string() ) { // Equaliy - auto its = g_cfg_values.equal_range(mi.name()); + auto its = g_cfg_values.equal_range(mi.name().c_str()); for(auto it = its.first; it != its.second; ++it) { DEBUG(""<second<<"' == '"< expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - if( ident != "" ) { - ERROR(sp, E0000, "cfg! doesn't take an identifier"); - } - auto lex = TTStream(sp, tt); auto attrs = Parse_MetaItem(lex); DEBUG("cfg!() - " << attrs); diff --git a/src/expand/concat.cpp b/src/expand/concat.cpp index 29a066df..bd741e2f 100644 --- a/src/expand/concat.cpp +++ b/src/expand/concat.cpp @@ -16,13 +16,11 @@ class CConcatExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { Token tok; auto lex = TTStream(sp, tt); - if( ident != "" ) - ERROR(sp, E0000, "format_args! doesn't take an ident"); ::std::string rv; do { diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index dddd82b6..6dea3028 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -58,6 +58,15 @@ static inline ::std::vector vec$(T v1, T v2, T v3, T v4, T v5) { tmp.push_back( mv$(v5) ); return mv$(tmp); } +static AST::Path get_path(const RcString& core_name, ::std::string c1, ::std::string c2) +{ + return AST::Path(core_name, { AST::PathNode(RcString::new_interned(c1), {}), AST::PathNode(RcString::new_interned(c2), {}) }); +} +static AST::Path get_path(const RcString& core_name, ::std::string c1, ::std::string c2, ::std::string c3) +{ + return AST::Path(core_name, { AST::PathNode(RcString::new_interned(c1), {}), AST::PathNode(RcString::new_interned(c2), {}), AST::PathNode(RcString::new_interned(c3), {}) }); +} + static inline AST::ExprNodeP mk_exprnodep(AST::ExprNode* en){ return AST::ExprNodeP(en); } //#define NEWNODE(type, ...) mk_exprnodep(new type(__VA_ARGS__)) @@ -65,7 +74,7 @@ static inline AST::ExprNodeP mk_exprnodep(AST::ExprNode* en){ return AST::ExprNo struct DeriveOpts { - ::std::string core_name; + RcString core_name; const ::std::vector<::AST::Attribute>& derive_items; }; @@ -288,7 +297,7 @@ class Deriver_Debug: // throw CompileError::Todo("derive(Debug) - _try"); //} - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path debug_trait = AST::Path(core_name, { AST::PathNode("fmt", {}), AST::PathNode("Debug", {}) }); TypeRef f_type(TypeRef::TagReference(), sp, AST::LifetimeRef(), true, @@ -319,7 +328,7 @@ public: AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override { - const ::std::string& name = type.path().nodes().back().name(); + ::std::string name = type.path().nodes().back().name().c_str(); // Generate code for Debug AST::ExprNodeP node; @@ -342,7 +351,7 @@ public: node = NEWNODE(CallMethod, mv$(node), AST::PathNode("field",{}), vec$( - NEWNODE(String, fld.m_name), + NEWNODE(String, fld.m_name.c_str()), NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), @@ -368,7 +377,7 @@ public: NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), - FMT(idx) + RcString::new_interned(FMT(idx)) ) )) ) @@ -396,7 +405,7 @@ public: code = NEWNODE(CallMethod, NEWNODE(NamedValue, AST::Path("f")), AST::PathNode("write_str",{}), - vec$( NEWNODE(String, v.m_name) ) + vec$( NEWNODE(String, v.m_name.c_str()) ) ); pat_a = AST::Pattern(AST::Pattern::TagValue(), sp, AST::Pattern::Value::make_Named(base_path + v.m_name)); ), @@ -407,12 +416,12 @@ public: node = NEWNODE(NamedValue, AST::Path("f")); node = NEWNODE(CallMethod, mv$(node), AST::PathNode("debug_tuple",{}), - vec$( NEWNODE(String, v.m_name) ) + vec$( NEWNODE(String, v.m_name.c_str()) ) ); for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); node = NEWNODE(CallMethod, @@ -427,24 +436,24 @@ public: pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_a)); ), (Struct, - ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_a; AST::ExprNodeP node; node = NEWNODE(NamedValue, AST::Path("f")); node = NEWNODE(CallMethod, mv$(node), AST::PathNode("debug_struct",{}), - vec$( NEWNODE(String, v.m_name) ) + vec$( NEWNODE(String, v.m_name.c_str()) ) ); for( const auto& fld : e.m_fields ) { - auto name_a = FMT("a" << fld.m_name); + auto name_a = RcString::new_interned(FMT("a" << fld.m_name)); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) ); node = NEWNODE(CallMethod, mv$(node), AST::PathNode("field",{}), vec$( - NEWNODE(String, fld.m_name), + NEWNODE(String, fld.m_name.c_str()), NEWNODE(NamedValue, AST::Path(name_a)) ) ); @@ -476,7 +485,7 @@ public: class Deriver_PartialEq: public Deriver { - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("PartialEq", {}) }); @@ -498,7 +507,7 @@ class Deriver_PartialEq: rv.add_function(false, false, "eq", mv$(fcn)); return mv$(rv); } - AST::ExprNodeP compare_and_ret(Span sp, const ::std::string& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const + AST::ExprNodeP compare_and_ret(Span sp, const RcString& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const { return NEWNODE(If, NEWNODE(BinOp, AST::ExprNode_BinOp::CMPNEQU, mv$(v1), mv$(v2)), @@ -528,7 +537,7 @@ public: (Tuple, for( unsigned int idx = 0; idx < e.ents.size(); idx ++ ) { - auto fld_name = FMT(idx); + auto fld_name = RcString::new_interned(FMT(idx)); nodes.push_back(this->compare_and_ret( sp, opts.core_name, NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld_name), NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld_name) @@ -566,8 +575,8 @@ public: for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); - auto name_b = FMT("b" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); + auto name_b = RcString::new_interned(FMT("b" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF) ); nodes.push_back(this->compare_and_ret(sp, opts.core_name, @@ -582,14 +591,14 @@ public: code = NEWNODE(Block, mv$(nodes)); ), (Struct, - ::std::vector< ::std::pair > pats_a; - ::std::vector< ::std::pair > pats_b; + ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_b; ::std::vector nodes; for( const auto& fld : e.m_fields ) { - auto name_a = FMT("a" << fld.m_name); - auto name_b = FMT("b" << fld.m_name); + auto name_a = RcString::new_interned(FMT("a" << fld.m_name)); + auto name_b = RcString::new_interned(FMT("b" << fld.m_name)); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) ); pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF)) ); nodes.push_back(this->compare_and_ret(sp, opts.core_name, @@ -642,16 +651,7 @@ public: class Deriver_PartialOrd: public Deriver { - AST::Path get_path(const ::std::string core_name, ::std::string c1, ::std::string c2) const - { - return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}) }); - } - AST::Path get_path(const ::std::string core_name, ::std::string c1, ::std::string c2, ::std::string c3) const - { - return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}), AST::PathNode(c3, {}) }); - } - - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("PartialOrd", {}) }); const AST::Path path_ordering(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Ordering", {}) }); @@ -678,10 +678,10 @@ class Deriver_PartialOrd: return mv$(rv); } - AST::ExprNodeP make_compare_and_ret(Span sp, const ::std::string& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const + AST::ExprNodeP make_compare_and_ret(Span sp, const RcString& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const { return NEWNODE(Match, - NEWNODE(CallPath, this->get_path(core_name, "cmp", "PartialOrd", "partial_cmp"), + NEWNODE(CallPath, get_path(core_name, "cmp", "PartialOrd", "partial_cmp"), ::make_vec2( NEWNODE(UniOp, AST::ExprNode_UniOp::REF, mv$(v1)), NEWNODE(UniOp, AST::ExprNode_UniOp::REF, mv$(v2)) @@ -689,13 +689,13 @@ class Deriver_PartialOrd: ), ::make_vec3( ::AST::ExprNode_Match_Arm( - ::make_vec1( AST::Pattern(AST::Pattern::TagValue(), sp, this->get_path(core_name, "option", "Option", "None")) ), + ::make_vec1( AST::Pattern(AST::Pattern::TagValue(), sp, get_path(core_name, "option", "Option", "None")) ), nullptr, - NEWNODE(Flow, AST::ExprNode_Flow::RETURN, "", NEWNODE(NamedValue, this->get_path(core_name, "option", "Option", "None"))) + NEWNODE(Flow, AST::ExprNode_Flow::RETURN, "", NEWNODE(NamedValue, get_path(core_name, "option", "Option", "None"))) ), ::AST::ExprNode_Match_Arm( - ::make_vec1( AST::Pattern(AST::Pattern::TagNamedTuple(), sp, this->get_path(core_name, "option", "Option", "Some"), - ::make_vec1( AST::Pattern(AST::Pattern::TagValue(), sp, this->get_path(core_name, "cmp", "Ordering", "Equal")) ) + ::make_vec1( AST::Pattern(AST::Pattern::TagNamedTuple(), sp, get_path(core_name, "option", "Option", "Some"), + ::make_vec1( AST::Pattern(AST::Pattern::TagValue(), sp, get_path(core_name, "cmp", "Ordering", "Equal")) ) ) ), nullptr, NEWNODE(Tuple, ::std::vector()) @@ -708,10 +708,10 @@ class Deriver_PartialOrd: ) ); } - AST::ExprNodeP make_ret_equal(const ::std::string& core_name) const + AST::ExprNodeP make_ret_equal(const RcString& core_name) const { - return NEWNODE(CallPath, this->get_path(core_name, "option", "Option", "Some"), - ::make_vec1( NEWNODE(NamedValue, this->get_path(core_name, "cmp", "Ordering", "Equal")) ) + return NEWNODE(CallPath, get_path(core_name, "option", "Option", "Some"), + ::make_vec1( NEWNODE(NamedValue, get_path(core_name, "cmp", "Ordering", "Equal")) ) ); } public: @@ -736,7 +736,7 @@ public: (Tuple, for( unsigned int idx = 0; idx < e.ents.size(); idx ++ ) { - auto fld_name = FMT(idx); + auto fld_name = RcString::new_interned(FMT(idx)); nodes.push_back(this->make_compare_and_ret( sp, opts.core_name, NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld_name), NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld_name) @@ -774,8 +774,8 @@ public: for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); - auto name_b = FMT("b" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); + auto name_b = RcString::new_interned(FMT("b" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF) ); @@ -791,14 +791,14 @@ public: code = NEWNODE(Block, mv$(nodes)); ), (Struct, - ::std::vector< ::std::pair > pats_a; - ::std::vector< ::std::pair > pats_b; + ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_b; ::std::vector nodes; for( const auto& fld : e.m_fields ) { - auto name_a = FMT("a" << fld.m_name); - auto name_b = FMT("b" << fld.m_name); + auto name_a = RcString::new_interned(FMT("a" << fld.m_name)); + auto name_b = RcString::new_interned(FMT("b" << fld.m_name)); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) ); pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF)) ); @@ -834,10 +834,10 @@ public: // - Requires a way of emitting said intrinsic into the AST // - LAZY WAY - hard-code ::"core"::intrinsics::discriminant_value { - auto code = NEWNODE(CallPath, this->get_path(opts.core_name, "cmp", "PartialOrd", "partial_cmp"), + auto code = NEWNODE(CallPath, get_path(opts.core_name, "cmp", "PartialOrd", "partial_cmp"), ::make_vec2( - NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, this->get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("self")) )) ), - NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, this->get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("v")) )) ) + NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("self")) )) ), + NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("v")) )) ) ) ); ::std::vector< AST::Pattern> pats = make_vec1( AST::Pattern() ); @@ -862,11 +862,11 @@ public: class Deriver_Eq: public Deriver { - AST::Path get_trait_path(const ::std::string& core_name) const { + AST::Path get_trait_path(const RcString& core_name) const { return AST::Path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Eq", {}) }); } - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path = this->get_trait_path(core_name); @@ -894,6 +894,9 @@ class Deriver_Eq: ); } AST::ExprNodeP field(const ::std::string& name) const { + return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), RcString::new_interned(name)); + } + AST::ExprNodeP field(const RcString& name) const { return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name); } @@ -949,7 +952,7 @@ public: for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) ); } @@ -958,12 +961,12 @@ public: code = NEWNODE(Block, mv$(nodes)); ), (Struct, - ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_a; ::std::vector nodes; for( const auto& fld : e.m_fields ) { - auto name_a = FMT("a" << fld.m_name); + auto name_a = RcString::new_interned(FMT("a" << fld.m_name)); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) ); nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) ); } @@ -1007,16 +1010,7 @@ public: class Deriver_Ord: public Deriver { - AST::Path get_path(const ::std::string core_name, ::std::string c1, ::std::string c2) const - { - return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}) }); - } - AST::Path get_path(const ::std::string core_name, ::std::string c1, ::std::string c2, ::std::string c3) const - { - return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}), AST::PathNode(c3, {}) }); - } - - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Ord", {}) }); const AST::Path path_ordering(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Ordering", {}) }); @@ -1040,10 +1034,10 @@ class Deriver_Ord: return mv$(rv); } - AST::ExprNodeP make_compare_and_ret(Span sp, const ::std::string& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const + AST::ExprNodeP make_compare_and_ret(Span sp, const RcString& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const { return NEWNODE(Match, - NEWNODE(CallPath, this->get_path(core_name, "cmp", "Ord", "cmp"), + NEWNODE(CallPath, get_path(core_name, "cmp", "Ord", "cmp"), // TODO: Optional Ref? ::make_vec2( NEWNODE(UniOp, AST::ExprNode_UniOp::REF, mv$(v1)), @@ -1052,7 +1046,7 @@ class Deriver_Ord: ), ::make_vec2( ::AST::ExprNode_Match_Arm( - ::make_vec1( AST::Pattern(AST::Pattern::TagValue(), sp, this->get_path(core_name, "cmp", "Ordering", "Equal")) ), + ::make_vec1( AST::Pattern(AST::Pattern::TagValue(), sp, get_path(core_name, "cmp", "Ordering", "Equal")) ), nullptr, NEWNODE(Tuple, ::std::vector()) ), @@ -1064,9 +1058,9 @@ class Deriver_Ord: ) ); } - AST::ExprNodeP make_ret_equal(const ::std::string& core_name) const + AST::ExprNodeP make_ret_equal(const RcString& core_name) const { - return NEWNODE(NamedValue, this->get_path(core_name, "cmp", "Ordering", "Equal")); + return NEWNODE(NamedValue, get_path(core_name, "cmp", "Ordering", "Equal")); } public: const char* trait_name() const override { return "Ord"; } @@ -1090,7 +1084,7 @@ public: (Tuple, for( unsigned int idx = 0; idx < e.ents.size(); idx ++ ) { - auto fld_name = FMT(idx); + auto fld_name = RcString::new_interned(FMT(idx)); nodes.push_back(this->make_compare_and_ret( sp, opts.core_name, NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld_name), NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld_name) @@ -1128,8 +1122,8 @@ public: for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); - auto name_b = FMT("b" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); + auto name_b = RcString::new_interned(FMT("b" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF) ); @@ -1145,14 +1139,14 @@ public: code = NEWNODE(Block, mv$(nodes)); ), (Struct, - ::std::vector< ::std::pair > pats_a; - ::std::vector< ::std::pair > pats_b; + ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_b; ::std::vector nodes; for( const auto& fld : e.m_fields ) { - auto name_a = FMT("a" << fld.m_name); - auto name_b = FMT("b" << fld.m_name); + auto name_a = RcString::new_interned(FMT("a" << fld.m_name)); + auto name_b = RcString::new_interned(FMT("b" << fld.m_name)); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) ); pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF)) ); @@ -1186,10 +1180,10 @@ public: { - auto code = NEWNODE(CallPath, this->get_path(opts.core_name, "cmp", "Ord", "cmp"), + auto code = NEWNODE(CallPath, get_path(opts.core_name, "cmp", "Ord", "cmp"), ::make_vec2( - NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, this->get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("self")) )) ), - NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, this->get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("v")) )) ) + NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("self")) )) ), + NEWNODE(UniOp, AST::ExprNode_UniOp::REF, NEWNODE(CallPath, get_path(opts.core_name, "intrinsics", "discriminant_value"), make_vec1( NEWNODE(NamedValue, AST::Path("v")) )) ) ) ); ::std::vector< AST::Pattern> pats = make_vec1( AST::Pattern() ); @@ -1214,14 +1208,14 @@ public: class Deriver_Clone: public Deriver { - AST::Path get_trait_path(const ::std::string& core_name) const { + AST::Path get_trait_path(const RcString& core_name) const { return AST::Path(core_name, { AST::PathNode("clone", {}), AST::PathNode("Clone", {}) }); } - AST::Path get_method_path(const ::std::string& core_name) const { + AST::Path get_method_path(const RcString& core_name) const { return get_trait_path(core_name) + "clone"; } - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path = this->get_trait_path(core_name); @@ -1242,22 +1236,25 @@ class Deriver_Clone: rv.add_function(false, false, "clone", mv$(fcn)); return mv$(rv); } - AST::ExprNodeP clone_val_ref(const ::std::string& core_name, AST::ExprNodeP val) const { + AST::ExprNodeP clone_val_ref(const RcString& core_name, AST::ExprNodeP val) const { // TODO: Hack for zero-sized arrays? (Not a 1.19 feature) return NEWNODE(CallPath, this->get_method_path(core_name), vec$( NEWNODE(UniOp, AST::ExprNode_UniOp::REF, mv$(val) ) ) ); } - AST::ExprNodeP clone_val_direct(const ::std::string& core_name, AST::ExprNodeP val) const { + AST::ExprNodeP clone_val_direct(const RcString& core_name, AST::ExprNodeP val) const { return NEWNODE(CallPath, this->get_method_path(core_name), vec$( mv$(val) ) ); } - AST::ExprNodeP field(const ::std::string& name) const { + AST::ExprNodeP field(const RcString& name) const { return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name); } + AST::ExprNodeP field(const ::std::string& name) const { + return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), RcString::new_interned(name)); + } public: const char* trait_name() const override { return "Clone"; } @@ -1314,7 +1311,7 @@ public: for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); nodes.push_back( this->clone_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) ); } @@ -1323,12 +1320,12 @@ public: code = NEWNODE(CallPath, base_path + v.m_name, mv$(nodes)); ), (Struct, - ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_a; ::AST::ExprNode_StructLiteral::t_values vals; for( const auto& fld : e.m_fields ) { - auto name_a = FMT("a" << fld.m_name); + auto name_a = RcString::new_interned(FMT("a" << fld.m_name)); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) ); vals.push_back({ {}, fld.m_name, this->clone_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) }); } @@ -1383,11 +1380,11 @@ private: class Deriver_Copy: public Deriver { - AST::Path get_trait_path(const ::std::string& core_name) const { + AST::Path get_trait_path(const RcString& core_name) const { return AST::Path(core_name, { AST::PathNode("marker", {}), AST::PathNode("Copy", {}) }); } - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path = this->get_trait_path(core_name); @@ -1418,14 +1415,14 @@ public: class Deriver_Default: public Deriver { - AST::Path get_trait_path(const ::std::string& core_name) const { + AST::Path get_trait_path(const RcString& core_name) const { return AST::Path(core_name, { AST::PathNode("default", {}), AST::PathNode("Default", {}) }); } - AST::Path get_method_path(const ::std::string& core_name) const { + AST::Path get_method_path(const RcString& core_name) const { return AST::Path(AST::Path::TagUfcs(), ::TypeRef(Span()), get_trait_path(core_name), { AST::PathNode("default", {}) } ); } - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path = this->get_trait_path(core_name); @@ -1444,7 +1441,7 @@ class Deriver_Default: rv.add_function(false, false, "default", mv$(fcn)); return mv$(rv); } - AST::ExprNodeP default_call(const ::std::string& core_name) const { + AST::ExprNodeP default_call(const RcString& core_name) const { return NEWNODE(CallPath, this->get_method_path(core_name), {} @@ -1493,17 +1490,17 @@ public: class Deriver_Hash: public Deriver { - AST::Path get_trait_path(const ::std::string& core_name) const { + AST::Path get_trait_path(const RcString& core_name) const { return AST::Path(core_name, { AST::PathNode("hash", {}), AST::PathNode("Hash", {}) }); } - AST::Path get_trait_path_Hasher(const ::std::string& core_name) const { + AST::Path get_trait_path_Hasher(const RcString& core_name) const { return AST::Path(core_name, { AST::PathNode("hash", {}), AST::PathNode("Hasher", {}) }); } - AST::Path get_method_path(const ::std::string& core_name) const { + AST::Path get_method_path(const RcString& core_name) const { return get_trait_path(core_name) + "hash"; } - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path = this->get_trait_path(core_name); @@ -1530,18 +1527,21 @@ class Deriver_Hash: rv.add_function(false, false, "hash", mv$(fcn)); return mv$(rv); } - AST::ExprNodeP hash_val_ref(const ::std::string& core_name, AST::ExprNodeP val) const { + AST::ExprNodeP hash_val_ref(const RcString& core_name, AST::ExprNodeP val) const { return this->hash_val_direct(core_name, NEWNODE(UniOp, AST::ExprNode_UniOp::REF, mv$(val)) ); } - AST::ExprNodeP hash_val_direct(const ::std::string& core_name, AST::ExprNodeP val) const { + AST::ExprNodeP hash_val_direct(const RcString& core_name, AST::ExprNodeP val) const { return NEWNODE(CallPath, this->get_method_path(core_name), vec$( mv$(val), NEWNODE(NamedValue, AST::Path("state")) ) ); } - AST::ExprNodeP field(const ::std::string& name) const { + AST::ExprNodeP field(const RcString& name) const { return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name); } + AST::ExprNodeP field(const std::string& name) const { + return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), RcString::new_interned(name)); + } public: const char* trait_name() const override { return "Hash"; } @@ -1596,7 +1596,7 @@ public: for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); nodes.push_back( this->hash_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) ); } @@ -1605,13 +1605,13 @@ public: code = NEWNODE(Block, mv$(nodes)); ), (Struct, - ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_a; ::std::vector< AST::ExprNodeP > nodes; nodes.push_back( mv$(var_idx_hash) ); for( const auto& fld : e.m_fields ) { - auto name_a = FMT("a" << fld.m_name); + auto name_a = RcString::new_interned(FMT("a" << fld.m_name)); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) ); nodes.push_back( this->hash_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) ); } @@ -1652,7 +1652,7 @@ class Deriver_RustcEncodable: return get_trait_path() + "encode"; } - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path = this->get_trait_path(); @@ -1689,9 +1689,12 @@ class Deriver_RustcEncodable: AST::ExprNodeP enc_val_ref(AST::ExprNodeP val) const { return this->enc_val_direct(NEWNODE(UniOp, AST::ExprNode_UniOp::REF, mv$(val)) ); } - AST::ExprNodeP field(const ::std::string& name) const { + AST::ExprNodeP field(const RcString& name) const { return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name); } + AST::ExprNodeP field(::std::string name) const { + return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), RcString::new_interned(name)); + } AST::ExprNodeP enc_closure(Span sp, AST::ExprNodeP code) const { return NEWNODE(Closure, @@ -1699,7 +1702,7 @@ class Deriver_RustcEncodable: mv$(code), false ); } - AST::ExprNodeP get_val_ok(const ::std::string& core_name) const { + AST::ExprNodeP get_val_ok(const RcString& core_name) const { return NEWNODE(CallPath, AST::Path(core_name, {AST::PathNode("result",{}), AST::PathNode("Result",{}), AST::PathNode("Ok",{})}), vec$( NEWNODE(Tuple, {})) ); } @@ -1708,7 +1711,7 @@ public: AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override { - const ::std::string& struct_name = type.m_data.as_Path().path.nodes().back().name(); + ::std::string struct_name = type.m_data.as_Path().path.nodes().back().name().c_str(); ::std::vector nodes; TU_MATCH(AST::StructData, (str.m_data), (e), @@ -1720,7 +1723,12 @@ public: { nodes.push_back( NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_struct_field", - vec$( NEWNODE(NamedValue, AST::Path("s")), NEWNODE(String, fld.m_name), NEWNODE(Integer, idx, CORETYPE_UINT), this->enc_closure( sp, this->enc_val_ref(this->field(fld.m_name)) ) ) + vec$( + NEWNODE(NamedValue, AST::Path("s")), + NEWNODE(String, fld.m_name.c_str()), + NEWNODE(Integer, idx, CORETYPE_UINT), + this->enc_closure( sp, this->enc_val_ref(this->field(fld.m_name)) ) + ) ) ); idx ++; } @@ -1778,7 +1786,7 @@ public: code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_variant", vec$( NEWNODE(NamedValue, AST::Path("s")), - NEWNODE(String, v.m_name), + NEWNODE(String, v.m_name.c_str()), NEWNODE(Integer, var_idx, CORETYPE_UINT), NEWNODE(Integer, 0, CORETYPE_UINT), this->enc_closure(sp, this->get_val_ok(opts.core_name)) @@ -1792,7 +1800,7 @@ public: for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ ) { - auto name_a = FMT("a" << idx); + auto name_a = RcString::new_interned(FMT("a" << idx)); pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) ); nodes.push_back( NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_variant_arg", vec$( @@ -1807,7 +1815,7 @@ public: code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_variant", vec$( NEWNODE(NamedValue, AST::Path("s")), - NEWNODE(String, v.m_name), + NEWNODE(String, v.m_name.c_str()), NEWNODE(Integer, var_idx, CORETYPE_UINT), NEWNODE(Integer, e.m_sub_types.size(), CORETYPE_UINT), this->enc_closure(sp, NEWNODE(Block, mv$(nodes))) @@ -1816,19 +1824,19 @@ public: pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_a)); ), (Struct, - ::std::vector< ::std::pair > pats_a; + ::std::vector< ::std::pair > pats_a; ::std::vector< AST::ExprNodeP > nodes; unsigned int idx = 0; for( const auto& fld : e.m_fields ) { - auto name_a = Ident( FMT("a" << fld.m_name) ); + auto name_a = Ident( RcString::new_interned(FMT("a" << fld.m_name)) ); pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, Ident(name_a), ::AST::PatternBinding::Type::REF)) ); nodes.push_back( NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_struct_variant_field", vec$( NEWNODE(NamedValue, AST::Path("s")), - NEWNODE(String, fld.m_name), + NEWNODE(String, fld.m_name.c_str()), NEWNODE(Integer, idx, CORETYPE_UINT), this->enc_closure(sp, this->enc_val_direct(NEWNODE(NamedValue, AST::Path(name_a.name)))) ) @@ -1841,7 +1849,7 @@ public: code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_struct_variant", vec$( NEWNODE(NamedValue, AST::Path("s")), - NEWNODE(String, v.m_name), + NEWNODE(String, v.m_name.c_str()), NEWNODE(Integer, var_idx, CORETYPE_UINT), NEWNODE(Integer, e.m_fields.size(), CORETYPE_UINT), this->enc_closure(sp, NEWNODE(Block, mv$(nodes))) @@ -1862,7 +1870,7 @@ public: auto node_match = NEWNODE(Match, NEWNODE(NamedValue, AST::Path("self")), mv$(arms)); - const ::std::string& enum_name = type.m_data.as_Path().path.nodes().back().name(); + ::std::string enum_name = type.m_data.as_Path().path.nodes().back().name().c_str(); auto node = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum", vec$( NEWNODE(NamedValue, AST::Path("s")), NEWNODE(String, enum_name), this->enc_closure(sp, mv$(node_match)) ) ); @@ -1885,11 +1893,11 @@ class Deriver_RustcDecodable: return get_trait_path() + "decode"; } - AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const + AST::Impl make_ret(Span sp, const RcString& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector types_to_bound, AST::ExprNodeP node) const { const AST::Path trait_path = this->get_trait_path(); - AST::Path result_path = AST::Path(core_name, { AST::PathNode("result", {}), AST::PathNode("Result", {}) }); + AST::Path result_path = AST::Path(core_name, { AST::PathNode(RcString::new_interned("result"), {}), AST::PathNode(RcString::new_interned("Result"), {}) }); result_path.nodes()[1].args().m_types.push_back( TypeRef(sp, "Self", 0xFFFF) ); result_path.nodes()[1].args().m_types.push_back( TypeRef(sp, AST::Path(AST::Path::TagUfcs(), TypeRef(sp, "D", 0x100|0), this->get_trait_path_Decoder(), { AST::PathNode("Error",{}) })) ); @@ -1920,7 +1928,7 @@ class Deriver_RustcDecodable: return NEWNODE(CallPath, this->get_method_path(), vec$( NEWNODE(NamedValue, AST::Path("d")) )); } AST::ExprNodeP field(const ::std::string& name) const { - return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name); + return NEWNODE(Field, NEWNODE(NamedValue, AST::Path(RcString::new_interned("self"))), RcString::new_interned(name)); } AST::ExprNodeP dec_closure(Span sp, AST::ExprNodeP code) const { @@ -1929,8 +1937,8 @@ class Deriver_RustcDecodable: mv$(code), false ); } - AST::ExprNodeP get_val_err_str(const ::std::string& core_name, ::std::string err_str) const { - return NEWNODE(CallPath, AST::Path(core_name, {AST::PathNode("result",{}), AST::PathNode("Result",{}), AST::PathNode("Err",{})}), vec$( + AST::ExprNodeP get_val_err_str(const RcString& core_name, ::std::string err_str) const { + return NEWNODE(CallPath, get_path(core_name, "result", "Result", "Err"), vec$( NEWNODE(CallMethod, NEWNODE(NamedValue, AST::Path("d")), AST::PathNode("error"), @@ -1938,10 +1946,10 @@ class Deriver_RustcDecodable: ) ) ); } - AST::ExprNodeP get_val_ok(const ::std::string& core_name, AST::ExprNodeP inner) const { - return NEWNODE(CallPath, AST::Path(core_name, {AST::PathNode("result",{}), AST::PathNode("Result",{}), AST::PathNode("Ok",{})}), vec$( mv$(inner) ) ); + AST::ExprNodeP get_val_ok(const RcString& core_name, AST::ExprNodeP inner) const { + return NEWNODE(CallPath, get_path(core_name, "result", "Result", "Ok"), vec$( mv$(inner) ) ); } - AST::ExprNodeP get_val_ok_unit(const ::std::string& core_name) const { + AST::ExprNodeP get_val_ok_unit(const RcString& core_name) const { return get_val_ok(core_name, NEWNODE(Tuple, {})); } @@ -1951,7 +1959,7 @@ public: AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override { AST::Path base_path = type.m_data.as_Path().path; - const ::std::string& struct_name = type.m_data.as_Path().path.nodes().back().name(); + ::std::string struct_name = type.m_data.as_Path().path.nodes().back().name().c_str(); AST::ExprNodeP node_v; TU_MATCH(AST::StructData, (str.m_data), (e), @@ -1964,7 +1972,7 @@ public: { vals.push_back({ {}, fld.m_name, NEWNODE(UniOp, ::AST::ExprNode_UniOp::QMARK, NEWNODE(CallPath, this->get_trait_path_Decoder() + "read_struct_field", - vec$( NEWNODE(NamedValue, AST::Path("d")), NEWNODE(String, fld.m_name), NEWNODE(Integer, idx, CORETYPE_UINT), this->dec_closure( sp, this->dec_val() ) ) + vec$( NEWNODE(NamedValue, AST::Path("d")), NEWNODE(String, fld.m_name.c_str()), NEWNODE(Integer, idx, CORETYPE_UINT), this->dec_closure( sp, this->dec_val() ) ) )) }); idx ++; } @@ -2053,7 +2061,7 @@ public: vals.push_back({ {}, fld.m_name, NEWNODE(UniOp, ::AST::ExprNode_UniOp::QMARK, NEWNODE(CallPath, this->get_trait_path_Decoder() + "read_enum_struct_variant_field", vec$( NEWNODE(NamedValue, AST::Path("d")), - NEWNODE(String, fld.m_name), + NEWNODE(String, fld.m_name.c_str()), NEWNODE(Integer, idx, CORETYPE_UINT), this->dec_closure(sp, this->dec_val()) ) @@ -2073,7 +2081,7 @@ public: nullptr, this->get_val_ok(opts.core_name, mv$(code)) )); - var_name_strs.push_back( NEWNODE(String, v.m_name) ); + var_name_strs.push_back( NEWNODE(String, v.m_name.c_str()) ); } // Default arm @@ -2095,7 +2103,7 @@ public: mv$(node_match), false ); - const ::std::string& enum_name = type.m_data.as_Path().path.nodes().back().name(); + ::std::string enum_name = type.m_data.as_Path().path.nodes().back().name().c_str(); auto node_rev = NEWNODE(CallPath, this->get_trait_path_Decoder() + "read_enum_variant", vec$( @@ -2117,7 +2125,7 @@ public: // -------------------------------------------------------------------- // Select and dispatch the correct derive() handler // -------------------------------------------------------------------- -static const Deriver* find_impl(const ::std::string& trait_name) +static const Deriver* find_impl(const RcString& trait_name) { #define _(obj) if(trait_name == obj.trait_name()) return &obj; _(g_derive_debug) @@ -2158,7 +2166,7 @@ static void derive_item(const Span& sp, const AST::Crate& crate, AST::Module& mo attr.items() }; - ::std::vector< ::std::string> missing_handlers; + ::std::vector< RcString> missing_handlers; for( const auto& trait : attr.items() ) { DEBUG("- " << trait.name()); @@ -2182,7 +2190,7 @@ static void derive_item(const Span& sp, const AST::Crate& crate, AST::Module& mo } else { // proc_macro - Invoke the handler. - auto lex = ProcMacro_Invoke(sp, crate, mac_path.path, path.nodes().back().name(), item); + auto lex = ProcMacro_Invoke(sp, crate, mac_path.path, path.nodes().back().name().c_str(), item); if( lex ) { Parse_ModRoot_Items(*lex, mod); diff --git a/src/expand/env.cpp b/src/expand/env.cpp index f4577ef1..825c895a 100644 --- a/src/expand/env.cpp +++ b/src/expand/env.cpp @@ -34,48 +34,44 @@ namespace { class CExpanderEnv: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - if( ident != "" ) - ERROR(sp, E0000, "env! doesn't take an ident"); ::std::string varname = get_string(sp, crate, mod, tt); const char* var_val_cstr = getenv(varname.c_str()); if( !var_val_cstr ) { ERROR(sp, E0000, "Environment variable '" << varname << "' not defined"); } - return box$( TTStreamO(sp, TokenTree(Token(TOK_STRING, var_val_cstr))) ); + return box$( TTStreamO(sp, TokenTree(Token(TOK_STRING, ::std::string(var_val_cstr)))) ); } }; class CExpanderOptionEnv: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - if( ident != "" ) - ERROR(sp, E0000, "option_env! doesn't take an ident"); ::std::string varname = get_string(sp, crate, mod, tt); const char* var_val_cstr = getenv(varname.c_str()); if( !var_val_cstr ) { ::std::vector< TokenTree> rv; rv.reserve(7); - rv.push_back( Token(TOK_IDENT, "None") ); + rv.push_back( Token(TOK_IDENT, RcString::new_interned("None")) ); rv.push_back( Token(TOK_DOUBLE_COLON) ); rv.push_back( Token(TOK_LT) ); rv.push_back( Token(TOK_AMP) ); - rv.push_back( Token(TOK_LIFETIME, "static") ); - rv.push_back( Token(TOK_IDENT, "str") ); + rv.push_back( Token(TOK_LIFETIME, RcString::new_interned("static")) ); + rv.push_back( Token(TOK_IDENT, RcString::new_interned("str")) ); rv.push_back( Token(TOK_GT) ); return box$( TTStreamO(sp, TokenTree( {}, mv$(rv) )) ); } else { ::std::vector< TokenTree> rv; rv.reserve(4); - rv.push_back( Token(TOK_IDENT, "Some") ); + rv.push_back( Token(TOK_IDENT, RcString::new_interned("Some")) ); rv.push_back( Token(TOK_PAREN_OPEN) ); - rv.push_back( Token(TOK_STRING, var_val_cstr) ); + rv.push_back( Token(TOK_STRING, ::std::string(var_val_cstr)) ); rv.push_back( Token(TOK_PAREN_CLOSE) ); return box$( TTStreamO(sp, TokenTree( {}, mv$(rv) )) ); } diff --git a/src/expand/file_line.cpp b/src/expand/file_line.cpp index 2bf85ffd..09d3e6b2 100644 --- a/src/expand/file_line.cpp +++ b/src/expand/file_line.cpp @@ -23,16 +23,16 @@ namespace { class CExpanderFile: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - return box$( TTStreamO(sp, TokenTree(Token(TOK_STRING, get_top_span(sp).filename.c_str()))) ); + return box$( TTStreamO(sp, TokenTree(Token(TOK_STRING, ::std::string(get_top_span(sp).filename.c_str())))) ); } }; class CExpanderLine: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { return box$( TTStreamO(sp, TokenTree(Token((uint64_t)get_top_span(sp).start_line, CORETYPE_U32))) ); } @@ -41,7 +41,7 @@ class CExpanderLine: class CExpanderColumn: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { return box$( TTStreamO(sp, TokenTree(Token((uint64_t)get_top_span(sp).start_ofs, CORETYPE_U32))) ); } @@ -49,7 +49,7 @@ class CExpanderColumn: class CExpanderUnstableColumn: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { return box$( TTStreamO(sp, TokenTree(Token((uint64_t)get_top_span(sp).start_ofs, CORETYPE_U32))) ); } @@ -58,13 +58,13 @@ class CExpanderUnstableColumn: class CExpanderModulePath: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { ::std::string path_str; for(const auto& comp : mod.path().nodes()) { if( &comp != &mod.path().nodes().front() ) path_str += "::"; - path_str += comp.name(); + path_str += comp.name().c_str(); } return box$( TTStreamO(sp, TokenTree( Token(TOK_STRING, mv$(path_str)) )) ); } diff --git a/src/expand/format_args.cpp b/src/expand/format_args.cpp index d79fd9d5..7f33eb6d 100644 --- a/src/expand/format_args.cpp +++ b/src/expand/format_args.cpp @@ -189,11 +189,11 @@ namespace { ::std::tuple< ::std::vector, ::std::string> parse_format_string( const Span& sp, const ::std::string& format_string, - const ::std::map< ::std::string,unsigned int>& named, + const ::std::map& named, unsigned int n_free ) { - unsigned int n_named = named.size(); + //unsigned int n_named = named.size(); unsigned int next_free = 0; ::std::vector frags; @@ -256,7 +256,7 @@ namespace { while( isalnum(*s) || *s == '_' || (*s < 0 || *s > 127) ) { s ++; } - ::std::string ident { start, s }; + auto ident = RcString(start, s - start); auto it = named.find(ident); if( it == named.end() ) ERROR(sp, E0000, "Named argument '"<& toks, const AST::Crate& crate, ::std::initializer_list il) { switch(crate.m_load_std) @@ -472,17 +475,17 @@ namespace { break; case ::AST::Crate::LOAD_CORE: toks.push_back( TokenTree(TOK_DOUBLE_COLON) ); - toks.push_back( Token(TOK_IDENT, "core") ); + toks.push_back( ident("core") ); break; case ::AST::Crate::LOAD_STD: toks.push_back( TokenTree(TOK_DOUBLE_COLON) ); - toks.push_back( Token(TOK_IDENT, "std") ); + toks.push_back( ident("std") ); break; } for(auto ent : il) { toks.push_back( TokenTree(TOK_DOUBLE_COLON) ); - toks.push_back( Token(TOK_IDENT, ent) ); + toks.push_back( ident(ent) ); } } void push_toks(::std::vector& toks, Token t1) { @@ -519,7 +522,7 @@ namespace { const auto& format_string_sp = format_string_np->span(); const auto& format_string = format_string_np->m_value; - ::std::map< ::std::string, unsigned int> named_args_index; + ::std::map named_args_index; ::std::vector named_args; ::std::vector free_args; @@ -535,7 +538,7 @@ namespace { if( lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_EQUAL ) { GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_EQUAL); @@ -600,7 +603,7 @@ namespace { toks.push_back( TokenTree(TOK_PAREN_OPEN) ); for(unsigned int i = 0; i < free_args.size() + named_args.size(); i ++ ) { - toks.push_back( Token(TOK_IDENT, FMT("a" << i)) ); + toks.push_back( ident(FMT("a" << i).c_str()) ); toks.push_back( TokenTree(TOK_COMMA) ); } toks.push_back( TokenTree(TOK_PAREN_CLOSE) ); @@ -612,13 +615,13 @@ namespace { // - Contains N+1 entries, where N is the number of fragments { toks.push_back( TokenTree(TOK_RWORD_STATIC) ); - toks.push_back( Token(TOK_IDENT, "FRAGMENTS") ); + toks.push_back( ident("FRAGMENTS") ); toks.push_back( TokenTree(TOK_COLON) ); toks.push_back( TokenTree(TOK_SQUARE_OPEN) ); toks.push_back( Token(TOK_AMP) ); - toks.push_back( Token(TOK_LIFETIME, "static") ); - toks.push_back( Token(TOK_IDENT, "str") ); + toks.push_back( Token(TOK_LIFETIME, RcString::new_interned("static")) ); + toks.push_back( ident("str") ); toks.push_back( Token(TOK_SEMICOLON) ); toks.push_back( Token(static_cast(fragments.size() + 1), CORETYPE_UINT) ); toks.push_back( TokenTree(TOK_SQUARE_CLOSE) ); @@ -644,7 +647,7 @@ namespace { toks.push_back( TokenTree(TOK_PAREN_OPEN) ); { toks.push_back( TokenTree(TOK_AMP) ); - toks.push_back( Token(TOK_IDENT, "FRAGMENTS") ); + toks.push_back( ident("FRAGMENTS") ); toks.push_back( TokenTree(TOK_COMMA) ); toks.push_back( TokenTree(TOK_AMP) ); @@ -653,7 +656,7 @@ namespace { { push_path(toks, crate, {"fmt", "ArgumentV1", "new"}); toks.push_back( Token(TOK_PAREN_OPEN) ); - toks.push_back( Token(TOK_IDENT, FMT("a" << frag.arg_index)) ); + toks.push_back( ident( FMT("a" << frag.arg_index).c_str() ) ); toks.push_back( TokenTree(TOK_COMMA) ); @@ -678,7 +681,7 @@ namespace { toks.push_back( TokenTree(TOK_PAREN_OPEN) ); { toks.push_back( TokenTree(TOK_AMP) ); - toks.push_back( Token(TOK_IDENT, "FRAGMENTS") ); + toks.push_back( ident("FRAGMENTS") ); toks.push_back( TokenTree(TOK_COMMA) ); // TODO: Fragments to format @@ -689,7 +692,7 @@ namespace { { push_path(toks, crate, {"fmt", "ArgumentV1", "new"}); toks.push_back( Token(TOK_PAREN_OPEN) ); - toks.push_back( Token(TOK_IDENT, FMT("a" << frag.arg_index)) ); + toks.push_back( ident(FMT("a" << frag.arg_index).c_str()) ); toks.push_back( TokenTree(TOK_COMMA) ); @@ -707,17 +710,17 @@ namespace { push_path(toks, crate, {"fmt", "rt", "v1", "Argument"}); toks.push_back( TokenTree(TOK_BRACE_OPEN) ); - push_toks(toks, Token(TOK_IDENT, "position"), TOK_COLON ); + push_toks(toks, ident("position"), TOK_COLON ); push_path(toks, crate, {"fmt", "rt", "v1", "Position", "Next"}); push_toks(toks, TOK_COMMA); - push_toks(toks, Token(TOK_IDENT, "format"), TOK_COLON ); + push_toks(toks, ident("format"), TOK_COLON ); push_path(toks, crate, {"fmt", "rt", "v1", "FormatSpec"}); toks.push_back( TokenTree(TOK_BRACE_OPEN) ); { - push_toks(toks, Token(TOK_IDENT, "fill"), TOK_COLON, Token(uint64_t(frag.args.align_char), CORETYPE_CHAR), TOK_COMMA ); + push_toks(toks, ident("fill"), TOK_COLON, Token(uint64_t(frag.args.align_char), CORETYPE_CHAR), TOK_COMMA ); - push_toks(toks, Token(TOK_IDENT, "align"), TOK_COLON); + push_toks(toks, ident("align"), TOK_COLON); const char* align_var_name = nullptr; switch( frag.args.align ) { @@ -729,19 +732,19 @@ namespace { push_path(toks, crate, {"fmt", "rt", "v1", "Alignment", align_var_name}); push_toks(toks, TOK_COMMA); - push_toks(toks, Token(TOK_IDENT, "flags"), TOK_COLON); + push_toks(toks, ident("flags"), TOK_COLON); uint64_t flags = 0; if(frag.args.alternate) flags |= 1 << 2; push_toks(toks, Token(uint64_t(flags), CORETYPE_U32)); push_toks(toks, TOK_COMMA); - push_toks(toks, Token(TOK_IDENT, "precision"), TOK_COLON ); + push_toks(toks, ident("precision"), TOK_COLON ); if( frag.args.prec_is_arg || frag.args.prec != 0 ) { push_path(toks, crate, {"fmt", "rt", "v1", "Count", "Is"}); push_toks(toks, TOK_PAREN_OPEN); if( frag.args.prec_is_arg ) { - push_toks(toks, TOK_STAR, Token(TOK_IDENT, FMT("a" << frag.args.prec)) ); + push_toks(toks, TOK_STAR, ident(FMT("a" << frag.args.prec).c_str()) ); } else { push_toks(toks, Token(uint64_t(frag.args.prec), CORETYPE_UINT) ); @@ -753,12 +756,12 @@ namespace { } toks.push_back( TokenTree(TOK_COMMA) ); - push_toks(toks, Token(TOK_IDENT, "width"), TOK_COLON ); + push_toks(toks, ident("width"), TOK_COLON ); if( frag.args.width_is_arg || frag.args.width != 0 ) { push_path(toks, crate, {"fmt", "rt", "v1", "Count", "Is"}); push_toks(toks, TOK_PAREN_OPEN); if( frag.args.width_is_arg ) { - push_toks(toks, TOK_STAR, Token(TOK_IDENT, FMT("a" << frag.args.width)) ); + push_toks(toks, TOK_STAR, ident(FMT("a" << frag.args.width).c_str()) ); } else { push_toks(toks, Token(uint64_t(frag.args.width), CORETYPE_UINT) ); @@ -791,14 +794,12 @@ namespace { class CFormatArgsExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { Token tok; auto lex = TTStream(sp, tt); lex.parse_state().module = &mod; - if( ident != "" ) - ERROR(sp, E0000, "format_args! doesn't take an ident"); return expand_format_args(sp, crate, lex, /*add_newline=*/false); } @@ -807,14 +808,12 @@ class CFormatArgsExpander: class CFormatArgsNlExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { Token tok; auto lex = TTStream(sp, tt); lex.parse_state().module = &mod; - if( ident != "" ) - ERROR(sp, E0000, "format_args_nl! doesn't take an ident"); return expand_format_args(sp, crate, lex, /*add_newline=*/true); } diff --git a/src/expand/include.cpp b/src/expand/include.cpp index 8078d5d0..14a7bc7b 100644 --- a/src/expand/include.cpp +++ b/src/expand/include.cpp @@ -64,11 +64,8 @@ namespace { class CIncludeExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - if( ident != "" ) - ERROR(sp, E0000, "include! doesn't take an ident"); - Token tok; auto lex = TTStream(sp, tt); @@ -91,11 +88,8 @@ class CIncludeExpander: class CIncludeBytesExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - if( ident != "" ) - ERROR(sp, E0000, "include_bytes! doesn't take an ident"); - Token tok; auto lex = TTStream(sp, tt); @@ -121,11 +115,8 @@ class CIncludeBytesExpander: class CIncludeStrExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - if( ident != "" ) - ERROR(sp, E0000, "include_str! doesn't take an ident"); - Token tok; auto lex = TTStream(sp, tt); diff --git a/src/expand/macro_rules.cpp b/src/expand/macro_rules.cpp index 3bacfcf7..88b7fc88 100644 --- a/src/expand/macro_rules.cpp +++ b/src/expand/macro_rules.cpp @@ -21,11 +21,12 @@ class CMacroRulesExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const ::AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override + { + ERROR(sp, E0000, "macro_rules! requires an identifier" ); + } + ::std::unique_ptr expand_ident(const Span& sp, const ::AST::Crate& crate, const RcString& ident, const TokenTree& tt, AST::Module& mod) override { - if( ident == "" ) - ERROR(sp, E0000, "macro_rules! requires an identifier" ); - DEBUG("Parsing macro_rules! " << ident); TTStream lex(sp, tt); auto mac = Parse_MacroRules(lex); @@ -48,7 +49,7 @@ class CMacroUseHandler: // Just ignore ) else TU_IFLET( ::AST::Item, i, Crate, ec_name, - const auto& ec = crate.m_extern_crates.at(ec_name.name); + const auto& ec = crate.m_extern_crates.at(ec_name.name.c_str()); if( mi.has_sub_items() ) { TODO(sp, "Named import from extern crate"); @@ -61,7 +62,7 @@ class CMacroUseHandler: }); for(const auto& p : ec.m_hir->m_proc_macros) { - mod.m_macro_imports.push_back({ false, p.path.m_components.back(), p.path.m_components, nullptr }); + mod.m_macro_imports.push_back(AST::Module::MacroImport{ false, p.path.m_components.back(), p.path.m_components, nullptr }); mod.m_macro_imports.back().path.insert( mod.m_macro_imports.back().path.begin(), p.path.m_crate_name ); } } @@ -153,7 +154,7 @@ class CMacroReexportHandler: } const auto& crate_name = i.as_Crate().name; - auto& ext_crate = *crate.m_extern_crates.at(crate_name).m_hir; + auto& ext_crate = *crate.m_extern_crates.at(crate_name.c_str()).m_hir; if( mi.has_sub_items() ) { diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index bc51e1ff..e3cef375 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -56,7 +56,7 @@ void ExpandDecorator::unexpected(const Span& sp, const AST::Attribute& mi, const void Expand_Attr(const Span& sp, const ::AST::Attribute& a, AttrStage stage, ::std::function f) { for( auto& d : g_decorators ) { - if( d.first == a.name() ) { + if( a.name() == d.first ) { DEBUG("#[" << d.first << "] " << (int)d.second->stage() << "-" << (int)stage); if( d.second->stage() == stage ) { f(sp, *d.second, a); @@ -94,7 +94,7 @@ void Expand_Attrs(::AST::AttributeList& attrs, AttrStage stage, ::AST::Crate& c ::std::unique_ptr Expand_Macro_Inner( const ::AST::Crate& crate, LList modstack, ::AST::Module& mod, - Span mi_span, const ::std::string& name, const ::std::string& input_ident, TokenTree& input_tt + Span mi_span, const RcString& name, const RcString& input_ident, TokenTree& input_tt ) { if( name == "" ) { @@ -105,7 +105,10 @@ void Expand_Attrs(::AST::AttributeList& attrs, AttrStage stage, ::AST::Crate& c { if( name == m.first ) { - auto e = m.second->expand(mi_span, crate, input_ident, input_tt, mod); + auto e = input_ident == "" + ? m.second->expand(mi_span, crate, input_tt, mod) + : m.second->expand_ident(mi_span, crate, input_ident, input_tt, mod) + ; return e; } } @@ -152,7 +155,7 @@ void Expand_Attrs(::AST::AttributeList& attrs, AttrStage stage, ::AST::Crate& c } ::std::unique_ptr Expand_Macro( const ::AST::Crate& crate, LList modstack, ::AST::Module& mod, - Span mi_span, const ::std::string& name, const ::std::string& input_ident, TokenTree& input_tt + Span mi_span, const RcString& name, const RcString& input_ident, TokenTree& input_tt ) { auto rv = Expand_Macro_Inner(crate, modstack, mod, mi_span, name, input_ident, input_tt); @@ -348,7 +351,7 @@ struct CExpandExpr: ::std::unique_ptr<::AST::ExprNode> replacement; // Stack of `try { ... }` blocks (the string is the loop label for the desugaring) - ::std::vector< ::std::string> m_try_stack; + ::std::vector m_try_stack; unsigned m_try_index = 0; AST::ExprNode_Block* current_block = nullptr; @@ -559,7 +562,7 @@ struct CExpandExpr: // } // ``` // NOTE: MIR lowering and HIR typecheck need to know to skip these (OR resolve should handle naming all loop blocks) - m_try_stack.push_back(FMT("#try" << m_try_index++)); + m_try_stack.push_back(RcString::new_interned(FMT("#try" << m_try_index++))); this->visit_nodelete(node, node.m_inner); auto loop_name = mv$(m_try_stack.back()); m_try_stack.pop_back(); @@ -858,7 +861,7 @@ struct CExpandExpr: nullptr, ::AST::ExprNodeP(new ::AST::ExprNode_Flow( (m_try_stack.empty() ? ::AST::ExprNode_Flow::RETURN : ::AST::ExprNode_Flow::BREAK), // NOTE: uses `break 'tryblock` instead of return if in a try block. - (m_try_stack.empty() ? "" : m_try_stack.back()), + (m_try_stack.empty() ? RcString("") : m_try_stack.back()), ::AST::ExprNodeP(new ::AST::ExprNode_CallPath( ::AST::Path(path_Try_from_error), ::make_vec1( @@ -1415,7 +1418,7 @@ void Expand(::AST::Crate& crate) for( auto& a : crate.m_attrs.m_items ) { for( auto& d : g_decorators ) { - if( d.first == a.name() && d.second->stage() == AttrStage::Pre ) { + if( a.name() == d.first && d.second->stage() == AttrStage::Pre ) { //d.second->handle(a, crate, ::AST::Path(), crate.m_root_module, crate.m_root_module); } } diff --git a/src/expand/proc_macro.cpp b/src/expand/proc_macro.cpp index f0f28f5a..24cd41d9 100644 --- a/src/expand/proc_macro.cpp +++ b/src/expand/proc_macro.cpp @@ -49,13 +49,13 @@ public: { if( attr.items()[i].name() == "attributes") { for(const auto& si : attr.items()[i].items()) { - attributes.push_back( si.name() ); + attributes.push_back( si.name().c_str() ); } } } // TODO: Store attributes for later use. - crate.m_proc_macros.push_back(AST::ProcMacroDef { FMT("derive#" << trait_name), path, mv$(attributes) }); + crate.m_proc_macros.push_back(AST::ProcMacroDef { RcString::new_interned(FMT("derive#" << trait_name)), path, mv$(attributes) }); } }; @@ -100,7 +100,7 @@ void Expand_ProcMacro(::AST::Crate& crate) { ::AST::ExprNode_StructLiteral::t_values desc_vals; // `name: "foo",` - desc_vals.push_back({ {}, "name", NEWNODE(_String, desc.name) }); + desc_vals.push_back({ {}, "name", NEWNODE(_String, desc.name.c_str()) }); // `handler`: ::foo desc_vals.push_back({ {}, "handler", NEWNODE(_NamedValue, AST::Path(desc.path)) }); @@ -211,7 +211,7 @@ public: void send_float(eCoreType ct, double v); //void send_fragment(); - bool attr_is_used(const ::std::string& n) const { + bool attr_is_used(const RcString& n) const { return ::std::find(m_proc_macro_desc.attributes.begin(), m_proc_macro_desc.attributes.end(), n) != m_proc_macro_desc.attributes.end(); } @@ -229,7 +229,7 @@ private: uint64_t recv_v128u(); }; -ProcMacroInv ProcMacro_Invoke_int(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path) +ProcMacroInv ProcMacro_Invoke_int(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path) { // 1. Locate macro in HIR list const auto& crate_name = mac_path.front(); @@ -745,7 +745,7 @@ namespace { } }; } -::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path, const ::std::string& item_name, const ::AST::Struct& i) +::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path, const ::std::string& item_name, const ::AST::Struct& i) { // 1. Create ProcMacroInv instance auto pmi = ProcMacro_Invoke_int(sp, crate, mac_path); @@ -757,7 +757,7 @@ namespace { // 3. Return boxed invocation instance return box$(pmi); } -::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path, const ::std::string& item_name, const ::AST::Enum& i) +::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path, const ::std::string& item_name, const ::AST::Enum& i) { // 1. Create ProcMacroInv instance auto pmi = ProcMacro_Invoke_int(sp, crate, mac_path); @@ -769,7 +769,7 @@ namespace { // 3. Return boxed invocation instance return box$(pmi); } -::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path, const ::std::string& item_name, const ::AST::Union& i) +::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path, const ::std::string& item_name, const ::AST::Union& i) { // 1. Create ProcMacroInv instance auto pmi = ProcMacro_Invoke_int(sp, crate, mac_path); diff --git a/src/expand/proc_macro.hpp b/src/expand/proc_macro.hpp index 8c5b71c7..e66bf037 100644 --- a/src/expand/proc_macro.hpp +++ b/src/expand/proc_macro.hpp @@ -8,8 +8,8 @@ #pragma once #include -extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path, const ::std::string& name, const ::AST::Struct& i); -extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path, const ::std::string& name, const ::AST::Enum& i); -extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path, const ::std::string& name, const ::AST::Union& i); -//extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector<::std::string>& mac_path, const TokenStream& tt); +extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path, const ::std::string& name, const ::AST::Struct& i); +extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path, const ::std::string& name, const ::AST::Enum& i); +extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path, const ::std::string& name, const ::AST::Union& i); +//extern ::std::unique_ptr ProcMacro_Invoke(const Span& sp, const ::AST::Crate& crate, const ::std::vector& mac_path, const TokenStream& tt); diff --git a/src/expand/rustc_diagnostics.cpp b/src/expand/rustc_diagnostics.cpp index 0e95bb7c..b36bf586 100644 --- a/src/expand/rustc_diagnostics.cpp +++ b/src/expand/rustc_diagnostics.cpp @@ -13,7 +13,7 @@ class CExpanderRegisterDiagnostic: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { return box$( TTStreamO(sp, TokenTree()) ); } @@ -21,7 +21,7 @@ class CExpanderRegisterDiagnostic: class CExpanderDiagnosticUsed: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { return box$( TTStreamO(sp, TokenTree()) ); } @@ -29,10 +29,8 @@ class CExpanderDiagnosticUsed: class CExpanderBuildDiagnosticArray: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { - if( ident != "" ) - ERROR(sp, E0000, "__build_diagnostic_array! doesn't take an ident"); auto lex = TTStream(sp, tt); Token tok; @@ -41,7 +39,7 @@ class CExpanderBuildDiagnosticArray: //auto crate_name = mv$(tok.str()); GET_CHECK_TOK(tok, lex, TOK_COMMA); GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto item_name = mv$(tok.str()); + auto item_name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_EOF); ::std::vector toks; @@ -51,9 +49,9 @@ class CExpanderBuildDiagnosticArray: toks.push_back( TOK_COLON ); toks.push_back( TOK_SQUARE_OPEN ); toks.push_back( TOK_PAREN_OPEN ); - toks.push_back( TOK_AMP ); toks.push_back( Token(TOK_LIFETIME, "static") ); toks.push_back( Token(TOK_IDENT, "str") ); + toks.push_back( TOK_AMP ); toks.push_back( Token(TOK_LIFETIME, RcString::new_interned("static")) ); toks.push_back( Token(TOK_IDENT, RcString::new_interned("str")) ); toks.push_back( TOK_COMMA ); - toks.push_back( TOK_AMP ); toks.push_back( Token(TOK_LIFETIME, "static") ); toks.push_back( Token(TOK_IDENT, "str") ); + toks.push_back( TOK_AMP ); toks.push_back( Token(TOK_LIFETIME, RcString::new_interned("static")) ); toks.push_back( Token(TOK_IDENT, RcString::new_interned("str")) ); toks.push_back( TOK_PAREN_CLOSE ); toks.push_back( TOK_SEMICOLON ); toks.push_back( Token(static_cast(0), CORETYPE_UINT) ); diff --git a/src/expand/stringify.cpp b/src/expand/stringify.cpp index f552ffd4..561177ef 100644 --- a/src/expand/stringify.cpp +++ b/src/expand/stringify.cpp @@ -12,7 +12,7 @@ class CExpander: public ExpandProcMacro { - ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) override { Token tok; ::std::string rv; diff --git a/src/expand/test.cpp b/src/expand/test.cpp index 9497c692..ac536228 100644 --- a/src/expand/test.cpp +++ b/src/expand/test.cpp @@ -25,7 +25,7 @@ class CTestHandler: for(const auto& node : path.nodes()) { td.name += "::"; - td.name += node.name(); + td.name += node.name().c_str(); } td.path = ::AST::Path(path); diff --git a/src/expand/test_harness.cpp b/src/expand/test_harness.cpp index f720cac7..36b60632 100644 --- a/src/expand/test_harness.cpp +++ b/src/expand/test_harness.cpp @@ -89,10 +89,10 @@ void Expand_TestHarness(::AST::Crate& crate) auto desc_expr = NEWNODE(_StructLiteral, ::AST::Path("test", { ::AST::PathNode("TestDesc")}), nullptr, mv$(desc_vals)); ::AST::ExprNode_StructLiteral::t_values descandfn_vals; - descandfn_vals.push_back({ {}, ::std::string("desc"), mv$(desc_expr) }); + descandfn_vals.push_back({ {}, RcString::new_interned("desc"), mv$(desc_expr) }); auto test_type_var_name = test.is_benchmark ? "StaticBenchFn" : "StaticTestFn"; - descandfn_vals.push_back({ {}, ::std::string("testfn"), NEWNODE(_CallPath, + descandfn_vals.push_back({ {}, RcString::new_interned("testfn"), NEWNODE(_CallPath, ::AST::Path("test", { ::AST::PathNode(test_type_var_name) }), ::make_vec1( NEWNODE(_NamedValue, AST::Path(test.path)) ) ) }); diff --git a/src/hir/crate_post_load.cpp b/src/hir/crate_post_load.cpp index 81c5b029..a0733987 100644 --- a/src/hir/crate_post_load.cpp +++ b/src/hir/crate_post_load.cpp @@ -9,7 +9,7 @@ #include // Used to update the crate name -void HIR::Crate::post_load_update(const ::std::string& name) +void HIR::Crate::post_load_update(const RcString& name) { // TODO: Do a pass across m_hir that // 1. Updates all absolute paths with the crate name diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index c5350b55..56671a04 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -22,13 +22,14 @@ class HirDeserialiser { - ::std::string m_crate_name; + RcString m_crate_name; ::HIR::serialise::Reader& m_in; public: HirDeserialiser(::HIR::serialise::Reader& in): m_in(in) {} + RcString read_istring() { return m_in.read_istring(); } ::std::string read_string() { return m_in.read_string(); } bool read_bool() { return m_in.read_bool(); } size_t deserialise_count() { return m_in.read_count(); } @@ -78,6 +79,51 @@ return rv; } + template + ::std::map< RcString,V> deserialise_istrmap() + { + TRACE_FUNCTION_F("<" << typeid(V).name() << ">"); + size_t n = m_in.read_count(); + ::std::map< RcString, V> rv; + //rv.reserve(n); + for(size_t i = 0; i < n; i ++) + { + auto s = m_in.read_istring(); + rv.insert( ::std::make_pair( mv$(s), D::des(*this) ) ); + } + return rv; + } + template + ::std::unordered_map< RcString,V> deserialise_istrumap() + { + TRACE_FUNCTION_F("<" << typeid(V).name() << ">"); + size_t n = m_in.read_count(); + ::std::unordered_map rv; + //rv.reserve(n); + for(size_t i = 0; i < n; i ++) + { + auto s = m_in.read_istring(); + DEBUG("- " << s); + rv.insert( ::std::make_pair( mv$(s), D::des(*this) ) ); + } + return rv; + } + template + ::std::unordered_multimap deserialise_istrummap() + { + TRACE_FUNCTION_F("<" << typeid(V).name() << ">"); + size_t n = m_in.read_count(); + ::std::unordered_multimap rv; + //rv.reserve(n); + for(size_t i = 0; i < n; i ++) + { + auto s = m_in.read_istring(); + DEBUG("- " << s); + rv.insert( ::std::make_pair( mv$(s), D::des(*this) ) ); + } + return rv; + } + template ::std::vector deserialise_vec() { @@ -117,6 +163,7 @@ } + ::HIR::LifetimeDef deserialise_lifetimedef(); ::HIR::LifetimeRef deserialise_lifetimeref(); ::HIR::TypeRef deserialise_type(); ::HIR::SimplePath deserialise_simplepath(); @@ -137,7 +184,7 @@ { ::HIR::ProcMacro pm; TRACE_FUNCTION_FR("", "ProcMacro { " << pm.name << ", " << pm.path << ", [" << pm.attributes << "]}"); - pm.name = m_in.read_string(); + pm.name = m_in.read_istring(); pm.path = deserialise_simplepath(); pm.attributes = deserialise_vec< ::std::string>(); DEBUG("pm = ProcMacro { " << pm.name << ", " << pm.path << ", [" << pm.attributes << "]}"); @@ -155,7 +202,7 @@ size_t method_count = m_in.read_count(); for(size_t i = 0; i < method_count; i ++) { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); rv.m_methods.insert( ::std::make_pair( mv$(name), ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { deserialise_pub(), m_in.read_bool(), deserialise_function() } ) ); @@ -163,7 +210,7 @@ size_t const_count = m_in.read_count(); for(size_t i = 0; i < const_count; i ++) { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); rv.m_constants.insert( ::std::make_pair( mv$(name), ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> { deserialise_pub(), m_in.read_bool(), deserialise_constant() } ) ); @@ -184,7 +231,7 @@ size_t method_count = m_in.read_count(); for(size_t i = 0; i < method_count; i ++) { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); auto is_spec = m_in.read_bool(); rv.m_methods.insert( ::std::make_pair( mv$(name), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { is_spec, deserialise_function() @@ -193,7 +240,7 @@ size_t const_count = m_in.read_count(); for(size_t i = 0; i < const_count; i ++) { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); auto is_spec = m_in.read_bool(); rv.m_constants.insert( ::std::make_pair( mv$(name), ::HIR::TraitImpl::ImplEnt< ::HIR::Constant> { is_spec, deserialise_constant() @@ -202,7 +249,7 @@ size_t static_count = m_in.read_count(); for(size_t i = 0; i < static_count; i ++) { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); auto is_spec = m_in.read_bool(); rv.m_statics.insert( ::std::make_pair( mv$(name), ::HIR::TraitImpl::ImplEnt< ::HIR::Static> { is_spec, deserialise_static() @@ -211,7 +258,7 @@ size_t type_count = m_in.read_count(); for(size_t i = 0; i < type_count; i ++) { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); auto is_spec = m_in.read_bool(); rv.m_types.insert( ::std::make_pair( mv$(name), ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> { is_spec, deserialise_type() @@ -240,10 +287,10 @@ // NOTE: This is set after loading. //rv.m_exported = true; rv.m_rules = deserialise_vec_c< ::MacroRulesArm>( [&](){ return deserialise_macrorulesarm(); }); - rv.m_source_crate = m_in.read_string(); + rv.m_source_crate = m_in.read_istring(); if(rv.m_source_crate == "") { - assert(!m_crate_name.empty()); + assert(m_crate_name != ""); rv.m_source_crate = m_crate_name; } return rv; @@ -288,7 +335,7 @@ } } ::MacroPatEnt deserialise_macropatent() { - auto s = m_in.read_string(); + auto s = m_in.read_istring(); auto n = static_cast(m_in.read_count()); auto type = static_cast< ::MacroPatEnt::Type>(m_in.read_tag()); ::MacroPatEnt rv { mv$(s), mv$(n), mv$(type) }; @@ -320,7 +367,7 @@ } ::MacroRulesArm deserialise_macrorulesarm() { ::MacroRulesArm rv; - rv.m_param_names = deserialise_vec< ::std::string>(); + rv.m_param_names = deserialise_vec(); rv.m_pattern = deserialise_vec_c< ::SimplePatEnt>( [&](){ return deserialise_simplepatent(); } ); rv.m_contents = deserialise_vec_c< ::MacroExpansionEnt>( [&](){ return deserialise_macroexpansionent(); } ); return rv; @@ -366,6 +413,8 @@ return ::Token::Data::make_None({}); case ::Token::Data::TAG_String: return ::Token::Data::make_String( m_in.read_string() ); + case ::Token::Data::TAG_IString: + return ::Token::Data::make_IString( m_in.read_istring() ); case ::Token::Data::TAG_Integer: { auto dty = static_cast(m_in.read_tag()); return ::Token::Data::make_Integer({ dty, m_in.read_u64c() }); @@ -723,7 +772,7 @@ { return ::HIR::AssociatedType { m_in.read_bool(), - "", // TODO: Better lifetime type + deserialise_lifetimeref(), deserialise_vec< ::HIR::TraitPath>(), deserialise_type() }; @@ -737,6 +786,9 @@ DEF_D( ::std::string, return d.read_string(); ); template<> + DEF_D( RcString, + return d.read_istring(); ); + template<> DEF_D( bool, return d.read_bool(); ); @@ -754,6 +806,8 @@ DEF_D( ::HIR::VisEnt, return d.deserialise_visent(); ) + template<> DEF_D( ::HIR::LifetimeDef, return d.deserialise_lifetimedef(); ) + template<> DEF_D( ::HIR::LifetimeRef, return d.deserialise_lifetimeref(); ) template<> DEF_D( ::HIR::TypeRef, return d.deserialise_type(); ) template<> DEF_D( ::HIR::SimplePath, return d.deserialise_simplepath(); ) template<> DEF_D( ::HIR::GenericPath, return d.deserialise_genericpath(); ) @@ -784,6 +838,12 @@ template<> DEF_D( ::HIR::ExternLibrary, return d.deserialise_extlib(); ) + ::HIR::LifetimeDef HirDeserialiser::deserialise_lifetimedef() + { + ::HIR::LifetimeDef rv; + rv.m_name = m_in.read_istring(); + return rv; + } ::HIR::LifetimeRef HirDeserialiser::deserialise_lifetimeref() { ::HIR::LifetimeRef rv; @@ -808,7 +868,7 @@ {} }) _(Generic, { - m_in.read_string(), + m_in.read_istring(), m_in.read_u16() }) _(TraitObject, { @@ -859,11 +919,11 @@ { TRACE_FUNCTION; // HACK! If the read crate name is empty, replace it with the name we're loaded with - auto crate_name = m_in.read_string(); - auto components = deserialise_vec< ::std::string>(); + auto crate_name = m_in.read_istring(); + auto components = deserialise_vec< RcString>(); if( crate_name == "" && components.size() > 0) { - assert(!m_crate_name.empty()); + assert(m_crate_name != ""); crate_name = m_crate_name; } return ::HIR::SimplePath { @@ -889,7 +949,7 @@ ::HIR::TraitPath HirDeserialiser::deserialise_traitpath() { auto gpath = deserialise_genericpath(); - auto tys = deserialise_strmap< ::HIR::TypeRef>(); + auto tys = deserialise_istrmap< ::HIR::TypeRef>(); return ::HIR::TraitPath { mv$(gpath), {}, mv$(tys) }; } ::HIR::Path HirDeserialiser::deserialise_path() @@ -904,7 +964,7 @@ DEBUG("Inherent"); return ::HIR::Path( ::HIR::Path::Data::Data_UfcsInherent { box$( deserialise_type() ), - m_in.read_string(), + m_in.read_istring(), deserialise_pathparams(), deserialise_pathparams() } ); @@ -913,7 +973,7 @@ return ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown { box$( deserialise_type() ), deserialise_genericpath(), - m_in.read_string(), + m_in.read_istring(), deserialise_pathparams() } ); default: @@ -926,7 +986,7 @@ TRACE_FUNCTION; ::HIR::GenericParams params; params.m_types = deserialise_vec< ::HIR::TypeParamDef>(); - params.m_lifetimes = deserialise_vec< ::std::string>(); + params.m_lifetimes = deserialise_vec< ::HIR::LifetimeDef>(); params.m_bounds = deserialise_vec< ::HIR::GenericBound>(); DEBUG("params = " << params.fmt_args() << ", " << params.fmt_bounds()); return params; @@ -934,7 +994,7 @@ ::HIR::TypeParamDef HirDeserialiser::deserialise_typaramdef() { auto rv = ::HIR::TypeParamDef { - m_in.read_string(), + m_in.read_istring(), deserialise_type(), m_in.read_bool() }; @@ -991,7 +1051,7 @@ } ::HIR::Enum::DataVariant HirDeserialiser::deserialise_enumdatavariant() { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); DEBUG("Enum::DataVariant " << name); return ::HIR::Enum::DataVariant { mv$(name), @@ -1001,7 +1061,7 @@ } ::HIR::Enum::ValueVariant HirDeserialiser::deserialise_enumvaluevariant() { - auto name = m_in.read_string(); + auto name = m_in.read_istring(); DEBUG("Enum::ValueVariant " << name); return ::HIR::Enum::ValueVariant { mv$(name), @@ -1014,7 +1074,7 @@ TRACE_FUNCTION; auto params = deserialise_genericparams(); auto repr = static_cast< ::HIR::Union::Repr>( m_in.read_tag() ); - auto variants = deserialise_vec< ::std::pair< ::std::string, ::HIR::VisEnt< ::HIR::TypeRef> > >(); + auto variants = deserialise_vec< ::std::pair< RcString, ::HIR::VisEnt< ::HIR::TypeRef> > >(); auto markings = deserialise_markings(); return ::HIR::Union { @@ -1041,7 +1101,7 @@ break; case ::HIR::Struct::Data::TAG_Named: DEBUG("Named"); - data = ::HIR::Struct::Data( deserialise_vec< ::std::pair< ::std::string, ::HIR::VisEnt< ::HIR::TypeRef> > >() ); + data = ::HIR::Struct::Data( deserialise_vec< ::std::pair< RcString, ::HIR::VisEnt< ::HIR::TypeRef> > >() ); break; default: BUG(Span(), "Bad tag for HIR::Struct::Data - " << tag); @@ -1061,15 +1121,16 @@ ::HIR::Trait rv { deserialise_genericparams(), - "", // TODO: Better type for lifetime + ::HIR::LifetimeRef(), // TODO: Better type for lifetime {} }; rv.m_is_marker = m_in.read_bool(); - rv.m_types = deserialise_strumap< ::HIR::AssociatedType>(); - rv.m_values = deserialise_strumap< ::HIR::TraitValueItem>(); - rv.m_value_indexes = deserialise_strummap< ::std::pair >(); - rv.m_type_indexes = deserialise_strumap< unsigned int>(); + rv.m_types = deserialise_istrumap< ::HIR::AssociatedType>(); + rv.m_values = deserialise_istrumap< ::HIR::TraitValueItem>(); + rv.m_value_indexes = deserialise_istrummap< ::std::pair >(); + rv.m_type_indexes = deserialise_istrumap< unsigned int>(); rv.m_all_parent_traits = deserialise_vec< ::HIR::TraitPath>(); + rv.m_vtable_path = deserialise_simplepath(); return rv; } @@ -1225,7 +1286,7 @@ _(Value, deserialise_mir_lvalue() ) _(Path, deserialise_path() ) _(Intrinsic, { - m_in.read_string(), + m_in.read_istring(), deserialise_pathparams() }) #undef _ @@ -1241,8 +1302,8 @@ ::HIR::Module rv; // m_traits doesn't need to be serialised - rv.m_value_items = deserialise_strumap< ::std::unique_ptr< ::HIR::VisEnt< ::HIR::ValueItem> > >(); - rv.m_mod_items = deserialise_strumap< ::std::unique_ptr< ::HIR::VisEnt< ::HIR::TypeItem> > >(); + rv.m_value_items = deserialise_istrumap< ::std::unique_ptr< ::HIR::VisEnt< ::HIR::ValueItem> > >(); + rv.m_mod_items = deserialise_istrumap< ::std::unique_ptr< ::HIR::VisEnt< ::HIR::TypeItem> > >(); return rv; } @@ -1256,8 +1317,8 @@ { ::HIR::Crate rv; - this->m_crate_name = m_in.read_string(); - assert(!this->m_crate_name.empty() && "Empty crate name loaded from metadata"); + this->m_crate_name = m_in.read_istring(); + assert(this->m_crate_name != "" && "Empty crate name loaded from metadata"); rv.m_crate_name = this->m_crate_name; rv.m_root_module = deserialise_module(); @@ -1280,14 +1341,14 @@ } } - rv.m_exported_macros = deserialise_strumap< ::MacroRulesPtr>(); + rv.m_exported_macros = deserialise_istrumap< ::MacroRulesPtr>(); rv.m_lang_items = deserialise_strumap< ::HIR::SimplePath>(); { size_t n = m_in.read_count(); for(size_t i = 0; i < n; i ++) { - auto ext_crate_name = m_in.read_string(); + auto ext_crate_name = m_in.read_istring(); auto ext_crate_file = m_in.read_string(); auto ext_crate = ::HIR::ExternCrate {}; ext_crate.m_basename = ext_crate_file; @@ -1304,7 +1365,7 @@ } //} -::HIR::CratePtr HIR_Deserialise(const ::std::string& filename, const ::std::string& loaded_name) +::HIR::CratePtr HIR_Deserialise(const ::std::string& filename) { try { diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 140ba817..d099ecb4 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -133,11 +133,11 @@ struct ExprNode_Return: struct ExprNode_Loop: public ExprNode { - ::std::string m_label; + RcString m_label; ::HIR::ExprNodeP m_code; bool m_diverges = false; - ExprNode_Loop(Span sp, ::std::string label, ::HIR::ExprNodeP code): + ExprNode_Loop(Span sp, RcString label, ::HIR::ExprNodeP code): //ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()), ExprNode(mv$(sp), ::HIR::TypeRef()), m_label( mv$(label) ), @@ -149,11 +149,11 @@ struct ExprNode_Loop: struct ExprNode_LoopControl: public ExprNode { - ::std::string m_label; + RcString m_label; bool m_continue; ::HIR::ExprNodeP m_value; - ExprNode_LoopControl(Span sp, ::std::string label, bool cont, ::HIR::ExprNodeP value={}): + ExprNode_LoopControl(Span sp, RcString label, bool cont, ::HIR::ExprNodeP value={}): ExprNode(mv$(sp), ::HIR::TypeRef::new_diverge()), m_label( mv$(label) ), m_continue( cont ), @@ -539,7 +539,7 @@ struct ExprNode_CallMethod: public ExprNode { ::HIR::ExprNodeP m_value; - ::std::string m_method; + RcString m_method; ::HIR::PathParams m_params; ::std::vector< ::HIR::ExprNodeP> m_args; @@ -553,7 +553,7 @@ struct ExprNode_CallMethod: // - A pool of ivars to use for searching for trait impls ::std::vector m_trait_param_ivars; - ExprNode_CallMethod(Span sp, ::HIR::ExprNodeP val, ::std::string method_name, ::HIR::PathParams params, ::std::vector< ::HIR::ExprNodeP> args): + ExprNode_CallMethod(Span sp, ::HIR::ExprNodeP val, RcString method_name, ::HIR::PathParams params, ::std::vector< ::HIR::ExprNodeP> args): ExprNode( mv$(sp) ), m_value( mv$(val) ), m_method( mv$(method_name) ), @@ -570,9 +570,9 @@ struct ExprNode_Field: public ExprNode { ::HIR::ExprNodeP m_value; - ::std::string m_field; + RcString m_field; - ExprNode_Field(Span sp, ::HIR::ExprNodeP val, ::std::string field): + ExprNode_Field(Span sp, ::HIR::ExprNodeP val, RcString field): ExprNode(mv$(sp)), m_value( mv$(val) ), m_field( mv$(field) ) @@ -677,10 +677,10 @@ struct ExprNode_PathValue: struct ExprNode_Variable: public ExprNode { - ::std::string m_name; + RcString m_name; unsigned int m_slot; - ExprNode_Variable(Span sp, ::std::string name, unsigned int slot): + ExprNode_Variable(Span sp, RcString name, unsigned int slot): ExprNode(mv$(sp)), m_name( mv$(name) ), m_slot( slot ) @@ -692,7 +692,7 @@ struct ExprNode_Variable: struct ExprNode_StructLiteral: public ExprNode { - typedef ::std::vector< ::std::pair< ::std::string, ExprNodeP > > t_values; + typedef ::std::vector< ::std::pair< RcString, ExprNodeP > > t_values; ::HIR::Path m_path; bool m_is_struct; @@ -719,12 +719,12 @@ struct ExprNode_UnionLiteral: public ExprNode { ::HIR::GenericPath m_path; - ::std::string m_variant_name; + RcString m_variant_name; ::HIR::ExprNodeP m_value; unsigned int m_variant_index = ~0; - ExprNode_UnionLiteral(Span sp, ::HIR::GenericPath path, ::std::string name, ::HIR::ExprNodeP value): + ExprNode_UnionLiteral(Span sp, ::HIR::GenericPath path, RcString name, ::HIR::ExprNodeP value): ExprNode( mv$(sp) ), m_path( mv$(path) ), m_variant_name( mv$(name) ), diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 2393cadd..84980818 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -23,15 +23,18 @@ ::HIR::TraitPath LowerHIR_TraitPath(const Span& sp, const ::AST::Path& path); ::HIR::SimplePath path_Sized; -::std::string g_core_crate; -::std::string g_crate_name; +RcString g_core_crate; +RcString g_crate_name; ::HIR::Crate* g_crate_ptr = nullptr; const ::AST::Crate* g_ast_crate_ptr; // -------------------------------------------------------------------- -::std::string LowerHIR_LifetimeRef(const ::AST::LifetimeRef& r) +HIR::LifetimeRef LowerHIR_LifetimeRef(const ::AST::LifetimeRef& r) { - return r.name().name; + return HIR::LifetimeRef { + // TODO: names? + r.binding() + }; } ::HIR::GenericParams LowerHIR_GenericParams(const ::AST::GenericParams& gp, bool* self_is_sized) @@ -48,7 +51,7 @@ const ::AST::Crate* g_ast_crate_ptr; if( gp.lft_params().size() > 0 ) { for(const auto& lft_def : gp.lft_params()) - rv.m_lifetimes.push_back( lft_def.name().name ); + rv.m_lifetimes.push_back( HIR::LifetimeDef { lft_def.name().name } ); } if( gp.bounds().size() > 0 ) { @@ -316,7 +319,7 @@ const ::AST::Crate* g_ast_crate_ptr; } } TU_ARMA(Struct, e) { - ::std::vector< ::std::pair< ::std::string, ::HIR::Pattern> > sub_patterns; + ::std::vector< ::std::pair< RcString, ::HIR::Pattern> > sub_patterns; for(const auto& sp : e.sub_patterns) sub_patterns.push_back( ::std::make_pair(sp.first, LowerHIR_Pattern(sp.second)) ); @@ -968,7 +971,7 @@ namespace { return rv; } -::HIR::Enum LowerHIR_Enum(::HIR::ItemPath path, const ::AST::Enum& ent, const ::AST::AttributeList& attrs, ::std::function push_struct) +::HIR::Enum LowerHIR_Enum(::HIR::ItemPath path, const ::AST::Enum& ent, const ::AST::AttributeList& attrs, ::std::function push_struct) { // 1. Figure out what sort of enum this is (value or data) bool has_value = false; @@ -1081,7 +1084,7 @@ namespace { throw ""; } - auto ty_name = FMT(path.name << "#" << var.m_name); + auto ty_name = RcString::new_interned(FMT(path.name << "#" << var.m_name)); push_struct( ty_name, ::HIR::Struct { @@ -1156,14 +1159,14 @@ namespace { bool trait_reqires_sized = false; auto params = LowerHIR_GenericParams(f.params(), &trait_reqires_sized); - ::std::string lifetime; + ::HIR::LifetimeRef lifetime; ::std::vector< ::HIR::TraitPath> supertraits; for(const auto& st : f.supertraits()) { if( st.ent.path.is_valid() ) { supertraits.push_back( LowerHIR_TraitPath(st.sp, st.ent.path) ); } else { - lifetime = "static"; + lifetime = ::HIR::LifetimeRef::new_static(); } } ::HIR::Trait rv { @@ -1201,7 +1204,7 @@ namespace { (Type, bool is_sized = true; ::std::vector< ::HIR::TraitPath> trait_bounds; - ::std::string lifetime_bound; + ::HIR::LifetimeRef lifetime_bound; auto gps = LowerHIR_GenericParams(i.params(), &is_sized); for(auto& b : gps.m_bounds) @@ -1385,10 +1388,10 @@ namespace { }; } -void _add_mod_ns_item(::HIR::Module& mod, ::std::string name, ::HIR::Publicity is_pub, ::HIR::TypeItem ti) { +void _add_mod_ns_item(::HIR::Module& mod, RcString name, ::HIR::Publicity is_pub, ::HIR::TypeItem ti) { mod.m_mod_items.insert( ::std::make_pair( mv$(name), ::make_unique_ptr(::HIR::VisEnt< ::HIR::TypeItem> { is_pub, mv$(ti) }) ) ); } -void _add_mod_val_item(::HIR::Module& mod, ::std::string name, ::HIR::Publicity is_pub, ::HIR::ValueItem ti) { +void _add_mod_val_item(::HIR::Module& mod, RcString name, ::HIR::Publicity is_pub, ::HIR::ValueItem ti) { mod.m_value_items.insert( ::std::make_pair( mv$(name), ::make_unique_ptr(::HIR::VisEnt< ::HIR::ValueItem> { is_pub, mv$(ti) }) ) ); } @@ -1418,7 +1421,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, ::HIR::Publicity if( submod_ptr ) { auto& submod = *submod_ptr; - ::std::string name = FMT("#" << i); + auto name = RcString::new_interned(FMT("#" << i)); auto item_path = ::HIR::ItemPath(path, name.c_str()); auto ti = ::HIR::TypeItem::make_Module( LowerHIR_Module(submod, item_path, mod.m_traits) ); _add_mod_ns_item( mod, mv$(name), get_pub(false), mv$(ti) ); @@ -1534,7 +1537,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, ::HIR::Publicity // If there's no code, demangle the name (TODO: By ABI) and set linkage. if( linkage.name == "" && ! e.value().is_valid() ) { - linkage.name = item.name; + linkage.name = item.name.c_str(); } _add_mod_val_item(mod, item.name, get_pub(item.is_pub), ::HIR::ValueItem::make_Static(::HIR::Static { @@ -1633,9 +1636,9 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat ::HIR::ItemPath path(type, trait_name, trait_args); DEBUG(path); - ::std::map< ::std::string, ::HIR::TraitImpl::ImplEnt< ::HIR::Function> > methods; - ::std::map< ::std::string, ::HIR::TraitImpl::ImplEnt< ::HIR::Constant> > constants; - ::std::map< ::std::string, ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> > types; + ::std::map< RcString, ::HIR::TraitImpl::ImplEnt< ::HIR::Function> > methods; + ::std::map< RcString, ::HIR::TraitImpl::ImplEnt< ::HIR::Constant> > constants; + ::std::map< RcString, ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> > types; for(const auto& item : impl.items()) { @@ -1711,8 +1714,8 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat auto priv_path = ::HIR::Publicity::new_priv( LowerHIR_SimplePath(Span(), ast_mod.path()) ); // TODO: Does this need to consume anon modules? auto get_pub = [&](bool is_pub){ return is_pub ? ::HIR::Publicity::new_global() : priv_path; }; - ::std::map< ::std::string, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> > methods; - ::std::map< ::std::string, ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> > constants; + ::std::map< RcString, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> > methods; + ::std::map< RcString, ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> > constants; for(const auto& item : impl.items()) { @@ -1809,18 +1812,20 @@ public: if(crate.m_crate_type != ::AST::Crate::Type::Executable) { - rv.m_crate_name = crate.m_crate_name; if(crate.m_crate_name_suffix != "") { - rv.m_crate_name += "-"; - rv.m_crate_name += crate.m_crate_name_suffix; + rv.m_crate_name = RcString::new_interned(FMT(crate.m_crate_name + "-" + crate.m_crate_name_suffix)); + } + else + { + rv.m_crate_name = RcString::new_interned(crate.m_crate_name); } } g_crate_ptr = &rv; g_ast_crate_ptr = &crate; g_crate_name = rv.m_crate_name; - g_core_crate = (crate.m_load_std == ::AST::Crate::LOAD_NONE ? rv.m_crate_name : "core"); + g_core_crate = (crate.m_load_std == ::AST::Crate::LOAD_NONE ? rv.m_crate_name : RcString::new_interned("core")); auto& macros = rv.m_exported_macros; // - Extract exported macros @@ -1896,7 +1901,7 @@ public: for(const auto& ent : crate.m_proc_macros) { // Register under an invalid simplepath - rv.m_proc_macros.push_back( ::HIR::ProcMacro { ent.name, ::HIR::SimplePath("", { ent.name}), ent.attributes } ); + rv.m_proc_macros.push_back( ::HIR::ProcMacro { ent.name, ::HIR::SimplePath(RcString(""), { ent.name }), ent.attributes } ); } } else diff --git a/src/hir/from_ast.hpp b/src/hir/from_ast.hpp index 4625f479..3eeaaa48 100644 --- a/src/hir/from_ast.hpp +++ b/src/hir/from_ast.hpp @@ -16,5 +16,5 @@ extern ::HIR::SimplePath LowerHIR_SimplePath(const Span& sp, const ::AST::Pat extern ::HIR::TypeRef LowerHIR_Type(const ::TypeRef& ty); extern ::HIR::Pattern LowerHIR_Pattern(const ::AST::Pattern& pat); -extern ::std::string g_core_crate; +extern RcString g_core_crate; extern ::HIR::Crate* g_crate_ptr; diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index fdb2b867..baca8d75 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -332,16 +332,16 @@ struct LowerHIR_ExprNode_Visitor: break; } - // TODO: Iterate the constructed loop and determine if there are any `break` statements pointing to it + // Iterate the constructed loop and determine if there are any `break` statements pointing to it { struct LoopVisitor: public ::HIR::ExprVisitorDef { - const ::std::string& top_label; + const RcString& top_label; bool top_is_broken; - ::std::vector< const ::std::string*> name_stack; + ::std::vector< const RcString*> name_stack; - LoopVisitor(const ::std::string& top_label): + LoopVisitor(const RcString& top_label): top_label(top_label), top_is_broken(false), name_stack() diff --git a/src/hir/generic_params.cpp b/src/hir/generic_params.cpp index 381277fc..3f6559a7 100644 --- a/src/hir/generic_params.cpp +++ b/src/hir/generic_params.cpp @@ -33,7 +33,7 @@ namespace HIR { { os << "<"; for(const auto& lft : x.gp.m_lifetimes) { - os << "'" << lft << ","; + os << "'" << lft.m_name << ","; } for(const auto& typ : x.gp.m_types) { os << typ.m_name; diff --git a/src/hir/generic_params.hpp b/src/hir/generic_params.hpp index ef83bda7..afa1c682 100644 --- a/src/hir/generic_params.hpp +++ b/src/hir/generic_params.hpp @@ -15,19 +15,23 @@ namespace HIR { struct TypeParamDef { - ::std::string m_name; + RcString m_name; ::HIR::TypeRef m_default; bool m_is_sized; }; +struct LifetimeDef +{ + RcString m_name; +}; TAGGED_UNION(GenericBound, Lifetime, (Lifetime, struct { - ::std::string test; - ::std::string valid_for; + LifetimeRef test; + LifetimeRef valid_for; }), (TypeLifetime, struct { ::HIR::TypeRef type; - ::std::string valid_for; + LifetimeRef valid_for; }), (TraitBound, struct { ::HIR::TypeRef type; @@ -47,8 +51,8 @@ extern ::std::ostream& operator<<(::std::ostream& os, const GenericBound& x); class GenericParams { public: - ::std::vector m_types; - ::std::vector< ::std::string> m_lifetimes; + ::std::vector m_types; + ::std::vector m_lifetimes; ::std::vector m_bounds; diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 2a8ac8bf..88b1cb8c 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -149,7 +149,7 @@ bool HIR::Publicity::is_visible(const ::HIR::SimplePath& p) const return true; } -size_t HIR::Enum::find_variant(const ::std::string& name) const +size_t HIR::Enum::find_variant(const RcString& name) const { if( m_data.is_Value() ) { diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index cc66a9e7..3f045dd2 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -192,7 +192,7 @@ struct TypeAlias }; typedef ::std::vector< VisEnt<::HIR::TypeRef> > t_tuple_fields; -typedef ::std::vector< ::std::pair< ::std::string, VisEnt<::HIR::TypeRef> > > t_struct_fields; +typedef ::std::vector< ::std::pair< RcString, VisEnt<::HIR::TypeRef> > > t_struct_fields; /// Cache of the state of various language traits on an enum/struct struct TraitMarkings @@ -258,7 +258,7 @@ class Enum { public: struct DataVariant { - ::std::string name; + RcString name; bool is_struct; // Indicates that the variant does not show up in the value namespace ::HIR::TypeRef type; }; @@ -269,7 +269,7 @@ public: Usize, U8, U16, U32, U64, }; struct ValueVariant { - ::std::string name; + RcString name; ::HIR::ExprPtr expr; // TODO: Signed. uint64_t val; @@ -290,7 +290,7 @@ public: size_t num_variants() const { return (m_data.is_Data() ? m_data.as_Data().size() : m_data.as_Value().variants.size()); } - size_t find_variant(const ::std::string& ) const; + size_t find_variant(const RcString& ) const; /// Returns true if this enum is a C-like enum (has values only) bool is_value() const; @@ -343,7 +343,7 @@ public: struct AssociatedType { bool is_sized; - ::std::string m_lifetime_bound; + LifetimeRef m_lifetime_bound; ::std::vector< ::HIR::TraitPath> m_trait_bounds; ::HIR::TypeRef m_default; }; @@ -356,23 +356,25 @@ class Trait { public: GenericParams m_params; - ::std::string m_lifetime; + LifetimeRef m_lifetime; ::std::vector< ::HIR::TraitPath > m_parent_traits; bool m_is_marker; // aka OIBIT - ::std::unordered_map< ::std::string, AssociatedType > m_types; - ::std::unordered_map< ::std::string, TraitValueItem > m_values; + ::std::unordered_map< RcString, AssociatedType > m_types; + ::std::unordered_map< RcString, TraitValueItem > m_values; // Indexes into the vtable for each present method and value - ::std::unordered_multimap< ::std::string, ::std::pair > m_value_indexes; + ::std::unordered_multimap< RcString, ::std::pair > m_value_indexes; // Indexes in the vtable parameter list for each associated type - ::std::unordered_map< ::std::string, unsigned int > m_type_indexes; + ::std::unordered_map< RcString, unsigned int > m_type_indexes; // Flattend set of parent traits (monomorphised and associated types fixed) ::std::vector< ::HIR::TraitPath > m_all_parent_traits; + // VTable path + ::HIR::SimplePath m_vtable_path; - Trait( GenericParams gps, ::std::string lifetime, ::std::vector< ::HIR::TraitPath> parents): + Trait( GenericParams gps, LifetimeRef lifetime, ::std::vector< ::HIR::TraitPath> parents): m_params( mv$(gps) ), m_lifetime( mv$(lifetime) ), m_parent_traits( mv$(parents) ), @@ -387,11 +389,11 @@ public: ::std::vector< ::HIR::SimplePath> m_traits; // Contains all values and functions (including type constructors) - ::std::unordered_map< ::std::string, ::std::unique_ptr> > m_value_items; + ::std::unordered_map< RcString, ::std::unique_ptr> > m_value_items; // Contains types, traits, and modules - ::std::unordered_map< ::std::string, ::std::unique_ptr> > m_mod_items; + ::std::unordered_map< RcString, ::std::unique_ptr> > m_mod_items; - ::std::vector< ::std::pair<::std::string, Static> > m_inline_statics; + ::std::vector< ::std::pair > m_inline_statics; Module() {} Module(const Module&) = delete; @@ -436,8 +438,8 @@ public: ::HIR::GenericParams m_params; ::HIR::TypeRef m_type; - ::std::map< ::std::string, VisImplEnt< ::HIR::Function> > m_methods; - ::std::map< ::std::string, VisImplEnt< ::HIR::Constant> > m_constants; + ::std::map< RcString, VisImplEnt< ::HIR::Function> > m_methods; + ::std::map< RcString, VisImplEnt< ::HIR::Constant> > m_constants; ::HIR::SimplePath m_src_module; @@ -460,11 +462,11 @@ public: ::HIR::PathParams m_trait_args; ::HIR::TypeRef m_type; - ::std::map< ::std::string, ImplEnt< ::HIR::Function> > m_methods; - ::std::map< ::std::string, ImplEnt< ::HIR::Constant> > m_constants; - ::std::map< ::std::string, ImplEnt< ::HIR::Static> > m_statics; + ::std::map< RcString, ImplEnt< ::HIR::Function> > m_methods; + ::std::map< RcString, ImplEnt< ::HIR::Constant> > m_constants; + ::std::map< RcString, ImplEnt< ::HIR::Static> > m_statics; - ::std::map< ::std::string, ImplEnt< ::HIR::TypeRef> > m_types; + ::std::map< RcString, ImplEnt< ::HIR::TypeRef> > m_types; ::HIR::SimplePath m_src_module; @@ -512,7 +514,7 @@ class ProcMacro { public: // Name of the macro - ::std::string name; + RcString name; // Path to the handler ::HIR::SimplePath path; // A list of attributes to hand to the handler @@ -521,7 +523,7 @@ public: class Crate { public: - ::std::string m_crate_name; + RcString m_crate_name; Module m_root_module; @@ -532,7 +534,7 @@ public: ::std::multimap< ::HIR::SimplePath, ::HIR::MarkerImpl > m_marker_impls; /// Macros exported by this crate - ::std::unordered_map< ::std::string, ::MacroRulesPtr > m_exported_macros; + ::std::unordered_map< RcString, ::MacroRulesPtr > m_exported_macros; /// Procedural macros presented ::std::vector< ::HIR::ProcMacro> m_proc_macros; @@ -540,7 +542,7 @@ public: ::std::unordered_map< ::std::string, ::HIR::SimplePath> m_lang_items; /// Referenced crates - ::std::unordered_map< ::std::string, ExternCrate> m_ext_crates; + ::std::unordered_map< RcString, ExternCrate> m_ext_crates; /// Referenced system libraries ::std::vector m_ext_libs; /// Extra paths for the linker @@ -548,7 +550,7 @@ public: /// Method called to populate runtime state after deserialisation /// See hir/crate_post_load.cpp - void post_load_update(const ::std::string& loaded_name); + void post_load_update(const RcString& loaded_name); const ::HIR::SimplePath& get_lang_item_path(const Span& sp, const char* name) const; const ::HIR::SimplePath& get_lang_item_path_opt(const char* name) const; diff --git a/src/hir/hir_ops.cpp b/src/hir/hir_ops.cpp index 89e48c80..32c70a72 100644 --- a/src/hir/hir_ops.cpp +++ b/src/hir/hir_ops.cpp @@ -825,6 +825,7 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl& static Span sp; for(const auto& tb : id.m_params.m_bounds) { + DEBUG(tb); if(tb.is_TraitBound()) { ::HIR::TypeRef tmp_ty; @@ -851,7 +852,7 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl& } } else if( TU_TEST1(ty.m_data, Path, .binding.is_Opaque()) ) { - TODO(Span(), "Check bound " << ty << " : " << trait << " in source bounds or trait bounds"); + TODO(sp, "Check bound " << ty << " : " << trait << " in source bounds or trait bounds"); } else { // Search the crate for an impl @@ -889,9 +890,14 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl& // 4. Check ATY bounds on the trait path for(const auto& atyb : trait.m_type_bounds) { - const auto& aty = ti.m_types.at(atyb.first); - if( !aty.data.match_test_generics(sp, atyb.second, cb_ident, cb_match) ) - return false; + if( ti.m_types.count(atyb.first) == 0 ) { + DEBUG("Associated type '" << atyb.first << "' not in trait impl, assuming good"); + } + else { + const auto& aty = ti.m_types.at(atyb.first); + if( !aty.data.match_test_generics(sp, atyb.second, cb_ident, cb_match) ) + return false; + } } // All those pass? It's good. return true; diff --git a/src/hir/item_path.hpp b/src/hir/item_path.hpp index d93df9e8..290bf23b 100644 --- a/src/hir/item_path.hpp +++ b/src/hir/item_path.hpp @@ -54,12 +54,12 @@ public: } else if( parent ) { assert(name); - return parent->get_simple_path() + name; + return parent->get_simple_path() + RcString::new_interned(name); } else { assert(!name); assert(crate_name); - return ::HIR::SimplePath(crate_name); + return ::HIR::SimplePath(RcString::new_interned(crate_name)); } } ::HIR::Path get_full_path() const { @@ -76,11 +76,11 @@ public: else if( parent->trait ) { assert(parent->ty); assert(parent->trait_params); - return ::HIR::Path( parent->ty->clone(), ::HIR::GenericPath(parent->trait->clone(), parent->trait_params->clone()), ::std::string(name) ); + return ::HIR::Path( parent->ty->clone(), ::HIR::GenericPath(parent->trait->clone(), parent->trait_params->clone()), RcString::new_interned(name) ); } else { assert(parent->ty); - return ::HIR::Path( parent->ty->clone(), ::std::string(name) ); + return ::HIR::Path( parent->ty->clone(), RcString::new_interned(name) ); } } const char* get_name() const { @@ -95,6 +95,9 @@ public: ItemPath operator+(const ::std::string& name) const { return ItemPath(*this, name.c_str()); } + ItemPath operator+(const RcString& name) const { + return ItemPath(*this, name.c_str()); + } bool operator==(const ::HIR::SimplePath& sp) const { if( sp.m_crate_name != "" ) return false; diff --git a/src/hir/main_bindings.hpp b/src/hir/main_bindings.hpp index 622d8e2e..89896df0 100644 --- a/src/hir/main_bindings.hpp +++ b/src/hir/main_bindings.hpp @@ -18,4 +18,4 @@ namespace AST { extern void HIR_Dump(::std::ostream& sink, const ::HIR::Crate& crate); extern ::HIR::CratePtr LowerHIR_FromAST(::AST::Crate crate); extern void HIR_Serialise(const ::std::string& filename, const ::HIR::Crate& crate); -extern ::HIR::CratePtr HIR_Deserialise(const ::std::string& filename, const ::std::string& loaded_name); +extern ::HIR::CratePtr HIR_Deserialise(const ::std::string& filename); diff --git a/src/hir/path.cpp b/src/hir/path.cpp index e6dab41f..a867c245 100644 --- a/src/hir/path.cpp +++ b/src/hir/path.cpp @@ -8,7 +8,7 @@ #include #include -::HIR::SimplePath HIR::SimplePath::operator+(const ::std::string& s) const +::HIR::SimplePath HIR::SimplePath::operator+(const RcString& s) const { ::HIR::SimplePath ret(m_crate_name); ret.m_components = m_components; @@ -193,11 +193,11 @@ bool ::HIR::TraitPath::operator==(const ::HIR::TraitPath& x) const m_data( ::HIR::Path::Data::make_Generic(::HIR::GenericPath(mv$(sp))) ) { } -::HIR::Path::Path(TypeRef ty, ::std::string item, PathParams item_params): +::HIR::Path::Path(TypeRef ty, RcString item, PathParams item_params): m_data(Data::make_UfcsInherent({ box$(ty), mv$(item), mv$(item_params) })) { } -::HIR::Path::Path(TypeRef ty, GenericPath trait, ::std::string item, PathParams item_params): +::HIR::Path::Path(TypeRef ty, GenericPath trait, RcString item, PathParams item_params): m_data( Data::make_UfcsKnown({ box$(mv$(ty)), mv$(trait), mv$(item), mv$(item_params) }) ) { } diff --git a/src/hir/path.hpp b/src/hir/path.hpp index f2bec6ee..86fe725e 100644 --- a/src/hir/path.hpp +++ b/src/hir/path.hpp @@ -25,7 +25,7 @@ enum Compare { }; typedef ::std::function t_cb_resolve_type; -typedef ::std::function< ::HIR::Compare(unsigned int, const ::std::string&, const ::HIR::TypeRef&) > t_cb_match_generics; +typedef ::std::function< ::HIR::Compare(unsigned int, const RcString&, const ::HIR::TypeRef&) > t_cb_match_generics; static inline ::std::ostream& operator<<(::std::ostream& os, const Compare& x) { switch(x) @@ -54,18 +54,18 @@ static inline Compare& operator &=(Compare& x, const Compare& y) { /// Simple path - Absolute with no generic parameters struct SimplePath { - ::std::string m_crate_name; - ::std::vector< ::std::string> m_components; + RcString m_crate_name; + ::std::vector< RcString> m_components; SimplePath(): m_crate_name("") { } - SimplePath(::std::string crate): + SimplePath(RcString crate): m_crate_name( mv$(crate) ) { } - SimplePath(::std::string crate, ::std::vector< ::std::string> components): + SimplePath(RcString crate, ::std::vector< RcString> components): m_crate_name( mv$(crate) ), m_components( mv$(components) ) { @@ -73,7 +73,7 @@ struct SimplePath SimplePath clone() const; - SimplePath operator+(const ::std::string& s) const; + SimplePath operator+(const RcString& s) const; bool operator==(const SimplePath& x) const { return m_crate_name == x.m_crate_name && m_components == x.m_components; } @@ -158,9 +158,9 @@ class TraitPath { public: GenericPath m_path; - ::std::vector< ::std::string> m_hrls; + ::std::vector< RcString> m_hrls; // TODO: Each bound should list its origin trait - ::std::map< ::std::string, ::HIR::TypeRef> m_type_bounds; + ::std::map< RcString, ::HIR::TypeRef> m_type_bounds; const ::HIR::Trait* m_trait_ptr; @@ -190,20 +190,20 @@ public: (Generic, GenericPath), (UfcsInherent, struct { ::std::unique_ptr type; - ::std::string item; + RcString item; PathParams params; PathParams impl_params; }), (UfcsKnown, struct { ::std::unique_ptr type; GenericPath trait; - ::std::string item; + RcString item; PathParams params; }), (UfcsUnknown, struct { ::std::unique_ptr type; //GenericPath ??; - ::std::string item; + RcString item; PathParams params; }) ); @@ -216,8 +216,8 @@ public: Path(GenericPath _); Path(SimplePath _); - Path(TypeRef ty, ::std::string item, PathParams item_params=PathParams()); - Path(TypeRef ty, GenericPath trait, ::std::string item, PathParams item_params=PathParams()); + Path(TypeRef ty, RcString item, PathParams item_params=PathParams()); + Path(TypeRef ty, GenericPath trait, RcString item, PathParams item_params=PathParams()); Path clone() const; Compare compare_with_placeholders(const Span& sp, const Path& x, t_cb_resolve_type resolve_placeholder) const; diff --git a/src/hir/pattern.cpp b/src/hir/pattern.cpp index d25b25e7..063ed1b3 100644 --- a/src/hir/pattern.cpp +++ b/src/hir/pattern.cpp @@ -154,8 +154,9 @@ namespace { rv.push_back( pat.clone() ); return rv; } - ::std::vector< ::std::pair< ::std::string, ::HIR::Pattern> > clone_pat_fields(const ::std::vector< ::std::pair< ::std::string, ::HIR::Pattern> >& pats) { - ::std::vector< ::std::pair< ::std::string, ::HIR::Pattern> > rv; + typedef ::std::vector< ::std::pair< RcString, ::HIR::Pattern> > pat_fields_t; + pat_fields_t clone_pat_fields(const pat_fields_t& pats) { + pat_fields_t rv; rv.reserve( pats.size() ); for(const auto& field : pats) rv.push_back( ::std::make_pair(field.first, field.second.clone()) ); diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp index d16fd942..136bd587 100644 --- a/src/hir/pattern.hpp +++ b/src/hir/pattern.hpp @@ -29,7 +29,7 @@ struct PatternBinding bool m_mutable; Type m_type; - ::std::string m_name; + RcString m_name; unsigned int m_slot; unsigned m_implicit_deref_count = 0; @@ -43,7 +43,7 @@ struct PatternBinding m_slot(0), m_implicit_deref_count(0) {} - PatternBinding(bool mut, Type type, ::std::string name, unsigned int slot): + PatternBinding(bool mut, Type type, RcString name, unsigned int slot): m_mutable(mut), m_type(type), m_name( mv$(name) ), @@ -104,7 +104,7 @@ struct Pattern (Struct, struct { GenericPath path; const Struct* binding; - ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; + ::std::vector< ::std::pair > sub_patterns; bool is_exhaustive; bool is_wildcard() const { @@ -129,7 +129,7 @@ struct Pattern GenericPath path; const Enum* binding_ptr; unsigned binding_idx; - ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; + ::std::vector< ::std::pair > sub_patterns; bool is_exhaustive; } ), (Slice, struct { diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index 2c72c801..c15630d9 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -20,6 +20,15 @@ m_out( out ) {} + template + void serialise_strmap(const ::std::map& map) + { + m_out.write_count(map.size()); + for(const auto& v : map) { + m_out.write_string(v.first); + serialise(v.second); + } + } template void serialise_strmap(const ::std::map< ::std::string,V>& map) { @@ -30,6 +39,16 @@ } } template + void serialise_strmap(const ::std::unordered_map& map) + { + m_out.write_count(map.size()); + for(const auto& v : map) { + DEBUG("- " << v.first); + m_out.write_string(v.first); + serialise(v.second); + } + } + template void serialise_strmap(const ::std::unordered_map< ::std::string,V>& map) { m_out.write_count(map.size()); @@ -40,6 +59,16 @@ } } template + void serialise_strmap(const ::std::unordered_multimap& map) + { + m_out.write_count(map.size()); + for(const auto& v : map) { + DEBUG("- " << v.first); + m_out.write_string(v.first); + serialise(v.second); + } + } + template void serialise_strmap(const ::std::unordered_multimap< ::std::string,V>& map) { m_out.write_count(map.size()); @@ -73,6 +102,11 @@ serialise(e.second); } template + void serialise(const ::std::pair< RcString, T>& e) { + m_out.write_string(e.first); + serialise(e.second); + } + template void serialise(const ::std::pair& e) { m_out.write_count(e.first); serialise(e.second); @@ -86,6 +120,10 @@ void serialise(uint64_t v) { m_out.write_u64c(v); }; void serialise(int64_t v) { m_out.write_i64c(v); }; + void serialise(const ::HIR::LifetimeDef& ld) + { + m_out.write_string(ld.m_name); + } void serialise(const ::HIR::LifetimeRef& lr) { m_out.write_count(lr.binding); @@ -392,6 +430,9 @@ void serialise(const ::std::string& v) { m_out.write_string(v); } + void serialise(const RcString& v) { + m_out.write_string(v); + } void serialise(const ::MacroRulesPtr& mac) { @@ -488,6 +529,9 @@ TU_ARM(td, String, e) { m_out.write_string(e); } break; + TU_ARM(td, IString, e) { + m_out.write_string(e); + } break; TU_ARM(td, Integer, e) { m_out.write_tag(e.m_datatype); m_out.write_u64c(e.m_intval); @@ -1041,6 +1085,7 @@ serialise_strmap( item.m_value_indexes ); serialise_strmap( item.m_type_indexes ); serialise_vec( item.m_all_parent_traits ); + serialise( item.m_vtable_path ); } void serialise(const ::HIR::TraitValueItem& tvi) { @@ -1063,7 +1108,7 @@ void serialise(const ::HIR::AssociatedType& at) { m_out.write_bool(at.is_sized); - //m_out.write_string(at.m_lifetime_bound); // TODO: better type for lifetime + serialise(at.m_lifetime_bound); serialise_vec(at.m_trait_bounds); serialise_type(at.m_default); } @@ -1072,8 +1117,10 @@ void HIR_Serialise(const ::std::string& filename, const ::HIR::Crate& crate) { - ::HIR::serialise::Writer out { filename }; + ::HIR::serialise::Writer out; HirSerialiser s { out }; s.serialise_crate(crate); + out.open(filename); + s.serialise_crate(crate); } diff --git a/src/hir/serialise_lowlevel.cpp b/src/hir/serialise_lowlevel.cpp index e69ff848..5c4b0df2 100644 --- a/src/hir/serialise_lowlevel.cpp +++ b/src/hir/serialise_lowlevel.cpp @@ -11,6 +11,7 @@ #include #include // memcpy #include +#include namespace HIR { namespace serialise { @@ -29,17 +30,58 @@ public: void write(const void* buf, size_t len); }; -Writer::Writer(const ::std::string& filename): - m_inner( new WriterInner(filename) ) +Writer::Writer(): + m_inner(nullptr) { } Writer::~Writer() { delete m_inner, m_inner = nullptr; } +void Writer::open(const ::std::string& filename) +{ + // 1. Sort strings by frequency + ::std::vector<::std::pair> sorted; + sorted.reserve(m_istring_cache.size()); + for(const auto& e : m_istring_cache) + sorted.push_back( e ); + // 2. Write out string table + ::std::sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b){ return a.second > b.second; }); + + m_inner = new WriterInner(filename); + // 3. Reset m_istring_cache to use the same value + this->write_count(sorted.size()); + for(size_t i = 0; i < sorted.size(); i ++) + { + const auto& s = sorted[i].first; + this->write_string(s.size(), s.c_str()); + DEBUG(i << " = " << m_istring_cache[s] << " '" << s << "'"); + m_istring_cache[s] = i; + } + for(const auto& e : m_istring_cache) + { + assert(e.second < sorted.size()); + } +} void Writer::write(const void* buf, size_t len) { - m_inner->write(buf, len); + if( m_inner ) { + m_inner->write(buf, len); + } + else { + // No-op, pre caching + } +} +void Writer::write_string(const RcString& v) +{ + if( m_inner ) { + // Emit ID from the cache + this->write_count( m_istring_cache.at(v) ); + } + else { + // Find/add in cache + m_istring_cache.insert(::std::make_pair(v, 0)).first->second += 1; + } } @@ -189,6 +231,14 @@ Reader::Reader(const ::std::string& filename): m_buffer(1024), m_pos(0) { + size_t n_strings = read_count(); + m_strings.reserve(n_strings); + DEBUG("n_strings = " << n_strings); + for(size_t i = 0; i < n_strings; i ++) + { + auto s = read_string(); + m_strings.push_back( RcString::new_interned(s) ); + } } Reader::~Reader() { diff --git a/src/hir/serialise_lowlevel.hpp b/src/hir/serialise_lowlevel.hpp index a35b8e98..b3633d54 100644 --- a/src/hir/serialise_lowlevel.hpp +++ b/src/hir/serialise_lowlevel.hpp @@ -9,8 +9,10 @@ #include #include +#include #include #include +#include namespace HIR { namespace serialise { @@ -21,12 +23,14 @@ class ReaderInner; class Writer { WriterInner* m_inner; + ::std::map m_istring_cache; public: - Writer(const ::std::string& path); + Writer(); Writer(const Writer&) = delete; Writer(Writer&&) = delete; ~Writer(); + void open(const ::std::string& filename); void write(const void* data, size_t count); void write_u8(uint8_t v) { @@ -114,16 +118,20 @@ public: write_u16( static_cast(c) ); } } - void write_string(const ::std::string& v) { - if(v.size() < 128) { - write_u8( static_cast(v.size()) ); + void write_string(const RcString& v); + void write_string(size_t len, const char* s) { + if(len < 128) { + write_u8( static_cast(len) ); } else { - assert(v.size() < (1u<<(16+7))); - write_u8( static_cast(128 + (v.size() >> 16)) ); - write_u16( static_cast(v.size() & 0xFFFF) ); + assert(len < (1u<<(16+7))); + write_u8( static_cast(128 + (len >> 16)) ); + write_u16( static_cast(len & 0xFFFF) ); } - this->write(v.data(), v.size()); + this->write(s, len); + } + void write_string(const ::std::string& v) { + write_string(v.size(), v.c_str()); } void write_bool(bool v) { write_u8(v ? 0xFF : 0x00); @@ -148,6 +156,7 @@ class Reader ReaderInner* m_inner; ReadBuffer m_buffer; size_t m_pos; + ::std::vector m_strings; public: Reader(const ::std::string& path); Reader(const Writer&) = delete; @@ -251,6 +260,10 @@ public: return ~0u; } } + RcString read_istring() { + size_t idx = read_count(); + return m_strings.at(idx); + } ::std::string read_string() { size_t len = read_u8(); if( len < 128 ) { diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 2fc1179d..38196a55 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -88,6 +88,7 @@ struct LifetimeRef static const uint32_t UNKNOWN = 0; static const uint32_t STATIC = 0xFFFF; + //RcString name; // Values below 2^16 are parameters/static, values above are per-function region IDs allocated during region inferrence. uint32_t binding = UNKNOWN; @@ -97,6 +98,9 @@ struct LifetimeRef return rv; } + Ordering ord(const LifetimeRef& x) const { + return ::ord(binding, x.binding); + } bool operator==(const LifetimeRef& x) const { return binding == x.binding; } @@ -191,7 +195,7 @@ public: TypePathBinding binding; }), (Generic, struct { - ::std::string name; + RcString name; // 0xFFFF = Self, 0-255 = Type/Trait, 256-511 = Method, 512-767 = Placeholder unsigned int binding; @@ -254,7 +258,7 @@ public: TypeRef(::std::vector< ::HIR::TypeRef> sts): m_data( Data::make_Tuple(mv$(sts)) ) {} - TypeRef(::std::string name, unsigned int slot): + TypeRef(RcString name, unsigned int slot): m_data( Data::make_Generic({ mv$(name), slot }) ) {} TypeRef(::HIR::TypeRef::Data x): diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 22909cdc..b97a6ae0 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -40,7 +40,7 @@ namespace { virtual ::HIR::Path new_static(::HIR::TypeRef type, ::HIR::Literal value) override { - auto name = FMT(name_prefix << next_item_idx); + auto name = RcString::new_interned(FMT(name_prefix << next_item_idx)); next_item_idx ++; DEBUG("mod_path = " << mod_path); auto rv = mod_path.get_simple_path() + name.c_str(); diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index ace154ff..94f272f8 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -147,7 +147,7 @@ namespace { { m_replacement = NEWNODE(node.m_res_type.clone(), Field, node.span(), get_self(node.span()), - FMT(binding_it - m_captures.begin()) + RcString::new_interned(FMT(binding_it - m_captures.begin())) ); if( binding_it->second != ::HIR::ValueUsage::Move ) { auto bt = (binding_it->second == ::HIR::ValueUsage::Mutate ? ::HIR::BorrowType::Unique : ::HIR::BorrowType::Shared); @@ -355,7 +355,7 @@ namespace { return ::HIR::TraitImpl { mv$(params), {}, mv$(closure_type), make_map1( - ::std::string("call_free"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + RcString::new_interned("call_free"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { false, ::HIR::Linkage {}, ::HIR::Function::Receiver::Free, ABI_RUST, false, false, @@ -385,7 +385,7 @@ namespace { return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( - ::std::string("call_once"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + RcString::new_interned("call_once"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { false, ::HIR::Linkage {}, ::HIR::Function::Receiver::Value, ABI_RUST, false, false, @@ -404,7 +404,7 @@ namespace { {}, {}, make_map1( - ::std::string("Output"), ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> { false, mv$(ret_ty) } + RcString::new_interned("Output"), ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> { false, mv$(ret_ty) } ), ::HIR::SimplePath() }; @@ -423,7 +423,7 @@ namespace { return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( - ::std::string("call_mut"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + RcString::new_interned("call_mut"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { false, ::HIR::Linkage {}, ::HIR::Function::Receiver::BorrowUnique, ABI_RUST, false, false, @@ -459,7 +459,7 @@ namespace { return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( - ::std::string("call"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + RcString::new_interned("call"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { false, ::HIR::Linkage {}, ::HIR::Function::Receiver::BorrowShared, ABI_RUST, false, false, @@ -801,11 +801,11 @@ namespace { for(size_t i = 0; i < args_tup_inner.size(); i ++) { const auto& ty = args_tup_inner[i]; - dispatch_args.push_back( NEWNODE(ty.clone(), Field, sp, NEWNODE(args_ty.clone(), Variable, sp, "arg", 1), FMT(i)) ); + dispatch_args.push_back( NEWNODE(ty.clone(), Field, sp, NEWNODE(args_ty.clone(), Variable, sp, RcString::new_interned("arg"), 1), RcString::new_interned(FMT(i))) ); dispatch_node_args_cache.push_back( ty.clone() ); } dispatch_node_args_cache.push_back( ret_type.clone() ); - auto path = ::HIR::Path(closure_type.clone(), "call_free"); + auto path = ::HIR::Path(closure_type.clone(), RcString::new_interned("call_free")); path.m_data.as_UfcsInherent().impl_params = closure_type.m_data.as_Path().path.m_data.as_Generic().m_params.clone(); HIR::ExprNodeP dispatch_node = NEWNODE(ret_type.clone(), CallPath, sp, mv$(path), @@ -814,7 +814,7 @@ namespace { dynamic_cast<::HIR::ExprNode_CallPath&>(*dispatch_node).m_cache.m_arg_types = mv$(dispatch_node_args_cache); auto args_arg = ::std::make_pair( - ::HIR::Pattern { {false, ::HIR::PatternBinding::Type::Move, "args", 1}, {} }, + ::HIR::Pattern { {false, ::HIR::PatternBinding::Type::Move, RcString::new_interned("args"), 1}, {} }, args_ty.clone() ); HIR::TraitImpl fcn; @@ -863,9 +863,9 @@ namespace { // - FnOnce { auto dispatch_node = NEWNODE(ret_type.clone(), CallPath, sp, - ::HIR::Path(closure_type.clone(), ::HIR::GenericPath(lang_Fn, trait_params.clone()), "call"), + ::HIR::Path(closure_type.clone(), ::HIR::GenericPath(lang_Fn, trait_params.clone()), RcString::new_interned("call")), make_vec2( - NEWNODE(method_self_ty.clone(), Borrow, sp, ::HIR::BorrowType::Shared, NEWNODE(closure_type.clone(), Variable, sp, "self", 0)), + NEWNODE(method_self_ty.clone(), Borrow, sp, ::HIR::BorrowType::Shared, NEWNODE(closure_type.clone(), Variable, sp, RcString::new_interned("self"), 0)), NEWNODE(args_ty.clone(), Variable, sp, "arg", 1) ) ); @@ -1181,7 +1181,7 @@ namespace { ::HIR::SimplePath root_mod_path(crate.m_crate_name,{}); m_cur_mod_path = &root_mod_path; m_new_type = [&](auto s)->auto { - auto name = FMT("closure#I_" << closure_count); + auto name = RcString::new_interned(FMT("closure#I_" << closure_count)); closure_count += 1; auto boxed = box$(( ::HIR::VisEnt< ::HIR::TypeItem> { ::HIR::Publicity::new_none(), ::HIR::TypeItem( mv$(s) ) } )); crate.m_root_module.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) ); @@ -1374,7 +1374,7 @@ void HIR_Expand_Closures_Expr(const ::HIR::Crate& crate_ro, ::HIR::ExprPtr& exp) static int closure_count = 0; out_impls_t new_trait_impls; new_type_cb_t new_type_cb = [&](auto s)->::HIR::SimplePath { - auto name = FMT("closure#C_" << closure_count); + auto name = RcString::new_interned(FMT("closure#C_" << closure_count)); closure_count += 1; auto boxed = box$(( ::HIR::VisEnt< ::HIR::TypeItem> { ::HIR::Publicity::new_none(), ::HIR::TypeItem( mv$(s) ) } )); crate.m_root_module.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) ); diff --git a/src/hir_expand/vtable.cpp b/src/hir_expand/vtable.cpp index 2b3dcfb4..cd7b3413 100644 --- a/src/hir_expand/vtable.cpp +++ b/src/hir_expand/vtable.cpp @@ -17,7 +17,7 @@ namespace { { const ::HIR::Crate& m_crate; //StaticTraitResolve m_resolve; - ::std::function<::HIR::SimplePath(bool, ::std::string, ::HIR::Struct)> m_new_type; + ::std::function<::HIR::SimplePath(bool, RcString, ::HIR::Struct)> m_new_type; ::HIR::SimplePath m_lang_Sized; public: OuterVisitor(const ::HIR::Crate& crate): @@ -72,7 +72,7 @@ namespace { //TODO(Span(), "Handle conflicting associated types - '" << ty.first << "'"); } else { - params.m_types.push_back( ::HIR::TypeParamDef { "a#"+ty.first, {}, ty.second.is_sized } ); + params.m_types.push_back( ::HIR::TypeParamDef { RcString::new_interned(FMT("a#" << ty.first)), {}, ty.second.is_sized } ); } i ++; } @@ -98,14 +98,14 @@ namespace { auto clone_cb = [&](const auto& t, auto& o) { if(t.m_data.is_Path() && t.m_data.as_Path().path.m_data.is_UfcsKnown()) { const auto& pe = t.m_data.as_Path().path.m_data.as_UfcsKnown(); - bool is_self = (*pe.type == ::HIR::TypeRef("Self", 0xFFFF)); + bool is_self = (*pe.type == ::HIR::TypeRef(RcString::new_interned("Self"), 0xFFFF)); auto it = trait_ptr->m_type_indexes.find(pe.item); bool has_item = (it != trait_ptr->m_type_indexes.end()); // TODO: Check the trait against m_type_indexes if( is_self /*&& pe.trait == trait_path*/ && has_item ) { DEBUG("[clone_cb] t=" << t << " -> " << it->second); // Replace with a new type param, need to know the index of it - o = ::HIR::TypeRef("a#"+pe.item, it->second); + o = ::HIR::TypeRef( RcString::new_interned(FMT("a#" << pe.item)), it->second); return true; } else { @@ -231,12 +231,13 @@ namespace { } } // TODO: Would like to have access to the publicity marker - auto item_path = m_new_type(true, FMT(p.get_name() << "#vtable"), ::HIR::Struct { + auto item_path = m_new_type(true, RcString::new_interned(FMT(p.get_name() << "#vtable")), ::HIR::Struct { mv$(args), ::HIR::Struct::Repr::Rust, ::HIR::Struct::Data(mv$(fields)), {} }); + tr.m_vtable_path = item_path; DEBUG("Vtable structure created - " << item_path); ::HIR::GenericPath path( mv$(item_path), mv$(params) ); diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 0d3bc8ab..aa26ae1f 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -832,7 +832,7 @@ namespace { // TODO: Either - Don't include the above impl bound, or change the below trait to the one that has that type for( const auto& assoc : be.trait.m_type_bounds ) { ::HIR::GenericPath type_trait_path; - bool has_ty = m_resolve.trait_contains_type(sp, real_trait, *be.trait.m_trait_ptr, assoc.first, type_trait_path); + bool has_ty = m_resolve.trait_contains_type(sp, real_trait, *be.trait.m_trait_ptr, assoc.first.c_str(), type_trait_path); ASSERT_BUG(sp, has_ty, "Type " << assoc.first << " not found in chain of " << real_trait); auto other_ty = monomorphise_type_with(sp, assoc.second, cache.m_monomorph_cb, true); @@ -934,7 +934,7 @@ namespace { const auto& sp = node.span(); const auto& str_ty = node.m_value->m_res_type; - bool is_index = ( '0' <= node.m_field[0] && node.m_field[0] <= '9' ); + bool is_index = ( '0' <= node.m_field.c_str()[0] && node.m_field.c_str()[0] <= '9' ); if( str_ty.m_data.is_Tuple() ) { ASSERT_BUG(sp, is_index, "Non-index _Field on tuple"); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index cda8edd0..ecaae208 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -53,7 +53,7 @@ struct Context struct Binding { - ::std::string name; + RcString name; ::HIR::TypeRef ty; //unsigned int ivar; }; @@ -79,7 +79,7 @@ struct Context ::HIR::SimplePath trait; ::HIR::PathParams params; ::HIR::TypeRef impl_ty; - ::std::string name; // if "", no type is used (and left is ignored) - Just does trait selection + RcString name; // if "", no type is used (and left is ignored) - Just does trait selection // HACK: operators are special - the result when both types are primitives is ALWAYS the lefthand side bool is_operator; @@ -252,7 +252,7 @@ struct Context void handle_pattern_direct_inner(const Span& sp, ::HIR::Pattern& pat, const ::HIR::TypeRef& type); void add_binding_inner(const Span& sp, const ::HIR::PatternBinding& pb, ::HIR::TypeRef type); - void add_var(const Span& sp, unsigned int index, const ::std::string& name, ::HIR::TypeRef type); + void add_var(const Span& sp, unsigned int index, const RcString& name, ::HIR::TypeRef type); const ::HIR::TypeRef& get_var(const Span& sp, unsigned int idx) const; // - Add a revisit entry @@ -304,7 +304,7 @@ namespace { ::HIR::GenericPath type_trait_path; ASSERT_BUG(sp, be.trait.m_trait_ptr, "Trait pointer not set in " << be.trait.m_path); // TODO: Store the source trait for this bound in the the bound list? - if( !context.m_resolve.trait_contains_type(sp, real_trait, *be.trait.m_trait_ptr, assoc.first, type_trait_path) ) + if( !context.m_resolve.trait_contains_type(sp, real_trait, *be.trait.m_trait_ptr, assoc.first.c_str(), type_trait_path) ) BUG(sp, "Couldn't find associated type " << assoc.first << " in trait " << real_trait); auto other_ty = monomorphise_type_with(sp, assoc.second, monomorph_cb, true); @@ -1480,7 +1480,7 @@ namespace { } // - Search in-scope trait list for traits that provide a method of this name - const ::std::string& method_name = node.m_method; + const RcString& method_name = node.m_method; ::HIR::t_trait_list possible_traits; unsigned int max_num_params = 0; for(const auto& trait_ref : ::reverse(m_traits)) @@ -2772,7 +2772,7 @@ namespace { // - If running in a mode after stablise (before defaults), fall // back to trait if the inherent is still ambigious. ::std::vector<::std::pair> possible_methods; - unsigned int deref_count = this->context.m_resolve.autoderef_find_method(node.span(), node.m_traits, node.m_trait_param_ivars, ty, node.m_method, possible_methods); + unsigned int deref_count = this->context.m_resolve.autoderef_find_method(node.span(), node.m_traits, node.m_trait_param_ivars, ty, node.m_method.c_str(), possible_methods); try_again: if( deref_count != ~0u ) { @@ -3003,6 +3003,7 @@ namespace { const auto* current_ty = &node.m_value->m_res_type; ::std::vector< ::HIR::TypeRef> deref_res_types; + // TODO: autoderef_find_field? do { const auto& ty = this->context.m_ivars.get_type(*current_ty); if( ty.m_data.is_Infer() ) { @@ -3013,7 +3014,7 @@ namespace { DEBUG("Hit unbound path, returning early"); return ; } - if( this->context.m_resolve.find_field(node.span(), ty, field_name, out_type) ) { + if( this->context.m_resolve.find_field(node.span(), ty, field_name.c_str(), out_type) ) { this->context.equate_types(node.span(), node.m_res_type, out_type); break; } @@ -5439,7 +5440,7 @@ void Context::possible_equate_type_disable_strong(const Span& sp, unsigned int i ent.force_disable = true; } -void Context::add_var(const Span& sp, unsigned int index, const ::std::string& name, ::HIR::TypeRef type) { +void Context::add_var(const Span& sp, unsigned int index, const RcString& name, ::HIR::TypeRef type) { DEBUG("(" << index << " " << name << " : " << type << ")"); assert(index != ~0u); if( m_bindings.size() <= index ) @@ -6923,7 +6924,7 @@ namespace { DEBUG("Check <" << t << ">::" << node.m_method); ::std::vector<::std::pair> possible_methods; - unsigned int deref_count = context.m_resolve.autoderef_find_method(node.span(), node.m_traits, node.m_trait_param_ivars, t, node.m_method, possible_methods); + unsigned int deref_count = context.m_resolve.autoderef_find_method(node.span(), node.m_traits, node.m_trait_param_ivars, t, node.m_method.c_str(), possible_methods); DEBUG("> deref_count = " << deref_count << ", " << possible_methods); if( !t.m_data.is_Infer() && possible_methods.empty() ) { diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 0ebb9c07..629b8bba 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -960,7 +960,7 @@ void TraitResolution::prep_indexes() // Locate the source trait ::HIR::GenericPath source_trait_path; - bool rv = this->trait_contains_type(sp, be.trait.m_path, m_crate.get_trait_by_path(sp, be.trait.m_path.m_path), tb.first, source_trait_path); + bool rv = this->trait_contains_type(sp, be.trait.m_path, m_crate.get_trait_by_path(sp, be.trait.m_path.m_path), tb.first.c_str(), source_trait_path); ASSERT_BUG(sp, rv, "Can't find `" << tb.first << "` in " << be.trait.m_path); auto ty_l = ::HIR::TypeRef( ::HIR::Path( be.type.clone(), mv$(source_trait_path), tb.first ) ); @@ -1005,7 +1005,7 @@ void TraitResolution::prep_indexes() // Find the source trait for this associated type ::HIR::GenericPath source_trait_path; - bool rv = this->trait_contains_type(sp, trait_mono.m_path, itrait, tb.first, source_trait_path); + bool rv = this->trait_contains_type(sp, trait_mono.m_path, itrait, tb.first.c_str(), source_trait_path); ASSERT_BUG(sp, rv, "Can't find `" << tb.first << "` in " << trait_mono.m_path); auto ty_l = ::HIR::TypeRef( ::HIR::Path( ty_a.clone(), mv$(source_trait_path), tb.first ) ); @@ -1091,7 +1091,7 @@ bool TraitResolution::iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data { ::HIR::GenericPath trait_path; DEBUG("Checking ATY bounds on " << pe.trait << " :: " << pe.item); - if( !this->trait_contains_type(sp, pe.trait, this->m_crate.get_trait_by_path(sp, pe.trait.m_path), pe.item, trait_path) ) + if( !this->trait_contains_type(sp, pe.trait, this->m_crate.get_trait_by_path(sp, pe.trait.m_path), pe.item.c_str(), trait_path) ) BUG(sp, "Cannot find associated type " << pe.item << " anywhere in trait " << pe.trait); DEBUG("trait_path=" << trait_path); const auto& trait_ref = m_crate.get_trait_by_path(sp, trait_path.m_path); @@ -1133,7 +1133,7 @@ bool TraitResolution::find_trait_impls_magic(const Span& sp, ) const { static ::HIR::PathParams null_params; - static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc; + static ::std::map null_assoc; const auto& lang_Sized = this->m_crate.get_lang_item_path(sp, "sized"); const auto& lang_Copy = this->m_crate.get_lang_item_path(sp, "copy"); @@ -1235,7 +1235,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, ) const { static ::HIR::PathParams null_params; - static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc; + static ::std::map null_assoc; const auto& type = this->m_ivars.get_type(ty); TRACE_FUNCTION_F("trait = " << trait << params << ", type = " << type); @@ -1295,7 +1295,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, ::HIR::PathParams pp; pp.m_types.push_back( ::HIR::TypeRef(mv$(args)) ); - ::std::map< ::std::string, ::HIR::TypeRef> types; + ::std::map types; types.insert( ::std::make_pair( "Output", e.m_rettype->clone() ) ); return callback( ImplRef(type.clone(), mv$(pp), mv$(types)), cmp ); } @@ -1337,7 +1337,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, ::HIR::PathParams pp; pp.m_types.push_back( ::HIR::TypeRef(mv$(args)) ); - ::std::map< ::std::string, ::HIR::TypeRef> types; + ::std::map types; types.insert( ::std::make_pair( "Output", e.m_rettype->clone() ) ); return callback( ImplRef(type.clone(), mv$(pp), mv$(types)), cmp ); } @@ -1362,7 +1362,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, { ::HIR::PathParams pp; pp.m_types.push_back( mv$(ty_usize) ); - ::std::map< ::std::string, ::HIR::TypeRef> types; + ::std::map types; types.insert( ::std::make_pair( "Output", e.inner->clone() ) ); return callback( ImplRef(type.clone(), mv$(pp), mv$(types)), cmp ); } @@ -1402,8 +1402,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, if( trait == mt.m_path ) { auto cmp = compare_pp(sp, mt.m_params, params); if( cmp != ::HIR::Compare::Unequal ) { - static ::std::map< ::std::string, ::HIR::TypeRef> types; - return callback( ImplRef(&type, &mt.m_params, &types), cmp ); + return callback( ImplRef(&type, &mt.m_params, &null_assoc), cmp ); } } } @@ -1417,7 +1416,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, auto cmp = this->compare_pp(sp, i_params, params); if( cmp != ::HIR::Compare::Unequal ) { // Invoke callback with a proper ImplRef - ::std::map< ::std::string, ::HIR::TypeRef> assoc_clone; + ::std::map assoc_clone; for(const auto& e : i_assoc) assoc_clone.insert( ::std::make_pair(e.first, e.second.clone()) ); auto ir = ImplRef(i_ty.clone(), i_params.clone(), mv$(assoc_clone)); @@ -1454,7 +1453,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, auto cmp = this->compare_pp(sp, i_params, params); if( cmp != ::HIR::Compare::Unequal ) { // Invoke callback with a proper ImplRef - ::std::map< ::std::string, ::HIR::TypeRef> assoc_clone; + ::std::map assoc_clone; for(const auto& e : i_assoc) assoc_clone.insert( ::std::make_pair(e.first, e.second.clone()) ); auto ir = ImplRef(i_ty.clone(), i_params.clone(), mv$(assoc_clone)); @@ -1498,7 +1497,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, ::HIR::PathParams params_mono_o; const auto& b_params_mono = (monomorphise_pathparams_needed(b_params) ? params_mono_o = monomorphise_path_params_with(sp, b_params, monomorph_cb, false) : b_params); // TODO: Monormophise and EAT associated types - ::std::map< ::std::string, ::HIR::TypeRef> b_atys; + ::std::map b_atys; for(const auto& aty : bound.m_type_bounds) b_atys.insert(::std::make_pair( aty.first, monomorphise_type_with(sp, aty.second, monomorph_cb) )); @@ -2080,7 +2079,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, // - Does simplification of complex associated types // ::HIR::GenericPath trait_path; - if( !this->trait_contains_type(sp, pe_inner.trait, this->m_crate.get_trait_by_path(sp, pe_inner.trait.m_path), pe_inner.item, trait_path) ) + if( !this->trait_contains_type(sp, pe_inner.trait, this->m_crate.get_trait_by_path(sp, pe_inner.trait.m_path), pe_inner.item.c_str(), trait_path) ) BUG(sp, "Cannot find associated type " << pe_inner.item << " anywhere in trait " << pe_inner.trait); const auto& trait_ptr = this->m_crate.get_trait_by_path(sp, trait_path.m_path); const auto& assoc_ty = trait_ptr.m_types.at(pe_inner.item); @@ -2150,7 +2149,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, // TODO: Search for the actual trait containing this associated type ::HIR::GenericPath trait_path; //if( !this->trait_contains_type(sp, pe.trait, this->m_crate.get_trait_by_path(sp, pe.trait.m_path), *pe.type, pe.item, trait_path) ) - if( !this->trait_contains_type(sp, pe.trait, this->m_crate.get_trait_by_path(sp, pe.trait.m_path), pe.item, trait_path) ) + if( !this->trait_contains_type(sp, pe.trait, this->m_crate.get_trait_by_path(sp, pe.trait.m_path), pe.item.c_str(), trait_path) ) BUG(sp, "Cannot find associated type " << pe.item << " anywhere in trait " << pe.trait); //pe.trait = mv$(trait_path); @@ -2350,7 +2349,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple type, [&](const auto& ty, const auto& b_params, const auto& assoc) { // TODO: Avoid duplicating this map every time - ::std::map< ::std::string,::HIR::TypeRef> assoc2; + ::std::map< RcString,::HIR::TypeRef> assoc2; for(const auto& i : assoc) { assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); } @@ -2447,7 +2446,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, { // TODO: Have a global cache of impls that don't reference either generics or ivars - static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc; + static ::std::map null_assoc; TRACE_FUNCTION_F(trait << FMT_CB(ss, if(params_ptr) { ss << *params_ptr; } else { ss << ""; }) << " for " << type); // Handle auto traits (aka OIBITs) @@ -2832,7 +2831,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, // TODO: Some impl blocks have type params used as part of type bounds. // - A rough idea is to have monomorph return a third class of generic for params that are not yet bound. // - compare_with_placeholders gets called on both ivars and generics, so that can be used to replace it once known. - ::std::string placeholder_name = FMT("impl_?_" << &impl_params); + auto placeholder_name = RcString::new_interned(FMT("impl_?_" << &impl_params)); for(unsigned int i = 0; i < impl_params.size(); i ++ ) { if( !impl_params[i] ) { if( placeholders.size() == 0 ) @@ -3061,7 +3060,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, } namespace { - bool trait_contains_method_inner(const ::HIR::Trait& trait_ptr, const ::std::string& name, const ::HIR::Function*& out_fcn_ptr) + bool trait_contains_method_inner(const ::HIR::Trait& trait_ptr, const char* name, const ::HIR::Function*& out_fcn_ptr) { auto it = trait_ptr.m_values.find(name); if( it != trait_ptr.m_values.end() ) @@ -3076,7 +3075,7 @@ namespace { } } -const ::HIR::Function* TraitResolution::trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const ::std::string& name, ::HIR::GenericPath& out_path) const +const ::HIR::Function* TraitResolution::trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const char* name, ::HIR::GenericPath& out_path) const { TRACE_FUNCTION_FR("trait_path=" << trait_path << ",name=" << name, out_path); const ::HIR::Function* rv = nullptr; @@ -3101,7 +3100,7 @@ const ::HIR::Function* TraitResolution::trait_contains_method(const Span& sp, co } return nullptr; } -bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const +bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const char* name, ::HIR::GenericPath& out_path) const { TRACE_FUNCTION_FR(trait_path << " has " << name, out_path); @@ -3698,7 +3697,7 @@ const ::HIR::TypeRef* TraitResolution::autoderef(const Span& sp, const ::HIR::Ty } unsigned int TraitResolution::autoderef_find_method(const Span& sp, - const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, + const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& top_ty, const char* method_name, /* Out -> */::std::vector<::std::pair>& possibilities ) const { @@ -3906,7 +3905,7 @@ const ::HIR::TypeRef* TraitResolution::check_method_receiver(const Span& sp, con } bool TraitResolution::find_method(const Span& sp, - const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& ty, const ::std::string& method_name, MethodAccess access, + const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& ty, const char* method_name, MethodAccess access, AutoderefBorrow borrow_type, /* Out -> */::std::vector<::std::pair>& possibilities ) const { @@ -4259,7 +4258,7 @@ bool TraitResolution::find_method(const Span& sp, return rv; } -unsigned int TraitResolution::autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& field_name, /* Out -> */::HIR::TypeRef& field_type) const +unsigned int TraitResolution::autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const char* field_name, /* Out -> */::HIR::TypeRef& field_type) const { unsigned int deref_count = 0; ::HIR::TypeRef tmp_type; // Temporary type used for handling Deref @@ -4299,7 +4298,7 @@ unsigned int TraitResolution::autoderef_find_field(const Span& sp, const ::HIR:: this->m_ivars.dump(); TODO(sp, "Error when no field could be found, but type is known - (: " << top_ty << ")." << field_name); } -bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_ty) const +bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const char* name, /* Out -> */::HIR::TypeRef& field_ty) const { TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e, TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be), diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index dd9a1581..00befd63 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -207,7 +207,7 @@ public: bool iterate_bounds_traits(const Span& sp, ::std::function cb) const; bool iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function cb) const; - typedef ::std::function&)> t_cb_trait_impl; + typedef ::std::function&)> t_cb_trait_impl; typedef ::std::function t_cb_trait_impl_r; /// Searches for a trait impl that matches the provided trait name and type @@ -250,17 +250,17 @@ public: /// Locate the named method by applying auto-dereferencing. /// \return Number of times deref was applied (or ~0 if _ was hit) unsigned int autoderef_find_method(const Span& sp, - const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, + const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& top_ty, const char* method_name, /* Out -> */::std::vector<::std::pair>& possibilities ) const; /// Locate the named field by applying auto-dereferencing. /// \return Number of times deref was applied (or ~0 if _ was hit) - unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; + unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const char* name, /* Out -> */::HIR::TypeRef& field_type) const; /// Apply an automatic dereference const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const; - bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; + bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const char* name, /* Out -> */::HIR::TypeRef& field_type) const; enum class MethodAccess { Shared, @@ -279,13 +279,13 @@ public: }; friend ::std::ostream& operator<<(::std::ostream& os, const AllowedReceivers& x); bool find_method(const Span& sp, - const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& ty, const ::std::string& method_name, MethodAccess access, + const HIR::t_trait_list& traits, const ::std::vector& ivars, const ::HIR::TypeRef& ty, const char* method_name, MethodAccess access, AutoderefBorrow borrow_type, /* Out -> */::std::vector<::std::pair>& possibilities ) const; /// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters) - const ::HIR::Function* trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const ::std::string& name, ::HIR::GenericPath& out_path) const; - bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const; + const ::HIR::Function* trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const char* name, ::HIR::GenericPath& out_path) const; + bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const char* name, ::HIR::GenericPath& out_path) const; ::HIR::Compare type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) const; ::HIR::Compare type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const; diff --git a/src/hir_typeck/impl_ref.hpp b/src/hir_typeck/impl_ref.hpp index 84d0b404..c67c8a81 100644 --- a/src/hir_typeck/impl_ref.hpp +++ b/src/hir_typeck/impl_ref.hpp @@ -27,12 +27,12 @@ struct ImplRef (BoundedPtr, struct { const ::HIR::TypeRef* type; const ::HIR::PathParams* trait_args; - const ::std::map< ::std::string, ::HIR::TypeRef>* assoc; + const ::std::map< RcString, ::HIR::TypeRef>* assoc; }), (Bounded, struct { ::HIR::TypeRef type; ::HIR::PathParams trait_args; - ::std::map< ::std::string, ::HIR::TypeRef> assoc; + ::std::map< RcString, ::HIR::TypeRef> assoc; }) ); @@ -45,10 +45,10 @@ struct ImplRef m_data(Data::make_TraitImpl({ mv$(params), mv$(params_ph), &trait, &impl })) {} - ImplRef(const ::HIR::TypeRef* type, const ::HIR::PathParams* args, const ::std::map< ::std::string, ::HIR::TypeRef>* assoc): + ImplRef(const ::HIR::TypeRef* type, const ::HIR::PathParams* args, const ::std::map< RcString, ::HIR::TypeRef>* assoc): m_data(Data::make_BoundedPtr({ type, mv$(args), mv$(assoc) })) {} - ImplRef(::HIR::TypeRef type, ::HIR::PathParams args, ::std::map< ::std::string, ::HIR::TypeRef> assoc): + ImplRef(::HIR::TypeRef type, ::HIR::PathParams args, ::std::map< RcString, ::HIR::TypeRef> assoc): m_data(Data::make_Bounded({ mv$(type), mv$(args), mv$(assoc) })) {} diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 6a8e8b35..c2b216d4 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -322,8 +322,9 @@ namespace { else if( m_fcn_ptr ) { size_t idx = m_fcn_ptr->m_params.m_types.size(); - auto new_ty = ::HIR::TypeRef( FMT("impl$" << idx), 256 + idx ); - m_fcn_ptr->m_params.m_types.push_back({ FMT("impl$" << idx), ::HIR::TypeRef(), true }); + auto name = RcString::new_interned(FMT("impl$" << idx)); + auto new_ty = ::HIR::TypeRef( name, 256 + idx ); + m_fcn_ptr->m_params.m_types.push_back({ name, ::HIR::TypeRef(), true }); for( const auto& trait : e.m_traits ) { m_fcn_ptr->m_params.m_bounds.push_back(::HIR::GenericBound::make_TraitBound({ diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index c71e71d7..0c0f1859 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -97,7 +97,7 @@ bool StaticTraitResolve::find_impl( auto cb_ident = [](const ::HIR::TypeRef&ty)->const ::HIR::TypeRef& { return ty; }; static ::HIR::PathParams null_params; - static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc; + static ::std::map null_assoc; if( !dont_handoff_to_specialised ) { if( trait_path == m_lang_Copy ) { @@ -159,7 +159,7 @@ bool StaticTraitResolve::find_impl( { trait_params = &null_params; } - ::std::map< ::std::string, ::HIR::TypeRef> assoc; + ::std::map< RcString, ::HIR::TypeRef> assoc; assoc.insert( ::std::make_pair("Output", e.m_rettype->clone()) ); return found_cb( ImplRef(type.clone(), trait_params->clone(), mv$(assoc)), false ); } @@ -200,7 +200,7 @@ bool StaticTraitResolve::find_impl( case ::HIR::ExprNode_Closure::Class::Shared: break; } - ::std::map< ::std::string, ::HIR::TypeRef> assoc; + ::std::map< RcString, ::HIR::TypeRef> assoc; assoc.insert( ::std::make_pair("Output", e->m_rettype->clone()) ); return found_cb( ImplRef(type.clone(), trait_params->clone(), mv$(assoc)), false ); } @@ -223,7 +223,7 @@ bool StaticTraitResolve::find_impl( if( trait_path == mt.m_path ) { if( !trait_params || mt.m_params == *trait_params ) { - static ::std::map< ::std::string, ::HIR::TypeRef> types; + static ::std::map< RcString, ::HIR::TypeRef> types; return found_cb( ImplRef(&type, &mt.m_params, &types), false ); } } @@ -235,7 +235,7 @@ bool StaticTraitResolve::find_impl( bool is_supertrait = trait_params && this->find_named_trait_in_trait(sp, trait_path,*trait_params, *e.m_trait.m_trait_ptr, e.m_trait.m_path.m_path,e.m_trait.m_path.m_params, type, [&](const auto& i_params, const auto& i_assoc) { // Invoke callback with a proper ImplRef - ::std::map< ::std::string, ::HIR::TypeRef> assoc_clone; + ::std::map< RcString, ::HIR::TypeRef> assoc_clone; for(const auto& e : i_assoc) assoc_clone.insert( ::std::make_pair(e.first, e.second.clone()) ); // HACK! Just add all the associated type bounds (only inserted if not already present) @@ -265,7 +265,7 @@ bool StaticTraitResolve::find_impl( bool is_supertrait = trait_params && this->find_named_trait_in_trait(sp, trait_path,*trait_params, *trait.m_trait_ptr, trait.m_path.m_path,trait.m_path.m_params, type, [&](const auto& i_params, const auto& i_assoc) { // Invoke callback with a proper ImplRef - ::std::map< ::std::string, ::HIR::TypeRef> assoc_clone; + ::std::map< RcString, ::HIR::TypeRef> assoc_clone; for(const auto& e : i_assoc) assoc_clone.insert( ::std::make_pair(e.first, e.second.clone()) ); // HACK! Just add all the associated type bounds (only inserted if not already present) @@ -312,7 +312,7 @@ bool StaticTraitResolve::find_impl( { if( &b_params_mono == ¶ms_mono_o || ::std::any_of(bound.m_type_bounds.begin(), bound.m_type_bounds.end(), [&](const auto& x){ return monomorphise_type_needed(x.second); }) ) { - ::std::map< ::std::string, ::HIR::TypeRef> atys; + ::std::map< RcString, ::HIR::TypeRef> atys; if( ! bound.m_type_bounds.empty() ) { for(const auto& tb : bound.m_type_bounds) @@ -722,7 +722,7 @@ bool StaticTraitResolve::find_impl__check_crate_raw( const ::HIR::TypeRef& exp = assoc_bound.second; ::HIR::GenericPath aty_src_trait; - trait_contains_type(sp, b_tp_mono.m_path, *e.trait.m_trait_ptr, aty_name, aty_src_trait); + trait_contains_type(sp, b_tp_mono.m_path, *e.trait.m_trait_ptr, aty_name.c_str(), aty_src_trait); bool rv = false; if( b_ty_mono.m_data.is_Generic() && (b_ty_mono.m_data.as_Generic().binding >> 8) == 2 ) { @@ -1241,7 +1241,7 @@ bool StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI // - Search for the actual trait containing this associated type ::HIR::GenericPath trait_path; - if( !this->trait_contains_type(sp, e2.trait, this->m_crate.get_trait_by_path(sp, e2.trait.m_path), e2.item, trait_path) ) + if( !this->trait_contains_type(sp, e2.trait, this->m_crate.get_trait_by_path(sp, e2.trait.m_path), e2.item.c_str(), trait_path) ) BUG(sp, "Cannot find associated type " << e2.item << " anywhere in trait " << e2.trait); //e2.trait = mv$(trait_path); @@ -1382,7 +1382,7 @@ bool StaticTraitResolve::find_named_trait_in_trait(const Span& sp, const ::HIR::SimplePath& des, const ::HIR::PathParams& des_params, const ::HIR::Trait& trait_ptr, const ::HIR::SimplePath& trait_path, const ::HIR::PathParams& pp, const ::HIR::TypeRef& target_type, - ::std::function)> callback + ::std::function)> callback ) const { TRACE_FUNCTION_F(des << des_params << " from " << trait_path << pp); @@ -1423,7 +1423,7 @@ bool StaticTraitResolve::find_named_trait_in_trait(const Span& sp, return false; } -bool StaticTraitResolve::trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const +bool StaticTraitResolve::trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const char* name, ::HIR::GenericPath& out_path) const { TRACE_FUNCTION_FR("name="<~RcString(); m_ptr = x.m_ptr; - m_len = x.m_len; if( m_ptr ) *m_ptr += 1; } return *this; @@ -62,27 +60,76 @@ public: { this->~RcString(); m_ptr = x.m_ptr; - m_len = x.m_len; x.m_ptr = nullptr; - x.m_len = 0; } return *this; } + const char* begin() const { return c_str(); } + const char* end() const { return c_str() + size(); } + size_t size() const { return m_ptr ? m_ptr[1] : 0; } const char* c_str() const { - if( m_len > 0 ) + if( m_ptr ) { - return reinterpret_cast(m_ptr + 1); + return reinterpret_cast(m_ptr + 2); } else { return ""; } } - bool operator==(const RcString& s) const { return *this == s.c_str(); } + + char back() const { + assert(size() > 0 ); + return *(c_str() + size() - 1); + } + + Ordering ord(const RcString& s) const; + bool operator==(const RcString& s) const { + if(s.size() != this->size()) + return false; + return this->ord(s) == OrdEqual; + } + bool operator!=(const RcString& s) const { + if(s.size() != this->size()) + return true; + return this->ord(s) != OrdEqual; + } + bool operator<(const RcString& s) const { return this->ord(s) == OrdLess; } + bool operator>(const RcString& s) const { return this->ord(s) == OrdGreater; } + + Ordering ord(const std::string& s) const; + bool operator==(const std::string& s) const { return this->ord(s) == OrdEqual; } + bool operator!=(const std::string& s) const { return this->ord(s) != OrdEqual; } + bool operator<(const std::string& s) const { return this->ord(s) == OrdLess; } + bool operator>(const std::string& s) const { return this->ord(s) == OrdGreater; } bool operator==(const char* s) const; - friend ::std::ostream& operator<<(::std::ostream& os, const RcString& x) { - return os << x.c_str(); + bool operator!=(const char* s) const { return !(*this == s); } + friend ::std::ostream& operator<<(::std::ostream& os, const RcString& x); + + friend bool operator==(const char* a, const RcString& b) { + return b == a; + } + friend bool operator!=(const char* a, const RcString& b) { + return b != a; + } + + int compare(size_t o, size_t l, const char* s) const { + assert(o <= this->size()); + return memcmp(this->c_str() + o, s, l); } }; + +namespace std { + static inline bool operator==(const string& a, const ::RcString& b) { + return b == a; + } + static inline bool operator!=(const string& a, const ::RcString& b) { + return b != a; + } + template<> struct hash + { + size_t operator()(const RcString& s) const noexcept; + }; +} diff --git a/src/include/synext_macro.hpp b/src/include/synext_macro.hpp index d414ceb0..e62a6126 100644 --- a/src/include/synext_macro.hpp +++ b/src/include/synext_macro.hpp @@ -27,7 +27,10 @@ class TokenStream; class ExpandProcMacro { public: - virtual ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) = 0; + virtual ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const TokenTree& tt, AST::Module& mod) = 0; + virtual ::std::unique_ptr expand_ident(const Span& sp, const AST::Crate& crate, const RcString& ident, const TokenTree& tt, AST::Module& mod) { + ERROR(sp, E0000, "macro doesn't take an identifier"); + } }; struct MacroDef; diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp index c40eb810..2d1b6bb1 100644 --- a/src/macro_rules/eval.cpp +++ b/src/macro_rules/eval.cpp @@ -405,7 +405,7 @@ class MacroExpander: { const RcString m_macro_filename; - const ::std::string m_crate_name; + const RcString m_crate_name; ::std::shared_ptr m_invocation_span; ParameterMappings m_mappings; @@ -418,7 +418,7 @@ class MacroExpander: public: MacroExpander(const MacroExpander& x) = delete; - MacroExpander(const ::std::string& macro_name, const Span& sp, const Ident::Hygiene& parent_hygiene, const ::std::vector& contents, ParameterMappings mappings, ::std::string crate_name): + MacroExpander(const ::std::string& macro_name, const Span& sp, const Ident::Hygiene& parent_hygiene, const ::std::vector& contents, ParameterMappings mappings, RcString crate_name): m_macro_filename( FMT("Macro:" << macro_name) ), m_crate_name( mv$(crate_name) ), m_invocation_span( new Span(sp) ), @@ -841,7 +841,7 @@ namespace case TOK_SQUARE_OPEN: return consume_tt(lex); case TOK_IDENT: - if( TARGETVER_1_29 && lex.next_tok().str() == "dyn" ) + if( TARGETVER_1_29 && lex.next_tok().istr() == "dyn" ) lex.consume(); case TOK_RWORD_SUPER: case TOK_RWORD_SELF: @@ -1345,7 +1345,7 @@ namespace return true; // Macro invocation // TODO: What about `union!` as a macro? Needs to be handled below - if( (lex.next() == TOK_IDENT && lex.next_tok().str() != "union") + if( (lex.next() == TOK_IDENT && lex.next_tok().istr() != "union") || lex.next() == TOK_RWORD_SELF || lex.next() == TOK_RWORD_SUPER || lex.next() == TOK_DOUBLE_COLON @@ -1481,7 +1481,7 @@ namespace return false; return consume_tt(lex); case TOK_IDENT: - if( lex.next_tok().str() == "union" ) + if( lex.next_tok().istr() == "union" ) { lex.consume(); if( lex.next() == TOK_EXCLAM ) @@ -1506,7 +1506,7 @@ namespace return consume_tt(lex); } } - else if( lex.next_tok().str() == "auto" ) + else if( lex.next_tok().istr() == "auto" ) { lex.consume(); if( lex.consume_if(TOK_RWORD_TRAIT) ) @@ -1960,7 +1960,7 @@ Token MacroExpander::realGetToken() DEBUG("Crate name hack"); if( m_crate_name != "" ) { - m_next_token = Token(TOK_STRING, m_crate_name); + m_next_token = Token(TOK_STRING, ::std::string(m_crate_name.c_str())); return Token(TOK_DOUBLE_COLON); } break; diff --git a/src/macro_rules/macro_rules.hpp b/src/macro_rules/macro_rules.hpp index 9e408fd5..05b1e065 100644 --- a/src/macro_rules/macro_rules.hpp +++ b/src/macro_rules/macro_rules.hpp @@ -41,7 +41,7 @@ extern ::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x /// Matching pattern entry struct MacroPatEnt { - ::std::string name; + RcString name; unsigned int name_index = 0; // TODO: Include a point span for the token? Token tok; @@ -77,7 +77,7 @@ struct MacroPatEnt { } - MacroPatEnt(::std::string name, unsigned int name_index, Type type): + MacroPatEnt(RcString name, unsigned int name_index, Type type): name( mv$(name) ), name_index( name_index ), tok(), @@ -134,7 +134,7 @@ extern::std::ostream& operator<<(::std::ostream& os, const SimplePatEnt& x); struct MacroRulesArm { /// Names for the parameters - ::std::vector< ::std::string> m_param_names; + ::std::vector m_param_names; /// Patterns ::std::vector m_pattern; @@ -164,7 +164,7 @@ public: /// Crate that defined this macro /// - Populated on deserialise if not already set - ::std::string m_source_crate; + RcString m_source_crate; Ident::Hygiene m_hygiene; @@ -181,8 +181,8 @@ public: extern ::std::unique_ptr Macro_InvokeRules(const char *name, const MacroRules& rules, const Span& sp, TokenTree input, AST::Module& mod); extern MacroRulesPtr Parse_MacroRules(TokenStream& lex); -extern ::std::vector Parse_MacroRules_Pat(TokenStream& lex, enum eTokenType open, enum eTokenType close, ::std::vector< ::std::string>& names); -extern ::std::vector Parse_MacroRules_Cont(TokenStream& lex, enum eTokenType open, enum eTokenType close, const ::std::vector< ::std::string>& var_names, ::std::map* var_set_ptr=nullptr); +extern ::std::vector Parse_MacroRules_Pat(TokenStream& lex, enum eTokenType open, enum eTokenType close, ::std::vector& names); +extern ::std::vector Parse_MacroRules_Cont(TokenStream& lex, enum eTokenType open, enum eTokenType close, const ::std::vector& var_names, ::std::map* var_set_ptr=nullptr); extern MacroRulesArm Parse_MacroRules_MakeArm(Span pat_sp, ::std::vector pattern, ::std::vector contents); #endif // MACROS_HPP_INCLUDED diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp index 4bd8a577..97e1f8f9 100644 --- a/src/macro_rules/parse.cpp +++ b/src/macro_rules/parse.cpp @@ -30,7 +30,7 @@ public: }; /// Parse the pattern of a macro_rules! arm -::std::vector Parse_MacroRules_Pat(TokenStream& lex, enum eTokenType open, enum eTokenType close, ::std::vector< ::std::string>& names) +::std::vector Parse_MacroRules_Pat(TokenStream& lex, enum eTokenType open, enum eTokenType close, ::std::vector& names) { TRACE_FUNCTION; Token tok; @@ -60,10 +60,10 @@ public: // TODO: Allow any reserved word case TOK_RWORD_PUB ... TOK_RWORD_UNSIZED: case TOK_IDENT: { - ::std::string name = tok.type() == TOK_IDENT ? mv$(tok.str()) : FMT(tok); + auto name = tok.type() == TOK_IDENT ? tok.istr() : RcString::new_interned(FMT(tok)); GET_CHECK_TOK(tok, lex, TOK_COLON); GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string type = mv$(tok.str()); + RcString type = tok.istr(); unsigned int idx = ::std::find( names.begin(), names.end(), name ) - names.begin(); if( idx == names.size() ) @@ -142,7 +142,7 @@ public: ::std::vector Parse_MacroRules_Cont( TokenStream& lex, enum eTokenType open, enum eTokenType close, - const ::std::vector< ::std::string>& var_names, + const ::std::vector& var_names, ::std::map* var_set_ptr/*=nullptr*/ ) { @@ -221,7 +221,7 @@ public: else if( tok.type() == TOK_IDENT || tok.type() >= TOK_RWORD_PUB ) { // Look up the named parameter in the list of param names for this arm - auto name = tok.type() == TOK_IDENT ? tok.str() : FMT(tok); + auto name = tok.type() == TOK_IDENT ? tok.istr() : RcString::new_interned(FMT(tok)); unsigned int idx = ::std::find(var_names.begin(), var_names.end(), name) - var_names.begin(); if( idx == var_names.size() ) { // TODO: `error-chain`'s quick_error macro has an arm which refers to an undefined metavar. @@ -269,7 +269,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex) throw ParseError::Unexpected(lex, tok); } // - Pattern entries - ::std::vector< ::std::string> names; + ::std::vector names; { auto ps = lex.start_span(); rule.m_pattern = Parse_MacroRules_Pat(lex, tok.type(), close, names); @@ -294,7 +294,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex) } // TODO: Also count the number of times each variable is used? -void enumerate_names(const ::std::vector& pats, ::std::vector< ::std::string>& names) +void enumerate_names(const ::std::vector& pats, ::std::vector& names) { for( const auto& pat : pats ) { diff --git a/src/main.cpp b/src/main.cpp index 5ffc195a..28d34da4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -351,9 +351,9 @@ int main(int argc, char *argv[]) if( crate.m_crate_type == ::AST::Crate::Type::Executable || params.test_harness || crate.m_crate_type == ::AST::Crate::Type::ProcMacro ) { bool allocator_crate_loaded = false; - ::std::string alloc_crate_name; + RcString alloc_crate_name; bool panic_runtime_loaded = false; - ::std::string panic_crate_name; + RcString panic_crate_name; bool panic_runtime_needed = false; for(const auto& ec : crate.m_extern_crates) { diff --git a/src/mir/check.cpp b/src/mir/check.cpp index b5abdb0a..0b032bbc 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -19,7 +19,6 @@ namespace { if( const auto* tep = unsized_ty.m_data.opt_TraitObject() ) { const auto& trait_path = tep->m_trait; - const auto& trait = *tep->m_trait.m_trait_ptr; if( trait_path.m_path.m_path == ::HIR::SimplePath() ) { @@ -27,8 +26,10 @@ namespace { } else { - auto vtable_ty_spath = trait_path.m_path.m_path; - vtable_ty_spath.m_components.back() += "#vtable"; + const auto& trait = *tep->m_trait.m_trait_ptr; + + const auto& vtable_ty_spath = trait.m_vtable_path; + MIR_ASSERT(state, vtable_ty_spath != ::HIR::SimplePath(), "Trait with no vtable - " << trait_path); const auto& vtable_ref = state.m_resolve.m_crate.get_struct_by_path(state.sp, vtable_ty_spath); // Copy the param set from the trait in the trait object ::HIR::PathParams vtable_params = trait_path.m_path.m_params.clone(); diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index dd5332b6..5d32d0c8 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -75,8 +75,7 @@ namespace { { const auto& trait = *te.m_trait.m_trait_ptr; - auto vtable_ty_spath = te.m_trait.m_path.m_path; - vtable_ty_spath.m_components.back() += "#vtable"; + const auto& vtable_ty_spath = trait.m_vtable_path; const auto& vtable_ref = resolve.m_crate.get_struct_by_path(sp, vtable_ty_spath); // Copy the param set from the trait in the trait object ::HIR::PathParams vtable_params = te.m_trait.m_path.m_params.clone(); @@ -676,8 +675,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& const auto& trait = *de.m_trait.m_trait_ptr; // Obtain vtable type `::"path"::to::Trait#vtable` - auto vtable_ty_spath = trait_path.m_path.m_path; - vtable_ty_spath.m_components.back() += "#vtable"; + const auto& vtable_ty_spath = trait.m_vtable_path; const auto& vtable_ref = state.m_crate.get_struct_by_path(state.sp, vtable_ty_spath); // Copy the param set from the trait in the trait object ::HIR::PathParams vtable_params = trait_path.m_path.m_params.clone(); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index b8549f8a..9e749811 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -51,7 +51,7 @@ namespace { struct LoopDesc { ScopeHandle scope; - ::std::string label; + RcString label; unsigned int cur; unsigned int next; ::MIR::LValue res_value; @@ -679,7 +679,7 @@ namespace { target_block = &*it; } else { - if( target_block->label != "" && target_block->label[0] == '#' ) { + if( target_block->label != "" && target_block->label.c_str()[0] == '#' ) { TODO(node.span(), "Break within try block, want to break parent loop instead"); } } @@ -1952,7 +1952,7 @@ namespace { { m_builder.end_block(::MIR::Terminator::make_Call({ next_block, panic_block, - res.clone(), ::MIR::CallTarget::make_Intrinsic({ "platform:"+gpath.m_path.m_components.back(), gpath.m_params.clone() }), + res.clone(), ::MIR::CallTarget::make_Intrinsic({ RcString(FMT("platform:" << gpath.m_path.m_components.back())), gpath.m_params.clone() }), mv$(values) })); } @@ -2054,8 +2054,8 @@ namespace { const auto& val_ty = node.m_value->m_res_type; unsigned int idx; - if( '0' <= node.m_field[0] && node.m_field[0] <= '9' ) { - ::std::stringstream(node.m_field) >> idx; + if( ::std::isdigit(node.m_field.c_str()[0]) ) { + ::std::stringstream(node.m_field.c_str()) >> idx; m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); } else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Struct() ) { diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index ebef039a..63acf89d 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -311,7 +311,7 @@ TAGGED_UNION(CallTarget, Intrinsic, (Value, LValue), (Path, ::HIR::Path), (Intrinsic, struct { - ::std::string name; + RcString name; ::HIR::PathParams params; }) ); @@ -419,7 +419,7 @@ class Function { public: ::std::vector< ::HIR::TypeRef> locals; - //::std::vector< ::std::string> local_names; + //::std::vector< RcString> local_names; ::std::vector drop_flags; ::std::vector blocks; diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 6ee0d3f4..d4a1d59a 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -46,7 +46,7 @@ extern ::AST::HigherRankedBounds Parse_HRB_Opt(TokenStream& lex); extern AST::AttributeList Parse_ItemAttrs(TokenStream& lex); extern void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out); extern AST::Attribute Parse_MetaItem(TokenStream& lex); -extern ::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan ps, ::std::string name, TokenStream& lex); +extern ::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan ps, RcString name, TokenStream& lex); extern TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list = true); extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 6cc94d74..2735c39e 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -32,8 +32,8 @@ ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon); ExprNodeP Parse_Stmt_Let(TokenStream& lex); ExprNodeP Parse_Expr0(TokenStream& lex); ExprNodeP Parse_IfStmt(TokenStream& lex); -ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime); -ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime); +ExprNodeP Parse_WhileStmt(TokenStream& lex, RcString lifetime); +ExprNodeP Parse_ForStmt(TokenStream& lex, RcString lifetime); ExprNodeP Parse_Expr_Match(TokenStream& lex); ExprNodeP Parse_Expr1(TokenStream& lex); ExprNodeP Parse_ExprMacro(TokenStream& lex, AST::Path tok); @@ -108,7 +108,7 @@ ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptrgetc(); } this->ungetc(); - return Token(TOK_LIFETIME, str); + return Token(TOK_LIFETIME, RcString::new_interned(str)); } else { throw ParseError::Todo("Lex Fail - Expected ' after character constant"); @@ -728,7 +728,7 @@ Token Lexer::getTokenInt() str += ch; } } - return Token(TOK_STRING, str); + return Token(TOK_STRING, mv$(str)); } default: assert(!"bugcheck"); @@ -806,7 +806,7 @@ Token Lexer::getTokenInt_RawString(bool is_byte) } } } - return Token(is_byte ? TOK_BYTESTRING : TOK_STRING, val); + return Token(is_byte ? TOK_BYTESTRING : TOK_STRING, mv$(val)); } Token Lexer::getTokenInt_Identifier(Codepoint leader, Codepoint leader2) { @@ -826,7 +826,7 @@ Token Lexer::getTokenInt_Identifier(Codepoint leader, Codepoint leader2) if( str < RWORDS[i].chars ) break; if( str == RWORDS[i].chars ) return Token((enum eTokenType)RWORDS[i].type); } - return Token(TOK_IDENT, mv$(str)); + return Token(TOK_IDENT, RcString::new_interned(str)); } // Takes the VERY lazy way of reading the float into a string then passing to strtod diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp index 5c99e049..8bfd20de 100644 --- a/src/parse/paths.cpp +++ b/src/parse/paths.cpp @@ -90,7 +90,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi return AST::Path("", Parse_PathNodes(lex, generic_mode)); } else if( GET_TOK(tok, lex) == TOK_STRING ) { - ::std::string cratename = tok.str(); + auto cratename = RcString::new_interned(tok.str()); GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); return AST::Path(cratename, Parse_PathNodes(lex, generic_mode)); } @@ -122,7 +122,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi ::AST::PathParams params; CHECK_TOK(tok, TOK_IDENT); - auto component = mv$( tok.str() ); + auto component = mv$( tok.istr() ); GET_TOK(tok, lex); if( generic_mode == PATH_GENERIC_TYPE ) @@ -166,7 +166,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi params = ::AST::PathParams { {}, ::make_vec1( TypeRef(TypeRef::TagTuple(), lex.end_span(ps), mv$(args)) ), - ::make_vec1( ::std::make_pair( ::std::string("Output"), mv$(ret_type) ) ) + ::make_vec1( ::std::make_pair( RcString::new_interned("Output"), mv$(ret_type) ) ) }; GET_TOK(tok, lex); @@ -210,7 +210,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi ::std::vector types; ::std::vector lifetimes; - ::std::vector< ::std::pair< ::std::string, TypeRef > > assoc_bounds; + ::std::vector< ::std::pair< RcString, TypeRef > > assoc_bounds; do { if( LOOK_AHEAD(lex) == TOK_GT || LOOK_AHEAD(lex) == TOK_DOUBLE_GT || LOOK_AHEAD(lex) == TOK_GTE || LOOK_AHEAD(lex) == TOK_DOUBLE_GT_EQUAL ) { @@ -225,7 +225,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi case TOK_IDENT: if( LOOK_AHEAD(lex) == TOK_EQUAL ) { - ::std::string name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_EQUAL); assoc_bounds.push_back( ::std::make_pair( mv$(name), Parse_Type(lex,false) ) ); break; diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index 239bac80..37b78123 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -46,7 +46,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) if( tok.type() == TOK_IDENT && lex.lookahead(0) == TOK_EXCLAM ) { lex.getToken(); - return AST::Pattern( AST::Pattern::TagMacro(), lex.end_span(ps), box$(Parse_MacroInvocation(ps, tok.str(), lex))); + return AST::Pattern( AST::Pattern::TagMacro(), lex.end_span(ps), box$(Parse_MacroInvocation(ps, tok.istr(), lex))); } if( tok.type() == TOK_INTERPOLATED_PATTERN ) { @@ -87,7 +87,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) if( expect_bind ) { CHECK_TOK(tok, TOK_IDENT); - auto bind_name = Ident(lex.getHygiene(), mv$(tok.str())); + auto bind_name = lex.get_ident(mv$(tok)); // If there's no '@' after it, it's a name binding only (_ pattern) if( GET_TOK(tok, lex) != TOK_AT ) { @@ -117,12 +117,12 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) break; // Known binding `ident @` case TOK_AT: - binding = AST::PatternBinding( Ident(lex.getHygiene(), mv$(tok.str())), bind_type/*MOVE*/, is_mut/*false*/ ); + binding = AST::PatternBinding( lex.get_ident(mv$(tok)), bind_type/*MOVE*/, is_mut/*false*/ ); GET_TOK(tok, lex); // '@' GET_TOK(tok, lex); // Match lex.putback() below break; default: { // Maybe bind - Ident name = Ident(lex.getHygiene(), mv$(tok.str())); + auto name = lex.get_ident(mv$(tok)); // if the pattern can be refuted (i.e this could be an enum variant), return MaybeBind if( is_refutable ) { assert(bind_type == ::AST::PatternBinding::Type::MOVE); @@ -459,7 +459,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, } bool is_exhaustive = true; - ::std::vector< ::std::pair< ::std::string, AST::Pattern> > subpats; + ::std::vector< ::std::pair< RcString, AST::Pattern> > subpats; do { GET_TOK(tok, lex); DEBUG("tok = " << tok); @@ -500,7 +500,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, CHECK_TOK(tok, TOK_IDENT); auto field_ident = lex.get_ident(mv$(tok)); - ::std::string field_name; + RcString field_name; GET_TOK(tok, lex); AST::Pattern pat; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index b0c37a21..677dbe26 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -21,6 +21,7 @@ #include #include #include +#include template Spanned get_spanned(TokenStream& lex, ::std::function f) { @@ -36,7 +37,7 @@ Spanned get_spanned(TokenStream& lex, ::std::function f) { // Check the next two tokens #define LOOKAHEAD2(lex, tok1, tok2) ((lex).lookahead(0) == (tok1) && (lex).lookahead(1) == (tok2)) -::std::string dirname(::std::string input) { +::helpers::path dirname(::std::string input) { while( input.size() > 0 && input.back() != '/' && input.back() != '\\' ) { input.pop_back(); } @@ -110,12 +111,12 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv) GET_CHECK_TOK(tok, lex, TOK_IDENT); case TOK_RWORD_IN: GET_CHECK_TOK(tok, lex, TOK_IDENT); - path.nodes().push_back( AST::PathNode(tok.str()) ); + path.nodes().push_back( AST::PathNode(tok.istr()) ); while( LOOK_AHEAD(lex) == TOK_DOUBLE_COLON ) { GET_TOK(tok, lex); GET_CHECK_TOK(tok, lex, TOK_IDENT); - path.nodes().push_back( AST::PathNode(tok.str()) ); + path.nodes().push_back( AST::PathNode(tok.istr()) ); } break; default: @@ -149,7 +150,7 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv) switch(GET_TOK(tok, lex)) { case TOK_LIFETIME: - rv.m_lifetimes.push_back(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), Ident(lex.getHygiene(), tok.str()))); + rv.m_lifetimes.push_back(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), lex.get_ident(mv$(tok)))); break; default: throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME)); @@ -175,7 +176,7 @@ namespace { AST::LifetimeRef get_LifetimeRef(TokenStream& lex, Token tok) { CHECK_TOK(tok, TOK_LIFETIME); - return AST::LifetimeRef(/*lex.point_span(), */Ident(lex.getHygiene(), mv$(tok.str()))); + return AST::LifetimeRef(/*lex.point_span(), */lex.get_ident(mv$(tok))); } } /// Parse type parameters in a definition @@ -242,7 +243,7 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex) GET_TOK(tok, lex); if( tok.type() == TOK_IDENT ) { - ::std::string param_name = mv$(tok.str()); + auto param_name = tok.istr(); ret.add_ty_param( AST::TypeParam( lex.point_span(), ::std::move(attrs), param_name ) ); auto param_ty = TypeRef(lex.point_span(), param_name); @@ -260,7 +261,7 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex) } else if( tok.type() == TOK_LIFETIME ) { - auto param_name = tok.str(); + auto param_name = tok.istr(); auto ref = get_LifetimeRef(lex, mv$(tok)); ret.add_lft_param(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), Ident(lex.getHygiene(), param_name) )); if( GET_TOK(tok, lex) == TOK_COLON ) @@ -621,7 +622,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::AttributeList& meta_items) bool is_pub = Parse_Publicity(lex); GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); TypeRef type = Parse_Type(lex); @@ -658,7 +659,7 @@ AST::Named Parse_Trait_Item(TokenStream& lex) GET_TOK(tok, lex); bool is_specialisable = false; - if( tok.type() == TOK_IDENT && tok.str() == "default" ) { + if( tok.type() == TOK_IDENT && tok.istr() == "default" ) { is_specialisable = true; GET_TOK(tok, lex); } @@ -669,13 +670,13 @@ AST::Named Parse_Trait_Item(TokenStream& lex) bool fn_is_unsafe = false; ::std::string abi = ABI_RUST; - ::std::string name; + RcString name; ::AST::Item rv; switch(tok.type()) { case TOK_RWORD_STATIC: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); + name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); auto ty = Parse_Type(lex); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); @@ -691,7 +692,7 @@ AST::Named Parse_Trait_Item(TokenStream& lex) break; } case TOK_RWORD_CONST: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); + name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); auto ty = Parse_Type(lex); @@ -708,7 +709,7 @@ AST::Named Parse_Trait_Item(TokenStream& lex) case TOK_RWORD_TYPE: { auto atype_params = ::AST::GenericParams { }; GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); + name = tok.istr(); if( GET_TOK(tok, lex) == TOK_COLON ) { // Bounded associated type @@ -746,7 +747,7 @@ AST::Named Parse_Trait_Item(TokenStream& lex) CHECK_TOK(tok, TOK_RWORD_FN); case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); + name = tok.istr(); // Self allowed, prototype-form allowed (optional names and no code) auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const); if( GET_TOK(tok, lex) == TOK_BRACE_OPEN ) @@ -863,7 +864,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::AttributeList& meta_items) SET_ATTRS(lex, item_attrs); GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string name = mv$(tok.str()); + auto name = tok.istr(); // Tuple-like variants if( GET_TOK(tok, lex) == TOK_PAREN_OPEN ) { @@ -901,7 +902,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::AttributeList& meta_items) auto field_attrs = Parse_ItemAttrs(lex); GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); auto ty = Parse_Type(lex); fields.push_back( ::AST::StructItem(mv$(field_attrs), true, mv$(name), mv$(ty)) ); @@ -966,7 +967,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::AttributeList& meta_items) bool is_pub = Parse_Publicity(lex); GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); auto ty = Parse_Type(lex); @@ -1029,7 +1030,7 @@ AST::Attribute Parse_MetaItem(TokenStream& lex) throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_INTEGER}); } - ::std::string name = mv$(tok.str()); + auto name = tok.istr(); switch(GET_TOK(tok, lex)) { case TOK_EQUAL: @@ -1199,7 +1200,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) GET_TOK(tok, lex); bool is_specialisable = false; - if( tok.type() == TOK_IDENT && tok.str() == "default" ) { + if( tok.type() == TOK_IDENT && tok.istr() == "default" ) { is_specialisable = true; GET_TOK(tok, lex); } @@ -1211,7 +1212,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) { case TOK_RWORD_TYPE: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_EQUAL); impl.add_type(is_public, is_specialisable, name, Parse_Type(lex)); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); @@ -1226,7 +1227,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE && !fn_is_unsafe ) { CHECK_TOK(tok, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); auto ty = Parse_Type(lex); GET_CHECK_TOK(tok, lex, TOK_EQUAL); @@ -1261,7 +1262,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); // TODO: Hygine on function names? - Not in impl blocks? - ::std::string name = mv$(tok.str()); + auto name = tok.istr(); DEBUG("Function " << name); // - Self allowed, can't be prototype-form auto fcn = Parse_FunctionDefWithCode(lex, abi, true, fn_is_unsafe, fn_is_const); @@ -1298,7 +1299,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::A { case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); // parse function as prototype // - no self, is prototype, is unsafe and not const auto i = ::AST::Item( Parse_FunctionDef(lex, abi, false, true, true,false) ); @@ -1316,7 +1317,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::A else PUTBACK(tok, lex); GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); auto type = Parse_Type(lex); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); @@ -1328,7 +1329,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::A break; } case TOK_RWORD_TYPE: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); auto sp = lex.end_span(ps); //TODO(sp, "Extern type"); @@ -1355,7 +1356,7 @@ void Parse_Use_Inner(TokenStream& lex, ::std::vector& entries switch( GET_TOK(tok, lex) ) { case TOK_IDENT: - path.append( AST::PathNode( mv$(tok.str()), {}) ); + path.append( AST::PathNode( tok.istr(), {}) ); break; case TOK_BRACE_OPEN: // Can't be an empty list @@ -1376,7 +1377,7 @@ void Parse_Use_Inner(TokenStream& lex, ::std::vector& entries if( LOOK_AHEAD(lex) == TOK_RWORD_AS ) { GET_TOK(tok, lex); GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); + name = tok.istr(); } entries.push_back({ lex.point_span(), AST::Path(path), ::std::move(name) }); } @@ -1399,13 +1400,13 @@ void Parse_Use_Inner(TokenStream& lex, ::std::vector& entries } } while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON ); - ::std::string name; + RcString name; // NOTE: The above loop has to run once, so the last token HAS to have been an ident if( tok.type() == TOK_RWORD_AS ) { GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); + name = tok.istr(); } else { @@ -1455,7 +1456,7 @@ void Parse_Use_Inner(TokenStream& lex, ::std::vector& entries if( LOOK_AHEAD(lex) == TOK_STRING ) { GET_CHECK_TOK(tok, lex, TOK_STRING); - path = ::AST::Path(tok.str(), {}); + path = ::AST::Path(RcString::new_interned(tok.str()), {}); } else { @@ -1478,12 +1479,12 @@ void Parse_Use_Inner(TokenStream& lex, ::std::vector& entries } -::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan span_start, ::std::string name, TokenStream& lex) +::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan span_start, RcString name, TokenStream& lex) { Token tok; - ::std::string ident; + RcString ident; if( GET_TOK(tok, lex) == TOK_IDENT ) { - ident = mv$(tok.str()); + ident = tok.istr(); } else { PUTBACK(tok, lex); @@ -1648,7 +1649,7 @@ namespace { auto ps = lex.start_span(); - ::std::string item_name; + RcString item_name; ::AST::Item item_data; { @@ -1684,7 +1685,7 @@ namespace { // `extern "" fn ...` case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, false,false) ); break; } // `extern "ABI" {` @@ -1699,7 +1700,7 @@ namespace { // `extern fn ...` case TOK_RWORD_FN: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, "C", false, false,false) ); break; @@ -1718,20 +1719,20 @@ namespace { // `extern crate "crate-name" as crate_name;` // NOTE: rustc doesn't allow this, keep in mrustc for for reparse support case TOK_STRING: - item_data = ::AST::Item::make_Crate({ tok.str() }); + item_data = ::AST::Item::make_Crate({ RcString::new_interned(tok.str()) }); GET_CHECK_TOK(tok, lex, TOK_RWORD_AS); GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); break; // `extern crate crate_name;` // `extern crate crate_name as other_name;` case TOK_IDENT: - item_name = mv$(tok.str()); + item_name = tok.istr(); if(GET_TOK(tok, lex) == TOK_RWORD_AS) { item_data = ::AST::Item::make_Crate({ mv$(item_name) }); GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); } else { PUTBACK(tok, lex); @@ -1754,7 +1755,7 @@ namespace { switch( GET_TOK(tok, lex) ) { case TOK_IDENT: { - item_name = mv$(tok.str()); + item_name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); TypeRef type = Parse_Type(lex); @@ -1766,12 +1767,12 @@ namespace { case TOK_RWORD_UNSAFE: GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,true/*unsafe,const*/) ); break; case TOK_RWORD_FN: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); // - self not allowed, not prototype item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,true/*unsafe,const*/) ); break; @@ -1788,7 +1789,7 @@ namespace { GET_TOK(tok, lex); } CHECK_TOK(tok, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); GET_CHECK_TOK(tok, lex, TOK_COLON); TypeRef type = Parse_Type(lex); @@ -1818,20 +1819,20 @@ namespace { } GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, true,false/*unsafe,const*/) ); break; } // `unsafe fn` case TOK_RWORD_FN: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); // - self not allowed, not prototype item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,false/*unsafe,const*/) ); break; // `unsafe trait` case TOK_RWORD_TRAIT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); auto tr = Parse_TraitDef(lex, meta_items); tr.set_is_unsafe(); item_data = ::AST::Item( ::std::move(tr) ); @@ -1852,10 +1853,10 @@ namespace { } // `unsafe auto trait` case TOK_IDENT: - if( TARGETVER_1_29 && tok.str() == "auto" ) { + if( TARGETVER_1_29 && tok.istr() == "auto" ) { GET_CHECK_TOK(tok, lex, TOK_RWORD_TRAIT); GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); auto tr = Parse_TraitDef(lex, meta_items); tr.set_is_unsafe(); tr.set_is_marker(); @@ -1870,40 +1871,40 @@ namespace { // `fn` case TOK_RWORD_FN: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); // - self not allowed, not prototype item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,false/*unsafe,const*/) ); break; // `type` case TOK_RWORD_TYPE: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_TypeAlias(lex) ); break; // `struct` case TOK_RWORD_STRUCT: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_Struct(lex, meta_items) ); break; // `enum` case TOK_RWORD_ENUM: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_EnumDef(lex, meta_items) ); break; // Contextual keywords case TOK_IDENT: - if( tok.str() == "union" ) { + if( tok.istr() == "union" ) { GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_Union(lex, meta_items) ); } // `auto trait` - else if( TARGETVER_1_29 && tok.str() == "auto" ) { + else if( TARGETVER_1_29 && tok.istr() == "auto" ) { GET_CHECK_TOK(tok, lex, TOK_RWORD_TRAIT); GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); auto tr = Parse_TraitDef(lex, meta_items); tr.set_is_marker(); item_data = ::AST::Item( ::std::move(tr) ); @@ -1918,7 +1919,7 @@ namespace { // `trait` case TOK_RWORD_TRAIT: GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); + item_name = tok.istr(); item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) ); break; @@ -1926,7 +1927,7 @@ namespace { if( TARGETVER_1_29 ) { GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = tok.str(); + auto name = tok.istr(); if( lex.lookahead(0) != TOK_PAREN_OPEN ) { GET_TOK(tok, lex); @@ -1934,7 +1935,7 @@ namespace { } DEBUG("name = " << name); - ::std::vector< ::std::string> names; + ::std::vector names; auto ps = lex.start_span(); GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); auto arm_pat = Parse_MacroRules_Pat(lex, TOK_PAREN_OPEN, TOK_PAREN_CLOSE, names); @@ -1966,7 +1967,7 @@ namespace { case TOK_RWORD_MOD: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); + auto name = tok.istr(); DEBUG("Sub module '" << name << "'"); AST::Module submod( mod_path + name ); @@ -1992,7 +1993,7 @@ namespace { //submod.m_file_info = get_submod_file(lex.end_span(ps), mod_fileinfo, name, path_attr, LOOK_AHEAD(lex) == TOK_SEMICOLON, H::check_item_cfg(meta_items)); - ::std::string sub_path; + ::helpers::path sub_path; bool sub_file_controls_dir = true; if( mod_fileinfo.path == "-" ) { if( path_attr.size() ) { @@ -2002,15 +2003,15 @@ namespace { } else if( path_attr.size() > 0 ) { - sub_path = dirname(mod_fileinfo.path) + path_attr; + sub_path = dirname(mod_fileinfo.path) / path_attr.c_str(); } else if( mod_fileinfo.controls_dir ) { - sub_path = dirname(mod_fileinfo.path) + name; + sub_path = dirname(mod_fileinfo.path) / name.c_str(); } else { - sub_path = dirname(mod_fileinfo.path) + mod_path.nodes().back().name() + "/" + name; + sub_path = dirname(mod_fileinfo.path) / mod_path.nodes().back().name().c_str() / name.c_str(); //sub_path = mod_fileinfo.path; sub_file_controls_dir = false; } @@ -2022,14 +2023,14 @@ namespace { switch( GET_TOK(tok, lex) ) { case TOK_BRACE_OPEN: - submod.m_file_info.path = sub_path + "/"; + submod.m_file_info.path = sub_path.str() + "/"; // TODO: If cfg fails, just eat the TT until a matching #[cfg]? // - Or, mark the file infor as not being valid (so child modules don't try to load) Parse_ModRoot(lex, submod, meta_items); GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); break; case TOK_SEMICOLON: - if( sub_path == "-" ) { + if( sub_path.str() == "-" ) { ERROR(lex.point_span(), E0000, "Cannot load module from file when reading stdin"); } else if( !H::check_item_cfg(meta_items) ) { @@ -2042,7 +2043,7 @@ namespace { { // TODO: Also search for curmod/submod.rs //::std::string newpath_file = (mod_path.nodes().size() > 1 ? dirname(mod_fileinfo.path) + mod_path.nodes()[mod_path.nodes().size()-2].name() + "/" + name + ".rs" : ""); - ::std::string newpath_file = (mod_path.nodes().size() >= 1 ? dirname(mod_fileinfo.path) + mod_path.nodes()[mod_path.nodes().size()-1].name() + "/" + name + ".rs" : ""); + ::std::string newpath_file = (mod_path.nodes().size() >= 1 ? dirname(mod_fileinfo.path) / mod_path.nodes()[mod_path.nodes().size()-1].name().c_str() / name.c_str() + ".rs" : ""); DEBUG("newpath_file = '" << newpath_file << "' " << mod_fileinfo.path << " " << mod_path); ::std::ifstream ifs_file(newpath_file); if( ifs_file.is_open() ) @@ -2061,7 +2062,7 @@ namespace { } else { - ::std::string newpath_dir = sub_path + "/"; + ::std::string newpath_dir = sub_path.str() + "/"; ::std::string newpath_file = path_attr.size() > 0 ? sub_path : sub_path + ".rs"; DEBUG("newpath_dir = '" << newpath_dir << "', newpath_file = '" << newpath_file << "'"); ::std::ifstream ifs_dir (newpath_dir + "mod.rs"); diff --git a/src/parse/token.cpp b/src/parse/token.cpp index d8a68d88..73ae7d93 100644 --- a/src/parse/token.cpp +++ b/src/parse/token.cpp @@ -52,6 +52,11 @@ Token::Token(enum eTokenType type): m_type(type) { } +Token::Token(enum eTokenType type, RcString str): + m_type(type), + m_data(Data::make_IString(mv$(str))) +{ +} Token::Token(enum eTokenType type, ::std::string str): m_type(type), m_data(Data::make_String(mv$(str))) @@ -163,6 +168,7 @@ Token::Token(const Token& t): assert( t.m_data.tag() != Data::TAGDEAD ); TU_MATCH(Data, (t.m_data), (e), (None, ), + (IString, m_data = Data::make_IString(e); ), (String, m_data = Data::make_String(e); ), (Integer, m_data = Data::make_Integer(e);), (Float, m_data = Data::make_Float(e);), @@ -178,6 +184,9 @@ Token Token::clone() const TU_MATCH(Data, (m_data), (e), (None, ), + (IString, + rv.m_data = Data::make_IString(e); + ), (String, rv.m_data = Data::make_String(e); ), @@ -333,8 +342,8 @@ struct EscapedString { case TOK_INTERPOLATED_IDENT: return "/*:ident*/"; case TOK_INTERPOLATED_VIS: return "/*:vis*/"; // Value tokens - case TOK_IDENT: return m_data.as_String(); - case TOK_LIFETIME: return "'" + m_data.as_String(); + case TOK_IDENT: return m_data.as_IString().c_str(); + case TOK_LIFETIME: return FMT("'" << m_data.as_IString().c_str()); case TOK_INTEGER: if( m_data.as_Integer().m_datatype == CORETYPE_ANY ) { return FMT(m_data.as_Integer().m_intval); diff --git a/src/parse/token.hpp b/src/parse/token.hpp index d5e7a6db..0d9a8015 100644 --- a/src/parse/token.hpp +++ b/src/parse/token.hpp @@ -64,6 +64,7 @@ class Token TAGGED_UNION(Data, None, (None, struct {}), + (IString, RcString), (String, ::std::string), (Integer, struct { enum eCoreType m_datatype; @@ -108,6 +109,7 @@ public: Token(enum eTokenType type); Token(enum eTokenType type, ::std::string str); + Token(enum eTokenType type, RcString str); Token(uint64_t val, enum eCoreType datatype); Token(double val, enum eCoreType datatype); Token(const InterpolatedFragment& ); @@ -115,6 +117,7 @@ public: Token(TagTakeIP, InterpolatedFragment ); enum eTokenType type() const { return m_type; } + const RcString& istr() const { return m_data.as_IString(); } ::std::string& str() { return m_data.as_String(); } const ::std::string& str() const { return m_data.as_String(); } enum eCoreType datatype() const { TU_MATCH_DEF(Data, (m_data), (e), (assert(!"Getting datatype of invalid token type");), (Integer, return e.m_datatype;), (Float, return e.m_datatype;)) throw ""; } @@ -135,6 +138,7 @@ public: return false; TU_MATCH(Data, (m_data, r.m_data), (e, re), (None, return true;), + (IString, return e == re; ), (String, return e == re; ), (Integer, return e.m_datatype == re.m_datatype && e.m_intval == re.m_intval;), (Float, return e.m_datatype == re.m_datatype && e.m_floatval == re.m_floatval;), diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp index 611df2ff..957bc673 100644 --- a/src/parse/tokenstream.cpp +++ b/src/parse/tokenstream.cpp @@ -138,11 +138,11 @@ Span TokenStream::point_span() const Ident TokenStream::get_ident(Token tok) const { if(tok.type() == TOK_IDENT) { - return Ident(getHygiene(), tok.str()); + return Ident(getHygiene(), tok.istr()); } else if(tok.type() == TOK_LIFETIME) { // TODO: Maybe only when it's explicitly asked for? - return Ident(getHygiene(), tok.str()); + return Ident(getHygiene(), tok.istr()); } else if( tok.type() == TOK_INTERPOLATED_IDENT ) { TODO(getPosition(), "get_ident from TOK_INTERPOLATED_IDENT"); diff --git a/src/parse/types.cpp b/src/parse/types.cpp index d261c403..979a8045 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -83,9 +83,9 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) { lex.getToken(); // TODO: path macros - return TypeRef(TypeRef::TagMacro(), Parse_MacroInvocation(ps, mv$(tok.str()), lex)); + return TypeRef(TypeRef::TagMacro(), Parse_MacroInvocation(ps, tok.istr(), lex)); } - if( TARGETVER_1_29 && tok.str() == "dyn" ) + if( TARGETVER_1_29 && tok.istr() == "dyn" ) { if( lex.lookahead(0) == TOK_PAREN_OPEN ) { GET_TOK(tok, lex); @@ -283,16 +283,17 @@ TypeRef Parse_Type_Path(TokenStream& lex, ::AST::HigherRankedBounds hrbs, bool a auto ps = lex.start_span(); + auto path = Parse_Path(lex, PATH_GENERIC_TYPE); if( hrbs.empty() && !allow_trait_list ) { - return TypeRef(TypeRef::TagPath(), lex.end_span(ps), Parse_Path(lex, PATH_GENERIC_TYPE)); + return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(path)); } else { ::std::vector traits; ::std::vector lifetimes; - traits.push_back(Type_TraitPath { mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); + traits.push_back(Type_TraitPath { mv$(hrbs), mv$(path) }); if( allow_trait_list ) { diff --git a/src/rc_string.cpp b/src/rc_string.cpp index 46f36923..0d7e253a 100644 --- a/src/rc_string.cpp +++ b/src/rc_string.cpp @@ -7,17 +7,18 @@ */ #include #include +#include #include RcString::RcString(const char* s, unsigned int len): - m_ptr(nullptr), - m_len(len) + m_ptr(nullptr) { if( len > 0 ) { - m_ptr = new unsigned int[1 + (len+1 + sizeof(unsigned int)-1) / sizeof(unsigned int)]; - *m_ptr = 1; - char* data_mut = reinterpret_cast(m_ptr + 1); + m_ptr = new unsigned int[2 + (len+1 + sizeof(unsigned int)-1) / sizeof(unsigned int)]; + m_ptr[0] = 1; + m_ptr[1] = len; + char* data_mut = reinterpret_cast(m_ptr + 2); for(unsigned int j = 0; j < len; j ++ ) data_mut[j] = s[j]; data_mut[len] = '\0'; @@ -36,14 +37,104 @@ RcString::~RcString() } } } +Ordering RcString::ord(const RcString& x) const +{ + if( m_ptr == x.m_ptr ) + return OrdEqual; + // Both can't be empty/null + if( m_ptr == nullptr ) + return OrdLess; + if( x.m_ptr == nullptr ) + return OrdGreater; + + assert(x.size() > 0); + assert(this->size() > 0); + + auto xp = x.c_str(); + auto tp = this->c_str(); + for(size_t i = 0; i < ::std::min(this->size(), x.size()); i ++) + { + if( *xp != *tp ) + return ::ord((unsigned)*xp, (unsigned)*tp); + xp ++; + tp ++; + } + return ::ord((unsigned)this->size(), (unsigned)x.size()); +} +Ordering RcString::ord(const std::string& x) const +{ + if( m_ptr == nullptr && x.size() == 0 ) + return OrdEqual; + // Both can't be empty/null + if( m_ptr == nullptr ) + return OrdLess; + if( x.empty() ) + return OrdGreater; + + assert(x.size() > 0); + assert(this->size() > 0); + + auto xp = x.c_str(); + auto tp = this->c_str(); + for(size_t i = 0; i < ::std::min(this->size(), x.size()); i ++) + { + if( *xp != *tp ) + return ::ord((unsigned)*xp, (unsigned)*tp); + xp ++; + tp ++; + } + return ::ord((unsigned)this->size(), (unsigned)x.size()); +} bool RcString::operator==(const char* s) const { - if( m_len == 0 ) + if( m_ptr == nullptr ) return *s == '\0'; - auto m = this->c_str(); - do { - if( *m != *s ) + const char* ts = this->c_str(); + const char* end = ts + this->size(); + // Loop while not at the end of either + while(s && ts != end) + { + if( *s != *ts ) return false; - } while( *m++ != '\0' && *s++ != '\0' ); - return true; + s ++; + ts ++; + } + // Only equal if we're at the end of both strings + return *s == '\0' && ts == end; +} + +::std::ostream& operator<<(::std::ostream& os, const RcString& x) +{ + for(size_t i = 0; i < x.size(); i ++) + { + os << x.c_str()[i]; + } + return os; +} + + +::std::set RcString_interned_strings; + +RcString RcString::new_interned(const ::std::string& s) +{ +#if 0 + auto it = RcString_interned_strings.find(s); + if( it == RcString_interned_strings.end() ) + { + it = RcString_interned_strings.insert(RcString(s)).first; + } + return *it; +#else + return *RcString_interned_strings.insert(RcString(s)).first; +#endif +} + +size_t std::hash::operator()(const RcString& s) const noexcept +{ + size_t h = 5381; + for(auto c : s) { + h = h * 33 + (unsigned)c; + } + return h; + //return hash(s.c_str(), s.size()); } diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index c2dedfcb..d26bb699 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -41,7 +41,7 @@ namespace template struct Named { - ::std::string name; + RcString name; Val value; }; template @@ -300,7 +300,7 @@ namespace } return ""; } - AST::Path lookup(const Span& sp, const ::std::string& name, const Ident::Hygiene& src_context, LookupMode mode) const { + AST::Path lookup(const Span& sp, const RcString& name, const Ident::Hygiene& src_context, LookupMode mode) const { auto rv = this->lookup_opt(name, src_context, mode); if( !rv.is_valid() ) { switch(mode) @@ -314,7 +314,7 @@ namespace } return rv; } - static bool lookup_in_mod(const ::AST::Module& mod, const ::std::string& name, LookupMode mode, ::AST::Path& path) { + static bool lookup_in_mod(const ::AST::Module& mod, const RcString& name, LookupMode mode, ::AST::Path& path) { switch(mode) { case LookupMode::Namespace: @@ -422,7 +422,7 @@ namespace } return false; } - AST::Path lookup_opt(const ::std::string& name, const Ident::Hygiene& src_context, LookupMode mode) const { + AST::Path lookup_opt(const RcString& name, const Ident::Hygiene& src_context, LookupMode mode) const { DEBUG("name=" << name <<", src_context=" << src_context); // NOTE: src_context may provide a module to search if( src_context.has_mod_path() ) @@ -513,7 +513,7 @@ namespace case LookupMode::Namespace: case LookupMode::Type: { // Look up primitive types - auto ct = coretype_fromstring(name); + auto ct = coretype_fromstring(name.c_str()); if( ct != CORETYPE_INVAL ) { return ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(Span("-",0,0,0,0), ct), ::AST::Path(), ::std::vector< ::AST::PathNode>() ); @@ -538,7 +538,7 @@ namespace return AST::Path(); } - unsigned int lookup_local(const Span& sp, const ::std::string name, LookupMode mode) { + unsigned int lookup_local(const Span& sp, const RcString name, LookupMode mode) { for(auto it = m_name_context.rbegin(); it != m_name_context.rend(); ++ it) { TU_MATCH(Ent, (*it), (e), @@ -732,7 +732,7 @@ void Resolve_Absolute_Path_BindUFCS(Context& context, const Span& sp, Context::L } namespace { - AST::Path split_into_crate(const Span& sp, AST::Path path, unsigned int start, const ::std::string& crate_name) + AST::Path split_into_crate(const Span& sp, AST::Path path, unsigned int start, const RcString& crate_name) { auto& nodes = path.nodes(); AST::Path np = AST::Path(crate_name, {}); @@ -1146,7 +1146,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex { auto& n = path_abs.nodes[i]; - if( n.name()[0] == '#' ) { + if( n.name().c_str()[0] == '#' ) { if( ! n.args().is_empty() ) { ERROR(sp, E0000, "Type parameters were not expected here"); } @@ -1157,7 +1157,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex char c; unsigned int idx; - ::std::stringstream ss( n.name() ); + ::std::stringstream ss( n.name().c_str() ); ss >> c; ss >> idx; assert( idx < mod->anon_mods().size() ); @@ -1367,7 +1367,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context:: // HACK: If this is a primitive name, and resolved to a module. // - If the next component isn't found in the located module // > Instead use the type name. - if( ! p.m_class.is_Local() && coretype_fromstring(e.nodes[0].name()) != CORETYPE_INVAL ) { + if( ! p.m_class.is_Local() && coretype_fromstring(e.nodes[0].name().c_str()) != CORETYPE_INVAL ) { if( const auto* pep = p.m_bindings.type.opt_Module() ) { const auto& pe = *pep; bool found = false; @@ -1421,7 +1421,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context:: } if( !found ) { - auto ct = coretype_fromstring(e.nodes[0].name()); + auto ct = coretype_fromstring(e.nodes[0].name().c_str()); p = ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(Span("-",0,0,0,0), ct), ::AST::Path(), ::std::vector< ::AST::PathNode>() ); } @@ -1467,7 +1467,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context:: const auto& mp_nodes = context.m_mod.path().nodes(); // Ignore any leading anon modules unsigned int start_len = mp_nodes.size(); - while( start_len > 0 && mp_nodes[start_len-1].name()[0] == '#' ) + while( start_len > 0 && mp_nodes[start_len-1].name().c_str()[0] == '#' ) start_len --; // - Create a new path @@ -1491,7 +1491,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context:: assert( e.count >= 1 ); // TODO: The first super should ignore any anon modules. unsigned int start_len = e.count > mp_nodes.size() ? 0 : mp_nodes.size() - e.count; - while( start_len > 0 && mp_nodes[start_len-1].name()[0] == '#' ) + while( start_len > 0 && mp_nodes[start_len-1].name().c_str()[0] == '#' ) start_len --; // - Create a new path diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp index 43182faf..45fb58f5 100644 --- a/src/resolve/index.cpp +++ b/src/resolve/index.cpp @@ -32,7 +32,7 @@ void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst } throw ""; } -::std::unordered_map< ::std::string, ::AST::Module::IndexEnt >& get_mod_index(::AST::Module& mod, IndexName location) { +::std::unordered_map< RcString, ::AST::Module::IndexEnt >& get_mod_index(::AST::Module& mod, IndexName location) { switch(location) { case IndexName::Namespace: @@ -57,7 +57,7 @@ namespace { } } // namespace -void _add_item(const Span& sp, AST::Module& mod, IndexName location, const ::std::string& name, bool is_pub, ::AST::Path ir, bool error_on_collision=true) +void _add_item(const Span& sp, AST::Module& mod, IndexName location, const RcString& name, bool is_pub, ::AST::Path ir, bool error_on_collision=true) { ASSERT_BUG(sp, ir.m_bindings.has_binding(), ""); auto& list = get_mod_index(mod, location); @@ -90,12 +90,12 @@ void _add_item(const Span& sp, AST::Module& mod, IndexName location, const ::std assert(rec.second); } } -void _add_item_type(const Span& sp, AST::Module& mod, const ::std::string& name, bool is_pub, ::AST::Path ir, bool error_on_collision=true) +void _add_item_type(const Span& sp, AST::Module& mod, const RcString& name, bool is_pub, ::AST::Path ir, bool error_on_collision=true) { _add_item(sp, mod, IndexName::Namespace, name, is_pub, ::AST::Path(ir), error_on_collision); _add_item(sp, mod, IndexName::Type, name, is_pub, mv$(ir), error_on_collision); } -void _add_item_value(const Span& sp, AST::Module& mod, const ::std::string& name, bool is_pub, ::AST::Path ir, bool error_on_collision=true) +void _add_item_value(const Span& sp, AST::Module& mod, const RcString& name, bool is_pub, ::AST::Path ir, bool error_on_collision=true) { _add_item(sp, mod, IndexName::Value, name, is_pub, mv$(ir), error_on_collision); } @@ -237,7 +237,7 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod) DEBUG(i_data.name << " - Not a macro"); } TU_ARMA(MacroRules, e) { - ::std::vector<::std::string> path; + ::std::vector path; path.push_back( i_data.path.m_class.as_Absolute().crate ); for(const auto& node : i_data.path.m_class.as_Absolute().nodes ) path.push_back( node.name() ); diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp index 95e6d2c1..cde9cd5f 100644 --- a/src/resolve/use.cpp +++ b/src/resolve/use.cpp @@ -51,7 +51,7 @@ void Resolve_Use(::AST::Crate& crate) // How can this happen? DEBUG("Relative " << path); // EVIL HACK: If the current module is an anon module, refer to the parent - if( base_path.nodes().size() > 0 && base_path.nodes().back().name()[0] == '#' ) { + if( base_path.nodes().size() > 0 && base_path.nodes().back().name().c_str()[0] == '#' ) { AST::Path np("", {}); for( unsigned int i = 0; i < base_path.nodes().size() - 1; i ++ ) np.nodes().push_back( base_path.nodes()[i] ); @@ -65,7 +65,7 @@ void Resolve_Use(::AST::Crate& crate) (Self, DEBUG("Self " << path); // EVIL HACK: If the current module is an anon module, refer to the parent - if( base_path.nodes().size() > 0 && base_path.nodes().back().name()[0] == '#' ) { + if( base_path.nodes().size() > 0 && base_path.nodes().back().name().c_str()[0] == '#' ) { AST::Path np("", {}); for( unsigned int i = 0; i < base_path.nodes().size() - 1; i ++ ) np.nodes().push_back( base_path.nodes()[i] ); @@ -86,7 +86,7 @@ void Resolve_Use(::AST::Crate& crate) // TODO: Do this in a cleaner manner. unsigned int n_anon = 0; // Skip any anon modules in the way (i.e. if the current module is an anon, go to the parent) - while( base_path.nodes().size() > n_anon && base_path.nodes()[ base_path.nodes().size()-1-n_anon ].name()[0] == '#' ) + while( base_path.nodes().size() > n_anon && base_path.nodes()[ base_path.nodes().size()-1-n_anon ].name().c_str()[0] == '#' ) n_anon ++; for( unsigned int i = 0; i < base_path.nodes().size() - e.count - n_anon; i ++ ) np.nodes().push_back( base_path.nodes()[i] ); @@ -252,13 +252,13 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path ::AST::Path::Bindings Resolve_Use_GetBinding_Mod( const Span& span, const ::AST::Crate& crate, const ::AST::Path& source_mod_path, const ::AST::Module& mod, - const ::std::string& des_item_name, + const RcString& des_item_name, ::std::span< const ::AST::Module* > parent_modules ) { ::AST::Path::Bindings rv; // If the desired item is an anon module (starts with #) then parse and index - if( des_item_name.size() > 0 && des_item_name[0] == '#' ) { + if( des_item_name.size() > 0 && des_item_name.c_str()[0] == '#' ) { unsigned int idx = 0; if( ::std::sscanf(des_item_name.c_str(), "#%u", &idx) != 1 ) { BUG(span, "Invalid anon path segment '" << des_item_name << "'"); @@ -283,6 +283,9 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path (MacroInv, BUG(span, "Hit MacroInv in use resolution"); ), + (Macro, + //rv.macro = ::AST::PathBinding_Macro::make_MacroRules({nullptr, e.get()}); + ), (Use, continue; // Skip for now ), @@ -479,7 +482,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path return rv; } - if( mod.path().nodes().size() > 0 && mod.path().nodes().back().name()[0] == '#' ) { + if( mod.path().nodes().size() > 0 && mod.path().nodes().back().name().c_str()[0] == '#' ) { assert( parent_modules.size() > 0 ); return Resolve_Use_GetBinding_Mod(span, crate, source_mod_path, *parent_modules.back(), des_item_name, parent_modules.subspan(0, parent_modules.size()-1)); } @@ -754,8 +757,8 @@ namespace { if( path.m_class.is_Absolute() && path.m_class.as_Absolute().crate != "" ) { const auto& path_abs = path.m_class.as_Absolute(); - ASSERT_BUG(span, crate.m_extern_crates.count(path_abs.crate), "Crate '" << path_abs.crate << "' not loaded"); - return Resolve_Use_GetBinding__ext(span, crate, path, crate.m_extern_crates.at( path_abs.crate ), 0); + ASSERT_BUG(span, crate.m_extern_crates.count(path_abs.crate.c_str()), "Crate '" << path_abs.crate << "' not loaded"); + return Resolve_Use_GetBinding__ext(span, crate, path, crate.m_extern_crates.at( path_abs.crate.c_str() ), 0); } ::AST::Path::Bindings rv; diff --git a/src/trans/auto_impls.cpp b/src/trans/auto_impls.cpp index ec4b8a42..07a52857 100644 --- a/src/trans/auto_impls.cpp +++ b/src/trans/auto_impls.cpp @@ -199,7 +199,7 @@ void Trans_AutoImpl_Clone(State& state, ::HIR::TypeRef ty) // Impl ::HIR::TraitImpl impl; impl.m_type = mv$(ty); - impl.m_methods.insert(::std::make_pair( ::std::string("clone"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::std::move(fcn) } )); + impl.m_methods.insert(::std::make_pair( RcString::new_interned("clone"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::std::move(fcn) } )); // Add impl to the crate state.crate.m_trait_impls.insert(::std::make_pair( state.lang_Clone, ::std::move(impl) )); diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index b229db8b..09b63f44 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -2187,8 +2187,7 @@ namespace { } { - auto vtable_sp = trait_path.m_path; - vtable_sp.m_components.back() += "#vtable"; + const auto& vtable_sp = trait.m_vtable_path; auto vtable_params = trait_path.m_params.clone(); for(const auto& ty : trait.m_type_indexes) { auto aty = ::HIR::TypeRef( ::HIR::Path( type.clone(), trait_path.clone(), ty.first ) ); @@ -4055,7 +4054,7 @@ namespace { } } - void emit_intrinsic_call(const ::std::string& name, const ::HIR::PathParams& params, const ::MIR::Terminator::Data_Call& e) + void emit_intrinsic_call(const RcString& name, const ::HIR::PathParams& params, const ::MIR::Terminator::Data_Call& e) { const auto& mir_res = *m_mir_res; enum class Ordering @@ -4088,7 +4087,7 @@ namespace { } throw ""; }; - auto get_atomic_ordering = [&](const ::std::string& name, size_t prefix_len)->Ordering { + auto get_atomic_ordering = [&](const RcString& name, size_t prefix_len)->Ordering { if( name.size() < prefix_len ) { return Ordering::SeqCst; @@ -5024,7 +5023,7 @@ namespace { || name == "atomic_min" || name.compare(0, 7+3+1, "atomic_min_") == 0 ) { auto ordering = get_atomic_ordering(name, 7+3+1); const auto& ty = params.m_types.at(0); - const char* op = (name[7+1] == 'a' ? "imax" : "imin"); // m'a'x vs m'i'n + const char* op = (name.c_str()[7+1] == 'a' ? "imax" : "imin"); // m'a'x vs m'i'n emit_lvalue(e.ret_val); m_of << " = __mrustc_atomicloop" << get_prim_size(ty) << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << get_atomic_ty_gcc(ordering) << ", __mrustc_op_" << op << get_prim_size(ty); m_of << ")"; @@ -5033,7 +5032,7 @@ namespace { || name == "atomic_umin" || name.compare(0, 7+4+1, "atomic_umin_") == 0 ) { auto ordering = get_atomic_ordering(name, 7+4+1); const auto& ty = params.m_types.at(0); - const char* op = (name[7+2] == 'a' ? "umax" : "umin"); // m'a'x vs m'i'n + const char* op = (name.c_str()[7+2] == 'a' ? "umax" : "umin"); // m'a'x vs m'i'n emit_lvalue(e.ret_val); m_of << " = __mrustc_atomicloop" << get_prim_size(ty) << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << get_atomic_ty_gcc(ordering) << ", __mrustc_op_" << op << get_prim_size(ty); m_of << ")"; diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index 032e6afa..50d36a8a 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -328,9 +328,9 @@ namespace const auto& te = t.m_data.as_TraitObject(); //auto vtp = t.m_data.as_TraitObject().m_trait.m_path; - auto vtable_gp = te.m_trait.m_path.clone(); - vtable_gp.m_path.m_components.back() += "#vtable"; const auto& trait = resolve.m_crate.get_trait_by_path(sp, te.m_trait.m_path.m_path); + auto vtable_gp = ::HIR::GenericPath(trait.m_vtable_path); + vtable_gp.m_params = te.m_trait.m_path.m_params.clone(); vtable_gp.m_params.m_types.resize( vtable_gp.m_params.m_types.size() + trait.m_type_indexes.size() ); for(const auto& ty : trait.m_type_indexes) { auto aty = te.m_trait.m_type_bounds.at(ty.first).clone(); @@ -948,8 +948,7 @@ namespace ::HIR::TypeRef vtable_ty; { - auto vtable_sp = trait_path.m_path; - vtable_sp.m_components.back() += "#vtable"; + const auto& vtable_sp = trait.m_vtable_path; auto vtable_params = trait_path.m_params.clone(); for(const auto& ty : trait.m_type_indexes) { auto aty = ::HIR::TypeRef( ::HIR::Path( type.clone(), trait_path.clone(), ty.first ) ); diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 4567c0e7..a2ecb408 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -592,8 +592,7 @@ namespace { const auto& trait = *te.m_trait.m_trait_ptr; ASSERT_BUG(Span(), ! te.m_trait.m_path.m_path.m_components.empty(), "TODO: Data trait is empty, what can be done?"); - auto vtable_ty_spath = te.m_trait.m_path.m_path; - vtable_ty_spath.m_components.back() += "#vtable"; + const auto& vtable_ty_spath = trait.m_vtable_path; const auto& vtable_ref = m_crate.get_struct_by_path(sp, vtable_ty_spath); // Copy the param set from the trait in the trait object ::HIR::PathParams vtable_params = te.m_trait.m_path.m_params.clone(); @@ -1039,8 +1038,7 @@ void Trans_Enumerate_Types(EnumState& state) const auto& gpath = ent.first.m_data.as_UfcsKnown().trait; const auto& trait = state.crate.get_trait_by_path(sp, gpath.m_path); - auto vtable_ty_spath = gpath.m_path; - vtable_ty_spath.m_components.back() += "#vtable"; + const auto& vtable_ty_spath = trait.m_vtable_path; const auto& vtable_ref = state.crate.get_struct_by_path(sp, vtable_ty_spath); // Copy the param set from the trait in the trait object ::HIR::PathParams vtable_params = gpath.m_params.clone(); @@ -1775,7 +1773,7 @@ namespace { TU_IFLET( ::HIR::ValueItem, vi.second->ent, Function, i, if( i.m_code.m_mir && i.m_linkage.name != "" && i.m_linkage.name == name ) { - out_path = (mod_path + vi.first.c_str()).get_simple_path(); + out_path = (mod_path + vi.first).get_simple_path(); return &i; } ) @@ -1784,7 +1782,7 @@ namespace { for(const auto& ti : mod.m_mod_items) { TU_IFLET( ::HIR::TypeItem, ti.second->ent, Module, i, - if( auto rv = find_function_by_link_name(i, mod_path + ti.first.c_str(), name, out_path) ) + if( auto rv = find_function_by_link_name(i, mod_path + ti.first, name, out_path) ) return rv; ) } diff --git a/src/trans/mangling.cpp b/src/trans/mangling.cpp index 741d13dd..5d7584ed 100644 --- a/src/trans/mangling.cpp +++ b/src/trans/mangling.cpp @@ -22,18 +22,27 @@ #include namespace { - ::std::string escape_str(const ::std::string& s) { + ::std::string escape_str(const char* s, size_t len) { ::std::string output; - output.reserve(s.size() + 1); - for(auto v : s) + output.reserve(len + 1); + for(auto vp = s; vp != s + len; vp ++) + { + auto v= *vp; if( v == '#' ) output += "$H"; else if( v == '-' ) output += "_"; else output += v; + } return output; } + ::std::string escape_str(const RcString& s) { + return escape_str(s.c_str(), s.size()); + } + ::std::string escape_str(const ::std::string& s) { + return escape_str(s.c_str(), s.size()); + } ::FmtLambda emit_params(const ::HIR::PathParams& params) { return FMT_CB(ss, -- cgit v1.2.3 From dab72ad78160ecd2a4d1759174cee837a5bedcbc Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 2 Jun 2019 11:55:02 +0800 Subject: MIR - Refactor LValue to reduce size and linked-list-ness (seems to have had a ~10% reduction in memory usage) --- Notes/MIR-PackedLValue.txt | 65 ++++ src/hir/deserialise.cpp | 32 +- src/hir/serialise.cpp | 41 +-- src/hir_conv/bind.cpp | 27 +- src/hir_conv/constant_evaluation.cpp | 112 +++---- src/include/tagged_union.hpp | 7 +- src/mir/check.cpp | 173 +++++----- src/mir/check_full.cpp | 230 ++++++-------- src/mir/cleanup.cpp | 82 +++-- src/mir/dump.cpp | 35 +- src/mir/from_hir.cpp | 76 ++--- src/mir/from_hir.hpp | 15 +- src/mir/from_hir_match.cpp | 112 +++---- src/mir/helpers.cpp | 135 ++++---- src/mir/helpers.hpp | 11 +- src/mir/mir.cpp | 189 ++++------- src/mir/mir.hpp | 402 ++++++++++++++++++----- src/mir/mir_builder.cpp | 597 ++++++++++++++++------------------- src/mir/optimise.cpp | 587 ++++++++++++++++++---------------- src/trans/auto_impls.cpp | 20 +- src/trans/codegen_c.cpp | 287 +++++++++-------- src/trans/codegen_mmir.cpp | 103 +++--- src/trans/enumerate.cpp | 340 ++++++-------------- src/trans/monomorphise.cpp | 40 +-- 24 files changed, 1863 insertions(+), 1855 deletions(-) create mode 100644 Notes/MIR-PackedLValue.txt (limited to 'src/trans/codegen_c.cpp') diff --git a/Notes/MIR-PackedLValue.txt b/Notes/MIR-PackedLValue.txt new file mode 100644 index 00000000..ce889aee --- /dev/null +++ b/Notes/MIR-PackedLValue.txt @@ -0,0 +1,65 @@ +Problem statement: +- MIR LValues are very common, and suffer from excessive indirection when + dereferences and field accesses are present +- Many MIR analysis passes care most about the inner values +- Pointer chasing ruins cache locality + +Solution: Replace the tagged union tree with a flatteded structure + +Quirk: Indexing takes two LValues to produce one BUT one of those is of a +lesser class, so doesn't need to be treated the same. + + + +Structure proposal: +---- +A LValue is made up of: +- A root value (referencing a local, argument, static, or the return value) +- And a list of wrappers (dereference, field, downcast, index) + +Root values are encoded as a packed pointer/value and tag, with the tag stored in the low 2 bits of the pointer +- This allows a 32-bit pointer to a word to be stored, using the alignment bits as tag +- Arguments and locals are encoded with the argument/local index in the "data" bits +- Return value is encoded as argument `-1` (all 1 bits in data) +- Statics are encoded as a pointer to a `::HIR::Path` + - This adds a new pointer access and allocation vs the existing LValue structure + - HIR::Path already has a bunch of pointers in it, may not hurt that much (and may help by keeping the normal size + of the LValue down) + +Wrappers are stored as a vector of words, packed in a similar way to root values +- Dereference is stored just as an entry (could pack multiple derefs into one, but that would make handling more + difficult) +- Field/Downcast is stored with the field/variant index in the "data" bits +- Indexing is stored as a pointer to a LValue + - ALTERNATIVE: Could require that indexing always uses a local, and just store the local index + - This would vastly reduce complexity in handling the Index wrapper, BUT would add a new statement in some cases + - A quick scan of the MMIR output of libstd crates, shows that the vast majority of indexing cases are with a local + directly. + - Doing so would simplify monomorph/clone/serialise (no need to clone the wrapper list, just copy it). + - Would also improve comparison times + + + +Usecase comparisons +------ +(Using 32-bit architecture) + +NOTES: +- Existing `LValue` structure is 3 words long (1 tag, plus 2 pointers for largest variant) + - WRONG. It's actually far larger due to the ::HIR::Path embedded in it (estimate at least 8 pointers, very likely + more). That should be fixed given the number of LValue-s that exist + - Fixed now, had a slight improvement in compile times (and memory usage?) +- New structure is 4 words long (root value, plus len/cap/ptr for vector) + +- Field access via `&self` + - Old: Field(Deref(Argument(0)), 0) + - 12 + 12 + 12 = 36 bytes w/ 2 pointers + - New: LValue( Argument(0), { Deref, Field(0) } ) + - 16 + 8 = 24 bytes w/ 1 pointer + +- Array stored in `&self` (common in librand) + - `(*arg0).2[var16].0` + - Old: Field( Index(Field(Deref(Argument(0)), 2), Local(16)), 0 ) + - 12 * 5 + 12 = 72 bytes 2/ 5 pointers + - New: LValue( Argument(0), { Deref, Field(2), Index(16), Field(0) } ) + - 16 + 16 = 32 bytes w/ 1 pointer diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 56671a04..35aeacca 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -464,32 +464,15 @@ rv = deserialise_mir_lvalue_(); return rv; } + ::MIR::LValue::Wrapper deserialise_mir_lvalue_wrapper() + { + return ::MIR::LValue::Wrapper::from_inner(m_in.read_count()); + } ::MIR::LValue deserialise_mir_lvalue_() { - switch(auto tag = m_in.read_tag()) - { - #define _(x, ...) case ::MIR::LValue::TAG_##x: return ::MIR::LValue::make_##x( __VA_ARGS__ ); - _(Return, {}) - _(Argument, { static_cast(m_in.read_count()) } ) - _(Local, static_cast(m_in.read_count()) ) - _(Static, box$(deserialise_path()) ) - _(Field, { - box$( deserialise_mir_lvalue() ), - static_cast(m_in.read_count()) - } ) - _(Deref, { box$( deserialise_mir_lvalue() ) }) - _(Index, { - box$( deserialise_mir_lvalue() ), - box$( deserialise_mir_lvalue() ) - } ) - _(Downcast, { - box$( deserialise_mir_lvalue() ), - static_cast(m_in.read_count()) - } ) - #undef _ - default: - BUG(Span(), "Bad tag for MIR::LValue - " << tag); - } + auto root_v = m_in.read_count(); + auto root = (root_v == 3 ? ::MIR::LValue::Storage::new_Static(deserialise_path()) : ::MIR::LValue::Storage::from_inner(root_v)); + return ::MIR::LValue( mv$(root), deserialise_vec<::MIR::LValue::Wrapper>() ); } ::MIR::RValue deserialise_mir_rvalue() { @@ -827,6 +810,7 @@ template<> DEF_D( ::HIR::TraitValueItem, return d.deserialise_traitvalueitem(); ) template<> DEF_D( ::MIR::Param, return d.deserialise_mir_param(); ) + template<> DEF_D( ::MIR::LValue::Wrapper, return d.deserialise_mir_lvalue_wrapper(); ) template<> DEF_D( ::MIR::LValue, return d.deserialise_mir_lvalue(); ) template<> DEF_D( ::MIR::Statement, return d.deserialise_mir_statement(); ) template<> DEF_D( ::MIR::BasicBlock, return d.deserialise_mir_basicblock(); ) diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index c15630d9..fc53e245 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -722,35 +722,18 @@ void serialise(const ::MIR::LValue& lv) { TRACE_FUNCTION_F("LValue = "<(lv.tag()) ); - TU_MATCHA( (lv), (e), - (Return, - ), - (Argument, - m_out.write_count(e.idx); - ), - (Local, - m_out.write_count(e); - ), - (Static, - serialise_path(*e); - ), - (Field, - serialise(e.val); - m_out.write_count(e.field_index); - ), - (Deref, - serialise(e.val); - ), - (Index, - serialise(e.val); - serialise(e.idx); - ), - (Downcast, - serialise(e.val); - m_out.write_count(e.variant_index); - ) - ) + if( lv.m_root.is_Static() ) { + m_out.write_count(3); + serialise_path(lv.m_root.as_Static()); + } + else { + m_out.write_count( lv.m_root.get_inner() ); + } + serialise_vec(lv.m_wrappers); + } + void serialise(const ::MIR::LValue::Wrapper& w) + { + m_out.write_count(w.get_inner()); } void serialise(const ::MIR::RValue& val) { diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 84854315..e3441157 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -704,30 +704,9 @@ namespace { struct H { static void visit_lvalue(Visitor& upper_visitor, ::MIR::LValue& lv) { - TU_MATCHA( (lv), (e), - (Return, - ), - (Local, - ), - (Argument, - ), - (Static, - upper_visitor.visit_path(*e, ::HIR::Visitor::PathContext::VALUE); - ), - (Field, - H::visit_lvalue(upper_visitor, *e.val); - ), - (Deref, - H::visit_lvalue(upper_visitor, *e.val); - ), - (Index, - H::visit_lvalue(upper_visitor, *e.val); - H::visit_lvalue(upper_visitor, *e.idx); - ), - (Downcast, - H::visit_lvalue(upper_visitor, *e.val); - ) - ) + if( lv.m_root.is_Static() ) { + upper_visitor.visit_path(lv.m_root.as_Static(), ::HIR::Visitor::PathContext::VALUE); + } } static void visit_constant(Visitor& upper_visitor, ::MIR::Constant& e) { diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index b97a6ae0..500ac490 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -293,61 +293,66 @@ namespace HIR { ::HIR::Literal& get_lval(const ::MIR::LValue& lv) { - TU_MATCHA( (lv), (e), + ::HIR::Literal* lit_ptr; + TRACE_FUNCTION_FR(lv, *lit_ptr); + TU_MATCHA( (lv.m_root), (e), (Return, - return retval; + lit_ptr = &retval; ), (Local, - if( e >= locals.size() ) - MIR_BUG(state, "Local index out of range - " << e << " >= " << locals.size()); - return locals[e]; + MIR_ASSERT(state, e < locals.size(), "Local index out of range - " << e << " >= " << locals.size()); + lit_ptr = &locals[e]; ), (Argument, - if( e.idx >= args.size() ) - MIR_BUG(state, "Local index out of range - " << e.idx << " >= " << args.size()); - return args[e.idx]; + MIR_ASSERT(state, e < args.size(), "Argument index out of range - " << e << " >= " << args.size()); + lit_ptr = &args[e]; ), (Static, - MIR_TODO(state, "LValue::Static - " << *e); - ), - (Field, - auto& val = get_lval(*e.val); - MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv); - auto& vals = val.as_List(); - MIR_ASSERT(state, e.field_index < vals.size(), "LValue::Field index out of range"); - return vals[ e.field_index ]; - ), - (Deref, - auto& val = get_lval(*e.val); - TU_MATCH_DEF( ::HIR::Literal, (val), (ve), - ( - MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }"); - ), - (BorrowData, - return *ve; - ), - (String, - // Just clone the string (hack) - // - TODO: Create a list? - return val; - ) - ) - ), - (Index, - auto& val = get_lval(*e.val); - MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv); - auto& idx = get_lval(*e.idx); - MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv); - auto& vals = val.as_List(); - auto idx_v = static_cast( idx.as_Integer() ); - MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range"); - return vals[ idx_v ]; - ), - (Downcast, - MIR_TODO(state, "LValue::Downcast - " << lv); + MIR_TODO(state, "LValue::Static - " << e); ) ) - throw ""; + + for(const auto& w : lv.m_wrappers) + { + auto& val = *lit_ptr; + TU_MATCH_HDRA( (w), {) + TU_ARMA(Field, e) { + MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv); + auto& vals = val.as_List(); + MIR_ASSERT(state, e < vals.size(), "LValue::Field index out of range"); + lit_ptr = &vals[ e ]; + } + TU_ARMA(Deref, e) { + TU_MATCH_DEF( ::HIR::Literal, (val), (ve), + ( + MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }"); + ), + (BorrowData, + lit_ptr = &*ve; + ), + (String, + // Just clone the string (hack) + // - TODO: Create a list? + lit_ptr = &val; + ) + ) + } + TU_ARMA(Index, e) { + MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv); + MIR_ASSERT(state, e < locals.size(), "LValue::Index index local out of range"); + auto& idx = locals[e]; + MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv); + auto& vals = val.as_List(); + auto idx_v = static_cast( idx.as_Integer() ); + MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range"); + lit_ptr = &vals[ idx_v ]; + } + TU_ARMA(Downcast, e) { + MIR_TODO(state, "LValue::Downcast - " << lv); + } + } + } + return *lit_ptr; } ::HIR::Literal read_lval(const ::MIR::LValue& lv) { @@ -481,17 +486,14 @@ namespace HIR { MIR_BUG(state, "Only shared borrows are allowed in constants"); } - if( e.type != ::HIR::BorrowType::Shared ) { - MIR_BUG(state, "Only shared borrows are allowed in constants"); - } - if( const auto* p = e.val.opt_Deref() ) { - if( p->val->is_Deref() ) - MIR_TODO(state, "Undo nested deref coercion - " << *p->val); - val = local_state.read_lval(*p->val); + if( !e.val.m_wrappers.empty() && e.val.m_wrappers.back().is_Deref() ) { + //if( p->val->is_Deref() ) + // MIR_TODO(state, "Undo nested deref coercion - " << *p->val); + val = local_state.read_lval(e.val.clone_unwrapped()); } - else if( const auto* p = e.val.opt_Static() ) { + else if( e.val.m_wrappers.empty() && e.val.m_root.is_Static() ){ // Borrow of a static, emit BorrowPath with the same path - val = ::HIR::Literal::make_BorrowPath( (*p)->clone() ); + val = ::HIR::Literal::make_BorrowPath( e.val.m_root.as_Static().clone() ); } else { auto inner_val = local_state.read_lval(e.val); diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index dab7f8ea..5a3359b8 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -28,7 +28,6 @@ #define TU_CASE(mod, class, var, name,src, ...) TU_CASE_BODY(mod,class,var, TU_CASE_ITEM(src,mod,var,name) __VA_ARGS__) #define TU_CASE2(mod, class, var, n1,s1, n2,s2, ...) TU_CASE_BODY(mod,class,var, TU_CASE_ITEM(s1,mod,var,n1) TU_CASE_ITEM(s2,mod,var,n2) __VA_ARGS__) - // Argument iteration #define TU_DISP0(n) #define TU_DISP1(n, _1) n _1 @@ -105,7 +104,7 @@ */ TU_MATCH_ARMS(CLASS, VAR, NAME, __VA_ARGS__)/* */ default: {TU_EXP DEF;} break;/* */} -#define TU_MATCH_BIND1(TAG, VAR, NAME) /*MATCH_BIND*/ auto& NAME = (VAR).as_##TAG(); (void)&NAME; +#define TU_MATCH_BIND1(TAG, VAR, NAME) /*MATCH_BIND*/ decltype((VAR).as_##TAG()) NAME = (VAR).as_##TAG(); (void)&NAME; #define TU_MATCH_BIND2_(TAG, v1,v2, n1,n2) TU_MATCH_BIND1(TAG, v1, n1) TU_MATCH_BIND1(TAG, v2, n2) #define TU_MATCH_BIND2(...) TU_EXP1( TU_MATCH_BIND2_(__VA_ARGS__) ) // << Exists to cause expansion of the vars #define TU_MATCH_ARM(CLASS, VAR, NAME, TAG, ...) case CLASS::TAG_##TAG: {/* @@ -119,12 +118,12 @@ #define TU_MATCH_HDR(VARS, brace) TU_MATCH_HDR_(::std::remove_reference::type, VARS, brace) #define TU_MATCH_HDR_(CLASS, VARS, brace) switch( (TU_FIRST VARS).tag() ) brace case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used"); // Evil hack: two for loops, the inner stops the outer after it's done. -#define TU_ARM(VAR, TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = (VAR).as_##TAG(); (void)NAME, tu_lc; tu_lc=false) +#define TU_ARM(VAR, TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(decltype((VAR).as_##TAG()) NAME = (VAR).as_##TAG(); (void)NAME, tu_lc; tu_lc=false) #define TU_MATCH_HDRA(VARS, brace) TU_MATCH_HDRA_(::std::remove_reference::type, VARS, brace) #define TU_MATCH_HDRA_(CLASS, VARS, brace) auto& tu_match_hdr2_v = (TU_FIRST VARS); switch( tu_match_hdr2_v.tag() ) brace case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used"); // Evil hack: two for loops, the inner stops the outer after it's done. -#define TU_ARMA(TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = tu_match_hdr2_v.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) +#define TU_ARMA(TAG, NAME) break; case ::std::remove_reference::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(decltype(tu_match_hdr2_v.as_##TAG()) NAME = tu_match_hdr2_v.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) //#define TU_TEST(VAL, ...) (VAL.is_##TAG() && VAL.as_##TAG() TEST) #define TU_TEST1(VAL, TAG1, TEST) (VAL.is_##TAG1() && VAL.as_##TAG1() TEST) diff --git a/src/mir/check.cpp b/src/mir/check.cpp index 0b032bbc..6ed34563 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -116,6 +116,11 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn { } + explicit ValStates(const ValStates& v) = default; + ValStates(ValStates&& v) = default; + ValStates& operator=(const ValStates& v) = delete; + ValStates& operator=(ValStates&& v) = default; + void fmt(::std::ostream& os) { os << "ValStates { "; switch(ret_state) @@ -159,12 +164,13 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn return locals.empty() && args.empty(); } + // NOTE: Moves if this state is empty bool merge(unsigned bb_idx, ValStates& other) { DEBUG("bb" << bb_idx << " this=" << FMT_CB(ss,this->fmt(ss);) << ", other=" << FMT_CB(ss,other.fmt(ss);)); if( this->empty() ) { - *this = other; + *this = ValStates(other); return true; } else if( *this == other ) @@ -183,34 +189,38 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn void mark_validity(const ::MIR::TypeResolve& state, const ::MIR::LValue& lv, bool is_valid) { - TU_MATCH_DEF( ::MIR::LValue, (lv), (e), - ( - ), + if( !lv.m_wrappers.empty()) + { + return ; + } + TU_MATCHA( (lv.m_root), (e), (Return, ret_state = is_valid ? State::Valid : State::Invalid; ), (Argument, - MIR_ASSERT(state, e.idx < this->args.size(), "Argument index out of range"); - DEBUG("arg$" << e.idx << " = " << (is_valid ? "Valid" : "Invalid")); - this->args[e.idx] = is_valid ? State::Valid : State::Invalid; + MIR_ASSERT(state, e < this->args.size(), "Argument index out of range " << lv); + DEBUG("arg$" << e << " = " << (is_valid ? "Valid" : "Invalid")); + this->args[e] = is_valid ? State::Valid : State::Invalid; ), (Local, - MIR_ASSERT(state, e < this->locals.size(), "Local index out of range"); + MIR_ASSERT(state, e < this->locals.size(), "Local index out of range - " << lv); DEBUG("_" << e << " = " << (is_valid ? "Valid" : "Invalid")); this->locals[e] = is_valid ? State::Valid : State::Invalid; + ), + (Static, ) ) } void ensure_valid(const ::MIR::TypeResolve& state, const ::MIR::LValue& lv) { - TU_MATCH( ::MIR::LValue, (lv), (e), + TU_MATCHA( (lv.m_root), (e), (Return, if( this->ret_state != State::Valid ) MIR_BUG(state, "Use of non-valid lvalue - " << lv); ), (Argument, - MIR_ASSERT(state, e.idx < this->args.size(), "Arg index out of range"); - if( this->args[e.idx] != State::Valid ) + MIR_ASSERT(state, e < this->args.size(), "Arg index out of range"); + if( this->args[e] != State::Valid ) MIR_BUG(state, "Use of non-valid lvalue - " << lv); ), (Local, @@ -219,27 +229,22 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn MIR_BUG(state, "Use of non-valid lvalue - " << lv); ), (Static, - ), - (Field, - ensure_valid(state, *e.val); - ), - (Deref, - ensure_valid(state, *e.val); - ), - (Index, - ensure_valid(state, *e.val); - ensure_valid(state, *e.idx); - ), - (Downcast, - ensure_valid(state, *e.val); ) ) + + for(const auto& w : lv.m_wrappers) + { + if( w.is_Index() ) + { + if( this->locals[w.as_Index()] != State::Valid ) + MIR_BUG(state, "Use of non-valid lvalue - " << ::MIR::LValue::new_Local(w.as_Index())); + } + } } void move_val(const ::MIR::TypeResolve& state, const ::MIR::LValue& lv) { ensure_valid(state, lv); - ::HIR::TypeRef tmp; - if( ! state.m_resolve.type_is_copy( state.sp, state.get_lvalue_type(tmp, lv) ) ) + if( ! state.lvalue_is_copy(lv) ) { mark_validity(state, lv, false); } @@ -284,20 +289,29 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn ::std::vector path; ValStates state; }; + // TODO: Remove this? The path is useful, but the cloned states are really expensive + // - Option: Keep the paths, but only ever use the pre-set entry state? ::std::vector to_visit_blocks; // TODO: Check that all used locals are also set (anywhere at all) - auto add_to_visit = [&](unsigned int idx, ::std::vector src_path, auto vs) { + auto add_to_visit = [&](unsigned int idx, ::std::vector src_path, ValStates& vs, bool can_move) { for(const auto& b : to_visit_blocks) if( b.bb == idx && b.state == vs) return ; if( block_start_states.at(idx) == vs ) return ; src_path.push_back(idx); - to_visit_blocks.push_back( ToVisit { idx, mv$(src_path), mv$(vs) } ); + // TODO: Update the target block, and only visit if we've induced a change + to_visit_blocks.push_back( ToVisit { idx, mv$(src_path), (can_move ? mv$(vs) : ValStates(vs)) } ); + }; + auto add_to_visit_move = [&](unsigned int idx, ::std::vector src_path, ValStates vs) { + add_to_visit(idx, mv$(src_path), vs, true); + }; + auto add_to_visit_copy = [&](unsigned int idx, ::std::vector src_path, ValStates& vs) { + add_to_visit(idx, mv$(src_path), vs, false); }; - add_to_visit( 0, {}, ValStates { state.m_args.size(), fcn.locals.size() } ); + add_to_visit_move( 0, {}, ValStates { state.m_args.size(), fcn.locals.size() } ); while( to_visit_blocks.size() > 0 ) { auto block = to_visit_blocks.back().bb; @@ -311,7 +325,8 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn if( ! block_start_states.at(block).merge(block, val_state) ) { continue ; } - DEBUG("BB" << block << " via [" << path << "]"); + ASSERT_BUG(Span(), val_state.locals.size() == fcn.locals.size(), ""); + DEBUG("BB" << block << " via [" << path << "] " << FMT_CB(ss,val_state.fmt(ss);)); // 2. Using the newly merged state, iterate statements checking the usage and updating state. const auto& bb = fcn.blocks[block]; @@ -411,13 +426,13 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn // 3. Pass new state on to destination blocks state.set_cur_stmt_term(block); DEBUG(state << bb.terminator); - TU_MATCH(::MIR::Terminator, (bb.terminator), (e), - (Incomplete, + TU_MATCH_HDRA( (bb.terminator), { ) + TU_ARMA(Incomplete, e) { // Should be impossible here. - ), - (Return, + } + TU_ARMA(Return, e) { // Check if the return value has been set - val_state.ensure_valid( state, ::MIR::LValue::make_Return({}) ); + val_state.ensure_valid( state, ::MIR::LValue::new_Return() ); // Ensure that no other non-Copy values are valid for(unsigned int i = 0; i < val_state.locals.size(); i ++) { @@ -432,51 +447,51 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn // TODO: Error, becuase this has just been leaked } } - ), - (Diverge, + } + TU_ARMA(Diverge, e) { // TODO: Ensure that cleanup has been performed. - ), - (Goto, + } + TU_ARMA(Goto, e) { // Push block with the new state - add_to_visit( e, mv$(path), mv$(val_state) ); - ), - (Panic, + add_to_visit_move( e, mv$(path), mv$(val_state) ); + } + TU_ARMA(Panic, e) { // What should be done here? - ), - (If, + } + TU_ARMA(If, e) { // Push blocks val_state.ensure_valid( state, e.cond ); - add_to_visit( e.bb0, path, val_state ); - add_to_visit( e.bb1, mv$(path), mv$(val_state) ); - ), - (Switch, + add_to_visit_copy( e.bb0, path, val_state ); + add_to_visit_move( e.bb1, mv$(path), mv$(val_state) ); + } + TU_ARMA(Switch, e) { val_state.ensure_valid( state, e.val ); for(const auto& tgt : e.targets) { - add_to_visit( tgt, path, val_state ); + add_to_visit( tgt, path, val_state, (&tgt == &e.targets.back()) ); } - ), - (SwitchValue, + } + TU_ARMA(SwitchValue, e) { val_state.ensure_valid( state, e.val ); for(const auto& tgt : e.targets) { - add_to_visit( tgt, path, val_state ); + add_to_visit_copy( tgt, path, val_state ); + } + add_to_visit_move( e.def_target, path, mv$(val_state) ); } - add_to_visit( e.def_target, path, val_state ); - ), - (Call, + TU_ARMA(Call, e) { if( e.fcn.is_Value() ) val_state.ensure_valid( state, e.fcn.as_Value() ); for(const auto& arg : e.args) val_state.move_val( state, arg ); // Push blocks (with return valid only in one) - add_to_visit(e.panic_block, path, val_state); + add_to_visit_copy(e.panic_block, path, val_state); // TODO: If the function returns !, don't follow the ret_block val_state.mark_validity( state, e.ret_val, true ); - add_to_visit(e.ret_block, mv$(path), mv$(val_state)); - ) - ) + add_to_visit_move(e.ret_block, mv$(path), mv$(val_state)); + } + } } } @@ -838,33 +853,33 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path state.set_cur_stmt_term(bb_idx); DEBUG(state << bb.terminator); - TU_MATCH(::MIR::Terminator, (bb.terminator), (e), - (Incomplete, - ), - (Return, + TU_MATCH_HDRA( (bb.terminator), {) + TU_ARMA(Incomplete, e) { + } + TU_ARMA(Return, e) { // TODO: Check if the function can return (i.e. if its return type isn't an empty type) - ), - (Diverge, - ), - (Goto, - ), - (Panic, - ), - (If, + } + TU_ARMA(Diverge, e) { + } + TU_ARMA(Goto, e) { + } + TU_ARMA(Panic, e) { + } + TU_ARMA(If, e) { // Check that condition lvalue is a bool ::HIR::TypeRef tmp; const auto& ty = state.get_lvalue_type(tmp, e.cond); if( ty != ::HIR::CoreType::Bool ) { MIR_BUG(state, "Type mismatch in `If` - expected bool, got " << ty); } - ), - (Switch, + } + TU_ARMA(Switch, e) { // Check that the condition is an enum - ), - (SwitchValue, + } + TU_ARMA(SwitchValue, e) { // Check that the condition's type matches the values - ), - (Call, + } + TU_ARMA(Call, e) { if( e.fcn.is_Value() ) { ::HIR::TypeRef tmp; @@ -875,8 +890,8 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path } } // Typecheck arguments and return value - ) - ) + } + } } } diff --git a/src/mir/check_full.cpp b/src/mir/check_full.cpp index 24a4930a..0cc83c6f 100644 --- a/src/mir/check_full.cpp +++ b/src/mir/check_full.cpp @@ -446,68 +446,54 @@ namespace } const State& get_lvalue_state(const ::MIR::TypeResolve& mir_res, const ::MIR::LValue& lv) const { - TU_MATCHA( (lv), (e), + const State* state_p = nullptr; + TU_MATCHA( (lv.m_root), (e), (Return, - return return_value; + state_p = &return_value; ), (Argument, - return args.at(e.idx); + state_p = &args.at(e); ), (Local, - return locals.at(e); + state_p = &locals.at(e); ), (Static, static State state_of_static(true); return state_of_static; - ), - (Field, - const auto& vs = get_lvalue_state(mir_res, *e.val); - if( vs.is_composite() ) - { - const auto& states = this->get_composite(mir_res, vs); - MIR_ASSERT(mir_res, e.field_index < states.size(), "Field index out of range"); - return states[e.field_index]; - } - else - { - return vs; + ) + ) + + for(const auto& w : lv.m_wrappers) + { + if( state_p->is_composite() ) { + break; } - ), - (Deref, - const auto& vs = get_lvalue_state(mir_res, *e.val); - if( vs.is_composite() ) - { + const auto& vs = *state_p; + state_p = nullptr; + + TU_MATCHA( (w), (e), + (Field, + const auto& states = this->get_composite(mir_res, vs); + MIR_ASSERT(mir_res, e < states.size(), "Field index out of range"); + state_p = &states[e]; + ), + (Deref, MIR_TODO(mir_res, "Deref with composite state"); - } - else - { - return vs; - } - ), - (Index, - const auto& vs_v = get_lvalue_state(mir_res, *e.val); - const auto& vs_i = get_lvalue_state(mir_res, *e.idx); - MIR_ASSERT(mir_res, !vs_v.is_composite(), ""); - MIR_ASSERT(mir_res, !vs_i.is_composite(), ""); - //return State(vs_v.is_valid() && vs_i.is_valid()); - MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalidated value"); - return vs_v; - ), - (Downcast, - const auto& vs_v = get_lvalue_state(mir_res, *e.val); - if( vs_v.is_composite() ) - { - const auto& states = this->get_composite(mir_res, vs_v); - MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << StateFmt(*this, vs_v)); - return states[0]; - } - else - { - return vs_v; - } + ), + (Index, + const auto& vs_i = get_lvalue_state(mir_res, ::MIR::LValue::new_Local(e)); + MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalidated value"); + MIR_BUG(mir_res, "Indexing a composite state"); + ), + (Downcast, + const auto& states = this->get_composite(mir_res, vs); + MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << StateFmt(*this, vs)); + state_p = &states[0]; + ) ) - ) - throw ""; + assert(state_p); + } + return *state_p; } void clear_state(const ::MIR::TypeResolve& mir_res, State& s) { @@ -522,42 +508,47 @@ namespace void set_lvalue_state(const ::MIR::TypeResolve& mir_res, const ::MIR::LValue& lv, State new_vs) { TRACE_FUNCTION_F(lv << " = " << StateFmt(*this, new_vs) << " (from " << StateFmt(*this, get_lvalue_state(mir_res, lv)) << ")"); - TU_MATCHA( (lv), (e), + State* state_p = nullptr; + TU_MATCHA( (lv.m_root), (e), (Return, - this->clear_state(mir_res, return_value); - return_value = mv$(new_vs); + state_p = &return_value; ), (Argument, - auto& slot = args.at(e.idx); - this->clear_state(mir_res, slot); - slot = mv$(new_vs); + state_p = &args.at(e); ), (Local, - auto& slot = locals.at(e); - this->clear_state(mir_res, slot); - slot = mv$(new_vs); + state_p = &locals.at(e); ), (Static, - // Ignore. - ), - (Field, - const auto& cur_vs = get_lvalue_state(mir_res, *e.val); + return ; + ) + ) + + for(const auto& w : lv.m_wrappers) + { + auto& cur_vs = *state_p; + + // If this is not a composite, and it matches the new state if( !cur_vs.is_composite() && cur_vs == new_vs ) { - // Not a composite, and no state change + // Early return + return; } - else - { - ::std::vector* states_p; + + state_p = nullptr; + TU_MATCHA( (w), (e), + (Field, + // Current isn't a composite, we need to change that if( !cur_vs.is_composite() ) { ::HIR::TypeRef tmp; - const auto& ty = mir_res.get_lvalue_type(tmp, *e.val); + const auto& ty = mir_res.get_lvalue_type(tmp, lv, /*wrapper_skip_count=*/(&lv.m_wrappers.back() - &w)); unsigned int n_fields = 0; if( const auto* e = ty.m_data.opt_Tuple() ) { n_fields = e->size(); } + // TODO: Fixed-size arrays else if( ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Struct() ) { const auto& e = ty.m_data.as_Path().binding.as_Struct(); @@ -573,94 +564,59 @@ namespace ) ) } - else { + else + { MIR_BUG(mir_res, "Unknown type being accessed with Field - " << ty); } - auto new_cur_vs = this->allocate_composite(n_fields, cur_vs); - set_lvalue_state(mir_res, *e.val, State(new_cur_vs)); - states_p = &this->get_composite(mir_res, new_cur_vs); - } - else - { - states_p = &this->get_composite(mir_res, cur_vs); + cur_vs = State(this->allocate_composite(n_fields, cur_vs)); } // Get composite state and assign into it - auto& states = *states_p; - MIR_ASSERT(mir_res, e.field_index < states.size(), "Field index out of range"); - this->clear_state(mir_res, states[e.field_index]); - states[e.field_index] = mv$(new_vs); - } - ), - (Deref, - const auto& cur_vs = get_lvalue_state(mir_res, *e.val); - if( !cur_vs.is_composite() && cur_vs == new_vs ) - { - // Not a composite, and no state change - } - else - { - ::std::vector* states_p; + auto& states = this->get_composite(mir_res, cur_vs); + MIR_ASSERT(mir_res, e< states.size(), "Field index out of range"); + state_p = &states[e]; + ), + (Deref, if( !cur_vs.is_composite() ) { + // TODO: Should this check if the type is Box? //::HIR::TypeRef tmp; //const auto& ty = mir_res.get_lvalue_type(tmp, *e.val); - // TODO: Should this check if the type is Box? - auto new_cur_vs = this->allocate_composite(2, cur_vs); - set_lvalue_state(mir_res, *e.val, State(new_cur_vs)); - states_p = &this->get_composite(mir_res, new_cur_vs); - } - else - { - states_p = &this->get_composite(mir_res, cur_vs); + cur_vs = State(this->allocate_composite(2, cur_vs)); } // Get composite state and assign into it - auto& states = *states_p; + auto& states = this->get_composite(mir_res, cur_vs); MIR_ASSERT(mir_res, states.size() == 2, "Deref with invalid state list size"); - this->clear_state(mir_res, states[1]); - states[1] = mv$(new_vs); - } - ), - (Index, - const auto& vs_v = get_lvalue_state(mir_res, *e.val); - const auto& vs_i = get_lvalue_state(mir_res, *e.idx); - MIR_ASSERT(mir_res, !vs_v.is_composite(), ""); - MIR_ASSERT(mir_res, !vs_i.is_composite(), ""); + state_p = &states[1]; + ), + (Index, + const auto& vs_i = get_lvalue_state(mir_res, ::MIR::LValue::new_Local(e)); + MIR_ASSERT(mir_res, !cur_vs.is_composite(), ""); + MIR_ASSERT(mir_res, !vs_i.is_composite(), ""); - MIR_ASSERT(mir_res, vs_v.is_valid(), "Indexing an invalid value"); - MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalid index"); + MIR_ASSERT(mir_res, cur_vs.is_valid(), "Indexing an invalid value"); + MIR_ASSERT(mir_res, vs_i.is_valid(), "Indexing with an invalid index"); - // NOTE: Ignore - ), - (Downcast, - const auto& cur_vs = get_lvalue_state(mir_res, *e.val); - if( !cur_vs.is_composite() && cur_vs == new_vs ) - { - // Not a composite, and no state change - } - else - { - ::std::vector* states_p; + // NOTE: Ignore + return ; + ), + (Downcast, if( !cur_vs.is_composite() ) { - auto new_cur_vs = this->allocate_composite(1, cur_vs); - set_lvalue_state(mir_res, *e.val, State(new_cur_vs)); - states_p = &this->get_composite(mir_res, new_cur_vs); + cur_vs = State(this->allocate_composite(1, cur_vs)); } - else - { - states_p = &this->get_composite(mir_res, cur_vs); - } - // Get composite state and assign into it - auto& states = *states_p; - MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << *e.val << " - " << this->fmt_state(mir_res, *e.val)); + auto& states = this->get_composite(mir_res, cur_vs); + MIR_ASSERT(mir_res, states.size() == 1, "Downcast on composite of invalid size - " << lv << " - " << StateFmt(*this, cur_vs)); this->clear_state(mir_res, states[0]); states[0] = mv$(new_vs); - } + ) ) - ) + assert(state_p); + } + this->clear_state(mir_res, *state_p); + *state_p = mv$(new_vs); } }; @@ -939,7 +895,7 @@ void MIR_Validate_FullValState(::MIR::TypeResolve& mir_res, const ::MIR::Functio (Incomplete, ), (Return, - state.ensure_lvalue_valid(mir_res, ::MIR::LValue::make_Return({})); + state.ensure_lvalue_valid(mir_res, ::MIR::LValue::new_Return()); if( ENABLE_LEAK_DETECTOR ) { auto ensure_dropped = [&](const State& s, const ::MIR::LValue& lv) { @@ -955,10 +911,10 @@ void MIR_Validate_FullValState(::MIR::TypeResolve& mir_res, const ::MIR::Functio } }; for(unsigned i = 0; i < state.locals.size(); i ++ ) { - ensure_dropped(state.locals[i], ::MIR::LValue::make_Local(i)); + ensure_dropped(state.locals[i], ::MIR::LValue::new_Local(i)); } for(unsigned i = 0; i < state.args.size(); i ++ ) { - ensure_dropped(state.args[i], ::MIR::LValue::make_Argument({i})); + ensure_dropped(state.args[i], ::MIR::LValue::new_Argument(i)); } } ), diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 5d32d0c8..b535c7ce 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -33,7 +33,7 @@ struct MirMutator ::MIR::LValue new_temporary(::HIR::TypeRef ty) { - auto rv = ::MIR::LValue::make_Local( static_cast(m_fcn.locals.size()) ); + auto rv = ::MIR::LValue::new_Local( static_cast(m_fcn.locals.size()) ); m_fcn.locals.push_back( mv$(ty) ); return rv; } @@ -493,12 +493,13 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con // Allocate a temporary for the vtable pointer itself auto vtable_lv = mutator.new_temporary( mv$(vtable_ty) ); // - Load the vtable and store it - auto ptr_lv = ::MIR::LValue::make_Deref({ box$(receiver_lvp.clone()) }); + auto ptr_lv = ::MIR::LValue::new_Deref( receiver_lvp.clone() ); MIR_Cleanup_LValue(state, mutator, ptr_lv); - auto vtable_rval = ::MIR::RValue::make_DstMeta({ mv$(*ptr_lv.as_Deref().val) }); + ptr_lv.m_wrappers.pop_back(); + auto vtable_rval = ::MIR::RValue::make_DstMeta({ mv$(ptr_lv) }); mutator.push_statement( ::MIR::Statement::make_Assign({ vtable_lv.clone(), mv$(vtable_rval) }) ); - auto fcn_lval = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(vtable_lv) })), vtable_idx }); + auto fcn_lval = ::MIR::LValue::new_Field( ::MIR::LValue::new_Deref( mv$(vtable_lv) ), vtable_idx ); ::HIR::TypeRef tmp; const auto& ty = state.get_lvalue_type(tmp, fcn_lval); @@ -526,23 +527,23 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con ), (Tuple, for(unsigned int i = 0; i < se.size(); i ++ ) { - auto val = (i == se.size() - 1 ? mv$(lv) : lv.clone()); + auto val = ::MIR::LValue::new_Field( (i == se.size() - 1 ? mv$(lv) : lv.clone()), i ); if( i == str.m_struct_markings.coerce_unsized_index ) { - vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].ent), ::MIR::LValue::make_Field({ box$(val), i }) ) ); + vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].ent), mv$(val)) ); } else { - vals.push_back( ::MIR::LValue::make_Field({ box$(val), i }) ); + vals.push_back( mv$(val) ); } } ), (Named, for(unsigned int i = 0; i < se.size(); i ++ ) { - auto val = (i == se.size() - 1 ? mv$(lv) : lv.clone()); + auto val = ::MIR::LValue::new_Field( (i == se.size() - 1 ? mv$(lv) : lv.clone()), i ); if( i == str.m_struct_markings.coerce_unsized_index ) { - vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].second.ent), ::MIR::LValue::make_Field({ box$(val), i }) ) ); + vals.push_back( H::get_unit_ptr(state, mutator, monomorph(se[i].second.ent), mv$(val) ) ); } else { - vals.push_back( ::MIR::LValue::make_Field({ box$(val), i }) ); + vals.push_back( mv$(val) ); } } ) @@ -777,7 +778,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& auto ty_d = monomorphise_type_with(state.sp, se[i].ent, monomorph_cb_d, false); auto ty_s = monomorphise_type_with(state.sp, se[i].ent, monomorph_cb_s, false); - auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::make_Field({ box$(value.clone()), i })); + auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::new_Field(value.clone(), i)); auto new_lval = mutator.in_temporary( mv$(ty_d), mv$(new_rval) ); ents.push_back( mv$(new_lval) ); @@ -793,7 +794,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& } else { - ents.push_back( ::MIR::LValue::make_Field({ box$(value.clone()), i}) ); + ents.push_back( ::MIR::LValue::new_Field(value.clone(), i) ); } } ), @@ -806,7 +807,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& auto ty_d = monomorphise_type_with(state.sp, se[i].second.ent, monomorph_cb_d, false); auto ty_s = monomorphise_type_with(state.sp, se[i].second.ent, monomorph_cb_s, false); - auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::make_Field({ box$(value.clone()), i })); + auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::new_Field(value.clone(), i)); auto new_lval = mutator.new_temporary( mv$(ty_d) ); mutator.push_statement( ::MIR::Statement::make_Assign({ new_lval.clone(), mv$(new_rval) }) ); @@ -823,7 +824,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& } else { - ents.push_back( ::MIR::LValue::make_Field({ box$(value.clone()), i}) ); + ents.push_back( ::MIR::LValue::new_Field(value.clone(), i) ); } } ) @@ -865,7 +866,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, ::MIR::LValue& lval) { - TU_MATCHA( (lval), (le), + TU_MATCHA( (lval.m_root), (le), (Return, ), (Argument, @@ -873,30 +874,22 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, :: (Local, ), (Static, - ), - (Field, - MIR_Cleanup_LValue(state, mutator, *le.val); - ), - (Deref, - MIR_Cleanup_LValue(state, mutator, *le.val); - ), - (Index, - MIR_Cleanup_LValue(state, mutator, *le.val); - MIR_Cleanup_LValue(state, mutator, *le.idx); - ), - (Downcast, - MIR_Cleanup_LValue(state, mutator, *le.val); ) ) - // If this is a deref of Box, unpack and deref the inner pointer - if( lval.is_Deref() ) + for(size_t i = 0; i < lval.m_wrappers.size(); i ++) { - auto& le = lval.as_Deref(); + if( !lval.m_wrappers[i].is_Deref() ) { + continue ; + } + + // If this is a deref of Box, unpack and deref the inner pointer ::HIR::TypeRef tmp; - const auto& ty = state.get_lvalue_type(tmp, *le.val); + const auto& ty = state.get_lvalue_type(tmp, lval, lval.m_wrappers.size() - i); if( state.m_resolve.is_type_owned_box(ty) ) { + unsigned num_injected_fld_zeros = 0; + // Handle Box by extracting it to its pointer. // - Locate (or remember) which field in Box is the pointer, and replace the inner by that field // > Dumb idea, assume it's always the first field. Keep accessing until located. @@ -924,11 +917,16 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, :: tmp = monomorphise_type(state.sp, str.m_params, te.path.m_data.as_Generic().m_params, *ty_tpl); typ = &tmp; - auto new_lval = ::MIR::LValue::make_Field({ mv$(le.val), 0 }); - le.val = box$(new_lval); + num_injected_fld_zeros ++; } MIR_ASSERT(state, typ->m_data.is_Pointer(), "First non-path field in Box wasn't a pointer - " << *typ); // We have reached the pointer. Good. + + // Inject all of the field zero accesses (before the deref) + while(num_injected_fld_zeros--) + { + lval.m_wrappers.insert( lval.m_wrappers.begin() + i, ::MIR::LValue::Wrapper::new_Field(0) ); + } } } } @@ -1030,9 +1028,9 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ), (DstMeta, // HACK: Ensure that the box Deref conversion fires here. - auto v = ::MIR::LValue::make_Deref({ box$(re.val) }); - MIR_Cleanup_LValue(state, mutator, v); - re.val = mv$( *v.as_Deref().val ); + re.val.m_wrappers.push_back( ::MIR::LValue::Wrapper::new_Deref() ); + MIR_Cleanup_LValue(state, mutator, re.val); + re.val.m_wrappers.pop_back(); // If the type is an array (due to a monomorpised generic?) then replace. ::HIR::TypeRef tmp; @@ -1053,9 +1051,9 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ), (DstPtr, // HACK: Ensure that the box Deref conversion fires here. - auto v = ::MIR::LValue::make_Deref({ box$(re.val) }); - MIR_Cleanup_LValue(state, mutator, v); - re.val = mv$( *v.as_Deref().val ); + re.val.m_wrappers.push_back( ::MIR::LValue::Wrapper::new_Deref() ); + MIR_Cleanup_LValue(state, mutator, re.val); + re.val.m_wrappers.pop_back(); ), (MakeDst, MIR_Cleanup_Param(state, mutator, re.ptr_val); @@ -1218,13 +1216,13 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, e.args.reserve( fcn_ty.m_arg_types.size() ); for(unsigned int i = 0; i < fcn_ty.m_arg_types.size(); i ++) { - e.args.push_back( ::MIR::LValue::make_Field({ box$(args_lvalue.clone()), i }) ); + e.args.push_back( ::MIR::LValue::new_Field(args_lvalue.clone(), i) ); } // If the trait is Fn/FnMut, dereference the input value. if( pe.trait.m_path == resolve.m_lang_FnOnce ) e.fcn = mv$(fcn_lvalue); else - e.fcn = ::MIR::LValue::make_Deref({ box$(fcn_lvalue) }); + e.fcn = ::MIR::LValue::new_Deref( mv$(fcn_lvalue) ); } } ) diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index b02c1e5b..69ffa850 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -176,40 +176,7 @@ namespace { #undef FMT } void fmt_val(::std::ostream& os, const ::MIR::LValue& lval) { - TU_MATCHA( (lval), (e), - (Return, - os << "RETURN"; - ), - (Argument, - os << "arg$" << e.idx; - ), - (Local, - os << "_$" << e; - ), - (Static, - os << *e; - ), - (Field, - os << "("; - fmt_val(os, *e.val); - os << ")." << e.field_index; - ), - (Deref, - os << "*"; - fmt_val(os, *e.val); - ), - (Index, - os << "("; - fmt_val(os, *e.val); - os << ")["; - fmt_val(os, *e.idx); - os << "]"; - ), - (Downcast, - fmt_val(os, *e.val); - os << " as variant" << e.variant_index; - ) - ) + os << lval; } void fmt_val(::std::ostream& os, const ::MIR::Constant& e) { TU_MATCHA( (e), (ce), diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 9e749811..d511a32a 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -177,7 +177,7 @@ namespace { for(size_t i = 0; i < pat.m_binding.m_implicit_deref_count; i ++) { - lval = ::MIR::LValue::make_Deref({ box$(lval) }); + lval = ::MIR::LValue::new_Deref(mv$(lval)); } switch( pat.m_binding.m_type ) @@ -215,35 +215,35 @@ namespace { for(size_t i = 0; i < pat.m_implicit_deref_count; i ++) { - lval = ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }); + lval = ::MIR::LValue::new_Deref(mv$(lval)); } TU_MATCH_HDRA( (pat.m_data), {) TU_ARMA(Any, e) { } TU_ARMA(Box, e) { - destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); + destructure_from_ex(sp, *e.sub, ::MIR::LValue::new_Deref(mv$(lval)), allow_refutable); } TU_ARMA(Ref, e) { - destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); + destructure_from_ex(sp, *e.sub, ::MIR::LValue::new_Deref(mv$(lval)), allow_refutable); } TU_ARMA(Tuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { - destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable); } } TU_ARMA(SplitTuple, e) { assert(e.total_size >= e.leading.size() + e.trailing.size()); for(unsigned int i = 0; i < e.leading.size(); i ++ ) { - destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable); } // TODO: Is there a binding in the middle? unsigned int ofs = e.total_size - e.trailing.size(); for(unsigned int i = 0; i < e.trailing.size(); i ++ ) { - destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), ofs+i}), allow_refutable); + destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Field(lval.clone(), ofs+i), allow_refutable); } } TU_ARMA(StructValue, e) { @@ -252,7 +252,7 @@ namespace { TU_ARMA(StructTuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { - destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable); } } TU_ARMA(Struct, e) { @@ -264,7 +264,7 @@ namespace { for(const auto& fld_pat : e.sub_patterns) { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); - destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval.clone() ), idx}), allow_refutable); + destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable); } } } @@ -302,10 +302,10 @@ namespace { ERROR(sp, E0000, "Variant " << variants[i].name << " not handled"); } } - auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); + auto lval_var = ::MIR::LValue::new_Downcast(mv$(lval), e.binding_idx); for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { - destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval_var.clone() ), i}), allow_refutable); + destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval_var.clone(), i), allow_refutable); } } TU_ARMA(EnumStruct, e) { @@ -316,11 +316,11 @@ namespace { const auto& str = *var.type.m_data.as_Path().binding.as_Struct(); ASSERT_BUG(sp, str.m_data.is_Named(), "Struct pattern on non-Named struct - " << e.path); const auto& fields = str.m_data.as_Named(); - auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); + auto lval_var = ::MIR::LValue::new_Downcast(mv$(lval), e.binding_idx); for(const auto& fld_pat : e.sub_patterns) { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); - destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval_var.clone() ), idx}), allow_refutable); + destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::new_Field(lval_var.clone(), idx), allow_refutable); } } TU_ARMA(Slice, e) { @@ -335,7 +335,7 @@ namespace { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++) { const auto& subpat = e.sub_patterns[i]; - destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable ); + destructure_from_ex(sp, subpat, ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable ); } } else @@ -346,7 +346,7 @@ namespace { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++) { const auto& subpat = e.sub_patterns[i]; - destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable ); + destructure_from_ex(sp, subpat, ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable ); } } } @@ -374,7 +374,7 @@ namespace { for(unsigned int i = 0; i < e.leading.size(); i ++) { unsigned int idx = 0 + i; - destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); + destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable ); } if( e.extra_bind.is_valid() ) { @@ -383,7 +383,7 @@ namespace { for(unsigned int i = 0; i < e.trailing.size(); i ++) { unsigned int idx = array_size - e.trailing.size() + i; - destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); + destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable ); } } else @@ -409,13 +409,13 @@ namespace { ::MIR::LValue len_lval; if( e.extra_bind.is_valid() || e.trailing.size() > 0 ) { - len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, lval).clone() })); + len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, lval) })); } for(unsigned int i = 0; i < e.leading.size(); i ++) { unsigned int idx = i; - destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); + destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable ); } if( e.extra_bind.is_valid() ) { @@ -427,7 +427,7 @@ namespace { ::HIR::BorrowType bt = H::get_borrow_type(sp, e.extra_bind); ::MIR::LValue ptr_val = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef::new_borrow( bt, inner_type.clone() ), - ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::make_Field({ box$(lval.clone()), static_cast(e.leading.size()) }) }) + ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::new_Field( lval.clone(), static_cast(e.leading.size()) ) }) ); // TODO: Cast to raw pointer? Or keep as a borrow? @@ -442,7 +442,7 @@ namespace { auto sub_val = ::MIR::Param(::MIR::Constant::make_Uint({ e.trailing.size() - i, ::HIR::CoreType::Usize })); ::MIR::LValue ofs_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ len_lval.clone(), ::MIR::eBinOp::SUB, mv$(sub_val) }) ); // Recurse with the indexed value - destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Index({ box$(lval.clone()), box$(ofs_val) }), allow_refutable); + destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Index( lval.clone(), ofs_val.m_root.as_Local() ), allow_refutable); } } } @@ -574,7 +574,7 @@ namespace { TRACE_FUNCTION_F("_Return"); this->visit_node_ptr(node.m_value); - m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Return({}), m_builder.get_result(node.span()) ); + m_builder.push_stmt_assign( node.span(), ::MIR::LValue::new_Return(), m_builder.get_result(node.span()) ); m_builder.terminate_scope_early( node.span(), m_builder.fcn_scope() ); m_builder.end_block( ::MIR::Terminator::make_Return({}) ); } @@ -1474,7 +1474,7 @@ namespace { limit_val = ::MIR::Constant::make_Uint({ e.size_val, ::HIR::CoreType::Usize }); ), (Slice, - limit_val = ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(node.m_value->span(), value).clone() }); + limit_val = ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(node.m_value->span(), value) }); ) ) @@ -1508,7 +1508,13 @@ namespace { m_builder.set_cur_block( arm_continue ); } - m_builder.set_result( node.span(), ::MIR::LValue::make_Index({ box$(value), box$(index) }) ); + if( !index.is_Local()) + { + auto local_idx = m_builder.new_temporary(::HIR::CoreType::Usize); + m_builder.push_stmt_assign(node.span(), local_idx.clone(), mv$(index)); + index = mv$(local_idx); + } + m_builder.set_result( node.span(), ::MIR::LValue::new_Index( mv$(value), index.m_root.as_Local() ) ); } void visit(::HIR::ExprNode_Deref& node) override @@ -1591,7 +1597,7 @@ namespace { } } - m_builder.set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Deref( mv$(val) ) ); } void visit(::HIR::ExprNode_Emplace& node) override @@ -1702,7 +1708,7 @@ namespace { // 3. Get the value and assign it into `place_raw` node.m_value->visit(*this); auto val = m_builder.get_result(node.span()); - m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Deref({ box$(place_raw.clone()) }), mv$(val) ); + m_builder.push_stmt_assign( node.span(), ::MIR::LValue::new_Deref(place_raw.clone()), mv$(val), /*drop_destination=*/false ); // 3. Return a call to `finalize` ::HIR::Path finalize_path(::HIR::GenericPath {}); @@ -1806,9 +1812,7 @@ namespace { auto place = m_builder.new_temporary( place_type ); m_builder.push_stmt_assign(node.span(), place.clone(), ::MIR::RValue::make_Cast({ mv$(place_raw), place_type.clone() })); // 3. Do a non-dropping write into the target location (i.e. just a MIR assignment) - // TODO: This should indicate that the destination shouldn't be dropped, but since drops don't happen on - // reassign currently, that's not yet an issue. - m_builder.push_stmt_assign(node.span(), ::MIR::LValue::make_Deref({box$(place.clone())}), mv$(val)); + m_builder.push_stmt_assign(node.span(), ::MIR::LValue::new_Deref(place.clone()), mv$(val), /*drop_destination=*/false); // 4. Convert the pointer into an `owned_box` auto res_type = ::HIR::TypeRef::new_path(::HIR::GenericPath(lang_owned_box, mv$(trait_params_data)), &m_builder.crate().get_struct_by_path(node.span(), lang_owned_box)); auto res = m_builder.new_temporary(res_type); @@ -2056,20 +2060,20 @@ namespace { unsigned int idx; if( ::std::isdigit(node.m_field.c_str()[0]) ) { ::std::stringstream(node.m_field.c_str()) >> idx; - m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Field( mv$(val), idx ) ); } else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Struct() ) { const auto& str = **bep; const auto& fields = str.m_data.as_Named(); idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin(); - m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Field( mv$(val), idx ) ); } else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Union() ) { const auto& unm = **bep; const auto& fields = unm.m_variants; idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin(); - m_builder.set_result( node.span(), ::MIR::LValue::make_Downcast({ box$(val), idx }) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Downcast( mv$(val), idx ) ); } else { BUG(node.span(), "Field access on non-union/struct - " << val_ty); @@ -2202,7 +2206,7 @@ namespace { m_builder.set_result( node.span(), mv$(tmp) ); ), (Static, - m_builder.set_result( node.span(), ::MIR::LValue::make_Static(box$(node.m_path.clone())) ); + m_builder.set_result( node.span(), ::MIR::LValue::new_Static(node.m_path.clone()) ); ), (StructConstant, // TODO: Why is this still a PathValue? @@ -2321,7 +2325,7 @@ namespace { ASSERT_BUG(sp, str.m_data.is_Named(), ""); const ::HIR::t_struct_fields& fields = str.m_data.as_Named(); - ::MIR::LValue base_val; + auto base_val = ::MIR::LValue::new_Return(); if( node.m_base_value ) { DEBUG("_StructLiteral - base"); @@ -2362,7 +2366,7 @@ namespace { if( !node.m_base_value) { ERROR(node.span(), E0000, "Field '" << fields[i].first << "' not specified"); } - values[i] = ::MIR::LValue::make_Field({ box$( base_val.clone() ), i }); + values[i] = ::MIR::LValue::new_Field( base_val.clone(), i ); } else { // Partial move support will handle dropping the rest? @@ -2545,7 +2549,7 @@ namespace { else { ev.define_vars_from(ptr->span(), arg.first); - ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::make_Argument({i})); + ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::new_Argument(i)); } i ++; } diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index 194fd0e0..a1f9a10f 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -188,13 +188,10 @@ public: // - Values ::MIR::LValue get_variable(const Span& sp, unsigned idx) const { - // DIASBLED: State tracking doesn't support arguments in loops/splits -#if 1 auto it = m_var_arg_mappings.find(idx); if(it != m_var_arg_mappings.end()) - return ::MIR::LValue::make_Argument({ it->second }); -#endif - return ::MIR::LValue::make_Local( idx ); + return ::MIR::LValue::new_Argument(it->second); + return ::MIR::LValue::new_Local(idx); } ::MIR::LValue new_temporary(const ::HIR::TypeRef& ty); ::MIR::LValue lvalue_or_temp(const Span& sp, const ::HIR::TypeRef& ty, ::MIR::RValue val); @@ -224,7 +221,7 @@ public: // - Statements // Push an assignment. NOTE: This also marks the rvalue as moved - void push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val); + void push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val, bool drop_destination=true); // Push a drop (likely only used by scope cleanup) void push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int drop_flag=~0u); // Push a shallow drop (for Box) @@ -296,7 +293,7 @@ private: const VarState& get_slot_state(const Span& sp, unsigned int idx, SlotType type, unsigned int skip_count=0) const; VarState& get_slot_state_mut(const Span& sp, unsigned int idx, SlotType type); - const VarState& get_val_state(const Span& sp, const ::MIR::LValue& lv, unsigned int skip_count=0); + VarState* get_val_state_mut_p(const Span& sp, const ::MIR::LValue& lv); VarState& get_val_state_mut(const Span& sp, const ::MIR::LValue& lv); void terminate_loop_early(const Span& sp, ScopeType::Data_Loop& sd_loop); @@ -306,11 +303,11 @@ private: void complete_scope(ScopeDef& sd); public: - void with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb) const; + void with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb, const ::MIR::LValue::Wrapper* stop_wrapper=nullptr) const; bool lvalue_is_copy(const Span& sp, const ::MIR::LValue& lv) const; // Obtain the base fat poiner for a dst reference. Errors if it wasn't via a fat pointer - const ::MIR::LValue& get_ptr_to_dst(const Span& sp, const ::MIR::LValue& lv) const; + ::MIR::LValue get_ptr_to_dst(const Span& sp, const ::MIR::LValue& lv) const; }; class MirConverter: diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index e3ddce30..2bfb1a27 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -1732,13 +1732,13 @@ namespace { ), (Tuple, ASSERT_BUG(sp, idx < e.size(), "Tuple index out of range"); - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); cur_ty = &e[idx]; ), (Path, if( idx == FIELD_DEREF ) { // TODO: Check that the path is Box - lval = ::MIR::LValue::make_Deref({ box$(lval) }); + lval = ::MIR::LValue::new_Deref( mv$(lval) ); cur_ty = &e.path.m_data.as_Generic().m_params.m_types.at(0); break; } @@ -1773,7 +1773,7 @@ namespace { else { cur_ty = &fld.ent; } - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); ), (Named, assert( idx < fields.size() ); @@ -1785,7 +1785,7 @@ namespace { else { cur_ty = &fld.ent; } - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); ) ) ), @@ -1804,7 +1804,7 @@ namespace { else { cur_ty = &fld.second.ent; } - lval = ::MIR::LValue::make_Downcast({ box$(lval), idx }); + lval = ::MIR::LValue::new_Downcast(mv$(lval), idx); ), (Enum, auto monomorph_to_ptr = [&](const auto& ty)->const auto* { @@ -1824,7 +1824,7 @@ namespace { const auto& var = variants[idx]; cur_ty = monomorph_to_ptr(var.type); - lval = ::MIR::LValue::make_Downcast({ box$(lval), idx }); + lval = ::MIR::LValue::new_Downcast(mv$(lval), idx); ) ) ), @@ -1841,7 +1841,7 @@ namespace { assert(idx < e.size_val); cur_ty = &*e.inner; if( idx < FIELD_INDEX_MAX ) - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); else { idx -= FIELD_INDEX_MAX; idx = FIELD_INDEX_MAX - idx; @@ -1851,16 +1851,16 @@ namespace { (Slice, cur_ty = &*e.inner; if( idx < FIELD_INDEX_MAX ) - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + lval = ::MIR::LValue::new_Field(mv$(lval), idx); else { idx -= FIELD_INDEX_MAX; idx = FIELD_INDEX_MAX - idx; // 1. Create an LValue containing the size of this slice subtract `idx` - auto len_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, lval).clone() })); + auto len_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, lval) })); auto sub_val = ::MIR::Param(::MIR::Constant::make_Uint({ idx, ::HIR::CoreType::Usize })); auto ofs_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ mv$(len_lval), ::MIR::eBinOp::SUB, mv$(sub_val) }) ); // 2. Return _Index with that value - lval = ::MIR::LValue::make_Index({ box$(lval), box$(ofs_val) }); + lval = ::MIR::LValue::new_Index(mv$(lval), ofs_val.as_Local()); } ), (Borrow, @@ -1874,7 +1874,7 @@ namespace { cur_ty = &*e.inner; } DEBUG(i << " " << *cur_ty); - lval = ::MIR::LValue::make_Deref({ box$(lval) }); + lval = ::MIR::LValue::new_Deref(mv$(lval)); ), (Pointer, ERROR(sp, E0000, "Attempting to match over a pointer"); @@ -1978,14 +1978,14 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& DEBUG("ty = " << ity << ", val = " << val); const auto& ty = ity; - TU_MATCHA( (ty.m_data), (te), - (Infer, + TU_MATCH_HDRA( (ty.m_data), {) + TU_ARMA(Infer, _te) { BUG(sp, "Hit _ in type - " << ty); - ), - (Diverge, + } + TU_ARMA(Diverge, _te) { BUG(sp, "Matching over !"); - ), - (Primitive, + } + TU_ARMA(Primitive, te) { switch(te) { case ::HIR::CoreType::Bool: { @@ -2152,17 +2152,20 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& case ::HIR::CoreType::Str: { ASSERT_BUG(sp, rule.is_Value() && rule.as_Value().is_StaticString(), ""); const auto& v = rule.as_Value(); + ASSERT_BUG(sp, val.is_Deref(), ""); + val.m_wrappers.pop_back(); + auto str_val = mv$(val); auto succ_bb = builder.new_bb_unlinked(); auto test_val = ::MIR::Param(::MIR::Constant( v.as_StaticString() )); - auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(*val.as_Deref().val), ::MIR::eBinOp::EQ, mv$(test_val) })); + auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(str_val), ::MIR::eBinOp::EQ, mv$(test_val) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) ); builder.set_cur_block(succ_bb); } break; } - ), - (Path, + } + TU_ARMA(Path, te) { TU_MATCHA( (te.binding), (pbe), (Unbound, BUG(sp, "Encounterd unbound path - " << te.path); @@ -2221,26 +2224,26 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& // Recurse with the new ruleset MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, re.sub_rules.data(), re.sub_rules.size(), - var_ty_m, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1, + var_ty_m, ::MIR::LValue::new_Downcast(val.clone(), var_idx), rule.field_path.size()+1, fail_bb ); } ) // TypePathBinding::Enum ) - ), // Type::Data::Path - (Generic, + } // Type::Data::Path + TU_ARMA(Generic, _te) { BUG(sp, "Attempting to match a generic"); - ), - (TraitObject, + } + TU_ARMA(TraitObject, te) { BUG(sp, "Attempting to match a trait object"); - ), - (ErasedType, + } + TU_ARMA(ErasedType, te) { BUG(sp, "Attempting to match an erased type"); - ), - (Array, + } + TU_ARMA(Array, te) { TODO(sp, "Match directly on array?"); - ), - (Slice, + } + TU_ARMA(Slice, te) { ASSERT_BUG(sp, rule.is_Slice() || rule.is_SplitSlice() || (rule.is_Value() && rule.as_Value().is_Bytes()), "Can only match slice with Bytes or Slice rules - " << rule); if( rule.is_Value() ) { ASSERT_BUG(sp, *te.inner == ::HIR::CoreType::U8, "Bytes pattern on non-&[u8]"); @@ -2249,7 +2252,8 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& auto succ_bb = builder.new_bb_unlinked(); - auto inner_val = val.as_Deref().val->clone(); + ASSERT_BUG(sp, val.is_Deref(), "Slice pattern on non-Deref - " << val); + auto inner_val = val.clone_unwrapped(); auto slice_rval = ::MIR::RValue::make_MakeDst({ mv$(cloned_val), mv$(size_val) }); auto test_lval = builder.lvalue_or_temp(sp, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone()), mv$(slice_rval)); @@ -2262,7 +2266,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& // Compare length auto test_val = ::MIR::Param( ::MIR::Constant::make_Uint({ re.len, ::HIR::CoreType::Usize }) ); - auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val).clone() })); + auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val) })); auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::EQ, mv$(test_val) })); auto len_succ_bb = builder.new_bb_unlinked(); @@ -2281,7 +2285,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& // Compare length auto test_val = ::MIR::Param( ::MIR::Constant::make_Uint({ re.min_len, ::HIR::CoreType::Usize}) ); - auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val).clone() })); + auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val) })); auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::LT, mv$(test_val) })); auto len_succ_bb = builder.new_bb_unlinked(); @@ -2302,23 +2306,23 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& else { BUG(sp, "Invalid rule type for slice - " << rule); } - ), - (Tuple, + } // Type::Data::Array + TU_ARMA(Tuple, te) { TODO(sp, "Match directly on tuple?"); - ), - (Borrow, + } + TU_ARMA(Borrow, te) { TODO(sp, "Match directly on borrow?"); - ), // Type::Data::Borrow - (Pointer, + } // Type::Data::Borrow + TU_ARMA(Pointer, te) { BUG(sp, "Attempting to match a pointer - " << rule << " against " << ty); - ), - (Function, + } + TU_ARMA(Function, te) { BUG(sp, "Attempting to match a function pointer - " << rule << " against " << ty); - ), - (Closure, + } + TU_ARMA(Closure, te) { BUG(sp, "Attempting to match a closure"); - ) - ) + } + } } return 0; } @@ -3035,10 +3039,10 @@ void MatchGenGrouped::gen_dispatch__primitive(::HIR::TypeRef ty, ::MIR::LValue v } m_builder.end_block( ::MIR::Terminator::make_Goto(def_blk) ); } break; - case ::HIR::CoreType::Str: + case ::HIR::CoreType::Str: { // Remove the deref on the &str - auto oval = mv$(val); - auto val = mv$(*oval.as_Deref().val); + ASSERT_BUG(sp, !val.m_wrappers.empty() && val.m_wrappers.back().is_Deref(), "&str match on non-Deref lvalue - " << val); + val.m_wrappers.pop_back(); ::std::vector< ::MIR::BasicBlockId> targets; ::std::vector< ::std::string> values; @@ -3062,7 +3066,7 @@ void MatchGenGrouped::gen_dispatch__primitive(::HIR::TypeRef ty, ::MIR::LValue v m_builder.end_block( ::MIR::Terminator::make_SwitchValue({ mv$(val), def_blk, mv$(targets), ::MIR::SwitchValues(mv$(values)) }) ); - break; + } break; } } @@ -3100,7 +3104,7 @@ void MatchGenGrouped::gen_dispatch__enum(::HIR::TypeRef ty, ::MIR::LValue val, c void MatchGenGrouped::gen_dispatch__slice(::HIR::TypeRef ty, ::MIR::LValue val, const ::std::vector& rules, size_t ofs, const ::std::vector<::MIR::BasicBlockId>& arm_targets, ::MIR::BasicBlockId def_blk) { - auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val).clone() })); + auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val) })); // TODO: Re-sort the rules list to interleve Constant::Bytes and Slice @@ -3162,8 +3166,8 @@ void MatchGenGrouped::gen_dispatch__slice(::HIR::TypeRef ty, ::MIR::LValue val, m_builder.set_cur_block(succ_blk); // TODO: What if `val` isn't a Deref? - ASSERT_BUG(sp, val.is_Deref(), "TODO: Handle non-Deref matches of byte strings"); - cmp_lval_eq = this->push_compare( val.as_Deref().val->clone(), ::MIR::eBinOp::EQ, mv$(cmp_slice_val) ); + ASSERT_BUG(sp, !val.m_wrappers.empty() && val.m_wrappers.back().is_Deref(), "TODO: Handle non-Deref matches of byte strings - " << val); + cmp_lval_eq = this->push_compare( val.clone_unwrapped(), ::MIR::eBinOp::EQ, mv$(cmp_slice_val) ); m_builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval_eq), arm_targets[tgt_ofs], def_blk }) ); m_builder.set_cur_block(next_cmp_blk); @@ -3273,7 +3277,7 @@ void MatchGenGrouped::gen_dispatch_splitslice(const field_path_t& field_path, co ASSERT_BUG(sp, ty.m_data.is_Slice(), "SplitSlice pattern on non-slice - " << ty); // Obtain slice length - auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val).clone() })); + auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val) })); // 1. Check that length is sufficient for the pattern to be used // `IF len < min_len : def_blk, next diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 1453acb3..6f0ef891 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -12,9 +12,12 @@ #include #include // ::std::find -void ::MIR::TypeResolve::fmt_pos(::std::ostream& os) const +void ::MIR::TypeResolve::fmt_pos(::std::ostream& os, bool include_path/*=false*/) const { - os << this->m_path << " BB" << this->bb_idx << "/"; + if( include_path ) { + os << this->m_path << " "; + } + os << "BB" << this->bb_idx << "/"; if( this->stmt_idx == STMT_TERM ) { os << "TERM"; } @@ -27,7 +30,7 @@ void ::MIR::TypeResolve::print_msg(const char* tag, ::std::functionget_lvalue_type(tmp, *e.val); + rv = &get_static_type(tmp, e); + ) + ) + assert(wrapper_skip_count <= val.m_wrappers.size()); + const auto* stop_wrapper = &val.m_wrappers[ val.m_wrappers.size() - wrapper_skip_count ]; + for(const auto& w : val.m_wrappers) + { + if( &w == stop_wrapper ) + break; + rv = &this->get_unwrapped_type(tmp, w, *rv); + } + return *rv; +} +const ::HIR::TypeRef& ::MIR::TypeResolve::get_unwrapped_type(::HIR::TypeRef& tmp, const ::MIR::LValue::Wrapper& w, const ::HIR::TypeRef& ty) const +{ + TU_MATCH_HDRA( (w), {) + TU_ARMA(Field, field_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Field access on unexpected type - " << ty); @@ -98,14 +115,14 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return *te.inner; ), (Tuple, - MIR_ASSERT(*this, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size()); - return te[e.field_index]; + MIR_ASSERT(*this, field_index < te.size(), "Field index out of range in tuple " << field_index << " >= " << te.size()); + return te[field_index]; ), (Path, if( const auto* tep = te.binding.opt_Struct() ) { const auto& str = **tep; - auto monomorph = [&](const auto& ty)->const auto& { + auto maybe_monomorph = [&](const auto& ty)->const auto& { if( monomorphise_type_needed(ty) ) { tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, ty); m_resolve.expand_associated_types(sp, tmp); @@ -120,12 +137,12 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c MIR_BUG(*this, "Field on unit-like struct - " << ty); ), (Tuple, - MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct " << te.path); - return monomorph(se[e.field_index].ent); + MIR_ASSERT(*this, field_index < se.size(), "Field index out of range in tuple-struct " << te.path); + return maybe_monomorph(se[field_index].ent); ), (Named, - MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct " << te.path); - return monomorph(se[e.field_index].second.ent); + MIR_ASSERT(*this, field_index < se.size(), "Field index out of range in struct " << te.path); + return maybe_monomorph(se[field_index].second.ent); ) ) } @@ -142,8 +159,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return t; } }; - MIR_ASSERT(*this, e.field_index < unm.m_variants.size(), "Field index out of range for union"); - return maybe_monomorph(unm.m_variants.at(e.field_index).second.ent); + MIR_ASSERT(*this, field_index < unm.m_variants.size(), "Field index out of range for union"); + return maybe_monomorph(unm.m_variants.at(field_index).second.ent); } else { @@ -151,9 +168,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c } ) ) - ), - (Deref, - const auto& ty = this->get_lvalue_type(tmp, *e.val); + } + TU_ARMA(Deref, _e) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Deref on unexpected type - " << ty); @@ -174,9 +190,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return *te.inner; ) ) - ), - (Index, - const auto& ty = this->get_lvalue_type(tmp, *e.val); + } + TU_ARMA(Index, index_local) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Index on unexpected type - " << ty); @@ -188,9 +203,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return *te.inner; ) ) - ), - (Downcast, - const auto& ty = this->get_lvalue_type(tmp, *e.val); + } + TU_ARMA(Downcast, variant_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( MIR_BUG(*this, "Downcast on unexpected type - " << ty); @@ -202,8 +216,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c const auto& enm = *te.binding.as_Enum(); MIR_ASSERT(*this, enm.m_data.is_Data(), "Downcast on non-data enum - " << ty); const auto& variants = enm.m_data.as_Data(); - MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range for " << ty); - const auto& variant = variants[e.variant_index]; + MIR_ASSERT(*this, variant_index < variants.size(), "Variant index out of range for " << ty); + const auto& variant = variants[variant_index]; const auto& var_ty = variant.type; if( monomorphise_type_needed(var_ty) ) { @@ -218,12 +232,13 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c else { const auto& unm = *te.binding.as_Union(); - MIR_ASSERT(*this, e.variant_index < unm.m_variants.size(), "Variant index out of range"); - const auto& variant = unm.m_variants[e.variant_index]; + MIR_ASSERT(*this, variant_index < unm.m_variants.size(), "Variant index out of range"); + const auto& variant = unm.m_variants[variant_index]; const auto& var_ty = variant.second.ent; + //return m_resolve.maybe_monomorph(sp, tmp, unm.m_params, te.path.m_data.as_Generic().m_params, var_ty); if( monomorphise_type_needed(var_ty) ) { - tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, variant.second.ent); + tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, var_ty); m_resolve.expand_associated_types(sp, tmp); return tmp; } @@ -233,8 +248,8 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c } ) ) - ) - ) + } + } throw ""; } const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, const ::MIR::Param& val) const @@ -383,6 +398,15 @@ namespace visit { { if( cb(lv, u) ) return true; +#if 1 + for(const auto& w : lv.m_wrappers) + { + if( w.is_Index() ) + { + cb(LValue::new_Local(w.as_Index()), ValUsage::Read); + } + } +#else TU_MATCHA( (lv), (e), (Return, ), @@ -408,6 +432,7 @@ namespace visit { return visit_mir_lvalue(*e.val, u, cb); ) ) +#endif return false; } @@ -625,32 +650,15 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime(::MIR::TypeResolve& state, c { auto assigned_lvalue = [&](size_t bb_idx, size_t stmt_idx, const ::MIR::LValue& lv) { // NOTE: Fills the first statement after running, just to ensure that any assigned value has _a_ lifetime - if( const auto* de = lv.opt_Local() ) + if( lv.m_root.is_Local() ) { - if( !mask || mask->at(*de) ) + auto de = lv.m_root.as_Local(); + if( !mask || mask->at(de) ) { - MIR_Helper_GetLifetimes_DetermineValueLifetime(state, fcn, bb_idx, stmt_idx, lv, block_offsets, slot_lifetimes[*de]); - slot_lifetimes[*de].fill(block_offsets, bb_idx, stmt_idx, stmt_idx); + MIR_Helper_GetLifetimes_DetermineValueLifetime(state, fcn, bb_idx, stmt_idx, lv, block_offsets, slot_lifetimes[de]); + slot_lifetimes[de].fill(block_offsets, bb_idx, stmt_idx, stmt_idx); } } - else - { - // Not a direct assignment of a slot. But check if a slot is mutated as part of this. - ::MIR::visit::visit_mir_lvalue(lv, ValUsage::Write, [&](const auto& ilv, ValUsage vu) { - if( const auto* de = ilv.opt_Local() ) - { - if( vu == ValUsage::Write ) - { - if( !mask || mask->at(*de) ) - { - MIR_Helper_GetLifetimes_DetermineValueLifetime(state, fcn, bb_idx, stmt_idx, lv, block_offsets, slot_lifetimes[*de]); - slot_lifetimes[*de].fill(block_offsets, bb_idx, stmt_idx, stmt_idx); - } - } - } - return false; - }); - } }; const auto& bb = fcn.blocks[bb_idx]; @@ -673,11 +681,12 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime(::MIR::TypeResolve& state, c else if( const auto* se = stmt.opt_Drop() ) { // HACK: Mark values as valid wherever there's a drop (prevents confusion by simple validator) - if( const auto* de = se->slot.opt_Local() ) + if( se->slot.m_wrappers.empty() && se->slot.m_root.is_Local() ) { - if( !mask || mask->at(*de) ) + auto de = se->slot.m_root.as_Local(); + if( !mask || mask->at(de) ) { - slot_lifetimes[*de].fill(block_offsets, bb_idx, stmt_idx,stmt_idx); + slot_lifetimes[de].fill(block_offsets, bb_idx, stmt_idx,stmt_idx); } } } diff --git a/src/mir/helpers.hpp b/src/mir/helpers.hpp index 58eee9b9..0296a1c4 100644 --- a/src/mir/helpers.hpp +++ b/src/mir/helpers.hpp @@ -104,7 +104,7 @@ public: } unsigned int get_cur_stmt_ofs() const; - void fmt_pos(::std::ostream& os) const; + void fmt_pos(::std::ostream& os, bool include_path=false) const; void print_bug(::std::function cb) const { print_msg("ERROR", cb); } @@ -116,7 +116,14 @@ public: const ::MIR::BasicBlock& get_block(::MIR::BasicBlockId id) const; const ::HIR::TypeRef& get_static_type(::HIR::TypeRef& tmp, const ::HIR::Path& path) const; - const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const; + const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val, unsigned wrapper_skip_count=0) const; + const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue::CRef& val) const { + return get_lvalue_type(tmp, val.lv(), val.lv().m_wrappers.size() - val.wrapper_count()); + } + const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue::MRef& val) const { + return get_lvalue_type(tmp, val.lv(), val.lv().m_wrappers.size() - val.wrapper_count()); + } + const ::HIR::TypeRef& get_unwrapped_type(::HIR::TypeRef& tmp, const ::MIR::LValue::Wrapper& w, const ::HIR::TypeRef& ty) const; const ::HIR::TypeRef& get_param_type(::HIR::TypeRef& tmp, const ::MIR::Param& val) const; ::HIR::TypeRef get_const_type(const ::MIR::Constant& c) const; diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 83f7e1f0..8e3045d6 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -91,119 +91,86 @@ namespace MIR { throw ""; } - ::std::ostream& operator<<(::std::ostream& os, const LValue& x) + void LValue::RefCommon::fmt(::std::ostream& os) const { - TU_MATCHA( (x), (e), + TU_MATCHA( (m_lv->m_root), (e), (Return, os << "retval"; ), (Argument, - os << "a" << e.idx; + os << "a" << e; ), (Local, os << "_" << e; ), (Static, - os << "(" << *e << ")"; - ), - (Field, - os << *e.val << "." << e.field_index; - ), - (Deref, - os << *e.val << "*"; - ), - (Index, - os << *e.val << "[" << *e.idx << "]"; - ), - (Downcast, - os << *e.val << "#" << e.variant_index; + os << "(" << e << ")"; ) ) + for(size_t i = 0; i < m_wrapper_count; i ++) + { + const LValue::Wrapper& w = m_lv->m_wrappers.at(i); + TU_MATCHA( (w), (e), + (Field, + os << "." << e; + ), + (Deref, + os << "*"; + ), + (Index, + os << "[_" << e << "]"; + ), + (Downcast, + os << "#" << e; + ) + ) + } + } + + ::std::ostream& operator<<(::std::ostream& os, const LValue& x) + { + LValue::CRef(x).fmt(os); return os; } - bool operator<(const LValue& a, const LValue& b) + + Ordering LValue::Storage::ord(const LValue::Storage& x) const { - if( a.tag() != b.tag() ) - return a.tag() < b.tag(); - TU_MATCHA( (a, b), (ea, eb), - (Return, - return false; - ), - (Argument, - return ea.idx < eb.idx; - ), - (Local, - return ea < eb; - ), - (Static, - return ea < eb; - ), - (Field, - if( *ea.val != *eb.val ) - return *ea.val < *eb.val; - if( ea.field_index != eb.field_index ) - return ea.field_index < eb.field_index; - return true; - ), - (Deref, - return *ea.val < *eb.val; - ), - (Index, - if( *ea.val != *eb.val ) - return *ea.val < *eb.val; - return *ea.idx < *eb.idx; - ), - (Downcast, - if( *ea.val != *eb.val ) - return *ea.val < *eb.val; - return ea.variant_index < eb.variant_index; - ) - ) - throw ""; + if( x.is_Static() ) + { + if( this->is_Static() ) + return this->as_Static().ord( x.as_Static() ); + else + return OrdLess; + } + else + { + if( this->is_Static() ) + return OrdGreater; + } + + return ::ord(this->val, x.val); } - bool operator==(const LValue& a, const LValue& b) + Ordering LValue::ord(const LValue& x) const { - if( a.tag() != b.tag() ) - return false; - TU_MATCHA( (a, b), (ea, eb), - (Return, - return true; - ), - (Argument, - return ea.idx == eb.idx; - ), - (Local, - return ea == eb; - ), - (Static, - return ea == eb; - ), - (Field, - if( *ea.val != *eb.val ) - return false; - if( ea.field_index != eb.field_index ) - return false; - return true; - ), - (Deref, - return *ea.val == *eb.val; - ), - (Index, - if( *ea.val != *eb.val ) - return false; - if( *ea.idx != *eb.idx ) - return false; - return true; - ), - (Downcast, - if( *ea.val != *eb.val ) - return false; - if( ea.variant_index != eb.variant_index ) - return false; - return true; - ) - ) - throw ""; + auto rv = m_root.ord(x.m_root); + if( rv != OrdEqual ) + return rv; + return ::ord(m_wrappers, x.m_wrappers); + } + Ordering LValue::RefCommon::ord(const LValue::RefCommon& x) const + { + Ordering rv; + //TRACE_FUNCTION_FR(FMT_CB(ss, this->fmt(ss); ss << " ? "; x.fmt(ss);), rv); + rv = m_lv->m_root.ord(x.m_lv->m_root); + if( rv != OrdEqual ) + return rv; + for(size_t i = 0; i < ::std::min(m_wrapper_count, x.m_wrapper_count); i ++) + { + rv = m_lv->m_wrappers[i].ord(x.m_lv->m_wrappers[i]); + if( rv != OrdEqual ) + return rv; + } + return (rv = ::ord(m_wrapper_count, x.m_wrapper_count)); } ::std::ostream& operator<<(::std::ostream& os, const Param& x) @@ -537,30 +504,14 @@ namespace MIR { } } -::MIR::LValue MIR::LValue::clone() const +::MIR::LValue::Storage MIR::LValue::Storage::clone() const { - TU_MATCHA( (*this), (e), - (Return, return LValue(e); ), - (Argument, return LValue(e); ), - (Local, return LValue(e); ), - (Static, return LValue(box$(e->clone())); ), - (Field, return LValue::make_Field({ - box$( e.val->clone() ), - e.field_index - }); ), - (Deref, return LValue::make_Deref({ - box$( e.val->clone() ) - }); ), - (Index, return LValue::make_Index({ - box$( e.val->clone() ), - box$( e.idx->clone() ) - }); ), - (Downcast, return LValue::make_Downcast({ - box$( e.val->clone() ), - e.variant_index - }); ) - ) - throw ""; + if( is_Static() ) { + return new_Static(as_Static().clone()); + } + else { + return Storage(this->val); + } } ::MIR::Constant MIR::Constant::clone() const { diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 63acf89d..f3d61dfa 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -12,21 +12,27 @@ #include // std::unique_ptr #include +class MonomorphState; + namespace MIR { typedef unsigned int RegionId; typedef unsigned int BasicBlockId; -#if 0 -// TODO: Store LValues as: +// Store LValues as: // - A packed root value (one word, using the low bits as an enum descriminator) // - A list of (inner to outer) wrappers struct LValue { class Storage { + public: + const static uintptr_t MAX_ARG = (1 << 30) - 1; // max value of 30 bits + private: + uintptr_t val; - static uintptr_t MAX_ARG = (1 << 30) - 1; // max value of 30 bits + + Storage(uintptr_t v): val(v) {} public: Storage(const Storage&) = delete; Storage& operator=(const Storage&) = delete; @@ -40,41 +46,89 @@ struct LValue this->~Storage(); this->val = x.val; x.val = 0; + return *this; } ~Storage() { if( is_Static() ) { - delete reinterpret_cast<::HIR::Path*>(val & ~3u); + delete reinterpret_cast<::HIR::Path*>(val & ~3ull); val = 0; } } - static Storage new_Return() { return Storage { MAX_ARG << 2 }; } - static Storage new_Argument(unsigned idx) { assert(idx < MAX_ARG); return Storage { idx << 2 }; ) - static Storage new_Local(unsigned idx) { assert(idx <= MAX_ARG); return Storage { (idx << 2) | 1 } }; + static Storage new_Return() { return Storage(0 << 2); } + static Storage new_Argument(unsigned idx) { assert(idx < MAX_ARG); return Storage((idx+1) << 2); } + static Storage new_Local(unsigned idx) { assert(idx <= MAX_ARG); return Storage((idx << 2) | 1); } static Storage new_Static(::HIR::Path p) { ::HIR::Path* ptr = new ::HIR::Path(::std::move(p)); - return Storage { static_cast(ptr) | 2; } + return Storage(reinterpret_cast(ptr) | 2); + } + + Storage clone() const; + + uintptr_t get_inner() const { + assert(!is_Static()); + return val; + } + static Storage from_inner(uintptr_t v) { + assert( (v & 3) < 2 ); + return Storage(v); + } + + enum Tag { + TAG_Argument, + TAG_Local, + TAG_Static, + TAG_Return, + TAGDEAD, + }; + Tag tag() const { + if(val == 0) + return TAG_Return; + return static_cast(val & 3); } - bool is_Return() const { return val == (MAX_ARG << 2) /*&& (val & 3) == 0*/; } - bool is_Argument() const { return val != (MAX_ARG << 2) && (val & 3) == 0; } + bool is_Return() const { return val == 0; } + bool is_Argument() const { return val != 0 && (val & 3) == 0; } bool is_Local() const { return (val & 3) == 1; } bool is_Static() const { return (val & 3) == 2; } - // No as_Return - unsigned as_Argument() const { assert(is_Argument()); return val >> 2; } - unsigned as_Local() const { assert(is_Local()); return val >> 2; } - const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3u); } + const char as_Return () const { assert(is_Return()); return 0; } + const unsigned as_Argument() const { assert(is_Argument()); return (val >> 2) - 1; } + const unsigned as_Local () const { assert(is_Local()); return val >> 2; } + + const ::HIR::Path& as_Static() const { assert(is_Static()); return *reinterpret_cast(val & ~3llu); } + ::HIR::Path& as_Static() { assert(is_Static()); return *reinterpret_cast< ::HIR::Path*>(val & ~3llu); } + + Ordering ord(const Storage& x) const; + bool operator==(const Storage& x) const { return this->ord(x) == OrdEqual; } + bool operator!=(const Storage& x) const { return this->ord(x) != OrdEqual; } }; class Wrapper { - uintptr_t val; + uint32_t val; + Wrapper(uint32_t v): val(v) {} public: - static Wrapper new_Deref() { return Wrapper { 0 }; } - static Wrapepr new_Field (unsigned idx) { return Wrapper { (idx << 2) | 1 }; } - static Wrapepr new_Downcast(unsigned idx) { return Wrapper { (idx << 2) | 2 }; } - static Wrapepr new_Index (unsigned idx) { return Wrapper { (idx << 2) | 3 }; } + static Wrapper new_Deref() { return Wrapper( 0 ); } + static Wrapper new_Field (unsigned idx) { return Wrapper( (idx << 2) | 1 ); } + static Wrapper new_Downcast(unsigned idx) { return Wrapper( (idx << 2) | 2 ); } + static Wrapper new_Index (unsigned idx) { if(idx == ~0u) idx = Storage::MAX_ARG; return Wrapper( (idx << 2) | 3 ); } + + uint32_t get_inner() const { return val; } + static Wrapper from_inner(uint32_t v) { + return Wrapper(v); + } + + enum Tag { + TAG_Deref, + TAG_Field, + TAG_Downcast, + TAG_Index, + TAGDEAD, + }; + Tag tag() const { + return static_cast(val & 3); + } bool is_Deref () const { return (val & 3) == 0; } // Stores the field index @@ -84,79 +138,269 @@ struct LValue // Stores a Local index bool is_Index () const { return (val & 3) == 3; } - // no as_Deref() - const unsigned as_Field() const { assert(is_Field()); return (val >> 2); } + const char as_Deref () const { assert(is_Deref()); return 0; } + const unsigned as_Field () const { assert(is_Field()); return (val >> 2); } const unsigned as_Downcast() const { assert(is_Downcast()); return (val >> 2); } // TODO: Should this return a LValue? - const unsigned as_Index() const { assert(is_Index()); return (val >> 2); } + const unsigned as_Index () const { assert(is_Index()); unsigned rv = (val >> 2); return rv; } + + void inc_Field () { assert(is_Field ()); *this = Wrapper::new_Field (as_Field () + 1); } + void inc_Downcast() { assert(is_Downcast()); *this = Wrapper::new_Downcast(as_Downcast() + 1); } + + Ordering ord(const Wrapper& x) const { return ::ord(val, x.val); } }; Storage m_root; ::std::vector m_wrappers; - static LValue new_Return() { return LValue { Storage::new_Return(), {} }; } - static LValue new_Argument(unsigned idx) { return LValue { Storage::new_Argument(idx), {} }; } - static LValue new_Local(unsigned idx) { return LValue { Storage::new_Local(idx), {} }; } - static LValue new_Static(::HIR::Path p) { return LValue { Storage::new_Static(::std::move(p)), {} }; } + LValue() + :m_root( Storage::new_Return() ) + { + } + LValue(Storage root, ::std::vector wrappers) + :m_root( ::std::move(root) ) + ,m_wrappers( ::std::move(wrappers) ) + { + } + + static LValue new_Return () { return LValue(Storage::new_Return(), {}); } + static LValue new_Argument(unsigned idx ) { return LValue(Storage::new_Argument(idx), {}); } + static LValue new_Local (unsigned idx ) { return LValue(Storage::new_Local(idx), {}); } + static LValue new_Static (::HIR::Path p) { return LValue(Storage::new_Static(::std::move(p)), {}); } + + static LValue new_Deref(LValue lv) { lv.m_wrappers.push_back(Wrapper::new_Deref()); return lv; } + static LValue new_Field(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Field(idx)); return lv; } + static LValue new_Downcast(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Downcast(idx)); return lv; } + static LValue new_Index(LValue lv, unsigned local_idx) { lv.m_wrappers.push_back(Wrapper::new_Index(local_idx)); return lv; } - static LValue new_Deref(LValue lv) { lv.m_wrappers.push_back(Wrapper::new_Deref()); } - static LValue new_Field(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Field(idx)); } - static LValue new_Downcast(LValue lv, unsigned idx) { lv.m_wrappers.push_back(Wrapper::new_Downcast(idx)); } - static LValue new_Index(LValue lv, unsigned local_idx) { lv.m_wrappers.push_back(Wrapper::new_Index(local_idx)); } + bool is_Return() const { return m_wrappers.empty() && m_root.is_Return(); } + bool is_Local () const { return m_wrappers.empty() && m_root.is_Local(); } + const unsigned as_Local() const { assert(m_wrappers.empty()); return m_root.as_Local(); } + + bool is_Deref () const { return m_wrappers.size() > 0 && m_wrappers.back().is_Deref(); } + bool is_Field () const { return m_wrappers.size() > 0 && m_wrappers.back().is_Field(); } + bool is_Downcast() const { return m_wrappers.size() > 0 && m_wrappers.back().is_Downcast(); } + const unsigned as_Field() const { assert(!m_wrappers.empty()); return m_wrappers.back().as_Field(); } + + void inc_Field () { assert(m_wrappers.size() > 0); m_wrappers.back().inc_Field (); } + void inc_Downcast() { assert(m_wrappers.size() > 0); m_wrappers.back().inc_Downcast(); } + + Ordering ord(const LValue& x) const; LValue monomorphise(const MonomorphState& ms, unsigned local_offset=0); //LValue monomorphise(const TransParams& ms, unsigned local_offset=0); - LValue clone() const; + LValue clone() const { + return LValue(m_root.clone(), m_wrappers); + } + LValue clone_wrapped(::std::vector wrappers) const { + if( this->m_wrappers.empty() ) { + return LValue(m_root.clone(), ::std::move(wrappers)); + } + else { + return clone_wrapped(wrappers.begin(), wrappers.end()); + } + } + template + LValue clone_wrapped(It begin_it, It end_it) const { + ::std::vector wrappers; + wrappers.reserve(m_wrappers.size() + ::std::distance(begin_it, end_it)); + wrappers.insert(wrappers.end(), m_wrappers.begin(), m_wrappers.end()); + wrappers.insert(wrappers.end(), begin_it, end_it); + return LValue(m_root.clone(), ::std::move(wrappers)); + } + + LValue clone_unwrapped(unsigned count=1) const { + assert(count > 0); + assert(count <= m_wrappers.size()); + return LValue(m_root.clone(), ::std::vector(m_wrappers.begin(), m_wrappers.end() - count)); + } + + /// Helper class that represents a LValue unwrapped to a certain degree + class RefCommon + { + protected: + const LValue* m_lv; + size_t m_wrapper_count; + + RefCommon(const LValue& lv, size_t wrapper_count) + :m_lv(&lv) + ,m_wrapper_count(wrapper_count) + { + assert(wrapper_count <= lv.m_wrappers.size()); + } + + public: + LValue clone() const { + return ::MIR::LValue( m_lv->m_root.clone(), ::std::vector(m_lv->m_wrappers.begin(), m_lv->m_wrappers.begin() + m_wrapper_count) ); + } + + const LValue& lv() const { return *m_lv; } + size_t wrapper_count() const { return m_wrapper_count; } + + /// Unwrap one level, returning false if already at the root + bool try_unwrap() { + if( m_wrapper_count == 0 ) { + return false; + } + else { + m_wrapper_count --; + return true; + } + } + + enum Tag { + TAGDEAD, + TAG_Return, + TAG_Argument, + TAG_Local, + TAG_Static, + TAG_Deref, + TAG_Field, + TAG_Downcast, + TAG_Index, + }; + Tag tag() const { + if( m_wrapper_count == 0 ) + { + switch(m_lv->m_root.tag()) + { + case Storage::TAGDEAD: return TAGDEAD; + case Storage::TAG_Return: return TAG_Return; + case Storage::TAG_Argument: return TAG_Argument; + case Storage::TAG_Local: return TAG_Local; + case Storage::TAG_Static: return TAG_Static; + } + } + else + { + switch(m_lv->m_wrappers[m_wrapper_count-1].tag()) + { + case Wrapper::TAGDEAD: return TAGDEAD; + case Wrapper::TAG_Deref: return TAG_Deref; + case Wrapper::TAG_Field: return TAG_Field; + case Wrapper::TAG_Downcast: return TAG_Downcast; + case Wrapper::TAG_Index: return TAG_Index; + } + } + return TAGDEAD; + } + + bool is_Local () const { return m_wrapper_count == 0 && m_lv->m_root.is_Local (); } + bool is_Return () const { return m_wrapper_count == 0 && m_lv->m_root.is_Return (); } + bool is_Argument() const { return m_wrapper_count == 0 && m_lv->m_root.is_Argument(); } + bool is_Static () const { return m_wrapper_count == 0 && m_lv->m_root.is_Static (); } + bool is_Deref () const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Deref (); } + bool is_Field () const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Field (); } + bool is_Downcast() const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Downcast(); } + bool is_Index () const { return m_wrapper_count >= 1 && m_lv->m_wrappers[m_wrapper_count-1].is_Index (); } + + const unsigned as_Local () const { assert(is_Local ()); return m_lv->m_root.as_Local (); } + const char as_Return () const { assert(is_Return ()); return m_lv->m_root.as_Return (); } + const unsigned as_Argument() const { assert(is_Argument()); return m_lv->m_root.as_Argument(); } + const HIR::Path& as_Static () const { assert(is_Static ()); return m_lv->m_root.as_Static (); } + const char as_Deref () const { assert(is_Deref ()); return m_lv->m_wrappers[m_wrapper_count-1].as_Deref (); } + const unsigned as_Field () const { assert(is_Field ()); return m_lv->m_wrappers[m_wrapper_count-1].as_Field (); } + const unsigned as_Downcast() const { assert(is_Downcast()); return m_lv->m_wrappers[m_wrapper_count-1].as_Downcast(); } + const unsigned as_Index () const { assert(is_Index ()); return m_lv->m_wrappers[m_wrapper_count-1].as_Index (); } - class Ref + void fmt(::std::ostream& os) const; + Ordering ord(const RefCommon& b) const; + }; + + class CRef: public RefCommon { - LValue& r; - size_t wrapper_idx; - public:: - LValue clone() const; - void replace(LValue x) const; + public: + CRef(const LValue& lv) + :RefCommon(lv, lv.m_wrappers.size()) + { + } + CRef(const LValue& lv, size_t wc) + :RefCommon(lv, wc) + { + } + + /// Unwrap one level + const CRef inner_ref() const { + assert(m_wrapper_count > 0); + auto rv = *this; + rv.m_wrapper_count--; + return rv; + } + + friend ::std::ostream& operator<<(::std::ostream& os, const CRef& x) { + x.fmt(os); + return os; + } + + bool operator<(const CRef& b) const { + return this->ord(b) == OrdLess; + } + bool operator==(const CRef& b) const { + return this->ord(b) == OrdEqual; + } }; + class MRef: public RefCommon + { + public: + MRef(LValue& lv) + :RefCommon(lv, lv.m_wrappers.size()) + { + } + + operator CRef() const { + return CRef(*m_lv, m_wrapper_count); + } + + MRef inner_ref() { + assert(m_wrapper_count > 0); + auto rv = *this; + rv.m_wrapper_count--; + return rv; + } + void replace(LValue x) { + auto& mut_lv = const_cast(*m_lv); + // Shortcut: No wrappers on source/destination (just assign the slot/root) + if( m_wrapper_count == 0 && x.m_wrappers.empty() ) { + mut_lv.m_root = ::std::move(x.m_root); + return ; + } + // If there's wrappers on this value (assigning over inner portion) + if( m_wrapper_count < m_lv->m_wrappers.size() ) { + // Add those wrappers to the end of the new value + x.m_wrappers.insert(x.m_wrappers.end(), m_lv->m_wrappers.begin() + m_wrapper_count, m_lv->m_wrappers.end()); + } + // Overwrite + mut_lv = ::std::move(x); + } + + friend ::std::ostream& operator<<(::std::ostream& os, const MRef& x) { + x.fmt(os); + return os; + } + }; + + Ordering ord(const LValue::CRef& x) const; + Ordering ord(const LValue::MRef& x) const; }; -#endif - -// "LVALUE" - Assignable values -TAGGED_UNION_EX(LValue, (), Return, ( - // Function return - (Return, struct{}), - // Function argument (input) - (Argument, struct { unsigned int idx; }), - // Variable/Temporary - (Local, unsigned int), - // `static` or `static mut` - (Static, ::std::unique_ptr<::HIR::Path>), - // Field access (tuple, struct, tuple struct, enum field, ...) - // NOTE: Also used to index an array/slice by a compile-time known index (e.g. in destructuring) - (Field, struct { - ::std::unique_ptr val; - unsigned int field_index; - }), - // Dereference a value - (Deref, struct { - ::std::unique_ptr val; - }), - // Index an array or slice (typeof(val) == [T; n] or [T]) - // NOTE: This is not bounds checked! - (Index, struct { - ::std::unique_ptr val; - ::std::unique_ptr idx; - }), - // Interpret an enum as a particular variant - (Downcast, struct { - ::std::unique_ptr val; - unsigned int variant_index; - }) - ), (),(), ( - LValue clone() const; - ) - ); extern ::std::ostream& operator<<(::std::ostream& os, const LValue& x); -extern bool operator<(const LValue& a, const LValue& b); -extern bool operator==(const LValue& a, const LValue& b); +static inline bool operator<(const LValue& a, const LValue::CRef& b) { + return a.ord(b) == OrdLess; +} +static inline bool operator<(const LValue& a, const LValue::MRef& b) { + return a.ord(b) == OrdLess; +} +static inline bool operator<(const LValue::CRef& a, const LValue& b) { + return b.ord(a) == OrdGreater; +} +static inline bool operator<(const LValue::MRef& a, const LValue& b) { + return b.ord(a) == OrdGreater; +} +static inline bool operator<(const LValue& a, const LValue& b) { + return a.ord(b) == OrdLess; +} +static inline bool operator==(const LValue& a, const LValue& b) { + return a.ord(b) == OrdEqual; +} static inline bool operator!=(const LValue& a, const LValue& b) { return !(a == b); } @@ -224,7 +468,7 @@ TAGGED_UNION_EX(Constant, (), Int, ( /// Parameter - A value used when a rvalue just reads (doesn't require a lvalue) /// Can be either a lvalue (memory address), or a constant -TAGGED_UNION_EX(Param, (), LValue, ( +TAGGED_UNION_EX(Param, (), Constant, ( (LValue, LValue), (Constant, Constant) ), (), (), ( @@ -237,7 +481,7 @@ TAGGED_UNION_EX(Param, (), LValue, ( ) ); -TAGGED_UNION_EX(RValue, (), Use, ( +TAGGED_UNION_EX(RValue, (), Tuple, ( (Use, LValue), (Constant, Constant), (SizedArray, struct { @@ -359,7 +603,7 @@ enum class eDropKind { SHALLOW, DEEP, }; -TAGGED_UNION(Statement, Assign, +TAGGED_UNION(Statement, Asm, // Value assigment (Assign, struct { LValue dst; diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 8d534314..a064b67d 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -68,7 +68,7 @@ MirBuilder::~MirBuilder() { if( has_result() ) { - push_stmt_assign( sp, ::MIR::LValue::make_Return({}), get_result(sp) ); + push_stmt_assign( sp, ::MIR::LValue::new_Return(), get_result(sp) ); } terminate_scope_early(sp, fcn_scope()); @@ -176,7 +176,7 @@ void MirBuilder::define_variable(unsigned int idx) auto& tmp_scope = top_scope->data.as_Owning(); assert(tmp_scope.is_temporary); tmp_scope.slots.push_back( rv ); - return ::MIR::LValue::make_Local(rv); + return ::MIR::LValue::new_Local(rv); } ::MIR::LValue MirBuilder::lvalue_or_temp(const Span& sp, const ::HIR::TypeRef& ty, ::MIR::RValue val) { @@ -258,12 +258,10 @@ void MirBuilder::set_result(const Span& sp, ::MIR::RValue val) m_result_valid = true; } -void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val) +void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val, bool drop_destination/*=true*/) { DEBUG(dst << " = " << val); ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - ASSERT_BUG(sp, dst.tag() != ::MIR::LValue::TAGDEAD, ""); - ASSERT_BUG(sp, val.tag() != ::MIR::RValue::TAGDEAD, ""); auto moved_param = [&](const ::MIR::Param& p) { if(const auto* e = p.opt_LValue()) { @@ -344,13 +342,15 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal ) // Drop target if populated - mark_value_assigned(sp, dst); + if( drop_destination ) + { + mark_value_assigned(sp, dst); + } this->push_stmt( sp, ::MIR::Statement::make_Assign({ mv$(dst), mv$(val) }) ); } void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int flag/*=~0u*/) { ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, ""); if( lvalue_is_copy(sp, val) ) { // Don't emit a drop for Copy values @@ -362,7 +362,6 @@ void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int void MirBuilder::push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val, unsigned int flag/*=~0u*/) { ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, ""); // TODO: Ensure that the type is a Box? @@ -400,22 +399,12 @@ void MirBuilder::push_stmt(const Span& sp, ::MIR::Statement stmt) void MirBuilder::mark_value_assigned(const Span& sp, const ::MIR::LValue& dst) { - VarState* state_p = nullptr; - // TODO: Tracking of complex asignment states (e.g. assignment of a field) - TU_MATCH_DEF(::MIR::LValue, (dst), (e), - ( - ), - (Return, - // Don't drop. - // No state tracking for the return value - ), - (Argument, - state_p = &get_slot_state_mut(sp, e.idx, SlotType::Argument); - ), - (Local, - state_p = &get_slot_state_mut(sp, e, SlotType::Local); - ) - ) + if( dst.m_root.is_Return() ) + { + ASSERT_BUG(sp, dst.m_wrappers.empty(), "Assignment to a component of the return value should be impossible."); + return ; + } + VarState* state_p = get_val_state_mut_p(sp, dst);; if( state_p ) { @@ -425,42 +414,28 @@ void MirBuilder::mark_value_assigned(const Span& sp, const ::MIR::LValue& dst) drop_value_from_state(sp, *state_p, dst.clone()); *state_p = VarState::make_Valid({}); } - // TODO: What about assigning into non-tracked locations? Should still cause a drop + else + { + // Assigning into non-tracked locations still causes a drop + drop_value_from_state(sp, VarState::make_Valid({}), dst.clone()); + } } void MirBuilder::raise_temporaries(const Span& sp, const ::MIR::LValue& val, const ScopeHandle& scope, bool to_above/*=false*/) { TRACE_FUNCTION_F(val); - TU_MATCH_DEF(::MIR::LValue, (val), (e), - ( + for(const auto& w : val.m_wrappers) + { + if( w.is_Index() ) { + // Raise index temporary + raise_temporaries(sp, ::MIR::LValue::new_Local(w.as_Index()), scope, to_above); + } + } + if( !val.m_root.is_Local() ) { // No raising of these source values? return ; - ), - // TODO: This may not be correct, because it can change the drop points and ordering - // HACK: Working around cases where values are dropped while the result is not yet used. - (Index, - raise_temporaries(sp, *e.val, scope, to_above); - raise_temporaries(sp, *e.idx, scope, to_above); - return ; - ), - (Deref, - raise_temporaries(sp, *e.val, scope, to_above); - return ; - ), - (Field, - raise_temporaries(sp, *e.val, scope, to_above); - return ; - ), - (Downcast, - raise_temporaries(sp, *e.val, scope, to_above); - return ; - ), - // Actual value types - (Local, - ) - ) - ASSERT_BUG(sp, val.is_Local(), "Hit value raising code with non-variable value - " << val); - const auto idx = val.as_Local(); + } + const auto idx = val.m_root.as_Local(); bool is_temp = (idx >= m_first_temp_idx); /* if( !is_temp ) { @@ -833,13 +808,12 @@ void MirBuilder::raise_all(const Span& sp, ScopeHandle source, const ScopeHandle } auto& src_scope_def = m_scopes.at(source.idx); -#if 1 ASSERT_BUG(sp, src_scope_def.data.is_Owning(), "Rasising scopes can only be done on temporaries (source)"); ASSERT_BUG(sp, src_scope_def.data.as_Owning().is_temporary, "Rasising scopes can only be done on temporaries (source)"); auto& src_list = src_scope_def.data.as_Owning().slots; for(auto idx : src_list) { - DEBUG("> Raising " << ::MIR::LValue::make_Local(idx)); + DEBUG("> Raising " << ::MIR::LValue::new_Local(idx)); assert(idx >= m_first_temp_idx); } @@ -910,13 +884,6 @@ void MirBuilder::raise_all(const Span& sp, ScopeHandle source, const ScopeHandle // Move all defined variables from one to the other auto& tgt_list = tgt_scope_def.data.as_Owning().slots; tgt_list.insert( tgt_list.end(), src_list.begin(), src_list.end() ); -#else - auto list = src_scope_def.data.as_Temporaries().temporaries; - for(auto idx : list) - { - this->raise_temporaries(sp, ::MIR::LValue::make_Temporary({ idx }), target); - } -#endif // Scope completed m_scope_stack.pop_back(); @@ -979,7 +946,7 @@ void MirBuilder::terminate_scope_early(const Span& sp, const ScopeHandle& scope, for(size_t i = 0; i < m_arg_states.size(); i ++) { const auto& state = get_slot_state(sp, i, SlotType::Argument); - this->drop_value_from_state(sp, state, ::MIR::LValue::make_Argument({ static_cast(i) })); + this->drop_value_from_state(sp, state, ::MIR::LValue::new_Argument(static_cast(i))); } } } @@ -1060,7 +1027,7 @@ namespace }); if( is_box ) { - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, *nse.inner_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, *nse.inner_state); } else { @@ -1086,13 +1053,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], nse.inner_states[i]); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], nse.inner_states[i]); } } } return; @@ -1168,7 +1135,7 @@ namespace }); if( is_box ) { - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, *nse.inner_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, *nse.inner_state); } else { BUG(sp, "MovedOut on non-Box"); @@ -1192,19 +1159,19 @@ namespace } auto& ose = old_state.as_Partial(); if( is_enum ) { - auto ilv = ::MIR::LValue::make_Downcast({ box$(lv.clone()), 0 }); + auto ilv = ::MIR::LValue::new_Downcast(lv.clone(), 0); for(size_t i = 0; i < ose.inner_states.size(); i ++) { merge_state(sp, builder, ilv, ose.inner_states[i], nse.inner_states[i]); - ilv.as_Downcast().variant_index ++; + ilv.inc_Downcast(); } } else { - auto ilv = ::MIR::LValue::make_Field({ box$(lv.clone()), 0 }); + auto ilv = ::MIR::LValue::new_Field(lv.clone(), 0); for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { merge_state(sp, builder, ilv, ose.inner_states[i], nse.inner_states[i]); - ilv.as_Field().field_index ++; + ilv.inc_Field(); } } } return; @@ -1268,13 +1235,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], nse.inner_states[i]); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], nse.inner_states[i]); } } return; } @@ -1309,7 +1276,7 @@ namespace builder.push_stmt_set_dropflag_val(sp, ose.outer_flag, is_valid); } - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, new_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, new_state); return ; } case VarState::TAG_Optional: { const auto& nse = new_state.as_Optional(); @@ -1334,7 +1301,7 @@ namespace builder.push_stmt_set_dropflag_other(sp, ose.outer_flag, nse); builder.push_stmt_set_dropflag_default(sp, nse); } - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, new_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, new_state); return; } case VarState::TAG_MovedOut: { const auto& nse = new_state.as_MovedOut(); @@ -1342,7 +1309,7 @@ namespace { TODO(sp, "Handle mismatched flags in MovedOut"); } - merge_state(sp, builder, ::MIR::LValue::make_Deref({ box$(lv.clone()) }), *ose.inner_state, *nse.inner_state); + merge_state(sp, builder, ::MIR::LValue::new_Deref(lv.clone()), *ose.inner_state, *nse.inner_state); return; } case VarState::TAG_Partial: BUG(sp, "MovedOut->Partial not valid"); @@ -1366,13 +1333,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], new_state); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], new_state); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], new_state); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], new_state); } } return ; @@ -1384,13 +1351,13 @@ namespace if( is_enum ) { for(size_t i = 0; i < ose.inner_states.size(); i ++) { - merge_state(sp, builder, ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast(i) }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Downcast(lv.clone(), static_cast(i)), ose.inner_states[i], nse.inner_states[i]); } } else { for(unsigned int i = 0; i < ose.inner_states.size(); i ++ ) { - merge_state(sp, builder, ::MIR::LValue::make_Field({ box$(lv.clone()), i }), ose.inner_states[i], nse.inner_states[i]); + merge_state(sp, builder, ::MIR::LValue::new_Field(lv.clone(), i), ose.inner_states[i], nse.inner_states[i]); } } } return ; @@ -1419,8 +1386,8 @@ void MirBuilder::terminate_loop_early(const Span& sp, ScopeType::Data_Loop& sd_l merge_state(sp, *this, val_cb(idx), old_state, get_slot_state(sp, idx, type)); } }; - merge_list(sd_loop.changed_slots, sd_loop.exit_state.states, ::MIR::LValue::make_Local, SlotType::Local); - merge_list(sd_loop.changed_args, sd_loop.exit_state.arg_states, [](auto v){ return ::MIR::LValue::make_Argument({v}); }, SlotType::Argument); + merge_list(sd_loop.changed_slots, sd_loop.exit_state.states, ::MIR::LValue::new_Local, SlotType::Local); + merge_list(sd_loop.changed_args, sd_loop.exit_state.arg_states, [](auto v){ return ::MIR::LValue::new_Argument(v); }, SlotType::Argument); } else { @@ -1475,7 +1442,7 @@ void MirBuilder::end_split_arm(const Span& sp, const ScopeHandle& handle, bool r auto it = states.find(idx); const auto& src_state = (it != states.end() ? it->second : get_slot_state(sp, idx, type, 1)); - auto lv = (type == SlotType::Local ? ::MIR::LValue::make_Local(idx) : ::MIR::LValue::make_Argument({idx})); + auto lv = (type == SlotType::Local ? ::MIR::LValue::new_Local(idx) : ::MIR::LValue::new_Argument(idx)); merge_state(sp, *this, mv$(lv), out_state, src_state); } }; @@ -1565,7 +1532,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) auto& vs = builder.get_slot_state_mut(sp, ent.first, SlotType::Local); if( vs != ent.second ) { - DEBUG(::MIR::LValue::make_Local(ent.first) << " " << vs << " => " << ent.second); + DEBUG(::MIR::LValue::new_Local(ent.first) << " " << vs << " => " << ent.second); vs = ::std::move(ent.second); } } @@ -1574,7 +1541,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) auto& vs = builder.get_slot_state_mut(sp, ent.first, SlotType::Argument); if( vs != ent.second ) { - DEBUG(::MIR::LValue::make_Argument({ent.first}) << " " << vs << " => " << ent.second); + DEBUG(::MIR::LValue::new_Argument(ent.first) << " " << vs << " => " << ent.second); vs = ::std::move(ent.second); } } @@ -1612,7 +1579,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) for(auto& ent : e->changed_slots) { auto& vs = this->get_slot_state_mut(sd.span, ent.first, SlotType::Local); - auto lv = ::MIR::LValue::make_Local(ent.first); + auto lv = ::MIR::LValue::new_Local(ent.first); DEBUG(lv << " " << vs << " => " << ent.second); if( vs != ent.second ) { @@ -1630,97 +1597,96 @@ void MirBuilder::complete_scope(ScopeDef& sd) } } -void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb) const +void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function cb, const ::MIR::LValue::Wrapper* stop_wrapper/*=nullptr*/) const { - TU_MATCH(::MIR::LValue, (val), (e), + ::HIR::TypeRef tmp; + const ::HIR::TypeRef* ty_p = nullptr; + TU_MATCHA( (val.m_root), (e), (Return, TODO(sp, "Return"); ), (Argument, - cb( m_args.at(e.idx).second ); + ty_p = &m_args.at(e).second; ), (Local, - cb( m_output.locals.at(e) ); + ty_p = &m_output.locals.at(e); ), (Static, - TU_MATCHA( (e->m_data), (pe), + TU_MATCHA( (e.m_data), (pe), (Generic, ASSERT_BUG(sp, pe.m_params.m_types.empty(), "Path params on static"); const auto& s = m_resolve.m_crate.get_static_by_path(sp, pe.m_path); - cb( s.m_type ); + ty_p = &s.m_type; ), (UfcsKnown, - TODO(sp, "Static - UfcsKnown - " << *e); + TODO(sp, "Static - UfcsKnown - " << e); ), (UfcsUnknown, - BUG(sp, "Encountered UfcsUnknown in Static - " << *e); + BUG(sp, "Encountered UfcsUnknown in Static - " << e); ), (UfcsInherent, - TODO(sp, "Static - UfcsInherent - " << *e); + TODO(sp, "Static - UfcsInherent - " << e); ) ) - ), - (Field, - with_val_type(sp, *e.val, [&](const auto& ty){ + ) + ) + assert(ty_p); + for(const auto& w : val.m_wrappers) + { + if( &w == stop_wrapper ) + { + stop_wrapper = nullptr; // Reset so the below bugcheck can work + break; + } + const auto& ty = *ty_p; + ty_p = nullptr; + auto maybe_monomorph = [&](const ::HIR::GenericParams& params_def, const ::HIR::Path& p, const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { + if( monomorphise_type_needed(t) ) { + tmp = monomorphise_type(sp, params_def, p.m_data.as_Generic().m_params, t); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return t; + } + }; + TU_MATCH_HDRA( (w), {) + TU_ARMA(Field, field_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Field access on unexpected type - " << ty); ), (Array, - cb( *te.inner ); + ty_p = &*te.inner; ), (Slice, - cb( *te.inner ); + ty_p = &*te.inner; ), (Path, - ::HIR::TypeRef tmp; if( const auto* tep = te.binding.opt_Struct() ) { const auto& str = **tep; - auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { - if( monomorphise_type_needed(t) ) { - tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, t); - m_resolve.expand_associated_types(sp, tmp); - return tmp; - } - else { - return t; - } - }; TU_MATCHA( (str.m_data), (se), (Unit, BUG(sp, "Field on unit-like struct - " << ty); ), (Tuple, - ASSERT_BUG(sp, e.field_index < se.size(), - "Field index out of range in tuple-struct " << ty << " - " << e.field_index << " > " << se.size()); - const auto& fld = se[e.field_index]; - cb( maybe_monomorph(fld.ent) ); + ASSERT_BUG(sp, field_index < se.size(), + "Field index out of range in tuple-struct " << ty << " - " << field_index << " > " << se.size()); + const auto& fld = se[field_index]; + ty_p = &maybe_monomorph(str.m_params, te.path, fld.ent); ), (Named, - ASSERT_BUG(sp, e.field_index < se.size(), - "Field index out of range in struct " << ty << " - " << e.field_index << " > " << se.size()); - const auto& fld = se[e.field_index].second; - cb( maybe_monomorph(fld.ent) ); + ASSERT_BUG(sp, field_index < se.size(), + "Field index out of range in struct " << ty << " - " << field_index << " > " << se.size()); + const auto& fld = se[field_index].second; + ty_p = &maybe_monomorph(str.m_params, te.path, fld.ent); ) ) } - else if( const auto* tep = te.binding.opt_Union() ) + else if( /*const auto* tep =*/ te.binding.opt_Union() ) { BUG(sp, "Field access on a union isn't valid, use Downcast instead - " << ty); - const auto& unm = **tep; - auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { - if( monomorphise_type_needed(t) ) { - tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, t); - m_resolve.expand_associated_types(sp, tmp); - return tmp; - } - else { - return t; - } - }; - ASSERT_BUG(sp, e.field_index < unm.m_variants.size(), "Field index out of range for union"); - cb( maybe_monomorph(unm.m_variants.at(e.field_index).second.ent) ); } else { @@ -1728,14 +1694,12 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: } ), (Tuple, - ASSERT_BUG(sp, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size()); - cb( te[e.field_index] ); + ASSERT_BUG(sp, field_index < te.size(), "Field index out of range in tuple " << field_index << " >= " << te.size()); + ty_p = &te[field_index]; ) ) - }); - ), - (Deref, - with_val_type(sp, *e.val, [&](const auto& ty){ + } + TU_ARMA(Deref, _e) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Deref on unexpected type - " << ty); @@ -1743,38 +1707,34 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: (Path, if( const auto* inner_ptr = this->is_type_owned_box(ty) ) { - cb( *inner_ptr ); + ty_p = &*inner_ptr; } else { BUG(sp, "Deref on unexpected type - " << ty); } ), (Pointer, - cb(*te.inner); + ty_p = &*te.inner; ), (Borrow, - cb(*te.inner); + ty_p = &*te.inner; ) ) - }); - ), - (Index, - with_val_type(sp, *e.val, [&](const auto& ty){ + } + TU_ARMA(Index, _index_val) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Index on unexpected type - " << ty); ), (Slice, - cb(*te.inner); + ty_p = &*te.inner; ), (Array, - cb(*te.inner); + ty_p = &*te.inner; ) ) - }); - ), - (Downcast, - with_val_type(sp, *e.val, [&](const auto& ty){ + } + TU_ARMA(Downcast, variant_index) { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( BUG(sp, "Downcast on unexpected type - " << ty); @@ -1785,33 +1745,19 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: const auto& enm = **pbe; ASSERT_BUG(sp, enm.m_data.is_Data(), "Downcast on non-data enum"); const auto& variants = enm.m_data.as_Data(); - ASSERT_BUG(sp, e.variant_index < variants.size(), "Variant index out of range"); - const auto& variant = variants[e.variant_index]; + ASSERT_BUG(sp, variant_index < variants.size(), "Variant index out of range"); + const auto& variant = variants[variant_index]; - if( monomorphise_type_needed(variant.type) ) { - auto tmp = monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, variant.type); - m_resolve.expand_associated_types(sp, tmp); - cb(tmp); - } - else { - cb(variant.type); - } + ty_p = &maybe_monomorph(enm.m_params, te.path, variant.type); } else if( const auto* pbe = te.binding.opt_Union() ) { const auto& unm = **pbe; - ASSERT_BUG(sp, e.variant_index < unm.m_variants.size(), "Variant index out of range"); - const auto& variant = unm.m_variants.at(e.variant_index); + ASSERT_BUG(sp, variant_index < unm.m_variants.size(), "Variant index out of range"); + const auto& variant = unm.m_variants.at(variant_index); const auto& fld = variant.second; - if( monomorphise_type_needed(fld.ent) ) { - auto sty = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, fld.ent); - m_resolve.expand_associated_types(sp, sty); - cb(sty); - } - else { - cb(fld.ent); - } + ty_p = &maybe_monomorph(unm.m_params, te.path, fld.ent); } else { @@ -1819,9 +1765,12 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: } ) ) - }); - ) - ) + } + } + assert(ty_p); + } + ASSERT_BUG(sp, !stop_wrapper, "A stop wrapper was passed, but not found"); + cb(*ty_p); } bool MirBuilder::lvalue_is_copy(const Span& sp, const ::MIR::LValue& val) const @@ -1998,165 +1947,177 @@ VarState& MirBuilder::get_slot_state_mut(const Span& sp, unsigned int idx, SlotT } } -const VarState& MirBuilder::get_val_state(const Span& sp, const ::MIR::LValue& lv, unsigned int skip_count) -{ - TODO(sp, ""); -} -VarState& MirBuilder::get_val_state_mut(const Span& sp, const ::MIR::LValue& lv) +VarState* MirBuilder::get_val_state_mut_p(const Span& sp, const ::MIR::LValue& lv) { TRACE_FUNCTION_F(lv); - TU_MATCHA( (lv), (e), + VarState* vs; + TU_MATCHA( (lv.m_root), (e), (Return, BUG(sp, "Move of return value"); - return get_slot_state_mut(sp, ~0u, SlotType::Local); + vs = &get_slot_state_mut(sp, ~0u, SlotType::Local); ), (Argument, - return get_slot_state_mut(sp, e.idx, SlotType::Argument); + vs = &get_slot_state_mut(sp, e, SlotType::Argument); ), (Local, - return get_slot_state_mut(sp, e, SlotType::Local); + vs = &get_slot_state_mut(sp, e, SlotType::Local); ), (Static, - BUG(sp, "Attempting to mutate state of a static"); - ), - (Field, - auto& ivs = get_val_state_mut(sp, *e.val); - VarState tpl; - TU_MATCHA( (ivs), (ivse), - (Invalid, - //BUG(sp, "Mutating inner state of an invalidated composite - " << lv); - tpl = VarState::make_Valid({}); - ), - (MovedOut, - BUG(sp, "Field on value with MovedOut state - " << lv); - ), - (Partial, - ), - (Optional, - tpl = ivs.clone(); - ), - (Valid, - tpl = VarState::make_Valid({}); - ) + return nullptr; + //BUG(sp, "Attempting to mutate state of a static"); ) - if( !ivs.is_Partial() ) - { - size_t n_flds = 0; - with_val_type(sp, *e.val, [&](const auto& ty) { - DEBUG("ty = " << ty); - if(const auto* e = ty.m_data.opt_Path()) { - ASSERT_BUG(sp, e->binding.is_Struct(), ""); - const auto& str = *e->binding.as_Struct(); - TU_MATCHA( (str.m_data), (se), - (Unit, - BUG(sp, "Field access of unit-like struct"); - ), - (Tuple, - n_flds = se.size(); - ), - (Named, - n_flds = se.size(); - ) - ) - } - else if(const auto* e = ty.m_data.opt_Tuple()) { - n_flds = e->size(); - } - else if(const auto* e = ty.m_data.opt_Array()) { - n_flds = e->size_val; - } - else { - TODO(sp, "Determine field count for " << ty); - } - }); - ::std::vector inner_vs; inner_vs.reserve(n_flds); - for(size_t i = 0; i < n_flds; i++) - inner_vs.push_back( tpl.clone() ); - ivs = VarState::make_Partial({ mv$(inner_vs) }); - } - return ivs.as_Partial().inner_states.at(e.field_index); - ), - (Deref, - // HACK: If the dereferenced type is a Box ("owned_box") then hack in move and shallow drop - bool is_box = false; - if( this->m_lang_Box ) - { - with_val_type(sp, *e.val, [&](const auto& ty){ - DEBUG("ty = " << ty); - is_box = this->is_type_owned_box(ty); - }); - } - + ) - if( is_box ) - { - auto& ivs = get_val_state_mut(sp, *e.val); - if( ! ivs.is_MovedOut() ) + for(const auto& w : lv.m_wrappers) + { + auto& ivs = *vs; + vs = nullptr; + TU_MATCH_HDRA( (w), { ) + TU_ARMA(Field, field_index) { + VarState tpl; + TU_MATCHA( (ivs), (ivse), + (Invalid, + //BUG(sp, "Mutating inner state of an invalidated composite - " << lv); + tpl = VarState::make_Valid({}); + ), + (MovedOut, + BUG(sp, "Field on value with MovedOut state - " << lv); + ), + (Partial, + ), + (Optional, + tpl = ivs.clone(); + ), + (Valid, + tpl = VarState::make_Valid({}); + ) + ) + if( !ivs.is_Partial() ) { - ::std::vector inner; - inner.push_back(VarState::make_Valid({})); - unsigned int drop_flag = (ivs.is_Optional() ? ivs.as_Optional() : ~0u); - ivs = VarState::make_MovedOut({ box$(VarState::make_Valid({})), drop_flag }); + size_t n_flds = 0; + with_val_type(sp, lv, [&](const auto& ty) { + DEBUG("ty = " << ty); + if(const auto* e = ty.m_data.opt_Path()) { + ASSERT_BUG(sp, e->binding.is_Struct(), ""); + const auto& str = *e->binding.as_Struct(); + TU_MATCHA( (str.m_data), (se), + (Unit, + BUG(sp, "Field access of unit-like struct"); + ), + (Tuple, + n_flds = se.size(); + ), + (Named, + n_flds = se.size(); + ) + ) + } + else if(const auto* e = ty.m_data.opt_Tuple()) { + n_flds = e->size(); + } + else if(const auto* e = ty.m_data.opt_Array()) { + n_flds = e->size_val; + } + else { + TODO(sp, "Determine field count for " << ty); + } + }, &w); + ::std::vector inner_vs; inner_vs.reserve(n_flds); + for(size_t i = 0; i < n_flds; i++) + inner_vs.push_back( tpl.clone() ); + ivs = VarState::make_Partial({ mv$(inner_vs) }); + } + vs = &ivs.as_Partial().inner_states.at(field_index); + } + TU_ARMA(Deref, _e) { + // HACK: If the dereferenced type is a Box ("owned_box") then hack in move and shallow drop + bool is_box = false; + if( this->m_lang_Box ) + { + with_val_type(sp, lv, [&](const auto& ty){ + DEBUG("ty = " << ty); + is_box = this->is_type_owned_box(ty); + }, &w); } - return *ivs.as_MovedOut().inner_state; - } - else - { - BUG(sp, "Move out of deref with non-Copy values - &move? - " << lv << " : " << FMT_CB(ss, this->with_val_type(sp, lv, [&](const auto& ty){ss<