This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Medium model support in GCC


Hi,
this is update of patch I sent back in stage2 of 4.0.0 but holded it
because of the freeze at that time.
It implements the AMD64 medium model PIC (so one can have shared libs
with data segments exceeding 2GB) and changes ABI of static medium
model.
Unlike current implementation all the objects are categorized according
to their size and large data goes to separate sections (ldata/lrodata
etc) allowing use of fast addressing modes for small objects (under
64K).  

The patch is ABI breaking but ABI has been updated and there are little
meiudm model binaries around, so it should be safe.  On the other hand
small model libraries should now statically link into medium model
programs exceeding 2GB as long as they don't directly reference to large
datastructures defined in medium model.

The patch was bootstrapped/regtested
i686-pc-gnu-linux/x86_64-pc-gnu-linux and x86_64-pc-gnu-linux with
defaults changed to medium model on hacked version of binutils to
support .largecomm directive and new sections.  H. J. kindly developed
better patch but it don't seem to bootstrap at the moment.  I also added
somewhat lame testcase that the basic references and sections are
handled correctly and we will hopefully be able to add better testsuite
in near future.  

Also since last incarnation of patch I've put the large section handling
back into i386.c as requested in last Richard's review.

OK?

	* 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.
	* 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.

	* x86-64-medium-?.c: New.
Index: output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.159
diff -c -3 -p -r1.159 output.h
*** output.h	25 Jun 2005 02:00:41 -0000	1.159
--- output.h	30 Jun 2005 20:11:16 -0000
*************** extern void no_asm_to_stream (FILE *);
*** 500,505 ****
--- 500,543 ----
  #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)
*************** extern unsigned int default_section_type
*** 510,515 ****
--- 548,554 ----
  
  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);
  
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.517
diff -c -3 -p -r1.517 varasm.c
*** varasm.c	30 Jun 2005 12:17:36 -0000	1.517
--- varasm.c	30 Jun 2005 20:11:39 -0000
*************** default_select_section (tree decl, int r
*** 4987,5033 ****
      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;
--- 4987,4993 ----
Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.143
diff -c -3 -p -r1.143 i386-protos.h
*** config/i386/i386-protos.h	29 Jun 2005 17:27:16 -0000	1.143
--- config/i386/i386-protos.h	30 Jun 2005 20:11:47 -0000
*************** struct ix86_address
*** 259,264 ****
--- 259,268 ----
  
  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 *,
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.838
diff -c -3 -p -r1.838 i386.c
*** config/i386/i386.c	29 Jun 2005 17:27:16 -0000	1.838
--- config/i386/i386.c	30 Jun 2005 20:12:38 -0000
*************** unsigned int ix86_preferred_stack_bounda
*** 812,817 ****
--- 812,822 ----
  /* 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.  */
+ 
+ static int ix86_section_threshold = 65536;
+ 
  /* Prefix built by ASM_GENERATE_INTERNAL_LABEL.  */
  char internal_label_prefix[16];
  int internal_label_prefix_len;
*************** static const char * const x86_64_reg_cla
*** 945,950 ****
--- 950,961 ----
  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
*************** static void init_ext_80387_constants (vo
*** 965,970 ****
--- 976,984 ----
  #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
*************** override_options (void)
*** 1288,1301 ****
      {
        if (!strcmp (ix86_cmodel_string, "small"))
  	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
        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
--- 1302,1315 ----
      {
        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, "large") && !flag_pic)
  	ix86_cmodel = CM_LARGE;
        else
*************** override_options (void)
*** 1633,1638 ****
--- 1647,1823 ----
      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))
