Skip to content

Commit da672e2

Browse files
committed
Add memcpy compiler test
1 parent bbb57ba commit da672e2

19 files changed

Lines changed: 4367 additions & 132 deletions

NOTICE

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,22 @@ Includes parts of TypeScript:
22

33
https://github.com/Microsoft/TypeScript
44

5+
Copyright (c) Microsoft Corporation. All rights reserved.
56
Apache License, Version 2.0
67
https://www.apache.org/licenses/LICENSE-2.0
78

89
Includes parts of Binaryen:
910

1011
https://github.com/WebAssembly/binaryen
1112

13+
Copyright 2015 WebAssembly Community Group participants
1214
Apache License, Version 2.0
1315
https://www.apache.org/licenses/LICENSE-2.0
16+
17+
Includes parts of musl:
18+
19+
http://www.musl-libc.org
20+
21+
Copyright © 2005-2014 Rich Felker, et al.
22+
MIT License
23+
https://opensource.org/licenses/MIT

src/program.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -929,8 +929,8 @@ export class Function extends Element {
929929
/** Contextual type arguments. */
930930
contextualTypeArguments: Map<string,Type> = new Map();
931931

932-
private breakMajor: i32 = 0;
933-
private breakMinor: i32 = 0;
932+
private nextBreakId: i32 = 0;
933+
private breakStack: i32[] | null = null;
934934

935935
/** Constructs a new concrete function. */
936936
constructor(prototype: FunctionPrototype, internalName: string, typeArguments: Type[], parameters: Parameter[], returnType: Type, instanceMethodOf: Class | null) {
@@ -974,17 +974,26 @@ export class Function extends Element {
974974

975975
/** Enters a(nother) break context. */
976976
enterBreakContext(): string {
977-
if (!this.breakMinor)
978-
this.breakMajor++;
979-
return this.breakContext = this.breakMajor.toString(10) + "." + (++this.breakMinor).toString(10);
977+
const id: i32 = this.nextBreakId++;
978+
if (!this.breakStack)
979+
this.breakStack = [ id ];
980+
else
981+
this.breakStack.push(id);
982+
return this.breakContext = id.toString(10);
980983
}
981984

982985
/** Leaves the current break context. */
983986
leaveBreakContext(): void {
984-
if (this.breakMinor < 1)
985-
throw new Error("unexpected unbalanced break context");
986-
if (--this.breakMinor == 0)
987+
assert(this.breakStack != null);
988+
const length: i32 = (<i32[]>this.breakStack).length;
989+
assert(length > 0);
990+
(<i32[]>this.breakStack).pop();
991+
if (length > 1) {
992+
this.breakContext = (<i32[]>this.breakStack)[length - 2].toString(10)
993+
} else {
987994
this.breakContext = null;
995+
this.breakStack = null;
996+
}
988997
}
989998
}
990999

std/impl/heap.ts

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,150 @@ class Heap {
3434
return (<usize>current_memory() << 16) - HEAP_START;
3535
}
3636

37+
static copy(dest: usize, src: usize, n: usize): usize {
38+
assert(dest >= HEAP_START);
39+
40+
// the following is based on musl's implementation of memcpy
41+
let dst: usize = dest;
42+
let w: u32, x: u32;
43+
44+
// copy 1 byte each until src is aligned to 4 bytes
45+
while (n != 0 && src % 4 != 0) {
46+
store<u8>(dst++, load<u8>(src++));
47+
n--;
48+
}
49+
50+
// if dst is aligned to 4 bytes as well, copy 4 bytes each
51+
if (dst % 4 == 0) {
52+
while (n >= 16) {
53+
store<u32>(dst , load<u32>(src ));
54+
store<u32>(dst + 4, load<u32>(src + 4));
55+
store<u32>(dst + 8, load<u32>(src + 8));
56+
store<u32>(dst + 12, load<u32>(src + 12));
57+
src += 16; dst += 16; n -= 16;
58+
}
59+
if (n & 8) {
60+
store<u32>(dst , load<u32>(src ));
61+
store<u32>(dst + 4, load<u32>(src + 4));
62+
dst += 8; src += 8;
63+
}
64+
if (n & 4) {
65+
store<u32>(dst, load<u32>(src));
66+
dst += 4; src += 4;
67+
}
68+
if (n & 2) { // drop to 2 bytes each
69+
store<u16>(dst, load<u16>(src));
70+
dst += 2; src += 2;
71+
}
72+
if (n & 1) { // drop to 1 byte
73+
store<u8>(dst++, load<u8>(src++));
74+
}
75+
return dest;
76+
}
77+
78+
// if dst is not aligned to 4 bytes, use alternating shifts to copy 4 bytes each
79+
// doing shifts if faster when copying enough bytes (here: 32 or more)
80+
if (n >= 32) {
81+
switch (dst % 4) {
82+
// known to be != 0
83+
case 1:
84+
w = load<u32>(src);
85+
store<u8>(dst++, load<u8>(src++));
86+
store<u8>(dst++, load<u8>(src++));
87+
store<u8>(dst++, load<u8>(src++));
88+
n -= 3;
89+
while (n >= 17) {
90+
x = load<u32>(src + 1);
91+
store<u32>(dst, w >> 24 | x << 8);
92+
w = load<u32>(src + 5);
93+
store<u32>(dst + 4, x >> 24 | w << 8);
94+
x = load<u32>(src + 9);
95+
store<u32>(dst + 8, w >> 24 | x << 8);
96+
w = load<u32>(src + 13);
97+
store<u32>(dst + 12, x >> 24 | w << 8);
98+
src += 16; dst += 16; n -= 16;
99+
}
100+
break;
101+
case 2:
102+
w = load<u32>(src);
103+
store<u8>(dst++, load<u8>(src++));
104+
store<u8>(dst++, load<u8>(src++));
105+
n -= 2;
106+
while (n >= 18) {
107+
x = load<u32>(src + 2);
108+
store<u32>(dst, w >> 16 | x << 16);
109+
w = load<u32>(src + 6);
110+
store<u32>(dst + 4, x >> 16 | w << 16);
111+
x = load<u32>(src + 10);
112+
store<u32>(dst + 8, w >> 16 | x << 16);
113+
w = load<u32>(src + 14);
114+
store<u32>(dst + 12, x >> 16 | w << 16);
115+
src += 16; dst += 16; n -= 16;
116+
}
117+
break;
118+
case 3:
119+
w = load<u32>(src);
120+
store<u8>(dst++, load<u8>(src++));
121+
n -= 1;
122+
while (n >= 19) {
123+
x = load<u32>(src + 3);
124+
store<u32>(dst, w >> 8 | x << 24);
125+
w = load<u32>(src + 7);
126+
store<u32>(dst + 4, x >> 8 | w << 24);
127+
x = load<u32>(src + 11);
128+
store<u32>(dst + 8, w >> 8 | x << 24);
129+
w = load<u32>(src + 15);
130+
store<u32>(dst + 12, x >> 8 | w << 24);
131+
src += 16; dst += 16; n -= 16;
132+
}
133+
break;
134+
}
135+
}
136+
137+
// copy remaining bytes one by one
138+
if (n & 16) {
139+
store<u8>(dst++, load<u8>(src++));
140+
store<u8>(dst++, load<u8>(src++));
141+
store<u8>(dst++, load<u8>(src++));
142+
store<u8>(dst++, load<u8>(src++));
143+
store<u8>(dst++, load<u8>(src++));
144+
store<u8>(dst++, load<u8>(src++));
145+
store<u8>(dst++, load<u8>(src++));
146+
store<u8>(dst++, load<u8>(src++));
147+
store<u8>(dst++, load<u8>(src++));
148+
store<u8>(dst++, load<u8>(src++));
149+
store<u8>(dst++, load<u8>(src++));
150+
store<u8>(dst++, load<u8>(src++));
151+
store<u8>(dst++, load<u8>(src++));
152+
store<u8>(dst++, load<u8>(src++));
153+
store<u8>(dst++, load<u8>(src++));
154+
store<u8>(dst++, load<u8>(src++));
155+
}
156+
if (n & 8) {
157+
store<u8>(dst++, load<u8>(src++));
158+
store<u8>(dst++, load<u8>(src++));
159+
store<u8>(dst++, load<u8>(src++));
160+
store<u8>(dst++, load<u8>(src++));
161+
store<u8>(dst++, load<u8>(src++));
162+
store<u8>(dst++, load<u8>(src++));
163+
store<u8>(dst++, load<u8>(src++));
164+
store<u8>(dst++, load<u8>(src++));
165+
}
166+
if (n & 4) {
167+
store<u8>(dst++, load<u8>(src++));
168+
store<u8>(dst++, load<u8>(src++));
169+
store<u8>(dst++, load<u8>(src++));
170+
store<u8>(dst++, load<u8>(src++));
171+
}
172+
if (n & 2) {
173+
store<u8>(dst++, load<u8>(src++));
174+
store<u8>(dst++, load<u8>(src++));
175+
}
176+
if (n & 1) {
177+
store<u8>(dst++, load<u8>(src++));
178+
}
179+
return dest;
180+
}
181+
37182
private constructor() {}
38183
}

tests/compiler/do.optimized.wast

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
(export "loopDoInDo" (func $do/loopDoInDo))
66
(export "memory" (memory $0))
77
(func $do/loopDo (; 0 ;) (type $iv) (param $0 i32)
8-
(loop $continue|1.1
9-
(br_if $continue|1.1
8+
(loop $continue|0
9+
(br_if $continue|0
1010
(tee_local $0
1111
(i32.sub
1212
(get_local $0)
@@ -17,15 +17,15 @@
1717
)
1818
)
1919
(func $do/loopDoInDo (; 1 ;) (type $iv) (param $0 i32)
20-
(loop $continue|1.1
20+
(loop $continue|0
2121
(set_local $0
2222
(i32.sub
2323
(get_local $0)
2424
(i32.const 1)
2525
)
2626
)
27-
(loop $continue|1.2
28-
(br_if $continue|1.2
27+
(loop $continue|1
28+
(br_if $continue|1
2929
(tee_local $0
3030
(i32.sub
3131
(get_local $0)
@@ -34,7 +34,7 @@
3434
)
3535
)
3636
)
37-
(br_if $continue|1.1
37+
(br_if $continue|0
3838
(get_local $0)
3939
)
4040
)

tests/compiler/do.wast

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,45 @@
66
(export "loopDoInDo" (func $do/loopDoInDo))
77
(export "memory" (memory $0))
88
(func $do/loopDo (; 0 ;) (type $iv) (param $0 i32)
9-
(block $break|1.1
10-
(loop $continue|1.1
9+
(block $break|0
10+
(loop $continue|0
1111
(set_local $0
1212
(i32.sub
1313
(get_local $0)
1414
(i32.const 1)
1515
)
1616
)
17-
(br_if $continue|1.1
17+
(br_if $continue|0
1818
(get_local $0)
1919
)
2020
)
2121
)
2222
)
2323
(func $do/loopDoInDo (; 1 ;) (type $iv) (param $0 i32)
24-
(block $break|1.1
25-
(loop $continue|1.1
24+
(block $break|0
25+
(loop $continue|0
2626
(block
2727
(set_local $0
2828
(i32.sub
2929
(get_local $0)
3030
(i32.const 1)
3131
)
3232
)
33-
(block $break|1.2
34-
(loop $continue|1.2
33+
(block $break|1
34+
(loop $continue|1
3535
(set_local $0
3636
(i32.sub
3737
(get_local $0)
3838
(i32.const 1)
3939
)
4040
)
41-
(br_if $continue|1.2
41+
(br_if $continue|1
4242
(get_local $0)
4343
)
4444
)
4545
)
4646
)
47-
(br_if $continue|1.1
47+
(br_if $continue|0
4848
(get_local $0)
4949
)
5050
)

tests/compiler/for.optimized.wast

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
(set_global $for/i
1010
(i32.const 0)
1111
)
12-
(loop $continue|1.1
12+
(loop $continue|0
1313
(if
1414
(i32.lt_s
1515
(get_global $for/i)
@@ -22,7 +22,7 @@
2222
(i32.const 1)
2323
)
2424
)
25-
(br $continue|1.1)
25+
(br $continue|0)
2626
)
2727
)
2828
)
@@ -36,7 +36,7 @@
3636
(set_local $0
3737
(i32.const 0)
3838
)
39-
(loop $continue|2.1
39+
(loop $continue|1
4040
(if
4141
(i32.lt_s
4242
(get_local $0)
@@ -49,11 +49,11 @@
4949
(i32.const 1)
5050
)
5151
)
52-
(br $continue|2.1)
52+
(br $continue|1)
5353
)
5454
)
5555
)
56-
(loop $continue|3.1
56+
(loop $continue|2
5757
(if
5858
(i32.gt_s
5959
(get_global $for/i)
@@ -66,17 +66,17 @@
6666
(i32.const 1)
6767
)
6868
)
69-
(br $continue|3.1)
69+
(br $continue|2)
7070
)
7171
)
7272
)
7373
(if
7474
(get_global $for/i)
7575
(unreachable)
7676
)
77-
(block $break|4.1
78-
(loop $continue|4.1
79-
(br_if $break|4.1
77+
(block $break|3
78+
(loop $continue|3
79+
(br_if $break|3
8080
(i32.eq
8181
(get_global $for/i)
8282
(i32.const 10)
@@ -88,17 +88,17 @@
8888
(i32.const 1)
8989
)
9090
)
91-
(br $continue|4.1)
91+
(br $continue|3)
9292
)
9393
)
94-
(loop $continue|5.1
94+
(loop $continue|4
9595
(set_global $for/i
9696
(i32.sub
9797
(get_global $for/i)
9898
(i32.const 1)
9999
)
100100
)
101-
(br_if $continue|5.1
101+
(br_if $continue|4
102102
(get_global $for/i)
103103
)
104104
)

0 commit comments

Comments
 (0)