+/* Generate an RTL constant from a decl initializer INIT with decl type TYPE,
+ for use in a later add_const_value_attribute call. */
+
+static rtx
+rtl_for_decl_init (tree init, tree type)
+{
+ rtx rtl = NULL_RTX;
+
+ /* If a variable is initialized with a string constant without embedded
+ zeros, build CONST_STRING. */
+ if (TREE_CODE (init) == STRING_CST && TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree enttype = TREE_TYPE (type);
+ tree domain = TYPE_DOMAIN (type);
+ enum machine_mode mode = TYPE_MODE (enttype);
+
+ if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
+ && domain
+ && integer_zerop (TYPE_MIN_VALUE (domain))
+ && compare_tree_int (TYPE_MAX_VALUE (domain),
+ TREE_STRING_LENGTH (init) - 1) == 0
+ && ((size_t) TREE_STRING_LENGTH (init)
+ == strlen (TREE_STRING_POINTER (init)) + 1))
+ rtl = gen_rtx_CONST_STRING (VOIDmode,
+ ggc_strdup (TREE_STRING_POINTER (init)));
+ }
+ /* If the initializer is something that we know will expand into an
+ immediate RTL constant, expand it now. Expanding anything else
+ tends to produce unresolved symbols; see debug/5770 and c++/6381. */
+ /* Aggregate, vector, and complex types may contain constructors that may
+ result in code being generated when expand_expr is called, so we can't
+ handle them here. Integer and float are useful and safe types to handle
+ here. */
+ else if ((INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type))
+ && initializer_constant_valid_p (init, type) == null_pointer_node)
+ {
+ rtl = expand_expr (init, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+
+ /* If expand_expr returns a MEM, it wasn't immediate. */
+ gcc_assert (!rtl || !MEM_P (rtl));
+ }
+
+ return rtl;
+}
+
+/* Generate RTL for the variable DECL to represent its location. */
+