+     default_elf_select_section (decl, reloc, align);
+   else
+     {
+       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);
+       else
+         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))
+     default_unique_section (decl, reloc);
+   else
+     {
+       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);
+ 	}
+       else
+         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 ");
+   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)
  {
*************** ix86_expand_prologue (void)
*** 4617,4623 ****
  
    if (pic_reg_used)
      {
!       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.
--- 4802,4811 ----
  
    if (pic_reg_used)
      {
!       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.
*************** legitimate_constant_p (rtx x)
*** 5146,5151 ****
--- 5334,5347 ----
        if (GET_CODE (x) == UNSPEC)
  	switch (XINT (x, 1))
  	  {
+ 	  case UNSPEC_GOTOFF:
+ 	    /* For 64bit target we have to deal with GOTOFF as 64bit values,
+ 	       for 32bit targets these are always part of addressing mode
+ 	       there is no point to allow dealing with them separately -
+ 	       doing so just increase register pressure.  */
+ 	    if (!TARGET_64BIT)
+ 	      return false;
+ 	    return local_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
  	  case UNSPEC_TPOFF:
  	  case UNSPEC_NTPOFF:
  	    return local_exec_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
*************** legitimate_pic_operand_p (rtx x)
*** 5205,5215 ****
--- 5401,5422 ----
      {
      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:
+ 	    /* For 64bit target we have to deal with GOTOFF as 64bit values,
+ 	       for 32bit targets these are always part of addressing mode
+ 	       there is no point to allow dealing with them separately -
+ 	       doing so just increase register pressure.  */
+ 	    if (!TARGET_64BIT)
+ 	      return false;
+ 	    return local_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
  	  case UNSPEC_TPOFF:
  	    return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
  	  default:
*************** legitimate_pic_address_disp_p (rtx disp)
*** 5242,5248 ****
        if (tls_symbolic_operand (disp, GET_MODE (disp)))
  	return 0;
        if (GET_CODE (disp) == SYMBOL_REF
! 	  && ix86_cmodel == CM_SMALL_PIC
  	  && SYMBOL_REF_LOCAL_P (disp))
  	return 1;
        if (GET_CODE (disp) == LABEL_REF)
--- 5449,5457 ----
        if (tls_symbolic_operand (disp, GET_MODE (disp)))
  	return 0;
        if (GET_CODE (disp) == SYMBOL_REF
! 	  && (ix86_cmodel == CM_SMALL_PIC
! 	      || (ix86_cmodel == CM_MEDIUM_PIC
! 		   && !SYMBOL_REF_FAR_ADDR_P (disp)))
  	  && SYMBOL_REF_LOCAL_P (disp))
  	return 1;
        if (GET_CODE (disp) == LABEL_REF)
*************** legitimate_pic_address_disp_p (rtx disp)
*** 5257,5263 ****
  	  if (tls_symbolic_operand (op0, GET_MODE (op0)))
  	    return 0;
  	  if (((GET_CODE (op0) == SYMBOL_REF
! 		&& ix86_cmodel == CM_SMALL_PIC
  		&& SYMBOL_REF_LOCAL_P (op0))
  	       || GET_CODE (op0) == LABEL_REF)
  	      && GET_CODE (op1) == CONST_INT
--- 5466,5474 ----
  	  if (tls_symbolic_operand (op0, GET_MODE (op0)))
  	    return 0;
  	  if (((GET_CODE (op0) == SYMBOL_REF
! 		&& (ix86_cmodel == CM_SMALL_PIC
! 		    || (ix86_cmodel == CM_MEDIUM_PIC
! 		        && !SYMBOL_REF_FAR_ADDR_P (op0)))
  		&& SYMBOL_REF_LOCAL_P (op0))
  	       || GET_CODE (op0) == LABEL_REF)
  	      && GET_CODE (op1) == CONST_INT
*************** legitimate_pic_address_disp_p (rtx disp)
*** 5275,5281 ****
        /* 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)
  	return 0;
  
        if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
--- 5486,5493 ----
        /* 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_GOTOFF))
  	return 0;
  
        if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
*************** legitimize_pic_address (rtx orig, rtx re
*** 5605,5610 ****
--- 5817,5855 ----
  
    if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
      new = addr;
+   else if (TARGET_64BIT && local_symbolic_operand (addr, Pmode)
+ 	   && ix86_cmodel != CM_SMALL_PIC)
+     {
+       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
*************** ix86_expand_move (enum machine_mode mode
*** 7857,7863 ****
  #else
        if (GET_CODE (op0) == MEM)
  	op1 = force_reg (Pmode, op1);
!       else
  	op1 = legitimize_address (op1, op1, Pmode);
  #endif /* TARGET_MACHO */
      }
--- 8102,8108 ----
  #else
        if (GET_CODE (op0) == MEM)
  	op1 = force_reg (Pmode, op1);
!       else 
  	op1 = legitimize_address (op1, op1, Pmode);
  #endif /* TARGET_MACHO */
      }
*************** ix86_md_asm_clobbers (tree outputs ATTRI
*** 17443,17448 ****
--- 17688,17736 ----
    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
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.440
diff -c -3 -p -r1.440 i386.h
*** config/i386/i386.h	26 Jun 2005 05:18:34 -0000	1.440
--- config/i386/i386.h	30 Jun 2005 20:12:49 -0000
*************** do {									\
*** 961,967 ****
  #define REAL_PIC_OFFSET_TABLE_REGNUM  3
  
  #define PIC_OFFSET_TABLE_REGNUM				\
!   (TARGET_64BIT || !flag_pic ? INVALID_REGNUM		\
     : reload_completed ? REGNO (pic_offset_table_rtx)	\
     : REAL_PIC_OFFSET_TABLE_REGNUM)
  
--- 961,968 ----
  #define REAL_PIC_OFFSET_TABLE_REGNUM  3
  
  #define PIC_OFFSET_TABLE_REGNUM				\
!   ((TARGET_64BIT && ix86_cmodel == CM_SMALL_PIC)	\
!    || !flag_pic ? INVALID_REGNUM			\
     : reload_completed ? REGNO (pic_offset_table_rtx)	\
     : REAL_PIC_OFFSET_TABLE_REGNUM)
  
*************** enum cmodel {
*** 2148,2154 ****
    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.  */
  };
  
  extern enum cmodel ix86_cmodel;
--- 2149,2156 ----
    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_MEDIUM_PIC	/* Assumes code+got/plt fits in a 31 bit region.  */
  };
  
  extern enum cmodel ix86_cmodel;
*************** struct machine_function GTY(())
*** 2286,2291 ****
--- 2288,2298 ----
  #define X86_FILE_START_VERSION_DIRECTIVE false
  #define X86_FILE_START_FLTUSED false
  
+ /* Flag to mark data that is in the large address area (addressable
+    via "addl", that is, within a 2GByte offset of 0.  */
+ #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
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.642
diff -c -3 -p -r1.642 i386.md
*** config/i386/i386.md	30 Jun 2005 14:29:46 -0000	1.642
--- config/i386/i386.md	30 Jun 2005 20:13:20 -0000
***************
*** 1183,1190 ****
  	      (const_string "sselog1")
  	    (eq_attr "alternative" "7,8,9,10,11")
  	      (const_string "ssemov")
! 	    (and (ne (symbol_ref "flag_pic") (const_int 0))
! 		 (match_operand:SI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
  	   (const_string "imov")))
--- 1183,1191 ----
  	      (const_string "sselog1")
  	    (eq_attr "alternative" "7,8,9,10,11")
  	      (const_string "ssemov")
!  	    (and (ne (symbol_ref "flag_pic && ix86_cmodel == CM_SMALL_PIC")
! 	    	     (const_int 0))
!   		 (match_operand:DI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
  	   (const_string "imov")))
***************
*** 1992,1999 ****
  	      (const_string "ssecvt")
  	    (eq_attr "alternative" "4")
  	      (const_string "multi")
!  	    (and (ne (symbol_ref "flag_pic") (const_int 0))
! 		 (match_operand:DI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
  	   (const_string "imov")))
--- 1993,2001 ----
  	      (const_string "ssecvt")
  	    (eq_attr "alternative" "4")
  	      (const_string "multi")
!  	    (and (ne (symbol_ref "flag_pic && ix86_cmodel == CM_SMALL_PIC")
! 	    	     (const_int 0))
!   		 (match_operand:DI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
  	   (const_string "imov")))
***************
*** 13447,13452 ****
--- 13449,13463 ----
    [(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))
+    (clobber (reg:CC 17))]
+   "TARGET_64BIT"
+   "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
+   [(set_attr "type" "lea")
+    (set_attr "length" "6")])
+ 
  (define_expand "epilogue"
    [(const_int 1)]
    ""
Index: config/i386/predicates.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/predicates.md,v
retrieving revision 1.19
diff -c -3 -p -r1.19 predicates.md
*** config/i386/predicates.md	25 Jun 2005 01:21:24 -0000	1.19
--- config/i386/predicates.md	30 Jun 2005 20:13:24 -0000
***************
*** 110,116 ****
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL);
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
--- 110,117 ----
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       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,156 ****
  		 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
  		  && offset < 16*1024*1024
  		  && trunc_int_for_mode (offset, SImode) == offset)
  		return 1;
--- 151,159 ----
  		 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
! 		   || (ix86_cmodel == CM_MEDIUM
! 		       && !SYMBOL_REF_FAR_ADDR_P (op1)))
  		  && offset < 16*1024*1024
  		  && trunc_int_for_mode (offset, SImode) == offset)
  		return 1;
***************
*** 224,230 ****
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return ix86_cmodel == CM_SMALL;
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
--- 227,235 ----
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       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,253 ****
  		 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
  		  && GET_CODE (op2) == CONST_INT
  		  && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
  		  && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
--- 252,260 ----
  		 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
! 		   || (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))
Index: config/i386/x86-64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/x86-64.h,v
retrieving revision 1.13
diff -c -3 -p -r1.13 x86-64.h
*** config/i386/x86-64.h	25 Jun 2005 01:21:24 -0000	1.13
--- config/i386/x86-64.h	30 Jun 2005 20:13:24 -0000
*************** Boston, MA 02110-1301, USA.  */
*** 52,58 ****
   %{Wa,*:%*} %{m32:--32} %{m64:--64}"
  
  #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
