Want to read Slashdot from your mobile device? Point it at m.slashdot.org and keep reading!

 



Forgot your password?
typodupeerror
×
Programming IT Technology

Pre-Processers for Inlined C Code? 62

Scott Snell asks: "I have inherited the C code for an embedded system project that has run out of code space. The source code is highly fragmented and the compiler doesnt generate efficient code for stack handling. Ideally I would direct the compiler to 'inline' a lot of the functions but unfortunately it doesnt support the inline keyword. Using macros is dangerous and manually inlining is driving me crazy! What I need is a tool that will take the source files, look for the 'inline' keyword and generate new source files that are inlined. Any ideas?"
This discussion has been archived. No new comments can be posted.

Pre-Processers for Inlined C Code?

Comments Filter:
  • Port it. (Score:3, Insightful)

    by Guspaz ( 556486 ) on Thursday October 10, 2002 @02:11PM (#4425791)
    Porting it to a compiler that supports inline functions might be easier than manually inlining the functions, depending on how non-standard the C in your program is.

    Regards, Guspaz.
  • by Naikrovek ( 667 )
    Perl.
    • Re:in a word... (Score:2, Redundant)

      by photon317 ( 208409 )

      Here Here!

      Perl would be excellent for this job.

      • And a hearty fuck you to whoever modded me redundant. No shit it's redundant, the point of the post is to bolset the opinion of the parent post. Multiple voices speak stronger than one. Redundant would be if two people both cut-n-pasted an article text or something like that.
    • You mean that you think Perl is a solution to a text processing task? Nexst you'll be suggesting using a clock to tell the time or something equally daft.
  • Use macros (Score:3, Interesting)

    by adb ( 31105 ) on Thursday October 10, 2002 @02:16PM (#4425844)

    Unless I'm on crack, inlining all calls to a function is pretty much the same as replacing the function with a macro. The main difference between inlining and macros would be that the compiler can decide not to inline a function if it doesn't make sense (e.g., if the function is recursive and the compiler isn't up to iterative-izing it), whereas with macros you just can't do recursion safely.

    • Re:Use macros (Score:4, Insightful)

      by bsmoor01 ( 150458 ) <`seth' `at' `beere.org'> on Thursday October 10, 2002 @02:58PM (#4426279)
      First off, macros are generally evil. With that out of my system, you're also not quite correct.

      Macros are simply 'cut-n-pasted' into the source, then compiled. Thus, no type checking takes place.

      There are many reasons you should try not to use macros. Personally, I try to avoid any preprocessing when I can. The C++ FAQ Lite [parashift.com] is much better at explaining it all that I. More specifcially, try Reason 1 [parashift.com] Reason 2 [parashift.com] Reason 3 [parashift.com] Reason 4 [parashift.com]
      • ...the poster is already talking about ways to transform the text of the code, which almost certainly won't pay attention to type checking anyway. I'd rather have a macro that gets transformed when the code is compiled than run a Perl script to mangle the code once and have to maintain it thereafter. (Yes, I forgot about type checking when I wrote my reply.)
      • Thus, no type checking takes place
        Since when was any arbitrary value not type checked? Just what are you talking about?
        #define blah 2 /* that there is an int... */
        int i = blah;
        Thats not an error nor even a warning IIRC.

        In cases where yuo put an entire function into a macro, you're not going to get a return value the way you normally do, most likely you'll pass the variable that will hold the return value as an argument. which in that case, since the preprocessing is done BEFORE the compiler ever sees the code, so it really is inlined in the truest sense of the word. And type checking is done just the same as with 'normal' code, because it IS normal code once the compiler gets the preprocessed code.

        say like:
        #define blah(a, b, c) do { \
        c = a + b; \
        } while(0)

        int one = 1, two = 2, three = 0;
        blah(one, two, three);
        is EXACTLY like:
        int one = 1, two = 2, three = 0;
        three = one + two;
        so where did the lack of type checking come from?
    • Wouldn't inlining make things worse?
    • I think you're missing one of the potential dangers of macros here. Try this one:
      #define double(x) (x+x)
      int y,x=3;
      y=double(x++)
      This expands to
      y=(x++) + (x++)
      giving an unexpected result that x is now 5, and y is now 9. This happens with most implementations of max and min. It's one of my favourite tricks to confuse people who think they know more about C than they actually do.
      • Yes, I failed to think about general macro lossage the first time around. I'm still going to claim that it's the sanest way of doing without inlines, since I've never seen a preprocessor that will inline __inline__ functions for you, and writing your own is unlikely to be worth the trouble. Go ahead and use macros, just beware of the pitfalls.

  • GCC? (Score:1, Interesting)

    by dhilvert ( 608753 )
    Is using GCC not an option?
  • by jspayne ( 98716 ) <jeff@nOSpAm.paynesplace.com> on Thursday October 10, 2002 @02:35PM (#4426030) Homepage
    Did I miss something, or is the poster asking how to *reduce* code size ("run out of code space") - using inline will make your code bigger by duplicating the source. Are you actually running out of stack (data) space?

    What compiler is being used? The inline keyword is not supported by ANSI C - it is a C++ feature. However many C compilers support a proprietary inline declaration. Examples:

    Green Hills: __inline
    Diab: __inline__
    Others use: #pragma inline

    So, RTFM. Also, check the docs for inlining optimizations.

    Jeff

    • by sunryder ( 192810 ) <`moc.liamtoh' `ta' `naalnahtan'> on Thursday October 10, 2002 @02:52PM (#4426215) Homepage
      You're right: inline functions will generate larger compiled code sizes if the function is called often enough. However, it is not impossible that the overhead of calling the function generates more machine code than inlining the code. This would depend on the system he is targetting and the size/purpose of the function that is to be inlined.

      On the other hand, I reread the post several times, and I'm probably wrong, but it almost sounds like he is running into a problem with "source code" space. Could it be that he is compiling the code on the embedded system?

      At any rate, this post should be modded as Offtopic because it doesn't really attempt to answer the problem. I'm guess I'm just trying to figure out if there isn't maybe another solution.
    • Actually it is an ANSI/ISO C feature but only with the current standard of C99, not C89 like most compilers implement.
    • by clem.dickey ( 102292 ) on Thursday October 10, 2002 @03:52PM (#4426804)
      > The inline keyword is not supported by ANSI C - it is a C++ feature.

      Inline is in C99, see section 6.7.4 of the standard.

      That said, inlining can reduce code size if the function body object code is small relative to the parameter setup object code. Absent an inline feature in the compiler (what compiler could that be?), I think macros would be less dangerous than any specialized "inline preprocessor", even if there should be one.
  • Green Hills [ghs.com] has proposed an Embedded C++ standard [ghs.com] which is essentially ANSI C++ without exception handling, mutiple inheritance, namespaces, run time type identification, templates, or virtual base classes. It does support the C++ inline keyword. So the compiler will, when possible, expand functions as macros. This results in faster performance at the expense of larger code space, but smaller stack space.

    There are few problems porting code from C to C++. It's actually more difficult to port from pre- to post-ANSI C++, e.g. because of changes to the definition of the for statement. A C++ compiler is more type strict then a C compiler, meaning that more operations between different fundamental data types will be flagged as errors.

    EC++ won't result in tremendous code bloat, either. About the same order of ANSI C. Plus if this system continues to evolve, one can take advantage of easier memory allocation with new and delete as opposed to malloc and free.

    Granted the original post asked about inlining C functions. But moving to C++ gives one portability, since the inline keyword is part of the ANSI C++ standard.

  • by funbobby ( 445204 ) on Thursday October 10, 2002 @03:04PM (#4426336)
    as using some strange non-standard tool or hack to get around this, or letting your code get really big and ugly from "manually inlining" everything.

    Macros have their dangers, but at least their dangers are well understood, and should be familiar to anyone who is writing embedded C. It is the commonly used solution to your problem, which makes it nice for keeping your code maintainable.

    If you use a trick to get around the problem, it will just be another thing to confuse the next person who has to maintain the code.
  • Various... (Score:2, Informative)

    by 0x69 ( 580798 )
    As our Asker noted, macros are dangerous. For example, let a macro processor replace

    foo = bar(i++);

    and you'd better hope that the parameter isn't used more than once in the function's code - otherwise i will get incremented too often - hello bugs!

    Flip side, you can eyeball the most commonly used functions for safe-to-macro-inline candidates and save space just on them.

    An el-crapo compiler could easily burn more bytes with call & return code than a small function would need inline.

    Are there any dusty & old or not-so-essential hunks of this code that could be ditched? A badly-written section that could be rewritten much smaller? Wordy user interface stuff to edit down?
    • foo = bar(i++);
      Macros arn't dangerous, just the lazyness of the coder.
      #define bar(i) do { int v=(i); /* use v multiple times here */ } while(0)
      And please if anyone says thats slower than:
      #define bar(i) (/*use i multiple times...*/)
      Prove it? with real benchmarks, and state the compiler, and arch/system youre using. (belive it or not, but they all influence the result)

      IIRC, the first example should be optimized up the waazoo. loop goes away (duh), and it's possible, depending what you're doing with v, that v will vanish.
  • by Euphonious Coward ( 189818 ) on Thursday October 10, 2002 @03:12PM (#4426410)
    Assuming that Gcc doesn't target your platform (otherwise you could just switch to Gcc) you can get an excellent inlining preprocessor from Comeau Computing (look it up on Google), at a very reasonable price.

    Their preprocessor happens also to be a complete C++ compiler. You don't have to use the rest of the C++ features. (You might, for example, want to turn off exception handling.)

    Any half-assed preprocessor that just folds function bodies into line is likely to be much worse than using macros. The worst possible outcome is code that's in some weird private language that only your weird private tools understand. (Cf. Qt/KDE)

  • #include "function.i"

    • That works, but it's really just a macro without any parameters. It removes some of the dangers of the macro, but also a lot of the usefulness.

      If you're going to do it, you might as well use #define. It will have the same effect, but its a more standard way to say it. (and you don't have to have a bunch of files with just one function)
      • #include is really more flexible, because you can
        have macro expansions in the included text without
        re-#defining the whole function body.

        As for parameters, do

        #define PARAM1 abc
        #define PARAM2 def
        #include "function.i"
        #undef PARAM1
        #undef PARAM2
  • by ComputerSlicer23 ( 516509 ) on Thursday October 10, 2002 @04:13PM (#4427010)
    Using M4 or some other preprocessor should alleviate a lot of the problems. You can use it to preprocess the code, before it gets to the C preprocessor. Possibly use a version of C-front, which outputs C code from C++, then just compile the C it outputs. Some of the C-front compilers support inlining no problem. Otherwise, it's relatively simple to follow the rules to make using straight C macros not be dangerous. Everything you pass to a macro is a locally declared variable, with no expressions, and it'll act just the way you want. It's a pain in the ass to remember, but then again, you are writting an embedded system.
  • Unless the functions to inline are *real* small. Think about it- if the function is f bytes in size inlined, and f+a bytes in size as a standalone, and it takes c bytes to call the standalone function, and the function is called in n places, then inlining the function everywhere takes f*n bytes, while calling it takes c*n + f + a bytes. If c f - ((f+a)/n), then it'll be cheaper (require fewer code bytes) to not inline f than to inline f. As n gets large, all you need is c f for it to be a win. How many bytes does it take to call a function? That's your target- if your function is more than a few lines of code (at best) you're probably better off not inlining the function.

    I'd actually be inclined to go the other direction- is it possible to uninline things? If the code is doing similiar things in different places, is it possible to write a single function which is instead called in both places?

    Barring that, other options include using a different complier- does gcc support your processor? I know gcc doesn't support everything under the sun- many 8- and 16-bit micros and DSPs aren't supported, for example. But if gcc is supported, it does pretty good on the stack space management and automatically inlining. Or you just might have to bite the bullet and spring for a larger rom/flash or larger cpu.

    Brian
  • A tad heavy handed, but if everything else fails, you can always write your dream inliner yourself with Cil :
    http://manju.cs.berkeley.edu/cil/cil001.html
  • "Dear Slashdot" (Score:5, Insightful)

    by kawika ( 87069 ) on Thursday October 10, 2002 @05:19PM (#4427638)
    I need to squeeze down some C code to fit into an embedded system. I can't tell you much about it, for example the processor type, what compiler I'm using, how much of the code is libraries and how much is our own code, or how far over the limit we are.

    I think the problem can be solved by inlining functions. Yes, inlining. Even though this generally increases code size, I think it's the solution in this case. You don't have enough information to argue about this, so trust me. Just give me a solution. Can you write me a Perl program, for example? I told you that the word you are looking for is "inline". Is there anything else you need to know?
  • Using macros is dangerous and manually inlining is driving me crazy! What I need is a tool that will take the source files, look for the 'inline' keyword and generate new source files that are inlined.

    Umm, isn't looking for the inline keyword and generating new source files dangerous as well?

  • by mekkab ( 133181 )
    Use awk.

    Why? So you can con management into buying you that nifty O-reilly CD-ROM series for UNIX!

    Worked for me...

  • are you really saying that you've run out of space in the code segment? or that the call depth is exceeding the size of the stack?
  • For about 10 years I have been working with C compilers that would (depending on optimization settings of course) inline functions with a code size under a certain threshold. Don't need a keyword, just a optimization threshold.

    That said, you are looking to refactor your software anyway, you might as well do it right, possibly starting with picking a newer more modern toolset, architecting the code differently to allow you to optimize for stack/code/data space, and many other factors. Will this take time, of course, but it might not take as long as a simple little hack, plus give you better results, and the ability to improve in the future. Will management buy it ??? Probably not, so just tell them you are inlining everything, and give them so much more out the back end.

  • are you kidding? (Score:5, Informative)

    by selectspec ( 74651 ) on Thursday October 10, 2002 @06:41PM (#4428246)
    I have inherited the C code for an embedded system project that has run out of code space.

    Stack space? Inlining is not neccessarily going to solve this problem. Recursion is probably your problem. Also, make the stack larger if possible.

    Instruction space? Inlining will most likely make this worse, except in extremely abstracted code where the overhead to make the function call is more than the inline expense.

    ...the compiler doesnt generate efficient code for stack handling.

    The solution is to fix the compiler's stack handling. When the compiler is the problem, fix the compiler. I've never heard of an embedded systems project that didn't include someone hacking with the compiler.

    Ideally I would direct the compiler to 'inline' a lot of the functions but unfortunately it doesnt support the inline keyword.

    Changing the compiler to support the keyword is probably a pain in the butt. However, there are very few C compilers which don't support some form of the inline keyword. Double check your docs.

    Using macros is dangerous...

    Macros Dangerous? That's rediculous. I suppose creating some wierd perl script to munch through your source code ripping up inline functions and auto-generating C files that will never have the propper dependecies is safe?

    ...and manually inlining is driving me crazy! What I need is a tool that will take the source files, look for the 'inline' keyword and generate new source files that are inlined. Any ideas?"

    This is crazy! Autogenerating code is a great way to totally fuck up your build system. You'll never get your dependencies right and you'll end up building your entire project every time. Writing a tool that will parse your source code and identify the inline keyword is *exactly* as complicated as making the compiler understand the inline keyword. Don't do some bizzare on-off wierd hack. Instead, if you really want to use inline, bust out your compiler source and get cranking. If you don't have the compiler source, bust out gcc source and get cranking porting gcc to your hardware.

  • On another note, I'm a compiler writer who's having problems writing my compiler. Does anyone who frequents Slashdot know of a tool that will take a language standard as its input, and generate a working, bug-free, efficient compiler? Barring that, is anyone proficient enough in Perl? That's the language I've been using to implement my compiler, and I find that it's great for parsing. And while you're at it, maybe you could...
    • Does anyone who frequents Slashdot know of a tool that will take a language standard as its input, and generate a working, bug-free, efficient compiler?
      Think about it. If such a thing were possible, why would compiler writers waste all their time doing it manually?

      There are lexer and parser generators (e.g. flex and bison) that take a context-free simplification of the language and automatically produce efficient and bug-free lexers and parsers. But you have to take care of the context-sensitive part of the language (e.g. checking that variables are declared before they are used) and the code generation manually.

      • Does anyone who frequents Slashdot know of a tool that will take a language standard as its input, and generate a working, bug-free, efficient compiler?

        Think about it. If such a thing were possible, why would compiler writers waste all their time doing it manually?

        Actually, I really am a compiler writer, and yes, I do know that such a thing is, of course, impossible. And that was part of the joke in the post you replied to. Asking for the impossible, or nearly impossible. Sort of like request in the story: "Can you give me a link to the nearly impossible? If not, can someone do it for me?" Also, please note the ellipsis at the end of the post. That tends to denote a lack of seriousness in a post that is a series of requests.

  • I don't think inline isn't part of the (old) C standard. It is part of the C++ standard and I believe it may have been when cfront was around. The original C++ compiler, cfront, worked by preprocessing C++ and spitting out C to a C compiler. If what I say is correct above it must have done what you ask. Therefore port the code to C++ (if you're using ANSI C this is most likely trivial) and cfront it. I believe a version of cfront may still be available.
  • I see this problem from another direction.
    You are talking about inline, stack, hacking, ... but dont forget every language make possible to write almost everything. So what you realy need to think about is not the inline problem, but your code itself. I saw many programmers who try to fix their problem with some hacking, insted of trying to find and fix the real problem.
    I think you have to think about your code functionality, and than you will be able to see how you can fix this problem witout any hacking. There is always a way to fix the real problem!
    What you are trying to make is cover a bug with another bigger one! Dont be crazy!!
    What you should do is planning and not hacking!

Today is a good day for information-gathering. Read someone else's mail file.

Working...