1 /******************************************************************************
2 *
3 * Copyright (C) 2006, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: ge 18.10.06 0.0.A.
11 *
12 * Author: Alexey Krivonogov ( gentee )
13 *
14 * Summary:
15 *
16 ******************************************************************************/
17
18 #ifndef RUNTIME
19
20 #include "ge.h"
21 #include "../vm/vm.h"
22 #include "../vm/vmload.h"
23 #include "../bytecode/bytecode.h"
24 #include "../genteeapi/gentee.h"
25
26 puint optiused;
27
28 void STDCALL geopti_var( pvartype var )
29 {
30 ge_getused( var->type );
31
32 if ( var->flag & VAR_OFTYPE )
33 ge_getused( var->oftype );
34 }
35
36 void STDCALL geopti_varlist( pvartype pvar, uint count )
37 {
38 uint i;
39
40 for ( i = 0; i < count; i++ )
41 geopti_var( pvar++ );
42 }
43
44 void STDCALL ge_getused( uint id )
45 {
46 puint ptr, end;
47 povmbcode bcode;
48 povmtype ptype;
49 pvmobj pvmo;
50 uint cmd, i, k, count = 0;
51
52 if ( id < KERNEL_COUNT || optiused[ id ] )
53 return;
54 optiused[ id ] = 1;
55 pvmo = ( pvmobj )PCMD( id );
56
57 if ( pvmo->type == OVM_BYTECODE )
58 {
59 bcode = ( povmbcode )pvmo;
60 geopti_var( bcode->vmf.ret );
61 geopti_varlist( bcode->vmf.params, bcode->vmf.parcount );
62
63 for ( i = 0; i < bcode->setcount; i++ )
64 count += bcode->sets[i].count;
65 geopti_varlist( bcode->vars, count );
66
67 ptr = ( puint )bcode->vmf.func;
68 if ( !ptr )
69 return;
70
71 end = ( puint )( ( pubyte )ptr + bcode->bcsize );
72 while ( ptr < end )
73 {
74 cmd = *ptr++;
75 if ( cmd < CNop || cmd >= CNop + STACK_COUNT )
76 {
77 if ( cmd >= KERNEL_COUNT )
78 ge_getused( cmd );
79 continue;
80 }
81
82 switch ( cmd )
83 {
84 case CQwload:
85 ptr += 2;
86 break;
87 case CDwload:
88 ptr++;
89 break;
90 case CDwsload:
91 i = *ptr++;
92 for ( k = 0; k < i; k++ )
93 ge_getused( ptr[k] & 0xFFFFFF );
94 ptr += i;
95 break;
96 case CAsm:
97 i = *ptr++;
98 ptr += i;
99 break;
100 case CResload:
101 case CCmdload:
102 case CPtrglobal:
103 ge_getused( *ptr++ );
104 break;
105 case CDatasize:
106 i = *ptr++;
107 ptr += ( i >> 2 ) + ( i & 3 ? 1 : 0 );
108 break;
109 default:
110 switch ( shifts[ cmd - CNop ] )
111 {
112 case SH1_3:
113 case SH2_3:
114 ptr++;
115 case SHN1_2:
116 case SH0_2:
117 case SH1_2:
118 ptr++;
119 break;
120 }
121 }
122 }
123 }
124 if ( pvmo->type == OVM_EXFUNC )
125 {
126 geopti_var( (( povmfunc )pvmo)->vmf.ret );
127 geopti_varlist( (( povmfunc )pvmo)->vmf.params,
128 (( povmfunc )pvmo)->vmf.parcount );
129
130 if ( pvmo->flag & GHEX_IMPORT )
131 ge_getused( (( povmfunc )pvmo)->import );
132 }
133 if ( pvmo->type == OVM_TYPE )
134 {
135 ptype = ( povmtype )pvmo;
136
137 if ( pvmo->flag & GHTY_INHERIT )
138 ge_getused( ptype->inherit );
139
140 if ( pvmo->flag & GHTY_INDEX )
141 {
142 ge_getused( ptype->index.type );
143 ge_getused( ptype->index.oftype );
144 }
145 if ( pvmo->flag & GHTY_INITDEL )
146 {
147 ge_getused( ptype->ftype[ FTYPE_INIT ] );
148 ge_getused( ptype->ftype[ FTYPE_DELETE ] );
149 }
150 if ( pvmo->flag & GHTY_EXTFUNC )
151 {
152 ge_getused( ptype->ftype[ FTYPE_OFTYPE ] );
153 ge_getused( ptype->ftype[ FTYPE_COLLECTION ] );
154 }
155 if ( pvmo->flag & GHTY_ARRAY )
156 {
157 i = 0;
158 while ( ptype->ftype[ FTYPE_ARRAY + i ] )
159 i++;
160 ge_getused( i == 1 ? ptype->ftype[ FTYPE_ARRAY ] : i );
161 if ( i > 1 )
162 for ( k = 0; k < i; k++ )
163 ge_getused( ptype->ftype[ FTYPE_ARRAY + k ] );
164 }
165 geopti_varlist( ptype->children, ptype->count );
166 }
167 if ( pvmo->type == OVM_GLOBAL )
168 geopti_var( (( povmglobal )pvmo)->type );
169 }
170
171 void STDCALL ge_optimize( void )
172 {
173 uint i, count, main = 0;
174 pvmobj pvmo;
175 pubyte cur;
176
177 count = arr_count( &_vm.objtbl );
178 // Deletes ALIAS and DEFINE
179 for ( i = KERNEL_COUNT; i < count ; i++ )
180 {
181 pvmo = ( pvmobj )PCMD( i );
182 if ( pvmo->flag & GHRT_SKIP )
183 continue;
184 switch ( pvmo->type )
185 {
186 case OVM_DEFINE:
187 if ( _compile->popti->flag & OPTI_DEFINE )
188 pvmo->flag |= GHRT_SKIP;
189 break;
190 case OVM_ALIAS:
191 pvmo->flag |= GHRT_SKIP;
192 break;
193 }
194 }
195 if ( !( _compile->popti->flag & OPTI_AVOID ))
196 return;
197 optiused = mem_allocz( count * sizeof( uint ));
198 for ( i = KERNEL_COUNT; i < count; i++ )
199 {
200 pvmo = ( pvmobj )PCMD( i );
201
202 if ( pvmo->name )
203 {
204 cur = _compile->popti->avoidon;
205 while ( *cur )
206 {
207 if ( ptr_wildcardignore( pvmo->name, cur ))
208 {
209 ge_getused( i );
210 break;
211 }
212 cur += mem_len( cur ) + 1;
213 }
214 }
215
216 if ( pvmo->type == OVM_BYTECODE || pvmo->type == OVM_EXFUNC )
217 if ( pvmo->flag & GHBC_ENTRY )
218 ge_getused( i );
219 else
220 if ( pvmo->flag & GHBC_MAIN )
221 if ( _compile->popti->flag & OPTI_MAIN )
222 main = i;
223 else
224 ge_getused( i );
225 }
226 if ( main )
227 ge_getused( main );
228
229 for ( i = KERNEL_COUNT; i < count ; i++ )
230 {
231 pvmo = ( pvmobj )PCMD( i );
232 if ( !optiused[ i ] )
233 pvmo->flag |= GHRT_SKIP;
234 }
235
236 mem_free( optiused );
237 }
238
239 #endif