Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add constant folding to const functions #870

Merged
merged 5 commits into from Jan 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions gcc/rust/Make-lang.in
Expand Up @@ -85,7 +85,6 @@ GRS_OBJS = \
rust/rust-tyty-bounds.o \
rust/rust-hir-type-check-util.o \
rust/rust-hir-trait-resolve.o \
rust/rust-hir-const-fold.o \
rust/rust-hir-type-check-type.o \
rust/rust-hir-type-check-struct.o \
rust/rust-hir-address-taken.o \
Expand All @@ -98,6 +97,7 @@ GRS_OBJS = \
rust/rust-base62.o \
rust/rust-compile-expr.o \
rust/rust-compile-type.o \
rust/rust-constexpr.o \
$(END)
# removed object files from here

Expand All @@ -107,7 +107,7 @@ RUST_ALL_OBJS = $(GRS_OBJS) $(RUST_TARGET_OBJS)
rust_OBJS = $(RUST_ALL_OBJS) rust/rustspec.o

# The compiler itself is called rust1 (formerly grs1)
rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)

Expand Down
7 changes: 6 additions & 1 deletion gcc/rust/ast/rust-item.h
Expand Up @@ -518,6 +518,11 @@ struct FunctionQualifiers
}

std::string as_string () const;

AsyncConstStatus get_const_status () const { return const_status; }
bool is_unsafe () const { return has_unsafe; }
bool is_extern () const { return has_extern; }
std::string get_extern_abi () const { return extern_abi; }
};

// A function parameter
Expand Down Expand Up @@ -1587,7 +1592,7 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
return function_body;
}

FunctionQualifiers get_qualifiers () const { return qualifiers; }
const FunctionQualifiers &get_qualifiers () const { return qualifiers; }

Identifier get_function_name () const { return function_name; }

Expand Down
11 changes: 7 additions & 4 deletions gcc/rust/backend/rust-compile-base.h
Expand Up @@ -37,15 +37,15 @@ class HIRCompileBase : public HIR::HIRFullVisitorBase

Context *get_context () { return ctx; }

void compile_function_body (tree fndecl,
std::unique_ptr<HIR::BlockExpr> &function_body,
void compile_function_body (tree fndecl, HIR::BlockExpr &function_body,
bool has_return_type);

bool compile_locals_for_block (Resolver::Rib &rib, tree fndecl,
std::vector<Bvariable *> &locals);

tree coercion_site (tree compiled_ref, TyTy::BaseType *actual,
TyTy::BaseType *expected, Location locus);
tree coercion_site (tree rvalue, TyTy::BaseType *actual,
TyTy::BaseType *expected, Location lvalue_locus,
Location rvalue_locus);

tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual,
const TyTy::BaseType *expected,
Expand All @@ -57,6 +57,9 @@ class HIRCompileBase : public HIR::HIRFullVisitorBase
std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>>
&receiver_bounds,
const TyTy::BaseType *receiver, const TyTy::BaseType *root, Location locus);

bool verify_array_capacities (tree ltype, tree rtype, Location ltype_locus,
Location rtype_locus);
};

} // namespace Compile
Expand Down
6 changes: 1 addition & 5 deletions gcc/rust/backend/rust-compile-context.h
Expand Up @@ -27,7 +27,6 @@
#include "rust-compile-tyty.h"
#include "rust-ast-full.h"
#include "rust-hir-full.h"
#include "rust-hir-const-fold-ctx.h"
#include "rust-mangle.h"

