source: dev/BasicCompiler32/Compile_Object.cpp@ 28

Last change on this file since 28 was 28, checked in by dai_9181, 17 years ago

・【32ビットコンパイラ】戻り値に実態オブジェクトを持つインデクサを呼び出すと強制終了してしまうバグを修正。
・仮想関数のオーバーロードが正常に動作しないバグを修正。
・純仮想関数(抽象メソッド)が仮想関数でオーバーロードされていると、クラスのインスタンスが生成できてしまうバグを修正。

File size: 7.4 KB
Line 
1#include "../BasicCompiler_Common/common.h"
2#include "opcode.h"
3
4void CallConstructor(CClass *pobj_c,char *CreateParameter,int ObjectSize,BOOL bSomeObjects){
5 ////////////////////////////
6 // コンストラクタの呼び出し
7 ////////////////////////////
8
9 //この関数を使用する場合は、
10 //・ebxにオブジェクトの個数
11 //・eaxに先頭ポインタ
12 //をセットしておかなければならない
13
14 int jnz_back;
15
16
17 //jnzの番地
18 jnz_back=obp;
19
20 //push ebx
21 op_push(REG_EBX);
22
23 // ※ここでプッシュされた値はコンストラクタのthisポインタとなる
24 //push eax
25 op_push(REG_EAX);
26
27
28
29 ////////////////////////
30 // オーバーロードを解決
31 ////////////////////////
32
33 SUBINFO **ppsi;
34 SUBINFO *psi;
35 int num;
36 ppsi=GetOverloadObjectSubHash(pobj_c->name,pobj_c,&num);
37 if(num){
38 //オーバーロードを解決
39 psi=OverloadSolutionWithStrParam(pobj_c->name,
40 ppsi,num,CreateParameter,"",NULL);
41 HeapDefaultFree(ppsi);
42
43 if(!psi) return;
44 }
45
46 //コンストラクタを呼び出す
47 Opcode_CallProc(CreateParameter,
48 psi,
49 0,
50 PROCFLAG_NEW,"",0);
51
52
53
54 //pop eax
55 op_pop(REG_EAX);
56
57 //pop ebx
58 op_pop(REG_EBX);
59
60 if(bSomeObjects){
61 //add eax,TypeSize
62 OpBuffer[obp++]=(char)0x05;
63 *((long *)(OpBuffer+obp))=ObjectSize;
64 obp+=sizeof(long);
65
66 //sub ebx,1
67 OpBuffer[obp++]=(char)0x83;
68 OpBuffer[obp++]=(char)0xEB;
69 OpBuffer[obp++]=(char)0x01;
70
71 //jnz ↑
72 OpBuffer[obp++]=(char)0x0F;
73 OpBuffer[obp++]=(char)0x85;
74 *((long *)(OpBuffer+obp))=jnz_back-(obp+sizeof(long));
75 obp+=sizeof(long);
76 }
77}
78int Operator_New(char *Parameter,LONG_PTR *plpIndex){
79 char TypeName[VN_SIZE],CreateParameter[VN_SIZE],ObjectSize[VN_SIZE];
80 int i,i2;
81
82 i=0;
83
84 if(Parameter[0]=='['){
85 i=GetStringInBracket(ObjectSize,Parameter);
86
87 SlideString(ObjectSize+1,-1);
88 ObjectSize[i-2]=0;
89 }
90 else ObjectSize[0]=0;
91
92 for(i2=0;;i++,i2++){
93 if(Parameter[i]=='('){
94 TypeName[i2]=0;
95
96 //コンストラクタに渡すパラメータを取得
97 i2=GetStringInPare(CreateParameter,Parameter+i);
98 RemoveStringPare(CreateParameter);
99 i+=i2;
100 if(Parameter[i]!='\0'){
101 SetError(42,NULL,cp);
102 return -1;
103 }
104 break;
105 }
106 TypeName[i2]=Parameter[i];
107 if(Parameter[i]=='\0'){
108 CreateParameter[0]=0;
109 break;
110 }
111 }
112
113 int type,TypeSize;
114 type=GetTypeFixed(TypeName,plpIndex);
115 if(type==-1){
116 SetError(3,TypeName,cp);
117 return -1;
118 }
119 TypeSize=GetTypeSize(type,*plpIndex);
120
121 if(type!=DEF_OBJECT){
122 ////////////////////////
123 // 通常のデータ型の場合
124 ////////////////////////
125
126 SetError(121,NULL,cp);
127 return -1;
128 }
129
130 CClass *pobj_c;
131 pobj_c=(CClass *)*plpIndex;
132
133 if(pobj_c->IsAbstract()){
134 //抽象クラスだったとき
135 SetError(125,pobj_c->name,cp);
136 }
137
138 if(ObjectSize[0]){
139 i2=NumOpe(ObjectSize,0,0,0);
140 ChangeTypeToLong(i2);
141
142 //pop eax
143 op_pop(REG_EAX);
144
145 //※添え字上限値であることを考慮
146 //add eax,1
147 OpBuffer[obp++]=(char)0x83;
148 OpBuffer[obp++]=(char)0xC0;
149 OpBuffer[obp++]=(char)0x01;
150
151 //オブジェクトの個数をebxに一時保持
152 //※ebxは関数が呼ばれても不変
153 //mov ebx,eax
154 OpBuffer[obp++]=(char)0x8B;
155 OpBuffer[obp++]=(char)0xD8;
156
157 //imul eax,size
158 OpBuffer[obp++]=(char)0x69;
159 OpBuffer[obp++]=(char)0xC0;
160 *((long *)(OpBuffer+obp))=TypeSize;
161 obp+=sizeof(long);
162
163 //add eax,sizeof(DWORD)*2
164 OpBuffer[obp++]=(char)0x05;
165 *((long *)(OpBuffer+obp))=sizeof(DWORD)*3;
166 obp+=sizeof(long);
167
168 //push eax
169 op_push(REG_EAX);
170 }
171 else{
172 //オブジェクトの個数をebxに一時保持
173 //※ebxは関数が呼ばれても不変
174 //mov ebx,1
175 OpBuffer[obp++]=(char)0xBB;
176 *((long *)(OpBuffer+obp))=1;
177 obp+=sizeof(long);
178
179 //push size
180 OpBuffer[obp++]=(char)0x68;
181 *((long *)(OpBuffer+obp))=TypeSize+sizeof(DWORD)*3;
182 obp+=sizeof(long);
183 }
184
185 //call calloc
186 extern SUBINFO *pSub_calloc;
187 op_call(pSub_calloc);
188
189
190 /*
191 確保されたヒープ領域のポインタ(callocの戻り値eax)をpPtrとすると、
192 pPtr-=sizeof(DWORD)*3
193 pPtr[0]=オブジェクトの個数
194 pPtr[1]=オブジェクトのサイズ
195 pPtr[2]=デストラクタの関数ポインタ
196 */
197
198
199 //mov dword ptr[eax],ebx(オブジェクトの個数)
200 OpBuffer[obp++]=(char)0x89;
201 OpBuffer[obp++]=(char)0x18;
202
203 //add eax,sizeof(DWORD)
204 OpBuffer[obp++]=(char)0x05;
205 *((long *)(OpBuffer+obp))=sizeof(DWORD);
206 obp+=sizeof(long);
207
208
209 //mov ecx,TypeSize
210 OpBuffer[obp++]=(char)0xB9;
211 *((long *)(OpBuffer+obp))=TypeSize;
212 obp+=sizeof(long);
213
214 //mov dword ptr[eax],ecx
215 OpBuffer[obp++]=(char)0x89;
216 OpBuffer[obp++]=(char)0x08;
217
218 //add eax,sizeof(DWORD)
219 OpBuffer[obp++]=(char)0x05;
220 *((long *)(OpBuffer+obp))=sizeof(DWORD);
221 obp+=sizeof(long);
222
223
224 //mov ecx,DestructorProcAddr
225 i2=pobj_c->DestructorMemberSubIndex;
226 if(i2==-1) return -1;
227 OpBuffer[obp++]=(char)0xB9;
228 pobj_SubAddrSchedule->add(pobj_c->ppobj_Method[i2]->psi,0);
229 pobj_c->ppobj_Method[i2]->psi->bUse=1;
230 obp+=sizeof(long);
231
232 //mov dword ptr[eax],ecx
233 OpBuffer[obp++]=(char)0x89;
234 OpBuffer[obp++]=(char)0x08;
235
236 //add eax,sizeof(DWORD)
237 OpBuffer[obp++]=(char)0x05;
238 *((long *)(OpBuffer+obp))=sizeof(DWORD);
239 obp+=sizeof(long);
240
241
242 // ※ここでプッシュされた値はNew演算子の戻り値となる
243 //push eax
244 op_push(REG_EAX);
245
246
247 /////////////////////////////////////////////////////////////////////
248
249 ////////////////////////////
250 // コンストラクタの呼び出し
251 ////////////////////////////
252
253 BOOL bSomeObjects;
254 if(ObjectSize[0]) bSomeObjects=1;
255 else bSomeObjects=0;
256 CallConstructor(pobj_c,CreateParameter,TypeSize,bSomeObjects);
257
258 return DEF_PTR_OBJECT;
259}
260
261void OpcodeDelete(char *Parameter){
262 int type;
263
264 type=NumOpe(Parameter,0,0,0);
265 if(type==-1) return;
266 if(!(type==DEF_PTR_OBJECT||type==DEF_PTR_VOID)) SetError(122,NULL,cp);
267
268 //pop eax
269 op_pop(REG_EAX);
270
271 //sub eax,sizeof(DWORD)*3
272 OpBuffer[obp++]=(char)0x83;
273 OpBuffer[obp++]=(char)0xE8;
274 OpBuffer[obp++]=(char)0x0C;
275
276 //push eax
277 op_push(REG_EAX);
278
279
280 //mov ebx,dword ptr[eax](オブジェクトの個数)
281 OpBuffer[obp++]=(char)0x8B;
282 OpBuffer[obp++]=(char)0x18;
283
284 //add eax,sizeof(DWORD)
285 OpBuffer[obp++]=(char)0x05;
286 *((long *)(OpBuffer+obp))=sizeof(DWORD);
287 obp+=sizeof(long);
288
289
290 //mov esi,dword ptr[eax](オブジェクトのサイズ)
291 OpBuffer[obp++]=(char)0x8B;
292 OpBuffer[obp++]=(char)0x30;
293
294 //add eax,sizeof(DWORD)
295 OpBuffer[obp++]=(char)0x05;
296 *((long *)(OpBuffer+obp))=sizeof(DWORD);
297 obp+=sizeof(long);
298
299
300 //mov edx,dword ptr[eax](デストラクタの関数ポインタ)
301 OpBuffer[obp++]=(char)0x8B;
302 OpBuffer[obp++]=(char)0x10;
303
304 //add eax,sizeof(DWORD)
305 OpBuffer[obp++]=(char)0x05;
306 *((long *)(OpBuffer+obp))=sizeof(DWORD);
307 obp+=sizeof(long);
308
309
310 //mov ecx,eax
311 OpBuffer[obp++]=(char)0x8B;
312 OpBuffer[obp++]=(char)0xC8;
313
314
315 //jnzの番地
316 int jnz_back;
317 jnz_back=obp;
318
319 //push ecx
320 op_push(REG_ECX);
321
322 //push edx
323 op_push(REG_EDX);
324
325 //push ecx(Thisポインタ ※隠れた第一パラメータ)
326 op_push(REG_ECX);
327
328 //call edx
329 OpBuffer[obp++]=(char)0xFF;
330 OpBuffer[obp++]=(char)0xD2;
331
332 //pop edx
333 op_pop(REG_EDX);
334
335 //pop ecx
336 op_pop(REG_ECX);
337
338 //add ecx,esi
339 OpBuffer[obp++]=(char)0x03;
340 OpBuffer[obp++]=(char)0xCE;
341
342 //sub ebx,1
343 OpBuffer[obp++]=(char)0x83;
344 OpBuffer[obp++]=(char)0xEB;
345 OpBuffer[obp++]=(char)0x01;
346
347 //jnz ↑
348 OpBuffer[obp++]=(char)0x0F;
349 OpBuffer[obp++]=(char)0x85;
350 *((long *)(OpBuffer+obp))=jnz_back-(obp+sizeof(long));
351 obp+=sizeof(long);
352
353
354 //////////////////////////////////////////
355 // オブジェクトメンバ変数用のメモリを解放
356 //////////////////////////////////////////
357
358 //call free
359 extern SUBINFO *pSub_free;
360 op_call(pSub_free);
361}
Note: See TracBrowser for help on using the repository browser.