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: Sun, 15 Dec 2013 10:49:16 +0000 (GMT)
User-agent: Alpine 2.02 (DEB 1266 2009-07-14)

Sorry about the wait in my reply. Good to see it works for you, today
I'm looking at getting tcc to do 'the right thing' with inline
functions, I'll let you know if I have anything worth pushing to mob.

Rob


On Thu, 12 Dec 2013, Pierre wrote:

I have tested the changes in gen_inline_functions but do not work.
I have made change in decl0() in tccgen around line 5706

                while ((sym = sym->next) != NULL)
                    if (!(sym->v & ~SYM_FIELD))
                       expect("identifier");
#ifdef _HACK
                if (type.t & VT_INLINE)
                  if (type.t & VT_EXTERN)
                    type.t &= ~VT_INLINE;
                  else
                    type.t |= VT_STATIC;
#else
                /* XXX: cannot do better now: convert extern inline to static 
inline */
                if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | 
VT_INLINE))
                    type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
#endif
                sym = sym_find(v);
                if (sym) {
                    if ((sym->type.t & VT_BTYPE) != VT_FUNC)
                        goto func_error1;


this works to link my project with inline code in .h
Pierre


Le 12/12/2013 06:45, Christian Jullien a écrit :

      Here is the relevant part of C11 talking about inline function:

       

      Any function with internal linkage can be an inline function. For a 
function with external

      linkage, the following restrictions apply: If a function is declared with 
an inline

      function specifier, then it shall also be defined in the same translation 
unit. If all of the

      file scope declarations for a function in a translation unit include the 
inline function

      specifier without extern, then the definition in that translation unit is 
an inline

      definition. An inline definition does not provide an external definition 
for the function,

      and does not forbid an external definition in another translation unit. 
An inline definition

      provides an alternative to an external definition, which a translator may 
use to implement

      any call to the function in the same translation unit. It is unspecified 
whether a call to the

      function uses the inline definition or the external definition.

       

      EXAMPLE 1 The declaration of an inline function with external linkage can 
result in either an external

      definition, or a definition available for use only within the translation 
unit. A file scope declaration with

      extern creates an external definition. The following example shows an 
entire translation unit.

      inline double fahr(double t)

      {

      return (9.0 * t) / 5.0 + 32.0;

      }

      inline double cels(double t)

      {

      return (5.0 * (t - 32.0)) / 9.0;

      }

      extern double fahr(double); // creates an external definition

       

      double convert(int is_fahr, double temp)

      {

      /* A translator may perform inline substitutions */

      return is_fahr ? cels(temp) : fahr(temp);

      }

      11 Note that the definition of fahr is an external definition because 
fahr is also declared with extern, but

      the definition of cels is an inline definition. Because cels has external 
linkage and is referenced, an

      external definition has to appear in another translation unit (see 6.9); 
the inline definition and the external

      definition are distinct and either may be used for the call.

       

       

       

      From: address@hidden [mailto:address@hidden On Behalf Of Pierre
      Sent: jeudi 12 décembre 2013 00:48
      To: address@hidden
      Subject: Re: [Tinycc-devel] RE :Re: inline functions

 

Yes in fact gen_inline_functions just convert refferenced inline function to 
normal function.
I have remove my changes (line 3042 & 3030) and just added in 
gen_inline_functions around line 5597

                if (file)
                    pstrcpy(file->filename, sizeof file->filename, 
fn->filename);
                sym->r = VT_SYM | VT_CONST;
                sym->type.t &= ~VT_INLINE;
#ifdef _HACK
                if (!(sym->type.t & VT_EXTERN))            // extern inline = 
extern
                  sym->type.t |= VT_STATIC;                     // else static
#endif
                macro_ptr = str;
                next();
                cur_text_section = text_section;

I will do some test tomorrow
Pierre

Le 12/12/2013 00:27, Rob a écrit :

      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






_______________________________________________

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]