Re: Port from Win to OSX with Inline functions
site_archiver@lists.apple.com Delivered-To: darwin-dev@lists.apple.com I thought "inline" was a compiler issue - not a linker issue? Definitely the prototype is inline. Here is the sample I created: ------ macbook:~/dev/inline chris$ cat macinline1.c #include <stdio.h> #define INLINER inline INLINER void macfn1(void); INLINER void macfn1(void) { printf("macfn1-1-->\n"); return; } void macfn2(void) { printf("macfn2-->\n"); macfn1(); return; } ------ ------ ------ macbook:~/dev/inline chris$ make gcc -o macinline macmain.o macinline1.o macinline2.o /usr/bin/ld: multiple definitions of symbol _macfn1 macinline1.o definition of _macfn1 in section (__TEXT,__text) macinline2.o definition of _macfn1 in section (__TEXT,__text) collect2: ld returned 1 exit status make: *** [macinline] Error 1 Since, by definition: 1) An inline function is short 2) Its definition must be available to anyone who calls it Later, -Chris _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-dev mailing list (Darwin-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-dev/site_archiver%40lists.appl... 2) By default - an inlined function will also have a regular non- inlined copy in the object file. So - the short-term answer is to redefine __INLINE as "extern inline __attribute((always_inline))" and to build with optimizations enabled. Ultimately, however, I will likely need to change the prorotypes and function definitions to be static - so they work whether or not they are inlined. Actually, the only thing inline means is that it's OK if there are multiple definitions of a function and the linker shouldn't complain. I believe is that your problem is that your prototypes aren't inline -- you MUST fix at least that -- otherwise, the non-inlined prototype will take precidence over the inline definition. Here is the assembly code produced by the compiler with optimization turned on: macbook:~/dev/inline chris$ cat macinline1.s .cstring LC0: .ascii "macfn1-1-->\0" .text .globl _macfn1 _macfn1: pushl %ebp movl %esp, %ebp pushl %ebx subl $20, %esp call ___i686.get_pc_thunk.bx "L00000000001$pb": leal LC0-"L00000000001$pb"(%ebx), %eax movl %eax, (%esp) call L_puts$stub addl $20, %esp popl %ebx popl %ebp ret .cstring LC1: .ascii "macfn2-->\0" .text .globl _macfn2 _macfn2: pushl %ebp movl %esp, %ebp pushl %ebx subl $20, %esp call ___i686.get_pc_thunk.bx "L00000000002$pb": leal LC1-"L00000000002$pb"(%ebx), %eax movl %eax, (%esp) call L_puts$stub leal LC0-"L00000000002$pb"(%ebx), %eax movl %eax, (%esp) call L_puts$stub addl $20, %esp popl %ebx popl %ebp ret .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code +pure_instructions,5 L_puts$stub: .indirect_symbol _puts hlt ; hlt ; hlt ; hlt ; hlt .subsections_via_symbols .section __TEXT,__textcoal_nt,coalesced,pure_instructions .weak_definition ___i686.get_pc_thunk.bx .private_extern ___i686.get_pc_thunk.bx ___i686.get_pc_thunk.bx: movl (%esp), %ebx ret As you can see - the function call is inlined - there is no call to macfn1 - the printf has been inlined. However, the compiler is still embedding a ".globl _macfn1" version of the function. When I build with a copy of this .C file included in the build (with macfn2 renamed to macfn3) - the linker err's out with this: Honestly - that is what I would expect? If a global function is defined in multiple .o files, how is the linker supposed to know that those functions are all the same - certainly not by the name? I always define inline functions in their header (with no separate declaration). If the inline keyword is in the declaration, there is no need to declare them static -- in fact this will cause code bloat if they are referenced from multiple files and not inlined. Simply using inline will cause the linker to keep just one implementation, but for this to happen, all declarations must be inline. I do not see this happening. In fact, I see nothing in the generated assembly that would clue the linker into the fact that the function was inlined - and again, this is not surprising to me - since inline is a compile-time operation, not a link-time operation. In fact, here is a statement from the gcc inline doc pointer from Colin ... "When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion." This email sent to site_archiver@lists.apple.com
participants (1)
-
Chris Edgington