#include "stringpool.h"
#include "attribs.h"
#include "tree.h"
+#include "print-tree.h"
namespace Rust {
namespace Compile {
}
void
-HIRCompileBase::compile_function_body (Context *ctx, tree fndecl,
+HIRCompileBase::compile_function_body (tree fndecl,
HIR::BlockExpr &function_body,
- bool has_return_type)
+ TyTy::BaseType *fn_return_ty)
{
for (auto &s : function_body.get_statements ())
{
if (function_body.has_expr ())
{
- // the previous passes will ensure this is a valid return
- // or a valid trailing expression
- tree compiled_expr
- = CompileExpr::Compile (function_body.expr.get (), ctx);
+ Location locus = function_body.get_final_expr ()->get_locus ();
+ tree return_value = CompileExpr::Compile (function_body.expr.get (), ctx);
- if (compiled_expr != nullptr)
+ // we can only return this if non unit value return type
+ if (!fn_return_ty->is_unit ())
{
- if (has_return_type)
- {
- std::vector<tree> retstmts;
- retstmts.push_back (compiled_expr);
-
- auto ret = ctx->get_backend ()->return_statement (
- fndecl, retstmts,
- function_body.get_final_expr ()->get_locus ());
- ctx->add_statement (ret);
- }
- else
- {
- // FIXME can this actually happen?
- ctx->add_statement (compiled_expr);
- }
+ tree return_stmt
+ = ctx->get_backend ()->return_statement (fndecl, return_value,
+ locus);
+ ctx->add_statement (return_stmt);
}
+ else
+ {
+ // just add the stmt expression
+ ctx->add_statement (return_value);
+
+ // now just return unit expression
+ tree unit_expr = unit_expression (ctx, locus);
+ tree return_stmt
+ = ctx->get_backend ()->return_statement (fndecl, unit_expr, locus);
+ ctx->add_statement (return_stmt);
+ }
+ }
+ else if (fn_return_ty->is_unit ())
+ {
+ // we can only do this if the function is of unit type otherwise other
+ // errors should have occurred
+ Location locus = function_body.get_locus ();
+ tree return_value = unit_expression (ctx, locus);
+ tree return_stmt
+ = ctx->get_backend ()->return_statement (fndecl, return_value, locus);
+ ctx->add_statement (return_stmt);
}
}
tree
HIRCompileBase::compile_function (
- Context *ctx, const std::string &fn_name, HIR::SelfParam &self_param,
+ const std::string &fn_name, HIR::SelfParam &self_param,
std::vector<HIR::FunctionParam> &function_params,
const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility,
AST::AttrVec &outer_attrs, Location locus, HIR::BlockExpr *function_body,
- const Resolver::CanonicalPath *canonical_path, TyTy::FnType *fntype,
- bool function_has_return)
+ const Resolver::CanonicalPath *canonical_path, TyTy::FnType *fntype)
{
tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
std::string ir_symbol_name
ctx->push_block (code_block);
Bvariable *return_address = nullptr;
- if (function_has_return)
- {
- tree return_type = TyTyResolveCompile::compile (ctx, tyret);
-
- bool address_is_taken = false;
- tree ret_var_stmt = NULL_TREE;
+ tree return_type = TyTyResolveCompile::compile (ctx, tyret);
- return_address
- = ctx->get_backend ()->temporary_variable (fndecl, code_block,
- return_type, NULL,
- address_is_taken, locus,
- &ret_var_stmt);
+ bool address_is_taken = false;
+ tree ret_var_stmt = NULL_TREE;
+ return_address
+ = ctx->get_backend ()->temporary_variable (fndecl, code_block, return_type,
+ NULL, address_is_taken, locus,
+ &ret_var_stmt);
- ctx->add_statement (ret_var_stmt);
- }
+ ctx->add_statement (ret_var_stmt);
ctx->push_fn (fndecl, return_address);
- compile_function_body (ctx, fndecl, *function_body, function_has_return);
+ compile_function_body (fndecl, *function_body, tyret);
tree bind_tree = ctx->pop_block ();
gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
tree
HIRCompileBase::compile_constant_item (
- Context *ctx, TyTy::BaseType *resolved_type,
- const Resolver::CanonicalPath *canonical_path, HIR::Expr *const_value_expr,
- Location locus)
+ TyTy::BaseType *resolved_type, const Resolver::CanonicalPath *canonical_path,
+ HIR::Expr *const_value_expr, Location locus)
{
const std::string &ident = canonical_path->get ();
+
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
tree const_type = build_qualified_type (type, TYPE_QUAL_CONST);
-
bool is_block_expr
= const_value_expr->get_expression_type () == HIR::Expr::ExprType::Block;
tree compiled_fn_type = ctx->get_backend ()->function_type (
receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL,
locus);
-
tree fndecl
= ctx->get_backend ()->function (compiled_fn_type, ident, "", 0, locus);
TREE_READONLY (fndecl) = 1;
{
HIR::BlockExpr *function_body
= static_cast<HIR::BlockExpr *> (const_value_expr);
- compile_function_body (ctx, fndecl, *function_body, true);
+ compile_function_body (fndecl, *function_body, resolved_type);
}
else
{
tree value = CompileExpr::Compile (const_value_expr, ctx);
+
tree return_expr = ctx->get_backend ()->return_statement (
- fndecl, {value}, const_value_expr->get_locus ());
+ fndecl, value, const_value_expr->get_locus ());
ctx->add_statement (return_expr);
}
return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
}
+tree
+HIRCompileBase::unit_expression (Context *ctx, Location locus)
+{
+ tree unit_type = TyTyResolveCompile::get_unit_type (ctx);
+ return ctx->get_backend ()->constructor_expression (unit_type, false, {}, -1,
+ locus);
+}
+
} // namespace Compile
} // namespace Rust
const Analysis::NodeMapping &expr_mappings,
Location expr_locus);
+ void compile_function_body (tree fndecl, HIR::BlockExpr &function_body,
+ TyTy::BaseType *fn_return_ty);
+
+ tree compile_constant_item (TyTy::BaseType *resolved_type,
+ const Resolver::CanonicalPath *canonical_path,
+ HIR::Expr *const_value_expr, Location locus);
+
+ tree compile_function (const std::string &fn_name, HIR::SelfParam &self_param,
+ std::vector<HIR::FunctionParam> &function_params,
+ const HIR::FunctionQualifiers &qualifiers,
+ HIR::Visibility &visibility, AST::AttrVec &outer_attrs,
+ Location locus, HIR::BlockExpr *function_body,
+ const Resolver::CanonicalPath *canonical_path,
+ TyTy::FnType *fntype);
+
+ static tree unit_expression (Context *ctx, Location locus);
+
static void setup_fndecl (tree fndecl, bool is_main_entry_point,
bool is_generic_fn, HIR::Visibility &visibility,
const HIR::FunctionQualifiers &qualifiers,
static std::vector<Bvariable *>
compile_locals_for_block (Context *ctx, Resolver::Rib &rib, tree fndecl);
- static void compile_function_body (Context *ctx, tree fndecl,
- HIR::BlockExpr &function_body,
- bool has_return_type);
-
- static tree compile_function (
- Context *ctx, const std::string &fn_name, HIR::SelfParam &self_param,
- std::vector<HIR::FunctionParam> &function_params,
- const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility,
- AST::AttrVec &outer_attrs, Location locus, HIR::BlockExpr *function_body,
- const Resolver::CanonicalPath *canonical_path, TyTy::FnType *fntype,
- bool function_has_return);
-
- static tree
- compile_constant_item (Context *ctx, TyTy::BaseType *resolved_type,
- const Resolver::CanonicalPath *canonical_path,
- HIR::Expr *const_value_expr, Location locus);
-
static tree named_constant_expression (tree type_tree,
const std::string &name,
tree const_val, Location location);
if (expr.has_expr ())
{
- // the previous passes will ensure this is a valid return or
- // a valid trailing expression
tree compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx);
- if (compiled_expr != nullptr)
+ if (result != nullptr)
{
- if (result == nullptr)
- {
- ctx->add_statement (compiled_expr);
- }
- else
- {
- tree result_reference = ctx->get_backend ()->var_expression (
- result, expr.get_final_expr ()->get_locus ());
-
- tree assignment
- = ctx->get_backend ()->assignment_statement (result_reference,
- compiled_expr,
- expr.get_locus ());
- ctx->add_statement (assignment);
- }
+ Location locus = expr.get_final_expr ()->get_locus ();
+ tree result_reference
+ = ctx->get_backend ()->var_expression (result, locus);
+
+ tree assignment
+ = ctx->get_backend ()->assignment_statement (result_reference,
+ compiled_expr,
+ expr.get_locus ());
+ ctx->add_statement (assignment);
}
}
+ else if (result != nullptr)
+ {
+ Location locus = expr.get_locus ();
+ tree compiled_expr = unit_expression (ctx, expr.get_locus ());
+ tree result_reference
+ = ctx->get_backend ()->var_expression (result, locus);
+
+ tree assignment
+ = ctx->get_backend ()->assignment_statement (result_reference,
+ compiled_expr,
+ expr.get_locus ());
+ ctx->add_statement (assignment);
+ }
ctx->pop_block ();
translated = new_block;
{
if (expr.is_unit ())
{
- translated = ctx->get_backend ()->unit_expression ();
+ translated = unit_expression (ctx, expr.get_locus ());
return;
}
{
auto fncontext = ctx->peek_fn ();
- std::vector<tree> retstmts;
- if (expr.has_return_expr ())
- {
- tree compiled_expr = CompileExpr::Compile (expr.return_expr.get (), ctx);
- rust_assert (compiled_expr != nullptr);
-
- retstmts.push_back (compiled_expr);
- }
-
- auto s = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts,
- expr.get_locus ());
- ctx->add_statement (s);
+ tree return_value = expr.has_return_expr ()
+ ? CompileExpr::Compile (expr.return_expr.get (), ctx)
+ : unit_expression (ctx, expr.get_locus ());
+ tree return_stmt
+ = ctx->get_backend ()->return_statement (fncontext.fndecl, return_value,
+ expr.get_locus ());
+ ctx->add_statement (return_stmt);
}
void
}
Bvariable *tmp = NULL;
- bool needs_temp = !if_type->is_unit ();
- if (needs_temp)
- {
- fncontext fnctx = ctx->peek_fn ();
- tree enclosing_scope = ctx->peek_enclosing_scope ();
- tree block_type = TyTyResolveCompile::compile (ctx, if_type);
+ fncontext fnctx = ctx->peek_fn ();
+ tree enclosing_scope = ctx->peek_enclosing_scope ();
+ tree block_type = TyTyResolveCompile::compile (ctx, if_type);
- bool is_address_taken = false;
- tree ret_var_stmt = nullptr;
- 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);
- }
+ bool is_address_taken = false;
+ tree ret_var_stmt = nullptr;
+ 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);
- if (tmp != NULL)
- {
- translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
- }
+ translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
}
void
}
Bvariable *tmp = NULL;
- bool needs_temp = !block_tyty->is_unit ();
- if (needs_temp)
- {
- fncontext fnctx = ctx->peek_fn ();
- tree enclosing_scope = ctx->peek_enclosing_scope ();
- tree block_type = TyTyResolveCompile::compile (ctx, block_tyty);
+ fncontext fnctx = ctx->peek_fn ();
+ tree enclosing_scope = ctx->peek_enclosing_scope ();
+ tree block_type = TyTyResolveCompile::compile (ctx, block_tyty);
- bool is_address_taken = false;
- tree ret_var_stmt = nullptr;
- 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);
- }
+ bool is_address_taken = false;
+ tree ret_var_stmt = nullptr;
+ 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 block_stmt = CompileBlock::compile (&expr, ctx, tmp);
rust_assert (TREE_CODE (block_stmt) == BIND_EXPR);
ctx->add_statement (block_stmt);
- if (tmp != NULL)
- {
- translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
- }
+ translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
}
void
}
rust_assert (tyty->is_unit ());
- translated = ctx->get_backend ()->unit_expression ();
+ translated = unit_expression (ctx, struct_expr.get_locus ());
}
void
fncontext fnctx = ctx->peek_fn ();
Bvariable *tmp = NULL;
- bool needs_temp = !expr_tyty->is_unit ();
- if (needs_temp)
- {
- tree enclosing_scope = ctx->peek_enclosing_scope ();
- tree block_type = TyTyResolveCompile::compile (ctx, expr_tyty);
+ tree enclosing_scope = ctx->peek_enclosing_scope ();
+ tree block_type = TyTyResolveCompile::compile (ctx, expr_tyty);
- bool is_address_taken = false;
- tree ret_var_stmt = nullptr;
- 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);
- }
+ bool is_address_taken = false;
+ tree ret_var_stmt = nullptr;
+ 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);
// lets compile the scrutinee expression
tree match_scrutinee_expr
// setup the switch-body-block
Location start_location; // FIXME
Location end_location; // FIXME
- tree enclosing_scope = ctx->peek_enclosing_scope ();
tree switch_body_block
= ctx->get_backend ()->block (fndecl, enclosing_scope, {}, start_location,
end_location);
// compile the expr and setup the assignment if required when tmp != NULL
tree kase_expr_tree = CompileExpr::Compile (kase.get_expr ().get (), ctx);
- if (tmp != NULL)
- {
- tree result_reference
- = ctx->get_backend ()->var_expression (tmp, arm_locus);
- tree assignment
- = ctx->get_backend ()->assignment_statement (result_reference,
- kase_expr_tree,
- arm_locus);
- ctx->add_statement (assignment);
- }
+ tree result_reference
+ = ctx->get_backend ()->var_expression (tmp, arm_locus);
+ tree assignment
+ = ctx->get_backend ()->assignment_statement (result_reference,
+ kase_expr_tree, arm_locus);
+ ctx->add_statement (assignment);
// go to end label
tree goto_end_label = build1_loc (arm_locus.gcc_location (), GOTO_EXPR,
ctx->add_statement (match_expr_stmt);
ctx->add_statement (end_label_decl_statement);
- if (tmp != NULL)
- {
- translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
- }
+ translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
}
void
ctx->push_block (code_block);
TyTy::BaseType *tyret = &closure_tyty.get_result_type ();
- bool function_has_return = !closure_tyty.get_result_type ().is_unit ();
Bvariable *return_address = nullptr;
- if (function_has_return)
- {
- tree return_type = TyTyResolveCompile::compile (ctx, tyret);
- bool address_is_taken = false;
- tree ret_var_stmt = NULL_TREE;
+ tree return_type = TyTyResolveCompile::compile (ctx, tyret);
+ bool address_is_taken = false;
+ tree ret_var_stmt = NULL_TREE;
- return_address = ctx->get_backend ()->temporary_variable (
- fndecl, code_block, return_type, NULL, address_is_taken,
- expr.get_locus (), &ret_var_stmt);
+ return_address
+ = ctx->get_backend ()->temporary_variable (fndecl, code_block, return_type,
+ NULL, address_is_taken,
+ expr.get_locus (),
+ &ret_var_stmt);
- ctx->add_statement (ret_var_stmt);
- }
+ ctx->add_statement (ret_var_stmt);
ctx->push_fn (fndecl, return_address);
if (is_block_expr)
{
HIR::BlockExpr *body = static_cast<HIR::BlockExpr *> (function_body);
- compile_function_body (ctx, fndecl, *body, true);
+ compile_function_body (fndecl, *body, tyret);
}
else
{
tree value = CompileExpr::Compile (function_body, ctx);
tree return_expr
- = ctx->get_backend ()->return_statement (fndecl, {value},
+ = ctx->get_backend ()->return_statement (fndecl, value,
function_body->get_locus ());
ctx->add_statement (return_expr);
}
// <http://www.gnu.org/licenses/>.
#include "rust-compile-implitem.h"
-#include "rust-compile-expr.h"
-#include "rust-compile-fnparam.h"
namespace Rust {
namespace Compile {
HIR::Expr *const_value_expr = constant.get_expr ().get ();
tree const_expr
- = compile_constant_item (ctx, resolved_type, canonical_path,
- const_value_expr, constant.get_locus ());
+ = compile_constant_item (resolved_type, canonical_path, const_value_expr,
+ constant.get_locus ());
ctx->push_const (const_expr);
ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr);
auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC);
HIR::TraitFunctionDecl &function = func.get_decl ();
tree fndecl
- = compile_function (ctx, function.get_function_name (),
- function.get_self (), function.get_function_params (),
+ = compile_function (function.get_function_name (), function.get_self (),
+ function.get_function_params (),
function.get_qualifiers (), vis,
func.get_outer_attrs (), func.get_locus (),
- func.get_block_expr ().get (), canonical_path, fntype,
- function.has_return_type ());
+ func.get_block_expr ().get (), canonical_path, fntype);
reference = address_expression (fndecl, ref_locus);
}
HIR::Expr *const_value_expr = var.get_expr ();
ctx->push_const_context ();
- tree value = compile_constant_item (ctx, resolved_type, canonical_path,
+ tree value = compile_constant_item (resolved_type, canonical_path,
const_value_expr, var.get_locus ());
ctx->pop_const_context ();
HIR::Expr *const_value_expr = constant.get_expr ();
ctx->push_const_context ();
tree const_expr
- = compile_constant_item (ctx, resolved_type, canonical_path,
- const_value_expr, constant.get_locus ());
+ = compile_constant_item (resolved_type, canonical_path, const_value_expr,
+ constant.get_locus ());
ctx->pop_const_context ();
ctx->push_const (const_expr);
ctx->push_const_context ();
tree fndecl
- = compile_function (ctx, function.get_function_name (),
+ = compile_function (function.get_function_name (),
function.get_self_param (),
function.get_function_params (),
function.get_qualifiers (), function.get_visibility (),
function.get_outer_attrs (), function.get_locus (),
function.get_definition ().get (), canonical_path,
- fntype, function.has_function_return_type ());
+ fntype);
reference = address_expression (fndecl, ref_locus);
if (function.get_qualifiers ().is_const ())
{
ctx->add_statement (init_expr);
- tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
-
- auto unit_type_init_expr
- = ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
- rval_locus);
+ auto unit_type_init_expr = unit_expression (ctx, rval_locus);
auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
unit_type_init_expr);
ctx->add_statement (s);
return error_mark_node;
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
-
- // it might be a unit-struct
if (adt->is_unit ())
- {
- return ctx->get_backend ()->unit_expression ();
- }
+ return unit_expression (ctx, expr_locus);
if (!adt->is_enum ())
return error_mark_node;
return enum_node;
}
+tree
+TyTyResolveCompile::get_unit_type (Context *ctx)
+{
+ static tree unit_type;
+ if (unit_type == nullptr)
+ {
+ auto unit_type_node = ctx->get_backend ()->struct_type ({});
+ unit_type
+ = ctx->get_backend ()->named_type ("()", unit_type_node,
+ Linemap::predeclared_location ());
+ }
+ return unit_type;
+}
+
void
TyTyResolveCompile::visit (const TyTy::ErrorType &)
{
std::vector<Backend::typed_identifier> parameters;
std::vector<Backend::typed_identifier> results;
- if (!type.get_return_type ()->is_unit ())
- {
- auto hir_type = type.get_return_type ();
- auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
- results.push_back (Backend::typed_identifier (
- "_", ret,
- ctx->get_mappings ()->lookup_location (hir_type->get_ref ())));
- }
+ auto hir_type = type.get_return_type ();
+ auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
+ Location return_type_locus
+ = ctx->get_mappings ()->lookup_location (hir_type->get_ref ());
+ results.push_back (Backend::typed_identifier ("_", ret, return_type_locus));
for (auto ¶m_pair : type.get_params ())
{
{
if (type.num_fields () == 0)
{
- translated = ctx->get_backend ()->unit_type ();
+ translated = get_unit_type (ctx);
return;
}
void
TyTyResolveCompile::visit (const TyTy::NeverType &)
{
- translated = ctx->get_backend ()->unit_type ();
+ translated = get_unit_type (ctx);
}
void
static tree get_implicit_enumeral_node_type (Context *ctx);
+ static tree get_unit_type (Context *ctx);
+
void visit (const TyTy::InferType &) override;
void visit (const TyTy::ADTType &) override;
void visit (const TyTy::TupleType &) override;
/* Don't VERIFY_CONSTANT here. */
if (*non_constant_p)
return t;
- gcc_checking_assert (TREE_CODE (op) != CONSTRUCTOR);
/* This function does more aggressive folding than fold itself. */
r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
if (TREE_CODE (r) == ADDR_EXPR && TREE_OPERAND (r, 0) == oldop)
// Types.
- // get unit-type
- virtual tree unit_type () = 0;
-
// Get the unnamed boolean type.
virtual tree bool_type () = 0;
// converting nil to other types.
virtual tree zero_expression (tree) = 0;
- virtual tree unit_expression () = 0;
-
// Create a reference to a variable.
virtual tree var_expression (Bvariable *var, Location) = 0;
// Create an assignment statement within the specified function.
virtual tree assignment_statement (tree lhs, tree rhs, Location) = 0;
- // Create a return statement, passing the representation of the
- // function and the list of values to return.
- virtual tree return_statement (tree, const std::vector<tree> &, Location) = 0;
+ // Create return statement for an decl for a value (can be NULL_TREE) at a
+ // location
+ virtual tree return_statement (tree fndecl, tree val, Location) = 0;
// Create an if statement within a function. ELSE_BLOCK may be NULL.
virtual tree if_statement (tree, tree condition, tree then_block,
// Types.
- tree unit_type ()
- {
- static tree unit_type;
- if (unit_type == nullptr)
- {
- auto unit_type_node = struct_type ({});
- unit_type = named_type ("()", unit_type_node,
- ::Linemap::predeclared_location ());
- }
-
- return unit_type;
- }
-
tree bool_type () { return boolean_type_node; }
tree char_type () { return char_type_node; }
tree zero_expression (tree);
- tree unit_expression () { return integer_zero_node; }
-
tree var_expression (Bvariable *var, Location);
tree integer_constant_expression (tree type, mpz_t val);
tree assignment_statement (tree lhs, tree rhs, Location);
- tree return_statement (tree, const std::vector<tree> &, Location);
+ tree return_statement (tree fndecl, tree val, Location locus);
tree if_statement (tree, tree condition, tree then_block, tree else_block,
Location);
if (result == error_mark_node)
return error_mark_node;
- // The libffi library cannot represent a zero-sized object. To
- // avoid causing confusion on 32-bit SPARC, we treat a function that
- // returns a zero-sized value as returning void. That should do no
- // harm since there is no actual value to be returned. See
- // https://gcc.gnu.org/PR72814 for details.
- if (result != void_type_node && int_size_in_bytes (result) == 0)
- result = void_type_node;
-
tree fntype = build_function_type (result, args);
if (fntype == error_mark_node)
return error_mark_node;
if (result == error_mark_node)
return error_mark_node;
- // The libffi library cannot represent a zero-sized object. To
- // avoid causing confusion on 32-bit SPARC, we treat a function that
- // returns a zero-sized value as returning void. That should do no
- // harm since there is no actual value to be returned. See
- // https://gcc.gnu.org/PR72814 for details.
- if (result != void_type_node && int_size_in_bytes (result) == 0)
- result = void_type_node;
-
tree fntype = build_varargs_function_type_array (result, n, args);
if (fntype == error_mark_node)
return error_mark_node;
// Return.
tree
-Gcc_backend::return_statement (tree fntree, const std::vector<tree> &vals,
- Location location)
+Gcc_backend::return_statement (tree fntree, tree val, Location location)
{
if (fntree == error_mark_node)
return error_mark_node;
+
tree result = DECL_RESULT (fntree);
if (result == error_mark_node)
return error_mark_node;
- // If the result size is zero bytes, we have set the function type
- // to have a result type of void, so don't return anything.
- // See the function_type method.
- tree res_type = TREE_TYPE (result);
- if (res_type == void_type_node || int_size_in_bytes (res_type) == 0)
- {
- tree stmt_list = NULL_TREE;
- for (std::vector<tree>::const_iterator p = vals.begin ();
- p != vals.end (); p++)
- {
- tree val = (*p);
- if (val == error_mark_node)
- return error_mark_node;
- append_to_statement_list (val, &stmt_list);
- }
- tree ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR,
- void_type_node, NULL_TREE);
- append_to_statement_list (ret, &stmt_list);
- return stmt_list;
- }
-
- tree ret;
- if (vals.empty ())
- ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR,
- void_type_node, NULL_TREE);
- else if (vals.size () == 1)
- {
- tree val = vals.front ();
- if (val == error_mark_node)
- return error_mark_node;
- tree set = fold_build2_loc (location.gcc_location (), MODIFY_EXPR,
- void_type_node, result, vals.front ());
- ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR,
- void_type_node, set);
- }
- else
- {
- // To return multiple values, copy the values into a temporary
- // variable of the right structure type, and then assign the
- // temporary variable to the DECL_RESULT in the return
- // statement.
- tree stmt_list = NULL_TREE;
- tree rettype = TREE_TYPE (result);
-
- if (DECL_STRUCT_FUNCTION (fntree) == NULL)
- push_struct_function (fntree);
- else
- push_cfun (DECL_STRUCT_FUNCTION (fntree));
- tree rettmp = create_tmp_var (rettype, "RESULT");
- pop_cfun ();
+ if (val == error_mark_node)
+ return error_mark_node;
- tree field = TYPE_FIELDS (rettype);
- for (std::vector<tree>::const_iterator p = vals.begin ();
- p != vals.end (); p++, field = DECL_CHAIN (field))
- {
- gcc_assert (field != NULL_TREE);
- tree ref
- = fold_build3_loc (location.gcc_location (), COMPONENT_REF,
- TREE_TYPE (field), rettmp, field, NULL_TREE);
- tree val = (*p);
- if (val == error_mark_node)
- return error_mark_node;
- tree set = fold_build2_loc (location.gcc_location (), MODIFY_EXPR,
- void_type_node, ref, (*p));
- append_to_statement_list (set, &stmt_list);
- }
- gcc_assert (field == NULL_TREE);
- tree set = fold_build2_loc (location.gcc_location (), MODIFY_EXPR,
- void_type_node, result, rettmp);
- tree ret_expr = fold_build1_loc (location.gcc_location (), RETURN_EXPR,
- void_type_node, set);
- append_to_statement_list (ret_expr, &stmt_list);
- ret = stmt_list;
- }
- return ret;
+ auto locus = location.gcc_location ();
+ tree set = fold_build2_loc (locus, MODIFY_EXPR, void_type_node, result, val);
+ return fold_build1_loc (locus, RETURN_EXPR, void_type_node, set);
}
// Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an
--- /dev/null
+static _V: () = {};