Chromium Code Reviews| Index: gcc/config/i386/i386.c |
| diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c |
| index f958b16c44d38ee1a5c98afab271b8ee6653693e..107c5cca3534d25892bf9eec888996203acec6e1 100644 |
| --- a/gcc/config/i386/i386.c |
| +++ b/gcc/config/i386/i386.c |
| @@ -4260,12 +4260,21 @@ ix86_handle_cconv_attribute (tree *node, tree name, |
| if (TARGET_64BIT) |
| { |
| - /* 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", |
| - IDENTIFIER_POINTER (name)); |
| - *no_add_attrs = true; |
| - return NULL_TREE; |
| + /* Usually x86-64 does not have attributes so they warn here, but |
|
Roland McGrath
2011/11/09 01:02:58
This is GNU code, so use GNU style:
/* Comment
jvoung - send to chromium...
2011/11/09 21:02:03
Done.
|
| + * we have added an attribute pnaclcall! Allow that. */ |
| + if (is_attribute_p ("pnaclcall", name)) { |
| + /* This is okay, go ahead and leave no_add_attrs alone. |
| + * Ignore the other i386 attributes though... |
| + */ |
| + return NULL_TREE; |
| + } else { |
| + /* 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", |
| + IDENTIFIER_POINTER (name)); |
| + *no_add_attrs = true; |
| + return NULL_TREE; |
| + } |
| } |
| /* Can combine fastcall with stdcall (redundant) and sseregparm. */ |
| @@ -4343,6 +4352,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,16 +4699,36 @@ ix86_cfun_abi (void) |
| /* regclass.c */ |
| extern void init_regs (void); |
| +/* Return true if the function is decorated with a pnaclcall attribute. */ |
|
Roland McGrath
2011/11/09 01:02:58
GNU style here: Two spaces after period, brace sty
jvoung - send to chromium...
2011/11/09 21:02:03
Done.
|
| +static bool is_pnaclcall(const_tree fntype) { |
| + if (fntype && lookup_attribute ("pnaclcall", |
|
Roland McGrath
2011/11/09 01:02:58
Don't need an if to return a boolean.
jvoung - send to chromium...
2011/11/09 21:02:03
Done.
|
| + TYPE_ATTRIBUTES (fntype))) { |
| + return 1; |
| + } else { |
| + return 0; |
| + } |
| +} |
| + |
| +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. */ |
| void |
| ix86_call_abi_override (const_tree fndecl) |
| { |
| - if (fndecl == NULL_TREE) |
| + if (fndecl == NULL_TREE) { |
| cfun->machine->call_abi = DEFAULT_ABI; |
| - else |
| + cfun->machine->pnaclcall = 0; |
| + } else { |
| 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 +4799,10 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ |
| ? (!prototype_p (fntype) || stdarg_p (fntype)) |
| : !libname); |
| + if (TARGET_64BIT) { |
|
Roland McGrath
2011/11/09 01:02:58
GNU style: no braces for a single line consequent.
jvoung - send to chromium...
2011/11/09 21:02:03
Done.
|
| + cum->pnaclcall = is_pnaclcall (fntype); |
| + } |
| + |
| if (!TARGET_64BIT) |
| { |
| /* If there are variable arguments, then we won't pass anything |
| @@ -4946,7 +4984,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 +5005,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 +5078,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 +5099,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 +5131,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 +5373,11 @@ 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 +5417,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 +5435,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 +5713,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 +5929,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 +6227,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 +6257,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 +6307,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 +6377,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 |
| @@ -6362,8 +6411,12 @@ 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); |
| + else { |
| + /* 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 +6435,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; |
| @@ -6860,7 +6913,7 @@ ix86_va_start (tree valist, rtx nextarg) |
| static tree |
| ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, |
| - gimple_seq *post_p) |
| + gimple_seq *post_p) |
| { |
| static const int intreg[6] = { 0, 1, 2, 3, 4, 5 }; |
| tree f_gpr, f_fpr, f_ovf, f_sav; |
| @@ -6927,7 +6980,8 @@ 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 +6999,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 +30214,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 }, |
|
Roland McGrath
2011/11/09 01:02:58
This could be upstreamable with a different attrib
jvoung - send to chromium...
2011/11/09 21:02:03
That's a good point... maybe revisit this later?
|
| /* Regparm attribute specifies how many integer arguments are to be |
| passed in registers. */ |
| { "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute }, |