aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-implitem.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend/rust-compile-implitem.h')
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h213
1 files changed, 213 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index 7608599..e446cf9 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -297,6 +297,219 @@ 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, fntype))
+ {
+ // 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_impl_item (self, fntype, function.get_function_name ());
+
+ 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