This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH,i386][4.3][RFC] PIC Generation on windows/cygwin
On 1/27/07, Andrew Pinski <pinskia@physics.uc.edu> wrote:
>
> *** gcc/config/i386/i386.c (revision 121238)
> --- gcc/config/i386/i386.c (working copy)
> *************** static void x86_64_elf_unique_section (t
> *** 1404,1409 ****
> --- 1404,1421 ----
> static section *x86_64_elf_select_section (tree decl, int reloc,
> unsigned HOST_WIDE_INT align)
> ATTRIBUTE_UNUSED;
> + #if TARGET_CYGMING
> + /* Support for position independent code on target cygming.
> + In position independent mode, references to static and global
> + symbols are generated as offsets relative to a base label. The same
> + base label is used for computing relative offsets of labels
> + in the address diff vector for a switch statement. There is
> + one base label in each function. */
> +
> + /* The base label used for all relative offsets in pic mode. */
> + static rtx base_label;
> + #endif
This is not really GC safe.
Thanks for pointing this out. (Also changed base_label to pic_base_label).
> + #if ! TARGET_CYGMING
> xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
> + #endif
Use:
if (!TARGET_CYGMING)
instead.
Done.
> + #if ! TARGET_CYGMING
> if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
> output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
> else
> output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %1+(.-%a2)}", xops);
> + #else
> + base_label = xops[2];
> + #endif
Likewise.
Done.
> + #if TARGET_CYGMING
> + addr = i386_pe_generate_imported_symbol_ref(addr);
> + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
> + #else
> new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
> + #endif
This one needs to stay #if because it uses a function from a non x86 generic
file.
> + #if ! TARGET_CYGMING
> fputs ("@GOTOFF", file);
> + #else
> + /* On target CYGMING, we interpret GOTOFF of a symbol
> + as the offset of the symbol from the PIC base label. */
> + putc ('-', file);
> + output_pic_addr_const (file, base_label, code);
> + #endif
Again if(!TARGET_CYGMING)
Done.
> + #if TARGET_CYGMING
> + else if (TARGET_CYGMING)
> + {
> + fprintf (file, "%s%s%d-%s%d\n",
> + ASM_LONG, LPREFIX, value, LPREFIX,
> + CODE_LABEL_NUMBER(XEXP(base_label,0)));
> + }
> + #endif
Don't need "#if TARGET_CYGMING" really.
It is needed because base_label is conditionally declared only CYGMING.
Without the #if, it will not compile on linux.
> ! #if TARGET_CYGMING
> ! {
> ! /* On target CYGMING, there is no PLT. Convert
> ! the function address to a PIC reference. */
> ! rtx reg;
> ! reg = legitimize_pic_address (XEXP (fnaddr, 0), 0);
> ! XEXP (fnaddr, 0) = reg;
> ! }
> ! #endif
Again if (TARGET_CYGMING)
Done.
Thanks,
Andrew Pinski
I have attached the new patch. I have started bootstrap/test again
with these changes
and will report back once it is complete.
Thanks
Murali
=================================================================
Index: gcc/config/i386/i386.h
===================================================================
*** gcc/config/i386/i386.h (revision 121377)
--- gcc/config/i386/i386.h (working copy)
*************** extern int x86_prefetch_sse, x86_cmpxchg
*** 294,299 ****
--- 294,302 ----
redefines this to 1. */
#define TARGET_MACHO 0
+ /* Default value for TARGET_CYGMING. cygming.h redefines this to 1. */
+ #define TARGET_CYGMING 0
+
/* Subtargets may reset this to 1 in order to enable 96-bit long double
with the rounding mode forced to 53 bits. */
#define TARGET_96_ROUND_53_LONG_DOUBLE 0
Index: gcc/config/i386/cygming.h
===================================================================
*** gcc/config/i386/cygming.h (revision 121377)
--- gcc/config/i386/cygming.h (working copy)
*************** Boston, MA 02110-1301, USA. */
*** 49,54 ****
--- 49,58 ----
#define TARGET_EXECUTABLE_SUFFIX ".exe"
+ /* support for position independent code on cygming */
+ #undef TARGET_CYGMING
+ #define TARGET_CYGMING 1
+
#include <stdio.h>
#define MAYBE_UWIN_CPP_BUILTINS() /* Nothing. */
*************** union tree_node;
*** 117,136 ****
Explicitly set data flag with 'd'. */
#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata,\"dr\""
- /* Don't allow flag_pic to propagate since gas may produce invalid code
- otherwise. */
-
- #undef SUBTARGET_OVERRIDE_OPTIONS
- #define SUBTARGET_OVERRIDE_OPTIONS \
- do { \
- if (flag_pic) \
- { \
- warning (0, "-f%s ignored for target (all code is position
independent)",\
- (flag_pic > 1) ? "PIC" : "pic"); \
- flag_pic = 0; \
- } \
- } while (0) \
-
/* Define this macro if references to a symbol must be treated
differently depending on something about the variable or
function named by the symbol (such as what section it is in).
--- 121,126 ----
*************** extern void i386_pe_record_exported_symb
*** 297,302 ****
--- 287,293 ----
extern void i386_pe_file_end (void);
extern int i386_pe_dllexport_name_p (const char *);
extern int i386_pe_dllimport_name_p (const char *);
+ extern rtx i386_pe_generate_imported_symbol_ref (rtx addr);
/* For Win32 ABI compatibility */
#undef DEFAULT_PCC_STRUCT_RETURN
Index: gcc/config/i386/predicates.md
===================================================================
*** gcc/config/i386/predicates.md (revision 121377)
--- gcc/config/i386/predicates.md (working copy)
*************** (define_predicate "local_symbolic_operan
*** 456,461 ****
--- 456,473 ----
return 0;
})
+ ;; Return true if OP is a imported symbolic operand
+ ;; (using the dllimport storage-class attribute).
+ (define_predicate "imported_symbolic_operand"
+ (match_code "symbol_ref")
+ {
+ #if TARGET_CYGMING
+ if (i386_pe_dllimport_name_p(XSTR (op, 0)))
+ return 1;
+ #endif
+ return 0;
+ })
+
;; Test for various thread-local symbols.
(define_predicate "tls_symbolic_operand"
(and (match_code "symbol_ref")
Index: gcc/config/i386/winnt.c
===================================================================
*** gcc/config/i386/winnt.c (revision 121377)
--- gcc/config/i386/winnt.c (working copy)
*************** i386_pe_file_end (void)
*** 733,736 ****
--- 733,761 ----
}
}
+ /* Given an RTX of type symbol_ref, generate and return an RTX
+ of type symbol_ref whose name is prefixed with DLL_IMPORT_PREFIX.
+ */
+
+ rtx i386_pe_generate_imported_symbol_ref (rtx addr)
+ {
+ const char *oldname;
+ char *newname;
+ tree idp;
+ rtx symref;
+
+ gcc_assert (GET_CODE (addr) == SYMBOL_REF);
+ oldname = XSTR (addr, 0);
+ gcc_assert(! i386_pe_dllimport_name_p (oldname));
+ /* strip dllexport prefix, if any. */
+ oldname = i386_pe_strip_name_encoding(oldname);
+ newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
+ sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
+
+ idp = get_identifier (newname);
+
+ symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
+ return symref;
+ }
+
#include "gt-winnt.h"
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c (revision 121377)
--- gcc/config/i386/i386.c (working copy)
*************** static void x86_64_elf_unique_section (t
*** 1404,1409 ****
--- 1404,1421 ----
static section *x86_64_elf_select_section (tree decl, int reloc,
unsigned HOST_WIDE_INT align)
ATTRIBUTE_UNUSED;
+ #if TARGET_CYGMING
+ /* Support for position independent code on target cygming.
+ In position independent mode, references to static and global
+ symbols are generated as offsets relative to a base label. The same
+ base label is used for computing relative offsets of labels
+ in the address diff vector for a switch statement. There is
+ one base label in each function. */
+
+ /* The base label used for all relative offsets in pic mode. */
+ static GTY(()) rtx pic_base_label;
+ #endif
+
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
*************** output_set_got (rtx dest, rtx label ATTR
*** 5091,5100 ****
rtx xops[3];
xops[0] = dest;
xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
! if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
{
xops[2] = gen_rtx_LABEL_REF (Pmode, label ? label : gen_label_rtx ());
if (!flag_pic)
--- 5103,5117 ----
rtx xops[3];
xops[0] = dest;
+ #if (!TARGET_CYGMING)
xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
+ #endif
! if (TARGET_CYGMING || ! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
{
+ /* On target CYGMING, references to static and global symbols and
+ entries in address diff vector for a switch statement are
+ generated as displacements from the following base label. */
xops[2] = gen_rtx_LABEL_REF (Pmode, label ? label : gen_label_rtx ());
if (!flag_pic)
*************** output_set_got (rtx dest, rtx label ATTR
*** 5138,5147 ****
--- 5155,5168 ----
if (TARGET_MACHO)
return "";
+ #if (!TARGET_CYGMING)
if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
else
output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %1+(.-%a2)}", xops);
+ #else
+ pic_base_label = xops[2];
+ #endif
return "";
}
*************** legitimate_pic_address_disp_p (rtx disp)
*** 6463,6472 ****
/* Refuse GOTOFF in 64bit mode since it is always 64bit when used.
While ABI specify also 32bit relocation but we don't produce it in
small PIC model at all. */
if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
|| GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF)
&& !TARGET_64BIT)
! return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
return false;
case UNSPEC_GOTTPOFF:
case UNSPEC_GOTNTPOFF:
--- 6484,6498 ----
/* Refuse GOTOFF in 64bit mode since it is always 64bit when used.
While ABI specify also 32bit relocation but we don't produce it in
small PIC model at all. */
+ /* On target CYGMING, a reference to the slot in Import Address
+ Table corresponding to a dllimport'ed symbol is
+ generated as a displacement from the PIC base label (@GOTOFF)
+ just like a local symbolic operand. */
if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
|| GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF)
&& !TARGET_64BIT)
! return (local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode)
! || imported_symbolic_operand (XVECEXP (disp, 0, 0), Pmode));
return false;
case UNSPEC_GOTTPOFF:
case UNSPEC_GOTNTPOFF:
*************** legitimize_pic_address (rtx orig, rtx re
*** 6819,6829 ****
}
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
base address (@GOTOFF). */
!
if (reload_in_progress)
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
if (GET_CODE (addr) == CONST)
--- 6845,6862 ----
}
else new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
}
! else if (!TARGET_64BIT && (local_symbolic_operand (addr, Pmode)
! || imported_symbolic_operand (addr, Pmode)))
{
/* This symbol may be referenced via a displacement from the PIC
base address (@GOTOFF). */
! /* On target CYGMING, dllimport'ed symbols are referenced via a load
! from the Import Address Table (IAT). For each dllimport'ed symbol
! <sym>, there is a slot in IAT which is referenced by the symbol
! __imp_<sym>. The symbol __imp_<sym> will be at a
! known (at link time) fixed displacement from the PIC base label.
! Hence, the symbol __imp_<sym> may be referenced via a
! displacement from the PIC base label (@GOTOFF). */
if (reload_in_progress)
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
if (GET_CODE (addr) == CONST)
*************** legitimize_pic_address (rtx orig, rtx re
*** 6865,6874 ****
{
/* This symbol must be referenced via a load from the
Global Offset Table (@GOT). */
!
if (reload_in_progress)
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
new = gen_const_mem (Pmode, new);
--- 6898,6925 ----
{
/* This symbol must be referenced via a load from the
Global Offset Table (@GOT). */
! /* On CYGMING, we do not know at compile time whether
! a global symbol which is not explicitly imported
! (through __declspec(dllimport) will be resolved
! within the same DLL or will be imported from another
! DLL. This will be known only at link time. We
! assume that such a symbol <sym> is dllimport'ed and
! reference it via a load from IAT. That means, a symbol
! <sym> is referenced as *__imp_<sym> where __imp_<sym>
! itself is accessed via a displacement from the PIC
! base label (@GOTOFF). At link time, if it turns out
! that the symbol is defined within the same DLL,
! the linker will provide a symbol definition for
! __imp_<sym> in the .data segment and load it with
! the symbol address for <sym>. */
if (reload_in_progress)
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ #if TARGET_CYGMING
+ addr = i386_pe_generate_imported_symbol_ref(addr);
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
+ #else
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
+ #endif
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
new = gen_const_mem (Pmode, new);
*************** legitimize_pic_address (rtx orig, rtx re
*** 6912,6918 ****
/* Check first to see if this is a constant offset from a @GOTOFF
symbol reference. */
! if (local_symbolic_operand (op0, Pmode)
&& CONST_INT_P (op1))
{
if (!TARGET_64BIT)
--- 6963,6972 ----
/* Check first to see if this is a constant offset from a @GOTOFF
symbol reference. */
! /* On target CYGMING, a reference to a IAT slot can be generated
! as a fixed displacement from the PIC base label (@GOTOFF).*/
! if ((local_symbolic_operand (op0, Pmode) ||
! imported_symbolic_operand (op0, Pmode))
&& CONST_INT_P (op1))
{
if (!TARGET_64BIT)
*************** output_pic_addr_const (FILE *file, rtx x
*** 7355,7361 ****
case SYMBOL_REF:
output_addr_const (file, x);
! if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
fputs ("@PLT", file);
break;
--- 7409,7420 ----
case SYMBOL_REF:
output_addr_const (file, x);
! /* On target CYGMING, there is no PLT.
! In ix86_expand_call(), we call legitimize_pic_address()
! to convert the address of a direct, non-local function
! to a PIC reference. */
! if (!TARGET_MACHO && code == 'P' &&
! ! (TARGET_CYGMING || SYMBOL_REF_LOCAL_P (x)))
fputs ("@PLT", file);
break;
*************** output_pic_addr_const (FILE *file, rtx x
*** 7430,7436 ****
--- 7489,7502 ----
fputs ("@GOT", file);
break;
case UNSPEC_GOTOFF:
+ #if (!TARGET_CYGMING)
fputs ("@GOTOFF", file);
+ #else
+ /* On target CYGMING, we interpret GOTOFF of a symbol
+ as the offset of the symbol from the PIC base label. */
+ putc ('-', file);
+ output_pic_addr_const (file, pic_base_label, code);
+ #endif
break;
case UNSPEC_GOTPCREL:
fputs ("@GOTPCREL(%rip)", file);
*************** ix86_output_addr_diff_elt (FILE *file, i
*** 9049,9054 ****
--- 9115,9130 ----
if (TARGET_64BIT)
fprintf (file, "%s%s%d-%s%d\n",
ASM_LONG, LPREFIX, value, LPREFIX, rel);
+ /* On cygming, GOTOFF of a label is the offset of the label
+ from the PIC base label. */
+ #if TARGET_CYGMING
+ else if (TARGET_CYGMING)
+ {
+ fprintf (file, "%s%s%d-%s%d\n",
+ ASM_LONG, LPREFIX, value, LPREFIX,
+ CODE_LABEL_NUMBER(XEXP(pic_base_label,0)));
+ }
+ #endif
else if (HAVE_AS_GOTOFF_IN_DATA)
fprintf (file, "%s%s%d@GOTOFF\n", ASM_LONG, LPREFIX, value);
#if TARGET_MACHO
*************** ix86_expand_call (rtx retval, rtx fnaddr
*** 14391,14397 ****
if (! TARGET_64BIT && flag_pic
&& GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
&& ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
! use_reg (&use, pic_offset_table_rtx);
}
if (TARGET_64BIT && INTVAL (callarg2) >= 0)
--- 14467,14484 ----
if (! TARGET_64BIT && flag_pic
&& GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
&& ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
! {
! use_reg (&use, pic_offset_table_rtx);
! #if (TARGET_CYGMING)
! {
! /* On target CYGMING, there is no PLT. Convert
! the function address to a PIC reference. */
! rtx reg;
! reg = legitimize_pic_address (XEXP (fnaddr, 0), 0);
! XEXP (fnaddr, 0) = reg;
! }
! #endif
! }
}
if (TARGET_64BIT && INTVAL (callarg2) >= 0)