[PATCH] add unconditional support for @encode block descriptor string

David Chisnall provided, as an option, an introspection field for blocks (const char *types) in the block literal data structure itself for use by the GNU runtime.

This was discussed and approved and integrated.

I am unconditionally adding this field instead to the read-only shared block descriptor data structure instead. I am unconditionally re-using his BLOCK_HAS_OBJC flag bit.

Also, I am introducing a second new reserved field for block internal layout, initially set to NULL.

These need to be discussed in the ABI document and supported in the runtime. Also, David's conditional support should be removed when he's ready. I left it in to simplify understanding of the changes and, of course, to support his clients until he transitions his runtime to use the new location of the types field.

This diff reflects the already committed cleanup from my previous PATCH post today.

CodeGen.patch (3.82 KB)

Few comments.
Since hasIntrospection is no longer in use, you need to remove the option and all the code controlled by this flag.
Please run your test suite with the change for any regression.
Provide a test case checking for new stuff being generated.

Our coding conversion is 1) no tab 2) limited to 80 columns (just in case).

Don't use {...}. Please remove '{' and '}'

- Fariborz

Hi Blaine,

Hi Blaine,

Also, David's conditional support should be removed when he's ready. I left it in to simplify understanding of the changes and, of course, to support his clients until he transitions his runtime to use the new location of the types field.

Feel free to remove it now.

On a related note, passing any block type to @encode() currently returns "@?". I wonder if we should change it to return the encoding of type of the block or, if this would break existing code (@? does already in quite a few cases that were written before blocks were introduced) provide some other mechanism for accessing this at compile time?

We can't change the encoding. Encoding for block is '@' for block and '?' for function type. Similar to function pointer type; except that
'^?' is used.

- fariborz

1) ? actually signifies 'unknown type', not 'function type'
2) This is completely irrelevant to what I said. I was talking about the return from doing something like:

typedef void(^foo)(id, void*); @encode(foo);

This currently returns "@?" if foo is any block type, rather than the type encoding that we are storing with the block. To get the block type encoding, we need to look up the type of a template block at run time, which prevents some optimisations when you test that two type encodings match, because neither is known at compile time (even though one actually is).

David

-- Sent from my PDP-11

We can't change the encoding. Encoding for block is '@' for block and '?' for function type. Similar to function pointer type; except that
'^?' is used.

1) ? actually signifies 'unknown type', not 'function type'

Granted you may not be looking at our Darwin source tree. But here it is:

else if (code == FUNCTION_TYPE) /* '?' */
     obstack_1grow (&util_obstack, '?');

2) This is completely irrelevant to what I said. I was talking about the return from doing something like:

Uncalled for. You need to be more clear so my comments become more 'relevant'.

typedef void(^foo)(id, void*); @encode(foo);

This currently returns "@?" if foo is any block type, rather than the type encoding that we are storing with the block. To get the block type encoding, we need to look up the type of a template block at run time, which prevents some optimisations when you test that two type encodings match, because neither is known at compile time (even though one actually is).

Fact of the matter is that we cannot change block's encoding at this time.
If you are using the same api to store encoding in block that @encode uses, you will get "@?". This is not very helpful. You need to write your
own encoding logic for block's detailed encoding to store in block's descriptor.

- Fariborz

1) ? actually signifies 'unknown type', not 'function type'

Granted you may not be looking at our Darwin source tree. But here it is:

else if (code == FUNCTION_TYPE) /* '?' */
   obstack_1grow (&util_obstack, '?');

Perhaps someone should update the Apple documentation then:

Unless the people who write documentation only have access to the GNU source code - your documentation corresponds with our implementation...

typedef void(^foo)(id, void*); @encode(foo);

This currently returns "@?" if foo is any block type, rather than the type encoding that we are storing with the block. To get the block type encoding, we need to look up the type of a template block at run time, which prevents some optimisations when you test that two type encodings match, because neither is known at compile time (even though one actually is).

Fact of the matter is that we cannot change block's encoding at this time.
If you are using the same api to store encoding in block that @encode uses, you will get "@?". This is not very helpful. You need to write your
own encoding logic for block's detailed encoding to store in block's descriptor.

The code to create the encoding stored with the block already exists. I wrote it months ago. Blaine has now modified where it is stored and made it unconditional.

What is lacking, is some way for users of clang to get this type encoding at compile time, without having to construct it themselves (or poke the semi-private block structure). The simplest way of supporting this would be for @encode on a block type to return the type of the block, rather than a generic type.

If this would break existing code, then we should consider adding a new @encode-like mechanism that can be used to get compile-time type encodings for block types. If we're doing that, then it would be nice for the same mechanism to support type encodings for functions and methods.

David

-- Sent from my PDP-11