Index: gcc/config/i386/i386.c |
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c |
index 2ee95d380b70b903ab2098a1f5228b6c115430ae..43b69e7490502bc1eb35422753c0ee03cbe0046e 100644 |
--- a/gcc/config/i386/i386.c |
+++ b/gcc/config/i386/i386.c |
@@ -3246,7 +3246,7 @@ override_options (bool main_args_p) |
/* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0) |
can be optimized to ap = __builtin_next_arg (0). */ |
- if (!TARGET_64BIT) |
+ if (!TARGET_64BIT && !TARGET_NACL) |
targetm.expand_builtin_va_start = NULL; |
if (TARGET_64BIT) |
@@ -6464,6 +6464,42 @@ ix86_build_builtin_va_list_abi (enum calling_abi abi) |
{ |
tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl; |
+ /* For i386 NaCl, use a structure of size 16, alignment 4, |
+ for compatibility with PNaCl. Only the first 4 bytes |
+ of the structure are used */ |
+ if (TARGET_NACL && !TARGET_64BIT) |
+ { |
+ tree f_ptr, f_pad1, f_pad2, f_pad3; |
+ record = (*lang_hooks.types.make_type) (RECORD_TYPE); |
+ type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record); |
+ |
+ f_ptr = build_decl (FIELD_DECL, get_identifier ("ptr"), |
+ ptr_type_node); |
+ f_pad1 = build_decl (FIELD_DECL, get_identifier ("pad1"), |
+ ptr_type_node); |
+ f_pad2 = build_decl (FIELD_DECL, get_identifier ("pad2"), |
+ ptr_type_node); |
+ f_pad3 = build_decl (FIELD_DECL, get_identifier ("pad3"), |
+ ptr_type_node); |
+ |
+ DECL_FIELD_CONTEXT (f_ptr) = record; |
+ DECL_FIELD_CONTEXT (f_pad1) = record; |
+ DECL_FIELD_CONTEXT (f_pad2) = record; |
+ DECL_FIELD_CONTEXT (f_pad3) = record; |
+ |
+ TREE_CHAIN (record) = type_decl; |
+ TYPE_NAME (record) = type_decl; |
+ TYPE_FIELDS (record) = f_ptr; |
+ TREE_CHAIN (f_ptr) = f_pad1; |
+ TREE_CHAIN (f_pad1) = f_pad2; |
+ TREE_CHAIN (f_pad2) = f_pad3; |
+ |
+ layout_type (record); |
+ |
+ /* The correct type is an array type of one element. */ |
+ return build_array_type (record, build_index_type (size_zero_node)); |
+ } |
+ |
/* For i386 we use plain pointer to argument area. */ |
if (!TARGET_64BIT || abi == MS_ABI) |
return build_pointer_type (char_type_node); |
@@ -6720,6 +6756,9 @@ is_va_list_char_pointer (tree type) |
{ |
tree canonic; |
+ if (TARGET_NACL) |
+ return false; |
+ |
/* For 32-bit it is always true. */ |
if (!TARGET_64BIT) |
return true; |
@@ -6738,6 +6777,19 @@ ix86_va_start (tree valist, rtx nextarg) |
tree gpr, fpr, ovf, sav, t; |
tree type; |
+ /* On NaCl 32, va_list is a structure. Use the first field. */ |
+ if (TARGET_NACL && !TARGET_64BIT) |
+ { |
+ tree f_ptr; |
+ f_ptr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); |
+ valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), |
+ valist); |
+ valist = build3 (COMPONENT_REF, TREE_TYPE(f_ptr), |
+ valist, f_ptr, NULL_TREE); |
+ std_expand_builtin_va_start (valist, nextarg); |
+ return; |
+ } |
+ |
/* Only 64bit target needs something special. */ |
if (!TARGET_64BIT || is_va_list_char_pointer (TREE_TYPE (valist))) |
{ |
@@ -6822,6 +6874,17 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, |
enum machine_mode nat_mode; |
int arg_boundary; |
+ /* On NaCl32, va_list is a structure. Use the first field only. */ |
+ if (TARGET_NACL && !TARGET_64BIT) |
+ { |
+ tree f_ptr; |
+ tree ptr; |
+ f_ptr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); |
+ ptr = build3 (COMPONENT_REF, TREE_TYPE (f_ptr), |
+ build_va_arg_indirect_ref (valist), f_ptr, NULL_TREE); |
+ return std_gimplify_va_arg_expr (ptr, type, pre_p, post_p); |
+ } |
+ |
/* Only 64bit target needs something special. */ |
if (!TARGET_64BIT || is_va_list_char_pointer (TREE_TYPE (valist))) |
return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); |
@@ -30172,7 +30235,7 @@ ix86_canonical_va_list_type (tree type) |
else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type))) |
type = TREE_TYPE (type); |
- if (TARGET_64BIT) |
+ if (TARGET_64BIT || TARGET_NACL) |
{ |
wtype = va_list_type_node; |
gcc_assert (wtype != NULL_TREE); |
@@ -30192,6 +30255,10 @@ ix86_canonical_va_list_type (tree type) |
} |
if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype)) |
return va_list_type_node; |
+ |
+ if (TARGET_NACL && !TARGET_64BIT) |
+ return NULL_TREE; |
+ |
wtype = sysv_va_list_type_node; |
gcc_assert (wtype != NULL_TREE); |
htype = type; |