namespace Rust {
Expand All @@ -45,8 +44,7 @@ class Context
Context (::Backend *backend)
: backend (backend), resolver (Resolver::Resolver::get ()),
tyctx (Resolver::TypeCheckContext::get ()),
mappings (Analysis::Mappings::get ()),
const_ctx (ConstFold::Context::get ()), mangler (Mangler ())
mappings (Analysis::Mappings::get ()), mangler (Mangler ())
{
// insert the builtins
auto builtins = resolver->get_builtin_types ();
Expand Down Expand Up @@ -110,7 +108,6 @@ class Context
Resolver::Resolver *get_resolver () { return resolver; }
Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
Analysis::Mappings *get_mappings () { return mappings; }
ConstFold::Context *get_const_ctx () { return const_ctx; }

void push_block (tree scope)
{
Expand Down Expand Up @@ -315,7 +312,6 @@ class Context
Resolver::Resolver *resolver;
Resolver::TypeCheckContext *tyctx;
Analysis::Mappings *mappings;
ConstFold::Context *const_ctx;
std::set<HirId> builtin_range;
Mangler mangler;

Expand Down
235 changes: 232 additions & 3 deletions gcc/rust/backend/rust-compile-expr.cc
Expand Up @@ -25,10 +25,12 @@
#include "rust-hir-type-bounds.h"
#include "rust-hir-dot-operator.h"
#include "rust-compile-pattern.h"
#include "rust-constexpr.h"

#include "fold-const.h"
#include "realmpfr.h"
#include "convert.h"
#include "print-tree.h"

namespace Rust {
namespace Compile {
Expand Down Expand Up @@ -381,7 +383,11 @@ CompileExpr::visit (HIR::CallExpr &expr)
rust_assert (ok);

// coerce it if required
rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
Location lvalue_locus
= ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
Location rvalue_locus = argument->get_locus ();
rvalue = coercion_site (rvalue, actual, expected, lvalue_locus,
rvalue_locus);

// add it to the list
arguments.push_back (rvalue);
Expand Down Expand Up @@ -477,7 +483,11 @@ CompileExpr::visit (HIR::CallExpr &expr)
rust_assert (ok);

// coerce it if required
rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
Location lvalue_locus
= ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
Location rvalue_locus = argument->get_locus ();
rvalue
= coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus);

// add it to the list
args.push_back (rvalue);
Expand Down Expand Up @@ -604,7 +614,11 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
rust_assert (ok);

// coerce it if required
rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
Location lvalue_locus
= ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
Location rvalue_locus = argument->get_locus ();
rvalue
= coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus);

// add it to the list
args.push_back (rvalue);
Expand Down Expand Up @@ -1093,5 +1107,220 @@ CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree,
expr_tree);
}

void
CompileExpr::visit (HIR::ArrayExpr &expr)
{
TyTy::BaseType *tyty = nullptr;
if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
&tyty))
{
rust_fatal_error (expr.get_locus (),
"did not resolve type for this array expr");
return;
}

tree array_type = TyTyResolveCompile::compile (ctx, tyty);
if (TREE_CODE (array_type) != ARRAY_TYPE)
{
translated = error_mark_node;
return;
}

rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY);
const TyTy::ArrayType &array_tyty
= static_cast<const TyTy::ArrayType &> (*tyty);

HIR::ArrayElems &elements = *expr.get_internal_elements ();
switch (elements.get_array_expr_type ())
{
case HIR::ArrayElems::ArrayExprType::VALUES: {
HIR::ArrayElemsValues &elems
= static_cast<HIR::ArrayElemsValues &> (elements);
translated
= array_value_expr (expr.get_locus (), array_tyty, array_type, elems);
}
return;

case HIR::ArrayElems::ArrayExprType::COPIED:
HIR::ArrayElemsCopied &elems
= static_cast<HIR::ArrayElemsCopied &> (elements);
translated
= array_copied_expr (expr.get_locus (), array_tyty, array_type, elems);
}
}

tree
CompileExpr::array_value_expr (Location expr_locus,
const TyTy::ArrayType &array_tyty,
tree array_type, HIR::ArrayElemsValues &elems)
{
std::vector<unsigned long> indexes;
std::vector<tree> constructor;
size_t i = 0;
for (auto &elem : elems.get_values ())
{
tree translated_expr = CompileExpr::Compile (elem.get (), ctx);
constructor.push_back (translated_expr);
indexes.push_back (i++);
}

return ctx->get_backend ()->array_constructor_expression (array_type, indexes,
constructor,
expr_locus);
}

tree
CompileExpr::array_copied_expr (Location expr_locus,
const TyTy::ArrayType &array_tyty,
tree array_type, HIR::ArrayElemsCopied &elems)
{
// see gcc/cp/typeck2.c:1369-1401
gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
tree domain = TYPE_DOMAIN (array_type);
if (!domain)
return error_mark_node;

if (!TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
{
rust_error_at (expr_locus, "non const capacity domain %qT", array_type);
return error_mark_node;
}

tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx);
if (!TREE_CONSTANT (capacity_expr))
{
rust_error_at (expr_locus, "non const num copies %qT", array_type);
return error_mark_node;
}

// get the compiled value
tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx);

tree max_domain = TYPE_MAX_VALUE (domain);
tree min_domain = TYPE_MIN_VALUE (domain);

