Re: mips16 and nomips16

2013-02-20 Thread Maciej W. Rozycki
On Fri, 25 Jan 2013, Richard Sandiford wrote:

> >  FWIW, I think the benefit from these attributes being a type property is 
> > questionable to say the least.  My understanding is the only application 
> > is to prevent the tail-call optimisation from being applied to non-PIC 
> > standard MIPS functions that otherwise would have to make a direct jump to 
> > MIPS16 code for which there is no hardware support (note that there is no 
> > issue with PIC code as with register jumps the ISA bit can be freely set 
> > at will as required).
> 
> I think the main benefit was more to avoid unnecessary hard-float
> interworking cruft.  If you're calling an indirect function (including
> vtable function) whose type has a mips16 attribute, you know that
> float values will be returned in GPRs without going through the
> libgcc stub.  So...
> 
> >  If that is the case, then perhaps producing a suitable call thunk 
> > instead, similar to these we use to pass floating-point arguments around 
> > with MIPS16 functions or to call PIC code from non-PIC code statically 
> > linked together, so that all standard MIPS code is link-time compatible 
> > with MIPS16 would be a better option?
> 
> ...I think the idea was to avoid this kind of overhead.

 OK, I see, I think it makes some sense I admit.  However in this case I 
think this should be a one-way enforcement, in that the presence of either 
attribute on a prototype would enforce a particular implementation, but 
any implementation would suit a prototype with neither attribute, in which 
case any caller could of course make no assumptions about the callee.

 I.e. these would be valid:

void foo (void);
void foo (void) {}

void __attribute__ ((mips16)) foo (void);
void __attribute__ ((mips16)) foo (void) {}

void __attribute__ ((nomips16)) foo (void);
void __attribute__ ((nomips16)) foo (void) {}

these would also be valid:

void foo (void);
void __attribute__ ((mips16)) foo (void) {}

void foo (void);
void __attribute__ ((nomips16)) foo (void) {}

but these would be invalid:

void __attribute__ ((mips16)) foo (void);
void __attribute__ ((nomips16)) foo (void) {}

void __attribute__ ((nomips16)) foo (void);
void __attribute__ ((mips16)) foo (void) {}

as would be incompatible prototypes:

void foo (void);
void __attribute__ ((mips16)) foo (void);

void foo (void);
void __attribute__ ((nomips16)) foo (void);

void __attribute__ ((mips16)) foo (void);
void __attribute__ ((nomips16)) foo (void);

and these might be invalid as well (debatable though):

void __attribute__ ((mips16)) foo (void);
void foo (void) {}

void __attribute__ ((nomips16)) foo (void);
void foo (void) {}

> But like I say, I might be misrepresenting things, and I'm certainly open
> to removing the check if there's agreement we don't want type attributes.

 The origin of the choice may have been lost in the mist of history I am 
afraid, and I'd be happy to know what it was if there's still someone 
around here who might be able to bring it back.  I wasn't involved with 
any of the original MIPS16 GCC stuff.

> FWIW, there's also the "target" attribute, which is designed specifically
> for turning options on and off at the function definition site, and which
> also has an associated pragma for controlling a block of functions.
> That isn't implemented yet for MIPS, but should be.  E.g. we could have
> target("mips16"), target("no-mips16"), target("micromips") and
> target("no-micromips").
> 
> So one alternative might be to keep the current attributes as they are
> and implement "target".

 That might make sense too; of course settings conflicting with the 
corresponding attribute would have to be diagnosed and rejected.

  Maciej


Re: mips16 and nomips16

2013-01-25 Thread Richard Sandiford
"Maciej W. Rozycki"  writes:
> On Fri, 18 Jan 2013, Richard Sandiford wrote:
>
>> > I would assume that foo would be nomips16 and goo would be mips16.
>> >
>> > The definition of plain foo() or goo() says that nothing is specified.
>> >
>> > What is not clear then?
>> >
>> > This is how all such other attributes in gcc are handled.
>> 
>> Well, in a way, these are the only such attributes in GCC :-)
>> I don't think any other port supports switching between different
>> ISA modes like this.
>> 
>> I think the original authors really wanted "mips16" and "nomips16" to be
>> type attributes rather than decl attributes.  nomips16 function pointers
>> and mips16 function pointers would be mutually-incompatible subtypes of
>> unannotated function pointers, so you would be able to implicitly
>> convert an annotated function pointer to an unannotated one, but not the
>> other way, and not between annotated function pointers.  GCC didn't at
>> the time (and as far as I know still doesn't) have hooks to enforce that
>> though.  The attributes therefore ended up being implemented as strict
>> decl attributes in the hope that they could be made type attributes in
>> future without breaking backwards compatibility.
>> 
>> Not having those hooks means that the validity and semantics of:
>> 
>>  void foo();
>>  void __attribute((subtype)) foo();
>> 
>> aren't really defined.  Does foo() keep its original type or change to
>> the subtype?  It's also not defined whether:
>> 
>>  void __attribute((subtype)) foo();
>>  void foo();
>> 
>> is invalid, or whether the subtype from the first declaration carries
>> over to the second.  Etc.  (To be clear, I'm not trying to start a
>> discussion on the right semantics, or anything like that.  I'm just
>> saying that I don't think the semantics are defined yet, although
>> I could be wrong.)
>
>  FWIW, I think the benefit from these attributes being a type property is 
> questionable to say the least.  My understanding is the only application 
> is to prevent the tail-call optimisation from being applied to non-PIC 
> standard MIPS functions that otherwise would have to make a direct jump to 
> MIPS16 code for which there is no hardware support (note that there is no 
> issue with PIC code as with register jumps the ISA bit can be freely set 
> at will as required).

I think the main benefit was more to avoid unnecessary hard-float
interworking cruft.  If you're calling an indirect function (including
vtable function) whose type has a mips16 attribute, you know that
float values will be returned in GPRs without going through the
libgcc stub.  So...

