Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Unified Diff: gcc/config/i386/i386.c

Issue 8479017: Add a compatibility function attribute (and flag) for nacl-gcc to (Closed) Base URL: http://git.chromium.org/native_client/nacl-gcc.git@master
Patch Set: period Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
Download patch
« no previous file with comments | « gcc/config/i386/i386.h ('k') | gcc/config/i386/nacl.opt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gcc/config/i386/i386.c
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f958b16c44d38ee1a5c98afab271b8ee6653693e..8f0111a8b3da630b15889d3f9701fc6df9ac7323 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -4260,6 +4260,12 @@ ix86_handle_cconv_attribute (tree *node, tree name,
if (TARGET_64BIT)
{
+ /* Usually x86-64 does not have attributes so they warn here, but
+ we have added an attribute pnaclcall so allow that. */
+ if (is_attribute_p ("pnaclcall", name))
+ /* Ignore the other i386 attributes and return. */
+ return NULL_TREE;
+
/* Do not warn when emulating the MS ABI. */
if (TREE_CODE (*node) != FUNCTION_TYPE || ix86_function_type_abi (*node)!=MS_ABI)
warning (OPT_Wattributes, "%qs attribute ignored",
@@ -4343,6 +4349,11 @@ ix86_comp_type_attributes (const_tree type1, const_tree type2)
!= !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2)))
return 0;
+ /* Check for mismatched pnaclcall types. */
+ if (!lookup_attribute ("pnaclcall", TYPE_ATTRIBUTES (type1))
+ != !lookup_attribute ("pnaclcall", TYPE_ATTRIBUTES (type2)))
+ return 0;
+
/* Check for mismatched return types (cdecl vs stdcall). */
if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
!= !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
@@ -4685,6 +4696,19 @@ ix86_cfun_abi (void)
/* regclass.c */
extern void init_regs (void);
+/* Return true if the function is decorated with a pnaclcall attribute. */
+static bool is_pnaclcall(const_tree fntype)
+{
+ return (fntype && lookup_attribute ("pnaclcall", TYPE_ATTRIBUTES (fntype)));
+}
+
+static bool ix86_cfun_pnaclcall (void)
+{
+ if (! cfun )
+ return 0;
+ return cfun->machine->pnaclcall;
+}
+
/* Implementation of call abi switching target hook. Specific to FNDECL
the specific call register sets are set. See also CONDITIONAL_REGISTER_USAGE
for more details. */
@@ -4692,9 +4716,15 @@ void
ix86_call_abi_override (const_tree fndecl)
{
if (fndecl == NULL_TREE)
- cfun->machine->call_abi = DEFAULT_ABI;
+ {
+ cfun->machine->call_abi = DEFAULT_ABI;
+ cfun->machine->pnaclcall = 0;
+ }
else
- cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl));
+ {
+ cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl));
+ cfun->machine->pnaclcall = is_pnaclcall (TREE_TYPE (fndecl));
+ }
}
/* MS and SYSV ABI have different set of call used registers. Avoid expensive
@@ -4765,6 +4795,9 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
? (!prototype_p (fntype) || stdarg_p (fntype))
: !libname);
+ if (TARGET_64BIT)
+ cum->pnaclcall = is_pnaclcall (fntype);
+
if (!TARGET_64BIT)
{
/* If there are variable arguments, then we won't pass anything
@@ -4946,7 +4979,8 @@ merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
static int
classify_argument (enum machine_mode mode, const_tree type,
- enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset)
+ enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset,
+ bool is_pnacl_cconv)
{
HOST_WIDE_INT bytes =
(mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
@@ -4966,6 +5000,10 @@ classify_argument (enum machine_mode mode, const_tree type,
tree field;
enum x86_64_reg_class subclasses[MAX_CLASSES];
+ /* Pass aggregates on the stack for PNaCl. */
+ if (TARGET_PNACL_CCONV || is_pnacl_cconv)
+ return 0;
+
/* On x86-64 we pass structures larger than 32 bytes on the stack. */
if (bytes > 32)
return 0;
@@ -5035,7 +5073,8 @@ classify_argument (enum machine_mode mode, const_tree type,
num = classify_argument (TYPE_MODE (type), type,
subclasses,
(int_bit_position (field)
- + bit_offset) % 256);
+ + bit_offset) % 256,
+ is_pnacl_cconv);
if (!num)
return 0;
for (i = 0; i < num; i++)
@@ -5055,7 +5094,8 @@ classify_argument (enum machine_mode mode, const_tree type,
{
int num;
num = classify_argument (TYPE_MODE (TREE_TYPE (type)),
- TREE_TYPE (type), subclasses, bit_offset);
+ TREE_TYPE (type), subclasses, bit_offset,
+ is_pnacl_cconv);
if (!num)
return 0;
@@ -5086,7 +5126,8 @@ classify_argument (enum machine_mode mode, const_tree type,
num = classify_argument (TYPE_MODE (TREE_TYPE (field)),
TREE_TYPE (field), subclasses,
- bit_offset);
+ bit_offset,
+ is_pnacl_cconv);
if (!num)
return 0;
for (i = 0; i < num; i++)
@@ -5327,10 +5368,10 @@ classify_argument (enum machine_mode mode, const_tree type,
class. Return 0 iff parameter should be passed in memory. */
static int
examine_argument (enum machine_mode mode, const_tree type, int in_return,
- int *int_nregs, int *sse_nregs)
+ int *int_nregs, int *sse_nregs, bool is_pnacl_cconv)
{
enum x86_64_reg_class regclass[MAX_CLASSES];
- int n = classify_argument (mode, type, regclass, 0);
+ int n = classify_argument (mode, type, regclass, 0, is_pnacl_cconv);
*int_nregs = 0;
*sse_nregs = 0;
@@ -5370,7 +5411,7 @@ examine_argument (enum machine_mode mode, const_tree type, int in_return,
static rtx
construct_container (enum machine_mode mode, enum machine_mode orig_mode,
const_tree type, int in_return, int nintregs, int nsseregs,
- const int *intreg, int sse_regno)
+ const int *intreg, int sse_regno, bool is_pnacl_cconv)
{
/* The following variables hold the static issued_error state. */
static bool issued_sse_arg_error;
@@ -5388,11 +5429,11 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
rtx exp[MAX_CLASSES];
rtx ret;
- n = classify_argument (mode, type, regclass, 0);
+ n = classify_argument (mode, type, regclass, 0, is_pnacl_cconv);
if (!n)
return NULL;
if (!examine_argument (mode, type, in_return, &needed_intregs,
- &needed_sseregs))
+ &needed_sseregs, is_pnacl_cconv))
return NULL;
if (needed_intregs > nintregs || needed_sseregs > nsseregs)
return NULL;
@@ -5666,7 +5707,7 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (!named && VALID_AVX256_REG_MODE (mode))
return;
- if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
+ if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs, cum->pnaclcall))
cum->words += words;
else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
{
@@ -5882,7 +5923,7 @@ function_arg_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return construct_container (mode, orig_mode, type, 0, cum->nregs,
cum->sse_nregs,
&x86_64_int_parameter_registers [cum->regno],
- cum->sse_regno);
+ cum->sse_regno, cum->pnaclcall);
}
static rtx
@@ -6180,7 +6221,7 @@ function_value_32 (enum machine_mode orig_mode, enum machine_mode mode,
static rtx
function_value_64 (enum machine_mode orig_mode, enum machine_mode mode,
- const_tree valtype)
+ const_tree valtype, bool is_pnacl_cconv)
{
rtx ret;
@@ -6210,7 +6251,7 @@ function_value_64 (enum machine_mode orig_mode, enum machine_mode mode,
ret = construct_container (mode, orig_mode, valtype, 1,
X86_64_REGPARM_MAX, X86_64_SSE_REGPARM_MAX,
- x86_64_int_return_registers, 0);
+ x86_64_int_return_registers, 0, is_pnacl_cconv);
/* For zero sized structures, construct_container returns NULL, but we
need to keep rest of compiler happy by returning meaningful value. */
@@ -6260,7 +6301,7 @@ ix86_function_value_1 (const_tree valtype, const_tree fntype_or_decl,
if (TARGET_64BIT && ix86_function_type_abi (fntype) == MS_ABI)
return function_value_ms_64 (orig_mode, mode);
else if (TARGET_64BIT)
- return function_value_64 (orig_mode, mode, valtype);
+ return function_value_64 (orig_mode, mode, valtype, is_pnaclcall (fntype));
else
return function_value_32 (orig_mode, mode, fntype, fn);
}
@@ -6330,10 +6371,12 @@ return_in_memory_32 (const_tree type, enum machine_mode mode)
}
static int ATTRIBUTE_UNUSED
-return_in_memory_64 (const_tree type, enum machine_mode mode)
+return_in_memory_64 (const_tree type, enum machine_mode mode,
+ bool is_pnacl_cconv)
{
int needed_intregs, needed_sseregs;
- return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
+ return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs,
+ is_pnacl_cconv);
}
static int ATTRIBUTE_UNUSED
@@ -6363,7 +6406,9 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
if (ix86_function_type_abi (fntype) == MS_ABI)
return return_in_memory_ms_64 (type, mode);
else
- return return_in_memory_64 (type, mode);
+ /* NOTE: fntype was meant to be unused, but we need to know
+ if a call was a pnaclcall. */
+ return return_in_memory_64 (type, mode, is_pnaclcall (fntype));
}
else
return return_in_memory_32 (type, mode);
@@ -6382,7 +6427,7 @@ ix86_sol10_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED
enum machine_mode mode = type_natural_mode (type, NULL);
if (TARGET_64BIT)
- return return_in_memory_64 (type, mode);
+ return return_in_memory_64 (type, mode, is_pnaclcall (fntype));
if (mode == BLKmode)
return 1;
@@ -6927,7 +6972,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
container = construct_container (nat_mode, TYPE_MODE (type),
type, 0, X86_64_REGPARM_MAX,
X86_64_SSE_REGPARM_MAX, intreg,
- 0);
+ 0, ix86_cfun_pnaclcall());
break;
}
@@ -6945,7 +6990,8 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
lab_false = create_artificial_label ();
lab_over = create_artificial_label ();
- examine_argument (nat_mode, type, 0, &needed_intregs, &needed_sseregs);
+ examine_argument (nat_mode, type, 0, &needed_intregs, &needed_sseregs,
+ ix86_cfun_pnaclcall());
need_temp = (!REG_P (container)
&& ((needed_intregs && TYPE_ALIGN (type) > 64)
@@ -30159,6 +30205,8 @@ static const struct attribute_spec ix86_attribute_table[] =
{ "fastcall", 0, 0, false, true, true, ix86_handle_cconv_attribute },
/* Cdecl attribute says the callee is a normal C declaration */
{ "cdecl", 0, 0, false, true, true, ix86_handle_cconv_attribute },
+ /* pnaclcall attribute says we are using the PNaCl x86_64 calling conv. */
+ { "pnaclcall", 0, 0, false, true, true, ix86_handle_cconv_attribute },
/* Regparm attribute specifies how many integer arguments are to be
passed in registers. */
{ "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute },
« no previous file with comments | « gcc/config/i386/i386.h ('k') | gcc/config/i386/nacl.opt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698