summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--rust-nightly-date2
-rw-r--r--src/expand/mod.cpp102
-rw-r--r--src/hir/from_ast.cpp88
-rw-r--r--src/hir/from_ast_expr.cpp47
-rw-r--r--src/hir_conv/expand_type.cpp16
-rw-r--r--src/hir_conv/resolve_ufcs.cpp31
-rw-r--r--src/hir_typeck/expr_cs.cpp38
-rw-r--r--src/hir_typeck/helpers.cpp21
-rw-r--r--src/hir_typeck/static.cpp102
-rw-r--r--src/hir_typeck/static.hpp5
-rw-r--r--src/main.cpp9
-rw-r--r--src/mir/from_hir.cpp10
-rw-r--r--src/parse/root.cpp9
-rw-r--r--src/resolve/absolute.cpp2
-rw-r--r--src/resolve/use.cpp1
-rw-r--r--src/trans/allocator.cpp30
-rw-r--r--src/trans/allocator.hpp32
-rw-r--r--src/trans/codegen_c.cpp145
-rw-r--r--src/trans/enumerate.cpp5
20 files changed, 612 insertions, 87 deletions
diff --git a/Makefile b/Makefile
index d2f588cc..37e44d2e 100644
--- a/Makefile
+++ b/Makefile
@@ -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