From mboxrd@z Thu Jan 1 00:00:00 1970 From: Richard Henderson To: Marc.Espie@liafa.jussieu.fr Cc: gcc@gcc.gnu.org Subject: openbsd gotoff workaround Date: Mon, 10 Sep 2001 18:18:00 -0000 Message-id: <20010910181833.A11350@redhat.com> References: <877kv7dp67.fsf@kaka.blahonga.org> <20010910184528.A10185@schutzenberger.liafa.jussieu.fr> X-SW-Source: 2001-09/msg00397.html On Mon, Sep 10, 2001 at 06:45:28PM +0200, Marc Espie wrote: > We can't ship a compiler that doesn't even compile OpenBSD i386 pic > code correctly (no news on my GOT/GOTOFF problems, rth ?). Try this. r~ Index: i386.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v retrieving revision 1.211.2.14 diff -c -p -d -r1.211.2.14 i386.c *** i386.c 2001/08/06 21:26:24 1.211.2.14 --- i386.c 2001/09/11 01:15:36 *************** int ix86_align_loops; *** 417,423 **** --- 417,428 ---- /* Power of two alignment for non-loop jumps. */ int ix86_align_jumps; + + /* Prefix built by ASM_GENERATE_INTERNAL_LABEL. */ + static int internal_label_prefix[16]; + static int internal_label_prefix_len; + static int local_symbolic_operand PARAMS ((rtx, enum machine_mode)); static void output_pic_addr_const PARAMS ((FILE *, rtx, int)); static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode, int, int, FILE *)); *************** override_options () *** 693,698 **** --- 698,712 ---- on by -msse. */ if (TARGET_SSE) target_flags |= MASK_MMX; + + /* Figure out what ASM_GENERATE_INTERNAL_LABEL builds as a prefix. */ + { + char *p; + ASM_GENERATE_INTERNAL_LABEL (internal_label_prefix, "LX", 0); + p = strchr (internal_label_prefix, 'X'); + internal_label_prefix_len = p - internal_label_prefix; + *p = '\0'; + } } /* A C statement (sans semicolon) to choose the order in which to *************** pic_symbolic_operand (op, mode) *** 1128,1133 **** --- 1142,1181 ---- return 0; } + /* Return true if OP is a symbolic operand that resolves locally. */ + + static int + local_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; + { + if (GET_CODE (op) == LABEL_REF) + return 1; + + if (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) + op = XEXP (XEXP (op, 0), 0); + + if (GET_CODE (op) != SYMBOL_REF) + return 0; + + /* These we've been told are local by varasm and encode_section_info + respectively. */ + if (CONSTANT_POOL_ADDRESS_P (op) || SYMBOL_REF_FLAG (op)) + return 1; + + /* There is, however, a not insubstantial body of code in the rest of + the compiler that assumes it can just stick the results of + ASM_GENERATE_INTERNAL_LABEL in a symbol_ref and have done. */ + + if (strncmp (XSTR (op, 0), internal_label_prefix, + internal_label_prefix_len) == 0) + return 1; + + return 0; + } + /* Test for a valid operand for a call instruction. Don't allow the arg pointer register or virtual regs since they may decay into reg + const, which the patterns can't handle. */ *************** legitimize_pic_address (orig, reg) *** 2767,2776 **** rtx new = orig; rtx base; ! if (GET_CODE (addr) == LABEL_REF ! || (GET_CODE (addr) == SYMBOL_REF ! && (CONSTANT_POOL_ADDRESS_P (addr) ! || SYMBOL_REF_FLAG (addr)))) { /* This symbol may be referenced via a displacement from the PIC base address (@GOTOFF). */ --- 2815,2821 ---- rtx new = orig; rtx base; ! if (local_symbolic_operand (addr, Pmode)) { /* This symbol may be referenced via a displacement from the PIC base address (@GOTOFF). */ *************** legitimize_pic_address (orig, reg) *** 2822,2831 **** /* Check first to see if this is a constant offset from a @GOTOFF symbol reference. */ ! if ((GET_CODE (op0) == LABEL_REF ! || (GET_CODE (op0) == SYMBOL_REF ! && (CONSTANT_POOL_ADDRESS_P (op0) ! || SYMBOL_REF_FLAG (op0)))) && GET_CODE (op1) == CONST_INT) { current_function_uses_pic_offset_table = 1; --- 2867,2873 ---- /* Check first to see if this is a constant offset from a @GOTOFF symbol reference. */ ! if (local_symbolic_operand (op0, Pmode)) && GET_CODE (op1) == CONST_INT) { current_function_uses_pic_offset_table = 1;