aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/cscope.h160
-rw-r--r--gcc/rust/backend/rust-compile-base.h6
-rw-r--r--gcc/rust/backend/rust-compile-block.h41
-rw-r--r--gcc/rust/backend/rust-compile-context.h16
-rw-r--r--gcc/rust/backend/rust-compile-expr.h54
-rw-r--r--gcc/rust/backend/rust-compile-fnparam.h16
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h248
-rw-r--r--gcc/rust/backend/rust-compile-item.h38
-rw-r--r--gcc/rust/backend/rust-compile-stmt.h26
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h23
-rw-r--r--gcc/rust/backend/rust-compile.cc201
11 files changed, 531 insertions, 298 deletions
diff --git a/gcc/rust/backend/cscope.h b/gcc/rust/backend/cscope.h
deleted file mode 100644
index 3ba837c..0000000
--- a/gcc/rust/backend/cscope.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (C) 2020 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#pragma once
-
-#include "rust-system.h"
-#include "rust-backend.h"
-#include "scope.h"
-
-namespace Rust {
-namespace Compile {
-
-class Scope
-{
-public:
- Scope (Backend *backend) : backend (backend) {}
-
- ~Scope () {}
-
- void Push ()
- {
- fndecls.Push ();
- vars.Push ();
- types.Push ();
- structDecls.Push ();
- }
-
- void Pop ()
- {
- fndecls.Pop ();
- vars.Pop ();
- types.Pop ();
- structDecls.Pop ();
- }
-
- void PushCurrentFunction (std::string name, Bfunction *fn, Btype *retType,
- Bvariable *retDecl)
- {
- fns.push_back (fn);
- fnRetType.push_back (retType);
- fnRetDecl.push_back (retDecl);
- }
-
- Bfunction *PopCurrentFunction ()
- {
- auto ret = fns.back ();
- fns.pop_back ();
- fnRetType.pop_back ();
- fnRetDecl.pop_back ();
- return ret;
- }
-
- Bfunction *GetCurrentFndecl () { return fns.back (); }
-
- Btype *GetCurrentFnRetType () { return fnRetType.back (); }
-
- Bvariable *GetCurrentFnRetDecl () { return fnRetDecl.back (); }
-
- Btype *GetFnRetType (Bfunction *fn)
- {
- auto it = fnRetTypeMapping.find (fn);
- if (it == fnRetTypeMapping.end ())
- {
- return NULL;
- }
- return it->second;
- }
-
- void PushBlock (Bblock *block)
- {
- blocks.push_back (block);
- std::vector<Bstatement *> empty;
- context.push_back (empty);
- }
-
- Bblock *PopBlock ()
- {
- auto ret = blocks.back ();
- blocks.pop_back ();
-
- auto stmts = context.back ();
- context.pop_back ();
-
- backend->block_add_statements (ret, stmts);
-
- return ret;
- }
-
- Bblock *CurBlock () { return blocks.back (); }
-
- void AddStatement (Bstatement *stmt) { context.back ().push_back (stmt); }
-
- void InsertStructDecl (std::string name, AST::StructStruct *decl)
- {
- structDecls.Insert (name, decl);
- }
-
- bool LookupStructDecl (std::string name, AST::StructStruct **decl)
- {
- return structDecls.Lookup (name, decl);
- }
-
- void InsertFunction (std::string name, Bfunction *fn, Btype *retType)
- {
- fndecls.Insert (name, fn);
- fnRetTypeMapping[fn] = retType;
- }
-
- bool LookupFunction (std::string name, Bfunction **fn)
- {
- return fndecls.Lookup (name, fn);
- }
-
- void InsertType (std::string name, Btype *type) { types.Insert (name, type); }
-
- bool LookupType (std::string name, Btype **type)
- {
- return types.Lookup (name, type);
- }
-
- void InsertVar (std::string name, Bvariable *var) { vars.Insert (name, var); }
-
- bool LookupVar (std::string name, Bvariable **var)
- {
- return vars.Lookup (name, var);
- }
-
-private:
- Backend *backend;
-
- ::std::vector<Bfunction *> fns;
- ::std::vector<Bblock *> blocks;
- ::std::vector< ::std::vector<Bstatement *> > context;
- ::std::vector< ::Btype *> fnRetType;
- ::std::vector< ::Bvariable *> fnRetDecl;
- ::std::map<Bfunction *, Btype *> fnRetTypeMapping;
-
- Analysis::Scope<Bfunction *> fndecls;
- Analysis::Scope<Bvariable *> vars;
- Analysis::Scope<Btype *> types;
- Analysis::Scope<AST::StructStruct *> structDecls;
-};
-
-} // namespace Compile
-} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index fdc5ad9..ec7c13a 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -237,9 +237,13 @@ public:
protected:
HIRCompileBase (Context *ctx) : ctx (ctx) {}
+ Context *ctx;
+
Context *get_context () { return ctx; }
- Context *ctx;
+ void compile_function_body (Bfunction *fndecl,
+ std::unique_ptr<HIR::BlockExpr> &function_body,
+ bool has_return_type);
};
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h
index b17fb05..879e32d 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -28,35 +28,35 @@ namespace Compile {
class CompileBlock : public HIRCompileBase
{
public:
- static Bblock *compile (HIR::BlockExpr *expr, Context *ctx)
+ static Bblock *compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result)
{
- CompileBlock compiler (ctx);
+ CompileBlock compiler (ctx, result);
expr->accept_vis (compiler);
return compiler.translated;
}
- ~CompileBlock () {}
-
void visit (HIR::BlockExpr &expr);
private:
- CompileBlock (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {}
+ CompileBlock (Context *ctx, Bvariable *result)
+ : HIRCompileBase (ctx), translated (nullptr), result (result)
+ {}
Bblock *translated;
+ Bvariable *result;
};
class CompileConditionalBlocks : public HIRCompileBase
{
public:
- static Bstatement *compile (HIR::IfExpr *expr, Context *ctx)
+ static Bstatement *compile (HIR::IfExpr *expr, Context *ctx,
+ Bvariable *result)
{
- CompileConditionalBlocks resolver (ctx);
+ CompileConditionalBlocks resolver (ctx, result);
expr->accept_vis (resolver);
return resolver.translated;
}
- ~CompileConditionalBlocks () {}
-
void visit (HIR::IfExpr &expr);
void visit (HIR::IfExprConseqElse &expr);
@@ -64,46 +64,47 @@ public:
void visit (HIR::IfExprConseqIf &expr);
private:
- CompileConditionalBlocks (Context *ctx)
- : HIRCompileBase (ctx), translated (nullptr)
+ CompileConditionalBlocks (Context *ctx, Bvariable *result)
+ : HIRCompileBase (ctx), translated (nullptr), result (result)
{}
Bstatement *translated;
+ Bvariable *result;
};
class CompileExprWithBlock : public HIRCompileBase
{
public:
- static Bstatement *compile (HIR::ExprWithBlock *expr, Context *ctx)
+ static Bstatement *compile (HIR::ExprWithBlock *expr, Context *ctx,
+ Bvariable *result)
{
- CompileExprWithBlock resolver (ctx);
+ CompileExprWithBlock resolver (ctx, result);
expr->accept_vis (resolver);
return resolver.translated;
}
- ~CompileExprWithBlock () {}
-
void visit (HIR::IfExpr &expr)
{
- translated = CompileConditionalBlocks::compile (&expr, ctx);
+ translated = CompileConditionalBlocks::compile (&expr, ctx, result);
}
void visit (HIR::IfExprConseqElse &expr)
{
- translated = CompileConditionalBlocks::compile (&expr, ctx);
+ translated = CompileConditionalBlocks::compile (&expr, ctx, result);
}
void visit (HIR::IfExprConseqIf &expr)
{
- translated = CompileConditionalBlocks::compile (&expr, ctx);
+ translated = CompileConditionalBlocks::compile (&expr, ctx, result);
}
private:
- CompileExprWithBlock (Context *ctx)
- : HIRCompileBase (ctx), translated (nullptr)
+ CompileExprWithBlock (Context *ctx, Bvariable *result)
+ : HIRCompileBase (ctx), translated (nullptr), result (result)
{}
Bstatement *translated;
+ Bvariable *result;
};
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 034568f..25c9b89 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -110,6 +110,11 @@ public:
return scope_stack.back ();
}
+ void add_statement_to_enclosing_scope (Bstatement *stmt)
+ {
+ statements.at (statements.size () - 2).push_back (stmt);
+ }
+
void add_statement (Bstatement *stmt) { statements.back ().push_back (stmt); }
void insert_var_decl (HirId id, ::Bvariable *decl)
@@ -222,11 +227,11 @@ public:
virtual ~TyTyResolveCompile () {}
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
+ void visit (TyTy::ErrorType &) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
+ void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
+ void visit (TyTy::StructFieldType &) override { gcc_unreachable (); }
void visit (TyTy::FnType &type) override
{
@@ -261,7 +266,7 @@ public:
ctx->get_mappings ()->lookup_location (type.get_ref ()));
}
- void visit (TyTy::UnitType &type) override
+ void visit (TyTy::UnitType &) override
{
translated = ctx->get_backend ()->void_type ();
}
@@ -278,8 +283,7 @@ public:
{
TyTy::StructFieldType *field = type.get_field (i);
Btype *compiled_field_ty
- = TyTyCompile::compile (ctx->get_backend (),
- field->get_field_type ());
+ = TyTyResolveCompile::compile (ctx, field->get_field_type ());
Backend::Btyped_identifier f (field->get_name (), compiled_field_ty,
ctx->get_mappings ()->lookup_location (
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index ccff51a..b823d29 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -99,6 +99,8 @@ public:
void visit (HIR::CallExpr &expr);
+ void visit (HIR::MethodCallExpr &expr);
+
void visit (HIR::IdentifierExpr &expr)
{
// need to look up the reference for this identifier
@@ -409,27 +411,71 @@ public:
void visit (HIR::IfExpr &expr)
{
- auto stmt = CompileConditionalBlocks::compile (&expr, ctx);
+ auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr);
ctx->add_statement (stmt);
}
void visit (HIR::IfExprConseqElse &expr)
{
- auto stmt = CompileConditionalBlocks::compile (&expr, ctx);
+ // this can be a return expression
+ TyTy::TyBase *if_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &if_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to lookup type of IfExprConseqElse");
+ return;
+ }
+
+ fncontext fnctx = ctx->peek_fn ();
+ Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
+ Btype *block_type = TyTyResolveCompile::compile (ctx, if_type);
+
+ bool is_address_taken = false;
+ Bstatement *ret_var_stmt = nullptr;
+ Bvariable *tmp = ctx->get_backend ()->temporary_variable (
+ fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken,
+ expr.get_locus (), &ret_var_stmt);
+ ctx->add_statement (ret_var_stmt);
+
+ auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp);
ctx->add_statement (stmt);
+
+ translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
}
void visit (HIR::IfExprConseqIf &expr)
{
- auto stmt = CompileConditionalBlocks::compile (&expr, ctx);
+ auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr);
ctx->add_statement (stmt);
}
void visit (HIR::BlockExpr &expr)
{
- auto code_block = CompileBlock::compile (&expr, ctx);
+ TyTy::TyBase *block_tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &block_tyty))
+ {
+ rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr");
+ return;
+ }
+
+ fncontext fnctx = ctx->peek_fn ();
+ Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
+ Btype *block_type = TyTyResolveCompile::compile (ctx, block_tyty);
+
+ bool is_address_taken = false;
+ Bstatement *ret_var_stmt = nullptr;
+ Bvariable *tmp = ctx->get_backend ()->temporary_variable (
+ fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken,
+ expr.get_locus (), &ret_var_stmt);
+ ctx->add_statement (ret_var_stmt);
+
+ auto code_block = CompileBlock::compile (&expr, ctx, tmp);
auto block_stmt = ctx->get_backend ()->block_statement (code_block);
ctx->add_statement (block_stmt);
+
+ translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
}
void visit (HIR::StructExprStructFields &struct_expr)
diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h
index cf6e6f7..1ea0c9f 100644
--- a/gcc/rust/backend/rust-compile-fnparam.h
+++ b/gcc/rust/backend/rust-compile-fnparam.h
@@ -61,6 +61,22 @@ private:
::Bvariable *translated;
};
+class CompileSelfParam : public HIRCompileBase
+{
+public:
+ static Bvariable *compile (Context *ctx, Bfunction *fndecl,
+ HIR::SelfParam &self, Btype *decl_type,
+ Location locus)
+ {
+ if (!self.get_is_mut ())
+ decl_type = ctx->get_backend ()->immutable_type (decl_type);
+
+ return ctx->get_backend ()->parameter_variable (fndecl, "self", decl_type,
+ false /* address_taken */,
+ locus);
+ }
+};
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index fe2abf1..6d180c8 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -32,10 +32,10 @@ namespace Compile {
class CompileInherentImplItem : public HIRCompileBase
{
public:
- static void Compile (HIR::Type *base, HIR::InherentImplItem *item,
+ static void Compile (TyTy::TyBase *self, HIR::InherentImplItem *item,
Context *ctx, bool compile_fns)
{
- CompileInherentImplItem compiler (base, ctx, compile_fns);
+ CompileInherentImplItem compiler (self, ctx, compile_fns);
item->accept_vis (compiler);
}
@@ -50,7 +50,7 @@ public:
::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type);
Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx);
- std::string ident = base->as_string () + "::" + constant.get_identifier ();
+ std::string ident = self->as_string () + "::" + constant.get_identifier ();
Bexpression *const_expr = ctx->get_backend ()->named_constant_expression (
type, constant.get_identifier (), value, constant.get_locus ());
@@ -78,7 +78,8 @@ public:
if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
&fntype_tyty))
{
- rust_fatal_error (function.locus, "failed to lookup function type");
+ rust_fatal_error (function.get_locus (),
+ "failed to lookup function type");
return;
}
@@ -93,23 +94,15 @@ public:
::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
unsigned int flags = 0;
- bool is_main_fn = function.function_name.compare ("main") == 0;
-
std::string fn_identifier
- = base->as_string () + "::" + function.function_name;
+ = self->as_string () + "::" + function.function_name;
// if its the main fn or pub visibility mark its as DECL_PUBLIC
// please see https://github.com/Rust-GCC/gccrs/pull/137
- if (is_main_fn || function.has_visibility ())
+ if (function.has_visibility ())
flags |= Backend::function_is_visible;
std::string asm_name = fn_identifier;
- if (!is_main_fn)
- {
- // FIXME need name mangling
- asm_name = "__" + function.function_name;
- }
-
Bfunction *fndecl
= ctx->get_backend ()->function (compiled_fn_type, fn_identifier,
asm_name, flags, function.get_locus ());
@@ -213,34 +206,219 @@ public:
ctx->push_fn (fndecl, return_address);
- // compile the block
- function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
- CompileStmt::Compile (s, ctx);
+ compile_function_body (fndecl, function.function_body,
+ function.has_function_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 (function.get_locus (), "failed to set body to function");
+ return;
+ }
+
+ ctx->pop_fn ();
+
+ ctx->push_function (fndecl);
+ }
+
+ void visit (HIR::Method &method)
+ {
+ if (!compile_fns)
+ return;
+
+ // items can be forward compiled which means we may not need to invoke this
+ // code
+ Bfunction *lookup = nullptr;
+ if (ctx->lookup_function_decl (method.get_mappings ().get_hirid (),
+ &lookup))
+ {
+ // has this been added to the list then it must be finished
+ if (ctx->function_completed (lookup))
+ return;
+ }
+
+ TyTy::TyBase *fntype_tyty;
+ if (!ctx->get_tyctx ()->lookup_type (method.get_mappings ().get_hirid (),
+ &fntype_tyty))
+ {
+ rust_fatal_error (method.get_locus (),
+ "failed to lookup function type");
+ return;
+ }
+
+ if (fntype_tyty->get_kind () != TyTy::TypeKind::FNDEF)
+ {
+ rust_error_at (method.get_locus (), "invalid TyTy for function item");
+ return;
+ }
+
+ TyTy::FnType *fntype = (TyTy::FnType *) fntype_tyty;
+ // convert to the actual function type
+ ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
+
+ unsigned int flags = 0;
+ std::string fn_identifier
+ = self->as_string () + "::" + method.get_method_name ();
+
+ // if its the main fn or pub visibility mark its as DECL_PUBLIC
+ // please see https://github.com/Rust-GCC/gccrs/pull/137
+ if (method.has_visibility ())
+ flags |= Backend::function_is_visible;
+
+ std::string asm_name = fn_identifier;
+ Bfunction *fndecl
+ = ctx->get_backend ()->function (compiled_fn_type, fn_identifier,
+ asm_name, flags, method.get_locus ());
+ ctx->insert_function_decl (method.get_mappings ().get_hirid (), fndecl);
+
+ // setup the params
+ TyTy::TyBase *tyret = fntype->return_type ();
+ std::vector<Bvariable *> param_vars;
+
+ // insert self
+ TyTy::TyBase *self_tyty_lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ method.get_self_param ().get_mappings ().get_hirid (),
+ &self_tyty_lookup))
+ {
+ rust_error_at (method.get_self_param ().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 (method.get_self_param ().get_locus (),
+ "failed to compile self param type");
+ return;
+ }
+
+ Bvariable *compiled_self_param
+ = CompileSelfParam::compile (ctx, fndecl, method.get_self_param (),
+ self_type,
+ method.get_self_param ().get_locus ());
+ if (compiled_self_param == nullptr)
+ {
+ rust_error_at (method.get_self_param ().get_locus (),
+ "failed to compile self param variable");
+ return;
+ }
+
+ param_vars.push_back (compiled_self_param);
+ ctx->insert_var_decl (method.get_self_param ().get_mappings ().get_hirid (),
+ compiled_self_param);
+
+ // offset from + 1 for the TyTy::FnType being used
+ size_t i = 1;
+ for (auto referenced_param : method.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 (method.get_locus (),
+ "failed to setup parameter variables");
+ return;
+ }
+
+ // lookup locals
+ auto block_expr = method.get_function_body ().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 (method.get_locus (),
+ "failed to setup locals per block");
+ return;
+ }
+
+ std::vector<Bvariable *> locals;
+ rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool {
+ Resolver::Definition d;
+ bool ok = ctx->get_resolver ()->lookup_definition (n, &d);
+ rust_assert (ok);
+
+ HIR::Stmt *decl = nullptr;
+ ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl);
+ rust_assert (ok);
+
+ Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx);
+ locals.push_back (compiled);
+
return true;
});
- if (function_body->has_expr () && function_body->tail_expr_reachable ())
+ bool toplevel_item
+ = method.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID;
+ Bblock *enclosing_scope
+ = toplevel_item ? NULL : ctx->peek_enclosing_scope ();
+
+ HIR::BlockExpr *function_body = method.get_function_body ().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 (method.has_function_return_type ())
{
- // the previous passes will ensure this is a valid return
- // dead code elimination should remove any bad trailing expressions
- Bexpression *compiled_expr
- = CompileExpr::Compile (function_body->expr.get (), ctx);
- rust_assert (compiled_expr != nullptr);
-
- auto fncontext = ctx->peek_fn ();
-
- std::vector<Bexpression *> retstmts;
- retstmts.push_back (compiled_expr);
- auto s = ctx->get_backend ()->return_statement (
- fncontext.fndecl, retstmts, function_body->expr->get_locus_slow ());
- ctx->add_statement (s);
+ 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,
+ method.get_locus (), &ret_var_stmt);
+
+ ctx->add_statement (ret_var_stmt);
}
+ ctx->push_fn (fndecl, return_address);
+
+ compile_function_body (fndecl, method.get_function_body (),
+ method.has_function_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 (function.get_locus (), "failed to set body to function");
+ rust_error_at (method.get_locus (), "failed to set body to function");
return;
}
@@ -250,11 +428,11 @@ public:
}
private:
- CompileInherentImplItem (HIR::Type *base, Context *ctx, bool compile_fns)
- : HIRCompileBase (ctx), base (base), compile_fns (compile_fns)
+ CompileInherentImplItem (TyTy::TyBase *self, Context *ctx, bool compile_fns)
+ : HIRCompileBase (ctx), self (self), compile_fns (compile_fns)
{}
- HIR::Type *base;
+ TyTy::TyBase *self;
bool compile_fns;
};
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index 83e4451..7f93af9f 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -265,28 +265,8 @@ public:
ctx->push_fn (fndecl, return_address);
- // compile the block
- function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
- CompileStmt::Compile (s, ctx);
- return true;
- });
-
- if (function_body->has_expr () && function_body->tail_expr_reachable ())
- {
- // the previous passes will ensure this is a valid return
- // dead code elimination should remove any bad trailing expressions
- Bexpression *compiled_expr
- = CompileExpr::Compile (function_body->expr.get (), ctx);
- rust_assert (compiled_expr != nullptr);
-
- auto fncontext = ctx->peek_fn ();
-
- std::vector<Bexpression *> retstmts;
- retstmts.push_back (compiled_expr);
- auto s = ctx->get_backend ()->return_statement (
- fncontext.fndecl, retstmts, function_body->expr->get_locus_slow ());
- ctx->add_statement (s);
- }
+ compile_function_body (fndecl, function.function_body,
+ function.has_function_return_type ());
ctx->pop_block ();
auto body = ctx->get_backend ()->block_statement (code_block);
@@ -297,15 +277,23 @@ public:
}
ctx->pop_fn ();
-
ctx->push_function (fndecl);
}
void visit (HIR::InherentImpl &impl_block)
{
+ TyTy::TyBase *self_lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ impl_block.get_type ()->get_mappings ().get_hirid (), &self_lookup))
+ {
+ rust_error_at (impl_block.get_locus (),
+ "failed to resolve type of impl");
+ return;
+ }
+
for (auto &impl_item : impl_block.get_impl_items ())
- CompileInherentImplItem::Compile (impl_block.get_type ().get (),
- impl_item.get (), ctx, compile_fns);
+ CompileInherentImplItem::Compile (self_lookup, impl_item.get (), ctx,
+ compile_fns);
}
private:
diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h
index c52f605..d021240e4 100644
--- a/gcc/rust/backend/rust-compile-stmt.h
+++ b/gcc/rust/backend/rust-compile-stmt.h
@@ -29,37 +29,24 @@ namespace Compile {
class CompileStmt : public HIRCompileBase
{
public:
- static void Compile (HIR::Stmt *stmt, Context *ctx)
+ static Bexpression *Compile (HIR::Stmt *stmt, Context *ctx)
{
CompileStmt compiler (ctx);
stmt->accept_vis (compiler);
rust_assert (compiler.ok);
+ return compiler.translated;
}
- virtual ~CompileStmt () {}
-
void visit (HIR::ExprStmtWithBlock &stmt)
{
ok = true;
- auto translated = CompileExpr::Compile (stmt.get_expr (), ctx);
-
- // these can be null
- if (translated == nullptr)
- return;
-
- gcc_unreachable ();
+ translated = CompileExpr::Compile (stmt.get_expr (), ctx);
}
void visit (HIR::ExprStmtWithoutBlock &stmt)
{
ok = true;
- auto translated = CompileExpr::Compile (stmt.get_expr (), ctx);
-
- // these can be null
- if (translated == nullptr)
- return;
-
- gcc_unreachable ();
+ translated = CompileExpr::Compile (stmt.get_expr (), ctx);
}
void visit (HIR::LetStmt &stmt)
@@ -99,9 +86,12 @@ public:
}
private:
- CompileStmt (Context *ctx) : HIRCompileBase (ctx), ok (false) {}
+ CompileStmt (Context *ctx)
+ : HIRCompileBase (ctx), ok (false), translated (nullptr)
+ {}
bool ok;
+ Bexpression *translated;
};
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index 2c54b17..0629cbe 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -44,22 +44,19 @@ public:
~TyTyCompile () {}
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
+ void visit (TyTy::ErrorType &) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
+ void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
+ void visit (TyTy::StructFieldType &) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
+ void visit (TyTy::ADTType &) override { gcc_unreachable (); }
- void visit (TyTy::TupleType &type) override { gcc_unreachable (); }
+ void visit (TyTy::TupleType &) override { gcc_unreachable (); }
- void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
+ void visit (TyTy::ArrayType &) override { gcc_unreachable (); }
- void visit (TyTy::UnitType &type) override
- {
- translated = backend->void_type ();
- }
+ void visit (TyTy::UnitType &) override { translated = backend->void_type (); }
void visit (TyTy::FnType &type) override
{
@@ -93,7 +90,7 @@ public:
mappings->lookup_location (type.get_ref ()));
}
- void visit (TyTy::BoolType &type) override
+ void visit (TyTy::BoolType &) override
{
translated = backend->named_type ("bool", backend->bool_type (),
Linemap::predeclared_location ());
@@ -190,14 +187,14 @@ public:
gcc_unreachable ();
}
- void visit (TyTy::USizeType &type) override
+ void visit (TyTy::USizeType &) override
{
translated = backend->named_type (
"usize", backend->integer_type (true, backend->get_pointer_size ()),
Linemap::predeclared_location ());
}
- void visit (TyTy::ISizeType &type) override
+ void visit (TyTy::ISizeType &) override
{
translated = backend->named_type (
"isize", backend->integer_type (false, backend->get_pointer_size ()),
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index ce6d827..0b83c72 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -95,6 +95,83 @@ CompileExpr::visit (HIR::CallExpr &expr)
}
}
+void
+CompileExpr::visit (HIR::MethodCallExpr &expr)
+{
+ // lookup the resolved name
+ NodeId resolved_node_id = UNKNOWN_NODEID;
+ if (!ctx->get_resolver ()->lookup_resolved_name (
+ expr.get_mappings ().get_nodeid (), &resolved_node_id))
+ {
+ rust_error_at (expr.get_locus (), "failed to lookup resolved MethodCall");
+ return;
+ }
+
+ // reverse lookup
+ HirId ref;
+ if (!ctx->get_mappings ()->lookup_node_to_hir (
+ expr.get_mappings ().get_crate_num (), resolved_node_id, &ref))
+ {
+ rust_fatal_error (expr.get_locus (), "reverse lookup failure");
+ return;
+ }
+
+ // lookup compiled functions
+ Bfunction *fn = nullptr;
+ if (!ctx->lookup_function_decl (ref, &fn))
+ {
+ // this might fail because its a forward decl so we can attempt to
+ // resolve it now
+ HIR::InherentImplItem *resolved_item
+ = ctx->get_mappings ()->lookup_hir_implitem (
+ expr.get_mappings ().get_crate_num (), ref);
+ if (resolved_item == nullptr)
+ {
+ rust_error_at (expr.get_locus (), "failed to lookup forward decl");
+ return;
+ }
+
+ TyTy::TyBase *self_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_receiver ()->get_mappings ().get_hirid (), &self_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for self param");
+ return;
+ }
+
+ CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true);
+ if (!ctx->lookup_function_decl (ref, &fn))
+ {
+ rust_error_at (expr.get_locus (), "forward decl was not compiled");
+ return;
+ }
+ }
+
+ Bexpression *fn_expr
+ = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ());
+
+ std::vector<Bexpression *> args;
+
+ // method receiver
+ Bexpression *self = CompileExpr::Compile (expr.get_receiver ().get (), ctx);
+ rust_assert (self != nullptr);
+ args.push_back (self);
+
+ // normal args
+ expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool {
+ Bexpression *compiled_expr = CompileExpr::Compile (p, ctx);
+ rust_assert (compiled_expr != nullptr);
+ args.push_back (compiled_expr);
+ return true;
+ });
+
+ auto fncontext = ctx->peek_fn ();
+ translated
+ = ctx->get_backend ()->call_expression (fncontext.fndecl, fn_expr, args,
+ nullptr, expr.get_locus ());
+}
+
// rust-compile-block.h
void
@@ -135,10 +212,30 @@ CompileBlock::visit (HIR::BlockExpr &expr)
start_location, end_location);
ctx->push_block (new_block);
- expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
- CompileStmt::Compile (s, ctx);
- return true;
- });
+ for (auto &s : expr.get_statements ())
+ {
+ auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
+ if (compiled_expr == nullptr)
+ continue;
+
+ if (result == nullptr)
+ {
+ Bstatement *final_stmt
+ = ctx->get_backend ()->expression_statement (fnctx.fndecl,
+ compiled_expr);
+ ctx->add_statement (final_stmt);
+ }
+ else
+ {
+ Bexpression *result_reference
+ = ctx->get_backend ()->var_expression (result,
+ s->get_locus_slow ());
+
+ Bstatement *assignment = ctx->get_backend ()->assignment_statement (
+ fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ());
+ ctx->add_statement (assignment);
+ }
+ }
if (expr.has_expr () && expr.tail_expr_reachable ())
{
@@ -147,14 +244,22 @@ CompileBlock::visit (HIR::BlockExpr &expr)
Bexpression *compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx);
rust_assert (compiled_expr != nullptr);
- auto fncontext = ctx->peek_fn ();
+ if (result == nullptr)
+ {
+ Bstatement *final_stmt
+ = ctx->get_backend ()->expression_statement (fnctx.fndecl,
+ compiled_expr);
+ ctx->add_statement (final_stmt);
+ }
+ else
+ {
+ Bexpression *result_reference = ctx->get_backend ()->var_expression (
+ result, expr.get_final_expr ()->get_locus_slow ());
- std::vector<Bexpression *> retstmts;
- retstmts.push_back (compiled_expr);
- auto s
- = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts,
- expr.expr->get_locus_slow ());
- ctx->add_statement (s);
+ Bstatement *assignment = ctx->get_backend ()->assignment_statement (
+ fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ());
+ ctx->add_statement (assignment);
+ }
}
ctx->pop_block ();
@@ -168,7 +273,8 @@ CompileConditionalBlocks::visit (HIR::IfExpr &expr)
Bfunction *fndecl = fnctx.fndecl;
Bexpression *condition_expr
= CompileExpr::Compile (expr.get_if_condition (), ctx);
- Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx);
+ Bblock *then_block
+ = CompileBlock::compile (expr.get_if_block (), ctx, result);
translated
= ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block,
@@ -182,8 +288,10 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr)
Bfunction *fndecl = fnctx.fndecl;
Bexpression *condition_expr
= CompileExpr::Compile (expr.get_if_condition (), ctx);
- Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx);
- Bblock *else_block = CompileBlock::compile (expr.get_else_block (), ctx);
+ Bblock *then_block
+ = CompileBlock::compile (expr.get_if_block (), ctx, result);
+ Bblock *else_block
+ = CompileBlock::compile (expr.get_else_block (), ctx, result);
translated
= ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block,
@@ -197,7 +305,8 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr)
Bfunction *fndecl = fnctx.fndecl;
Bexpression *condition_expr
= CompileExpr::Compile (expr.get_if_condition (), ctx);
- Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx);
+ Bblock *then_block
+ = CompileBlock::compile (expr.get_if_block (), ctx, result);
// else block
std::vector<Bvariable *> locals;
@@ -210,7 +319,8 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr)
ctx->push_block (else_block);
Bstatement *else_stmt_decl
- = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx);
+ = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx,
+ result);
ctx->add_statement (else_stmt_decl);
ctx->pop_block ();
@@ -244,5 +354,64 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field)
translated = CompileExpr::Compile (&expr, ctx);
}
+// Shared methods in compilation
+
+void
+HIRCompileBase::compile_function_body (
+ Bfunction *fndecl, std::unique_ptr<HIR::BlockExpr> &function_body,
+ bool has_return_type)
+{
+ for (auto &s : function_body->get_statements ())
+ {
+ auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
+ if (compiled_expr != nullptr)
+ {
+ if (has_return_type)
+ {
+ std::vector<Bexpression *> retstmts;
+ retstmts.push_back (compiled_expr);
+
+ auto ret
+ = ctx->get_backend ()->return_statement (fndecl, retstmts,
+ s->get_locus_slow ());
+ ctx->add_statement (ret);
+ }
+ else
+ {
+ Bstatement *final_stmt
+ = ctx->get_backend ()->expression_statement (fndecl,
+ compiled_expr);
+ ctx->add_statement (final_stmt);
+ }
+ }
+ }
+
+ if (function_body->has_expr () && function_body->tail_expr_reachable ())
+ {
+ // the previous passes will ensure this is a valid return
+ // dead code elimination should remove any bad trailing expressions
+ Bexpression *compiled_expr
+ = CompileExpr::Compile (function_body->expr.get (), ctx);
+ rust_assert (compiled_expr != nullptr);
+
+ if (has_return_type)
+ {
+ std::vector<Bexpression *> retstmts;
+ retstmts.push_back (compiled_expr);
+
+ auto ret = ctx->get_backend ()->return_statement (
+ fndecl, retstmts,
+ function_body->get_final_expr ()->get_locus_slow ());
+ ctx->add_statement (ret);
+ }
+ else
+ {
+ Bstatement *final_stmt
+ = ctx->get_backend ()->expression_statement (fndecl, compiled_expr);
+ ctx->add_statement (final_stmt);
+ }
+ }
+}
+
} // namespace Compile
} // namespace Rust