aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-tree.cc
diff options
context:
space:
mode:
authorFaisal Abbas <90.abbasfaisal@gmail.com>2022-07-18 16:07:22 +0100
committerPhilip Herron <philip.herron@embecosm.com>2022-08-25 12:40:24 +0100
commita00b61e6bfc4a79af55236db0e602e09cd8fda72 (patch)
tree372b21fad7406485934f78a8d48c682901a9d832 /gcc/rust/backend/rust-tree.cc
parent7c13a2e5873f5919c00b5f37b6db52af8d0f7300 (diff)
downloadgcc-a00b61e6bfc4a79af55236db0e602e09cd8fda72.zip
gcc-a00b61e6bfc4a79af55236db0e602e09cd8fda72.tar.gz
gcc-a00b61e6bfc4a79af55236db0e602e09cd8fda72.tar.bz2
gccrs const folding port: continue porting potential_constant_expression_1()
Following functions are ported in this changeset: - find_heap_var_refs - find_immediate_fndecl - instantiation_dependent_expression_p - cp_get_callee - build_nop - scalarish_type_p - type_has_nontrivial_copy_init - build_local_temp - is_normal_capture_proxy - reject_gcc_builtin - is_bitfield_expr_with_lowered_type - maybe_undo_parenthesized_ref - fold_offsetof - char_type_p - resolve_nondeduced_context - null_node_p Following structs, classes and enums are ported in this changeset: - c_tree_index - warning_sentinel - uid_sensitive_constexpr_evaluation_checker - iloc_sentinel - ptrmem_cst This changeset puts c_global_trees and cp_global_trees outside Rust and Compile namespaces because keeping them inside is causing build issues. This is possibly because rust-tree.cc contains only Rust namespace while rust-constexpr.cc is Rust+Compile namespace. This causes issues when trying to use them inside both files. Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com>
Diffstat (limited to 'gcc/rust/backend/rust-tree.cc')
-rw-r--r--gcc/rust/backend/rust-tree.cc501
1 files changed, 500 insertions, 1 deletions
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index 9221f7b..22e91f4 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -26,6 +26,13 @@
#include "hash-map.h"
#include "diagnostic.h"
#include "timevar.h"
+#include "convert.h"
+#include "gimple-expr.h"
+
+// forked from gcc/c-family/c-common.cc c_global_trees
+tree c_global_trees[CTI_MAX];
+// forked from gcc/cp/decl.cc cp_global_trees
+tree cp_global_trees[CPTI_MAX];
namespace Rust {
@@ -995,7 +1002,115 @@ rs_type_quals (const_tree type)
tree type_info_type_node, tinfo_decl_id, tinfo_decl_type;
tree tinfo_var_id; */
-tree cp_global_trees[CPTI_MAX];
+/* The following symbols are subsumed in the c_global_trees array, and
+ listed here individually for documentation purposes.
+
+ INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
+
+ tree short_integer_type_node;
+ tree long_integer_type_node;
+ tree long_long_integer_type_node;
+
+ tree short_unsigned_type_node;
+ tree long_unsigned_type_node;
+ tree long_long_unsigned_type_node;
+
+ tree truthvalue_type_node;
+ tree truthvalue_false_node;
+ tree truthvalue_true_node;
+
+ tree ptrdiff_type_node;
+
+ tree unsigned_char_type_node;
+ tree signed_char_type_node;
+ tree wchar_type_node;
+
+ tree char8_type_node;
+ tree char16_type_node;
+ tree char32_type_node;
+
+ tree float_type_node;
+ tree double_type_node;
+ tree long_double_type_node;
+
+ tree complex_integer_type_node;
+ tree complex_float_type_node;
+ tree complex_double_type_node;
+ tree complex_long_double_type_node;
+
+ tree dfloat32_type_node;
+ tree dfloat64_type_node;
+ tree_dfloat128_type_node;
+
+ tree intQI_type_node;
+ tree intHI_type_node;
+ tree intSI_type_node;
+ tree intDI_type_node;
+ tree intTI_type_node;
+
+ tree unsigned_intQI_type_node;
+ tree unsigned_intHI_type_node;
+ tree unsigned_intSI_type_node;
+ tree unsigned_intDI_type_node;
+ tree unsigned_intTI_type_node;
+
+ tree widest_integer_literal_type_node;
+ tree widest_unsigned_literal_type_node;
+
+ Nodes for types `void *' and `const void *'.
+
+ tree ptr_type_node, const_ptr_type_node;
+
+ Nodes for types `char *' and `const char *'.
+
+ tree string_type_node, const_string_type_node;
+
+ Type `char[SOMENUMBER]'.
+ Used when an array of char is needed and the size is irrelevant.
+
+ tree char_array_type_node;
+
+ Type `wchar_t[SOMENUMBER]' or something like it.
+ Used when a wide string literal is created.
+
+ tree wchar_array_type_node;
+
+ Type `char8_t[SOMENUMBER]' or something like it.
+ Used when a UTF-8 string literal is created.
+
+ tree char8_array_type_node;
+
+ Type `char16_t[SOMENUMBER]' or something like it.
+ Used when a UTF-16 string literal is created.
+
+ tree char16_array_type_node;
+
+ Type `char32_t[SOMENUMBER]' or something like it.
+ Used when a UTF-32 string literal is created.
+
+ tree char32_array_type_node;
+
+ Type `int ()' -- used for implicit declaration of functions.
+
+ tree default_function_type;
+
+ A VOID_TYPE node, packaged in a TREE_LIST.
+
+ tree void_list_node;
+
+ The lazily created VAR_DECLs for __FUNCTION__, __PRETTY_FUNCTION__,
+ and __func__. (C doesn't generate __FUNCTION__ and__PRETTY_FUNCTION__
+ VAR_DECLS, but C++ does.)
+
+ tree function_name_decl_node;
+ tree pretty_function_name_decl_node;
+ tree c99_function_name_decl_node;
+
+ Stack of nested function name VAR_DECLs.
+
+ tree saved_function_name_decls;
+
+*/
// forked from gcc/cp/module.cc fixed_trees
@@ -1035,6 +1150,7 @@ maybe_add_global (tree val, unsigned &crc)
/* Global trees. */
static const std::pair<tree *, unsigned> global_tree_arys[] = {
std::pair<tree *, unsigned> (cp_global_trees, CPTI_MODULE_HWM),
+ std::pair<tree *, unsigned> (c_global_trees, CTI_MODULE_HWM),
};
// forked from gcc/cp/module.cc init_modules
@@ -1051,6 +1167,13 @@ init_modules ()
{
maybe_add_global (*ptr, crc);
}
+
+ ptr = global_tree_arys[1].first;
+ limit = global_tree_arys[1].second;
+ for (unsigned ix = 0; ix != limit; ix++, ptr++)
+ {
+ maybe_add_global (*ptr, crc);
+ }
}
// forked from gcc/cp/constexpr.cc var_in_constexpr_fn
@@ -3222,4 +3345,380 @@ release_tree_vector (vec<tree, va_gc> *vec)
}
}
}
+
+// forked from gcc/cp/cvt.cc instantiation_dependent_expression_p
+
+/* As above, but also check value-dependence of the expression as a whole. */
+
+bool
+instantiation_dependent_expression_p (tree expression)
+{
+ return false;
+}
+
+// forked from gcc/cp/cvt.cc cp_get_callee
+
+/* If CALL is a call, return the callee; otherwise null. */
+
+tree
+cp_get_callee (tree call)
+{
+ if (call == NULL_TREE)
+ return call;
+ else if (TREE_CODE (call) == CALL_EXPR)
+ return CALL_EXPR_FN (call);
+ return NULL_TREE;
+}
+
+// forked from gcc/cp/typeck.cc build_nop
+
+/* Return a NOP_EXPR converting EXPR to TYPE. */
+
+tree
+build_nop (tree type, tree expr)
+{
+ if (type == error_mark_node || error_operand_p (expr))
+ return expr;
+ return build1_loc (EXPR_LOCATION (expr), NOP_EXPR, type, expr);
+}
+
+// forked from gcc/cp/tree.cc scalarish_type_p
+
+/* Returns 1 iff type T is something we want to treat as a scalar type for
+ the purpose of deciding whether it is trivial/POD/standard-layout. */
+
+bool
+scalarish_type_p (const_tree t)
+{
+ if (t == error_mark_node)
+ return 1;
+
+ return (SCALAR_TYPE_P (t) || VECTOR_TYPE_P (t));
+}
+
+// forked from gcc/cp/tree.cc type_has_nontrivial_copy_init
+
+/* Returns true iff copying an object of type T (including via move
+ constructor) is non-trivial. That is, T has no non-trivial copy
+ constructors and no non-trivial move constructors, and not all copy/move
+ constructors are deleted. This function implements the ABI notion of
+ non-trivial copy, which has diverged from the one in the standard. */
+
+bool
+type_has_nontrivial_copy_init (const_tree type)
+{
+ return false;
+}
+
+// forked from gcc/cp/tree.cc build_local_temp
+
+/* Return an undeclared local temporary of type TYPE for use in building a
+ TARGET_EXPR. */
+
+tree
+build_local_temp (tree type)
+{
+ tree slot = build_decl (input_location, VAR_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (slot) = 1;
+ DECL_IGNORED_P (slot) = 1;
+ DECL_CONTEXT (slot) = current_function_decl;
+ layout_decl (slot, 0);
+ return slot;
+}
+
+// forked from gcc/cp/lambda.cc is_normal_capture_proxy
+
+/* Returns true iff DECL is a capture proxy for a normal capture
+ (i.e. without explicit initializer). */
+
+bool
+is_normal_capture_proxy (tree decl)
+{
+ return false;
+}
+
+// forked from gcc/cp/c-common.cc reject_gcc_builtin
+
+/* For an EXPR of a FUNCTION_TYPE that references a GCC built-in function
+ with no library fallback or for an ADDR_EXPR whose operand is such type
+ issues an error pointing to the location LOC.
+ Returns true when the expression has been diagnosed and false
+ otherwise. */
+
+bool
+reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
+{
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ STRIP_ANY_LOCATION_WRAPPER (expr);
+
+ if (TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
+ && TREE_CODE (expr) == FUNCTION_DECL
+ /* The intersection of DECL_BUILT_IN and DECL_IS_UNDECLARED_BUILTIN avoids
+ false positives for user-declared built-ins such as abs or
+ strlen, and for C++ operators new and delete.
+ The c_decl_implicit() test avoids false positives for implicitly
+ declared built-ins with library fallbacks (such as abs). */
+ && fndecl_built_in_p (expr) && DECL_IS_UNDECLARED_BUILTIN (expr)
+ && !DECL_ASSEMBLER_NAME_SET_P (expr))
+ {
+ if (loc == UNKNOWN_LOCATION)
+ loc = EXPR_LOC_OR_LOC (expr, input_location);
+
+ /* Reject arguments that are built-in functions with
+ no library fallback. */
+ error_at (loc, "built-in function %qE must be directly called", expr);
+
+ return true;
+ }
+
+ return false;
+}
+
+// forked from gcc/cp/typeck.cc is_bitfield_expr_with_lowered_type
+
+/* If EXP is a reference to a bit-field, and the type of EXP does not
+ match the declared type of the bit-field, return the declared type
+ of the bit-field. Otherwise, return NULL_TREE. */
+
+tree
+is_bitfield_expr_with_lowered_type (const_tree exp)
+{
+ switch (TREE_CODE (exp))
+ {
+ case COND_EXPR:
+ if (!is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1)
+ ? TREE_OPERAND (exp, 1)
+ : TREE_OPERAND (exp, 0)))
+ return NULL_TREE;
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 2));
+
+ case COMPOUND_EXPR:
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1));
+
+ case MODIFY_EXPR:
+ case SAVE_EXPR:
+ case UNARY_PLUS_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case BIT_NOT_EXPR:
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
+
+ case COMPONENT_REF: {
+ tree field;
+
+ field = TREE_OPERAND (exp, 1);
+ if (TREE_CODE (field) != FIELD_DECL || !DECL_BIT_FIELD_TYPE (field))
+ return NULL_TREE;
+ if (same_type_ignoring_top_level_qualifiers_p (
+ TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
+ return NULL_TREE;
+ return DECL_BIT_FIELD_TYPE (field);
+ }
+
+ case VAR_DECL:
+ if (DECL_HAS_VALUE_EXPR_P (exp))
+ return is_bitfield_expr_with_lowered_type (
+ DECL_VALUE_EXPR (CONST_CAST_TREE (exp)));
+ return NULL_TREE;
+
+ case VIEW_CONVERT_EXPR:
+ if (location_wrapper_p (exp))
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
+ else
+ return NULL_TREE;
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+// forked from gcc/cp/semantics.cc maybe_undo_parenthesized_ref
+
+/* If T is an id-expression obfuscated by force_paren_expr, undo the
+ obfuscation and return the underlying id-expression. Otherwise
+ return T. */
+
+tree
+maybe_undo_parenthesized_ref (tree t)
+{
+ if ((TREE_CODE (t) == PAREN_EXPR || TREE_CODE (t) == VIEW_CONVERT_EXPR)
+ && REF_PARENTHESIZED_P (t))
+ t = TREE_OPERAND (t, 0);
+
+ return t;
+}
+
+// forked from gcc/c-family/c-common.cc fold_offsetof
+
+/* Fold an offsetof-like expression. EXPR is a nested sequence of component
+ references with an INDIRECT_REF of a constant at the bottom; much like the
+ traditional rendering of offsetof as a macro. TYPE is the desired type of
+ the whole expression. Return the folded result. */
+
+tree
+fold_offsetof (tree expr, tree type, enum tree_code ctx)
+{
+ tree base, off, t;
+ tree_code code = TREE_CODE (expr);
+ switch (code)
+ {
+ case ERROR_MARK:
+ return expr;
+
+ case VAR_DECL:
+ error ("cannot apply %<offsetof%> to static data member %qD", expr);
+ return error_mark_node;
+
+ case CALL_EXPR:
+ case TARGET_EXPR:
+ error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
+ return error_mark_node;
+
+ case NOP_EXPR:
+ case INDIRECT_REF:
+ if (!TREE_CONSTANT (TREE_OPERAND (expr, 0)))
+ {
+ error ("cannot apply %<offsetof%> to a non constant address");
+ return error_mark_node;
+ }
+ return convert (type, TREE_OPERAND (expr, 0));
+
+ case COMPONENT_REF:
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ if (DECL_C_BIT_FIELD (t))
+ {
+ error ("attempt to take address of bit-field structure "
+ "member %qD",
+ t);
+ return error_mark_node;
+ }
+ off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
+ size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
+ / BITS_PER_UNIT));
+ break;
+
+ case ARRAY_REF:
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ STRIP_ANY_LOCATION_WRAPPER (t);
+
+ /* Check if the offset goes beyond the upper bound of the array. */
+ if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
+ {
+ tree upbound = array_ref_up_bound (expr);
+ if (upbound != NULL_TREE && TREE_CODE (upbound) == INTEGER_CST
+ && !tree_int_cst_equal (upbound,
+ TYPE_MAX_VALUE (TREE_TYPE (upbound))))
+ {
+ if (ctx != ARRAY_REF && ctx != COMPONENT_REF)
+ upbound = size_binop (PLUS_EXPR, upbound,
+ build_int_cst (TREE_TYPE (upbound), 1));
+ if (tree_int_cst_lt (upbound, t))
+ {
+ tree v;
+
+ for (v = TREE_OPERAND (expr, 0);
+ TREE_CODE (v) == COMPONENT_REF; v = TREE_OPERAND (v, 0))
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE)
+ {
+ tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
+ for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
+ if (TREE_CODE (fld_chain) == FIELD_DECL)
+ break;
+
+ if (fld_chain)
+ break;
+ }
+ /* Don't warn if the array might be considered a poor
+ man's flexible array member with a very permissive
+ definition thereof. */
+ if (TREE_CODE (v) == ARRAY_REF
+ || TREE_CODE (v) == COMPONENT_REF)
+ warning (OPT_Warray_bounds,
+ "index %E denotes an offset "
+ "greater than size of %qT",
+ t, TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ }
+ }
+
+ t = convert (sizetype, t);
+ off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+ break;
+
+ case COMPOUND_EXPR:
+ /* Handle static members of volatile structs. */
+ t = TREE_OPERAND (expr, 1);
+ gcc_checking_assert (VAR_P (get_base_address (t)));
+ return fold_offsetof (t, type);
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (!POINTER_TYPE_P (type))
+ return size_binop (PLUS_EXPR, base, convert (type, off));
+ return fold_build_pointer_plus (base, off);
+}
+
+// forked from gcc/cp/tree.cc char_type_p
+
+/* Returns nonzero if TYPE is a character type, including wchar_t. */
+
+int
+char_type_p (tree type)
+{
+ return (same_type_p (type, char_type_node)
+ || same_type_p (type, unsigned_char_type_node)
+ || same_type_p (type, signed_char_type_node)
+ || same_type_p (type, char8_type_node)
+ || same_type_p (type, char16_type_node)
+ || same_type_p (type, char32_type_node)
+ || same_type_p (type, wchar_type_node));
+}
+
+// forked from gcc/cp/pt.cc resolve_nondeduced_context
+
+/* Core DR 115: In contexts where deduction is done and fails, or in
+ contexts where deduction is not done, if a template argument list is
+ specified and it, along with any default template arguments, identifies
+ a single function template specialization, then the template-id is an
+ lvalue for the function template specialization. */
+
+tree
+resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain)
+{
+ tree expr, offset, baselink;
+ bool addr;
+
+ if (!type_unknown_p (orig_expr))
+ return orig_expr;
+
+ expr = orig_expr;
+ addr = false;
+ offset = NULL_TREE;
+ baselink = NULL_TREE;
+
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ {
+ expr = TREE_OPERAND (expr, 0);
+ addr = true;
+ }
+
+ return orig_expr;
+}
} // namespace Rust