>  If that is the case, then perhaps producing a suitable call thunk 
> instead, similar to these we use to pass floating-point arguments around 
> with MIPS16 functions or to call PIC code from non-PIC code statically 
> linked together, so that all standard MIPS code is link-time compatible 
> with MIPS16 would be a better option?

...I think the idea was to avoid this kind of overhead.

But like I say, I might be misrepresenting things, and I'm certainly open
to removing the check if there's agreement we don't want type attributes.

FWIW, there's also the "target" attribute, which is designed specifically
for turning options on and off at the function definition site, and which
also has an associated pragma for controlling a block of functions.
That isn't implemented yet for MIPS, but should be.  E.g. we could have
target("mips16"), target("no-mips16"), target("micromips") and
target("no-micromips").

So one alternative might be to keep the current attributes as they are
and implement "target".

Richard


Re: mips16 and nomips16

2013-01-25 Thread Maciej W. Rozycki
On Fri, 18 Jan 2013, Richard Sandiford wrote:

> > I would assume that foo would be nomips16 and goo would be mips16.
> >
> > The definition of plain foo() or goo() says that nothing is specified.
> >
> > What is not clear then?
> >
> > This is how all such other attributes in gcc are handled.
> 
> Well, in a way, these are the only such attributes in GCC :-)
> I don't think any other port supports switching between different
> ISA modes like this.
> 
> I think the original authors really wanted "mips16" and "nomips16" to be
> type attributes rather than decl attributes.  nomips16 function pointers
> and mips16 function pointers would be mutually-incompatible subtypes of
> unannotated function pointers, so you would be able to implicitly
> convert an annotated function pointer to an unannotated one, but not the
> other way, and not between annotated function pointers.  GCC didn't at
> the time (and as far as I know still doesn't) have hooks to enforce that
> though.  The attributes therefore ended up being implemented as strict
> decl attributes in the hope that they could be made type attributes in
> future without breaking backwards compatibility.
> 
> Not having those hooks means that the validity and semantics of:
> 
>  void foo();
>  void __attribute((subtype)) foo();
> 
> aren't really defined.  Does foo() keep its original type or change to
> the subtype?  It's also not defined whether:
> 
>  void __attribute((subtype)) foo();
>  void foo();
> 
> is invalid, or whether the subtype from the first declaration carries
> over to the second.  Etc.  (To be clear, I'm not trying to start a
> discussion on the right semantics, or anything like that.  I'm just
> saying that I don't think the semantics are defined yet, although
> I could be wrong.)

 FWIW, I think the benefit from these attributes being a type property is 
questionable to say the least.  My understanding is the only application 
is to prevent the tail-call optimisation from being applied to non-PIC 
standard MIPS functions that otherwise would have to make a direct jump to 
MIPS16 code for which there is no hardware support (note that there is no 
issue with PIC code as with register jumps the ISA bit can be freely set 
at will as required).

 If that is the case, then perhaps producing a suitable call thunk 
instead, similar to these we use to pass floating-point arguments around 
with MIPS16 functions or to call PIC code from non-PIC code statically 
linked together, so that all standard MIPS code is link-time compatible 
with MIPS16 would be a better option?

  Maciej


Re: mips16 and nomips16

2013-01-25 Thread Maciej W. Rozycki
On Tue, 15 Jan 2013, David Daney wrote:

> > I'm not understanding why mips16 and nomips16 are not simple inheritable
> > attributes.
> 
> The mips16ness of a function must be known by the caller so that the
> appropriate version of the JAL/JALX instruction can be emitted

 Not really, the issue of JAL vs JALX is sorted out by the linker, for
both instruction encodings.

 It is the use of tail/sibling calls that is more of a problem (there's no
JX instruction to relax J to; of course this applies to standard MIPS code
only, as there's no MIPS16 J instruction), but that is generally
controlled with the -minterlink-mips16 option.

 The same applies to mixing standard MIPS and microMIPS code as far as the
linker is concerned (there are some additional restrictions due to a short
delay slot a jump instruction may have; such instructions cannot be
relaxed to cross-mode jumps).

> > i..e you should be able to say:
> > 
> > void foo();
> > void __attribute((nomips16)) foo();
> > 
> > 
> > or
> > 
> > void goo();
> 
> Any call here would assume nomips16
> 
> > void __attribute((mips16)) goo();
> 
> A call here would assume mips16.
> 
> Which is it?  If you allow it to change, one case will always be incorrect.

 You can still provide a prototype with neither attribute applied and then
build the actual function as either standard MIPS or MIPS16 code by using
the -mips16 or -mno-mips16 command line option.

  Maciej


Re: mips16 and nomips16

2013-01-18 Thread Richard Sandiford
Sorry for the slow reply, only just saw this.

reed kotler  writes:
> On 01/14/2013 04:50 PM, David Daney wrote:
>> On 01/14/2013 04:32 PM, reed kotler wrote:
>>> I'm not understanding why mips16 and nomips16 are not simple inheritable
>>> attributes.
>>
>> The mips16ness of a function must be known by the caller so that the 
>> appropriate version of the JAL/JALX instruction can be emitted
>>
>>
>>>
>>> i..e you should be able to say:
>>>
>>> void foo();
>>> void __attribute((nomips16)) foo();
>>>
>>>
>>> or
>>>
>>> void goo();
>>
>> Any call here would assume nomips16
>>
>>> void __attribute((mips16)) goo();
>>
>> A call here would assume mips16.
>>
>> Which is it?  If you allow it to change, one case will always be 
>> incorrect.
>>
>> Or perhaps I misunderstand the question.
>>
>> David Daney
>>
> I would assume that foo would be nomips16 and goo would be mips16.
>
> The definition of plain foo() or goo() says that nothing is specified.
>
> What is not clear then?
>
> This is how all such other attributes in gcc are handled.

Well, in a way, these are the only such attributes in GCC :-)
I don't think any other port supports switching between different
ISA modes like this.

I think the original authors really wanted "mips16" and "nomips16" to be
type attributes rather than decl attributes.  nomips16 function pointers
and mips16 function pointers would be mutually-incompatible subtypes of
unannotated function pointers, so you would be able to implicitly
convert an annotated function pointer to an unannotated one, but not the
other way, and not between annotated function pointers.  GCC didn't at
the time (and as far as I know still doesn't) have hooks to enforce that
though.  The attributes therefore ended up being implemented as strict
decl attributes in the hope that they could be made type attributes in
future without breaking backwards compatibility.

Not having those hooks means that the validity and semantics of:

 void foo();
 void __attribute((subtype)) foo();

aren't really defined.  Does foo() keep its original type or change to
the subtype?  It's also not defined whether:

 void __attribute((subtype)) foo();
 void foo();

is invalid, or whether the subtype from the first declaration carries
over to the second.  Etc.  (To be clear, I'm not trying to start a
discussion on the right semantics, or anything like that.  I'm just
saying that I don't think the semantics are defined yet, although
I could be wrong.)

FWIW, the original implementation came from MTI, but it was a while ago
and I no longer have a record of the discussion.  (It was discussed and
submitted under a CodeSourcery contract.)  I might be misrepresenting things.

If you (MTI) are sure that we don't want them to be type attributes,
and that we should treat them more like optimisation switches, then we
can probably remove the check.  I think it's a one-way street though.

Richard


Re: mips16 and nomips16

2013-01-14 Thread reed kotler

On 01/14/2013 04:50 PM, David Daney wrote:

On 01/14/2013 04:32 PM, reed kotler wrote:

I'm not understanding why mips16 and nomips16 are not simple inheritable
attributes.


The mips16ness of a function must be known by the caller so that the 
appropriate version of the JAL/JALX instruction can be emitted





i..e you should be able to say:

void foo();
void __attribute((nomips16)) foo();


or

void goo();


Any call here would assume nomips16


void __attribute((mips16)) goo();


A call here would assume mips16.

Which is it?  If you allow it to change, one case will always be 
incorrect.


Or perhaps I misunderstand the question.

David Daney


I would assume that foo would be nomips16 and goo would be mips16.

The definition of plain foo() or goo() says that nothing is specified.

What is not clear then?

This is how all such other attributes in gcc are handled.






Re: mips16 and nomips16

2013-01-14 Thread David Daney

On 01/14/2013 04:32 PM, reed kotler wrote:

I'm not understanding why mips16 and nomips16 are not simple inheritable
attributes.


The mips16ness of a function must be known by the caller so that the 
appropriate version of the JAL/JALX instruction can be emitted





i..e you should be able to say:

void foo();
void __attribute((nomips16)) foo();


or

void goo();


Any call here would assume nomips16


void __attribute((mips16)) goo();


A call here would assume mips16.

Which is it?  If you allow it to change, one case will always be incorrect.

Or perhaps I misunderstand the question.

David Daney



mips16 and nomips16

2013-01-14 Thread reed kotler
I'm not understanding why mips16 and nomips16 are not simple inheritable 
attributes.


i..e you should be able to say:

void foo();
void __attribute((nomips16)) foo();


or

void goo();
void __attribute((mips16)) goo();

There does not seem to be any other cases in gcc where this would not be 
allowed.


Tia.

Reed