[Bug objc/102537] Objective-C: can't use >= USE_FIXUP_BEFORE paths on non-Darwin

2021-10-18 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102537

--- Comment #2 from Matt Jacobson  ---
I certainly haven't spent as much time thinking about this as you, but I think
my personal preference would be to add new values to the `flag_objc_abi`
argument.  It's already the case that "objc-next-runtime-abi-01.c" supports
both 0 and 1 values; I think it would be reasonable to have
`objc-next-runtime-abi-02.c` support multiple values too.  I'd imagine
something like:

2 -- "modern" runtime ABI, pre-SnowLeopard (fixup messages, etc.)
3 -- "modern" runtime ABI, SnowLeopard and later (no fixup messages, weak
protocol metadata

Then the Darwin-target code could (absent an explicit override in the
arguments) select the value for `flag_objc_abi` based on
`-mmacosx-version-min`.  And non-Darwin targets could simply default to the
newest ABI (absent an explicit override).

Other versions could be added in the future as support for newer
runtime-ABI-dependent features (e.g., `objc_autoreleasePoolPush()`,
`objc_opt_self()`, `objc_loadWeak()`) is added.

Under this scheme, I think it would make sense to switch `flag_next_runtime` to
being a simple boolean.

===

I think I like this better than using the high byte of `flag_next_runtime`,
which could be cumbersome to build conditionals for.  For example, taking your
example of using 0x0100 as the "AVR" platform, a check of whether to use
non-fixup messaging might end up look like:

#define PLATFORM(r) (((r) >> 24) & 0xFF)
#define VERSION(r)  ((r) & 0xFF)

if ((PLATFORM(flag_next_runtime) == DARWIN && VERSION(flag_next_runtime) >=
USE_FIXUP_BEFORE)
|| PLATFORM(flag_next_runtime) == AVR)
  { ... }

Yeah, the existing `flag_next_runtime >= USE_FIXUP_BEFORE` would technically
work, but you could imagine other platforms with ID > 0 that want the
pre-USE_FIXUP_BEFORE behavior.

===

> These two were both thoughts during the development but I suspect that the
> mapping to values is a build-time decision and ought to be done in the flags
> override code.

I'd like to understand better what you mean here.  Is it that, under the
`flag_objc_abi` scheme I described, the x86_64-Darwin target may want different
logic to select `flag_objc_abi` than the AVR target (for example)?  If so then
I agree -- shouldn't that be similar to how the `flag_next_runtime` override is
currently target-dependent?  Apologies if I've completely misread that.

[Bug objc/102537] New: Objective-C: can't use >= USE_FIXUP_BEFORE paths for non-Darwin

2021-09-29 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102537

Bug ID: 102537
   Summary: Objective-C: can't use >= USE_FIXUP_BEFORE paths for
non-Darwin
   Product: gcc
   Version: 10.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: objc
  Assignee: unassigned at gcc dot gnu.org
  Reporter: mhjacobson at me dot com
  Target Milestone: ---

I am working on a NeXTv2-ABI-compatible Objective-C runtime for a non-Darwin
platform (AVR micros).  I'd like my Objective-C code to make use of the most
modern ABI features, namely those guarded in the code by `flag_next_runtime >=
USE_FIXUP_BEFORE`.

However, there appears to be no way to control `flag_next_runtime` (short of
modifying the compiler source).  I can set it to zero with `-fgnu-runtime` or
one with `-fnext-runtime`, but `USE_FIXUP_BEFORE` is an encoded Mac OS X
version (namely 100600, referring to Snow Leopard).

There is Darwin-specific option parsing code (`darwin_override_options()`) that
appears to set `flag_next_runtime` based on `-mmacosx-version-min`, but
obviously that doesn't run for non-Darwin targets.

I could imagine a few approaches to fixing this:

1. Parse `-mmacosx-version-min` even when the target is not Darwin, whenever
we're compiling Objective-C.  On non-Darwin, this would be interpreted as
requesting Objective-C codegen compatible with the Objective-C ABI of the
specified release of Mac OS X.

2. Allow an argument to `-fnext-runtime`, with the meaning approximately the
same as in #1.

3. Instead of using `flag_next_runtime` as a version number, switch it back to
being zero or one, and use a separate flag (perhaps the existing
`-fobjc-abi-version`?) to differentiate ABIs.

[Bug objc/101666] Objective-C frontend crashes with `-fobjc-nilcheck`

2021-08-14 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101666

--- Comment #3 from Matt Jacobson  ---


[Bug objc/101718] Objective-C frontend emits wrong code to call methods returning scalar types returned in memory

2021-08-10 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101718

--- Comment #2 from Matt Jacobson  ---
(In reply to Iain Sandoe from comment #1)
> can you give me some idea of the platform? it would help with testing at
> least (assuming that there is a suitable machine on the cfarm).

Sure, but I'm guessing it's not going to be very helpful!  The platform I'm
using is an AVR microcontroller, with my own custom NeXT-v2-ABI-compliant
runtime.




> Having said that, there could be some types for which this would fire even
> on Darwin.

Hm -- I'm not so sure.

The x86_64 calling convention allocates *two* (64-bit) registers to
integer/pointer return values, so `__int128` doesn't require memory. 
Similarly, it can return `_Complex double` via multiple SSE registers. 
Finally, there's also `_Complex long double`, which is returned via the x87
stack (and for which there is yet another messenger routine,
`objc_msgSend_fp2ret`).

In fact, a close reading of the ABI spec suggests that the *only* types that
would ever be returned through memory are structs and unions.  So the code here
would work.

[Bug objc/101718] New: Objective-C frontend emits wrong code to call methods returning _Complex types returned in memory

2021-08-02 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101718

Bug ID: 101718
   Summary: Objective-C frontend emits wrong code to call methods
returning _Complex types returned in memory
   Product: gcc
   Version: 10.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: objc
  Assignee: unassigned at gcc dot gnu.org
  Reporter: mhjacobson at me dot com
  Target Milestone: ---

When a method returns a type that the platform ABI says is returned in memory,
the Objective-C frontend (for the NeXT runtime ABIs) emits a call to
`objc_msgSend_stret`; the `_stret` variant of the message dispatcher knows to
look at the *second* argument for `self`, and so on, since the first argument
is the pointer to where the return value will go.

On some platforms, `_Complex double` is too large to be returned through
registers, so it's returned through memory.

But the Objective-C frontend still insists on using `objc_msgSend`, not
`objc_msgSend_stret`.

`objc_msgSend` is thoroughly confused when the first argument, which it expects
to be `self`, is actually a pointer to garbage-filled stack.

I believe this happens because this check:

```
  /* If we are returning a struct in memory, and the address
 of that memory location is passed as a hidden first
 argument, then change which messenger entry point this
 expr will call.  NB: Note that sender_cast remains
 unchanged (it already has a struct return type).  */
  if (!targetm.calls.struct_value_rtx (0, 0)
  && (TREE_CODE (ret_type) == RECORD_TYPE
  || TREE_CODE (ret_type) == UNION_TYPE)
  && targetm.calls.return_in_memory (ret_type, 0))
{
```

limits the use of `stret` to record/union types.  Primitive types that are
returned in memory should also be made to use `stret` (the name's meaning
notwithstanding).

[Bug objc/101616] Objective-C frontend should not emit vtable/fixup messages (at least, not by default)

2021-07-28 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101616

--- Comment #3 from Matt Jacobson  ---
Thanks -- I updated to 10.3.0 and looked into the changes.  (Sorry for
originally filing this against such an out-of-date compiler.)

As it happens, I'm targeting the NeXT v2 runtime, but I'm *not* actually
targeting Darwin.  So `flag_next_runtime` is just 1 for me--not an OS version
value like 100600 (`USE_FIXUP_BEFORE` / SnowLeopard).  (And I can't fake it via
arguments, AFAICT.)

I wonder if it would be reasonable to add a separate flag to disable (or
enable) fixup messages, such that the default value of the flag is controlled
by `-mmacosx-version-min` when targeting Darwin.

[Bug objc/101666] Objective-C frontend crashes with `-fobjc-nilcheck`

2021-07-28 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101666

--- Comment #2 from Matt Jacobson  ---
(Oops, ignore the `[8*3]` part in the explanation.)

[Bug objc/101666] Objective-C frontend crashes with `-fobjc-nilcheck`

2021-07-28 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101666

--- Comment #1 from Matt Jacobson  ---
I'm not an expert on GCC ASTs, but would this change be correct here?  I'm
trying to simulate something like `struct whatever ftree[8 * 3] = {0};`.

diff --git a/gcc/objc/objc-next-runtime-abi-02.c
b/gcc/objc/objc-next-runtime-abi-02.c
index e401906ed..0cc19a079 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -1631,9 +1631,8 @@ build_v2_build_objc_method_call (int super_flag, tree
method_prototype,
  || TREE_CODE (ret_type) == UNION_TYPE)
{
  vec *rtt = NULL;
- /* ??? CHECKME. hmmm. think we need something more
-here.  */
- CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
+ CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, build_int_cst
(integer_type_node,
+   0));
  ftree = objc_build_constructor (ret_type, rtt);
}
   else

[Bug objc/101666] New: Objective-C frontend crashes with `-fobjc-nilcheck`

2021-07-28 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101666

Bug ID: 101666
   Summary: Objective-C frontend crashes with `-fobjc-nilcheck`
   Product: gcc
   Version: 10.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: objc
  Assignee: unassigned at gcc dot gnu.org
  Reporter: mhjacobson at me dot com
  Target Milestone: ---

Details, including minimal reproducer, below.  The Objective-C frontend crashes
when I try to use -fobjc-nilcheck under the NeXT v2 ABI.  If I send a message
whose return type would require using objc_msgSend_stret (and a nil check),
crash.  Message sends not requiring stret (and thus no nil check) work fine.

===

macOS 10.15.7 "Catalina" / x86_64

$ gcc --version
gcc (GCC) 10.2.0

$ gcc -Os -fobjc-nilcheck -xobjective-c -
struct point { double x, y, z; };

@interface Foo
- (struct point)bar;
@end

Foo *f;

int main(void) {
struct point p = [f bar];
}
: In function ‘main’:
:10:9: internal compiler error: Segmentation fault: 11

Here's the backtrace:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS
(code=1, address=0x0)
  * frame #0: 0x0001012ce428
cc1obj`recompute_constructor_flags(c=0x000144513f90) at tree.c:2018:12
frame #1: 0x0001012cd45f
cc1obj`build_constructor(type=0x000144505930, vals=0x00014450a678) at
tree.c:2059:3
frame #2: 0x0001c2bd
cc1obj`objc_build_constructor(type=0x000144505930, elts=0x00014450a678)
at objc-act.c:3235:22
frame #3: 0x000100031b37
cc1obj`build_v2_build_objc_method_call(super_flag=0,
method_prototype=0x000144504a18, lookup_object=0x0001444f3720,
selector=0x0001444f36a0, method_params=0x00014452b140,
check_for_nil=true) at objc-next-runtime-abi-02.c:1637:12
frame #4: 0x00010002d8da
cc1obj`next_runtime_abi_02_build_objc_method_call(loc=62820,
method_prototype=0x000144504a18, receiver=0x000142c5d240,
rtype=0x000144527000, sel_name=0x00014451bf00,
method_params=0x, super=0) at
objc-next-runtime-abi-02.c:1720:10
frame #5: 0x0001902d
cc1obj`objc_finish_message_expr(receiver=0x000142c5d240,
sel_name=0x00014451bf00, method_params=0x,
deprecated_method_prototype=0x) at objc-act.c:5679:12
frame #6: 0x0001ec8f
cc1obj`objc_build_message_expr(receiver=0x000142c5d240,
message_args=0x00014451bf00) at objc-act.c:5308:10
frame #7: 0x0001000be312
cc1obj`c_parser_postfix_expression(parser=0x000142c5d1b0) at
c-parser.c:10163:17
frame #8: 0x0001000b5f21
cc1obj`c_parser_unary_expression(parser=0x000142c5d1b0) at
c-parser.c:8276:14
frame #9: 0x0001000b3ce5
cc1obj`c_parser_cast_expression(parser=0x000142c5d1b0,
after=0x) at c-parser.c:8115:12
frame #10: 0x0001000b209b
cc1obj`c_parser_binary_expression(parser=0x000142c5d1b0,
after=0x, omp_atomic_lhs=0x) at
c-parser.c:7918:19
frame #11: 0x0001000b1800
cc1obj`c_parser_conditional_expression(parser=0x000142c5d1b0,
after=0x, omp_atomic_lhs=0x) at
c-parser.c:7652:10
frame #12: 0x0001000b13ed
cc1obj`c_parser_expr_no_commas(parser=0x000142c5d1b0,
after=0x, omp_atomic_lhs=0x) at
c-parser.c:7569:9
frame #13: 0x0001000c6921
cc1obj`c_parser_initializer(parser=0x000142c5d1b0) at c-parser.c:5227:13
frame #14: 0x0001000c34a0
cc1obj`c_parser_declaration_or_fndef(parser=0x000142c5d1b0, fndef_ok=false,
static_assert_ok=true, empty_ok=true, nested=true, start_attr_ok=true,
objc_foreach_object_declaration=0x,
omp_declare_simd_clauses=vec @ 0x7ffeefbfede8,
have_attrs=false, attrs=0x,
oacc_routine_data=0x, fallthru_attr_p=0x7ffeefbfeebf) at
c-parser.c:2248:12
frame #15: 0x0001000c00d4
cc1obj`c_parser_compound_statement_nostart(parser=0x000142c5d1b0) at
c-parser.c:5718:4
frame #16: 0x0001000c6c3d
cc1obj`c_parser_compound_statement(parser=0x000142c5d1b0,
endlocp=0x7ffeefbff070) at c-parser.c:5617:24
frame #17: 0x0001000c3e66
cc1obj`c_parser_declaration_or_fndef(parser=0x000142c5d1b0, fndef_ok=true,
static_assert_ok=true, empty_ok=true, nested=false, start_attr_ok=true,
objc_foreach_object_declaration=0x,
omp_declare_simd_clauses=vec @ 0x7ffeefbff478,
have_attrs=false, attrs=0x,
oacc_routine_data=0x, fallthru_attr_p=0x) at
c-parser.c:2505:11
frame #18: 0x0001000ee11e
cc1obj`c_parser_external_declaration(parser=0x000142c5d1b0) at
c-parser.c:1745:7
frame #19: 0x0001000b095d
cc1obj`c_parser_translation_unit(parser=0x000142c5d1b0) at
c-parser.c:1618:4
frame #20: 0x0001000b066b cc1obj`c_parse_file() at c-parser.c:21745:3
frame #21: 

[Bug objc/101616] New: Objective-C frontend should not emit vtable/fixup messages (at least, not by default)

2021-07-24 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101616

Bug ID: 101616
   Summary: Objective-C frontend should not emit vtable/fixup
messages (at least, not by default)
   Product: gcc
   Version: 10.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: objc
  Assignee: unassigned at gcc dot gnu.org
  Reporter: mhjacobson at me dot com
  Target Milestone: ---

In 10.2.0, the Objective-C frontend (in NeXT v2 ABI mode) emits "fixup"
messages for all message sends.  Fixup messages are an abandoned optimization
in which the runtime specializes the message send routine to a fast vtable
lookup routine for a small set of common selectors.  (The set of common
selectors is hard-coded in the runtime.)  For other selectors, the fixup
message simply devolves into a normal message send, albeit with extra pointer
chasing.

The Apple runtime has not actually supported this optimization since OS X
Mountain Lion, as an inspection of the Mountain Lion [0] and Mavericks [1]
sources will confirm.  (Search for "fixupMessageRef".)  The Mavericks-and-later
runtimes still *deal* with fixup messages, but all callsites are treated as
non-optimized selectors.  Clang appears to have stopped emitting fixup messages
around 2010.

Furthermore, even when Clang *did* use fixup messages, it did so only for a
small set of selectors (that presumably tended to match the ones optimized by
the runtime).  By contrast, GCC simply uses them for all messages.

GCC should probably just stop emitting fixup messages calls entirely, but at
least it should only do so behind some driver flag.

[0]
https://opensource.apple.com/source/objc4/objc4-532/runtime/objc-runtime-new.mm.auto.html
[1]
https://opensource.apple.com/source/objc4/objc4-551.1/runtime/objc-runtime-new.mm.auto.html

[Bug driver/100830] Multilib directory picking logic handles default arguments oddly

2021-05-30 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100830

--- Comment #1 from Matt Jacobson  ---
Another place that exhibits this weirdness is `print_multilib_info()` (which is
used at build time for the target libraries).  It also calls `default_arg()`
and omits lines that match the defaults.

[Bug driver/100830] New: Multilib directory picking logic handles default arguments oddly

2021-05-30 Thread mhjacobson at me dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100830

Bug ID: 100830
   Summary: Multilib directory picking logic handles default
arguments oddly
   Product: gcc
   Version: 10.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: driver
  Assignee: unassigned at gcc dot gnu.org
  Reporter: mhjacobson at me dot com
  Target Milestone: ---

`set_multilib_dir()` is responsible for selecting a multilib directory given
(a) `multilib_select` and (b) the state of the switches.

But (at least, IMO), it handles the following case very unintuitively:

Suppose `multilib_select` is (newlines added for clarity):

. !mmcu=avr4 !mmcu=avr5;
avr4 mmcu=avr4 !mmcu=avr5;
avr5 !mmcu=avr4 mmcu=avr5;

i.e., choose "avr4" if `-mmcu=avr4`; "avr5" if `-mmcu=avr5`, and "." if
neither.

Suppose also that the default value of `mmcu`, specified in
`multilib_defaults`, is `avr5`.

Then the logic described by this comment will unintuitively cause "." to be
picked even when `-mmcu=avr5` is explicitly passed as an argument to the
driver:

/* If this is a default argument, we can just ignore it.
This is true even if this_arg begins with '!'.  Beginning
with '!' does not mean that this argument is necessarily
inappropriate for this library: it merely means that
there is a more specific library which uses this
argument.  If this argument is a default, we need not
consider that more specific library.  */

The code that actually implements this is the check of default_arg() after
we've already failed the used_arg() check.

Perhaps it's not a valid configuration to have a default value in
`multilib_defaults` that does not correspond to ".", but if so, I think that's
weird.