tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] RE :Re: inline functions


From: Rob
Subject: Re: [Tinycc-devel] RE :Re: inline functions
Date: Wed, 11 Dec 2013 23:27:37 +0000 (GMT)
User-agent: Alpine 2.02 (DEB 1266 2009-07-14)

Odd, msvc isn't a C99 compiler, didn't expect it to conform.

Anyway - I know the tcc code somewhat, but I'm not sure about inline
functions. They're handled as sort-of-macros in some cases, see
gen_inline_functions().

In short, I'm not sure of the changes and I'm off to bed shortly. I do
think tcc should remain standard-compliant though, and not imply static
or extern from just 'inline'. Perhaps we need another flag?


Rob


On Wed, 11 Dec 2013, Pierre wrote:
yes I think you are right, it is same with msvc v6.

I don't know well the tcc code, but I don't think it inline functions (like a 
macro, should be complicated to do).
So defining inline (alone) as static maybe a good idea ?

int tccgen.c line 3042

change:

        case TOK_INLINE1:
        case TOK_INLINE2:
        case TOK_INLINE3:
            t |= VT_INLINE;
            next();
            break;

to

        case TOK_INLINE1:
        case TOK_INLINE2:
        case TOK_INLINE3:
            if (!(t & VT_EXTERN))                   // if extern defined ignore 
'inline'
                t |= VT_INLINE | VT_STATIC;   // if not extern, set static as 
default
            next();
            break;

and line 3030

change
        case TOK_EXTERN:
            t |= VT_EXTERN;

to
   
        case TOK_EXTERN:
        {
            t |= VT_EXTERN;
            t &= ~VT_INLINE;                            // remove 'inline'
        }


I don't know if some more changes are required ?
Pierre


Le 11/12/2013 23:22, Rob a écrit :
      'inline' alone should not generate code, I'm pretty certain. It's an
      inline-only definition. If it can't be inlined, you get a linker error.

      For example:

      inline int f()
      {
          return 3;
      }

      int main()
      {
          return f();
      }

      A standalone function named 'f' will never appear in the generated code.
      If the compiler inlines 'f' into main, the program will link. If the
      compiler doesn't or can't inline 'f', you'll get a linker error.

      So we get a linker error with 'gcc -std=c99 -O0', but the program links
      fine with 'gcc -std=c99 -O1', as f isn't referenced (since it's
      inlined by an optimiser).

      Also, I checked - gcc defaults to -std=gnu89, which means gnu89 inline
      semantics, so when testing, make sure you give it '-std=c99'.

      Clang exhibits the same behaviour w.r.t. inline, so I'm pretty sure I've
      interpreted the standard correctly. Note that clang defaults to C99.


      Thanks,
      Rob


      On Wed, 11 Dec 2013, Pierre wrote:
            So inline alone should export nothing if not refferenced (with code 
or forward declared), and at most, create a static function if cannot be 
inlined ?

            And an 'extern inline ' simply ignore 'inline' ?


            Le 11/12/2013 22:33, Rob a écrit :
                  On Wed, 11 Dec 2013, Thomas Preud'homme wrote:
                        Le mercredi 11 décembre 2013, 09:28:07 Christian 
JULLIEN a écrit :
                        I knew about the fact that it is a hint and I knew even 
when inlined, the
                        function still needs to be output in case its address 
is used. However I
                        forgot about the other details. I stand corrected, 
thanks.

                        I remembered extern and inline has a special meaning as 
well but I forgot so I
                        checked online and I think the documentation of gcc [0] 
explains pretty well
                        how inline behave. I'm a bit surprised though because I 
thought the special
                        meaning of extern inline was not in the standard but 
something gcc specific.
                        Again, I stand corrected.

                        [0] http://gcc.gnu.org/onlinedocs/gcc/Inline.html

                              If you want to avoid problems when you define an 
inlined function in a .h is
                              to declare this function static. This way, if 
compiler is not able to
                              inline function, the two or more translation 
units using it will have their
                              own static copy that will make linker happy.


                        Or extern inline which has a slightly different 
meaning. With static inline you
                        need to provide two implementation of the function, one 
with static inline in
                        the header, and one normal implementation somewhere 
else in case there is a
                        call that cannot be inlined or if the address of the 
function is used. With
                        extern inline you make it clear that you want the 
function inlined no matter
                        what. At least that is my understanding after a quick 
read but again, I might
                        have read too quickly.



                  There are very subtle differences and with gcc I'm pretty 
sure you have
                  to specify -std=c99 otherwise it defaults to gnu89 which has 
different,
                  GNU inline semantics.

                  'inline', unfortunately is not just a hint to the compiler. 
There are a
                  few checks compilers have to perform too.


                  So we have three forms of inline:

                  extern inline void func() { ... } // 1
                  static inline void func() { ... } // 2
                         inline void func() { ... } // 3


                  The first form, 'extern inline', will always cause a
                  standalone/non-inlined function to be emitted, just as if 
'inline'
                  wasn't present. The inline modifier here simply acts as a 
hint that this
                  function may be inlined.

                  The second form, 'static inline', will cause function code to 
be
                  emitted, but the compiler may omit this if it knows the 
function is
                  never used (since it's static, it's not called from another 
translation
                  unit). Again, 'inline' acts only as a hint.

                  The final form, 'inline' without a storage class is where we 
have
                  special handling. In this case, standalone function code is 
never
                  emitted, this version is _only_ to be used for inline 
substitution.


                  For the final form to take affect, none of the declarations 
of `func'
                  must mention extern, for example:


                  inline f();
                  inline f();
                  extern inline f(); // this causes `f' to be in form 2
                  inline f() { ... }



                  At least, that's what I've gathered from the standard and 
various
                  searches.


                  Thanks, Rob


            _______________________________________________
            Tinycc-devel mailing list
            address@hidden
            https://lists.nongnu.org/mailman/listinfo/tinycc-devel






_______________________________________________
Tinycc-devel mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/tinycc-devel




reply via email to

[Prev in Thread] Current Thread [Next in Thread]