Re: Port from Win to OSX with Inline functions
site_archiver@lists.apple.com Delivered-To: darwin-dev@lists.apple.com <prototypes> <lots of other stuff> <inline functions> Here's a sample: void FunctionToInline(void); <lots of other stuff> __inline void FunctionToInline(void) { <code that needs to be inlined> } -Chris On Oct 7, 2006, at 12:02 AM, Eric Albert wrote: -Eric On Oct 6, 2006, at 8:58 PM, Chris Edgington wrote: -Chris On Oct 6, 2006, at 11:54 PM, Eric Albert wrote: If you define INLINER this way, it works: #define INLINER static inline __attribute__((always_inline)) For that matter, this works too: #define INLINER static inline Hope this helps, Eric On Oct 6, 2006, at 8:37 PM, Chris Edgington wrote: Thanks for the quick responses ... I'll answer your questions ... ---------- #include <stdio.h> #define INLINER inline __attribute__((always_inline)) INLINER void macfn1(void) { printf("macfn1-->\n"); return; } void macfn2(void) { printf("macfn2-->\n"); macfn1(); return; } ---------- Here is the assembly produced by compiling that code: ----------- Any more thoughts? Thanks, -Chris On 6 Oct 2006, at 16:48, Chris Edgington wrote: Anybody have any thoughts on how to resolve this? Thanks, -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... Maybe I have not explained well, or maybe I'm not understanding. Your message sounds like you're saying that I can change the prototypes via the prefix header. The problem is this - the prototypes aren't marked as inline. Here's how the files are laid out: So the macro in a prefix file will only change the function decleration, not the prototype, unfortunately. That's what I wrote what I did about the prefix header. You need to change the prototype too, and that's how you'd do it. Eric - I agree that that seems like the right answer. The problem is this - that isn't required to build the code successfully under Windows - so the prototypes for all of the functions are not declared as static. Therefore, when I switch to "static inline" - the compiler then complains that the function does not match its prototype. Here is a sample error when I do this: filename.h:1285: error: static declaration of 'MyTestFunction' follows non-static declaration filename.h:440: error: previous declaration of 'MyTestFunction' was here Without 'static' in there, the function is exported. If the function is exported, its implementation has to exist so that other translation units may call it. The compiler could still inline it at some call sites and leave the out of line implementation in place, but that'd duplicate code and I'm not sure if the compiler ever thinks that would be a win. If you're worried about making this change in tons of files, the easiest fix is this: #define inline static inline Put that in a prefix file and you're all set. 1) The code is straight C 2) I've tried lots of different things - static inline, extern inline, compiler options, ... 3) I understand that inline isn't the performance gain that it used to be - but this is code that has evolved over the last 6-8 years 4) I suspect that static inline is ultimately the best workaround - the problem is that all the functions that are inlined also have a prototype that does not include the static keyword - so when I try to use static inline the compiler complains that the function doesn't match the prototype. Again - the goal here is to get this code to compile/work without changing it - 'cause there are over a HUNDRED files that use this format. So, if I can accomplish this by redefining __inline as a macro that resolves to something else - than I'm home free without having to change lots of source. Now - on to my research this evening. It looks like I cannot get gcc to inline a function, no matter what I do - and that the errors I'm seeing are likely a result of that fact. Here is some code: .cstring LC0: .ascii "macfn1-->\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 call _macfn1 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 call to macfn1 is not inlined - even though I'm clearly defining the function as having the always_inline attribute. I'm using the stock gcc in latest OSX dev environment (Tiger 10.4.8). Here's the output during the make - so you can see what the compiler is saying: gcc -c -S -v macinline1.c Using built-in specs. Target: i686-apple-darwin8 Configured with: /private/var/tmp/gcc/gcc-5363.obj~28/src/ configure --disable-checking -enable-werror --prefix=/usr -- mandir=/share/man --enable-languages=c,objc,c++,obj-c++ -- program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx- include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib -- build=powerpc-apple-darwin8 --with-arch=nocona --with- tune=generic --program-prefix= --host=i686-apple-darwin8 -- target=i686-apple-darwin8 Thread model: posix gcc version 4.0.1 (Apple Computer, Inc. build 5363) /usr/libexec/gcc/i686-apple-darwin8/4.0.1/cc1 -quiet -v - D__DYNAMIC__ macinline1.c -fPIC -quiet -dumpbase macinline1.c - march=nocona -auxbase macinline1 -version -o macinline1.s ignoring nonexistent directory "/usr/local/include" ignoring nonexistent directory "/usr/lib/gcc/i686-apple- darwin8/4.0.1/../../../../i686-apple-darwin8/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/i686-apple-darwin8/4.0.1/include /usr/include /System/Library/Frameworks /Library/Frameworks End of search list. GNU C version 4.0.1 (Apple Computer, Inc. build 5363) (i686- apple-darwin8) compiled by GNU C version 4.0.1 (Apple Computer, Inc. build 5363). GGC heuristics: --param ggc-min-expand=100 --param ggc-min- heapsize=131072 Compiler executable checksum: 117f4efba60aa7f11e5d2cf30dda5d40 I'm porting a large application from Windows to OSX. I'm trying to minimize changes to my clients codebase. One area that is giving me problems is inline functions. All over the place the client has functions in header files marked as inline (this is a performance-critical app). These header files get included by multiple .C files. When building with gcc on OSX - what ends up happening is that the compiler puts a copy of each inlined function in each .o file, then when I goto link I get linker errors because of multiple definitions of the same symbol. This email sent to site_archiver@lists.apple.com
participants (1)
-
Chris Edgington