source: dev/trunk/ab5.0/abdev/compiler_x86/Compile_Statement.cpp@ 712

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

ForeachがIDisposableを実装したIEnumerator<T>を取り扱うように変更(x86のみ)

File size: 34.6 KB
Line 
1#include "stdafx.h"
2
3#include <LexicalScope.h>
4#include <Compiler.h>
5
6#include "../BasicCompiler_Common/common.h"
7#include "Opcode.h"
8
9void OpcodeOthers( const char *Command ){
10 int i,i2;
11
12 char leftTerm[8192];
13 int lastParePos = 0;
14 for(i=0;;i++){
15 if(Command[i]=='\"'){
16 //ダブルクォートは不正なのでエラー扱い
17 leftTerm[i]=0;
18 compiler.errorMessenger.Output(3,leftTerm,cp);
19 return;
20 }
21
22 if(Command[i]=='('){
23 lastParePos = i;
24 i2=GetStringInPare(leftTerm+i,Command+i);
25 i+=i2-1;
26 continue;
27 }
28 if(Command[i]=='['){
29 i2=GetStringInBracket(leftTerm+i,Command+i);
30 i+=i2-1;
31 continue;
32 }
33 if(Command[i]=='\0'){
34 leftTerm[i] = 0;
35 break;
36 }
37
38 if( IsNumCalcMark( Command, i ) ){
39 leftTerm[i] = 0;
40 break;
41 }
42
43 leftTerm[i]=Command[i];
44 }
45 if(!(
46 IsVariableTopChar(leftTerm[0])||
47 leftTerm[0]=='.'||
48 (leftTerm[0]==1&&leftTerm[1]==ESC_PSMEM)
49 )){
50 compiler.errorMessenger.Output(1,NULL,cp);
51 return;
52 }
53
54
55 if(Command[i]=='\0' && lastParePos == 0){
56 //////////////////////////////
57 // パラメータ無しのマクロ検索
58 //////////////////////////////
59
60 const UserProc *pUserProc = GetSubHash(Command);
61
62 //GetSubHash内でエラー提示が行われた場合
63 if(pUserProc==(UserProc *)-1) return;
64
65 if(pUserProc==0){
66 char temporary[VN_SIZE];
67 lstrcpy(temporary,Command);
68
69 CharUpper(temporary);
70 pUserProc=GetSubHash(temporary);
71
72 //GetSubHash内でエラー提示が行われた場合
73 if(pUserProc==(UserProc *)-1) return;
74 }
75
76 if(pUserProc){
77 if( !pUserProc->IsMacro() ){
78 compiler.errorMessenger.Output(10,Command,cp);
79 }
80
81 Opcode_CallProc("",pUserProc,0,"");
82
83 return;
84 }
85 }
86 else if(IsNumCalcMark(Command,i)){
87 //代入演算
88 OpcodeCalc(Command);
89 return;
90 }
91
92 Type resultType;
93 bool isLiteral, isNeedHeapFreeStructure = false;
94 bool result = TermOpe( leftTerm, Type(), resultType, isLiteral, isNeedHeapFreeStructure, NULL, true );
95 if( result ){
96
97 /////////////////////
98 // 戻り値の処理
99 /////////////////////
100
101 if( resultType.IsReal() ){
102 //fstp st(0)
103 compiler.codeGenerator.PutOld(
104 (char)0xDD,
105 (char)0xD8
106 );
107 }
108 else if( resultType.IsStruct() ){
109 //mov ebx,eax
110 compiler.codeGenerator.op_mov_RR(REG_EBX,REG_EAX);
111
112 FreeTempObject(REG_EBX,&resultType.GetClass());
113 }
114
115 return;
116 }
117
118 // どこにも当てはまらなかったため、失敗
119 compiler.errorMessenger.Output(1,NULL,cp);
120}
121
122void OpcodeIf(char *Parameter){
123 int i,i2;
124 Type tempType;
125
126 for(i=0;;i++){
127 if(Parameter[i]=='\0'){
128 compiler.errorMessenger.Output(21,NULL,cp);
129 return;
130 }
131 if(Parameter[i]==1&&Parameter[i+1]==ESC_THEN){
132 Parameter[i]=0;
133 break;
134 }
135 }
136
137 const PertialSchedule *pIfPertialSchedule = NULL;
138 bool isNeedHeapFreeStructure;
139 if( NumOpe( Parameter, Type(DEF_BOOLEAN), tempType, &isNeedHeapFreeStructure ) )
140 {
141 if( tempType.IsObject() )
142 {
143 // Boolean型にキャストする
144 Type booleanType( DEF_BOOLEAN );
145 CallCastOperatorProc( tempType, isNeedHeapFreeStructure, booleanType );
146 tempType = booleanType;
147 }
148
149 if( tempType.IsDouble() ){
150 //fld qword ptr[esp]
151 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
152
153 //push 0
154 compiler.codeGenerator.op_push_V(0);
155
156 //fild dword ptr[esp]
157 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
158
159 //add esp,sizeof(double)+sizeof(long)
160 compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long));
161
162 //fcompp
163 compiler.codeGenerator.op_fcompp();
164
165 //fnstsw ax
166 compiler.codeGenerator.op_fnstsw_ax();
167
168 //test ah,40
169 compiler.codeGenerator.op_test_ah( (char)0x40 );
170
171 //jne (endif、または else まで)
172 pIfPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
173 }
174 else if( tempType.IsSingle() ){
175 //fld dword ptr[esp]
176 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
177
178 //push 0
179 compiler.codeGenerator.op_push_V(0);
180
181 //fild dword ptr[esp]
182 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
183
184 //add esp,sizeof(float)+sizeof(long)
185 compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long));
186
187 //fcompp
188 compiler.codeGenerator.op_fcompp();
189
190 //fnstsw ax
191 compiler.codeGenerator.op_fnstsw_ax();
192
193 //test ah,40
194 compiler.codeGenerator.op_test_ah( (char)0x40 );
195
196 //jne (endif、または else まで)
197 pIfPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
198 }
199 else if( tempType.Is64() ){
200 //64ビット型
201
202 //pop eax
203 compiler.codeGenerator.op_pop(REG_EAX);
204
205 //pop ebx
206 compiler.codeGenerator.op_pop(REG_EBX);
207
208 //cmp eax,0
209 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
210
211 //jne
212 const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
213
214 //cmp ebx,0
215 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 );
216
217 //jne
218 const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
219
220 //jmp (endif、または else までジャンプ)
221 pIfPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
222
223 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
224 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
225 }
226 else{
227 //32ビット型
228
229 //pop eax
230 compiler.codeGenerator.op_pop(REG_EAX);
231
232 //cmp eax,0
233 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
234
235 //je (endif、または else まで条件ジャンプ)
236 pIfPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
237 }
238 }
239
240
241 /////////////////////////
242 // If内をコード化
243 /////////////////////////
244
245 //レキシカルスコープをレベルアップ
246 compiler.codeGenerator.lexicalScopes.Start(
247 compiler.codeGenerator.GetNativeCodeSize(),
248 LexicalScope::SCOPE_TYPE_IF
249 );
250
251 i2=CompileBuffer(ESC_ENDIF,0);
252
253 //レキシカルスコープをレベルダウン
254 compiler.codeGenerator.lexicalScopes.End();
255
256
257 if( pIfPertialSchedule == NULL ) return;
258
259 if(i2==ESC_ELSE){
260 //jmp (endifまで)
261 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
262
263 compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule );
264
265
266 /////////////////////////
267 // Else内をコード化
268 /////////////////////////
269
270 //レキシカルスコープをレベルアップ
271 compiler.codeGenerator.lexicalScopes.Start(
272 compiler.codeGenerator.GetNativeCodeSize(),
273 LexicalScope::SCOPE_TYPE_IF
274 );
275
276 CompileBuffer(ESC_ENDIF,0);
277
278 //レキシカルスコープをレベルダウン
279 compiler.codeGenerator.lexicalScopes.End();
280
281
282 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
283 }
284 else{
285 compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule );
286 }
287}
288
289int GetLabelAddress(char *LabelName,int LineNum){
290 if(LabelName){
291 BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels )
292 {
293 if( label.name.size() > 0 )
294 {
295 if( label.name == LabelName )
296 {
297 return label.address;
298 }
299 }
300 }
301 }
302 else{
303 BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels )
304 {
305 if( label.name.size() == 0 )
306 {
307 if( label.line == LineNum )
308 {
309 return label.address;
310 }
311 }
312 }
313 }
314 return -1;
315}
316void OpcodeGoto(char *Parameter){
317 extern HANDLE hHeap;
318 int i,LineNum;
319
320 if(Parameter[0]=='*'){
321 i=GetLabelAddress(Parameter+1,0);
322
323 if( i == -1 )
324 {
325 //jmp ...(schedule)
326 compiler.codeGenerator.op_jmp_goto_schedule( (const std::string)(Parameter + 1), 0, cp );
327 }
328 else
329 {
330 //jmp ...
331 compiler.codeGenerator.op_jmp(
332 i-compiler.codeGenerator.GetNativeCodeSize(),
333 sizeof(long),
334 false,
335 true
336 );
337 }
338 }
339 else{
340 LineNum=atoi(Parameter);
341 i=GetLabelAddress(0,LineNum);
342
343 if( i == -1 )
344 {
345 //jmp ...(schedule)
346 compiler.codeGenerator.op_jmp_goto_schedule( "", LineNum, cp );
347 }
348 else
349 {
350 //jmp ...
351 compiler.codeGenerator.op_jmp(
352 i-compiler.codeGenerator.GetNativeCodeSize(),
353 sizeof(long),
354 false,
355 true
356 );
357 }
358 }
359}
360void OpcodeWhile(char *Parameter){
361 extern HANDLE hHeap;
362
363 //Continueアドレスのバックアップとセット
364 compiler.codeGenerator.ContinueAreaBegin();
365
366 if(!Parameter[0]) compiler.errorMessenger.Output(10,"While",cp);
367
368 const PertialSchedule *pWhilePertialSchedule = NULL;
369 Type tempType;
370 bool isNeedHeapFreeStructure;
371 if( NumOpe( Parameter, Type(), tempType, &isNeedHeapFreeStructure ) )
372 {
373 if( tempType.IsObject() )
374 {
375 // Boolean型にキャストする
376 Type booleanType( DEF_BOOLEAN );
377 CallCastOperatorProc( tempType, isNeedHeapFreeStructure, booleanType );
378 tempType = booleanType;
379 }
380
381 if( tempType.IsDouble() ){
382 //fld qword ptr[esp]
383 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
384
385 //push 0
386 compiler.codeGenerator.op_push_V(0);
387
388 //fild dword ptr[esp]
389 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
390
391 //add esp,sizeof(double)+sizeof(long)
392 compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long));
393
394 //fcompp
395 compiler.codeGenerator.op_fcompp();
396
397 //fnstsw ax
398 compiler.codeGenerator.op_fnstsw_ax();
399
400 //test ah,40
401 compiler.codeGenerator.op_test_ah( (char)0x40 );
402
403 //jne (Wend まで)
404 pWhilePertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
405 }
406 else if( tempType.IsSingle() ){
407 //fld dword ptr[esp]
408 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
409
410 //push 0
411 compiler.codeGenerator.op_push_V(0);
412
413 //fild dword ptr[esp]
414 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
415
416 //add esp,sizeof(float)+sizeof(long)
417 compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long));
418
419 //fcompp
420 compiler.codeGenerator.op_fcompp();
421
422 //fnstsw ax
423 compiler.codeGenerator.op_fnstsw_ax();
424
425 //test ah,40h
426 compiler.codeGenerator.op_test_ah( (char)0x40 );
427
428 //jne (Wend まで)
429 pWhilePertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
430 }
431 else if( tempType.Is64() ){
432 //64ビット型
433
434 //pop eax
435 compiler.codeGenerator.op_pop(REG_EAX);
436
437 //pop ebx
438 compiler.codeGenerator.op_pop(REG_EBX);
439
440 //cmp eax,0
441 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
442
443 //jne
444 const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
445
446 //cmp ebx,0
447 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 );
448
449 //jne
450 const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
451
452 //jmp (Wendまでジャンプ)
453 pWhilePertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
454
455 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
456 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
457 }
458 else{
459 //その他整数型
460
461 //pop eax
462 compiler.codeGenerator.op_pop(REG_EAX);
463
464 //cmp eax,0
465 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
466
467 //je (Wend まで)
468 pWhilePertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
469 }
470 }
471
472 //レキシカルスコープをレベルアップ
473 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_WHILE );
474
475 //While内をコンパイル
476 CompileBuffer(0,COM_WEND);
477
478 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
479
480 //jmp ...
481 compiler.codeGenerator.op_jmp_continue();
482
483 //レキシカルスコープをレベルダウン
484 compiler.codeGenerator.lexicalScopes.End();
485
486 if( pWhilePertialSchedule )
487 {
488 compiler.codeGenerator.opfix_JmpPertialSchedule( pWhilePertialSchedule );
489 }
490
491 compiler.codeGenerator.ContinueAreaEnd();
492}
493
494char szNextVariable[VN_SIZE];
495void OpcodeFor(char *Parameter){
496 extern HANDLE hHeap;
497 int i,i2;
498 char temporary[VN_SIZE],variable[VN_SIZE],JudgeNum[VN_SIZE],StepNum[VN_SIZE];
499
500 //第1パラメータを取得
501 i=GetOneParameter(Parameter,0,temporary);
502 if(!Parameter[i]){
503 compiler.errorMessenger.Output(12,"For",cp);
504 goto ErrorStep;
505 }
506
507 for(i2=0;;i2++){
508 if(temporary[i2]=='='){
509 variable[i2]=0;
510
511 //カウンタ初期化
512 OpcodeCalc(temporary);
513 break;
514 }
515 if(temporary[i2]=='\0'){
516 compiler.errorMessenger.Output(12,"For",cp);
517 goto ErrorStep;
518 }
519 variable[i2]=temporary[i2];
520 }
521
522 //jmp ...
523 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
524
525 //Continueアドレスのバックアップとセット
526 compiler.codeGenerator.ContinueAreaBegin();
527
528 //第2パラメータを取得(to~)
529 i=GetOneParameter(Parameter,i,JudgeNum);
530
531 //第3パラメータを取得(step~)
532 if(Parameter[i]){
533 i=GetOneParameter(Parameter,i,StepNum);
534 if(Parameter[i]) compiler.errorMessenger.Output(12,"For",cp);
535 }
536 else lstrcpy(StepNum,"1");
537
538 //カウンタを増加させる
539 sprintf(temporary,"%s=(%s)+(%s)",variable,variable,StepNum);
540 OpcodeCalc(temporary);
541
542 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
543
544 //増加か減少かを区別する
545 sprintf(temporary,"(%s)>=0",StepNum);
546 NumOpe(temporary,Type(),Type());
547
548 //pop eax
549 compiler.codeGenerator.op_pop(REG_EAX);
550
551 //cmp eax,0
552 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
553
554 //je [カウンタ減少の場合の判定]
555 pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
556
557 //判定(カウンタ増加の場合)
558 sprintf(temporary,"%s<=(%s)",variable,JudgeNum);
559 NumOpe(temporary,Type(),Type());
560
561 //pop eax
562 compiler.codeGenerator.op_pop(REG_EAX);
563
564 //jmp [カウンタ減少の場合の判定を飛び越す]
565 const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
566
567 //jeジャンプ先のオフセット値
568 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
569
570 //判定(カウンタ減少の場合)
571 sprintf(temporary,"%s>=(%s)",variable,JudgeNum);
572 NumOpe(temporary,Type(),Type());
573
574 //pop eax
575 compiler.codeGenerator.op_pop(REG_EAX);
576
577 //jmpジャンプ先のオフセット値
578 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
579
580 //cmp eax,0
581 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
582
583ErrorStep:
584
585 //je ...
586 pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
587
588 //レキシカルスコープをレベルアップ
589 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR );
590
591 //For内をコンパイル
592 CompileBuffer(0,COM_NEXT);
593
594 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
595
596 if(szNextVariable[0]){
597 if(lstrcmp(szNextVariable,variable)!=0){
598 compiler.errorMessenger.Output(55,szNextVariable,cp);
599 }
600 }
601
602 //jmp ...
603 compiler.codeGenerator.op_jmp_continue();
604
605 //レキシカルスコープをレベルダウン
606 compiler.codeGenerator.lexicalScopes.End();
607
608 //jeジャンプ先のオフセット値
609 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
610
611 //Continueアドレスを復元
612 compiler.codeGenerator.ContinueAreaEnd();
613}
614
615void OpcodeForeach( const char *Parameter )
616{
617 Type resultType;
618 char temporary[VN_SIZE],variable[VN_SIZE],collectionVar[VN_SIZE];
619 bool isError = false;
620 std::string elementTypeName;
621
622 //第1パラメータを取得
623 int i = 0;
624 GetCustomToken( variable, Parameter, i, ESC_IN, true );
625 if(!Parameter[i]){
626 compiler.errorMessenger.Output(12,"Foreach",cp);
627 isError = true;
628 goto ErrorStep;
629 }
630 i++;
631
632 //第2パラメータを取得(in~)
633 lstrcpy( collectionVar, Parameter + i );
634
635
636 Exception::TryCommand(); //Finallyで_System_ForeachEnumerator.Disposeするため
637
638 //Enumeratorの取得
639 sprintf(temporary,"_System_ForeachEnumerator=%s.GetEnumerator()", collectionVar );
640 OpcodeDim(temporary,DIMFLAG_INITDEBUGVAR);
641
642 //レキシカルスコープをレベルアップ
643 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR );
644
645 {
646 Type collectionType;
647 if( !NumOpe_GetType( collectionVar, Type(), collectionType ) )
648 {
649 isError = true;
650 goto ErrorStep;
651 }
652 elementTypeName = collectionType.GetActualGenericType(0).GetClass().GetFullName();
653 }
654
655 if( !GetVarType( variable, resultType, false ) )
656 {
657
658 // 未定義の場合は自動的に定義する
659 sprintf(temporary,"%s=Nothing%c%c%s", variable, 1, ESC_AS, elementTypeName.c_str() );
660 OpcodeDim(temporary,DIMFLAG_INITDEBUGVAR);
661 }
662
663 //Continueアドレスのバックアップとセット
664 compiler.codeGenerator.ContinueAreaBegin();
665
666 // MoveNextメソッドを呼び出す
667 NumOpe("_System_ForeachEnumerator.MoveNext()",Type(),Type());
668
669 //pop eax
670 compiler.codeGenerator.op_pop(REG_EAX);
671
672 //cmp eax,0
673 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
674
675ErrorStep:
676
677 //je ...
678 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
679
680 if( !isError )
681 {
682 // Currentプロパティから現在の値を取得
683 sprintf( temporary, "%s=_System_ForeachEnumerator.Current%c%c%s", variable, 1, ESC_AS, elementTypeName.c_str() );
684 Compile( temporary );
685 }
686
687 //For内をコンパイル
688 CompileBuffer(0,COM_NEXT);
689
690 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
691
692 if(szNextVariable[0]){
693 if(lstrcmp(szNextVariable,variable)!=0){
694 compiler.errorMessenger.Output(55,szNextVariable,cp);
695 }
696 }
697
698 if( !isError )
699 {
700 //jmp ...
701 compiler.codeGenerator.op_jmp_continue();
702 }
703
704 //レキシカルスコープをレベルダウン
705 compiler.codeGenerator.lexicalScopes.End();
706
707 //jeジャンプ先のオフセット値
708 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
709
710 //Disposeを呼んでTryスコープを終える
711 Exception::FinallyCommand();
712 Compile( "_System_ForeachEnumerator.Dispose()" );
713 Exception::EndTryCommand();
714
715 //Continueアドレスを復元
716 compiler.codeGenerator.ContinueAreaEnd();
717}
718
719void OpcodeDo(char *Parameter){
720 extern HANDLE hHeap;
721 int i,i2,i3;
722
723 if(Parameter[0]) compiler.errorMessenger.Output(10,"Do",cp);
724
725 //Continueアドレスのバックアップとセット
726 compiler.codeGenerator.ContinueAreaBegin();
727
728 //レキシカルスコープをレベルアップ
729 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_DO );
730
731 //Do内をコンパイル
732 CompileBuffer(0,COM_LOOP);
733
734 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
735
736 const PertialSchedule *pDoPertialSchedule = NULL;
737
738 extern char *basbuf;
739 char temporary[VN_SIZE];
740 for(i=cp-1;;i--){
741 if(IsCommandDelimitation(basbuf[i])){
742 i+=3;
743 if(!(basbuf[i]=='0'||basbuf[i]=='1')){
744 //無条件ループ
745 break;
746 }
747 i3=i;
748
749 for(i+=2,i2=0;;i++,i2++){
750 if(IsCommandDelimitation(basbuf[i])){
751 temporary[i2]=0;
752 break;
753 }
754 temporary[i2]=basbuf[i];
755 }
756
757 Type tempType;
758 bool isNeedHeapFreeStructure;
759 NumOpe( temporary, Type(), tempType, &isNeedHeapFreeStructure );
760
761 if( tempType.IsObject() )
762 {
763 // Boolean型にキャストする
764 Type booleanType( DEF_BOOLEAN );
765 CallCastOperatorProc( tempType, isNeedHeapFreeStructure, booleanType );
766 tempType = booleanType;
767 }
768
769 if( tempType.IsDouble() ){
770 //fld qword ptr[esp]
771 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
772
773 //push 0
774 compiler.codeGenerator.op_push_V(0);
775
776 //fild dword ptr[esp]
777 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
778
779 //add esp,sizeof(double)+sizeof(long)
780 compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long));
781
782 //fcompp
783 compiler.codeGenerator.op_fcompp();
784
785 //fnstsw ax
786 compiler.codeGenerator.op_fnstsw_ax();
787
788 //test ah,40
789 compiler.codeGenerator.op_test_ah( (char)0x40 );
790
791 if(basbuf[i3]=='0'){
792 //While
793
794 //jne 5(ループ終了)
795 pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
796 }
797 else if(basbuf[i3]=='1'){
798 //Until
799
800 //je 5(ループ終了)
801 pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true );
802 }
803 }
804 else if( tempType.IsSingle() ){
805 //fld dword ptr[esp]
806 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
807
808 //push 0
809 compiler.codeGenerator.op_push_V(0);
810
811 //fild dword ptr[esp]
812 compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
813
814 //add esp,sizeof(float)+sizeof(long)
815 compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long));
816
817 //fcompp
818 compiler.codeGenerator.op_fcompp();
819
820 //fnstsw ax
821 compiler.codeGenerator.op_fnstsw_ax();
822
823 //test ah,40
824 compiler.codeGenerator.op_test_ah( (char)0x40 );
825
826 if(basbuf[i3]=='0'){
827 //While
828
829 //jne 5(ループ終了)
830 pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
831 }
832 else if(basbuf[i3]=='1'){
833 //Until
834
835 //je 5(ループ終了)
836 pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true );
837 }
838 }
839 else if( tempType.Is64() ){
840 //64ビット型
841
842 //pop eax
843 compiler.codeGenerator.op_pop(REG_EAX);
844
845 //pop ebx
846 compiler.codeGenerator.op_pop(REG_EBX);
847
848 //cmp eax,0
849 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
850
851 //jne
852 const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
853
854 //cmp ebx,0
855 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 );
856
857 //jne
858 const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
859
860 if(basbuf[i3]=='0'){
861 //While
862
863 //jmp 5(ループ終了)
864 pDoPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(char), true );
865
866 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
867 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
868 }
869 else if(basbuf[i3]=='1'){
870 //Until
871
872 //jmp 2(ループを続ける)
873 const PertialSchedule *pTempPertialSchedule3 = compiler.codeGenerator.op_jmp( 0, sizeof(char), true );
874
875 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
876 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
877
878 //jmp 5(ループ終了)
879 pDoPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(char), true );
880
881 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule3 );
882 }
883 }
884 else{
885 //pop eax
886 compiler.codeGenerator.op_pop(REG_EAX);
887
888 //cmp eax,0
889 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
890
891 if(basbuf[i3]=='0'){
892 //While
893
894 //je 5(ループ終了)
895 pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true );
896 }
897 else if(basbuf[i3]=='1'){
898 //Until
899
900 //jne 5(ループ終了)
901 pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
902 }
903 }
904 break;
905 }
906 }
907
908 //jmp ...
909 compiler.codeGenerator.op_jmp_continue();
910
911 if( pDoPertialSchedule )
912 {
913 compiler.codeGenerator.opfix_JmpPertialSchedule( pDoPertialSchedule );
914 }
915
916 //jmp ...
917 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
918
919 //レキシカルスコープをレベルダウン
920 compiler.codeGenerator.lexicalScopes.End();
921
922 //jmpジャンプ先のオフセット値
923 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
924
925 //Continueアドレスを復元
926 compiler.codeGenerator.ContinueAreaEnd();
927}
928void OpcodeContinue(void){
929 //jmp ...(Continue addr)
930 compiler.codeGenerator.op_jmp_continue();
931}
932
933void OpcodeExitSub(void){
934 if( compiler.IsGlobalAreaCompiling() ){
935 compiler.errorMessenger.Output(12,"Exit Sub/Function",cp);
936 return;
937 }
938
939 //未解放のローカルオブジェクトのデストラクタを呼び出す
940 compiler.codeGenerator.lexicalScopes.CallDestructorsOfReturn();
941
942 //jmp ...(End Sub/Function)
943 compiler.codeGenerator.op_jmp_exitsub();
944}
945
946//Caseスケジュール
947class SelectSchedule
948{
949public:
950 SelectSchedule( int typeSize )
951 : typeSize( typeSize )
952 , nowCaseSchedule( 0 )
953 {
954 }
955
956 PertialSchedules casePertialSchedules;
957 int typeSize;
958 int nowCaseSchedule;
959};
960std::vector<SelectSchedule> selectSchedules;
961
962void OpcodeSelect(const char *lpszParms)
963{
964 extern HANDLE hHeap;
965 extern char *basbuf;
966 int i,i2,i3,sw,NowCaseCp;
967 char temporary[VN_SIZE];
968
969 Type type1;
970 bool result = NumOpe(lpszParms,Type(), type1 );
971
972 selectSchedules.push_back( SelectSchedule( type1.GetSize() ) );
973
974 if( result )
975 {
976 if( selectSchedules.back().typeSize < sizeof(long) ){
977 selectSchedules.back().typeSize = sizeof(long);
978 }
979
980 for(i=cp,sw=0;;i++){
981 if(basbuf[i]=='\0'){
982 selectSchedules.pop_back();
983 compiler.errorMessenger.Output(22,"Select",cp);
984 return;
985 }
986 if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE){
987 for(i2=0;;i++){
988 if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE) i2++;
989 if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT){
990 i2--;
991 if(i2==0) break;
992 }
993 }
994 continue;
995 }
996 if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT){
997 if(sw==0){
998 //add esp,CaseTypeSize
999 compiler.codeGenerator.op_add_esp( selectSchedules.back().typeSize );
1000 }
1001 break;
1002 }
1003 if(basbuf[i]==1&&basbuf[i+1]==ESC_CASE){
1004 NowCaseCp=i;
1005
1006 i++;
1007 while(1){
1008 for(i++,i2=0;;i++,i2++){
1009 if(basbuf[i]=='\"'){
1010 i3=GetStringInQuotation(temporary+i2,basbuf+i);
1011 i+=i3-1;
1012 i2+=i3-1;
1013 continue;
1014 }
1015 if(basbuf[i]=='('){
1016 i3=GetStringInPare(temporary+i2,basbuf+i);
1017 i+=i3-1;
1018 i2+=i3-1;
1019 continue;
1020 }
1021 if(basbuf[i]=='['){
1022 i3=GetStringInBracket(temporary+i2,basbuf+i);
1023 i+=i3-1;
1024 i2+=i3-1;
1025 continue;
1026 }
1027
1028 if(IsCommandDelimitation(basbuf[i])){
1029 temporary[i2]=0;
1030 break;
1031 }
1032 if(basbuf[i]==','){
1033 temporary[i2]=0;
1034 break;
1035 }
1036
1037 temporary[i2]=basbuf[i];
1038 }
1039
1040 //エラー用
1041 i2=cp;
1042 cp=NowCaseCp;
1043
1044 Type type2;
1045 if( !NumOpe(temporary,type1,type2) ){
1046 return;
1047 }
1048
1049 cp=i2;
1050
1051 if(type1.IsObject()){
1052 std::vector<const UserProc *> subs;
1053 type1.GetClass().GetDynamicMethods().Enum( CALC_EQUAL, subs );
1054 if( subs.size() == 0 ){
1055 return;
1056 }
1057
1058 Parameters params;
1059 params.push_back( new Parameter( "", Type( type2 ) ) );
1060
1061 //オーバーロードを解決
1062 const UserProc *pUserProc = OverloadSolution( "==", subs, params, Type( DEF_BOOLEAN ), type1 );
1063
1064 delete params[0];
1065
1066 if(!pUserProc){
1067 //エラー
1068 return;
1069 }
1070
1071
1072 //pop edx
1073 compiler.codeGenerator.op_pop(REG_EDX);
1074
1075 //mov ecx,dword ptr[esp]
1076 compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_ESP,0,MOD_BASE);
1077
1078 //push edx
1079 compiler.codeGenerator.op_push(REG_EDX);
1080
1081 //push ecx
1082 compiler.codeGenerator.op_push(REG_ECX);
1083
1084 //call operator_proc ※ ==演算子
1085 compiler.codeGenerator.op_call(pUserProc);
1086
1087 //test eax,eax
1088 compiler.codeGenerator.op_test(REG_EAX,REG_EAX);
1089
1090 //jne ...
1091 selectSchedules.back().casePertialSchedules.push_back(
1092 compiler.codeGenerator.op_jne( 0, sizeof(long), true )
1093 );
1094 }
1095 else if(type1.IsDouble()){
1096 ChangeTypeToDouble(type2.GetBasicType());
1097
1098 //fld qword ptr[esp]
1099 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
1100
1101 //add esp,CaseTypeSize
1102 compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize);
1103
1104 //fld qword ptr[esp]
1105 compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
1106
1107 //fcompp
1108 compiler.codeGenerator.op_fcompp();
1109
1110 //fnstsw ax
1111 compiler.codeGenerator.op_fnstsw_ax();
1112
1113 //test ah,40
1114 compiler.codeGenerator.op_test_ah( (char)0x40 );
1115
1116 //jne ...
1117 selectSchedules.back().casePertialSchedules.push_back(
1118 compiler.codeGenerator.op_jne( 0, sizeof(long), true )
1119 );
1120 }
1121 else if(type1.IsSingle()){
1122 ChangeTypeToSingle(type2.GetBasicType());
1123
1124 //fld dword ptr[esp]
1125 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
1126
1127 //add esp,CaseTypeSize
1128 compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize);
1129
1130 //fld dword ptr[esp]
1131 compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
1132
1133 //fcompp
1134 compiler.codeGenerator.op_fcompp();
1135
1136 //fnstsw ax
1137 compiler.codeGenerator.op_fnstsw_ax();
1138
1139 //test ah,40
1140 compiler.codeGenerator.op_test_ah( (char)0x40 );
1141
1142 //jne ...
1143 selectSchedules.back().casePertialSchedules.push_back(
1144 compiler.codeGenerator.op_jne( 0, sizeof(long), true )
1145 );
1146 }
1147 else{
1148 //その他整数型
1149
1150 //pop ebx
1151 compiler.codeGenerator.op_pop(REG_EBX);
1152
1153 //mov eax,dword ptr[esp]
1154 compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EAX, REG_ESP, 0, MOD_BASE );
1155
1156 //cmp eax,ebx
1157 compiler.codeGenerator.op_cmp_RR( REG_EAX, REG_EBX );
1158
1159 //je ...
1160 selectSchedules.back().casePertialSchedules.push_back(
1161 compiler.codeGenerator.op_je( 0, sizeof(long), true )
1162 );
1163 }
1164
1165 if(basbuf[i]!=',') break;
1166 }
1167 }
1168 if(basbuf[i]==1&&basbuf[i+1]==ESC_CASEELSE){
1169 sw=1;
1170
1171 //jmp ...
1172 selectSchedules.back().casePertialSchedules.push_back(
1173 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
1174 );
1175 }
1176 }
1177 }
1178
1179 //レキシカルスコープをレベルアップ
1180 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_SELECT );
1181
1182 //Select Case内をコンパイル
1183 CompileBuffer(ESC_ENDSELECT,0);
1184
1185 //jmp EndSelect
1186 selectSchedules.back().casePertialSchedules.push_back(
1187 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
1188 );
1189
1190 //最終スケジュール
1191 for(i=selectSchedules.back().nowCaseSchedule;i<(int)selectSchedules.back().casePertialSchedules.size();i++){
1192 compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[i] );
1193 }
1194
1195 //レキシカルスコープをレベルダウン
1196 compiler.codeGenerator.lexicalScopes.End();
1197
1198 selectSchedules.pop_back();
1199}
1200void OpcodeCase(char *Parameter){
1201 int i;
1202
1203 if(selectSchedules.back().typeSize==-1){
1204 compiler.errorMessenger.Output(30,"Case",cp);
1205 return;
1206 }
1207
1208 //jmp EndSelect
1209 selectSchedules.back().casePertialSchedules.push_back(
1210 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
1211 );
1212
1213 i=0;
1214 while(1){
1215 //Caseスケジュール
1216 compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[selectSchedules.back().nowCaseSchedule] );
1217 selectSchedules.back().nowCaseSchedule++;
1218
1219 i=JumpOneParameter(Parameter,i);
1220 if(Parameter[i]=='\0') break;
1221 }
1222
1223 //add esp,CaseTypeSize
1224 compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize);
1225}
1226
1227void OpcodeGosub(char *Parameter){
1228 extern HANDLE hHeap;
1229 int i,LineNum;
1230
1231 if(Parameter[0]=='*'){
1232 i=GetLabelAddress(Parameter+1,0);
1233
1234 if( i == -1 )
1235 {
1236 //jmp ...(schedule)
1237 compiler.codeGenerator.op_jmp_goto_schedule( (const std::string)(Parameter + 1), 0, cp );
1238 }
1239 else
1240 {
1241 //jmp ...
1242 compiler.codeGenerator.op_jmp(
1243 i-compiler.codeGenerator.GetNativeCodeSize(),
1244 sizeof(long),
1245 false,
1246 true
1247 );
1248 }
1249 }
1250 else{
1251 LineNum=atoi(Parameter);
1252 i=GetLabelAddress(0,LineNum);
1253
1254 if( i == -1 )
1255 {
1256 //jmp ...(schedule)
1257 compiler.codeGenerator.op_jmp_goto_schedule( "", LineNum, cp );
1258 }
1259 else
1260 {
1261 //jmp ...
1262 compiler.codeGenerator.op_jmp(
1263 i-compiler.codeGenerator.GetNativeCodeSize(),
1264 sizeof(long),
1265 false,
1266 true
1267 );
1268 }
1269 }
1270}
1271void OpcodeReturn(char *Parameter){
1272 if( compiler.IsGlobalAreaCompiling() ){
1273 //Gosub~Returnとして扱う
1274
1275 //ret
1276 compiler.codeGenerator.op_ret();
1277 }
1278 else{
1279 //戻り値をセット
1280 if(Parameter[0]){
1281 const UserProc &proc = compiler.GetCompilingUserProc();
1282
1283 const char *temp = "_System_ReturnValue";
1284 if(proc.GetName()[0]==1&&proc.GetName()[1]==ESC_OPERATOR)
1285 {
1286 }
1287 else{
1288 temp=proc.GetName().c_str();
1289 }
1290
1291 char temporary[VN_SIZE];
1292 sprintf(temporary,"%s=%s",temp,Parameter);
1293 OpcodeCalc(temporary);
1294 }
1295
1296 //プロシージャを抜け出す(C言語のreturnと同様の処理を行う)
1297 OpcodeExitSub();
1298 }
1299}
1300
1301
1302////////////
1303// ポインタ
1304
1305void OpcodeSetPtrData(char *Parameter,int type){
1306 int i;
1307 char temporary[VN_SIZE];
1308
1309 if(Parameter[0]=='('){
1310 i=JumpStringInPare(Parameter,1);
1311 if(Parameter[i+1]=='\0'){
1312 for(i=0;;i++){
1313 Parameter[i]=Parameter[i+1];
1314 if(Parameter[i]=='\0') break;
1315 }
1316 Parameter[i-1]=0;
1317 }
1318 }
1319
1320 //第1パラメータを取得
1321 i=GetOneParameter(Parameter,0,temporary);
1322 if(!Parameter[i]){
1323 compiler.errorMessenger.Output(1,NULL,cp);
1324 return;
1325 }
1326
1327 Type resultType;
1328 if( !NumOpe(temporary,Type(),resultType) ){
1329 return;
1330 }
1331 if(!resultType.IsWhole()){
1332 compiler.errorMessenger.Output(11,Parameter,cp);
1333 return;
1334 }
1335
1336 ChangeTypeToLong( resultType.GetBasicType() );
1337
1338 //第2パラメータを取得
1339 i=GetOneParameter(Parameter,i,temporary);
1340 if(Parameter[i]){
1341 compiler.errorMessenger.Output(1,NULL,cp);
1342 return;
1343 }
1344
1345 if( !NumOpe(temporary,Type(),resultType) ){
1346 return;
1347 }
1348
1349 if(type==DEF_DOUBLE){
1350 ChangeTypeToDouble_ToFpuReg( resultType.GetBasicType() );
1351
1352 //pop eax
1353 compiler.codeGenerator.op_pop(REG_EAX);
1354
1355 //fstp qword ptr[eax]
1356 compiler.codeGenerator.PutOld(
1357 (char)0xDD,
1358 (char)0x18
1359 );
1360 }
1361 else if(type==DEF_SINGLE){
1362 ChangeTypeToSingle( resultType.GetBasicType() );
1363
1364 //pop ebx
1365 compiler.codeGenerator.op_pop(REG_EBX);
1366
1367 //pop eax
1368 compiler.codeGenerator.op_pop(REG_EAX);
1369
1370 //mov dword ptr[eax],ebx
1371 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE );
1372 }
1373 else if(type==DEF_QWORD){
1374 ChangeTypeToInt64( resultType.GetBasicType() );
1375
1376 //pop ecx
1377 compiler.codeGenerator.op_pop(REG_ECX);
1378
1379 //pop ebx
1380 compiler.codeGenerator.op_pop(REG_EBX);
1381
1382 //pop eax
1383 compiler.codeGenerator.op_pop(REG_EAX);
1384
1385 //mov dword ptr[eax],ecx
1386 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE );
1387
1388 //mov dword ptr[eax+sizeof(long)],ebx
1389 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0x04, MOD_BASE_DISP8 );
1390 }
1391 else if(type==DEF_DWORD){
1392 ChangeTypeToLong( resultType.GetBasicType() );
1393
1394 //pop ebx
1395 compiler.codeGenerator.op_pop(REG_EBX);
1396
1397 //pop eax
1398 compiler.codeGenerator.op_pop(REG_EAX);
1399
1400 //mov dword ptr[eax],ebx
1401 compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE );
1402 }
1403 else if(type==DEF_WORD){
1404 ChangeTypeToLong( resultType.GetBasicType() );
1405
1406 //pop ebx
1407 compiler.codeGenerator.op_pop(REG_EBX);
1408
1409 //pop eax
1410 compiler.codeGenerator.op_pop(REG_EAX);
1411
1412 //mov word ptr[eax],bx
1413 compiler.codeGenerator.op_mov_MR( sizeof(short), REG_EBX, REG_EAX, 0, MOD_BASE );
1414 }
1415 else if(type==DEF_BYTE){
1416 ChangeTypeToLong( resultType.GetBasicType() );
1417
1418 //pop ebx
1419 compiler.codeGenerator.op_pop(REG_EBX);
1420
1421 //pop eax
1422 compiler.codeGenerator.op_pop(REG_EAX);
1423
1424 //mov byte ptr[eax],bl
1425 compiler.codeGenerator.op_mov_MR( sizeof(char), REG_EBX, REG_EAX, 0, MOD_BASE );
1426 }
1427}
Note: See TracBrowser for help on using the repository browser.