aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2005-07-31 11:12:34 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2005-07-31 09:12:34 +0000
commit7dcbf65993ee71dd17805df86bbff9d7a8716258 (patch)
tree87b4af46aac16d4fea8bf9447284ab5f9c4ceba0
parent3601aa8ab0cb341d65b608937d781a5e3c8c5b9b (diff)
downloadgcc-7dcbf65993ee71dd17805df86bbff9d7a8716258.zip
gcc-7dcbf65993ee71dd17805df86bbff9d7a8716258.tar.gz
gcc-7dcbf65993ee71dd17805df86bbff9d7a8716258.tar.bz2
output.h (enum section_category): Export from varasm.c
* output.h (enum section_category): Export from varasm.c (categorize_decl_for_section): Likewise. * varasm.c (enum section_category): Kill. (categorize_decl_for_section): Make global. * i386-protos.h (x86_output_aligned_bss, x86_elf_aligned_common): Declare. * i386.c (ix86_section_threshold): New static variable. (ix86_in_large_data_p, ix86_encode_section_info, x86_64_elf_unique_section, x86_64_elf_select_section): New functions. (TARGET_ENCODE_SECTION_INFO): Define (override_options): Enable medium model for PIC. (ix86_expand_prologue): Expand gen_set_got_rex64. (legitimate_constant_p): Handle new UNSPECs. (legitimate_pic_address_disp_p): Likewise. (legitimize_pic_address): Lower MEDIUM model addressing. * i386.h (PIC_OFFSET_TABLE_REGNUM): Set for medium model PIC. (enum cmodel): Add MEDIUM_PIC. (SYMBOL_REF_FAR_ADDR_P): New macro. (SYMBOL_FLAG_FAR_ADDR): New flag. * i386.md (movdi): Support medium model. (set_got_rex64): New pattern. * i386.opt (mlarge-data-threshold): New flag. * predicates.md (zext_operand/sext_operand): Deal with medium model. * x86-64.h (ASM_OUTPUT_ALIGNED_BSS): Use x86_output_aligned_bss. (ASM_OUTPUT_ALIGNED_COMMON, TARGET_ASM_SELECT_SECTION, TARGET_ASM_UNIQUE_SECTION): New. * invoke.texi (-mlarge_data_threshold): Document From-SVN: r102606
-rw-r--r--gcc/ChangeLog32
-rw-r--r--gcc/config/i386/i386-protos.h4
-rw-r--r--gcc/config/i386/i386.c293
-rw-r--r--gcc/config/i386/i386.h12
-rw-r--r--gcc/config/i386/i386.md8
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/predicates.md15
-rw-r--r--gcc/config/i386/x86-64.h12
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/output.h39
-rw-r--r--gcc/varasm.c40
11 files changed, 410 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a2c7bdc..967a610 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,37 @@
2005-07-31 Jan Hubicka <jh@suse.cz>
+ * output.h (enum section_category): Export from varasm.c
+ (categorize_decl_for_section): Likewise.
+ * varasm.c (enum section_category): Kill.
+ (categorize_decl_for_section): Make global.
+ * i386-protos.h (x86_output_aligned_bss, x86_elf_aligned_common):
+ Declare.
+ * i386.c (ix86_section_threshold): New static variable.
+ (ix86_in_large_data_p, ix86_encode_section_info,
+ x86_64_elf_unique_section,
+ x86_64_elf_select_section): New functions.
+ (TARGET_ENCODE_SECTION_INFO): Define
+ (override_options): Enable medium model for PIC.
+ (ix86_expand_prologue): Expand gen_set_got_rex64.
+ (legitimate_constant_p): Handle new UNSPECs.
+ (legitimate_pic_address_disp_p): Likewise.
+ (legitimize_pic_address): Lower MEDIUM model addressing.
+ * i386.h (PIC_OFFSET_TABLE_REGNUM): Set for medium model PIC.
+ (enum cmodel): Add MEDIUM_PIC.
+ (SYMBOL_REF_FAR_ADDR_P): New macro.
+ (SYMBOL_FLAG_FAR_ADDR): New flag.
+ * i386.md (movdi): Support medium model.
+ (set_got_rex64): New pattern.
+ * i386.opt (mlarge-data-threshold): New flag.
+ * predicates.md (zext_operand/sext_operand): Deal with medium model.
+ * x86-64.h (ASM_OUTPUT_ALIGNED_BSS): Use x86_output_aligned_bss.
+ (ASM_OUTPUT_ALIGNED_COMMON, TARGET_ASM_SELECT_SECTION,
+ TARGET_ASM_UNIQUE_SECTION): New.
+
+ * invoke.texi (-mlarge_data_threshold): Document
+
+2005-07-31 Jan Hubicka <jh@suse.cz>
+
* tree-outof-ssa.c (coalesce_ssa_name): Use coalesce_cost.
(coalesce_vars): Likewise.
* tree-ssa-live.c (coalesce_cost): New.
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index dfbf11a..94cecdc 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -259,6 +259,10 @@ struct ix86_address
extern int ix86_decompose_address (rtx, struct ix86_address *);
extern int memory_address_length (rtx addr);
+extern void x86_output_aligned_bss (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT, int);
+extern void x86_elf_aligned_common (FILE *, const char *,
+ unsigned HOST_WIDE_INT, int);
#ifdef RTX_CODE
extern void ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *,
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e9cf7db..94648b1 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -812,6 +812,11 @@ unsigned int ix86_preferred_stack_boundary;
/* Values 1-5: see jump.c */
int ix86_branch_cost;
+/* Variables which are this size or smaller are put in the data/bss
+ or ldata/lbss sections. */
+
+int ix86_section_threshold = 65536;
+
/* Prefix built by ASM_GENERATE_INTERNAL_LABEL. */
char internal_label_prefix[16];
int internal_label_prefix_len;
@@ -945,6 +950,12 @@ static const char * const x86_64_reg_class_name[] = {
static REAL_VALUE_TYPE ext_80387_constants_table [5];
static bool ext_80387_constants_init = 0;
static void init_ext_80387_constants (void);
+static bool ix86_in_large_data_p (tree);
+static void ix86_encode_section_info (tree, rtx, int);
+static void x86_64_elf_unique_section (tree decl, int reloc) ATTRIBUTE_UNUSED;
+static void x86_64_elf_select_section (tree decl, int reloc,
+ unsigned HOST_WIDE_INT align)
+ ATTRIBUTE_UNUSED;
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
@@ -965,6 +976,9 @@ static void init_ext_80387_constants (void);
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO ix86_encode_section_info
+
#undef TARGET_ASM_OPEN_PAREN
#define TARGET_ASM_OPEN_PAREN ""
#undef TARGET_ASM_CLOSE_PAREN
@@ -1291,14 +1305,14 @@ override_options (void)
{
if (!strcmp (ix86_cmodel_string, "small"))
ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+ else if (!strcmp (ix86_cmodel_string, "medium"))
+ ix86_cmodel = flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM;
else if (flag_pic)
sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
else if (!strcmp (ix86_cmodel_string, "32"))
ix86_cmodel = CM_32;
else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
ix86_cmodel = CM_KERNEL;
- else if (!strcmp (ix86_cmodel_string, "medium") && !flag_pic)
- ix86_cmodel = CM_MEDIUM;
else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
ix86_cmodel = CM_LARGE;
else
@@ -1502,6 +1516,14 @@ override_options (void)
else
ix86_branch_cost = i;
}
+ if (ix86_section_threshold_string)
+ {
+ i = atoi (ix86_section_threshold_string);
+ if (i < 0)
+ error ("-mlarge-data-threshold=%d is negative", i);
+ else
+ ix86_section_threshold = i;
+ }
if (ix86_tls_dialect_string)
{
@@ -1641,6 +1663,175 @@ override_options (void)
flag_schedule_insns_after_reload = flag_schedule_insns = 0;
}
+/* switch to the appropriate section for output of DECL.
+ DECL is either a `VAR_DECL' node or a constant of some sort.
+ RELOC indicates whether forming the initial value of DECL requires
+ link-time relocations. */
+
+static void
+x86_64_elf_select_section (tree decl, int reloc,
+ unsigned HOST_WIDE_INT align)
+{
+ if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+ && ix86_in_large_data_p (decl))
+ {
+ const char *sname = NULL;
+ switch (categorize_decl_for_section (decl, reloc, flag_pic))
+ {
+ case SECCAT_DATA:
+ sname = ".ldata";
+ break;
+ case SECCAT_DATA_REL:
+ sname = ".ldata.rel";
+ break;
+ case SECCAT_DATA_REL_LOCAL:
+ sname = ".ldata.rel.local";
+ break;
+ case SECCAT_DATA_REL_RO:
+ sname = ".ldata.rel.ro";
+ break;
+ case SECCAT_DATA_REL_RO_LOCAL:
+ sname = ".ldata.rel.ro.local";
+ break;
+ case SECCAT_BSS:
+ sname = ".lbss";
+ break;
+ case SECCAT_RODATA:
+ case SECCAT_RODATA_MERGE_STR:
+ case SECCAT_RODATA_MERGE_STR_INIT:
+ case SECCAT_RODATA_MERGE_CONST:
+ sname = ".lrodata";
+ break;
+ case SECCAT_SRODATA:
+ case SECCAT_SDATA:
+ case SECCAT_SBSS:
+ gcc_unreachable ();
+ case SECCAT_TEXT:
+ case SECCAT_TDATA:
+ case SECCAT_TBSS:
+ /* We don't split these for medium model. Place them into
+ default sections and hope for best. */
+ break;
+ }
+ if (sname)
+ {
+ named_section (decl, sname, reloc);
+ return;
+ }
+ }
+ default_elf_select_section (decl, reloc, align);
+}
+
+/* Build up a unique section name, expressed as a
+ STRING_CST node, and assign it to DECL_SECTION_NAME (decl).
+ RELOC indicates whether the initial value of EXP requires
+ link-time relocations. */
+
+static void
+x86_64_elf_unique_section (tree decl, int reloc)
+{
+ if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+ && ix86_in_large_data_p (decl))
+ {
+ const char *prefix = NULL;
+ /* We only need to use .gnu.linkonce if we don't have COMDAT groups. */
+ bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
+
+ switch (categorize_decl_for_section (decl, reloc, flag_pic))
+ {
+ case SECCAT_DATA:
+ case SECCAT_DATA_REL:
+ case SECCAT_DATA_REL_LOCAL:
+ case SECCAT_DATA_REL_RO:
+ case SECCAT_DATA_REL_RO_LOCAL:
+ prefix = one_only ? ".gnu.linkonce.ld." : ".ldata.";
+ break;
+ case SECCAT_BSS:
+ prefix = one_only ? ".gnu.linkonce.lb." : ".lbss.";
+ break;
+ case SECCAT_RODATA:
+ case SECCAT_RODATA_MERGE_STR:
+ case SECCAT_RODATA_MERGE_STR_INIT:
+ case SECCAT_RODATA_MERGE_CONST:
+ prefix = one_only ? ".gnu.linkonce.lr." : ".lrodata.";
+ break;
+ case SECCAT_SRODATA:
+ case SECCAT_SDATA:
+ case SECCAT_SBSS:
+ gcc_unreachable ();
+ case SECCAT_TEXT:
+ case SECCAT_TDATA:
+ case SECCAT_TBSS:
+ /* We don't split these for medium model. Place them into
+ default sections and hope for best. */
+ break;
+ }
+ if (prefix)
+ {
+ const char *name;
+ size_t nlen, plen;
+ char *string;
+ plen = strlen (prefix);
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = targetm.strip_name_encoding (name);
+ nlen = strlen (name);
+
+ string = alloca (nlen + plen + 1);
+ memcpy (string, prefix, plen);
+ memcpy (string + plen, name, nlen + 1);
+
+ DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
+ return;
+ }
+ }
+ default_unique_section (decl, reloc);
+}
+
+/* This says how to output assembler code to declare an
+ uninitialized external linkage data object.
+
+ For medim model x86-64 we need to use .largecomm opcode for
+ large objects. */
+void
+x86_elf_aligned_common (FILE *file,
+ const char *name, unsigned HOST_WIDE_INT size,
+ int align)
+{
+ if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+ && size > (unsigned int)ix86_section_threshold)
+ fprintf (file, ".largecomm\t");
+ else
+ fprintf (file, "%s", COMMON_ASM_OP);
+ assemble_name (file, name);
+ fprintf (file, ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
+ size, align / BITS_PER_UNIT);
+}
+
+/* Utility function for targets to use in implementing
+ ASM_OUTPUT_ALIGNED_BSS. */
+
+void
+x86_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
+ const char *name, unsigned HOST_WIDE_INT size,
+ int align)
+{
+ if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+ && size > (unsigned int)ix86_section_threshold)
+ named_section (decl, ".lbss", 0);
+ else
+ bss_section ();
+ ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
+#ifdef ASM_DECLARE_OBJECT_NAME
+ last_assemble_variable_decl = decl;
+ ASM_DECLARE_OBJECT_NAME (file, name, decl);
+#else
+ /* Standard thing is just output label for the object. */
+ ASM_OUTPUT_LABEL (file, name);
+#endif /* ASM_DECLARE_OBJECT_NAME */
+ ASM_OUTPUT_SKIP (file, size ? size : 1);
+}
+
void
optimization_options (int level, int size ATTRIBUTE_UNUSED)
{
@@ -4644,7 +4835,10 @@ ix86_expand_prologue (void)
if (pic_reg_used)
{
- insn = emit_insn (gen_set_got (pic_offset_table_rtx));
+ if (TARGET_64BIT)
+ insn = emit_insn (gen_set_got_rex64 (pic_offset_table_rtx));
+ else
+ insn = emit_insn (gen_set_got (pic_offset_table_rtx));
/* Even with accurate pre-reload life analysis, we can wind up
deleting all references to the pic register after reload.
@@ -5173,6 +5367,8 @@ legitimate_constant_p (rtx x)
if (GET_CODE (x) == UNSPEC)
switch (XINT (x, 1))
{
+ case UNSPEC_GOTOFF:
+ return TARGET_64BIT;
case UNSPEC_TPOFF:
case UNSPEC_NTPOFF:
return local_exec_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
@@ -5232,11 +5428,16 @@ legitimate_pic_operand_p (rtx x)
{
case CONST:
inner = XEXP (x, 0);
+ if (GET_CODE (inner) == PLUS
+ && GET_CODE (XEXP (inner, 1)) == CONST_INT)
+ inner = XEXP (inner, 0);
/* Only some unspecs are valid as "constants". */
if (GET_CODE (inner) == UNSPEC)
switch (XINT (inner, 1))
{
+ case UNSPEC_GOTOFF:
+ return TARGET_64BIT;
case UNSPEC_TPOFF:
return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
default:
@@ -5269,7 +5470,7 @@ legitimate_pic_address_disp_p (rtx disp)
if (tls_symbolic_operand (disp, GET_MODE (disp)))
return 0;
if (GET_CODE (disp) == SYMBOL_REF
- && ix86_cmodel == CM_SMALL_PIC
+ && !SYMBOL_REF_FAR_ADDR_P (disp)
&& SYMBOL_REF_LOCAL_P (disp))
return 1;
if (GET_CODE (disp) == LABEL_REF)
@@ -5284,7 +5485,7 @@ legitimate_pic_address_disp_p (rtx disp)
if (tls_symbolic_operand (op0, GET_MODE (op0)))
return 0;
if (((GET_CODE (op0) == SYMBOL_REF
- && ix86_cmodel == CM_SMALL_PIC
+ && !SYMBOL_REF_FAR_ADDR_P (op0)
&& SYMBOL_REF_LOCAL_P (op0))
|| GET_CODE (op0) == LABEL_REF)
&& GET_CODE (op1) == CONST_INT
@@ -5302,7 +5503,8 @@ legitimate_pic_address_disp_p (rtx disp)
/* We are unsafe to allow PLUS expressions. This limit allowed distance
of GOT tables. We should not need these anyway. */
if (GET_CODE (disp) != UNSPEC
- || XINT (disp, 1) != UNSPEC_GOTPCREL)
+ || (XINT (disp, 1) != UNSPEC_GOTPCREL
+ && XINT (disp, 1) != UNSPEC_GOTOFF))
return 0;
if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
@@ -5632,6 +5834,40 @@ legitimize_pic_address (rtx orig, rtx reg)
if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
new = addr;
+ else if (TARGET_64BIT
+ && ix86_cmodel != CM_SMALL_PIC
+ && local_symbolic_operand (addr, Pmode))
+ {
+ rtx tmpreg;
+ /* This symbol may be referenced via a displacement from the PIC
+ base address (@GOTOFF). */
+
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ if (GET_CODE (addr) == CONST)
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == PLUS)
+ {
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF);
+ new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1));
+ }
+ else
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ if (!reg)
+ tmpreg = gen_reg_rtx (Pmode);
+ else
+ tmpreg = reg;
+ emit_move_insn (tmpreg, new);
+
+ if (reg != 0)
+ {
+ new = expand_simple_binop (Pmode, PLUS, reg, pic_offset_table_rtx,
+ tmpreg, 1, OPTAB_DIRECT);
+ new = reg;
+ }
+ else new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
+ }
else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
{
/* This symbol may be referenced via a displacement from the PIC
@@ -7884,7 +8120,7 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
#else
if (GET_CODE (op0) == MEM)
op1 = force_reg (Pmode, op1);
- else
+ else
op1 = legitimize_address (op1, op1, Pmode);
#endif /* TARGET_MACHO */
}
@@ -17525,6 +17761,49 @@ ix86_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
return clobbers;
}
+/* Return true if this goes in small data/bss. */
+
+static bool
+ix86_in_large_data_p (tree exp)
+{
+ if (ix86_cmodel != CM_MEDIUM && ix86_cmodel != CM_MEDIUM_PIC)
+ return false;
+
+ /* Functions are never large data. */
+ if (TREE_CODE (exp) == FUNCTION_DECL)
+ return false;
+
+ if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+ {
+ const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+ if (strcmp (section, ".ldata") == 0
+ || strcmp (section, ".lbss") == 0)
+ return true;
+ return false;
+ }
+ else
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+
+ /* If this is an incomplete type with size 0, then we can't put it
+ in data because it might be too big when completed. */
+ if (!size || size > ix86_section_threshold)
+ return true;
+ }
+
+ return false;
+}
+static void
+ix86_encode_section_info (tree decl, rtx rtl, int first)
+{
+ default_encode_section_info (decl, rtl, first);
+
+ if (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
+ && ix86_in_large_data_p (decl))
+ SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FAR_ADDR;
+}
+
/* Worker function for REVERSE_CONDITION. */
enum rtx_code
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e140bd2..d1f5dd9 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -961,7 +961,8 @@ do { \
#define REAL_PIC_OFFSET_TABLE_REGNUM 3
#define PIC_OFFSET_TABLE_REGNUM \
- (TARGET_64BIT || !flag_pic ? INVALID_REGNUM \
+ ((TARGET_64BIT && ix86_cmodel == CM_SMALL_PIC) \
+ || !flag_pic ? INVALID_REGNUM \
: reload_completed ? REGNO (pic_offset_table_rtx) \
: REAL_PIC_OFFSET_TABLE_REGNUM)
@@ -2143,7 +2144,8 @@ enum cmodel {
CM_KERNEL, /* Assumes all code and data fits in the high 31 bits. */
CM_MEDIUM, /* Assumes code fits in the low 31 bits; data unlimited. */
CM_LARGE, /* No assumptions. */
- CM_SMALL_PIC /* Assumes code+data+got/plt fits in a 31 bit region. */
+ CM_SMALL_PIC, /* Assumes code+data+got/plt fits in a 31 bit region. */
+ CM_MEDIUM_PIC /* Assumes code+got/plt fits in a 31 bit region. */
};
extern enum cmodel ix86_cmodel;
@@ -2160,7 +2162,7 @@ enum asm_dialect {
extern enum asm_dialect ix86_asm_dialect;
extern unsigned int ix86_preferred_stack_boundary;
-extern int ix86_branch_cost;
+extern int ix86_branch_cost, ix86_section_threshold;
/* Smallest class containing REGNO. */
extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER];
@@ -2281,6 +2283,10 @@ struct machine_function GTY(())
#define X86_FILE_START_VERSION_DIRECTIVE false
#define X86_FILE_START_FLTUSED false
+/* Flag to mark data that is in the large address area. */
+#define SYMBOL_FLAG_FAR_ADDR (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_REF_FAR_ADDR_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_FAR_ADDR) != 0)
/*
Local variables:
version-control: t
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 685c645..d533408 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -13788,6 +13788,14 @@
[(set_attr "type" "multi")
(set_attr "length" "12")])
+(define_insn "set_got_rex64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
+ "TARGET_64BIT"
+ "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
+ [(set_attr "type" "lea")
+ (set_attr "length" "6")])
+
(define_expand "epilogue"
[(const_int 1)]
""
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index effd1e1..2a51fcb 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -87,6 +87,10 @@ mbranch-cost=
Target RejectNegative Joined Var(ix86_branch_cost_string)
Branches are this expensive (1-5, arbitrary units)
+mlarge-data-threshold=
+Target RejectNegative Joined Var(ix86_section_threshold_string)
+Data greater than given threshold will go into .ldata section in x86-64 medium model
+
mcmodel=
Target RejectNegative Joined Var(ix86_cmodel_string)
Use given x86-64 code model
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 292d46e..f8ff804 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -110,7 +110,8 @@
/* TLS symbols are not constant. */
if (tls_symbolic_operand (op, Pmode))
return false;
- return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL);
+ return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
+ || (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op)));
case LABEL_REF:
/* For certain code models, the code is near as well. */
@@ -150,7 +151,9 @@
end of 31bits boundary. We may also accept pretty
large negative constants knowing that all objects are
in the positive half of address space. */
- if (ix86_cmodel == CM_SMALL
+ if ((ix86_cmodel == CM_SMALL
+ || (ix86_cmodel == CM_MEDIUM
+ && !SYMBOL_REF_FAR_ADDR_P (op1)))
&& offset < 16*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
@@ -224,7 +227,9 @@
/* TLS symbols are not constant. */
if (tls_symbolic_operand (op, Pmode))
return false;
- return ix86_cmodel == CM_SMALL;
+ return (ix86_cmodel == CM_SMALL
+ || (ix86_cmodel == CM_MEDIUM
+ && !SYMBOL_REF_FAR_ADDR_P (op)));
case LABEL_REF:
/* For certain code models, the code is near as well. */
@@ -247,7 +252,9 @@
offsets, since one bit is available for free. Negative
offsets are limited by the size of NULL pointer area
specified by the ABI. */
- if (ix86_cmodel == CM_SMALL
+ if ((ix86_cmodel == CM_SMALL
+ || (ix86_cmodel == CM_MEDIUM
+ && !SYMBOL_REF_FAR_ADDR_P (op1)))
&& GET_CODE (op2) == CONST_INT
&& trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
&& trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
diff --git a/gcc/config/i386/x86-64.h b/gcc/config/i386/x86-64.h
index c80353b..b0e6947 100644
--- a/gcc/config/i386/x86-64.h
+++ b/gcc/config/i386/x86-64.h
@@ -52,7 +52,11 @@ Boston, MA 02110-1301, USA. */
%{Wa,*:%*} %{m32:--32} %{m64:--64}"
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
- asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+ x86_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ x86_elf_aligned_common (FILE, NAME, SIZE, ALIGN);
/* This is used to align code labels according to Intel recommendations. */
@@ -75,3 +79,9 @@ Boston, MA 02110-1301, USA. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION x86_64_elf_select_section
+
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION x86_64_elf_unique_section
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5004419..399083d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -521,7 +521,7 @@ Objective-C and Objective-C++ Dialects}.
-m96bit-long-double -mregparm=@var{num} -msseregparm @gol
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
-mcmodel=@var{code-model} @gol
--m32 -m64}
+-m32 -m64 -mlarge-data-threshold=@var{num}}
@emph{IA-64 Options}
@gccoptlist{-mbig-endian -mlittle-endian -mgnu-as -mgnu-ld -mno-pic @gol
@@ -9046,6 +9046,11 @@ their size as well as function calling convention for function taking
@code{long double} will be modified. Hence they will not be binary
compatible with arrays or structures in code compiled without that switch.
+@item -mmlarge-data-threshold=@var{number}
+@opindex mlarge-data-threshold=@var{number}
+When @option{-mcmodel=medium} is specified, the data greater than
+@var{threshold} are placed in large data section. This value must be the
+same across all object linked into the binarry and defaults to 65535.
@item -msvr3-shlib
@itemx -mno-svr3-shlib
diff --git a/gcc/output.h b/gcc/output.h
index 221e4df..c0dfb5f 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -500,6 +500,44 @@ extern void no_asm_to_stream (FILE *);
#define SECTION_NOTYPE 0x80000 /* don't output @progbits */
#define SECTION_MACH_DEP 0x100000 /* subsequent bits reserved for target */
+/* A helper function for default_elf_select_section and
+ default_elf_unique_section. Categorizes the DECL. */
+
+enum section_category
+{
+ SECCAT_TEXT,
+
+ SECCAT_RODATA,
+ SECCAT_RODATA_MERGE_STR,
+ SECCAT_RODATA_MERGE_STR_INIT,
+ SECCAT_RODATA_MERGE_CONST,
+ SECCAT_SRODATA,
+
+ SECCAT_DATA,
+
+ /* To optimize loading of shared programs, define following subsections
+ of data section:
+ _REL Contains data that has relocations, so they get grouped
+ together and dynamic linker will visit fewer pages in memory.
+ _RO Contains data that is otherwise read-only. This is useful
+ with prelinking as most relocations won't be dynamically
+ linked and thus stay read only.
+ _LOCAL Marks data containing relocations only to local objects.
+ These relocations will get fully resolved by prelinking. */
+ SECCAT_DATA_REL,
+ SECCAT_DATA_REL_LOCAL,
+ SECCAT_DATA_REL_RO,
+ SECCAT_DATA_REL_RO_LOCAL,
+
+ SECCAT_SDATA,
+ SECCAT_TDATA,
+
+ SECCAT_BSS,
+ SECCAT_SBSS,
+ SECCAT_TBSS
+};
+
+
extern bool set_named_section_flags (const char *, unsigned int);
#define named_section_flags(NAME, FLAGS) \
named_section_real((NAME), (FLAGS), /*decl=*/NULL_TREE)
@@ -510,6 +548,7 @@ extern unsigned int default_section_type_flags_1 (tree, const char *, int, int);
extern void default_no_named_section (const char *, unsigned int, tree);
extern void default_elf_asm_named_section (const char *, unsigned int, tree);
+extern enum section_category categorize_decl_for_section (tree, int, int);
extern void default_coff_asm_named_section (const char *, unsigned int, tree);
extern void default_pe_asm_named_section (const char *, unsigned int, tree);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 88068b5..6c5a533 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -5017,47 +5017,7 @@ default_select_section (tree decl, int reloc,
data_section ();
}
-/* A helper function for default_elf_select_section and
- default_elf_unique_section. Categorizes the DECL. */
-
enum section_category
-{
- SECCAT_TEXT,
-
- SECCAT_RODATA,
- SECCAT_RODATA_MERGE_STR,
- SECCAT_RODATA_MERGE_STR_INIT,
- SECCAT_RODATA_MERGE_CONST,
- SECCAT_SRODATA,
-
- SECCAT_DATA,
-
- /* To optimize loading of shared programs, define following subsections
- of data section:
- _REL Contains data that has relocations, so they get grouped
- together and dynamic linker will visit fewer pages in memory.
- _RO Contains data that is otherwise read-only. This is useful
- with prelinking as most relocations won't be dynamically
- linked and thus stay read only.
- _LOCAL Marks data containing relocations only to local objects.
- These relocations will get fully resolved by prelinking. */
- SECCAT_DATA_REL,
- SECCAT_DATA_REL_LOCAL,
- SECCAT_DATA_REL_RO,
- SECCAT_DATA_REL_RO_LOCAL,
-
- SECCAT_SDATA,
- SECCAT_TDATA,
-
- SECCAT_BSS,
- SECCAT_SBSS,
- SECCAT_TBSS
-};
-
-static enum section_category
-categorize_decl_for_section (tree, int, int);
-
-static enum section_category
categorize_decl_for_section (tree decl, int reloc, int shlib)
{
enum section_category ret;