Fix issues with more than 64 locals, see #99

This commit is contained in:
dcodeIO 2018-05-08 22:16:12 +02:00
parent 2a7f40953a
commit 1f3bb61fae
9 changed files with 1451 additions and 18 deletions

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2008,8 +2008,10 @@ export class Compiler extends DiagnosticEmitter {
}
if (initExpr) {
initializers.push(this.compileAssignmentWithValue(declaration.name, initExpr));
flow.setLocalWrapped(local.index, !flow.canOverflow(initExpr, type));
} else {
if (local.type.is(TypeFlags.SHORT | TypeFlags.INTEGER)) {
flow.setLocalWrapped(local.index, !flow.canOverflow(initExpr, type));
}
} else if (local.type.is(TypeFlags.SHORT | TypeFlags.INTEGER)) {
flow.setLocalWrapped(local.index, true); // zero
}
}
@ -4418,7 +4420,9 @@ export class Compiler extends DiagnosticEmitter {
return module.createUnreachable();
}
let flow = this.currentFunction.flow;
flow.setLocalWrapped((<Local>target).index, !flow.canOverflow(valueWithCorrectType, type));
if (type.is(TypeFlags.SHORT | TypeFlags.INTEGER)) {
flow.setLocalWrapped((<Local>target).index, !flow.canOverflow(valueWithCorrectType, type));
}
return tee
? module.createTeeLocal((<Local>target).index, valueWithCorrectType)
: module.createSetLocal((<Local>target).index, valueWithCorrectType);

View File

@ -2898,7 +2898,7 @@ export class Function extends Element {
private tempF64s: Local[] | null = null;
/** Gets a free temporary local of the specified type. */
getTempLocal(type: Type, wrapped: bool): Local {
getTempLocal(type: Type, wrapped: bool = false): Local {
var temps: Local[] | null;
switch (type.toNativeType()) {
case NativeType.I32: {
@ -2926,7 +2926,9 @@ export class Function extends Element {
} else {
local = this.addLocal(type);
}
this.flow.setLocalWrapped(local.index, wrapped);
if (type.is(TypeFlags.SHORT | TypeFlags.INTEGER)) {
this.flow.setLocalWrapped(local.index, wrapped);
}
return local;
}
@ -2989,7 +2991,9 @@ export class Function extends Element {
local = this.addLocal(type);
temps.push(local);
}
this.flow.setLocalWrapped(local.index, wrapped);
if (type.is(TypeFlags.SHORT | TypeFlags.INTEGER)) {
this.flow.setLocalWrapped(local.index, wrapped);
}
return local;
}
@ -3701,7 +3705,9 @@ export class Flow {
}
}
this.scopedLocals.set(name, scopedLocal);
this.setLocalWrapped(scopedLocal.index, wrapped);
if (type.is(TypeFlags.SHORT | TypeFlags.INTEGER)) {
this.setLocalWrapped(scopedLocal.index, wrapped);
}
return scopedLocal;
}
@ -3775,17 +3781,20 @@ export class Flow {
/** Sets if the local with the specified index is considered wrapped. */
setLocalWrapped(index: i32, wrapped: bool): void {
var map: I64;
var i: i32 = -1;
var off: i32 = -1;
if (index < 64) {
if (index < 0) return; // inlined constant
map = this.wrappedLocals;
} else {
let ext = this.wrappedLocalsExt;
i = ((index - 64) / 64) | 0;
if (!ext) ext = new Array(i + 1);
else while (ext.length <= i) ext.push(i64_new(0));
map = ext[i];
index -= (i + 1) * 64;
off = ((index - 64) / 64) | 0;
if (!ext) {
this.wrappedLocalsExt = ext = new Array(off + 1);
ext.length = 0;
}
while (ext.length <= off) ext.push(i64_new(0));
map = ext[off];
index -= (off + 1) * 64;
}
map = wrapped
? i64_or(
@ -3804,7 +3813,7 @@ export class Flow {
)
)
);
if (i >= 0) (<I64[]>this.wrappedLocalsExt)[i] = map;
if (off >= 0) (<I64[]>this.wrappedLocalsExt)[off] = map;
else this.wrappedLocals = map;
}

View File

@ -0,0 +1,60 @@
(module
(type $ii (func (param i32) (result i32)))
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 4) "\0e\00\00\00m\00a\00n\00y\00-\00l\00o\00c\00a\00l\00s\00.\00t\00s")
(export "testI32" (func $many-locals/testI32))
(export "testI8" (func $many-locals/testI8))
(export "memory" (memory $0))
(start $start)
(func $many-locals/testI32 (; 1 ;) (type $ii) (param $0 i32) (result i32)
(get_local $0)
)
(func $many-locals/testI8 (; 2 ;) (type $ii) (param $0 i32) (result i32)
(i32.shr_s
(i32.shl
(get_local $0)
(i32.const 24)
)
(i32.const 24)
)
)
(func $start (; 3 ;) (type $v)
(if
(i32.ne
(call $many-locals/testI32
(i32.const 42)
)
(i32.const 42)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 133)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.ne
(call $many-locals/testI8
(i32.const 42)
)
(i32.const 42)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 267)
(i32.const 0)
)
(unreachable)
)
)
)
)

View File

