8
8
#include <stdbool.h>
9
9
#include <stdint.h>
10
10
#include <stdio.h>
11
+ #include <stdlib.h>
11
12
#include <string.h>
12
13
13
14
struct Block {
14
15
uint32_t type ;
15
16
uint32_t label ;
16
17
uint32_t stack_i ;
18
+ uint32_t reuse_i ;
17
19
};
18
20
19
21
struct FuncGen {
20
22
int8_t * type ;
23
+ uint32_t * reuse ;
21
24
uint32_t * stack ;
22
25
struct Block * block ;
23
26
uint32_t type_i ;
27
+ uint32_t reuse_i ;
24
28
uint32_t stack_i ;
25
29
uint32_t block_i ;
26
30
uint32_t type_len ;
31
+ uint32_t reuse_len ;
27
32
uint32_t stack_len ;
28
33
uint32_t block_len ;
29
34
};
@@ -34,13 +39,15 @@ static void FuncGen_init(struct FuncGen *self) {
34
39
35
40
static void FuncGen_reset (struct FuncGen * self ) {
36
41
self -> type_i = 0 ;
42
+ self -> reuse_i = 0 ;
37
43
self -> stack_i = 0 ;
38
44
self -> block_i = 0 ;
39
45
}
40
46
41
47
static void FuncGen_free (struct FuncGen * self ) {
42
48
free (self -> block );
43
49
free (self -> stack );
50
+ free (self -> reuse );
44
51
free (self -> type );
45
52
}
46
53
@@ -65,20 +72,41 @@ static uint32_t FuncGen_localAlloc(struct FuncGen *self, int8_t type) {
65
72
self -> type = realloc (self -> type , sizeof (int8_t ) * self -> type_len );
66
73
if (self -> type == NULL ) panic ("out of memory" );
67
74
}
68
- uint32_t local_i = self -> type_i ;
69
- self -> type [local_i ] = type ;
75
+ uint32_t local_idx = self -> type_i ;
76
+ self -> type [local_idx ] = type ;
70
77
self -> type_i += 1 ;
71
- return local_i ;
78
+ return local_idx ;
79
+ }
80
+
81
+ static enum WasmValType FuncGen_localType (const struct FuncGen * self , uint32_t local_idx ) {
82
+ return self -> type [local_idx ];
72
83
}
73
84
74
85
static uint32_t FuncGen_localDeclare (struct FuncGen * self , FILE * out , enum WasmValType val_type ) {
75
- uint32_t local_i = FuncGen_localAlloc (self , (int8_t )val_type );
76
- fprintf (out , "%s l%" PRIu32 , WasmValType_toC (val_type ), local_i );
77
- return local_i ;
86
+ uint32_t local_idx = FuncGen_localAlloc (self , (int8_t )val_type );
87
+ fprintf (out , "%s l%" PRIu32 , WasmValType_toC (val_type ), local_idx );
88
+ return local_idx ;
78
89
}
79
90
80
- static enum WasmValType FuncGen_localType (const struct FuncGen * self , uint32_t local_idx ) {
81
- return self -> type [local_idx ];
91
+ static uint32_t FuncGen_reuseTop (const struct FuncGen * self ) {
92
+ return self -> block_i > 0 ? self -> block [self -> block_i - 1 ].reuse_i : 0 ;
93
+ }
94
+
95
+ static void FuncGen_reuseReset (struct FuncGen * self ) {
96
+ self -> reuse_i = FuncGen_reuseTop (self );
97
+ }
98
+
99
+ static uint32_t FuncGen_reuseLocal (struct FuncGen * self , FILE * out , enum WasmValType val_type ) {
100
+ for (uint32_t i = FuncGen_reuseTop (self ); i < self -> reuse_i ; i += 1 ) {
101
+ uint32_t local_idx = self -> reuse [i ];
102
+ if (FuncGen_localType (self , local_idx ) == val_type ) {
103
+ self -> reuse_i -= 1 ;
104
+ self -> reuse [i ] = self -> reuse [self -> reuse_i ];
105
+ fprintf (out , "l%" PRIu32 , local_idx );
106
+ return local_idx ;
107
+ }
108
+ }
109
+ return FuncGen_localDeclare (self , out , val_type );
82
110
}
83
111
84
112
static void FuncGen_stackPush (struct FuncGen * self , FILE * out , enum WasmValType val_type ) {
@@ -89,8 +117,7 @@ static void FuncGen_stackPush(struct FuncGen *self, FILE *out, enum WasmValType
89
117
if (self -> stack == NULL ) panic ("out of memory" );
90
118
}
91
119
FuncGen_indent (self , out );
92
- fputs ("const " , out );
93
- self -> stack [self -> stack_i ] = FuncGen_localDeclare (self , out , val_type );
120
+ self -> stack [self -> stack_i ] = FuncGen_reuseLocal (self , out , val_type );
94
121
self -> stack_i += 1 ;
95
122
fputs (" = " , out );
96
123
}
@@ -100,8 +127,17 @@ static uint32_t FuncGen_stackAt(const struct FuncGen *self, uint32_t stack_idx)
100
127
}
101
128
102
129
static uint32_t FuncGen_stackPop (struct FuncGen * self ) {
130
+ if (self -> reuse_i == self -> reuse_len ) {
131
+ self -> reuse_len += 10 ;
132
+ self -> reuse_len *= 2 ;
133
+ self -> reuse = realloc (self -> reuse , sizeof (uint32_t ) * self -> reuse_len );
134
+ if (self -> reuse == NULL ) panic ("out of memory" );
135
+ }
103
136
self -> stack_i -= 1 ;
104
- return self -> stack [self -> stack_i ];
137
+ uint32_t local_idx = self -> stack [self -> stack_i ];
138
+ self -> reuse [self -> reuse_i ] = local_idx ;
139
+ self -> reuse_i += 1 ;
140
+ return local_idx ;
105
141
}
106
142
107
143
static void FuncGen_label (struct FuncGen * self , FILE * out , uint32_t label ) {
@@ -118,7 +154,6 @@ static void FuncGen_blockBegin(struct FuncGen *self, FILE *out, enum WasmOpcode
118
154
self -> block = realloc (self -> block , sizeof (struct Block ) * self -> block_len );
119
155
if (self -> block == NULL ) panic ("out of memory" );
120
156
}
121
- uint32_t label = FuncGen_localAlloc (self , type < 0 ? ~(int8_t )kind : (int8_t )kind );
122
157
123
158
if (kind == WasmOpcode_if ) {
124
159
FuncGen_indent (self , out );
@@ -128,11 +163,24 @@ static void FuncGen_blockBegin(struct FuncGen *self, FILE *out, enum WasmOpcode
128
163
fputs ("{\n" , out );
129
164
}
130
165
166
+ uint32_t label = FuncGen_localAlloc (self , type < 0 ? ~(int8_t )kind : (int8_t )kind );
131
167
self -> block [self -> block_i ].type = type < 0 ? ~type : type ;
132
168
self -> block [self -> block_i ].label = label ;
133
169
self -> block [self -> block_i ].stack_i = self -> stack_i ;
170
+ self -> block [self -> block_i ].reuse_i = self -> reuse_i ;
134
171
self -> block_i += 1 ;
135
172
if (kind == WasmOpcode_loop ) FuncGen_label (self , out , label );
173
+
174
+ uint32_t reuse_top = FuncGen_reuseTop (self );
175
+ uint32_t reuse_n = self -> reuse_i - reuse_top ;
176
+ if (reuse_n > self -> reuse_len - self -> reuse_i ) {
177
+ self -> reuse_len += 10 ;
178
+ self -> reuse_len *= 2 ;
179
+ self -> reuse = realloc (self -> reuse , sizeof (uint32_t ) * self -> reuse_len );
180
+ if (self -> reuse == NULL ) panic ("out of memory" );
181
+ }
182
+ memcpy (& self -> reuse [self -> reuse_i ], & self -> reuse [reuse_top ], sizeof (uint32_t ) * reuse_n );
183
+ self -> reuse_i += reuse_n ;
136
184
}
137
185
138
186
static enum WasmOpcode FuncGen_blockKind (const struct FuncGen * self , uint32_t label_idx ) {
@@ -165,6 +213,8 @@ static void FuncGen_blockEnd(struct FuncGen *self, FILE *out) {
165
213
fprintf (out , "// stack mismatch %u != %u\n" , self -> stack_i , self -> block [self -> block_i ].stack_i );
166
214
}
167
215
self -> stack_i = self -> block [self -> block_i ].stack_i ;
216
+
217
+ self -> reuse_i = self -> block [self -> block_i ].reuse_i ;
168
218
}
169
219
170
220
static bool FuncGen_done (const struct FuncGen * self ) {
0 commit comments