Giter Site home page Giter Site logo

espruinocompiler's People

Contributors

fanoush avatar gfwilliams avatar jamwaffles avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

asupawat fanoush

espruinocompiler's Issues

compiled code locks Espruino device while interpreted code runs

see this post (near the end) for a sample which could be used for testing (tested on an original Espruino, no need to actually attach WS2812 LEDs)

Currently, the mentioned code contains three major functions, one of them still runs when "compiled", adding "compiled" to the other ones produces no compiler errors but - when uploaded into flash (because of its length) and started - locks the whole device (I had to reflash the firmware in order to get the board operational again)

This is a K.O. bug as it turns out to be so unpredictable (you never know whether compiled code will run or not) and so labour-intensive (because the firmware has to be flashed again)

Cache symbol table lookups

Originally: espruino/EspruinoTools#8

Currently, if I write:

function f() {
  "compiled";
  a = 1;
  a = 2;
  a = 3;
}

It does 3 symbol table lookups for a. Ideally it'd look a up once and then keep it for future use.

Even more of an issue for something like:

function f() {
  "compiled";
  digitalWrite(LED1,0);
  digitalWrite(LED1,1);
  digitalWrite(LED1,0);
  digitalWrite(LED1,1);
}

Where both digitalWrite and LED1 get looked up each time.

While potentially that causes issues with something like this:

function setA() {
 a=1;
}

function f() {
  "compiled";
  console.log(a);
  setA();
  console.log(a);
}

