Wednesday, March 23, 2016

Compiler Directives

<< Prev: Xcode vs. AppCode       Next: Plugging Gaps >>

So there I was, faced with some inexplicable snippet of Linux code. I googled it. I landed at http://lxr.free-electrons.com/, which has got to be one of the single most useful resources for porting Linux code, hands down.

Whatever I was looking at was a compiler directive. Probably it was something like __maybe_unused. I followed the link on that page to compiler-gcc.h. And what do you know? Right above __maybe_unused is __packed. Remember __packed? I remember. It took me at least an hour to eliminate every occurrence of __packed.

But wait. That was way back when I thought __packed was complete magic. Now it turns out it's just a macro for an annotation that the compiler picks up.

But that's for GCC, and OS X has switched away from GCC. I'm pretty sure that's true -- I mean, I had to use lldb instead of gdb, and the project screen has a bunch of settings for Apple LLVM 7.0. But, I thought I heard that gcc and some other compiler forked and merged... maybe that was LLVM? (No.) Maybe they're pretty close after all? (Yes. Despite being different projects, GCC compatibility appears to be a goal of clang, the C/C++ compiler "front end" to LLVM.)

Bottom line, could I just snarf the definition of __packed instead of rewriting all that code? Yes I could. Yes I should, since that would make it a lot easier to update to the latest driver code later.

And while __packed (and __aligned) were the most obvious, there were a lot of others:
#define __packed             __attribute__((packed))
#define __aligned(x)         __attribute__((aligned(x)))
#define __printf(a, b)       __attribute__((format(printf, a, b)))
#define __attribute_const__  __attribute__((__const__))
#define __maybe_unused       __attribute__((unused))
#define __bitwise__          __attribute__((bitwise))
#define __must_check         __attribute__((warn_unused_result))

Most of those I had previously #defined to nothing, so it was nice that they would work more as intended, adding extra compile-time checks to the code.

But there were a few that didn't work too:
#define __force           __attribute__((force))
#define __acquires(x)     __attribute__((context(x,0,1)))
#define __releases(x)     __attribute__((context(x,1,0)))
#define __acquire(x)      __context__(x,1)
#define __release(x)      __context__(x,-1)

Actually, __acquires and __releases didn't cause any problems, but __acquire and __release caused a complaint about __context__, and I didn't see any further setup for that. I gather __context__(a,b) adds the second argument to a compiler variable named by the first argument (passed into the macro), while context(a,b,c) says that the compiler variable named by the first argument (passed into the macro) must have value "b" at the start of the function and value "c" when the function returns. But either those definitions are hiding somewhere else, or they're one of the areas where GCC has a feature that LLVM hasn't picked up.

Likewise it didn't seem to like the attribute force, but that just seems to suppress warnings for an odd cast, so it's not so critical for now. I'm way far away from attempting to get all the warnings out of the code!

Anyway, this let me blow another hour or more removing all the #prama pack statements. In return, though, it gave me a lot more confidence that the structs would come out as intended, and made it immensely easier to update the code to the driver included in a newer Linux release, when I later got around to that.

<< Prev: Xcode vs. AppCode       Next: Plugging Gaps >>

No comments:

Post a Comment