aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/hir
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-01-14 15:49:07 +0000
committerGitHub <noreply@github.com>2022-01-14 15:49:07 +0000
commitb21caeb3af4313016afeb94a91956e8fc4c2656d (patch)
tree03b1cac2b3442af423cd565b0168682e6d4541b3 /gcc/rust/hir
parent03e56b5181506a4e6cdb9fe86c543a57840e54c3 (diff)
parent93554f3bce5bd42d8671559a774818767979cdae (diff)
downloadgcc-b21caeb3af4313016afeb94a91956e8fc4c2656d.zip
gcc-b21caeb3af4313016afeb94a91956e8fc4c2656d.tar.gz
gcc-b21caeb3af4313016afeb94a91956e8fc4c2656d.tar.bz2
Merge #870
870: Add constant folding to const functions r=philberty a=philberty In Rust the ArrayType has a constant capacity constraint, which means it allows for bounds checking at compile time as no variable-length arrays are allowed. In order to typecheck this case we had a constant folding pass as part of the type checking system which generated gcc tree's for the IR and enforced the constant checking along the way. GCC with optimizations turned on is capable of constant folding/propogating the compilation unit fully, but we need a method that works regardless of middlle-end optimizations to fold constant expressions at the front-end, turns out the CPP front-end already does this via its constexpr mechanism to ensure that these _do_ fold correctly. Another major reason to do this change is that the original const fold pass was a striped down copy of what the backend is _already_ doing which is creating a duplication of the code generation pass. With this all unified into the code generation pass all we need to do is port over gcc/cp/constexpr.c to enforce the const rules fully but at the GCC tree level not at the typed HIR level. Now that we have unified the pass when we hit a const function we can simply emit a normal GCC function and outside of const expressions GCC will simply emit a normal CallExpr and depending on optimization level fully optimize this. If we are in a ConstDecl we will follow the rust-constexpr.cc and fold the values or error_mark_node with an apropriate error. By reusing the CPP constexpr code we _know_ it works so reusing it as much as possible is a good idea in general for this front-end. Fixes #799 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/hir')
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h3
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h5
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc28
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h170
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h6
-rw-r--r--gcc/rust/hir/tree/rust-hir.h69
6 files changed, 232 insertions, 49 deletions
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 457ca1d..047d531 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -278,6 +278,9 @@ protected:
HIR::QualifiedPathType
lower_qual_path_type (AST::QualifiedPathType &qual_path_type);
+
+ HIR::FunctionQualifiers
+ lower_qualifiers (const AST::FunctionQualifiers &qualifiers);
};
} // namespace HIR
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 60315db..af9e129 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -429,8 +429,8 @@ public:
}
HIR::WhereClause where_clause (std::move (where_clause_items));
- HIR::FunctionQualifiers qualifiers (
- HIR::FunctionQualifiers::AsyncConstStatus::NONE, Unsafety::Normal);
+ HIR::FunctionQualifiers qualifiers
+ = lower_qualifiers (function.get_qualifiers ());
HIR::Visibility vis = HIR::Visibility::create_public ();
// need
@@ -439,7 +439,6 @@ public:
{
generic_params = lower_generic_params (function.get_generic_params ());
}
-
Identifier function_name = function.get_function_name ();
Location locus = function.get_locus ();
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index d8d53eb..326412b 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -593,5 +593,33 @@ struct_field_name_exists (std::vector<HIR::StructField> &fields,
return false;
}
+HIR::FunctionQualifiers
+ASTLoweringBase::lower_qualifiers (const AST::FunctionQualifiers &qualifiers)
+{
+ HIR::FunctionQualifiers::AsyncConstStatus const_status;
+ switch (qualifiers.get_const_status ())
+ {
+ case AST::FunctionQualifiers::AsyncConstStatus::NONE:
+ const_status = HIR::FunctionQualifiers::AsyncConstStatus::NONE;
+ break;
+ case AST::FunctionQualifiers::AsyncConstStatus::CONST:
+ const_status = HIR::FunctionQualifiers::AsyncConstStatus::CONST;
+ break;
+ case AST::FunctionQualifiers::AsyncConstStatus::ASYNC:
+ const_status = HIR::FunctionQualifiers::AsyncConstStatus::ASYNC;
+ break;
+ }
+
+ Unsafety unsafety
+ = qualifiers.is_unsafe () ? Unsafety::Unsafe : Unsafety::Normal;
+ bool has_extern = qualifiers.is_extern ();
+
+ // FIXME turn this into the Rust::ABI enum
+ std::string extern_abi = qualifiers.get_extern_abi ();
+
+ return HIR::FunctionQualifiers (const_status, unsafety, has_extern,
+ extern_abi);
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index c1495d4..1d7d528 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -47,14 +47,17 @@ protected:
return clone_expr_with_block_impl ();
}
- bool is_expr_without_block () const final override { return false; };
-
public:
// Unique pointer custom clone function
std::unique_ptr<ExprWithBlock> clone_expr_with_block () const
{
return std::unique_ptr<ExprWithBlock> (clone_expr_with_block_impl ());
}
+
+ BlockType get_block_expr_type () const final override
+ {
+ return BlockType::WITH_BLOCK;
+ };
};
// Literals? Or literal base?
@@ -98,6 +101,8 @@ public:
Literal &get_literal () { return literal; }
const Literal &get_literal () const { return literal; }
+ ExprType get_expression_type () const override final { return ExprType::Lit; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -167,6 +172,11 @@ public:
Location get_locus () const override final { return locus; }
std::unique_ptr<Expr> &get_expr () { return main_or_left_expr; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Operator;
+ }
};
/* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be
@@ -795,6 +805,11 @@ public:
return expr_in_parens;
}
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Grouped;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -816,6 +831,12 @@ protected:
class ArrayElems
{
public:
+ enum ArrayExprType
+ {
+ VALUES,
+ COPIED,
+ };
+
virtual ~ArrayElems () {}
// Unique pointer custom clone ArrayElems function
@@ -828,6 +849,8 @@ public:
virtual void accept_vis (HIRFullVisitor &vis) = 0;
+ virtual ArrayExprType get_array_expr_type () const = 0;
+
protected:
// pure virtual clone implementation
virtual ArrayElems *clone_array_elems_impl () const = 0;
@@ -875,6 +898,11 @@ public:
std::vector<std::unique_ptr<Expr> > &get_values () { return values; }
+ ArrayElems::ArrayExprType get_array_expr_type () const override final
+ {
+ return ArrayElems::ArrayExprType::VALUES;
+ }
+
protected:
ArrayElemsValues *clone_array_elems_impl () const override
{
@@ -923,6 +951,11 @@ public:
Expr *get_num_copies_expr () { return num_copies.get (); }
+ ArrayElems::ArrayExprType get_array_expr_type () const override final
+ {
+ return ArrayElems::ArrayExprType::COPIED;
+ }
+
protected:
ArrayElemsCopied *clone_array_elems_impl () const override
{
@@ -988,6 +1021,11 @@ public:
ArrayElems *get_internal_elements () { return internal_elements.get (); };
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Array;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1001,11 +1039,6 @@ protected:
}
};
-// Aka IndexExpr (also applies to slices)
-/* Apparently a[b] is equivalent to *std::ops::Index::index(&a, b) or
- * *std::ops::Index::index_mut(&mut a, b) */
-/* Also apparently deref operations on a will be repeatedly applied to find an
- * implementation */
class ArrayIndexExpr : public ExprWithoutBlock
{
std::unique_ptr<Expr> array_expr;
@@ -1054,6 +1087,11 @@ public:
Expr *get_array_expr () { return array_expr.get (); }
Expr *get_index_expr () { return index_expr.get (); }
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::ArrayIndex;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1140,6 +1178,11 @@ public:
bool is_unit () const { return tuple_elems.size () == 0; }
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Tuple;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1153,18 +1196,12 @@ protected:
}
};
-// aka TupleIndexingExpr
-// HIR representation of a tuple indexing expression
class TupleIndexExpr : public ExprWithoutBlock
{
std::unique_ptr<Expr> tuple_expr;
- // TupleIndex is a decimal int literal with no underscores or suffix
TupleIndex tuple_index;
-
Location locus;
- // i.e. pair.0
-
public:
std::string as_string () const override;
@@ -1209,6 +1246,11 @@ public:
return tuple_expr;
}
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::TupleIdx;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1242,6 +1284,11 @@ public:
PathInExpression &get_struct_name () { return struct_name; }
std::string as_string () const override;
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Struct;
+ }
};
// Actual HIR node of the struct creator (with no fields). Not abstract!
@@ -1630,7 +1677,6 @@ class CallExpr : public ExprWithoutBlock
{
std::unique_ptr<Expr> function;
std::vector<std::unique_ptr<Expr> > params;
-
Location locus;
public:
@@ -1692,6 +1738,11 @@ public:
return params;
}
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Call;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1711,7 +1762,6 @@ class MethodCallExpr : public ExprWithoutBlock
std::unique_ptr<Expr> receiver;
PathExprSegment method_name;
std::vector<std::unique_ptr<Expr> > params;
-
Location locus;
public:
@@ -1776,6 +1826,11 @@ public:
return params;
}
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::MethodCall;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1847,6 +1902,11 @@ public:
Identifier get_field_name () const { return field; }
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::FieldAccess;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1921,10 +1981,7 @@ public:
class ClosureExpr : public ExprWithoutBlock
{
bool has_move;
- std::vector<ClosureParam> params; // may be empty
- /* also note a double pipe "||" can be used for empty params - does not need a
- * space */
-
+ std::vector<ClosureParam> params;
Location locus;
protected:
@@ -1939,6 +1996,11 @@ public:
std::string as_string () const override;
Location get_locus () const override final { return locus; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Closure;
+ }
};
// Represents a non-type-specified closure expression HIR node
@@ -2004,10 +2066,8 @@ class BlockExpr : public ExprWithBlock
{
public:
AST::AttrVec inner_attrs;
-
std::vector<std::unique_ptr<Stmt> > statements;
- std::unique_ptr<Expr> expr; // inlined from Statements
-
+ std::unique_ptr<Expr> expr;
bool tail_reachable;
Location locus;
@@ -2091,6 +2151,11 @@ public:
std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Block;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2181,7 +2246,6 @@ protected:
// HIR node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
- // bool has_label;
Lifetime label;
Location locus;
@@ -2204,6 +2268,11 @@ public:
Lifetime &get_label () { return label; }
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Continue;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2219,7 +2288,6 @@ protected:
return new ContinueExpr (*this);
}
};
-// TODO: merge "break" and "continue"? Or even merge in "return"?
// HIR node representing break expression within loops
class BreakExpr : public ExprWithoutBlock
@@ -2285,6 +2353,11 @@ public:
std::unique_ptr<Expr> &get_expr () { return break_expr; }
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Break;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2311,6 +2384,11 @@ protected:
public:
Location get_locus () const override final { return locus; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Range;
+ }
};
// Range from (inclusive) and to (exclusive) expression HIR node object
@@ -2658,6 +2736,11 @@ public:
Expr *get_expr () { return return_expr.get (); }
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Return;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2679,7 +2762,6 @@ class UnsafeBlockExpr : public ExprWithBlock
{
// Or just have it extend BlockExpr
std::unique_ptr<BlockExpr> expr;
-
Location locus;
public:
@@ -2719,6 +2801,11 @@ public:
std::unique_ptr<BlockExpr> &get_block_expr () { return expr; }
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::UnsafeBlock;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2766,10 +2853,7 @@ public:
class BaseLoopExpr : public ExprWithBlock
{
protected:
- // protected to allow subclasses better use of them
- // bool has_loop_label;
LoopLabel loop_label;
-
std::unique_ptr<BlockExpr> loop_block;
private:
@@ -2808,6 +2892,11 @@ protected:
BaseLoopExpr (BaseLoopExpr &&other) = default;
BaseLoopExpr &operator= (BaseLoopExpr &&other) = default;
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::BaseLoop;
+ }
+
public:
bool has_loop_label () const { return !loop_label.is_error (); }
@@ -3110,6 +3199,8 @@ public:
Expr *get_if_condition () { return condition.get (); }
BlockExpr *get_if_block () { return if_block.get (); }
+ ExprType get_expression_type () const final override { return ExprType::If; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3328,6 +3419,11 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::IfLet;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3880,6 +3976,11 @@ public:
const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
std::vector<MatchCase> &get_match_cases () { return match_arms; }
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Match;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3897,7 +3998,6 @@ protected:
class AwaitExpr : public ExprWithoutBlock
{
std::unique_ptr<Expr> awaited_expr;
-
Location locus;
public:
@@ -3934,6 +4034,11 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Await;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3946,10 +4051,8 @@ protected:
// Async block expression HIR node (block expr that evaluates to a future)
class AsyncBlockExpr : public ExprWithBlock
{
- // TODO: should this extend BlockExpr rather than be a composite of it?
bool has_move;
std::unique_ptr<BlockExpr> block_expr;
-
Location locus;
public:
@@ -3987,6 +4090,11 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::AsyncBlock;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index fb45bfa..09f9d38 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -511,6 +511,10 @@ public:
}
std::string as_string () const;
+
+ AsyncConstStatus get_status () const { return const_status; }
+
+ bool is_const () const { return const_status == AsyncConstStatus::CONST; }
};
// A function parameter
@@ -1216,7 +1220,7 @@ public:
return function_body;
}
- FunctionQualifiers get_qualifiers () const { return qualifiers; }
+ const FunctionQualifiers &get_qualifiers () const { return qualifiers; }
Identifier get_function_name () const { return function_name; }
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 532b95b..de312ee 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -166,12 +166,46 @@ class ExprWithoutBlock;
// Base expression HIR node - abstract
class Expr
{
- // TODO: move outer attribute data to derived classes?
AST::AttrVec outer_attrs;
-
Analysis::NodeMapping mappings;
public:
+ enum BlockType
+ {
+ WITH_BLOCK,
+ WITHOUT_BLOCK,
+ };
+
+ enum ExprType
+ {
+ Lit,
+ Operator,
+ Grouped,
+ Array,
+ ArrayIndex,
+ Tuple,
+ TupleIdx,
+ Struct,
+ Call,
+ MethodCall,
+ FieldAccess,
+ Closure,
+ Block,
+ Continue,
+ Break,
+ Range,
+ Return,
+ UnsafeBlock,
+ BaseLoop,
+ If,
+ IfLet,
+ Match,
+ Await,
+ AsyncBlock,
+ Ident,
+ Path,
+ };
+
const AST::AttrVec &get_outer_attrs () const { return outer_attrs; }
// Unique pointer custom clone function
@@ -180,11 +214,6 @@ public:
return std::unique_ptr<Expr> (clone_expr_impl ());
}
- /* TODO: public methods that could be useful:
- * - get_type() - returns type of expression. set_type() may also be useful
- * for some?
- * - evaluate() - evaluates expression if constant? can_evaluate()? */
-
/* HACK: downcasting without dynamic_cast (if possible) via polymorphism -
* overrided in subclasses of ExprWithoutBlock */
virtual ExprWithoutBlock *as_expr_without_block () const { return nullptr; }
@@ -196,9 +225,6 @@ public:
virtual Location get_locus () const = 0;
- // HACK: strictly not needed, but faster than full downcast clone
- virtual bool is_expr_without_block () const = 0;
-
virtual void accept_vis (HIRFullVisitor &vis) = 0;
const Analysis::NodeMapping &get_mappings () const { return mappings; }
@@ -206,6 +232,10 @@ public:
// Clone function implementation as pure virtual method
virtual Expr *clone_expr_impl () const = 0;
+ virtual BlockType get_block_expr_type () const = 0;
+
+ virtual ExprType get_expression_type () const = 0;
+
protected:
// Constructor
Expr (Analysis::NodeMapping mappings,
@@ -242,8 +272,6 @@ protected:
return clone_expr_without_block_impl ();
}
- bool is_expr_without_block () const final override { return true; };
-
public:
// Unique pointer custom clone function
std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
@@ -257,6 +285,11 @@ public:
{
return clone_expr_without_block_impl ();
}
+
+ BlockType get_block_expr_type () const final override
+ {
+ return BlockType::WITHOUT_BLOCK;
+ };
};
/* HACK: IdentifierExpr, delete when figure out identifier vs expr problem in
@@ -294,6 +327,11 @@ public:
Identifier get_identifier () const { return ident; }
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Ident;
+ }
+
protected:
// Clone method implementation
IdentifierExpr *clone_expr_without_block_impl () const override
@@ -760,14 +798,17 @@ protected:
{}
public:
- // TODO: think of a better and less hacky way to allow this
-
/* Replaces the outer attributes of this path expression with the given outer
* attributes. */
void replace_outer_attrs (AST::AttrVec outer_attrs)
{
set_outer_attrs (std::move (outer_attrs));
}
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Path;
+ }
};
} // namespace HIR
} // namespace Rust