The first use of a should have failed with a ReferenceError (but it doesn't in Espruino) so we're probably safe to ignore it.

how to config the process.env.EXPORTS

When I sent code optimized the function with "compiled", It prompt "Compiler not active as no process.env.EXPORTS available". How to fix it ?
The firmware version is 1v17.24, and The "EXPORTS" variable has no values.

Infer argument types

Currently if I write:

function a(x) {
  "compiled";
  print(x|0);
}

You get something a bit like like:

void a(JsVar *x) {
  print(jsvGetInteger(x)|0);
}

We know that x|0 is an integer already, so ideally:

  • x itself would get converted to an integer, which would change the argument type
  • x|0 then detected as a no-op and removed (although the compiler would do this so do we care?)
void a(int x) {
  print(x);
}

Make sure ^= (and others) work with ints

Something like this:

function checksum(m) { 
  "compiled"; 
  var ck = 0;
  var l = 0|m.length;
  var c = m.charCodeAt.bind(m);
  for (var i=0;i<l;i++) ck ^= c(i);
  return ck;
}

Isn't as fast as it could be, because ck is treated as a JsVar, not an int.

ASM.js support

Originally: espruino/EspruinoTools#9
And also: espruino/Espruino#332

It'd be nice to make sure we compile asm.js code relatively efficiently. I think the main requirements are:

  • Infer argument types: #4
  • Make sure we access arraybuffers such as MEM8 in a fast way (ideally getting a pointer and dealing directly with that)

Make sure .length result is treated as an int

Currently a simple FOR loop can fall off the fast path:

var l = "Hello".length;
for (var i=0;i<l;i++) ;

Will generate code that does 'l' (and hence the comparison) with JsVars instead of ints

no space allocated for BSS section - uninitialized global variables corrupt memory

see also conversation https://forum.espruino.com/conversations/383232/

I also remember hitting this. Workaround is to initialize variable with nonzero value like int a = -1; below so that it goes into .data section, not .bss

var c = E.compiledC(`
// void init()
// int f()
int a = -1;
void init() {
  a = 0;
}
int f() {
  a++;
  return a;
}
`);

Here is the difference
not initialized or initialized to zero ends with:

00000018 <_Z4initv>:
  18:   4b02            ldr     r3, [pc, #8]    ; (24 <_Z4initv+0xc>)
  1a:   447b            add     r3, pc
  1c:   2200            movs    r2, #0
  1e:   601a            str     r2, [r3, #0]
  20:   4770            bx      lr
  22:   bf00            nop
  24:   0000000a        andeq   r0, r0, sl

Disassembly of section .bss:

00000028 <a>:
  28:   00000000        andeq   r0, r0, r0


----------------------------------------
(function(){
  var bin=atob("Akt7RBhoATAYYHBHGgAAAAJLe0QAIhpgcEcAvwoAAAA=");
  return {
    init:E.nativeCall(17, "void()", bin),
    f:E.nativeCall(1, "int()", bin),
  };
})()
----------------------------------------

Initialized ends with

00000018 <_Z4initv>:
  18:   4b02            ldr     r3, [pc, #8]    ; (24 <_Z4initv+0xc>)
  1a:   447b            add     r3, pc
  1c:   2200            movs    r2, #0
  1e:   601a            str     r2, [r3, #0]
  20:   4770            bx      lr
  22:   bf00            nop
  24:   0000000a        andeq   r0, r0, sl

Disassembly of section .data:

00000028 <a>:
  28:   ffffffff                        ; <UNDEFINED> instruction: 0xffffffff


----------------------------------------
(function(){
  var bin=atob("Akt7RBhoATAYYHBHGgAAAAJLe0QAIhpgcEcAvwoAAAD/////");
  return {
    init:E.nativeCall(17, "void()", bin),
    f:E.nativeCall(1, "int()", bin),
  };
})()
----------------------------------------

it can be seen that the var bin string is longer in initialized case woAAAA vs woAAAD/////

One possible fix is to put everything into text segment in the linker file as we load to RAM anyway and don't support separate data vs code and relocation of data references. Or at least the .bss can be included into .data.

diff --git a/inc/linker.ld b/inc/linker.ld
index 7ea3647..7d4d609 100644
--- a/inc/linker.ld
+++ b/inc/linker.ld
@@ -22,17 +22,21 @@ SECTIONS
     *(.rodata)
     *(.rodata*)
     . = ALIGN(4);
+/*
   } >RAM

   .data :
   {
     . = ALIGN(4);
+*/
     *(.data)           /* .data sections */
     *(.data*)          /* .data* sections */
+/*
   } >RAM

   .bss :
   {
+*/
     /* This is used by the startup in order to initialize the .bss secion */
     *(.bss)
     *(.bss*)

floating point support

One example in https://www.espruino.com/InlineC is using double type however the caveats section mentions "Arithmetic with floats, doubles and uint64 may not work since it requires functions that won't be compiled in."
I tried the mandelbrot javascript example as inline C (just replacing var by int and double or float like

var c = E.compiledC(`
// int mand(int, int)
int mand(int x,int y){
  double Xr = 0;
  double Xi = 0;
  int i = 0;
  double Cr=(4*x/64)-2;
  double Ci=(4*y/64)-2;
  while ((i<32) & ((Xr*Xr+Xi*Xi)<4)) {
    double t=Xr*Xr - Xi*Xi + Cr;
    Xi=2*Xr*Xi+Ci;
    Xr=t;
    i=i+1;
  }
  return i;
}
`);

An indeed it doesn't work and compiler produces

>---------------------------------------------------
                                 COMPILER MESSAGE
---------------------------------------------------
/tmp/ccpIbvpd.ltrans0.ltrans.o: In function `mand(int, int)':
<artificial>:(.text._Z4mandii+0x10): undefined reference to `__aeabi_i2d'
<artificial>:(.text._Z4mandii+0x1e): undefined reference to `__aeabi_i2d'
<artificial>:(.text._Z4mandii+0x3a): undefined reference to `__aeabi_dmul'
<artificial>:(.text._Z4mandii+0x4a): undefined reference to `__aeabi_dmul'
<artificial>:(.text._Z4mandii+0x68): undefined reference to `__aeabi_dadd'
<artificial>:(.text._Z4mandii+0x74): undefined reference to `__aeabi_dcmplt'
<artificial>:(.text._Z4mandii+0x8c): undefined reference to `__aeabi_dsub'
<artificial>:(.text._Z4mandii+0x94): undefined reference to `__aeabi_dadd'
<artificial>:(.text._Z4mandii+0xa4): undefined reference to `__aeabi_dadd'
<artificial>:(.text._Z4mandii+0xac): undefined reference to `__aeabi_dmul'
<artificial>:(.text._Z4mandii+0xb8): undefined reference to `__aeabi_dadd'
collect2: error: ld returned 1 exit status
---------------------------------------------------

I see there are quite lot of methods exported via process.env.EXPTR for the javascript compiler to work. Would it work if the export list was extended by those eabi floating point methods listed above? Or are there other fundamental issues why this was not done? All those are probably linked inside espruino binary already so it would just enlarge the export table a bit by couple of pointers?

Errors generated randomly when uploading "compiled" function Espruino 1v4

So, I use some compiled javascript functions and get unpredictable results:
a- the compiler is not accessible
b- the complied code is rejected by the board and I get the non compiled javascript function
c- the compiled code seems to be non functionnal, this creates some random behaviour later.
d-the compiled code is apparently ok but the next javascript, uncompiled, function is ignored and not defined
e- the IDE complains at upload time that some parenthesis are not closed... Which is impossible because those compiled functions are unchanged from one upload to the other and the IDE doesn't show any warning at the beginnig of any line.

Of course it also happens to work correctly but this is about 1/4th of the uploads.
Commenting out "compiled" instructions does allow a correct execution of the code, just half the speed of compiled code.

The URL used for the compiler is "http://www.espruino.com:32766".
The IDE is v0.56.1 but this happened with v0.56.0 too

The example below is the most common one.

>reset();
=undefined
 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v80.323 Copyright 2015 G.Williams
>echo(0);
Uncaught SyntaxError: Got ID:JsVar expected ','
 at line 1 col 192
... ddmmyy = E.nativeCall(1, "JsVar(JsVar)", atob("LenwTwVGd0iP...

Or also with throtte send, for exactly the same source code: This is just the same result actually, the functions in trouble seems to be randomly "selected".

reset();
=undefined
 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v80.323 Copyright 2015 G.Williams
>echo(0);
Uncaught SyntaxError: Got ID:JsVar expected ','
 at line 1 col 534
...ar secn = E.nativeCall(1, "JsVar(JsVar)", atob("LenwT4NNjbAH...

Excerpt of the code in trouble


// ---- beg (modified) GPS module code

// convert latitudes and longitudes from nmea ascii coding to float

function lln(d1,d2,negs) {
  //"compiled";
  var dfp=d1.indexOf(".")-2;
  var v=(parseInt(d1.substr(0,dfp),10)+parseFloat(d1.substr(dfp))/60);
  if (d2==negs) {
    return (0-v);
  } else { return v; }
}

function secn(d) {
  //"compiled";
  return (parseInt(d.substr(0,2),10)*3600+parseInt(d.substr(2,2),10)*60+parseFloat(d.substr(4,5)));
} // hhmmss.ss

function ddmmyy(d) {
  //"compiled";
  return Date.parse('20'+d.substr(4,2)+"-"+d.substr(2,2)+'-'+d.substr(0,2));
}

function cks7(m) { 
  //"compiled"; 
  var ck = 0;
  var l = 0|m.length; // ensure we don't have to check the length each time
  var c = m.charCodeAt.bind(m); // ensure we don't have to look up 'charCodeAt' each time
  for (var i=0;i<l;i++) ck ^= c(i);
  return ck;
}


function checksum(msg) {
  var cks = 0;
  new Uint8Array(E.toArrayBuffer(msg)).forEach(function (c) { cks^=c; }); 
  return cks;
}

// compute the checksum for NMEA sentences and splits it from ','
function nmea_checksum(s) {
  try {
    var n=s.split('$').pop(); // remove leading uncomplete sentences AND the no more usefull leading $
    n=n.split('*'); // separate checksum from line
    var cksum = parseInt(n.pop(),16); // make checksum a number and remove it from n
    n=n.pop(); // keep content alone
    if (cksum===cks7(n)) // mean leap 0.02532994300 s
      return n.split(',');  // mean leap 0.01426320198 s
    else {
      throw "different checksums "+cksum.toString(16)+" versus "+cks7(n).toString(16)+" in line "+s ;
    }
  } catch(x) {
    throw "Checksum error "+x+' in sentence '+s; 
  }
}

empty first part of `for` loop gives Cannot read property 'type' of null

"compiled" JS code
for (; i < 16; i++) gives

TypeError: Cannot read property 'type' of null
    at handle (/home/fanoush/EspruinoCompiler/src/compile.js:277:12)
    at Object.ForStatement (/home/fanoush/EspruinoCompiler/src/compile.js:259:22)
    at handle (/home/fanoush/EspruinoCompiler/src/compile.js:278:35)
    at /home/fanoush/EspruinoCompiler/src/compile.js:406:9
    at Array.forEach (<anonymous>)
    at Object.exports.jsToC (/home/fanoush/EspruinoCompiler/src/compile.js:404:18)
    at exports.compileFunction (/home/fanoush/EspruinoCompiler/src/compile.js:533:26)
    at compile_js (/home/fanoush/EspruinoCompiler/server.js:18:5)
    at handlePost (/home/fanoush/EspruinoCompiler/server.js:59:7)
    at IncomingMessage.<anonymous> (/home/fanoush/EspruinoCompiler/server.js:110:7)
===============================================

because of node

 "init": null,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.