/* Default language-specific hooks.
- Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Alexandre Oliva <aoliva@redhat.com>
#include "toplev.h"
#include "tree.h"
#include "tree-inline.h"
-#include "tree-gimple.h"
+#include "gimple.h"
#include "rtl.h"
#include "insn-config.h"
#include "integrate.h"
#include "langhooks-def.h"
#include "ggc.h"
#include "diagnostic.h"
+#include "tree-diagnostic.h"
+#include "cgraph.h"
+#include "output.h"
/* Do nothing; in many cases the default hook. */
{
}
-/* Do nothing (int). */
-
-void
-lhd_do_nothing_i (int ARG_UNUSED (i))
+/* Pass through (tree). */
+tree
+lhd_pass_through_t (tree t)
{
+ return t;
}
/* Do nothing (int, int, int). Return NULL_TREE. */
{
}
-/* Do nothing (return the tree node passed). */
-
-tree
-lhd_return_tree (tree t)
-{
- return t;
-}
-
/* Do nothing (return NULL_TREE). */
tree
bool
lhd_post_options (const char ** ARG_UNUSED (pfilename))
{
+ /* Excess precision other than "fast" requires front-end
+ support. */
+ flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
return false;
}
{
}
-/* Called from staticp. */
-
-tree
-lhd_staticp (tree ARG_UNUSED (exp))
-{
- return NULL;
-}
-
/* Called from check_global_declarations. */
bool
/* This is what used to exist in check_global_declarations. Probably
not many of these actually apply to non-C languages. */
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
return false;
if (TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl))
return false;
&& (TREE_STATIC (decl)
|| DECL_EXTERNAL (decl)
|| TREE_PUBLIC (decl))));
-
+
/* By default, assume the name to use in assembly code is the same
as that used in the source language. (That's correct for C, and
GCC used to set DECL_ASSEMBLER_NAME to the same value as
compatibility with existing front-ends. This assumption is wrapped
in a target hook, to allow for target-specific modification of the
identifier.
-
+
Can't use just the variable's own name for a variable whose scope
is less than the whole compilation. Concatenate a distinguishing
number - we use the DECL_UID. */
- if (TREE_PUBLIC (decl) || DECL_CONTEXT (decl) == NULL_TREE)
+ if (TREE_PUBLIC (decl) || DECL_FILE_SCOPE_P (decl))
id = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl));
else
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
char *label;
-
+
ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
id = get_identifier (label);
}
return -1;
}
-/* This is the default expand_expr function. */
-
-rtx
-lhd_expand_expr (tree ARG_UNUSED (t), rtx ARG_UNUSED (r),
- enum machine_mode ARG_UNUSED (mm),
- int ARG_UNUSED (em),
- rtx * ARG_UNUSED (a))
-{
- gcc_unreachable ();
-}
-
-/* The default language-specific function for expanding a decl. After
- the language-independent cases are handled, this function will be
- called. If this function is not defined, it is assumed that
- declarations other than those for variables and labels do not require
- any RTL generation. */
-
-int
-lhd_expand_decl (tree ARG_UNUSED (t))
-{
- return 0;
-}
-
/* This is the default decl_printable_name function. */
const char *
return TYPE_QUALS (t);
}
-/* lang_hooks.expr_size: Determine the size of the value of an expression T
- in a language-specific way. Returns a tree for the size in bytes. */
-
-tree
-lhd_expr_size (const_tree exp)
-{
- if (DECL_P (exp)
- && DECL_SIZE_UNIT (exp) != 0)
- return DECL_SIZE_UNIT (exp);
- else
- return size_in_bytes (TREE_TYPE (exp));
-}
-
/* lang_hooks.gimplify_expr re-writes *EXPR_P into GIMPLE form. */
int
-lhd_gimplify_expr (tree *expr_p ATTRIBUTE_UNUSED, tree *pre_p ATTRIBUTE_UNUSED,
- tree *post_p ATTRIBUTE_UNUSED)
+lhd_gimplify_expr (tree *expr_p ATTRIBUTE_UNUSED,
+ gimple_seq *pre_p ATTRIBUTE_UNUSED,
+ gimple_seq *post_p ATTRIBUTE_UNUSED)
{
return GS_UNHANDLED;
}
return true;
}
-/* Return the COMDAT group into which DECL should be placed. */
-
-const char *
-lhd_comdat_group (tree decl)
-{
- return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-}
-
/* lang_hooks.decls.final_write_globals: perform final processing on
global variables. */
void
write_global_declarations (void)
{
+ tree globals, decl, *vec;
+ int len, i;
+
+ /* This lang hook is dual-purposed, and also finalizes the
+ compilation unit. */
+ cgraph_finalize_compilation_unit ();
+
/* Really define vars that have had only a tentative definition.
Really output inline functions that must actually be callable
and have not been output so far. */
- tree globals = lang_hooks.decls.getdecls ();
- int len = list_length (globals);
- tree *vec = XNEWVEC (tree, len);
- int i;
- tree decl;
+ globals = lang_hooks.decls.getdecls ();
+ len = list_length (globals);
+ vec = XNEWVEC (tree, len);
/* Process the decls in reverse order--earliest first.
Put them into VEC from back to front, then take out from front. */
- for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+ for (i = 0, decl = globals; i < len; i++, decl = DECL_CHAIN (decl))
vec[len - i - 1] = decl;
wrapup_global_declarations (vec, len);
/* Called to perform language-specific initialization of CTX. */
void
-lhd_initialize_diagnostics (struct diagnostic_context *ctx ATTRIBUTE_UNUSED)
+lhd_initialize_diagnostics (diagnostic_context *ctx ATTRIBUTE_UNUSED)
+{
+}
+
+/* Called to perform language-specific options initialization. */
+void
+lhd_init_options (unsigned int decoded_options_count ATTRIBUTE_UNUSED,
+ struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED)
+{
+}
+
+/* By default, always complain about options for the wrong language. */
+bool
+lhd_complain_wrong_lang_p (const struct cl_option *option ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+/* By default, no language-specific options are valid. */
+bool
+lhd_handle_option (size_t code ATTRIBUTE_UNUSED,
+ const char *arg ATTRIBUTE_UNUSED,
+ int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+ location_t loc ATTRIBUTE_UNUSED,
+ const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
{
+ return false;
}
/* The default function to print out name of current function that caused
if (diagnostic_last_function_changed (context, diagnostic))
{
const char *old_prefix = context->printer->prefix;
- tree abstract_origin = diagnostic->abstract_origin;
+ tree abstract_origin = diagnostic_abstract_origin (diagnostic);
char *new_prefix = (file && abstract_origin == NULL)
? file_name_as_prefix (file) : NULL;
if (abstract_origin)
{
ao = BLOCK_ABSTRACT_ORIGIN (abstract_origin);
- while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+ while (TREE_CODE (ao) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (ao)
+ && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
ao = BLOCK_ABSTRACT_ORIGIN (ao);
gcc_assert (TREE_CODE (ao) == FUNCTION_DECL);
fndecl = ao;
if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
pp_printf
(context->printer, _("In member function %qs"),
- lang_hooks.decl_printable_name (fndecl, 2));
+ identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)));
else
pp_printf
(context->printer, _("In function %qs"),
- lang_hooks.decl_printable_name (fndecl, 2));
+ identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)));
while (abstract_origin)
{
{
ao = BLOCK_ABSTRACT_ORIGIN (block);
- while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+ while (TREE_CODE (ao) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (ao)
+ && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
ao = BLOCK_ABSTRACT_ORIGIN (ao);
if (TREE_CODE (ao) == FUNCTION_DECL)
while (block && TREE_CODE (block) == BLOCK)
block = BLOCK_SUPERCONTEXT (block);
- if (TREE_CODE (block) == FUNCTION_DECL)
+ if (block && TREE_CODE (block) == FUNCTION_DECL)
fndecl = block;
abstract_origin = NULL;
}
pp_newline (context->printer);
if (s.file != NULL)
{
-#ifdef USE_MAPPED_LOCATION
- if (flag_show_column && s.column != 0)
+ if (context->show_column)
pp_printf (context->printer,
_(" inlined from %qs at %s:%d:%d"),
- lang_hooks.decl_printable_name (fndecl, 2),
+ identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)),
s.file, s.line, s.column);
else
-#endif
pp_printf (context->printer,
_(" inlined from %qs at %s:%d"),
- lang_hooks.decl_printable_name (fndecl, 2),
+ identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)),
s.file, s.line);
}
else
pp_printf (context->printer, _(" inlined from %qs"),
- lang_hooks.decl_printable_name (fndecl, 2));
+ identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)));
}
}
pp_character (context->printer, ':');
tree
lhd_callgraph_analyze_expr (tree *tp ATTRIBUTE_UNUSED,
- int *walk_subtrees ATTRIBUTE_UNUSED,
- tree decl ATTRIBUTE_UNUSED)
+ int *walk_subtrees ATTRIBUTE_UNUSED)
{
return NULL;
}
}
tree
-lhd_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
- bool *ti ATTRIBUTE_UNUSED, bool *se ATTRIBUTE_UNUSED)
+lhd_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se ATTRIBUTE_UNUSED)
{
return expr;
}
tree
lhd_omp_assignment (tree clause ATTRIBUTE_UNUSED, tree dst, tree src)
{
- return build_gimple_modify_stmt (dst, src);
+ return build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
}
/* Register language specific type size variables as potentially OpenMP
{
}
-tree
-add_builtin_function (const char *name,
- tree type,
- int function_code,
- enum built_in_class cl,
- const char *library_name,
- tree attrs)
+/* Common function for add_builtin_function and
+ add_builtin_function_ext_scope. */
+static tree
+add_builtin_function_common (const char *name,
+ tree type,
+ int function_code,
+ enum built_in_class cl,
+ const char *library_name,
+ tree attrs,
+ tree (*hook) (tree))
{
tree id = get_identifier (name);
- tree decl = build_decl (FUNCTION_DECL, id, type);
+ tree decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, id, type);
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_BUILT_IN_CLASS (decl) = cl;
- DECL_FUNCTION_CODE (decl) = -1;
- gcc_assert (DECL_FUNCTION_CODE (decl) >= function_code);
- DECL_FUNCTION_CODE (decl) = function_code;
+ DECL_FUNCTION_CODE (decl) = (enum built_in_function) function_code;
+
+ /* DECL_FUNCTION_CODE is a bitfield; verify that the value fits. */
+ gcc_assert (DECL_FUNCTION_CODE (decl) == function_code);
if (library_name)
{
else
decl_attributes (&decl, NULL_TREE, 0);
- return lang_hooks.builtin_function (decl);
+ return hook (decl);
+
+}
+
+/* Create a builtin function. */
+
+tree
+add_builtin_function (const char *name,
+ tree type,
+ int function_code,
+ enum built_in_class cl,
+ const char *library_name,
+ tree attrs)
+{
+ return add_builtin_function_common (name, type, function_code, cl,
+ library_name, attrs,
+ lang_hooks.builtin_function);
+}
+
+/* Like add_builtin_function, but make sure the scope is the external scope.
+ This is used to delay putting in back end builtin functions until the ISA
+ that defines the builtin is declared via function specific target options,
+ which can save memory for machines like the x86_64 that have multiple ISAs.
+ If this points to the same function as builtin_function, the backend must
+ add all of the builtins at program initialization time. */
+tree
+add_builtin_function_ext_scope (const char *name,
+ tree type,
+ int function_code,
+ enum built_in_class cl,
+ const char *library_name,
+ tree attrs)
+{
+ return add_builtin_function_common (name, type, function_code, cl,
+ library_name, attrs,
+ lang_hooks.builtin_function_ext_scope);
}
tree
lang_hooks.decls.pushdecl (decl);
return decl;
}
+
+/* LTO hooks. */
+
+/* Used to save and restore any previously active section. */
+static section *saved_section;
+
+
+/* Begin a new LTO output section named NAME. This default implementation
+ saves the old section and emits assembly code to switch to the new
+ section. */
+
+void
+lhd_begin_section (const char *name)
+{
+ section *section;
+
+ /* Save the old section so we can restore it in lto_end_asm_section. */
+ gcc_assert (!saved_section);
+ saved_section = in_section;
+ if (!saved_section)
+ saved_section = text_section;
+
+ /* Create a new section and switch to it. */
+ section = get_section (name, SECTION_DEBUG, NULL);
+ switch_to_section (section);
+}
+
+
+/* Write DATA of length LEN to the current LTO output section. This default
+ implementation just calls assemble_string and frees BLOCK. */
+
+void
+lhd_append_data (const void *data, size_t len, void *block)
+{
+ if (data)
+ assemble_string ((const char *)data, len);
+ free (block);
+}
+
+
+/* Finish the current LTO output section. This default implementation emits
+ assembly code to switch to any section previously saved by
+ lhd_begin_section. */
+
+void
+lhd_end_section (void)
+{
+ if (saved_section)
+ {
+ switch_to_section (saved_section);
+ saved_section = NULL;
+ }
+}