@ -0,0 +1,267 @@
export function testI32(a: i32): i32 { // does not have to remember wrap states
var a00 = a;
var a01 = a00;
var a02 = a01;
var a03 = a02;
var a04 = a03;
var a05 = a04;
var a06 = a05;
var a07 = a06;
var a08 = a07;
var a09 = a08;
var a0A = a09;
var a0B = a0A;
var a0C = a0B;
var a0D = a0C;
var a0E = a0D;
var a0F = a0E;
var a10 = a0F;
var a11 = a10;
var a12 = a11;
var a13 = a12;
var a14 = a13;
var a15 = a14;
var a16 = a15;
var a17 = a16;
var a18 = a17;
var a19 = a18;
var a1A = a19;
var a1B = a1A;
var a1C = a1B;
var a1D = a1C;
var a1E = a1D;
var a1F = a1E;
var a20 = a1F;
var a21 = a20;
var a22 = a21;
var a23 = a22;
var a24 = a23;
var a25 = a24;
var a26 = a25;
var a27 = a26;
var a28 = a27;
var a29 = a28;
var a2A = a29;
var a2B = a2A;
var a2C = a2B;
var a2D = a2C;
var a2E = a2D;
var a2F = a2E;
var a30 = a2F;
var a31 = a30;
var a32 = a31;
var a33 = a32;
var a34 = a33;
var a35 = a34;
var a36 = a35;
var a37 = a36;
var a38 = a37;
var a39 = a38;
var a3A = a39;
var a3B = a3A;
var a3C = a3B;
var a3D = a3C;
var a3E = a3D;
var a3F = a3E;
var a40 = a3F;
var a41 = a40;
var a42 = a41;
var a43 = a42;
var a44 = a43;
var a45 = a44;
var a46 = a45;
var a47 = a46;
var a48 = a47;
var a49 = a48;
var a4A = a49;
var a4B = a4A;
var a4C = a4B;
var a4D = a4C;
var a4E = a4D;
var a4F = a4E;
var a50 = a4F;
var a51 = a50;
var a52 = a51;
var a53 = a52;
var a54 = a53;
var a55 = a54;
var a56 = a55;
var a57 = a56;
var a58 = a57;
var a59 = a58;
var a5A = a59;
var a5B = a5A;
var a5C = a5B;
var a5D = a5C;
var a5E = a5D;
var a5F = a5E;
var a60 = a5F;
var a61 = a60;
var a62 = a61;
var a63 = a62;
var a64 = a63;
var a65 = a64;
var a66 = a65;
var a67 = a66;
var a68 = a67;
var a69 = a68;
var a6A = a69;
var a6B = a6A;
var a6C = a6B;
var a6D = a6C;
var a6E = a6D;
var a6F = a6E;
var a70 = a6F;
var a71 = a70;
var a72 = a71;
var a73 = a72;
var a74 = a73;
var a75 = a74;
var a76 = a75;
var a77 = a76;
var a78 = a77;
var a79 = a78;
var a7A = a79;
var a7B = a7A;
var a7C = a7B;
var a7D = a7C;
var a7E = a7D;
var a7F = a7E;
return a7F;
}
assert(testI32(42) == 42);
export function testI8(a: i8): i8 { // has to remember wrap states
var a00 = a;
var a01 = a00;
var a02 = a01;
var a03 = a02;
var a04 = a03;
var a05 = a04;
var a06 = a05;
var a07 = a06;
var a08 = a07;
var a09 = a08;
var a0A = a09;
var a0B = a0A;
var a0C = a0B;
var a0D = a0C;
var a0E = a0D;
var a0F = a0E;
var a10 = a0F;
var a11 = a10;
var a12 = a11;
var a13 = a12;
var a14 = a13;
var a15 = a14;
var a16 = a15;
var a17 = a16;
var a18 = a17;
var a19 = a18;
var a1A = a19;
var a1B = a1A;
var a1C = a1B;
var a1D = a1C;
var a1E = a1D;
var a1F = a1E;
var a20 = a1F;
var a21 = a20;
var a22 = a21;
var a23 = a22;
var a24 = a23;
var a25 = a24;
var a26 = a25;
var a27 = a26;
var a28 = a27;
var a29 = a28;
var a2A = a29;
var a2B = a2A;
var a2C = a2B;
var a2D = a2C;
var a2E = a2D;
var a2F = a2E;
var a30 = a2F;
var a31 = a30;
var a32 = a31;
var a33 = a32;
var a34 = a33;
var a35 = a34;
var a36 = a35;
var a37 = a36;
var a38 = a37;
var a39 = a38;
var a3A = a39;
var a3B = a3A;
var a3C = a3B;
var a3D = a3C;
var a3E = a3D;
var a3F = a3E;
var a40 = a3F;
var a41 = a40;
var a42 = a41;
var a43 = a42;
var a44 = a43;
var a45 = a44;
var a46 = a45;
var a47 = a46;
var a48 = a47;
var a49 = a48;
var a4A = a49;
var a4B = a4A;
var a4C = a4B;
var a4D = a4C;
var a4E = a4D;
var a4F = a4E;
var a50 = a4F;
var a51 = a50;
var a52 = a51;
var a53 = a52;
var a54 = a53;
var a55 = a54;
var a56 = a55;
var a57 = a56;
var a58 = a57;
var a59 = a58;
var a5A = a59;
var a5B = a5A;
var a5C = a5B;
var a5D = a5C;
var a5E = a5D;
var a5F = a5E;
var a60 = a5F;
var a61 = a60;
var a62 = a61;
var a63 = a62;
var a64 = a63;
var a65 = a64;
var a66 = a65;
var a67 = a66;
var a68 = a67;
var a69 = a68;
var a6A = a69;
var a6B = a6A;
var a6C = a6B;
var a6D = a6C;
var a6E = a6D;
var a6F = a6E;
var a70 = a6F;
var a71 = a70;
var a72 = a71;
var a73 = a72;
var a74 = a73;
var a75 = a74;
var a76 = a75;
var a77 = a76;
var a78 = a77;
var a79 = a78;
var a7A = a79;
var a7B = a7A;
var a7C = a7B;
var a7D = a7C;
var a7E = a7D;
var a7F = a7E;
return a7F;
}
assert(testI8(42) == 42);

File diff suppressed because it is too large Load Diff