aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-implitem.h
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-08-20 12:34:35 +0000
committerGitHub <noreply@github.com>2021-08-20 12:34:35 +0000
commit79754bd20bdfa64a4ce91e5b4a65154c313b2d83 (patch)
tree47dc551f706c4015c017a299a4054cb7db460857 /gcc/rust/backend/rust-compile-implitem.h
parent387f73626ae0e04c3f81d71d4de6780a4caad052 (diff)
parent048261647afd1a08f681b78c90c58a9baaeef76d (diff)
downloadgcc-79754bd20bdfa64a4ce91e5b4a65154c313b2d83.zip
gcc-79754bd20bdfa64a4ce91e5b4a65154c313b2d83.tar.gz
gcc-79754bd20bdfa64a4ce91e5b4a65154c313b2d83.tar.bz2
Merge #626
626: Optional trait items r=philberty a=philberty Optional trait items like function may contain associated types. These are dependant on the associated impl block for this type in order to correctly propagate the correct types for the associated trait item during type checking and compilation. Fixes #542 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/backend/rust-compile-implitem.h')
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h214
1 files changed, 214 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index 7608599..7337154 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -297,6 +297,220 @@ private:
TyTy::BaseType *concrete;
};
+class CompileTraitItem : public HIRCompileBase
+{
+ using Rust::Compile::HIRCompileBase::visit;
+
+public:
+ static void Compile (TyTy::BaseType *self, HIR::TraitItem *item, Context *ctx,
+ TyTy::BaseType *concrete)
+ {
+ CompileTraitItem compiler (self, ctx, concrete);
+ item->accept_vis (compiler);
+ }
+
+ void visit (HIR::TraitItemFunc &func) override
+ {
+ rust_assert (func.has_block_defined ());
+
+ rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *fntype = static_cast<TyTy::FnType *> (concrete);
+
+ // items can be forward compiled which means we may not need to invoke this
+ // code. We might also have already compiled this generic function as well.
+ Bfunction *lookup = nullptr;
+ if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup))
+ {
+ // has this been added to the list then it must be finished
+ if (ctx->function_completed (lookup))
+ {
+ Bfunction *dummy = nullptr;
+ if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
+ {
+ ctx->insert_function_decl (fntype->get_ty_ref (), lookup,
+ fntype);
+ }
+ return;
+ }
+ }
+
+ if (fntype->has_subsititions_defined ())
+ {
+ // override the Hir Lookups for the substituions in this context
+ fntype->override_context ();
+ }
+
+ // convert to the actual function type
+ ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
+
+ HIR::TraitFunctionDecl &function = func.get_decl ();
+ unsigned int flags = 0;
+
+ const Resolver::CanonicalPath *canonical_path = nullptr;
+ rust_assert (ctx->get_mappings ()->lookup_canonical_path (
+ func.get_mappings ().get_crate_num (), func.get_mappings ().get_nodeid (),
+ &canonical_path));
+
+ std::string fn_identifier = canonical_path->get ();
+ std::string asm_name = ctx->mangle_item (fntype, *canonical_path);
+
+ Bfunction *fndecl
+ = ctx->get_backend ()->function (compiled_fn_type, fn_identifier,
+ asm_name, flags, func.get_locus ());
+ ctx->insert_function_decl (fntype->get_ty_ref (), fndecl, fntype);
+
+ // setup the params
+ TyTy::BaseType *tyret = fntype->get_return_type ();
+ std::vector<Bvariable *> param_vars;
+
+ if (function.is_method ())
+ {
+ // insert self
+ TyTy::BaseType *self_tyty_lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ function.get_self ().get_mappings ().get_hirid (),
+ &self_tyty_lookup))
+ {
+ rust_error_at (function.get_self ().get_locus (),
+ "failed to lookup self param type");
+ return;
+ }
+
+ Btype *self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup);
+ if (self_type == nullptr)
+ {
+ rust_error_at (function.get_self ().get_locus (),
+ "failed to compile self param type");
+ return;
+ }
+
+ Bvariable *compiled_self_param
+ = CompileSelfParam::compile (ctx, fndecl, function.get_self (),
+ self_type,
+ function.get_self ().get_locus ());
+ if (compiled_self_param == nullptr)
+ {
+ rust_error_at (function.get_self ().get_locus (),
+ "failed to compile self param variable");
+ return;
+ }
+
+ param_vars.push_back (compiled_self_param);
+ ctx->insert_var_decl (function.get_self ().get_mappings ().get_hirid (),
+ compiled_self_param);
+ }
+
+ // offset from + 1 for the TyTy::FnType being used when this is a method to
+ // skip over Self on the FnType
+ size_t i = function.is_method () ? 1 : 0;
+ for (auto referenced_param : function.get_function_params ())
+ {
+ auto tyty_param = fntype->param_at (i);
+ auto param_tyty = tyty_param.second;
+
+ auto compiled_param_type
+ = TyTyResolveCompile::compile (ctx, param_tyty);
+ if (compiled_param_type == nullptr)
+ {
+ rust_error_at (referenced_param.get_locus (),
+ "failed to compile parameter type");
+ return;
+ }
+
+ Location param_locus
+ = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ());
+ Bvariable *compiled_param_var
+ = CompileFnParam::compile (ctx, fndecl, &referenced_param,
+ compiled_param_type, param_locus);
+ if (compiled_param_var == nullptr)
+ {
+ rust_error_at (param_locus, "Failed to compile parameter variable");
+ return;
+ }
+
+ param_vars.push_back (compiled_param_var);
+
+ ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (),
+ compiled_param_var);
+ i++;
+ }
+
+ if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
+ {
+ rust_fatal_error (func.get_locus (),
+ "failed to setup parameter variables");
+ return;
+ }
+
+ // lookup locals
+ auto block_expr = func.get_block_expr ().get ();
+ auto body_mappings = block_expr->get_mappings ();
+
+ Resolver::Rib *rib = nullptr;
+ if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (),
+ &rib))
+ {
+ rust_fatal_error (func.get_locus (),
+ "failed to setup locals per block");
+ return;
+ }
+
+ std::vector<Bvariable *> locals;
+ bool ok = compile_locals_for_block (*rib, fndecl, locals);
+ rust_assert (ok);
+
+ Bblock *enclosing_scope = NULL;
+ HIR::BlockExpr *function_body = func.get_block_expr ().get ();
+ Location start_location = function_body->get_locus ();
+ Location end_location = function_body->get_closing_locus ();
+
+ Bblock *code_block
+ = ctx->get_backend ()->block (fndecl, enclosing_scope, locals,
+ start_location, end_location);
+ ctx->push_block (code_block);
+
+ Bvariable *return_address = nullptr;
+ if (function.has_return_type ())
+ {
+ Btype *return_type = TyTyResolveCompile::compile (ctx, tyret);
+
+ bool address_is_taken = false;
+ Bstatement *ret_var_stmt = nullptr;
+
+ return_address = ctx->get_backend ()->temporary_variable (
+ fndecl, code_block, return_type, NULL, address_is_taken,
+ func.get_locus (), &ret_var_stmt);
+
+ ctx->add_statement (ret_var_stmt);
+ }
+
+ ctx->push_fn (fndecl, return_address);
+
+ compile_function_body (fndecl, func.get_block_expr (),
+ function.has_return_type ());
+
+ ctx->pop_block ();
+ auto body = ctx->get_backend ()->block_statement (code_block);
+ if (!ctx->get_backend ()->function_set_body (fndecl, body))
+ {
+ rust_error_at (func.get_locus (), "failed to set body to function");
+ return;
+ }
+
+ ctx->pop_fn ();
+ ctx->push_function (fndecl);
+ }
+
+private:
+ CompileTraitItem (TyTy::BaseType *self, Context *ctx,
+ TyTy::BaseType *concrete)
+ : HIRCompileBase (ctx), self (self), concrete (concrete)
+ {}
+
+ TyTy::BaseType *self;
+ TyTy::BaseType *concrete;
+};
+
} // namespace Compile
} // namespace Rust