Wednesday 15 July 2009

GCC and Microchip MPLAB Compilers

As a professional software engineer I don't have a problem with closed source software. As a pragmatist I recognise that some Open Source software really is world class - the Linux kernal and the GNU 'C' compiler being notable examples.

The kernel and compilers are, of course, available as a free download. Alternatively, some companies package the Open Source software (in strict accordance with the GNU Public License) in a convenient form that people want to pay for. Often they also add proprietary applications that help you use or administer the system - it's the ecosystem of Open Source.

Microchip make the popular PIC microcontrollers, and they needed a compiler suite for their 16-bit chips. They decided to base their suite on the GNU 'C' compiler with extra code generation features for an additional charge.

Unfortunately, the free version of their compiler isn't just the GCC compiler: their licensing system accidentally nobbles many of the built-in features provided by the Open Source community: if you use the free version then all optimisations are disabled.

Fortunately this situation can be easily remedied, enabling optimisations though obviously not the Microchip proprietary features (that would be piracy...)

The fun starts in the Microchip contributed PIC30 code generator, released under GPL v2.0

pic30.c:1624

pic30_license_valid = 0;
path = make_relative_prefix(save_argv[0], STANDARD_BINDIR_PREFIX,
STANDARD_EXEC_PREFIX);

if (!path) fatal_error("Could not locate `%s`\n", save_argv[0]);
exec = xmalloc(strlen(path)+sizeof("pic30-lm.exe") + 1);
sprintf(exec, "%spic30-lm.exe", path);
args[0] = exec;
pid = pexecute(exec, args, "foobar", 0, &err_msg, &err_arg,
PEXECUTE_FIRST | PEXECUTE_LAST);
if (pid == -1) fatal_error (err_msg, exec);
pid = pwait(pid, &status, 0);
if (pid < 0) abort();
if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) {
pic30_license_valid=1;
} else if (WIFEXITED(status)) {
pic30_license_valid=WEXITSTATUS(status) - 256;
}


all well & good: the code generator is finding out whether the software is the free or paid version using a license manager helper pic30-lm.exe

Then something awful happens, and the none-too-discreet comment suggests it might not be a bug.

pic30.c:1776

if (pic30_license_valid < 0) {
/* an invalid license,
disable those optimizations turned on by -O2,-O3,-Os */
static int message_displayed;
char *invalid = (char*) "invalid";

#define NULLIFY(X) \
if ((X) && (message_displayed++ == 0)) \
warning("Options have been disabled due to %s license", invalid); \
X

if ((pic30_license_valid == -253) ||
(pic30_license_valid == -252)) invalid = (char*) "missing";
else if (pic30_license_valid == -248) invalid = (char*) "expired";
NULLIFY(flag_optimize_sibling_calls) = 0;
NULLIFY(flag_cse_follow_jumps) = 0;
NULLIFY(flag_cse_skip_blocks) = 0;
NULLIFY(flag_gcse) = 0;
NULLIFY(flag_expensive_optimizations) = 0;
NULLIFY(flag_strength_reduce) = 0;
NULLIFY(flag_rerun_cse_after_loop) = 0;
NULLIFY(flag_rerun_loop_opt) = 0;
NULLIFY(flag_caller_saves) = 0;
NULLIFY(flag_peephole2) = 0;
NULLIFY(flag_schedule_insns) = 0;
NULLIFY(flag_schedule_insns_after_reload) = 0;
NULLIFY(flag_regmove) = 0;
NULLIFY(flag_strict_aliasing) = 0;
NULLIFY(flag_delete_null_pointer_checks) = 0;
NULLIFY(flag_reorder_blocks) = 0;
NULLIFY(flag_reorder_functions) = 0;
NULLIFY(flag_inline_functions) = 0;
NULLIFY(flag_rename_registers) = 0;
NULLIFY(align_loops) = 0;
NULLIFY(align_jumps) = 0;
NULLIFY(align_labels) = 0;
NULLIFY(align_functions) = 0;

#undef NULLIFY
}


So that's all the Open Source pre-code generation optimisations disabled if you've not paid for the proprietary code generator?? Sounds a bit unfair.

However, if you replace pic30-lm.exe with a simple program that returns the result code 0 then GCC's former function is completely restored and you get precisely what you paid for: the Free (as in speech) bits.


main()
{
return 0;
}


should do it.

1 comment:

  1. Do you know if they are still in this state?

    I assume that to rebuild this one would need to set up a gcc x86 tool chain?

    ReplyDelete