auto max = wi::to_offset (max_domain);
auto min = wi::to_offset (min_domain);
auto precision = TYPE_PRECISION (TREE_TYPE (domain));
auto sign = TYPE_SIGN (TREE_TYPE (domain));
unsigned HOST_WIDE_INT len
= wi::ext (max - min + 1, precision, sign).to_uhwi ();

// create the constructor
size_t idx = 0;
std::vector<unsigned long> indexes;
std::vector<tree> constructor;
for (unsigned HOST_WIDE_INT i = 0; i < len; i++)
{
constructor.push_back (translated_expr);
indexes.push_back (idx++);
}

return ctx->get_backend ()->array_constructor_expression (array_type, indexes,
constructor,
expr_locus);
}

// tree
// CompileExpr::array_copied_expr (Location expr_locus, tree array_type,
// HIR::ArrayElemsCopied &elems)
// {
// // create tmp for the result
// fncontext fnctx = ctx->peek_fn ();
// Location start_location = expr_locus;
// Location end_location = expr_locus;
// tree fndecl = fnctx.fndecl;
// tree enclosing_scope = ctx->peek_enclosing_scope ();

// bool is_address_taken = false;
// tree result_var_stmt = nullptr;
// Bvariable *result
// = ctx->get_backend ()->temporary_variable (fnctx.fndecl,
// enclosing_scope,
// array_type, NULL,
// is_address_taken, expr_locus,
// &result_var_stmt);
// ctx->add_statement (result_var_stmt);

// // get the compiled value
// tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (),
// ctx);

// // lets assign each index in the array
// TyTy::BaseType *capacity_tyty = nullptr;
// HirId capacity_ty_id
// = elems.get_num_copies_expr ()->get_mappings ().get_hirid ();
// bool ok = ctx->get_tyctx ()->lookup_type (capacity_ty_id,
// &capacity_tyty); rust_assert (ok); tree capacity_type =
// TyTyResolveCompile::compile (ctx, capacity_tyty); tree capacity_expr =
// CompileExpr::Compile (elems.get_num_copies_expr (), ctx);

// // create a loop for this with assignments to array_index exprs
// tree index_type = capacity_type;
// Bvariable *idx
// = ctx->get_backend ()->temporary_variable (fnctx.fndecl,
// enclosing_scope,
// index_type, NULL,
// is_address_taken, expr_locus,
// &result_var_stmt);
// ctx->add_statement (result_var_stmt);

// // set index to zero
// tree index_lvalue = error_mark_node;
// tree zero = build_int_cst (index_type, 0);
// tree index_assignment
// = ctx->get_backend ()->assignment_statement (fnctx.fndecl,
// index_lvalue,
// zero, expr_locus);
// ctx->add_statement (index_assignment);

// // BEGIN loop block
// tree loop_body = ctx->get_backend ()->block (fndecl, enclosing_scope, {},
// start_location, end_location);
// ctx->push_block (loop_body);

// // loop predicate
// tree loop_predicate
// = fold_build2_loc (expr_locus.gcc_location (), GE_EXPR,
// boolean_type_node,
// ctx->get_backend ()->var_expression (idx, expr_locus),
// capacity_expr);
// tree exit_expr = fold_build1_loc (expr_locus.gcc_location (), EXIT_EXPR,
// void_type_node, loop_predicate);
// tree break_stmt
// = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr);
// ctx->add_statement (break_stmt);

// // increment index
// tree increment
// = fold_build2_loc (expr_locus.gcc_location (), POSTINCREMENT_EXPR,
// index_type,
// ctx->get_backend ()->var_expression (idx, expr_locus),
// build_int_cst (index_type, 1));

// // create index_assess
// tree index_access = ctx->get_backend ()->array_index_expression (
// ctx->get_backend ()->var_expression (result, expr_locus), increment,
// expr_locus);

// // create assignment to index_access
// tree array_assignment
// = ctx->get_backend ()->assignment_statement (fnctx.fndecl,
// index_access,
// translated_expr, expr_locus);
// ctx->add_statement (array_assignment);

// // END loop block
// ctx->pop_block ();

// tree loop_expr = ctx->get_backend ()->loop_expression (loop_body,
// expr_locus); tree loop_stmt
// = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr);
// ctx->add_statement (loop_stmt);

// // result is the tmp
// return ctx->get_backend ()->var_expression (result, expr_locus);
// }

} // namespace Compile
} // namespace Rust