* [PATCH, ARM] attribute target (thumb,arm) [4/6]
@ 2014-11-19 13:54 Christian Bruel
0 siblings, 0 replies; only message in thread
From: Christian Bruel @ 2014-11-19 13:54 UTC (permalink / raw)
To: ramana Radhakrishnan; +Cc: Richard Earnshaw, Terry Guo, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 373 bytes --]
Implements and document the hooks to support target_attributes.
The emission of blx is handled directly for armv5 to overcome a bug with
the current binutils that fails with calls to a static symbol in a
different section. (e.g .text -> .text.startup) in different modes.
(ref https://sourceware.org/bugzilla/show_bug.cgi?id=17505)
Regtests included
Thanks
Christian
[-- Attachment #2: attr4.patch --]
[-- Type: text/x-patch, Size: 16115 bytes --]
2014-09-23 Christian Bruel <christian.bruel@st.com>
* config/arm/arm.opt (mthumb): Save.
* config/arm/arm.h (arm_valid_target_attribute_tree): Declare.
(arm_reset_previous_fndecl, arm_change_mode_p): Likewise.
(SWITCHABLE_TARGET): Define.
* config/arm/arm.c (arm_reset_previous_fndecl): New functions.
(arm_valid_target_attribute_tree, arm_change_mode_p): Likewise.
(arm_valid_target_attribute_p): Likewise.
(arm_set_current_function, arm_can_inline_p): Likewise.
(arm_valid_target_attribute_rec): Likewise.
(arm_previous_fndecl): New variable.
(TARGET_SET_CURRENT_FUNCTION, TARGET_OPTION_VALID_ATTRIBUTE_P): Define.
(TARGET_CAN_INLINE_P): Define.
(arm_asm_trampoline_template): Emit mode.
(arm_file_start): Don't set unified syntax.
(arm_declare_function_name): Set unified syntax and mode.
(arm_option_override): Init target_option_default_node.
and target_option_current_node.
* config/arm/arm.md (*call_value_symbol): Set mode when possible.
(*call_symbol): Likewise.
* doc/extend.texi: Document ARM target and pragma attribute.
* doc/invoke.texi: Likewise.
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/config/arm/arm.c e/gcc/gcc/config/arm/arm.c
--- d/gcc/gcc/config/arm/arm.c 2014-11-18 08:51:50.000000000 +0100
+++ e/gcc/gcc/config/arm/arm.c 2014-11-18 09:05:57.000000000 +0100
@@ -80,6 +80,7 @@
#include "opts.h"
#include "dumpfile.h"
#include "gimple-expr.h"
+#include "target-globals.h"
#include "builtins.h"
#include "tm-constrs.h"
#include "rtl-iter.h"
@@ -258,6 +259,9 @@ static tree arm_build_builtin_va_list (v
static void arm_expand_builtin_va_start (tree, rtx);
static tree arm_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
static void arm_option_override (void);
+static void arm_set_current_function (tree);
+static bool arm_can_inline_p (tree, tree);
+static bool arm_valid_target_attribute_p (tree, tree, tree, int);
static unsigned HOST_WIDE_INT arm_shift_truncation_mask (machine_mode);
static bool arm_cannot_copy_insn_p (rtx_insn *);
static int arm_issue_rate (void);
@@ -400,6 +404,9 @@ static const struct attribute_spec arm_a
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P arm_can_inline_p
+
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE arm_option_override
@@ -412,6 +419,12 @@ static const struct attribute_spec arm_a
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
+#undef TARGET_SET_CURRENT_FUNCTION
+#define TARGET_SET_CURRENT_FUNCTION arm_set_current_function
+
+#undef TARGET_OPTION_VALID_ATTRIBUTE_P
+#define TARGET_OPTION_VALID_ATTRIBUTE_P arm_valid_target_attribute_p
+
#undef TARGET_SCHED_REORDER
#define TARGET_SCHED_REORDER arm_sched_reorder
@@ -3205,6 +3218,11 @@ arm_option_override (void)
/* Register global variables with the garbage collector. */
arm_add_gc_roots ();
+
+ /* Save the initial options in case the user does function specific
+ options. */
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (&global_options);
}
static void
@@ -3358,13 +3376,20 @@ arm_warn_func_return (tree decl)
static void
arm_asm_trampoline_template (FILE *f)
{
+ if (TARGET_UNIFIED_ASM)
+ fprintf (f, "\t.syntax unified\n");
+ else
+ fprintf (f, "\t.syntax divided\n");
+
if (TARGET_ARM)
{
+ fprintf (f, "\t.arm\n");
asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM, PC_REGNUM);
asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", PC_REGNUM, PC_REGNUM);
}
else if (TARGET_THUMB2)
{
+ fprintf (f, "\t.thumb\n");
/* The Thumb-2 trampoline is similar to the arm implementation.
Unlike 16-bit Thumb, we enter the stub in thumb mode. */
asm_fprintf (f, "\tldr.w\t%r, [%r, #4]\n",
@@ -26874,6 +26899,23 @@ thumb_far_jump_used_p (void)
return 0;
}
+/* Check that FUNC is called with a different mode. */
+
+bool
+arm_change_mode_p (tree func)
+{
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return false;
+
+ tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (func);
+
+ if (!callee_tree)
+ callee_tree = target_option_default_node;
+
+ struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
+
+ return (TREE_TARGET_THUMB (callee_opts) != TARGET_THUMB);
+}
/* Given the stack offsets and register mask in OFFSETS, decide how
many additional registers to push instead of subtracting a constant
@@ -28448,9 +28490,6 @@ arm_file_start (void)
{
int val;
- if (TARGET_UNIFIED_ASM)
- asm_fprintf (asm_out_file, "\t.syntax unified\n");
-
if (TARGET_BPABI)
{
const char *fpu_name;
@@ -32387,9 +32426,201 @@ arm_is_constant_pool_ref (rtx x)
&& CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)));
}
+/* Remember the last target of arm_set_current_function. */
+static GTY(()) tree arm_previous_fndecl;
+
+/* Invalidate arm_previous_fndecl. */
+void
+arm_reset_previous_fndecl (void)
+{
+ arm_previous_fndecl = NULL_TREE;
+}
+
+/* Establish appropriate back-end context for processing the function
+ FNDECL. The argument might be NULL to indicate processing at top
+ level, outside of any function scope. */
+static void
+arm_set_current_function (tree fndecl)
+{
+ if (!fndecl || fndecl == arm_previous_fndecl)
+ return;
+
+ tree old_tree = (arm_previous_fndecl
+ ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl)
+ : NULL_TREE);
+
+ tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+
+ arm_previous_fndecl = fndecl;
+ if (old_tree == new_tree)
+ ;
+
+ else if (new_tree)
+ {
+ cl_target_option_restore (&global_options,
+ TREE_TARGET_OPTION (new_tree));
+
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else
+ TREE_TARGET_GLOBALS (new_tree)
+ = save_target_globals_default_opts ();
+ }
+
+ else if (old_tree)
+ {
+ new_tree = target_option_current_node;
+
+ cl_target_option_restore (&global_options,
+ TREE_TARGET_OPTION (new_tree));
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else if (new_tree == target_option_default_node)
+ restore_target_globals (&default_target_globals);
+ else
+ TREE_TARGET_GLOBALS (new_tree)
+ = save_target_globals_default_opts ();
+ }
+
+ arm_option_params_internal (&global_options);
+}
+
+/* Hook to determine if one function can safely inline another. */
+
+static bool
+arm_can_inline_p (tree caller ATTRIBUTE_UNUSED, tree callee ATTRIBUTE_UNUSED)
+{
+ /* Overidde default hook: Always OK to inline between different modes.
+ Function with mode specific instructions, e.g using asm, must be explicitely
+ protected with noinline. */
+ return true;
+}
+
+/* Inner function to process the attribute((target(...))), take an argument and
+ set the current options from the argument. If we have a list, recursively
+ go over the list. */
+
+static bool
+arm_valid_target_attribute_rec (tree args, struct gcc_options *opts)
+{
+ if (TREE_CODE (args) == TREE_LIST)
+ {
+ bool ret = true;
+ for (; args; args = TREE_CHAIN (args))
+ if (TREE_VALUE (args)
+ && !arm_valid_target_attribute_rec (TREE_VALUE (args), opts))
+ ret = false;
+ return ret;
+ }
+
+ else if (TREE_CODE (args) != STRING_CST)
+ {
+ error ("attribute %<target%> argument not a string");
+ return false;
+ }
+
+ char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
+ while (argstr && *argstr != '\0')
+ {
+ while (ISSPACE (*argstr))
+ argstr++;
+
+ if (!strncmp (argstr, "thumb", 5))
+ {
+ opts->x_target_flags |= MASK_THUMB;
+ arm_option_check_internal (opts);
+ return true;
+ }
+
+ if (!strncmp (argstr, "arm", 3))
+ {
+ opts->x_target_flags &= ~MASK_THUMB;
+ arm_option_check_internal (opts);
+ return true;
+ }
+
+ warning (0, "attribute(target(\"%s\")) is unknown", argstr);
+ return false;
+ }
+
+ return false;
+}
+
+/* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
+
+tree
+arm_valid_target_attribute_tree (tree args, struct gcc_options *opts)
+{
+ tree t = NULL_TREE;
+
+ if (!arm_valid_target_attribute_rec (args, opts))
+ return NULL_TREE;
+
+ t = build_target_option_node (opts);
+
+ /* Do any overrides, such as global options arch=xxx. */
+ arm_option_override_internal (opts);
+
+ return t;
+}
+
+/* Hook to validate attribute((target("string"))). */
+
+static bool
+arm_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags))
+{
+ tree cur_tree, new_optimize;
+ struct gcc_options func_options;
+ gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE));
+
+ tree old_optimize = build_optimization_node (&global_options);
+
+ /* Get the optimization options of the current function. */
+ tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+ if (!func_optimize)
+ func_optimize = old_optimize;
+
+ /* Init func_options. */
+ memset (&func_options, 0, sizeof (func_options));
+ init_options_struct (&func_options, NULL);
+ lang_hooks.init_options_struct (&func_options);
+
+ /* Initialize func_options to the defaults. */
+ cl_optimization_restore (&func_options,
+ TREE_OPTIMIZATION (func_optimize));
+
+ cl_target_option_restore (&func_options,
+ TREE_TARGET_OPTION (target_option_default_node));
+
+ /* Set func_options flags with new target mode. */
+ cur_tree = arm_valid_target_attribute_tree (args, &func_options);
+
+ if (cur_tree == NULL_TREE)
+ return false;
+
+ new_optimize = build_optimization_node (&func_options);
+
+ if (fndecl)
+ {
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree;
+
+ if (old_optimize != new_optimize)
+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+ }
+
+ return true;
+}
+
void
arm_declare_function_name (FILE *stream, const char *name, tree decl)
{
+ if (TARGET_UNIFIED_ASM)
+ fprintf (stream, "\t.syntax unified\n");
+ else
+ fprintf (stream, "\t.syntax divided\n");
+
if (TARGET_THUMB)
{
if (is_called_in_ARM_mode (decl)
@@ -32401,6 +32635,8 @@ arm_declare_function_name (FILE *stream,
else
fprintf (stream, "\t.thumb\n\t.thumb_func\n");
}
+ else
+ fprintf (stream, "\t.arm\n");
if (TARGET_POKE_FUNCTION_NAME)
arm_poke_function_name (stream, (const char *) name);
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/config/arm/arm.h e/gcc/gcc/config/arm/arm.h
--- d/gcc/gcc/config/arm/arm.h 2014-11-13 12:19:45.000000000 +0100
+++ e/gcc/gcc/config/arm/arm.h 2014-11-13 13:48:59.000000000 +0100
@@ -2359,4 +2359,8 @@ extern const char *host_detect_local_cpu
#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS
#define TARGET_SUPPORTS_WIDE_INT 1
+
+/* For switching between functions with different target attributes. */
+#define SWITCHABLE_TARGET 1
+
#endif /* ! GCC_ARM_H */
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/config/arm/arm.md e/gcc/gcc/config/arm/arm.md
--- d/gcc/gcc/config/arm/arm.md 2014-11-18 08:51:50.000000000 +0100
+++ e/gcc/gcc/config/arm/arm.md 2014-11-18 08:49:18.000000000 +0100
@@ -7728,6 +7728,13 @@
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
"*
{
+ rtx op = operands[0];
+
+ /* Switch mode now when possible. */
+ if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
+ && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
+ return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
+
return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
}"
[(set_attr "type" "call")]
@@ -7745,6 +7754,13 @@
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
"*
{
+ rtx op = operands[1];
+
+ /* Switch mode now when possible. */
+ if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
+ && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
+ return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
+
return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
}"
[(set_attr "type" "call")]
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/config/arm/arm.opt e/gcc/gcc/config/arm/arm.opt
--- d/gcc/gcc/config/arm/arm.opt 2014-11-13 12:15:32.000000000 +0100
+++ e/gcc/gcc/config/arm/arm.opt 2014-11-13 14:07:44.000000000 +0100
@@ -186,7 +186,7 @@ Target RejectNegative Joined UInteger Va
Specify the minimum bit alignment of structures
mthumb
-Target Report RejectNegative Mask(THUMB)
+Target Report RejectNegative Mask(THUMB) Save
Generate code for Thumb state
mthumb-interwork
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/config/arm/arm-protos.h e/gcc/gcc/config/arm/arm-protos.h
--- d/gcc/gcc/config/arm/arm-protos.h 2014-11-13 12:21:36.000000000 +0100
+++ e/gcc/gcc/config/arm/arm-protos.h 2014-11-13 13:07:47.000000000 +0100
@@ -207,6 +207,8 @@ extern int arm_dllexport_p (tree);
extern int arm_dllimport_p (tree);
extern void arm_mark_dllexport (tree);
extern void arm_mark_dllimport (tree);
+extern bool arm_change_mode_p (tree);
+extern tree arm_valid_target_attribute_tree (tree, struct gcc_options *);
#endif
extern void arm_pr_long_calls (struct cpp_reader *);
@@ -297,6 +299,8 @@ extern bool arm_autoinc_modes_ok_p (mach
extern void arm_emit_eabi_attribute (const char *, int, int);
+extern void arm_reset_previous_fndecl (void);
+
/* Defined in gcc/common/config/arm-common.c. */
extern const char *arm_rewrite_selected_cpu (const char *name);
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/doc/extend.texi e/gcc/gcc/doc/extend.texi
--- d/gcc/gcc/doc/extend.texi 2014-11-12 13:58:42.000000000 +0100
+++ e/gcc/gcc/doc/extend.texi 2014-11-13 14:53:49.000000000 +0100
@@ -3953,10 +3953,24 @@ You can either use multiple
strings to specify multiple options, or separate the options
with a comma (@samp{,}).
-The @code{target} attribute is presently implemented for
-i386/x86_64, PowerPC, and Nios II targets only.
+The @code{target} attribute is implemented for
+ARM, i386/x86_64, PowerPC, and Nios II targets.
The options supported are specific to each target.
+for ARM, the following options are allowed:
+
+@table @samp
+@item thumb
+@cindex @code{target("thumb")} attribute
+Force Thumb1 Thumb2 code generation depending on the architecture.
+
+@item arm
+@cindex @code{target("arm")} attribute
+Force ARM code generation.
+@end table
+
+Functions from different modes can be inlined , unless the callee has asm statements.
+
On the 386, the following options are allowed:
@table @samp
@@ -17728,8 +17742,8 @@ function. The parenthesis around the op
@xref{Function Attributes}, for more information about the
@code{target} attribute and the attribute syntax.
-The @code{#pragma GCC target} pragma is presently implemented for
-i386/x86_64, PowerPC, and Nios II targets only.
+The @code{#pragma GCC target} pragma is implemented for
+ARM, i386/x86_64, PowerPC, and Nios II targets.
@end table
@table @code
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/doc/invoke.texi e/gcc/gcc/doc/invoke.texi
--- d/gcc/gcc/doc/invoke.texi 2014-11-18 08:51:29.000000000 +0100
+++ e/gcc/gcc/doc/invoke.texi 2014-11-18 08:49:02.000000000 +0100
@@ -12982,6 +12982,10 @@ that executes in ARM state, but the defa
configuring GCC with the @option{--with-mode=}@var{state}
configure option.
+You can also override the ARM and Thumb mode for each function
+by using the @code{target("thumb")} and @code{target("arm")} function attributes
+(@pxref{Function Attributes}) or pragmas (@pxref{Function Specific Option Pragmas}).
+
@item -mtpcs-frame
@opindex mtpcs-frame
Generate a stack frame that is compliant with the Thumb Procedure Call
[-- Attachment #3: attr4-tests.patch --]
[-- Type: text/x-patch, Size: 3056 bytes --]
2014-09-23 Christian Bruel <christian.bruel@st.com>
* gcc.target/arm/attr_arm.c: New test.
* gcc.target/arm/attr_thumb.c: New test.
* gcc.target/arm/attr_thumb-static.c: New test.
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c e/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c
--- d/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c 1970-01-01 01:00:00.000000000 +0100
+++ e/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c 2014-11-18 10:56:51.000000000 +0100
@@ -0,0 +1,13 @@
+/* Check that attribute target arm is recogniwed. */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arm_ok } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler ".arm" } } */
+/* { dg-final { scan-assembler-not "ite" } } */
+
+int __attribute__((target("arm")))
+foo(int a)
+{
+ return a ? 1 : 5;
+}
+
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c e/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c
--- d/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c 1970-01-01 01:00:00.000000000 +0100
+++ e/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c 2014-11-18 10:56:19.000000000 +0100
@@ -0,0 +1,12 @@
+/* Check that attribute target arm is rejected for M profile. */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arm_ok } */
+/* { dg-add-options arm_arch_v6m } */
+
+int __attribute__((target("arm")))
+foo(int a)
+{ /* { dg-error "does not support" } */
+ return a ? 1 : 5;
+}
+
+
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c e/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c
--- d/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 1970-01-01 01:00:00.000000000 +0100
+++ e/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 2014-11-18 11:02:25.000000000 +0100
@@ -0,0 +1,13 @@
+/* Check that attribute target thumb is recogniwed. */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler ".thumb" } } */
+/* { dg-final { scan-assembler "ite" } } */
+
+int __attribute__((target("thumb")))
+foo(int a)
+{
+ return a ? 1 : 5;
+}
+
diff '--exclude=ChangeLog*' '--exclude=.svn' '--exclude=*~' '--exclude=#*#' -rupN d/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c e/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c
--- d/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c 1970-01-01 01:00:00.000000000 +0100
+++ e/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c 2014-11-18 11:02:22.000000000 +0100
@@ -0,0 +1,24 @@
+/* Check that a change mode to a static function is correctly handled. */
+/* { dg-do run } */
+/* { dg-require-effective-target arm_thumb1_ok } */
+
+static void
+ __attribute__((__noinline__))
+foo (void)
+{
+ __asm__ ("");
+}
+
+static void
+__attribute__((__noinline__))
+__attribute__((target("thumb")))
+bar (void)
+{
+ __asm__ ("");
+}
+
+int main()
+{
+ foo();
+ bar();
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-11-19 13:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-19 13:54 [PATCH, ARM] attribute target (thumb,arm) [4/6] Christian Bruel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).