source: dev/trunk/ab5.0/abdev/compiler_x86/Compile_Object.cpp@ 750

Last change on this file since 750 was 750, checked in by イグトランス (egtra), 16 years ago

BOOST_FOREACHを可能なものはVC++ 2005 for eachへ置換(やや速くなる)。

File size: 9.9 KB
Line 
1#include "stdafx.h"
2
3#include <Compiler.h>
4
5#include "../BasicCompiler_Common/common.h"
6#include "opcode.h"
7
8void _call_constructor( const CClass *pobj_c, const char *CreateParameter,int ObjectSize,BOOL bSomeObjects){
9 ////////////////////////////
10 // コンストラクタの呼び出し
11 ////////////////////////////
12
13 //この関数を使用する場合は、
14 //・ebxにオブジェクトの個数
15 //・eaxに先頭ポインタ
16 //をセットしておかなければならない
17
18
19/* //jnzのジャンプ先番地
20 extern int obp;
21 int jnz_back = obp;*/
22
23 if(bSomeObjects){
24 compiler.errorMessenger.OutputFatalError();
25
26 //push ebx
27 //compiler.codeGenerator.op_push(REG_EBX);
28 }
29
30 // ※ここでプッシュされた値はコンストラクタのthisポインタとなる
31 //push eax
32 compiler.codeGenerator.op_push(REG_EAX);
33
34
35
36 ////////////////////////
37 // オーバーロードを解決
38 ////////////////////////
39
40 std::vector<const UserProc *> subs;
41 pobj_c->GetDynamicMethods().Enum( pobj_c->GetName().c_str(), subs );
42
43 const UserProc *pUserProc;
44 if( subs.size() > 0 ){
45 //オーバーロードを解決
46 pUserProc=OverloadSolutionWithStrParam(pobj_c->GetName().c_str(),
47 subs,CreateParameter,"");
48
49 if(!pUserProc) return;
50 }
51
52 {
53 // 動的型情報をセットする
54 // obj._System_SetType( _System_TypeBase_Search( fullName ) )
55 subs.clear();
56 pobj_c->GetDynamicMethods().Enum( "_System_SetType", subs );
57 if( subs.size() == 1 ){
58 char temporary[VN_SIZE];
59 sprintf( temporary, "_System_TypeBase_Search(\"%s\"))", pobj_c->GetFullName().c_str() );
60
61 Opcode_CallProc(temporary,
62 subs[0],
63 PROCFLAG_NEW,"");
64 }
65 else{
66 compiler.errorMessenger.OutputFatalError();
67 }
68
69 // インターフェイスを初期化する
70 // TODO: 実装
71 }
72
73 //コンストラクタを呼び出す
74 Opcode_CallProc(CreateParameter,
75 pUserProc,
76 PROCFLAG_NEW | PROCFLAG_PERMIT_CONSTRUCTOR,"");
77
78
79
80 //pop eax
81 compiler.codeGenerator.op_pop(REG_EAX);
82
83 if(bSomeObjects){
84 /*
85 //pop ebx
86 compiler.codeGenerator.op_pop(REG_EBX);
87
88 //add eax,TypeSize
89 compiler.codeGenerator.op_add_RV( REG_EAX, ObjectSize );
90
91 //sub ebx,1
92 compiler.codeGenerator.op_sub_RV8(REG_EBX,1);
93
94 //jne ↑
95 compiler.codeGenerator.op_jne( jnz_back-obp, sizeof(long), false, true );
96 */
97 }
98}
99void Operator_New( const CClass &objClass, const char *objectSizeStr, const char *parameter, const Type &baseType )
100{
101 const CClass *pClass = &objClass;
102
103 if( pClass->IsInterface() )
104 {
105 pClass = compiler.GetObjectModule().meta.GetClasses().GetInterfaceInfoClassPtr();
106 }
107
108 int typeSize = pClass->GetSize();
109
110 if(pClass->IsAbstract())
111 {
112 std::string tempMessage;
113 foreach( const CMethod *pMethod, pClass->GetDynamicMethods() ){
114 if(pMethod->IsVirtual()){
115 if(pMethod->IsAbstract()){
116 if( !tempMessage.empty() )
117 {
118 tempMessage += ", ";
119 }
120 tempMessage += pMethod->GetUserProc().GetName();
121 }
122 }
123 }
124
125 // インターフェイスのvtbl
126 foreach( const ::Interface *pInterface, pClass->GetInterfaces() )
127 {
128 foreach( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
129 if(pMethod->IsVirtual()){
130 if(pMethod->IsAbstract()){
131 if( !tempMessage.empty() )
132 {
133 tempMessage += ", ";
134 }
135 tempMessage += pMethod->GetUserProc().GetName();
136 }
137 }
138 }
139 }
140
141 //抽象クラスだったとき
142 compiler.errorMessenger.Output(-1,"\"%s\" は抽象クラスです。インスタンス化することはできません(抽象メソッド … " + tempMessage + ")。",cp);
143 }
144
145 BOOL bSomeObjects=0;
146 if(objectSizeStr[0]){
147 bSomeObjects=1;
148
149 Type tempType;
150 NumOpe(objectSizeStr,Type(),tempType);
151 if( !tempType.IsWhole() ) compiler.errorMessenger.Output(49,NULL,cp);
152 ChangeTypeToLong(tempType.GetBasicType());
153
154 //pop eax
155 compiler.codeGenerator.op_pop(REG_EAX);
156
157 //※添え字上限値であることを考慮
158 //inc eax
159 compiler.codeGenerator.op_inc( REG_EAX );
160
161 //オブジェクトの個数をebxに一時保持
162 //※ebxは関数が呼ばれても不変
163 //mov ebx,eax
164 compiler.codeGenerator.op_mov_RR( REG_EBX, REG_EAX );
165
166 //imul eax,size
167 compiler.codeGenerator.op_imul_RV( REG_EAX, typeSize );
168
169 //add eax,OBJECT_HEAD_SIZE
170 compiler.codeGenerator.op_add_RV8( REG_EAX, (char)OBJECT_HEAD_SIZE );
171
172 //push eax
173 compiler.codeGenerator.op_push(REG_EAX);
174 }
175 else{
176 //オブジェクトの個数をebxに一時保持
177 //※ebxは関数が呼ばれても不変
178 //mov ebx,1
179 compiler.codeGenerator.op_mov_RV( REG_EBX, 1 );
180
181 //push size + OBJECT_HEAD_SIZE
182 compiler.codeGenerator.op_push_V( typeSize + OBJECT_HEAD_SIZE );
183 }
184
185 if( baseType.IsObject() ){
186 // オブジェクト インスタンス
187 // ※DeleteはGCで処理
188
189 //call _System_GC_malloc_ForObject
190 extern const UserProc *pSub_System_GC_malloc_ForObject;
191 compiler.codeGenerator.op_call(pSub_System_GC_malloc_ForObject);
192 }
193 else{
194 // オブジェクトポインタ
195 // ※明示的なDeleteが必要
196
197 //call _System_GC_malloc_ForObjectPtr
198 extern const UserProc *pSub_System_GC_malloc_ForObjectPtr;
199 compiler.codeGenerator.op_call(pSub_System_GC_malloc_ForObjectPtr);
200 }
201
202
203 /*
204 確保されたヒープ領域のポインタ(callocの戻り値eax)をpPtrとすると、
205 pPtr[0]=オブジェクトの個数
206 pPtr[1]=オブジェクトのサイズ
207 pPtr[2]=デストラクタの関数ポインタ
208 pPtr[3]=reserve
209 */
210
211
212 //mov dword ptr[eax],ebx(オブジェクトの個数)
213 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE );
214
215 //add eax,sizeof(long)
216 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
217
218 //mov ecx,TypeSize
219 compiler.codeGenerator.op_mov_RV( REG_ECX, typeSize );
220
221 //mov dword ptr[eax],ecx(オブジェクトのサイズ)
222 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE );
223
224 //add eax,sizeof(long)
225 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
226
227
228 const CMethod *method = pClass->GetDestructorMethod();
229 if( method == NULL ) return;
230
231 //mov ecx,DestructorProcAddr
232 compiler.codeGenerator.op_addressof( REG_ECX, &method->GetUserProc() );
233
234 //mov dword ptr[eax],ecx(デストラクタの関数ポインタ)
235 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE );
236
237 //add eax,sizeof(long)
238 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
239
240
241 // リザーブ領域
242 //add eax,sizeof(long)
243 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
244
245
246 //仮想関数テーブルを初期化
247 if( pClass->IsExistVirtualFunctions()
248 && !pClass->IsAbstract() )
249 {
250 // mov ecx,com_vtbl
251 compiler.codeGenerator.op_mov_RV_com_vtbl( REG_ECX, pClass );
252
253 //mov dword ptr[eax],ecx
254 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE );
255
256 // mov rcx,vtblAddress
257 compiler.codeGenerator.op_mov_RV_vtbl( REG_ECX, pClass );
258
259 //mov qword ptr[rax+sizeof(com_vtbl)],rcx
260 compiler.codeGenerator.op_mov_MR(sizeof(long),REG_ECX,REG_EAX,PTR_SIZE,MOD_BASE_DISP8);
261
262 // 仮想関数になるメソッドに使用チェックをつける
263 foreach( const CMethod *pMethod, pClass->GetDynamicMethods() )
264 {
265 if( pMethod->IsVirtual() )
266 {
267 pMethod->GetUserProc().Using();
268 }
269 }
270 foreach( const ::Interface *pInterface, pClass->GetInterfaces() )
271 {
272 foreach( const CMethod *pMethod, pInterface->GetDynamicMethods() )
273 {
274 if( pMethod->IsVirtual() )
275 {
276 pMethod->GetUserProc().Using();
277 }
278 }
279 }
280 }
281
282
283 // ※ここでプッシュされた値はNew演算子の戻り値となる
284 //push eax
285 compiler.codeGenerator.op_push(REG_EAX);
286
287
288 /////////////////////////////////////////////////////////////////////
289
290 ////////////////////////////
291 // コンストラクタの呼び出し
292 ////////////////////////////
293
294 _call_constructor(pClass,parameter,typeSize,bSomeObjects);
295}
296void OpcodeDelete(const char *Parameter, bool isSweeping){
297 Type tempType;
298 if( !NumOpe(Parameter,Type(),tempType) ){
299 return;
300 }
301 if(!( tempType.IsObjectPtr() || tempType.IsVoidPtr() )) compiler.errorMessenger.Output(122,NULL,cp);
302
303 //pop eax
304 compiler.codeGenerator.op_pop(REG_EAX);
305
306 //sub eax,sizeof(DWORD)*3
307 compiler.codeGenerator.op_sub_RV8( REG_EAX, OBJECT_HEAD_SIZE );
308
309 //push eax
310 compiler.codeGenerator.op_push(REG_EAX);
311
312
313 //mov ebx,dword ptr[eax](オブジェクトの個数)
314 compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE );
315
316 //add eax,sizeof(long)
317 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
318
319
320 //mov esi,dword ptr[eax](オブジェクトのサイズ)
321 compiler.codeGenerator.op_mov_RM( sizeof(long), REG_ESI, REG_EAX, 0, MOD_BASE );
322
323 //add eax,sizeof(long)
324 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
325
326
327 //mov edx,dword ptr[eax](デストラクタの関数ポインタ)
328 compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EDX, REG_EAX, 0, MOD_BASE );
329
330 //add eax,sizeof(long)
331 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
332
333
334 // リザーブ領域
335 //add eax,sizeof(long)
336 compiler.codeGenerator.op_add_RV8( REG_EAX, sizeof(long) );
337
338
339 //mov ecx,eax
340 compiler.codeGenerator.op_mov_RR( REG_ECX, REG_EAX );
341
342
343 //jnzの番地
344 /*extern int obp;
345 int jnz_back = obp;*/
346
347 //push ecx
348 compiler.codeGenerator.op_push(REG_ECX);
349
350 //push edx
351 compiler.codeGenerator.op_push(REG_EDX);
352
353 //push ecx(Thisポインタ ※隠れた第一パラメータ)
354 compiler.codeGenerator.op_push(REG_ECX);
355
356 //call edx
357 compiler.codeGenerator.op_call_R( REG_EDX );
358
359 //pop edx
360 compiler.codeGenerator.op_pop(REG_EDX);
361
362 //pop ecx
363 compiler.codeGenerator.op_pop(REG_ECX);
364
365 //add ecx,esi
366 compiler.codeGenerator.op_add_RR( REG_ECX, REG_ESI );
367
368 //sub ebx,1
369 compiler.codeGenerator.op_sub_RV8(REG_EBX,1);
370
371 //jne ↑
372 //compiler.codeGenerator.op_jne( jnz_back-obp, sizeof(long), false, true );
373
374
375 //////////////////////////////////////////
376 // オブジェクトメンバ変数用のメモリを解放
377 //////////////////////////////////////////
378
379 if( isSweeping ){
380 //call _System_GC_free_for_SweepingDelete
381 extern const UserProc *pSub_System_GC_free_for_SweepingDelete;
382 compiler.codeGenerator.op_call(pSub_System_GC_free_for_SweepingDelete);
383 }
384 else{
385 //call free
386 extern const UserProc *pSub_free;
387 compiler.codeGenerator.op_call(pSub_free);
388 }
389}
Note: See TracBrowser for help on using the repository browser.