!   asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
  
  /* This is used to align code labels according to Intel recommendations.  */
  
--- 52,62 ----
   %{Wa,*:%*} %{m32:--32} %{m64:--64}"
  
  #define 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.  */
  
*************** Boston, MA 02110-1301, USA.  */
*** 75,77 ****
--- 79,87 ----
  
  #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
Index: testsuite/gcc.dg/x86-64-medium-1.c
===================================================================
RCS file: testsuite/gcc.dg/x86-64-medium-1.c
diff -N testsuite/gcc.dg/x86-64-medium-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/x86-64-medium-1.c	30 Jun 2005 20:14:02 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fpic -mcmodel=medium" { target { { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler "lbss" } } */
+ /* { dg-final { scan-assembler-not "GOTOFF" } } */
+ /* { dg-final { scan-assembler "GOTPCREL" } } */
+ 
+ 
+ int a[65536]={0};
+ int *
+ q()
+ {
+   return a;
+ }
Index: testsuite/gcc.dg/x86-64-medium-2.c
===================================================================
RCS file: testsuite/gcc.dg/x86-64-medium-2.c
diff -N testsuite/gcc.dg/x86-64-medium-2.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/x86-64-medium-2.c	30 Jun 2005 20:14:02 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fpic -mcmodel=medium" { target { { x86_64-*-* } && ilp32 } } } */
+ /* { dg-final { scan-assembler "ldata" } } */
+ /* { dg-final { scan-assembler-not "GOTOFF" } } */
+ /* { dg-final { scan-assembler "GOTPCREL" } } */
+ 
+ 
+ int a[65536]={1};
+ int *
+ q()
+ {
+   return a;
+ }
Index: testsuite/gcc.dg/x86-64-medium-3.c
===================================================================
RCS file: testsuite/gcc.dg/x86-64-medium-3.c
diff -N testsuite/gcc.dg/x86-64-medium-3.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/x86-64-medium-3.c	30 Jun 2005 20:14:02 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fpic -mcmodel=medium" { target { { x86_64-*-* } && ilp32 } } } */
+ /* { dg-final { scan-assembler "largecomm" } } */
+ /* { dg-final { scan-assembler-not "GOTOFF" } } */
+ /* { dg-final { scan-assembler "GOTPCREL" } } */
+ 
+ 
+ int a[65536];
+ int *
+ q()
+ {
+   return a;
+ }
Index: testsuite/gcc.dg/x86-64-medium-4.c
===================================================================
RCS file: testsuite/gcc.dg/x86-64-medium-4.c
diff -N testsuite/gcc.dg/x86-64-medium-4.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/x86-64-medium-4.c	30 Jun 2005 20:14:02 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fpic -mcmodel=medium" { target { { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler "largecommon" } } */
+ /* { dg-final { scan-assembler "GOTOFF" } } */
+ /* { dg-final { scan-assembler-not "GOTPCREL" } } */
+ 
+ 
+ static int a[65536]={0};
+ int *
+ q()
+ {
+   return a;
+ }
Index: testsuite/gcc.dg/x86-64-medium-5.c
===================================================================
RCS file: testsuite/gcc.dg/x86-64-medium-5.c
diff -N testsuite/gcc.dg/x86-64-medium-5.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/x86-64-medium-5.c	30 Jun 2005 20:14:02 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fpic -mcmodel=medium" { target { { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler "lrodata" } } */
+ /* { dg-final { scan-assembler-not "GOTOFF" } } */
+ /* { dg-final { scan-assembler "GOTPCREL" } } */
+ 
+ 
+ const int a[65536]={1};
+ int *
+ q()
+ {
+   return a;
+ }
Index: testsuite/gcc.dg/x86-64-medium-6.c
===================================================================
RCS file: testsuite/gcc.dg/x86-64-medium-6.c
diff -N testsuite/gcc.dg/x86-64-medium-6.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/x86-64-medium-6.c	30 Jun 2005 20:14:02 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fpic -mcmodel=medium" { target { { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler "rodata" } } */
+ /* { dg-final { scan-assembler-not "GOTOFF" } } */
+ /* { dg-final { scan-assembler "GOTPCREL" } } */
+ 
+ 
+ const int a[256]={1};
+ int *
+ q()
+ {
+   return a;
+ }
Index: testsuite/gcc.dg/x86-64-medium-7.c
===================================================================
RCS file: testsuite/gcc.dg/x86-64-medium-7.c
diff -N testsuite/gcc.dg/x86-64-medium-7.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/x86-64-medium-7.c	30 Jun 2005 20:14:02 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fpic -mcmodel=medium" { target { { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler "rodata" } } */
+ /* { dg-final { scan-assembler-not "GOTOFF" } } */
+ /* { dg-final { scan-assembler-not "GOTPCREL" } } */
+ 
+ 
+ static const int a[256]={1};
+ int *
+ q()
+ {
+   return a;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]