From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id CC4583856DF5; Mon, 29 Aug 2022 15:34:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CC4583856DF5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1661787295; bh=BOZKiRGc8Wchun275YrLsNaFt0HbbQjlSybBneZDthI=; h=From:To:Subject:Date:From; b=t6gCVShBM/YdXNSXujRjEuGcnWVKMd8DRiwmHw/axyY+iAcOblpKoJda7kDhYQUsp Biw+exXq76UtKBoqdVXnBZZbplhqKjw3czty6aoz6CMn04ovzuCakALFK0nI24i3VS x0O89KUnl8kNTQxt2wuR+/iSmcPoUOgzggL1c6kw= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] rust constexprC: start porting cxx_eval_builtin_function_call X-Act-Checkin: gcc X-Git-Author: Faisal Abbas <90.abbasfaisal@gmail.com> X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: bd31c63fe15c4e39d3036ff7adcd22eadd6b53ea X-Git-Newrev: e1170b0abe208b212eb395dc1d79fcfb7515e754 Message-Id: <20220829153455.CC4583856DF5@sourceware.org> Date: Mon, 29 Aug 2022 15:34:55 +0000 (GMT) List-Id: https://gcc.gnu.org/g:e1170b0abe208b212eb395dc1d79fcfb7515e754 commit e1170b0abe208b212eb395dc1d79fcfb7515e754 Author: Faisal Abbas <90.abbasfaisal@gmail.com> Date: Mon Aug 8 18:22:54 2022 +0100 rust constexprC: start porting cxx_eval_builtin_function_call Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com> Diff: --- gcc/rust/backend/rust-tree.cc | 732 ++++++++++++++++++++++++++++++++++++++++++ gcc/rust/backend/rust-tree.h | 86 +++++ 2 files changed, 818 insertions(+) diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index ad457a2e4ce..8c6543271aa 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -31,6 +31,11 @@ #include "gimplify.h" #include "function.h" #include "gcc-rich-location.h" +#include "target.h" +#include "file-prefix-map.h" +#include "cgraph.h" + +#include "output.h" // forked from gcc/c-family/c-common.cc c_global_trees tree c_global_trees[CTI_MAX]; @@ -44,6 +49,9 @@ namespace Rust { void mark_exp_read (tree exp) { + char tmp_name[32]; + ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lsrc_loc", 1); + if (exp == NULL) return; @@ -4151,4 +4159,728 @@ rs_get_callee_fndecl_nofold (tree call) return rs_get_fndecl_from_callee (cp_get_callee (call), false); } +// forked from gcc/cp/init.cc is_class_type + +/* Report an error if TYPE is not a user-defined, class type. If + OR_ELSE is nonzero, give an error message. */ + +int +is_class_type (tree type, int or_else) +{ + if (type == error_mark_node) + return 0; + + if (!CLASS_TYPE_P (type)) + { + if (or_else) + error ("%qT is not a class type", type); + return 0; + } + return 1; +} + +// forked from gcc/cp/decl.cc lookup_enumerator + +/* Look for an enumerator with the given NAME within the enumeration + type ENUMTYPE. This routine is used primarily for qualified name + lookup into an enumerator in C++0x, e.g., + + enum class Color { Red, Green, Blue }; + + Color color = Color::Red; + + Returns the value corresponding to the enumerator, or + NULL_TREE if no such enumerator was found. */ +tree +lookup_enumerator (tree enumtype, tree name) +{ + tree e; + gcc_assert (enumtype && TREE_CODE (enumtype) == ENUMERAL_TYPE); + + e = purpose_member (name, TYPE_VALUES (enumtype)); + return e ? TREE_VALUE (e) : NULL_TREE; +} + +// forked from gcc/cp/init.cc constant_value_1 +// commented out mark_used + +/* If DECL is a scalar enumeration constant or variable with a + constant initializer, return the initializer (or, its initializers, + recursively); otherwise, return DECL. If STRICT_P, the + initializer is only returned if DECL is a + constant-expression. If RETURN_AGGREGATE_CST_OK_P, it is ok to + return an aggregate constant. If UNSHARE_P, return an unshared + copy of the initializer. */ + +static tree +constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p, + bool unshare_p) +{ + while (TREE_CODE (decl) == CONST_DECL || decl_constant_var_p (decl) + || (!strict_p && VAR_P (decl) + && RS_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))) + { + tree init; + /* If DECL is a static data member in a template + specialization, we must instantiate it here. The + initializer for the static data member is not processed + until needed; we need it now. */ + // mark_used (decl, tf_none); + init = DECL_INITIAL (decl); + if (init == error_mark_node) + { + if (TREE_CODE (decl) == CONST_DECL + || DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + /* Treat the error as a constant to avoid cascading errors on + excessively recursive template instantiation (c++/9335). */ + return init; + else + return decl; + } + + /* Instantiate a non-dependent initializer for user variables. We + mustn't do this for the temporary for an array compound literal; + trying to instatiate the initializer will keep creating new + temporaries until we crash. Probably it's not useful to do it for + other artificial variables, either. */ + if (!DECL_ARTIFICIAL (decl)) + init = instantiate_non_dependent_or_null (init); + if (!init || !TREE_TYPE (init) || !TREE_CONSTANT (init) + || (!return_aggregate_cst_ok_p + /* Unless RETURN_AGGREGATE_CST_OK_P is true, do not + return an aggregate constant (of which string + literals are a special case), as we do not want + to make inadvertent copies of such entities, and + we must be sure that their addresses are the + same everywhere. */ + && (TREE_CODE (init) == CONSTRUCTOR + || TREE_CODE (init) == STRING_CST))) + break; + /* Don't return a CONSTRUCTOR for a variable with partial run-time + initialization, since it doesn't represent the entire value. + Similarly for VECTOR_CSTs created by cp_folding those + CONSTRUCTORs. */ + if ((TREE_CODE (init) == CONSTRUCTOR || TREE_CODE (init) == VECTOR_CST) + && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + break; + /* If the variable has a dynamic initializer, don't use its + DECL_INITIAL which doesn't reflect the real value. */ + if (VAR_P (decl) && TREE_STATIC (decl) + && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) + && DECL_NONTRIVIALLY_INITIALIZED_P (decl)) + break; + decl = init; + } + return unshare_p ? unshare_expr (decl) : decl; +} + +// forked from gcc/cp/init.cc decl_constant_value + +/* A more relaxed version of decl_really_constant_value, used by the + common C/C++ code. */ + +tree +decl_constant_value (tree decl, bool unshare_p) +{ + return constant_value_1 (decl, /*strict_p=*/false, + /*return_aggregate_cst_ok_p=*/true, + /*unshare_p=*/unshare_p); +} + +// Below is forked from gcc/cp/init.cc decl_constant_value + +tree +decl_constant_value (tree decl) +{ + return decl_constant_value (decl, /*unshare_p=*/true); +} + +// Below is forked from gcc/cp/cp-gimplify.cc + +/* Type for source_location_table hash_set. */ +struct GTY ((for_user)) source_location_table_entry +{ + location_t loc; + unsigned uid; + tree var; +}; + +/* Traits class for function start hash maps below. */ + +struct source_location_table_entry_hash + : ggc_remove +{ + typedef source_location_table_entry value_type; + typedef source_location_table_entry compare_type; + + static hashval_t hash (const source_location_table_entry &ref) + { + inchash::hash hstate (0); + hstate.add_int (ref.loc); + hstate.add_int (ref.uid); + return hstate.end (); + } + + static bool equal (const source_location_table_entry &ref1, + const source_location_table_entry &ref2) + { + return ref1.loc == ref2.loc && ref1.uid == ref2.uid; + } + + static void mark_deleted (source_location_table_entry &ref) + { + ref.loc = UNKNOWN_LOCATION; + ref.uid = -1U; + ref.var = NULL_TREE; + } + + static const bool empty_zero_p = true; + + static void mark_empty (source_location_table_entry &ref) + { + ref.loc = UNKNOWN_LOCATION; + ref.uid = 0; + ref.var = NULL_TREE; + } + + static bool is_deleted (const source_location_table_entry &ref) + { + return (ref.loc == UNKNOWN_LOCATION && ref.uid == -1U + && ref.var == NULL_TREE); + } + + static bool is_empty (const source_location_table_entry &ref) + { + return (ref.loc == UNKNOWN_LOCATION && ref.uid == 0 + && ref.var == NULL_TREE); + } + + static void pch_nx (source_location_table_entry &p) + { + extern void gt_pch_nx (source_location_table_entry &); + gt_pch_nx (p); + } + + static void pch_nx (source_location_table_entry &p, gt_pointer_operator op, + void *cookie) + { + extern void gt_pch_nx (source_location_table_entry *, gt_pointer_operator, + void *); + gt_pch_nx (&p, op, cookie); + } +}; + +static GTY (()) + hash_table *source_location_table; +static GTY (()) unsigned int source_location_id; + +// Above is forked from gcc/cp/cp-gimplify.cc + +// forked from gcc/cp/tree.cc lvalue_kind + +/* If REF is an lvalue, returns the kind of lvalue that REF is. + Otherwise, returns clk_none. */ + +cp_lvalue_kind +lvalue_kind (const_tree ref) +{ + cp_lvalue_kind op1_lvalue_kind = clk_none; + cp_lvalue_kind op2_lvalue_kind = clk_none; + + /* Expressions of reference type are sometimes wrapped in + INDIRECT_REFs. INDIRECT_REFs are just internal compiler + representation, not part of the language, so we have to look + through them. */ + if (REFERENCE_REF_P (ref)) + return lvalue_kind (TREE_OPERAND (ref, 0)); + + if (TREE_TYPE (ref) && TYPE_REF_P (TREE_TYPE (ref))) + { + /* unnamed rvalue references are rvalues */ + if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref)) && TREE_CODE (ref) != PARM_DECL + && !VAR_P (ref) + && TREE_CODE (ref) != COMPONENT_REF + /* Functions are always lvalues. */ + && TREE_CODE (TREE_TYPE (TREE_TYPE (ref))) != FUNCTION_TYPE) + { + op1_lvalue_kind = clk_rvalueref; + if (implicit_rvalue_p (ref)) + op1_lvalue_kind |= clk_implicit_rval; + return op1_lvalue_kind; + } + + /* lvalue references and named rvalue references are lvalues. */ + return clk_ordinary; + } + + if (ref == current_class_ptr) + return clk_none; + + /* Expressions with cv void type are prvalues. */ + if (TREE_TYPE (ref) && VOID_TYPE_P (TREE_TYPE (ref))) + return clk_none; + + switch (TREE_CODE (ref)) + { + case SAVE_EXPR: + return clk_none; + + /* preincrements and predecrements are valid lvals, provided + what they refer to are valid lvals. */ + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case TRY_CATCH_EXPR: + case REALPART_EXPR: + case IMAGPART_EXPR: + case VIEW_CONVERT_EXPR: + return lvalue_kind (TREE_OPERAND (ref, 0)); + + case ARRAY_REF: { + tree op1 = TREE_OPERAND (ref, 0); + if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE) + { + op1_lvalue_kind = lvalue_kind (op1); + if (op1_lvalue_kind == clk_class) + /* in the case of an array operand, the result is an lvalue if + that operand is an lvalue and an xvalue otherwise */ + op1_lvalue_kind = clk_rvalueref; + return op1_lvalue_kind; + } + else + return clk_ordinary; + } + + case MEMBER_REF: + case DOTSTAR_EXPR: + if (TREE_CODE (ref) == MEMBER_REF) + op1_lvalue_kind = clk_ordinary; + else + op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); + if (TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (ref, 1)))) + op1_lvalue_kind = clk_none; + else if (op1_lvalue_kind == clk_class) + /* The result of a .* expression whose second operand is a pointer to a + data member is an lvalue if the first operand is an lvalue and an + xvalue otherwise. */ + op1_lvalue_kind = clk_rvalueref; + return op1_lvalue_kind; + + case COMPONENT_REF: + op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); + if (op1_lvalue_kind == clk_class) + /* If E1 is an lvalue, then E1.E2 is an lvalue; + otherwise E1.E2 is an xvalue. */ + op1_lvalue_kind = clk_rvalueref; + + /* Look at the member designator. */ + if (!op1_lvalue_kind) + ; + else if (is_overloaded_fn (TREE_OPERAND (ref, 1))) + /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some + situations. If we're seeing a COMPONENT_REF, it's a non-static + member, so it isn't an lvalue. */ + op1_lvalue_kind = clk_none; + else if (TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL) + /* This can be IDENTIFIER_NODE in a template. */; + else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1))) + { + /* Clear the ordinary bit. If this object was a class + rvalue we want to preserve that information. */ + op1_lvalue_kind &= ~clk_ordinary; + /* The lvalue is for a bitfield. */ + op1_lvalue_kind |= clk_bitfield; + } + else if (DECL_PACKED (TREE_OPERAND (ref, 1))) + op1_lvalue_kind |= clk_packed; + + return op1_lvalue_kind; + + case STRING_CST: + case COMPOUND_LITERAL_EXPR: + return clk_ordinary; + + case CONST_DECL: + /* CONST_DECL without TREE_STATIC are enumeration values and + thus not lvalues. With TREE_STATIC they are used by ObjC++ + in objc_build_string_object and need to be considered as + lvalues. */ + if (!TREE_STATIC (ref)) + return clk_none; + /* FALLTHRU */ + case VAR_DECL: + if (VAR_P (ref) && DECL_HAS_VALUE_EXPR_P (ref)) + return lvalue_kind (DECL_VALUE_EXPR (CONST_CAST_TREE (ref))); + + if (TREE_READONLY (ref) && !TREE_STATIC (ref) && DECL_LANG_SPECIFIC (ref) + && DECL_IN_AGGR_P (ref)) + return clk_none; + /* FALLTHRU */ + case INDIRECT_REF: + case ARROW_EXPR: + case PARM_DECL: + case RESULT_DECL: + case PLACEHOLDER_EXPR: + return clk_ordinary; + + case MAX_EXPR: + case MIN_EXPR: + /* Disallow ? as lvalues if either argument side-effects. */ + if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0)) + || TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1))) + return clk_none; + op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); + op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1)); + break; + + case COND_EXPR: { + tree op1 = TREE_OPERAND (ref, 1); + if (!op1) + op1 = TREE_OPERAND (ref, 0); + tree op2 = TREE_OPERAND (ref, 2); + op1_lvalue_kind = lvalue_kind (op1); + op2_lvalue_kind = lvalue_kind (op2); + if (!op1_lvalue_kind != !op2_lvalue_kind) + { + /* The second or the third operand (but not both) is a + throw-expression; the result is of the type + and value category of the other. */ + if (op1_lvalue_kind && TREE_CODE (op2) == THROW_EXPR) + op2_lvalue_kind = op1_lvalue_kind; + else if (op2_lvalue_kind && TREE_CODE (op1) == THROW_EXPR) + op1_lvalue_kind = op2_lvalue_kind; + } + } + break; + + case MODIFY_EXPR: + case TYPEID_EXPR: + return clk_ordinary; + + case COMPOUND_EXPR: + return lvalue_kind (TREE_OPERAND (ref, 1)); + + case TARGET_EXPR: + return clk_class; + + case VA_ARG_EXPR: + return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none); + + case CALL_EXPR: + /* We can see calls outside of TARGET_EXPR in templates. */ + if (CLASS_TYPE_P (TREE_TYPE (ref))) + return clk_class; + return clk_none; + + case FUNCTION_DECL: + /* All functions (except non-static-member functions) are + lvalues. */ + return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref) ? clk_none : clk_ordinary); + + case NON_DEPENDENT_EXPR: + case PAREN_EXPR: + return lvalue_kind (TREE_OPERAND (ref, 0)); + + case TEMPLATE_PARM_INDEX: + if (CLASS_TYPE_P (TREE_TYPE (ref))) + /* A template parameter object is an lvalue. */ + return clk_ordinary; + return clk_none; + + default: + default_: + if (!TREE_TYPE (ref)) + return clk_none; + if (CLASS_TYPE_P (TREE_TYPE (ref)) + || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE) + return clk_class; + return clk_none; + } + + /* If one operand is not an lvalue at all, then this expression is + not an lvalue. */ + if (!op1_lvalue_kind || !op2_lvalue_kind) + return clk_none; + + /* Otherwise, it's an lvalue, and it has all the odd properties + contributed by either operand. */ + op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind; + /* It's not an ordinary lvalue if it involves any other kind. */ + if ((op1_lvalue_kind & ~clk_ordinary) != clk_none) + op1_lvalue_kind &= ~clk_ordinary; + /* It can't be both a pseudo-lvalue and a non-addressable lvalue. + A COND_EXPR of those should be wrapped in a TARGET_EXPR. */ + if ((op1_lvalue_kind & (clk_rvalueref | clk_class)) + && (op1_lvalue_kind & (clk_bitfield | clk_packed))) + op1_lvalue_kind = clk_none; + return op1_lvalue_kind; +} + +// forked from gcc/cp/tree.cc glvalue_p + +/* This differs from lvalue_p in that xvalues are included. */ + +bool +glvalue_p (const_tree ref) +{ + cp_lvalue_kind kind = lvalue_kind (ref); + if (kind & clk_class) + return false; + else + return (kind != clk_none); +} + +// forked from gcc/cp/init.cc cv_qualified_p + +/* Returns nonzero if TYPE is const or volatile. */ + +bool +cv_qualified_p (const_tree type) +{ + int quals = rs_type_quals (type); + return (quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) != 0; +} + +// forked from gcc/cp/tree.cc rvalue + +/* EXPR is being used in an rvalue context. Return a version of EXPR + that is marked as an rvalue. */ + +tree +rvalue (tree expr) +{ + tree type; + + if (error_operand_p (expr)) + return expr; + + expr = mark_rvalue_use (expr); + + /* [basic.lval] + + Non-class rvalues always have cv-unqualified types. */ + type = TREE_TYPE (expr); + if (!CLASS_TYPE_P (type) && cv_qualified_p (type)) + type = cv_unqualified (type); + + /* We need to do this for rvalue refs as well to get the right answer + from decltype; see c++/36628. */ + if (glvalue_p (expr)) + { + /* But don't use this function for class lvalues; use move (to treat an + lvalue as an xvalue) or force_rvalue (to make a prvalue copy). */ + gcc_checking_assert (!CLASS_TYPE_P (type)); + expr = build1 (NON_LVALUE_EXPR, type, expr); + } + else if (type != TREE_TYPE (expr)) + expr = build_nop (type, expr); + + return expr; +} + +// forked from gcc/cp/tree.cc bitfield_p + +/* True if REF is a bit-field. */ + +bool +bitfield_p (const_tree ref) +{ + return (lvalue_kind (ref) & clk_bitfield); +} + +// forked from gcc/cp/typeck.cc cxx_mark_addressable + +/* Mark EXP saying that we need to be able to take the + address of it; it should not be allocated in a register. + Value is true if successful. ARRAY_REF_P is true if this + is for ARRAY_REF construction - in that case we don't want + to look through VIEW_CONVERT_EXPR from VECTOR_TYPE to ARRAY_TYPE, + it is fine to use ARRAY_REFs for vector subscripts on vector + register variables. + + C++: we do not allow `current_class_ptr' to be addressable. */ + +bool +cxx_mark_addressable (tree exp, bool array_ref_p) +{ + tree x = exp; + + while (1) + switch (TREE_CODE (x)) + { + case VIEW_CONVERT_EXPR: + if (array_ref_p && TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE + && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0)))) + return true; + x = TREE_OPERAND (x, 0); + break; + + case COMPONENT_REF: + if (bitfield_p (x)) + error ("attempt to take address of bit-field"); + /* FALLTHRU */ + case ADDR_EXPR: + case ARRAY_REF: + case REALPART_EXPR: + case IMAGPART_EXPR: + x = TREE_OPERAND (x, 0); + break; + + case PARM_DECL: + if (x == current_class_ptr) + { + error ("cannot take the address of %, which is an rvalue " + "expression"); + TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later. */ + return true; + } + /* Fall through. */ + + case VAR_DECL: + /* Caller should not be trying to mark initialized + constant fields addressable. */ + gcc_assert (DECL_LANG_SPECIFIC (x) == 0 || DECL_IN_AGGR_P (x) == 0 + || TREE_STATIC (x) || DECL_EXTERNAL (x)); + /* Fall through. */ + + case RESULT_DECL: + if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) && !DECL_ARTIFICIAL (x)) + { + if (VAR_P (x) && DECL_HARD_REGISTER (x)) + { + error ("address of explicit register variable %qD requested", + x); + return false; + } + else if (extra_warnings) + warning ( + OPT_Wextra, + "address requested for %qD, which is declared %", x); + } + TREE_ADDRESSABLE (x) = 1; + return true; + + case CONST_DECL: + case FUNCTION_DECL: + TREE_ADDRESSABLE (x) = 1; + return true; + + case CONSTRUCTOR: + TREE_ADDRESSABLE (x) = 1; + return true; + + case TARGET_EXPR: + TREE_ADDRESSABLE (x) = 1; + cxx_mark_addressable (TREE_OPERAND (x, 0)); + return true; + + default: + return true; + } +} + +// forked from gcc/cp/typeck.cc build_address + +/* Returns the address of T. This function will fold away + ADDR_EXPR of INDIRECT_REF. This is only for low-level usage; + most places should use cp_build_addr_expr instead. */ + +tree +build_address (tree t) +{ + if (error_operand_p (t) || !cxx_mark_addressable (t)) + return error_mark_node; + gcc_checking_assert (TREE_CODE (t) != CONSTRUCTOR); + t = build_fold_addr_expr_loc (EXPR_LOCATION (t), t); + if (TREE_CODE (t) != ADDR_EXPR) + t = rvalue (t); + return t; +} + +// forked from gcc/cp/gp-gimplify.cc fold_builtin_source_location + +/* Fold __builtin_source_location () call. LOC is the location + of the call. */ + +tree +fold_builtin_source_location (location_t loc) +{ + if (source_location_impl == error_mark_node) + return build_zero_cst (const_ptr_type_node); + if (source_location_table == NULL) + source_location_table + = hash_table::create_ggc (64); + const line_map_ordinary *map; + source_location_table_entry entry; + entry.loc = linemap_resolve_location (line_table, loc, + LRK_MACRO_EXPANSION_POINT, &map); + entry.uid = current_function_decl ? DECL_UID (current_function_decl) : -1; + entry.var = error_mark_node; + source_location_table_entry *entryp + = source_location_table->find_slot (entry, INSERT); + tree var; + if (entryp->var) + var = entryp->var; + else + { + char tmp_name[32]; + ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lsrc_loc", source_location_id++); + var = build_decl (loc, VAR_DECL, get_identifier (tmp_name), + source_location_impl); + TREE_STATIC (var) = 1; + TREE_PUBLIC (var) = 0; + DECL_ARTIFICIAL (var) = 1; + DECL_IGNORED_P (var) = 1; + DECL_EXTERNAL (var) = 0; + DECL_DECLARED_CONSTEXPR_P (var) = 1; + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (var) = 1; + layout_decl (var, 0); + + vec *v = NULL; + vec_alloc (v, 4); + for (tree field = TYPE_FIELDS (source_location_impl); + (field = next_initializable_field (field)) != NULL_TREE; + field = DECL_CHAIN (field)) + { + const char *n = IDENTIFIER_POINTER (DECL_NAME (field)); + tree val = NULL_TREE; + if (strcmp (n, "_M_file_name") == 0) + { + if (const char *fname = LOCATION_FILE (loc)) + { + fname = remap_macro_filename (fname); + val = build_string_literal (strlen (fname) + 1, fname); + } + else + val = build_string_literal (1, ""); + } + else if (strcmp (n, "_M_function_name") == 0) + { + const char *name = "todo: add funciton name here"; + + // if (current_function_decl) + // name = cxx_printable_name (current_function_decl, 2); + + val = build_string_literal (strlen (name) + 1, name); + } + else if (strcmp (n, "_M_line") == 0) + val = build_int_cst (TREE_TYPE (field), LOCATION_LINE (loc)); + else if (strcmp (n, "_M_column") == 0) + val = build_int_cst (TREE_TYPE (field), LOCATION_COLUMN (loc)); + else + gcc_unreachable (); + CONSTRUCTOR_APPEND_ELT (v, field, val); + } + + tree ctor = build_constructor (source_location_impl, v); + TREE_CONSTANT (ctor) = 1; + TREE_STATIC (ctor) = 1; + DECL_INITIAL (var) = ctor; + varpool_node::finalize_decl (var); + *entryp = entry; + entryp->var = var; + } + + return build_fold_addr_expr_with_type_loc (loc, var, const_ptr_type_node); +} + } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index 9efa4096bf6..bb3b4304372 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -1279,6 +1279,24 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; #define TARGET_EXPR_DIRECT_INIT_P(NODE) \ TREE_LANG_FLAG_2 (TARGET_EXPR_CHECK (NODE)) +/* Nonzero if DECL is a declaration of __builtin_constant_p. */ +#define DECL_IS_BUILTIN_CONSTANT_P(NODE) \ + (TREE_CODE (NODE) == FUNCTION_DECL \ + && DECL_BUILT_IN_CLASS (NODE) == BUILT_IN_NORMAL \ + && DECL_FUNCTION_CODE (NODE) == BUILT_IN_CONSTANT_P) + +/* True iff this represents an lvalue being treated as an rvalue during return + or throw as per [class.copy.elision]. */ +#define IMPLICIT_RVALUE_P(NODE) \ + TREE_LANG_FLAG_3 (TREE_CHECK2 ((NODE), NON_LVALUE_EXPR, STATIC_CAST_EXPR)) + +/* Nonzero for _DECL means that this decl appears in (or will appear + in) as a member in a RECORD_TYPE or UNION_TYPE node. It is also for + detecting circularity in case members are multiply defined. In the + case of a VAR_DECL, it means that no definition has been seen, even + if an initializer has been. */ +#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE)) + #if defined ENABLE_TREE_CHECKING #define LANG_DECL_MIN_CHECK(NODE) \ @@ -1400,6 +1418,16 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; // Above macros are copied from gcc/c-family/c-common.h +// Below macros are copied from gcc/cp/name-lookup.h + +/* Lookup walker marking. */ +#define LOOKUP_SEEN_P(NODE) TREE_VISITED (NODE) +#define LOOKUP_FOUND_P(NODE) \ + TREE_LANG_FLAG_4 (TREE_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, \ + NAMESPACE_DECL)) + +// Above macros are copied from gcc/cp/name-lookup.h + // Below macros are copied from gcc/cp/name-lookup.cc /* Create an overload suitable for recording an artificial TYPE_DECL @@ -1435,6 +1463,22 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; // Above macros are copied from gcc/cp/name-lookup.cc +/* The various kinds of lvalues we distinguish. */ +enum cp_lvalue_kind_flags +{ + clk_none = 0, /* Things that are not an lvalue. */ + clk_ordinary = 1, /* An ordinary lvalue. */ + clk_rvalueref = 2, /* An xvalue (rvalue formed using an rvalue reference) */ + clk_class = 4, /* A prvalue of class or array type. */ + clk_bitfield = 8, /* An lvalue for a bit-field. */ + clk_packed = 16, /* An lvalue for a packed field. */ + clk_implicit_rval = 1 << 5 /* An lvalue being treated as an xvalue. */ +}; + +/* This type is used for parameters and variables which hold + combinations of the flags in enum cp_lvalue_kind_flags. */ +typedef int cp_lvalue_kind; + // forked from gcc/cp/name_lookup.h scope_kind /* The kinds of scopes we recognize. */ @@ -2673,6 +2717,29 @@ in_immediate_context (); extern tree cp_get_callee_fndecl_nofold (tree); +extern bool +cxx_mark_addressable (tree, bool = false); + +extern tree fold_builtin_source_location (location_t); + +extern tree build_address (tree); + +extern bool bitfield_p (const_tree); + +extern tree rvalue (tree); + +extern bool glvalue_p (const_tree); + +extern cp_lvalue_kind lvalue_kind (const_tree); + +extern tree +decl_constant_value (tree, bool); + +extern tree lookup_enumerator (tree, tree); + +extern int +is_class_type (tree, int); + // forked from gcc/cp/cp-tree.h enum @@ -2875,6 +2942,25 @@ cxx_incomplete_type_error (const_tree value, const_tree type) extern location_t location_of (tree t); +/* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference. */ + +inline bool +implicit_rvalue_p (const_tree t) +{ + if (REFERENCE_REF_P (t)) + t = TREE_OPERAND (t, 0); + return ((TREE_CODE (t) == NON_LVALUE_EXPR) && IMPLICIT_RVALUE_P (t)); +} +inline tree +set_implicit_rvalue_p (tree ot) +{ + tree t = ot; + if (REFERENCE_REF_P (t)) + t = TREE_OPERAND (t, 0); + IMPLICIT_RVALUE_P (t) = 1; + return ot; +} + namespace Compile { extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);