gcc-patches@gcc.gnu.org
[Top] [All Lists]

Re: fixes for Darwin/x86

Subject: Re: fixes for Darwin/x86
From: Stuart Hastings
Date: Thu, 1 Dec 2005 16:03:51 -0800

On Nov 30, 2005, at 5:35 PM, Richard Henderson wrote:

On Wed, Nov 30, 2005 at 02:37:34PM -0800, Stuart Hastings wrote:
AFAICT, Darwin/x86 must be the only GCC port where the default stack
alignment can be /lowered/ from the commandline ("-mpreferred-stack-
boundary=2").  Darwin requires a 16-byte (SSE) stack alignment, yet
the Darwin/x86 GCC is obliged to support a few projects
(cough*kernel*cough) that require 4-byte alignment.  It's trivial to
make the STACK_BOUNDARY macro expand to a variable, but that won't
bootstrap, as the middle-end uses STACK_BOUNDARY in signed and
unsigned comparisons.

How is this different in practice from Linux?  Yes, you're touching
STACK_BOUNDARY, but I wanna know why.  As far as I know, you needn't
be touching *anything* to get your 16-byte stack alignment.

Hm. You're right. This was necessary to get a consistent 16-byte alignment for Darwin/x86 when it was done (three-plus years ago?), and it hasn't been examined since. I'll try it your way.

-  emit_insn (gen_set_got (pic_offset_table_rtx));
+  if (TARGET_MACHO)
+    {
+      rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+      rtx tmplabrtx;
+      char tmplab[20];
+
+      ASM_GENERATE_INTERNAL_LABEL(tmplab, \"LSJR\",
+                                 CODE_LABEL_NUMBER (operands[0]));
+      tmplabrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tmplab));
+
+      emit_insn (gen_load_macho_picbase_si (picreg));
+    }
+  else
+    emit_insn (gen_set_got (pic_offset_table_rtx));

Any reason this isn't going into output_set_got, wherein we
already have macho hackery?

Trying to avoid re-inventing the wheel, copying from GeoffKs version in Darwin/PPC. I'd be happy to move everything to output_set_got; discussion below.

And even so, tmplabrtx is unused.

My bad.

+  if (flag_pic == 1)                                                   \
+    {                                                                  \
+      /* Darwin doesn't support -fpic.  */                             \
+      warning (0, "-fpic is not supported; -fPIC assumed");          \
+      flag_pic = 2;                                                    \

This made sense for ppc, where -fpic and -fPIC are different.

They are the same.  There is no -fpic on Darwin/PPC.

Why are you bothing for x86?

As noted in my comments, Darwin/PPC has the same warning, and the Darwin/PPC DejaGnu UNSUPPORTS the same tests. If that's not the example I should follow, let's fix Darwin/PPC.

Just to annoy users?

(Sigh.)

Answering your question directly, "no"; I thought I was duplicating the experience users have today with Darwin/PPC. Apple has gone to great lengths to make the our x86 compiler as similar to our PPC compiler as possible.

If the warning is wrong for Darwin/x86, then it must also be wrong for Darwin/PPC, because they both support -fPIC and neither supports - fpic.

I'd be happy to remove this warning from the Darwin/PPC compiler; would you approve such a patch? (Darwin/PPC would pass 27 more C++ tests if we did.)

Should the regexp that matches the warning be removed from DejaGnu (testsuite/lib/prune.exp) ? It's clearly not pruning out this warning. (I haven't spent the time to figure out why; my guess is that the -fpic testing in testsuite/lib/target-supports.exp somehow avoids prune.exp.)

-  if (USE_HIDDEN_LINKONCE)
+  if (USE_HIDDEN_LINKONCE || TARGET_MACHO)

Adjust the definition of USE_HIDDEN_LINKONCE instead.  I'm surprised
it isn't automatically happening...

O.K., but the Darwin assembler doesn't like the ".hidden" stuff generated in ix86_file_end(). I'll need to hack up ix86_file_end() to say "if (USE_HIDDEN_LINKONCE && !TARGET_MACHO)". :-P

+#if TARGET_MACHO
+  if (1)
+    {
+ /* If this isn't the 'first_time', recompute the original Mach-O pic-base. */
+      if (!first_time)
+ output_asm_insn ("lea{l}\t{%P1-%P2(%0), %0|%0, %P1-%P2(%0)}", xops);
+    }
+  else
+#endif

What are you doing?  This looks suspiciously like a gross hack.

It /is/ a gross hack. (And if you're offended by this, there are a few functions in config/darwin.c that you should avoid looking at. :-)

The Mach-O runtime was designed before my time, but it seems to assume a complete set of PC-relative addressing modes (e.g. the 68K- based NeXT); these assumptions seem to make it a poor fit for x86-32 and PPC.

Where Linux/x86-32 always uses the same idiom to compute the GOT address, the Mach-O runtime uses one unique "pic-base" per function. The first time we compute a pic-base, we use an arbitrary label in the prologue. The 2nd..nth times we recompute that address, we need an extra ADD to recompute that same pic-base.

This cruft above is a simplified form of the logic in config/rs6000/ darwin.md(macho_correct_pic_si). This ugly, stateful, 'first_time' hack gives output_set_got() enough knowledge to know when the extra ADD is necessary.

On Darwin/x86, inside any given function, we generate

        call    ___i686.get_pc_thunk.bx
L171:
"L00000000005$pb":

the first time we compute a pic-base, and we generate

        call    ___i686.get_pc_thunk.bx
L172:
        leal    "L00000000005$pb"-L172(%ebx), %ebx

on subsequent pic-base computations (e.g. builtin_setjmp_receiver). All of this has precedent on Darwin/PPC.

I don't care where this stuff goes, but it has to go somewhere; it's needed to fix a bunch of DejaGnu failures. Would you prefer

A) pushing the LEA cruft into the builtin_setjmp_receiver pattern, or
B) leaving it in output_set_got(), with the "first_time" stateful gross hack, or
C) some other, much better idea I haven't thought of?

stuart

<Prev in Thread] Current Thread [Next in Thread>