Review: ByteCraft MPC Compiler
I've used the MPC C cross-compiler from ByteCraft and I'm basically satisfied with it. It runs quickly, and produces small, fast code. However, it's not perfect. Here's a list of the problems and limitations I've found. Some of these are due to the extremely limited PIC architecture, and some of these are simply compiler quirks:
- The compiler can only accomodate two bytes of arguments passed to each function. Any more than that need to be passed via global variables.
- Arrays can be no larger than 256 bytes.
- Arrays may have only one dimension.
- Structs or unions cannot be part of arrays.
- Local variables are local in scope, but are stored in the global memory space, and the memory is not reused by other functions. For this reason, I used a few global variables for temporary data, loop counters, and the like which are usually implemented as local variables. This worked OK, but is hardly ideal ...
- The "long" data type is only 16 bits, rather than the normal 32 bits.
- "sizeof" doesn't work on arrays or structures.
- Enumerated types are only for variables -- won't work for function return values or parameters ...
- The compiler does not (yet) have a linker, so multi-file programs must #include support modules rather than compiling them separately and then linking them in as a separate step. Note: A linker is currently in beta ...
- "extern" works only for function prototypes, not with data; thus, all variables, even in separate modules, effectively have global scope.
- By default, the compiler treats "ints" as 8-bit data. Specify the "+i" command line option to force 16-bit ints.
- If you try to assign too large of a value to a variable, the compiler doesn't issue a warning -- it will silently convert the number to the required type. For example, the statement "char a = 0x1234" will put "0x34" in "a".
- A function (or its arguments) cannot be of type "bits".
- The "static" modifier is accepted by the compiler, but has no effect.
- If a local variable is initialized in its declaration, the initialization is performed every time the function is called (regardless of whether the variable is declared as "static").
- Bitfields are not supported.
- The compiler uses about 22 bytes of RAM for working registers.
- There are quite a few incompatabilities between the built-in assembler and MPASM, which is surprising, considering that ByteCraft wrote that as well. Some of the differences are:
- All labels must begin in column 1.
- The "processor" directive is not supported.
- "if" / "endif" directives are not supported.
- The "error" directive is not supported.
- Macro syntax is different.
- Binary contants are specified with 00000000b rather than B'00000000'.
- MPC already pre-defines all the internal registers, so there were quite a few conflicts.
- The "CBLOCK" directive seems to work, though it's not documented in the MPC docs.
- "#define" is not supported.
- The "ADCON" directive is not supported.
- The "OPTIONREG" is not supported.
Support has been fair. They generally respond to questions within a few days, and compiler updates are available on their BBS. Unfortunately, while they have a web site, it only contains demos -- not updates or support files from the BBS.
Note #1: Since I wrote the rant above, ByteCraft has released an update (which they sent out for free to registered users) that apparently addresses a number of these concerns. In particular, it adds a linker and support for separately-compiled source modules. I haven't played with it yet, but when I do, I will update this list accordingly ...
Note #2: Microchip now has a C compiler of their own, known as MPLAB-C. It is based on the ByteCraft source code, but the two products are not the same. They are obviously very similar, but will likely each diverge in their own direction in the coming years. I have a copy of MPLAB-C, but I have not yet actually used it.
Bottom Line: Recommended