diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-07-16 13:27:31 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-07-16 13:27:31 +0800 |
commit | 97567dbbd8c3f8719dbb9e32c6d0f3a155246508 (patch) | |
tree | 3268a7f2bcadd013199883b7bbc2f26b9c385643 | |
parent | 9d1a660045de5a3cc37315c78a3a75999fef9b9a (diff) | |
download | mrust-97567dbbd8c3f8719dbb9e32c6d0f3a155246508.tar.gz |
All - Upgrade to rustc 1.19.0 beta (2017-07-08)
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | rust-nightly-date | 2 | ||||
-rw-r--r-- | src/expand/mod.cpp | 102 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 88 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 47 | ||||
-rw-r--r-- | src/hir_conv/expand_type.cpp | 16 | ||||
-rw-r--r-- | src/hir_conv/resolve_ufcs.cpp | 31 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 38 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 21 | ||||
-rw-r--r-- | src/hir_typeck/static.cpp | 102 | ||||
-rw-r--r-- | src/hir_typeck/static.hpp | 5 | ||||
-rw-r--r-- | src/main.cpp | 9 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 10 | ||||
-rw-r--r-- | src/parse/root.cpp | 9 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 2 | ||||
-rw-r--r-- | src/resolve/use.cpp | 1 | ||||
-rw-r--r-- | src/trans/allocator.cpp | 30 | ||||
-rw-r--r-- | src/trans/allocator.hpp | 32 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 145 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 5 |
20 files changed, 612 insertions, 87 deletions
@@ -50,6 +50,8 @@ RUST_FLAGS := --cfg debug_assertions RUST_FLAGS += -g RUST_FLAGS += -O RUST_FLAGS += $(RUST_FLAGS_EXTRA) +# > TODO: This is needed for anything that uses libstd. build.rs adds it with cargo magic, no idea how it gets to the rlib +RUST_FLAGS += -lbacktrace SHELL = bash @@ -113,7 +115,7 @@ OBJ += hir/serialise.o hir/deserialise.o hir/serialise_lowlevel.o OBJ += trans/trans_list.o trans/mangling.o OBJ += trans/enumerate.o trans/monomorphise.o trans/codegen.o OBJ += trans/codegen_c.o trans/codegen_c_structured.o -OBJ += trans/target.o +OBJ += trans/target.o trans/allocator.o PCHS := ast/ast.hpp diff --git a/rust-nightly-date b/rust-nightly-date index 766c55d4..700cfb0a 100644 --- a/rust-nightly-date +++ b/rust-nightly-date @@ -1 +1 @@ -2017-01-05 +2017-07-08 diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 5c3be722..629020a7 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -272,6 +272,44 @@ void Expand_Type(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST: ) ) } +void Expand_Path(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Module& mod, ::AST::Path& p) +{ + auto expand_nodes = [&](::std::vector<::AST::PathNode>& nodes) { + for(auto& node : nodes) + { + for(auto& typ : node.args().m_types) + Expand_Type(crate, modstack, mod, typ); + for(auto& aty : node.args().m_assoc) + Expand_Type(crate, modstack, mod, aty.second); + } + }; + + TU_MATCHA( (p.m_class), (pe), + (Invalid, + ), + (Local, + ), + (Relative, + expand_nodes(pe.nodes); + ), + (Self, + expand_nodes(pe.nodes); + ), + (Super, + expand_nodes(pe.nodes); + ), + (Absolute, + expand_nodes(pe.nodes); + ), + (UFCS, + Expand_Type(crate, modstack, mod, *pe.type); + if( pe.trait ) { + Expand_Path(crate, modstack, mod, *pe.trait); + } + expand_nodes(pe.nodes); + ) + ) +} struct CExpandExpr: public ::AST::NodeVisitor @@ -494,9 +532,11 @@ struct CExpandExpr: this->visit_nodelete(node, node.m_value); } void visit(::AST::ExprNode_CallPath& node) override { + Expand_Path(crate, modstack, this->cur_mod(), node.m_path); this->visit_vector(node.m_args); } void visit(::AST::ExprNode_CallMethod& node) override { + // TODO: Path params. this->visit_nodelete(node, node.m_val); this->visit_vector(node.m_args); } @@ -627,7 +667,9 @@ struct CExpandExpr: void visit(::AST::ExprNode_Tuple& node) override { this->visit_vector(node.m_values); } - void visit(::AST::ExprNode_NamedValue& node) override { } + void visit(::AST::ExprNode_NamedValue& node) override { + Expand_Path(crate, modstack, this->cur_mod(), node.m_path); + } void visit(::AST::ExprNode_Field& node) override { this->visit_nodelete(node, node.m_obj); } @@ -649,6 +691,64 @@ struct CExpandExpr: void visit(::AST::ExprNode_BinOp& node) override { this->visit_nodelete(node, node.m_left); this->visit_nodelete(node, node.m_right); + + switch(node.m_type) + { + case ::AST::ExprNode_BinOp::RANGE: { + // NOTE: Not language items + auto core_crate = (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core"); + auto path_Range = ::AST::Path(core_crate, {::AST::PathNode("ops"), ::AST::PathNode("Range") }); + auto path_RangeFrom = ::AST::Path(core_crate, {::AST::PathNode("ops"), ::AST::PathNode("RangeFrom") }); + auto path_RangeTo = ::AST::Path(core_crate, {::AST::PathNode("ops"), ::AST::PathNode("RangeTo") }); + auto path_RangeFull = ::AST::Path(core_crate, {::AST::PathNode("ops"), ::AST::PathNode("RangeFull") }); + + ::AST::ExprNode_StructLiteral::t_values values; + if( node.m_left && node.m_right ) + { + values.push_back( ::std::make_pair( ::std::string("start"), mv$(node.m_left ) ) ); + values.push_back( ::std::make_pair( ::std::string("end") , mv$(node.m_right) ) ); + replacement.reset( new ::AST::ExprNode_StructLiteral(mv$(path_Range), nullptr, mv$(values)) ); + } + else if( node.m_left ) + { + values.push_back( ::std::make_pair( ::std::string("start"), mv$(node.m_left ) ) ); + replacement.reset( new ::AST::ExprNode_StructLiteral(mv$(path_RangeFrom), nullptr, mv$(values)) ); + } + else if( node.m_right ) + { + values.push_back( ::std::make_pair( ::std::string("end") , mv$(node.m_right) ) ); + replacement.reset( new ::AST::ExprNode_StructLiteral(mv$(path_RangeTo), nullptr, mv$(values)) ); + } + else + { + replacement.reset( new ::AST::ExprNode_StructLiteral(mv$(path_RangeFull), nullptr, mv$(values)) ); + } + replacement->set_span( node.span() ); + break; } + case ::AST::ExprNode_BinOp::RANGE_INC: { + // NOTE: Not language items + auto core_crate = (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core"); + auto path_RangeInclusive_NonEmpty = ::AST::Path(core_crate, { ::AST::PathNode("ops"), ::AST::PathNode("RangeInclusive") }); + auto path_RangeToInclusive = ::AST::Path(core_crate, { ::AST::PathNode("ops"), ::AST::PathNode("RangeToInclusive") }); + + if( node.m_left ) + { + ::AST::ExprNode_StructLiteral::t_values values; + values.push_back( ::std::make_pair( ::std::string("start"), mv$(node.m_left) ) ); + values.push_back( ::std::make_pair( ::std::string("end") , mv$(node.m_right) ) ); + replacement.reset( new ::AST::ExprNode_StructLiteral(mv$(path_RangeInclusive_NonEmpty), nullptr, mv$(values)) ); + } + else + { + ::AST::ExprNode_StructLiteral::t_values values; + values.push_back( ::std::make_pair( ::std::string("end") , mv$(node.m_right) ) ); + replacement.reset( new ::AST::ExprNode_StructLiteral(mv$(path_RangeToInclusive), nullptr, mv$(values)) ); + } + replacement->set_span( node.span() ); + break; } + default: + break; + } } void visit(::AST::ExprNode_UniOp& node) override { this->visit_nodelete(node, node.m_value); diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index e0429aca..96cd4725 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -894,7 +894,10 @@ namespace { if( const auto* attr_repr = attrs.get("repr") ) { - const auto& repr_str = attr_repr->string(); + ASSERT_BUG(Span(), attr_repr->has_sub_items(), "#[repr] attribute malformed, " << *attr_repr); + ASSERT_BUG(Span(), attr_repr->items().size() == 1, "#[repr] attribute malformed, " << *attr_repr); + ASSERT_BUG(Span(), attr_repr->items()[0].has_noarg(), "#[repr] attribute malformed, " << *attr_repr); + const auto& repr_str = attr_repr->items()[0].name(); if( repr_str == "C" ) { repr = ::HIR::Union::Repr::C; } @@ -1607,6 +1610,89 @@ public: // Set all pointers in the HIR to the correct (now fixed) locations IndexVisitor(rv).visit_crate( rv ); + // TODO: If the current crate is libcore, store the paths to various non-lang ops items + if( crate.m_crate_name == "core" ) + { + struct H { + static ::HIR::SimplePath resolve_path(const ::HIR::Crate& crate, bool is_value, ::std::initializer_list<const char*> n) + { + ::HIR::SimplePath cur_path("", {}); + + const ::HIR::Module* mod = &crate.m_root_module; + assert(n.begin() != n.end()); + for(auto it = n.begin(); it != n.end()-1; ++it) + { + auto it2 = mod->m_mod_items.find(*it); + if( it2 == mod->m_mod_items.end() ) + return ::HIR::SimplePath(); + const auto& e = it2->second; + if(const auto* ip = e->ent.opt_Import()) + { + // TODO: Handle module aliases? + (void)ip; + return ::HIR::SimplePath(); + } + else if(const auto* ep = e->ent.opt_Module() ) + { + cur_path.m_components.push_back(*it); + mod = ep; + } + else + { + // Incorrect item type + return ::HIR::SimplePath(); + } + } + + auto last = *(n.end()-1); + if( is_value ) + { + throw ""; + } + else + { + auto it2 = mod->m_mod_items.find(last); + if( it2 == mod->m_mod_items.end() ) + return ::HIR::SimplePath(); + + // Found: Either return the current path, or return this alias. + if(const auto* ip = it2->second->ent.opt_Import()) + { + if(ip->is_variant) + return ::HIR::SimplePath(); + return ip->path; + } + else + { + cur_path.m_components.push_back(last); + return cur_path; + } + } + } + }; + // TODO: Check for existing defintions of lang items + if( rv.m_lang_items.count("boxed_trait") == 0 ) + { + rv.m_lang_items.insert(::std::make_pair( ::std::string("boxed_trait"), H::resolve_path(rv, false, {"ops", "Boxed"}) )); + } + if( rv.m_lang_items.count("placer_trait") == 0 ) + { + rv.m_lang_items.insert(::std::make_pair( ::std::string("placer_trait"), H::resolve_path(rv, false, {"ops", "Placer"}) )); + } + if( rv.m_lang_items.count("place_trait") == 0 ) + { + rv.m_lang_items.insert(::std::make_pair( ::std::string("place_trait"), H::resolve_path(rv, false, {"ops", "Place"}) )); + } + if( rv.m_lang_items.count("box_place_trait") == 0 ) + { + rv.m_lang_items.insert(::std::make_pair( ::std::string("box_place_trait"), H::resolve_path(rv, false, {"ops", "BoxPlace"}) )); + } + if( rv.m_lang_items.count("in_place_trait") == 0 ) + { + rv.m_lang_items.insert(::std::make_pair( ::std::string("in_place_trait"), H::resolve_path(rv, false, {"ops", "InPlace"}) )); + } + } + g_crate_ptr = nullptr; return ::HIR::CratePtr( mv$(rv) ); } diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 296bdce1..4a82867f 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -118,53 +118,10 @@ struct LowerHIR_ExprNode_Visitor: switch(v.m_type) { case ::AST::ExprNode_BinOp::RANGE: { - // NOTE: Not language items - auto path_Range = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "Range"}) ); - auto path_RangeFrom = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeFrom"}) ); - auto path_RangeTo = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeTo"}) ); - auto path_RangeFull = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeFull"}) ); - - ::HIR::ExprNode_StructLiteral::t_values values; - if( v.m_left ) - values.push_back( ::std::make_pair( ::std::string("start"), LowerHIR_ExprNode_Inner( *v.m_left ) ) ); - if( v.m_right ) - values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) ); - - if( v.m_left ) { - if( v.m_right ) { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_Range), true, nullptr, mv$(values)) ); - } - else { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeFrom), true, nullptr, mv$(values)) ); - } - } - else { - if( v.m_right ) { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeTo), true, nullptr, mv$(values)) ); - } - else { - m_rv.reset( new ::HIR::ExprNode_UnitVariant(v.span(), mv$(path_RangeFull), true) ); - } - } + BUG(v.span(), "Unexpected RANGE binop"); break; } case ::AST::ExprNode_BinOp::RANGE_INC: { - // NOTE: Not language items - auto path_RangeInclusive_NonEmpty = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeInclusive", "NonEmpty"}) ); - auto path_RangeToInclusive = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeToInclusive"}) ); - - if( v.m_left ) - { - ::HIR::ExprNode_StructLiteral::t_values values; - values.push_back( ::std::make_pair( ::std::string("start"), LowerHIR_ExprNode_Inner( *v.m_left ) ) ); - values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) ); - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeInclusive_NonEmpty), false, nullptr, mv$(values)) ); - } - else - { - ::HIR::ExprNode_StructLiteral::t_values values; - values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) ); - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeToInclusive), true, nullptr, mv$(values)) ); - } + BUG(v.span(), "Unexpected RANGE_INC binop"); break; } case ::AST::ExprNode_BinOp::PLACE_IN: TODO(v.span(), "Desugar placement syntax"); diff --git a/src/hir_conv/expand_type.cpp b/src/hir_conv/expand_type.cpp index 511a35b0..44102f18 100644 --- a/src/hir_conv/expand_type.cpp +++ b/src/hir_conv/expand_type.cpp @@ -296,7 +296,23 @@ public: } void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override { + static Span sp; m_impl_type = &impl.m_type; + + // HACK: Expand defaults for parameters in trait names here. + { + const auto& trait = m_crate.get_trait_by_path(sp, trait_path); + auto monomorph_cb = monomorphise_type_get_cb(sp, &impl.m_type, &impl.m_trait_args, nullptr); + + while( impl.m_trait_args.m_types.size() < trait.m_params.m_types.size() ) + { + const auto& def = trait.m_params.m_types[ impl.m_trait_args.m_types.size() ]; + auto ty = monomorphise_type_with(sp, def.m_default, monomorph_cb); + DEBUG("Add default trait arg " << ty << " from " << def.m_default); + impl.m_trait_args.m_types.push_back( mv$(ty) ); + } + } + ::HIR::Visitor::visit_trait_impl(trait_path, impl); m_impl_type = nullptr; } diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index d397d78c..587c54dd 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -73,7 +73,7 @@ namespace { void visit_trait(::HIR::ItemPath p, ::HIR::Trait& trait) override { m_current_trait = &trait; m_current_trait_path = &p; - //auto _ = m_resolve.set_item_generics(trait.m_params); + //auto _ = m_resolve.set_cur_trait(p, trait); auto _ = m_resolve.set_impl_generics(trait.m_params); ::HIR::Visitor::visit_trait(p, trait); m_current_trait = nullptr; @@ -464,10 +464,39 @@ namespace { return false; } + void visit_type(::HIR::TypeRef& ty) override + { + // TODO: Add a span parameter. + static Span sp; + + ::HIR::Visitor::visit_type(ty); + + unsigned counter = 0; + while( m_resolve.expand_associated_types_single(sp, ty) ) + { + ASSERT_BUG(sp, counter++ < 20, "Sanity limit exceeded when resolving UFCS in type " << ty); + // Invoke a special version of EAT that only processes a single item. + // - Keep recursing while this does replacements + ::HIR::Visitor::visit_type(ty); + } + } + void visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc) override { static Span sp; + if(auto* pe = p.m_data.opt_UfcsKnown()) + { + // If the trait has missing type argumenst, replace them with the defaults + auto& tp = pe->trait; + const auto& trait = m_resolve.m_crate.get_trait_by_path(sp, tp.m_path); + + if(tp.m_params.m_types.size() < trait.m_params.m_types.size()) + { + //TODO(sp, "Defaults in UfcsKnown - " << p); + } + } + TU_IFLET(::HIR::Path::Data, p.m_data, UfcsUnknown, e, TRACE_FUNCTION_FR("UfcsUnknown - p=" << p, p); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index de7f05ec..66c07e6d 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -2306,11 +2306,11 @@ namespace { BUG(sp, "Encountered Noop _Emplace in typecheck"); case ::HIR::ExprNode_Emplace::Type::Boxer: //this->context.equate_types_assoc(sp, {}, ::HIR::SimplePath("core", { "ops", "Boxer" }), ::make_vec1(data_ty.clone()), *inner_ty, ""); - this->context.equate_types_assoc(sp, data_ty, ::HIR::SimplePath("core", { "ops", "Boxed" }), {}, *inner_ty, "Data"); + this->context.equate_types_assoc(sp, data_ty, this->context.m_crate.get_lang_item_path(sp, "boxed_trait"), {}, *inner_ty, "Data"); break; case ::HIR::ExprNode_Emplace::Type::Placer: // TODO: Search for `Placer<T>`, not `Placer` - this->context.equate_types_assoc(sp, {}, ::HIR::SimplePath("core", { "ops", "Placer" }), ::make_vec1(data_ty.clone()), *inner_ty, ""); + this->context.equate_types_assoc(sp, {}, this->context.m_crate.get_lang_item_path(sp, "placer_trait"), ::make_vec1(data_ty.clone()), *inner_ty, ""); break; } @@ -3908,6 +3908,24 @@ void Context::equate_types_shadow(const Span& sp, const ::HIR::TypeRef& l, bool } void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::HIR::PathParams pp, const ::HIR::TypeRef& impl_ty, const char *name, bool is_op) { + for(const auto& a : this->link_assoc) + { + if( a.left_ty != l ) + continue ; + if( a.trait != trait ) + continue ; + if( a.params != pp ) + continue ; + if( a.impl_ty != impl_ty ) + continue ; + if( a.name != name ) + continue ; + if( a.is_operator != is_op ) + continue ; + + DEBUG("(DUPLICATE " << a << ")"); + return ; + } this->link_assoc.push_back(Associated { sp, l.clone(), @@ -5113,6 +5131,18 @@ namespace { if( found ) { // Fully-known impl if( v.name != "" ) { + // Stop this from just pushing the same rule again. + if( output_type.m_data.is_Path() && output_type.m_data.as_Path().path.m_data.is_UfcsKnown() ) + { + const auto& te = output_type.m_data.as_Path(); + const auto& pe = te.path.m_data.as_UfcsKnown(); + // If the target type is unbound, and is this rule exactly, don't return success + if( te.binding.is_Unbound() && *pe.type == v.impl_ty && pe.item == v.name && pe.trait.m_path == v.trait && pe.trait.m_params == v.params) + { + DEBUG("Would re-create the same rule, returning unconsumed"); + return false; + } + } context.equate_types(sp, v.left_ty, output_type); } return true; @@ -5883,6 +5913,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: } // 3. Check associated type rules DEBUG("--- Associated types"); + unsigned int link_assoc_iter_limit = context.link_assoc.size() * 4; for(unsigned int i = 0; i < context.link_assoc.size(); ) { // - Move out (and back in later) to avoid holding a bad pointer if the list is updated auto rule = mv$(context.link_assoc[i]); @@ -5900,6 +5931,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: DEBUG("- Consumed associated type rule " << i << "/" << context.link_assoc.size() << " - " << rule); if( i != context.link_assoc.size()-1 ) { + //assert( context.link_assoc[i] != context.link_assoc.back() ); context.link_assoc[i] = mv$( context.link_assoc.back() ); } context.link_assoc.pop_back(); @@ -5908,6 +5940,8 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: context.link_assoc[i] = mv$(rule); i ++; } + + ASSERT_BUG(Span(), link_assoc_iter_limit -- > 0, "link_assoc iteration limit exceeded"); } // 4. Revisit nodes that require revisiting DEBUG("--- Node revisits"); diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index c860c6ce..504ff454 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1933,7 +1933,6 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, // - Does simplification of complex associated types const auto& trait_ptr = this->m_crate.get_trait_by_path(sp, pe_inner.trait.m_path); const auto& assoc_ty = trait_ptr.m_types.at(pe_inner.item); - DEBUG("TODO: Search bounds on associated type - " << assoc_ty.m_trait_bounds); // Resolve where Self=pe_inner.type (i.e. for the trait this inner UFCS is on) auto cb_placeholders_trait = [&](const auto& ty)->const ::HIR::TypeRef&{ @@ -1952,7 +1951,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, for(const auto& bound : assoc_ty.m_trait_bounds) { // If the bound is for Self and the outer trait - // - TODO: Parameters? + // - TODO: Fuzzy check the parameters? if( bound.m_path == pe.trait ) { auto it = bound.m_type_bounds.find( pe.item ); if( it != bound.m_type_bounds.end() ) { @@ -1967,6 +1966,24 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, return ; } } + + // TODO: Find trait in this trait. + const auto& bound_trait = m_crate.get_trait_by_path(sp, bound.m_path.m_path); + bool replaced = this->find_named_trait_in_trait(sp, + pe.trait.m_path,pe.trait.m_params, + bound_trait, bound.m_path.m_path,bound.m_path.m_params, *pe.type, + [&](const auto&, const auto& x, const auto& assoc){ + auto it = assoc.find(pe.item); + if( it != assoc.end() ) { + input = it->second.clone(); + return true; + } + return false; + } + ); + if( replaced ) { + return ; + } } DEBUG("pe = " << *pe.type << ", input = " << input); ) diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 1d613d96..09f2e6c6 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -855,6 +855,18 @@ void StaticTraitResolve::expand_associated_types(const Span& sp, ::HIR::TypeRef& TRACE_FUNCTION_F(input); this->expand_associated_types_inner(sp, input); } +bool StaticTraitResolve::expand_associated_types_single(const Span& sp, ::HIR::TypeRef& input) const +{ + TRACE_FUNCTION_F(input); + if( input.m_data.is_Path() && input.m_data.as_Path().path.m_data.is_UfcsKnown() ) + { + return expand_associated_types__UfcsKnown(sp, input, /*recurse=*/false); + } + else + { + return false; + } +} void StaticTraitResolve::expand_associated_types_inner(const Span& sp, ::HIR::TypeRef& input) const { TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e), @@ -889,7 +901,7 @@ void StaticTraitResolve::expand_associated_types_inner(const Span& sp, ::HIR::Ty return; ), (UfcsUnknown, - BUG(sp, "Encountered UfcsUnknown"); + BUG(sp, "Encountered UfcsUnknown in EAT - " << e.path); ) ) ), @@ -929,7 +941,7 @@ void StaticTraitResolve::expand_associated_types_inner(const Span& sp, ::HIR::Ty ) ) } -void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HIR::TypeRef& input) const +bool StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HIR::TypeRef& input, bool recurse/*=true*/) const { auto& e = input.m_data.as_Path(); auto& e2 = e.path.m_data.as_UfcsKnown(); @@ -950,7 +962,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI if( e2.trait.m_path == trait_fn || e2.trait.m_path == trait_fn_mut || e2.trait.m_path == trait_fn_once ) { if( e2.item == "Output" ) { input = te.m_rettype->clone(); - return ; + return true; } else { ERROR(sp, E0000, "No associated type " << e2.item << " for trait " << e2.trait); @@ -977,7 +989,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI } input = it->second.clone(); - return ; + return true; } } ) @@ -1061,10 +1073,16 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI input.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); DEBUG("Assuming that " << input << " is an opaque name"); - this->replace_equalities(input); + bool rv = this->replace_equalities(input); + if( recurse ) + this->expand_associated_types_inner(sp, input); + return rv; + } + else { + if( recurse ) + this->expand_associated_types_inner(sp, input); + return true; } - this->expand_associated_types_inner(sp, input); - return; } // If the type of this UfcsKnown is ALSO a UfcsKnown - Check if it's bounded by this trait with equality @@ -1103,10 +1121,29 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI else { input = it->second.clone(); } - this->expand_associated_types(sp, input); - return ; + if( recurse ) + this->expand_associated_types(sp, input); + return true; } } + + // Find trait in this trait. + const auto& bound_trait = m_crate.get_trait_by_path(sp, bound.m_path.m_path); + bool replaced = this->find_named_trait_in_trait(sp, + e2.trait.m_path, e2.trait.m_params, + bound_trait, bound.m_path.m_path,bound.m_path.m_params, *e2.type, + [&](const auto& params, const auto& assoc){ + auto it = assoc.find(e2.item); + if( it != assoc.end() ) { + input = it->second.clone(); + return true; + } + return false; + } + ); + if( replaced ) { + return true; + } } DEBUG("e2 = " << *e2.type << ", input = " << input); ) @@ -1120,6 +1157,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI BUG(sp, "Cannot find associated type " << e2.item << " anywhere in trait " << e2.trait); //e2.trait = mv$(trait_path); + bool replacement_happened = true; ::ImplRef best_impl; rv = this->find_impl(sp, trait_path.m_path, trait_path.m_params, *e2.type, [&](auto impl, bool fuzzy) { DEBUG("[expand_associated_types] Found " << impl); @@ -1157,30 +1195,32 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI if( nt == ::HIR::TypeRef() ) { DEBUG("Mark " << e.path << " as opaque"); e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); - this->replace_equalities(input); + replacement_happened = this->replace_equalities(input); } else { DEBUG("Converted UfcsKnown - " << e.path << " = " << nt); input = mv$(nt); + replacement_happened = true; } return true; } }); if( rv ) { - this->expand_associated_types(sp, input); - return; + if( recurse ) + this->expand_associated_types(sp, input); + return replacement_happened; } if( best_impl.is_valid() ) { e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); this->replace_equalities(input); DEBUG("- Couldn't find a non-specialised impl of " << trait_path << " for " << *e2.type << " - treating as opaque"); - return ; + return false; } ERROR(sp, E0000, "Cannot find an implementation of " << trait_path << " for " << *e2.type); } -void StaticTraitResolve::replace_equalities(::HIR::TypeRef& input) const +bool StaticTraitResolve::replace_equalities(::HIR::TypeRef& input) const { TRACE_FUNCTION_F("input="<<input); DEBUG("m_type_equalities = {" << m_type_equalities << "}"); @@ -1189,6 +1229,10 @@ void StaticTraitResolve::replace_equalities(::HIR::TypeRef& input) const if( a != m_type_equalities.end() ) { input = a->second.clone(); DEBUG("- Replace with " << input); + return true; + } + else { + return false; } } @@ -1422,10 +1466,34 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) } ), (Path, - auto pp = ::HIR::PathParams(); - // TODO: Destructure? + TU_MATCHA( (e.binding), (pbe), + (Unbound, + ), + (Opaque, + //auto pp = ::HIR::PathParams(); + //return this->find_impl(sp, m_lang_Sized, &pp, ty, [&](auto , bool){ return true; }, true); + // TODO: This can only be with UfcsKnown, so check if the trait specifies ?Sized + return true; + ), + (Struct, + // TODO: Destructure? + switch( pbe->m_markings.dst_type ) + { + case ::HIR::TraitMarkings::DstType::None: + return true; + case ::HIR::TraitMarkings::DstType::Possible: + return type_is_sized( sp, e.path.m_data.as_Generic().m_params.m_types.at(pbe->m_markings.unsized_param) ); + case ::HIR::TraitMarkings::DstType::Slice: + case ::HIR::TraitMarkings::DstType::TraitObject: + return false; + } + ), + (Enum, + ), + (Union, + ) + ) return true; - //return this->find_impl(sp, m_lang_Sized, &pp, ty, [&](auto , bool){ return true; }, true); ), (Diverge, // The ! type is kinda Copy ... diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index 4c094218..82ede197 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -149,11 +149,12 @@ private: public: void expand_associated_types(const Span& sp, ::HIR::TypeRef& input) const; + bool expand_associated_types_single(const Span& sp, ::HIR::TypeRef& input) const; private: void expand_associated_types_inner(const Span& sp, ::HIR::TypeRef& input) const; - void expand_associated_types__UfcsKnown(const Span& sp, ::HIR::TypeRef& input) const; - void replace_equalities(::HIR::TypeRef& input) const; + bool expand_associated_types__UfcsKnown(const Span& sp, ::HIR::TypeRef& input, bool recurse=true) const; + bool replace_equalities(::HIR::TypeRef& input) const; public: /// \} diff --git a/src/main.cpp b/src/main.cpp index 0435a90b..7b1d94be 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -359,6 +359,7 @@ int main(int argc, char *argv[]) crate = ::AST::Crate(); // Replace type aliases (`type`) into the actual type + // - Also inserts defaults in trait impls CompilePhaseV("Resolve Type Aliases", [&]() { ConvertHIR_ExpandAliases(*hir_crate); }); @@ -366,12 +367,14 @@ int main(int argc, char *argv[]) CompilePhaseV("Resolve Bind", [&]() { ConvertHIR_Bind(*hir_crate); }); - CompilePhaseV("Resolve UFCS paths", [&]() { - ConvertHIR_ResolveUFCS(*hir_crate); - }); + // Enumerate marker impls on types and other useful metadata CompilePhaseV("Resolve HIR Markings", [&]() { ConvertHIR_Markings(*hir_crate); }); + // Determine what trait to use for <T>::Foo (and does some associated type expansion) + CompilePhaseV("Resolve UFCS paths", [&]() { + ConvertHIR_ResolveUFCS(*hir_crate); + }); // Basic constant evalulation (intergers/floats only) CompilePhaseV("Constant Evaluate", [&]() { ConvertHIR_ConstantEvaluate(*hir_crate); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 786c2243..5604d154 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -1505,11 +1505,11 @@ namespace { if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) { return node.m_value->visit(*this); } - //auto path_Placer = ::HIR::SimplePath("core", {"ops", "Placer"}); - auto path_BoxPlace = ::HIR::SimplePath("core", {"ops", "BoxPlace"}); - auto path_Place = ::HIR::SimplePath("core", {"ops", "Place"}); - auto path_Boxed = ::HIR::SimplePath("core", {"ops", "Boxed"}); - //auto path_InPlace = ::HIR::SimplePath("core", {"ops", "InPlace"}); + //const auto& path_Placer = m_builder.crate().get_lang_item_path(node.span(), "placer_trait"); + const auto& path_Boxed = m_builder.crate().get_lang_item_path(node.span(), "boxed_trait"); + const auto& path_Place = m_builder.crate().get_lang_item_path(node.span(), "place_trait"); + const auto& path_BoxPlace = m_builder.crate().get_lang_item_path(node.span(), "box_place_trait"); + //const auto& path_InPlace = m_builder.crate().get_lang_item_path(node.span(), "in_place_trait"); const auto& data_ty = node.m_value->m_res_type; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 9c045880..cdb36345 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -140,6 +140,12 @@ void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_ do { + // If an item terminator is seen (end of item, start of body, list separator), return early. + //if( LOOK_AHEAD(lex) == TOK_SEMICOLON || LOOK_AHEAD(lex) == TOK_COMMA ) + //{ + // return; + //} + ::std::vector< ::std::string> hrls; if(GET_TOK(tok, lex) == TOK_LIFETIME) { ret.add_bound(AST::GenericBound::make_TypeLifetime( { @@ -625,6 +631,9 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) // TODO: Need a better way of indiciating 'static than just an invalid path supertraits.push_back( make_spanned( Span(tok.get_pos()), AST::Path() ) ); } + else if( tok.type() == TOK_BRACE_OPEN ) { + break; + } else { PUTBACK(tok, lex); supertraits.push_back( GET_SPANNED(::AST::Path, lex, Parse_Path(lex, PATH_GENERIC_TYPE)) ); diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index bbce7056..45b371c9 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -1449,7 +1449,7 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type) // ! type ), (Macro, - BUG(sp, "Resolve_Absolute_Type - Encountered an unexpanded macro"); + BUG(sp, "Resolve_Absolute_Type - Encountered an unexpanded macro in type - " << type); ), (Primitive, ), diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp index 475cec1d..5e1fce6d 100644 --- a/src/resolve/use.cpp +++ b/src/resolve/use.cpp @@ -135,6 +135,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path allow = Lookup::Value; break; case ::AST::PathBinding::TAG_Struct: + case ::AST::PathBinding::TAG_Union: allow = Lookup::Value; break; case ::AST::PathBinding::TAG_EnumVar: diff --git a/src/trans/allocator.cpp b/src/trans/allocator.cpp new file mode 100644 index 00000000..ce4b3340 --- /dev/null +++ b/src/trans/allocator.cpp @@ -0,0 +1,30 @@ + + +#include "allocator.hpp" + +#define DEF_METHOD_ARGS(name, ...) const AllocatorDataTy ALLOCATOR_METHODS_ARGS_##name[] = { __VA_ARGS__ }; +#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(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] = { + 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) + }; diff --git a/src/trans/allocator.hpp b/src/trans/allocator.hpp new file mode 100644 index 00000000..67d56c11 --- /dev/null +++ b/src/trans/allocator.hpp @@ -0,0 +1,32 @@ +/* + */ +#include <cstddef> + +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 +}; +struct AllocatorMethod { + const char* name; + AllocatorDataTy ret; + size_t n_args; + const AllocatorDataTy* args; // Terminated by Never +}; +enum class AllocatorKind { + Global, + DefaultLib, + DefaultExe, +}; + +extern const AllocatorMethod ALLOCATOR_METHODS[10]; + diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index cb761a66..ca91bef4 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -16,6 +16,7 @@ #include <mir/helpers.hpp> #include "codegen_c.hpp" #include "target.hpp" +#include "allocator.hpp" namespace { struct FmtShell @@ -340,6 +341,96 @@ namespace { m_of << "\treturn " << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(argc, argv);\n"; } m_of << "}\n"; + + // Emit allocator bindings + for(const auto& method : ALLOCATOR_METHODS) + { + ::std::vector<const char*> args; + const char* ret_ty = nullptr; + // TODO: Configurable between __rg_, __rdl_, and __rde_ + auto prefix = "__rdl_"; + + for(size_t i = 0; i < method.n_args; i++) + { + switch(method.args[i]) + { + case AllocatorDataTy::Never: + case AllocatorDataTy::Unit: + case AllocatorDataTy::ResultPtr: + case AllocatorDataTy::ResultExcess: + case AllocatorDataTy::UsizePair: + case AllocatorDataTy::ResultUnit: + BUG(Span(), "Invalid data type for allocator argument"); + break; + case AllocatorDataTy::Layout: + args.push_back("uintptr_t"); + args.push_back("uintptr_t"); + break; + case AllocatorDataTy::LayoutRef: + args.push_back("uint8_t*"); + break; + case AllocatorDataTy::AllocError: + args.push_back("uint8_t*"); + break; + case AllocatorDataTy::Ptr: + args.push_back("uint8_t*"); + break; + } + } + switch(method.ret) + { + case AllocatorDataTy::Never: + case AllocatorDataTy::Unit: + ret_ty = "void"; + break; + case AllocatorDataTy::ResultPtr: + args.push_back("uint8_t*"); + ret_ty = "uint8_t*"; + break; + case AllocatorDataTy::ResultExcess: + args.push_back("uint8_t*"); + args.push_back("uint8_t*"); + ret_ty = "uint8_t*"; + break; + case AllocatorDataTy::UsizePair: + args.push_back("uintptr_t*"); + args.push_back("uintptr_t*"); + ret_ty = "void"; + break; + case AllocatorDataTy::ResultUnit: + ret_ty = "int8_t"; + break; + case AllocatorDataTy::Layout: + case AllocatorDataTy::AllocError: + case AllocatorDataTy::Ptr: + case AllocatorDataTy::LayoutRef: + BUG(Span(), "Invalid data type for allocator return"); + } + + m_of << "extern " << ret_ty << " " << prefix << method.name << "("; + for(size_t i = 0; i < args.size(); i++) + { + if(i > 0) m_of << ", "; + m_of << args[i] << " arg" << i; + } + m_of << ");\n"; + + m_of << ret_ty << " __rust_" << method.name << "("; + for(size_t i = 0; i < args.size(); i++) + { + if(i > 0) m_of << ", "; + m_of << args[i] << " arg" << i; + } + m_of << ") {\n"; + m_of << "\treturn " << prefix << method.name << "("; + for(size_t i = 0; i < args.size(); i++) + { + if(i > 0) m_of << ", "; + m_of << "arg" << i; + } + m_of << ");\n"; + m_of << "}\n"; + } } m_of.flush(); @@ -1956,7 +2047,29 @@ namespace { if(is_volatile) m_of << "__volatile__"; // TODO: Convert format string? // TODO: Use a C-specific escaper here. - m_of << "(\"" << (is_intel ? ".syntax intel; " : "") << FmtEscaped(e.tpl) << (is_intel ? ".syntax att; " : "") << "\""; + m_of << "(\"" << (is_intel ? ".syntax intel; " : ""); + for(auto it = e.tpl.begin(); it != e.tpl.end(); ++it) + { + if( *it == '\n' ) + m_of << ";\\n"; + else if( *it == '"' ) + m_of << "\\\""; + else if( *it == '\\' ) + m_of << "\\\\"; + else if( *it == '/' && *(it+1) == '/' ) + { + while( it != e.tpl.end() || *it == '\n' ) + ++it; + -- it; + } + else if( *it == '%' && *(it+1) == '%' ) + m_of << "%"; + else if( *it == '%' && !isdigit(*(it+1)) ) + m_of << "%%"; + else + m_of << *it; + } + m_of << (is_intel ? ".syntax att; " : "") << "\""; m_of << ": "; for(unsigned int i = 0; i < e.outputs.size(); i ++ ) { @@ -2645,6 +2758,28 @@ namespace { ), (UfcsKnown, // TODO: Check if the return type is ! + const auto& tr = m_resolve.m_crate.get_trait_by_path(sp, pe.trait.m_path); + const auto& fcn = tr.m_values.find(pe.item)->second.as_Function(); + const auto& rv_tpl = fcn.m_return; + if( rv_tpl.m_data.is_Diverge() ) + { + is_diverge |= true; + } + else if( const auto* te = rv_tpl.m_data.opt_Generic() ) + { + (void)te; + // TODO: Generic lookup + } + else if( const auto* te = rv_tpl.m_data.opt_Path() ) + { + if( te->binding.is_Opaque() ) { + // TODO: Associated type lookup + } + } + else + { + // Not a ! type + } ) ) if(!is_diverge) @@ -3221,13 +3356,13 @@ namespace { // Bit Twiddling // - CounT Leading Zeroes // - CounT Trailing Zeroes - else if( name == "ctlz" || name == "cttz" ) { + else if( name == "ctlz" || name == "ctlz_nonzero" || name == "cttz" ) { auto emit_arg0 = [&](){ emit_param(e.args.at(0)); }; const auto& ty = params.m_types.at(0); emit_lvalue(e.ret_val); m_of << " = ("; if( ty == ::HIR::CoreType::U128 ) { - if( name == "ctlz" ) { + if( name == "ctlz" || name == "ctlz_nonzero" ) { m_of << "intrinsic_ctlz_u128("; emit_param(e.args.at(0)); m_of << ")"; } else { @@ -3239,7 +3374,7 @@ namespace { else if( ty == ::HIR::CoreType::U64 || (ty == ::HIR::CoreType::Usize /*&& target_is_64_bit */) ) { emit_param(e.args.at(0)); m_of << " != 0 ? "; - if( name == "ctlz" ) { + if( name == "ctlz" || name == "ctlz_nonzero" ) { m_of << "__builtin_clz64("; emit_arg0(); m_of << ")"; } else { @@ -3249,7 +3384,7 @@ namespace { else { emit_param(e.args.at(0)); m_of << " != 0 ? "; - if( name == "ctlz" ) { + if( name == "ctlz" || name == "ctlz_nonzero" ) { m_of << "__builtin_clz("; emit_param(e.args.at(0)); m_of << ")"; } else { diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 41489e2b..b45b72fd 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -152,6 +152,7 @@ TransList Trans_Enumerate_Public(::HIR::Crate& crate) for(auto& impl : crate.m_trait_impls) { const auto& impl_ty = impl.second.m_type; + TRACE_FUNCTION_F("Impl " << impl.first << impl.second.m_trait_args << " for " << impl_ty); if( impl.second.m_params.m_types.size() == 0 ) { auto cb_monomorph = monomorphise_type_get_cb(sp, &impl_ty, &impl.second.m_trait_args, nullptr); @@ -160,10 +161,14 @@ TransList Trans_Enumerate_Public(::HIR::Crate& crate) const auto& trait = crate.get_trait_by_path(sp, impl.first); for(const auto& vi : trait.m_values) { + TRACE_FUNCTION_F("Item " << vi.first << " : " << vi.second.tag_str()); + // Constant, no codegen if( vi.second.is_Constant() ) ; + // Generic method, no codegen else if( vi.second.is_Function() && vi.second.as_Function().m_params.m_types.size() > 0 ) ; + // VTable, magic else if( vi.first == "#vtable" ) ; else |