diff options
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r-- | gcc/rust/backend/rust-compile-context.h | 15 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 57 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-item.cc | 2 |
3 files changed, 63 insertions, 11 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 4bade5c..de9d03f 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -250,6 +250,10 @@ public: fn_stack.push_back (fncontext{fn, ret_addr}); } void pop_fn () { fn_stack.pop_back (); } + + bool in_fn () { return fn_stack.size () != 0; } + + // Note: it is undefined behavior to call peek_fn () if fn_stack is empty. fncontext peek_fn () { return fn_stack.back (); } void push_type (tree t) { type_decls.push_back (t); } @@ -301,6 +305,14 @@ public: return pop; } + void push_const_context (void) { const_context++; } + void pop_const_context (void) + { + if (const_context > 0) + const_context--; + } + bool const_context_p (void) { return (const_context > 0); } + std::string mangle_item (const TyTy::BaseType *ty, const Resolver::CanonicalPath &path) const { @@ -341,6 +353,9 @@ private: std::vector<::Bvariable *> var_decls; std::vector<tree> const_decls; std::vector<tree> func_decls; + + // Nonzero iff we are currently compiling something inside a constant context. + unsigned int const_context = 0; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 74ab6a4..49a6f2f 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1163,19 +1163,54 @@ CompileExpr::array_copied_expr (Location expr_locus, 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++); + // In a const context we must initialize the entire array, which entails + // allocating for each element. If the user wants a huge array, we will OOM + // and die horribly. + if (ctx->const_context_p ()) + { + 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); } - return ctx->get_backend ()->array_constructor_expression (array_type, indexes, - constructor, - expr_locus); + else + { + // Create a new block scope in which to initialize the array + tree fndecl = NULL_TREE; + if (ctx->in_fn ()) + fndecl = ctx->peek_fn ().fndecl; + + std::vector<Bvariable *> locals; + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree init_block + = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + expr_locus, expr_locus); + ctx->push_block (init_block); + + tree tmp; + tree stmts + = ctx->get_backend ()->array_initializer (fndecl, init_block, + array_type, capacity_expr, + translated_expr, &tmp, + expr_locus); + ctx->add_statement (stmts); + + tree block = ctx->pop_block (); + + // The result is a compound expression which creates a temporary array, + // initializes all the elements in a loop, and then yeilds the array. + return ctx->get_backend ()->compound_expression (block, tmp, expr_locus); + } } tree diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 21cbb1c..80b7ceb 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -92,9 +92,11 @@ CompileItem::visit (HIR::ConstantItem &constant) rust_assert (ok); 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 ()); + ctx->pop_const_context (); ctx->push_const (const_expr); ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); |