18

One of my (embedded) targets only has a C89 compiler.

I am working on a (hobby) project which targets multiple devices.

Is there a way of compiling (transpiling?) a C11 code base into C89?

(Otherwise I will have to code like it's 1989, literally.)

fadedbee
  • 42,671
  • 44
  • 178
  • 308
  • 6
    Welcome to my world - my lowest common denominator is Microsoft MSVC, which still doesn't even support C99. – Paul R Oct 01 '13 at 16:35
  • 11
    what C11-specific features are you using? – SheetJS Oct 01 '13 at 16:35
  • C89, is that with K&R arguments? main(argc, argv) int argc; char **argv; Memories... – Charlie Burns Oct 01 '13 at 16:38
  • 3
    @CharlieBurns Of course not. K&R arguments are only mandatory in K&R C. C89 allows modern prototypes. – Pascal Cuoq Oct 01 '13 at 16:47
  • 2
    What is that target you are compiling for? Even though this does not answer your question as it is, it might be someone knows a way to compile C11 to that target somehow. – MvG Oct 01 '13 at 17:08
  • 3
    If it wasn't for the C.11 request, I would recommend [Comeau C](http://www.comeaucomputing.com/). It compiles C.99 code into C.90 code. – jxh Oct 01 '13 at 17:18
  • 1
    I'd complain to the manufacturer. Other than that, there may be someone else who has ported the chip to GCC. – ldav1s Oct 01 '13 at 17:56
  • 3
    I feel your pain @PaulR. Maybe in 2013 some of these [promised C99 features](http://blogs.msdn.com/b/vcblog/archive/2013/06/28/c-11-14-stl-features-fixes-and-breaking-changes-in-vs-2013.aspx) will be available in MSVC. I'm not holding my breath, though. – ldav1s Oct 01 '13 at 17:57
  • 5
    What's your target? Would it be hard to port clang/llvm? – Carl Norum Oct 01 '13 at 18:02
  • Not directly, but whether there is a simple solution will depend on what C11 specific features your code base uses. In embedded systems it is common to use a restricted subset of a language to ensure portability across platforms where compiler development may not be as fast as you might like. Architectures with low volumes do not have the tools development critical mass of ARM for example, and other architectures may not have the on-chip resources to make some features useful (or even safe). – Clifford Oct 02 '13 at 09:51
  • 2
    @MvG, Carl Norum - Target is Z80 - there are several immature attempts at LLVM/Z80, but nothing that's made it back into the official release. Currently using z88dk. – fadedbee Oct 02 '13 at 10:54
  • @Nirk user defined literals, plus other things from C99, like limiting the scope of loop variables to the loop and designated initializers. I don't need all the new threading stuff for the single core Z80. – fadedbee Oct 02 '13 at 11:02
  • See also https://stackoverflow.com/q/10804162 – Arto Bendiken Sep 01 '18 at 04:33

2 Answers2

9

No I don't think that it is possible for all of C11. C11 has features that simply not exist in C89 or C99: _Generic, _Atomic, _Thread, _Alignof, well defined sequenced before ordering, unnamed struct and union members ... These don't have counter parts in the older versions and would be really difficult to emulate.

For any of these features you would have to rely on extensions of your target compiler, so probably possible for some of the features for one given compiler. But it would be a nightmare to write such a tools that would have plain C89 as a generic target. You'd better implement a C11 compiler directly.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • If it's not necessary to get readable source code, a conversion should be possible with clang/llvm – jeb Oct 02 '13 at 07:46
  • @jeb, I am not so sure. To implement certain of the new constructs in some way, is certainly possible with some ugly looking code. But C11 has subtle differences in its guarantees for data consistency which might be difficult to map to C89. The thing is that when moving from one standard to the next all efforts are made to keep conforming programs for the older standard conforming for the newer. But programs that have undefined behavior in the older standard may become valid in the new one. It will be very difficult to "translate" them back to the older standard without triggering that UB. – Jens Gustedt Oct 02 '13 at 08:40
  • But as C11 can be translated to asm or in this case llvm, it's posible that you can create from this asm/llvm code valid c89 code. – jeb Oct 02 '13 at 09:43
  • @jeb, I am not sure if you take an assembler that is produced for one architecture, disassemble this to C89, and then compile on a different platform you'd have the same properties and consistency guarantees that you have for your original C11 code. In fact it even is quite unlikely. – Jens Gustedt Oct 02 '13 at 11:53
  • But as all (C89/C11/asm/llvm) are all turing complete, it's obvious that it must be possible to convert each one in each other variant. The new features of C11 aren't so relevant here as it must be simple to convert them also to asm. – jeb Oct 02 '13 at 12:54
  • @jeb, that's not what I said. Clearly you can convert the new features to asm. What is difficult is to disassemble them to C89 with exactly the same properties as the orginal C11 code, regardles with which C89 conforming compiler it will be compiled. – Jens Gustedt Oct 02 '13 at 13:37
  • It would not be possible to translate C11 into fully-portable C89 code, but it should be possible to write a translator that could target a C89 compiler for any reasonably-normal platform. C89 may not support _Generic or _Alignof, but it could simply substitute the proper types in the former case or the proper value in the latter. C89 also doesn't support `long long`, but a translator could define a `__longlong` structure type and a library of routines that operate on values of that type. – supercat Dec 08 '16 at 00:56
3

As Carl Norum comments:

What's your target? Would it be hard to port clang/llvm?

This seems to be the promising approach.
It's not necessary to port your target, a port for C89 is enough.

So clang compiles your code to llvm and then llvm to c89 and then you get it.

jeb
  • 78,592
  • 17
  • 171
  • 225