Unhelpful error message and compiler deficiency

Former Member
Former Member
From monkeyc compiler.

ERROR: ERROR:stdin:17812: Redefinition of label (code) _Users_dave_Garmin_DinghyRacer_source_AppMenu_mc_5_0


Turned out the error was the second line in this excerpt in a completely different file:

const PI = 3.14159;
const PIx2 = PI * 2.0; <<<< this caused the error.

Two points here - the error message doesn't help and the compiler should be able to resolve this at compile time.

Dave.
  • I think it would be very helpful to the development team if you could provide a test case for the issue and make a post in the Bug Reports forum (be sure to follow the Bug Reports Forum Rules in your post.

    I tried to reproduce the error given the snippet provided, but my test case works as expected (using the 2.2.3 SDK)

    using Toybox.Application as App;
    using Toybox.WatchUi as Ui;
    using Toybox.Graphics as Gfx;
    using Toybox.WatchUi as Ui;
    using Toybox.Math as Math;

    const PI = 3.14159;
    const PIx2 = PI * 2.0;

    class XView extends Ui.View
    {
    function initialize() {
    View.initialize();
    }

    function onUpdate(dc) {
    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_BLACK);
    dc.clear();

    var cx = dc.getWidth() / 2;
    var cy = dc.getHeight() / 2;

    dc.drawText(cx, cy, Gfx.FONT_LARGE, PIx2.toString(), Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    }
    }

    class XApp extends App.AppBase
    {
    function initialize() {
    AppBase.initialize();
    }

    function getInitialView() {
    return [ new XView() ];
    }
    }


    According to the Release Notes section for v2.2.0 in ${SDKROOT}/README.html, it appears that MonkeyC is supposed to fold literal constants. Here is the text...

    Optimize apps by having the compiler fold constants into a single value. var number = 4 + 5; will now compile to var number = 9; instead of performing an add operation.


    It does not seem that it has the ability to fold fold non-literal constants yet. I did some experimenting, and found some interesting stuff.

    Given this code...

    const PI = 3.14159;
    const PIx2 = PI * 2;


    I can see the following in the generated 'assembly' code (you can see this by compiling with -g and capturing the output being sent to stderr). I see this...

    globals:
    CLASSDEF
    APPTYPE 15
    MODULEID globals
    PI 1 FLOAT 3.14159;
    PIx2 1 NULL;
    XApp 1 CLASS @globals_XApp;
    <init> 2 METHOD @globals_<init>;
    Rez 1 MODULE globals_Rez;
    <init> 2 METHOD @globals_<init>;
    Toybox 0 NULL;
    END

    /* snipped */

    source_XApp_mc_4_0:
    lgetv 0
    spush PIx2
    lgetv 0
    spush PI
    getv
    fpush 2.0
    mulv

    putv
    return


    You can see that PI is a global that is statically initialized, but PIx2 is dynamically initialized in source_XApp_mc_4_0. It looks like the one source file in my project has this special init section. If there are multiple files with globals in them, and one of those globals depends on those from another file, it seems like there may be an order of initialization issue. I'll have to investigate to prove it, but if this is an issue, one way to avoid that would be to put all globals into a single file.

    Anyway, if you build with this code...

    const PI = 3.14159;
    const PIx2 = 3.14159 * 2;


    You will see the difference in source_XApp_mc_4_0...

    source_XApp_mc_4_0:
    lgetv 0
    spush PIx2
    fpush 6.28318
    putv
    return


    The global is still initialized dynamically, but no arithmetic is done at runtime. You can improve this further, but potentially increase maintenance cost, by explicitly giving a value to the constant without doing any arithmetic.

    const PI = 3.14159;
    const PIx2 = 6.28318;


    That results in this...

    globals:
    CLASSDEF
    APPTYPE 15
    MODULEID globals
    PI 1 FLOAT 3.14159;
    PIx2 1 FLOAT 6.28318;
    XApp 1 CLASS @globals_XApp;
    <init> 2 METHOD @globals_<init>;
    Rez 1 MODULE globals_Rez;
    <init> 2 METHOD @globals_<init>;
    Toybox 0 NULL;
    END


    I'm not sure this really helps you, but it does confirm that MonkeyC doesn't do folding of constant expressions where it could be. It seems to me that this is completely in line with what the ConnectIQ development team has announced, so I'm not sure it could be considered a bug. It also points out that there may be an issue with initialization order of globals in different source files (I'll experiment with this and post a bug report if I can confirm).

    Travis
  • While playing with the initialization order issue I mentioned above, I've discovered how to reproduce your issue. The problem comes up if you have globals declared in multiple files. I'll be posting a test case in the Bug Reports forum shortly.

    Travis
  • I've posted a bug report and list possible workarounds in this thread.

    Travis
  • @davebaldwinxyz: This is a little beside the point, but we do make a PI constant available in the Math module: https://developer.garmin.com/downloads/connect-iq/monkey-c/doc/Toybox/Math.html

    using Toybox.Math;
    var PIx2 = Math.PI * 2;