source: dev/trunk/ab5.0/abdev/compiler_x64/Compile_Statement.cpp@ 720

Last change on this file since 720 was 720, checked in by dai, 16 years ago

#189への対応。型パラメータに型パラメータを指定したときにテンプレート展開の対象にならない不具合を修正。

File size: 24.9 KB
RevLine 
[206]1#include "stdafx.h"
2
[183]3#include <Compiler.h>
4
[3]5#include "../BasicCompiler_Common/common.h"
6#include "Opcode.h"
7
[129]8void OpcodeOthers(const char *Command){
[3]9 int i,i2;
10
[122]11 char leftTerm[8192];
12 int lastParePos = 0;
[3]13 for(i=0;;i++){
[122]14 if(Command[i]=='\"'){
15 //ダブルクォートは不正なのでエラー扱い
16 leftTerm[i]=0;
[468]17 compiler.errorMessenger.Output(3,leftTerm,cp);
[122]18 return;
19 }
20
21 if(Command[i]=='('){
22 lastParePos = i;
23 i2=GetStringInPare(leftTerm+i,Command+i);
[3]24 i+=i2-1;
25 continue;
26 }
[122]27 if(Command[i]=='['){
28 i2=GetStringInBracket(leftTerm+i,Command+i);
29 i+=i2-1;
[3]30 continue;
31 }
[122]32 if(Command[i]=='\0'){
33 leftTerm[i] = 0;
[3]34 break;
35 }
[122]36
37 if( IsNumCalcMark( Command, i ) ){
38 leftTerm[i] = 0;
39 break;
40 }
41
42 leftTerm[i]=Command[i];
[3]43 }
44 if(!(
[122]45 IsVariableTopChar(leftTerm[0])||
46 leftTerm[0]=='.'||
47 (leftTerm[0]==1&&leftTerm[1]==ESC_PSMEM)
[3]48 )){
[468]49 compiler.errorMessenger.Output(1,NULL,cp);
[3]50 return;
51 }
52
53
[122]54 if(Command[i]=='\0' && lastParePos == 0){
[3]55 //////////////////////////////
56 // パラメータ無しのマクロ検索
57 //////////////////////////////
58
[206]59 const UserProc *pUserProc=GetSubHash(Command);
[3]60
61 //GetSubHash内でエラー提示が行われた場合
[75]62 if(pUserProc==(UserProc *)-1) return;
[3]63
[75]64 if(pUserProc==0){
[3]65 char temporary[VN_SIZE];
66 lstrcpy(temporary,Command);
67
68 CharUpper(temporary);
[75]69 pUserProc=GetSubHash(temporary);
[3]70
71 //GetSubHash内でエラー提示が行われた場合
[75]72 if(pUserProc==(UserProc *)-1) return;
[3]73 }
74
[75]75 if(pUserProc){
[97]76 if( !pUserProc->IsMacro() ){
[468]77 compiler.errorMessenger.Output(10,Command,cp);
[97]78 }
[3]79
[308]80 Opcode_CallProc("",pUserProc,0,"");
[3]81
82 return;
83 }
84 }
85 else if(IsNumCalcMark(Command,i)){
86 //代入演算
87 OpcodeCalc(Command);
88 return;
89 }
90
[122]91 if( pobj_reg ){
[468]92 compiler.errorMessenger.OutputFatalError();
[122]93 }
94 pobj_reg=new CRegister(REG_RAX);
[3]95
[122]96 Type resultType;
[436]97 bool isLiteral, isNeedHeapFreeStructure = false;
98 bool result = TermOpe( leftTerm, Type(), resultType, isLiteral, isNeedHeapFreeStructure, NULL, true );
[3]99
[122]100 delete pobj_reg;
101 pobj_reg = NULL;
[3]102
[122]103 if( result ){
[3]104
105 /////////////////////
106 // 戻り値の処理
107 /////////////////////
108
[75]109 if( resultType.IsStruct() ){
[3]110 //mov r14,rax
[226]111 compiler.codeGenerator.op_mov_RR(REG_R14,REG_RAX);
[3]112
[75]113 FreeTempObject(REG_R14,&resultType.GetClass());
[3]114 }
[386]115
116 return;
[3]117 }
[386]118
119 // どこにも当てはまらなかったため、失敗
[468]120 compiler.errorMessenger.Output(1,NULL,cp);
[3]121}
122
123void Judgment(char *buffer){
[75]124 int reg=REG_RAX;
125 Type resultType;
[676]126 bool isNeedHeapFreeStructure;
127 if( !NumOpe(&reg,buffer,Type(DEF_BOOLEAN),resultType, &isNeedHeapFreeStructure) ){
[75]128 return;
129 }
[3]130
[676]131 if( resultType.IsObject() )
132 {
133 // Boolean型にキャストする
134 Type booleanType( DEF_BOOLEAN );
135 CallCastOperatorProc( reg, resultType, isNeedHeapFreeStructure, booleanType );
136 resultType = booleanType;
137 }
138
[3]139 int offset;
140
[75]141 if(resultType.IsDouble()){
[3]142 double dbl=0;
[587]143 offset=compiler.GetObjectModule().dataTable.Add( dbl );
[3]144
145 //comisd xmm0,qword ptr[data table offset]
[242]146 compiler.codeGenerator.PutOld(
147 (char)0x66,
148 (char)0x0F,
149 (char)0x2F,
150 (char)0x04,
151 (char)0x25
152 );
153 compiler.codeGenerator.PutOld(
154 (long)offset,
155 Schedule::DataTable
156 );
[3]157 }
[75]158 else if(resultType.IsSingle()){
[3]159 float flt=0;
[587]160 offset=compiler.GetObjectModule().dataTable.Add( flt );
[3]161
162 //comiss xmm0,dword ptr[data table offset]
[242]163 compiler.codeGenerator.PutOld(
164 (char)0x0F,
165 (char)0x2F,
166 (char)0x04,
167 (char)0x25
168 );
169 compiler.codeGenerator.PutOld(
170 (long)offset,
171 Schedule::DataTable
172 );
[3]173 }
174 else{
175 //整数型
176
177 //cmp rax,0
[226]178 compiler.codeGenerator.op_cmp_value(resultType.GetSize(),REG_RAX,0);
[3]179 }
180}
181
182void OpcodeIf(char *Parameter){
[242]183 for(int i=0;;i++){
[3]184 if(Parameter[i]=='\0'){
[468]185 compiler.errorMessenger.Output(21,NULL,cp);
[3]186 return;
187 }
188 if(Parameter[i]==1&&Parameter[i+1]==ESC_THEN){
189 Parameter[i]=0;
190 break;
191 }
192 }
193
194 //条件式を実行してフラグをセット
195 Judgment(Parameter);
196
197 //je (endif、または else まで条件ジャンプ)
[254]198 const PertialSchedule *pIfPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
[3]199
200
201 /////////////////////////
202 // If内をコード化
203 /////////////////////////
204
205 //レキシカルスコープをレベルアップ
[308]206 compiler.codeGenerator.lexicalScopes.Start(
207 compiler.codeGenerator.GetNativeCodeSize(),
208 LexicalScope::SCOPE_TYPE_IF
209 );
[3]210
[242]211 int i2=CompileBuffer(ESC_ENDIF,0);
[3]212
213 //レキシカルスコープをレベルダウン
[254]214 compiler.codeGenerator.lexicalScopes.End();
[3]215
216
217 if(i2==ESC_ELSE){
218 //jmp (endifまで)
[254]219 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
[3]220
[242]221 compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule );
[3]222
223
224
225 /////////////////////////
226 // Else内をコード化
227 /////////////////////////
228
229 //レキシカルスコープをレベルアップ
[308]230 compiler.codeGenerator.lexicalScopes.Start(
231 compiler.codeGenerator.GetNativeCodeSize(),
232 LexicalScope::SCOPE_TYPE_IF
233 );
[3]234
235 CompileBuffer(ESC_ENDIF,0);
236
237 //レキシカルスコープをレベルダウン
[254]238 compiler.codeGenerator.lexicalScopes.End();
[3]239
240
[242]241 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
[3]242 }
243 else{
[242]244 compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule );
[3]245 }
246}
247
248int GetLabelAddress(char *LabelName,int LineNum){
249 if(LabelName){
[262]250 BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels )
251 {
252 if( label.name.size() > 0 )
253 {
254 if( label.name == LabelName )
255 {
256 return label.address;
257 }
[3]258 }
259 }
260 }
261 else{
[262]262 BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels )
263 {
264 if( label.name.size() == 0 )
265 {
266 if( label.line == LineNum )
267 {
268 return label.address;
269 }
[3]270 }
271 }
272 }
273 return -1;
274}
275void OpcodeGoto(char *Parameter){
276 extern HANDLE hHeap;
277 int i,LineNum;
278
279 if(Parameter[0]=='*'){
280 i=GetLabelAddress(Parameter+1,0);
281
[254]282 if( i == -1 )
283 {
284 //jmp ...(schedule)
285 compiler.codeGenerator.op_jmp_goto_schedule( (const std::string)(Parameter + 1), 0, cp );
[3]286 }
[254]287 else
288 {
289 //jmp ...
[308]290 compiler.codeGenerator.op_jmp(
291 i-compiler.codeGenerator.GetNativeCodeSize(),
292 sizeof(long),
293 false,
294 true
295 );
[254]296 }
[3]297 }
298 else{
299 LineNum=atoi(Parameter);
300 i=GetLabelAddress(0,LineNum);
301
[254]302 if( i == -1 )
303 {
304 //jmp ...(schedule)
305 compiler.codeGenerator.op_jmp_goto_schedule( "", LineNum, cp );
[3]306 }
[254]307 else
308 {
309 //jmp ...
[308]310 compiler.codeGenerator.op_jmp(
311 i-compiler.codeGenerator.GetNativeCodeSize(),
312 sizeof(long),
313 false,
314 true
315 );
[254]316 }
[3]317 }
318}
319void OpcodeWhile(char *Parameter){
320 extern HANDLE hHeap;
321
322 //Continueアドレスのバックアップとセット
[242]323 compiler.codeGenerator.ContinueAreaBegin();
[3]324
[468]325 if(!Parameter[0]) compiler.errorMessenger.Output(10,"While",cp);
[3]326
327 //条件式を実行してフラグをセット
328 Judgment(Parameter);
329
330 //je (Wend まで)
[254]331 const PertialSchedule *pWhilePertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
[3]332
333 //レキシカルスコープをレベルアップ
[308]334 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_WHILE );
[3]335
336 //While内をコンパイル
337 CompileBuffer(0,COM_WEND);
338
[254]339 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
[3]340
341 //jmp ...
[242]342 compiler.codeGenerator.op_jmp_continue();
[3]343
344 //レキシカルスコープをレベルダウン
[254]345 compiler.codeGenerator.lexicalScopes.End();
[3]346
[242]347 compiler.codeGenerator.opfix_JmpPertialSchedule( pWhilePertialSchedule );
[3]348
349 //Continueアドレスを復元
[242]350 compiler.codeGenerator.ContinueAreaEnd();
[3]351}
352
353char szNextVariable[VN_SIZE];
354void OpcodeFor(char *Parameter){
355 extern HANDLE hHeap;
[75]356 Type resultType;
[242]357 int i,i2;
[3]358 char temporary[VN_SIZE],variable[VN_SIZE],JudgeNum[VN_SIZE],StepNum[VN_SIZE];
[34]359 bool isError = false;
[3]360
361 //第1パラメータを取得
362 i=GetOneParameter(Parameter,0,temporary);
363 if(!Parameter[i]){
[468]364 compiler.errorMessenger.Output(12,"For",cp);
[34]365 isError = true;
[3]366 goto ErrorStep;
367 }
368
369 for(i2=0;;i2++){
370 if(temporary[i2]=='='){
371 variable[i2]=0;
372
373 //カウンタ初期化
374 OpcodeCalc(temporary);
375 break;
376 }
377 if(temporary[i2]=='\0'){
[468]378 compiler.errorMessenger.Output(12,"For",cp);
[34]379 isError = true;
[3]380 goto ErrorStep;
381 }
382 variable[i2]=temporary[i2];
383 }
384
385 //jmp ...
[254]386 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
[3]387
388 //Continueアドレスのバックアップとセット
[242]389 compiler.codeGenerator.ContinueAreaBegin();
[3]390
391 //第2パラメータを取得(to~)
392 i=GetOneParameter(Parameter,i,JudgeNum);
393
394 //第3パラメータを取得(step~)
395 if(Parameter[i]){
396 i=GetOneParameter(Parameter,i,StepNum);
[468]397 if(Parameter[i]) compiler.errorMessenger.Output(12,"For",cp);
[3]398 }
399 else lstrcpy(StepNum,"1");
400
401 //カウンタを増加させる
402 sprintf(temporary,"%s=(%s)+(%s)",variable,variable,StepNum);
403 OpcodeCalc(temporary);
404
[242]405 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
[3]406
407 //増加か減少かを区別する
408 sprintf(temporary,"(%s)>=0",StepNum);
409
[75]410 int reg;
[3]411 reg=REG_RAX;
[75]412 if( !NumOpe(&reg,temporary,Type(),resultType) ){
413 return;
414 }
[3]415
416 //cmp rax,0
[226]417 compiler.codeGenerator.op_cmp_value(resultType.GetSize(),REG_RAX,0);
[3]418
419 //je [カウンタ減少の場合の判定]
[242]420 pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
[3]421
422 //判定(カウンタ増加の場合)
423 sprintf(temporary,"%s<=(%s)",variable,JudgeNum);
424
425 reg=REG_RAX;
[75]426 NumOpe(&reg,temporary,Type(),Type());
[3]427
428 //jmp [カウンタ減少の場合の判定を飛び越す]
[254]429 const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
[3]430
[242]431 //jeジャンプ先のオフセット値
432 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
[3]433
434 //判定(カウンタ減少の場合)
435 sprintf(temporary,"%s>=(%s)",variable,JudgeNum);
436
437 reg=REG_RAX;
[75]438 NumOpe(&reg,temporary,Type(),resultType);
[3]439
[242]440 //jmpジャンプ先のオフセット値
441 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
[3]442
443 //cmp rax,0
[226]444 compiler.codeGenerator.op_cmp_value(resultType.GetSize(),REG_RAX,0);
[3]445
446ErrorStep:
447
448 //je ...
[242]449 pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
[3]450
451 //レキシカルスコープをレベルアップ
[308]452 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR );
[3]453
454 //For内をコンパイル
455 CompileBuffer(0,COM_NEXT);
456
[254]457 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
[3]458
459 if(szNextVariable[0]){
460 if(lstrcmp(szNextVariable,variable)!=0){
[468]461 compiler.errorMessenger.Output(55,szNextVariable,cp);
[3]462 }
463 }
464
465 //jmp ...
[242]466 compiler.codeGenerator.op_jmp_continue();
[3]467
468 //レキシカルスコープをレベルダウン
[254]469 compiler.codeGenerator.lexicalScopes.End();
[3]470
[242]471 //jeジャンプ先のオフセット値
472 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
[3]473
474 //Continueアドレスを復元
[242]475 compiler.codeGenerator.ContinueAreaEnd();
[3]476}
477
[372]478void OpcodeForeach( const char *Parameter )
479{
480 Type resultType;
481 char temporary[VN_SIZE],variable[VN_SIZE],collectionVar[VN_SIZE];
482 bool isError = false;
[716]483 std::string elementTypeName;
[372]484
485 //第1パラメータを取得
[381]486 int i = 0;
487 GetCustomToken( variable, Parameter, i, ESC_IN, true );
[372]488 if(!Parameter[i]){
[468]489 compiler.errorMessenger.Output(12,"Foreach",cp);
[372]490 isError = true;
491 goto ErrorStep;
492 }
[381]493 i++;
[372]494
495 //第2パラメータを取得(in~)
[381]496 lstrcpy( collectionVar, Parameter + i );
[372]497
[716]498
499 Exception::TryCommand(); //Finallyで_System_ForeachEnumerator.Disposeするため
500
501 //Enumeratorの取得
502 sprintf(temporary,"_System_ForeachEnumerator=%s.GetEnumerator()", collectionVar );
503 OpcodeDim(temporary,DIMFLAG_INITDEBUGVAR);
504
505 //レキシカルスコープをレベルアップ
506 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR );
507
[375]508 {
509 Type collectionType;
510 if( !NumOpe_GetType( collectionVar, Type(), collectionType ) )
511 {
512 isError = true;
513 goto ErrorStep;
514 }
[720]515
516 Type elementType;
517 if( collectionType.GetClass().IsExpanded() )
518 {
519 // テンプレート展開されたジェネリッククラス
520 elementType = collectionType.GetClass().expandedClassActualTypeParameters[0];
521 }
522 else
523 {
524 // 通常のジェネリッククラス
525 elementType = collectionType.GetActualGenericType(0);
526 }
527
528 elementTypeName = compiler.TypeToString( elementType );
[716]529 }
[375]530
[716]531 if( !GetVarType( variable, resultType, false ) )
532 {
533
[375]534 // 未定義の場合は自動的に定義する
[716]535 sprintf(temporary,"%s=Nothing%c%c%s", variable, 1, ESC_AS, elementTypeName.c_str() );
[375]536 OpcodeDim(temporary,DIMFLAG_INITDEBUGVAR);
537 }
538
[372]539 //Continueアドレスのバックアップとセット
540 compiler.codeGenerator.ContinueAreaBegin();
541
542 // MoveNextメソッドを呼び出す
543 int reg = REG_RAX;
[716]544 NumOpe( &reg, "_System_ForeachEnumerator.MoveNext()", Type(), resultType );
[372]545
546 //cmp rax,0
547 compiler.codeGenerator.op_cmp_value(resultType.GetSize(),REG_RAX,0);
548
549ErrorStep:
550
551 //je ...
552 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
553
[381]554 if( !isError )
555 {
556 // Currentプロパティから現在の値を取得
[716]557 sprintf( temporary, "%s=_System_ForeachEnumerator.Current%c%c%s", variable, 1, ESC_AS, elementTypeName.c_str() );
[381]558 Compile( temporary );
559 }
[372]560
561 //For内をコンパイル
562 CompileBuffer(0,COM_NEXT);
563
564 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
565
566 if(szNextVariable[0]){
567 if(lstrcmp(szNextVariable,variable)!=0){
[468]568 compiler.errorMessenger.Output(55,szNextVariable,cp);
[372]569 }
570 }
571
[381]572 if( !isError )
573 {
574 //jmp ...
575 compiler.codeGenerator.op_jmp_continue();
576 }
[372]577
578 //レキシカルスコープをレベルダウン
579 compiler.codeGenerator.lexicalScopes.End();
580
581 //jeジャンプ先のオフセット値
582 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
583
[716]584 //Disposeを呼んでTryスコープを終える
585 Exception::FinallyCommand();
586 Compile( "_System_ForeachEnumerator.Dispose()" );
587 Exception::EndTryCommand();
588
[372]589 //Continueアドレスを復元
590 compiler.codeGenerator.ContinueAreaEnd();
591}
592
[3]593void OpcodeDo(char *Parameter){
594 extern HANDLE hHeap;
595 int i,i2,i3;
596
[468]597 if(Parameter[0]) compiler.errorMessenger.Output(10,"Do",cp);
[3]598
599 //Continueアドレスのバックアップとセット
[242]600 compiler.codeGenerator.ContinueAreaBegin();
[3]601
602 //レキシカルスコープをレベルアップ
[308]603 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_DO );
[3]604
605 //Do内をコンパイル
606 CompileBuffer(0,COM_LOOP);
607
[254]608 compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
[3]609
[254]610 const PertialSchedule *pDoPertialSchedule = NULL;
[242]611
[3]612 extern char *basbuf;
613 char temporary[VN_SIZE];
614 for(i=cp-1;;i--){
615 if(IsCommandDelimitation(basbuf[i])){
616 i+=3;
617 if(!(basbuf[i]=='0'||basbuf[i]=='1')){
618 //無条件ループ
619 break;
620 }
621 i3=i;
622
623 for(i+=2,i2=0;;i++,i2++){
624 if(IsCommandDelimitation(basbuf[i])){
625 temporary[i2]=0;
626 break;
627 }
628 temporary[i2]=basbuf[i];
629 }
630
631 //条件式を実行してフラグをセット
632 Judgment(temporary);
633
634 if(basbuf[i3]=='0'){
635 //While
636
637 //je 5(ループ終了)
[242]638 pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true );
[3]639 }
640 else if(basbuf[i3]=='1'){
641 //Until
642
643 //jne 5(ループ終了)
[242]644 pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
[3]645 }
646 break;
647 }
648 }
649
650 //jmp ...
[242]651 compiler.codeGenerator.op_jmp_continue();
[3]652
[242]653 if( pDoPertialSchedule )
654 {
655 compiler.codeGenerator.opfix_JmpPertialSchedule( pDoPertialSchedule );
656 }
657
[3]658 //jmp ...
[254]659 const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
[3]660
661 //レキシカルスコープをレベルダウン
[254]662 compiler.codeGenerator.lexicalScopes.End();
[3]663
[243]664 //jmpジャンプ先のオフセット値
665 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
[3]666
667 //Continueアドレスを復元
[242]668 compiler.codeGenerator.ContinueAreaEnd();
[3]669}
670void OpcodeContinue(void){
671 //jmp ...(Continue addr)
[242]672 compiler.codeGenerator.op_jmp_continue();
[3]673}
674
675void OpcodeExitSub(void){
[584]676 if( compiler.IsGlobalAreaCompiling() ){
[468]677 compiler.errorMessenger.Output(12,"Exit Sub/Function",cp);
[3]678 return;
679 }
680
[34]681 //未解放のローカルオブジェクトのデストラクタを呼び出す
[254]682 compiler.codeGenerator.lexicalScopes.CallDestructorsOfReturn();
[34]683
[3]684 //jmp ...(End Sub/Function)
[254]685 compiler.codeGenerator.op_jmp_exitsub();
686}
[3]687
[254]688//Caseスケジュール
689class SelectSchedule
690{
691public:
692 SelectSchedule( int typeSize )
693 : typeSize( typeSize )
694 , nowCaseSchedule( 0 )
695 {
696 }
[3]697
[254]698 PertialSchedules casePertialSchedules;
699 int typeSize;
700 int nowCaseSchedule;
701};
702std::vector<SelectSchedule> selectSchedules;
[3]703
[408]704void OpcodeSelect( const char *lpszParms )
705{
[3]706 extern HANDLE hHeap;
707 extern char *basbuf;
708 int i,i2,i3,NowCaseCp;
709 char temporary[VN_SIZE];
[254]710
[75]711 int reg1=REG_RAX;
712 Type type1;
[408]713 bool result = NumOpe(&reg1,lpszParms,Type(), type1 );
[3]714
[254]715 selectSchedules.push_back( SelectSchedule( type1.GetSize() ) );
716
[408]717 if( result )
718 {
719 if( selectSchedules.back().typeSize < sizeof(long) ){
720 selectSchedules.back().typeSize = sizeof(long);
721 }
[254]722
[408]723 if(type1.IsDouble()){
724 //movsd qword ptr[rsp+offset],xmm_reg ※スタックフレームを利用
725 pobj_sf->push(reg1,sizeof(double));
[3]726 }
[408]727 else if(type1.IsSingle()){
728 //movss dword ptr[rsp+offset],xmm_reg ※スタックフレームを利用
729 pobj_sf->push(reg1,sizeof(float));
[3]730 }
[408]731 else{
732 ExtendTypeTo64(type1.GetBasicType(),reg1);
[3]733
[408]734 //mov qword ptr[rsp+offset],reg ※スタックフレームを利用
735 pobj_sf->push(reg1);
736 }
[3]737
[408]738 for(i=cp;;i++){
739 if(basbuf[i]=='\0'){
740 selectSchedules.pop_back();
[468]741 compiler.errorMessenger.Output(22,"Select",cp);
[408]742 return;
743 }
744 if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE){
745 for(i2=0;;i++){
746 if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE) i2++;
747 if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT){
748 i2--;
749 if(i2==0) break;
[3]750 }
[408]751 }
752 continue;
753 }
754 if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT) break;
[3]755
[408]756 if(basbuf[i]==1&&basbuf[i+1]==ESC_CASE){
757 NowCaseCp=i;
[3]758
[408]759 i++;
760 while(1){
761 for(i++,i2=0;;i++,i2++){
762 if(basbuf[i]=='\"'){
763 i3=GetStringInQuotation(temporary+i2,basbuf+i);
764 i+=i3-1;
765 i2+=i3-1;
766 continue;
767 }
768 if(basbuf[i]=='('){
769 i3=GetStringInPare(temporary+i2,basbuf+i);
770 i+=i3-1;
771 i2+=i3-1;
772 continue;
773 }
774 if(basbuf[i]=='['){
775 i3=GetStringInBracket(temporary+i2,basbuf+i);
776 i+=i3-1;
777 i2+=i3-1;
778 continue;
779 }
[3]780
[408]781 if(IsCommandDelimitation(basbuf[i])){
782 temporary[i2]=0;
783 break;
784 }
785 if(basbuf[i]==','){
786 temporary[i2]=0;
787 break;
788 }
[3]789
[408]790 temporary[i2]=basbuf[i];
791 }
[3]792
[408]793 //エラー用
794 i2=cp;
795 cp=NowCaseCp;
[3]796
[408]797 int reg2=REG_RDX;
798 Type type2;
799 if( !NumOpe(&reg2,temporary,type1,type2) ){
[3]800 return;
801 }
802
[408]803 cp=i2;
[3]804
[408]805 if(type1.IsObject()){
806 std::vector<const UserProc *> subs;
807 type1.GetClass().GetDynamicMethods().Enum( CALC_EQUAL, subs );
808 if( subs.size() == 0 ){
809 return;
810 }
[3]811
[408]812 Parameters params;
813 params.push_back( new Parameter( "", Type( type2 ) ) );
[75]814
[408]815 //オーバーロードを解決
[425]816 const UserProc *pUserProc = OverloadSolution( "==", subs, params, Type( DEF_BOOLEAN ), type1 );
[3]817
[408]818 delete params[0];
[3]819
[408]820 if(!pUserProc){
821 //エラー
822 return;
823 }
[3]824
825
[408]826 //実体オブジェクト
827 if(reg2!=REG_RDX){
828 //mov rdx,reg2
829 compiler.codeGenerator.op_mov_RR(REG_RDX,reg2);
830 }
[3]831
[408]832 //mov rcx,qword ptr[rsp+offset] ※スタックフレームから参照
833 pobj_sf->ref(REG_RCX);
[3]834
[408]835 //call operator_proc ※ ==演算子
836 compiler.codeGenerator.op_call(pUserProc);
[3]837
[408]838 //test rax,rax
839 compiler.codeGenerator.op_test(REG_RAX,REG_RAX);
[3]840
[408]841 //jne ...
842 selectSchedules.back().casePertialSchedules.push_back(
843 compiler.codeGenerator.op_jne( 0, sizeof(long), true )
844 );
[3]845 }
[408]846 else{
847 if(type1.IsDouble()){
848 int xmm_reg;
849 if(IsXmmReg(reg2)) xmm_reg=reg2;
850 else xmm_reg=REG_XMM5;
851 ChangeTypeToXmm_Double(type2.GetBasicType(),xmm_reg,reg2);
[3]852
[408]853 //movsd xmm4,qword ptr[rsp+offset] ※スタックフレームから参照
854 pobj_sf->ref(REG_XMM4,sizeof(double));
[3]855
[408]856 //comiss xmm_reg1,xmm_reg2
857 compiler.codeGenerator.op_comisd(xmm_reg,REG_XMM4);
858 }
859 else if(type1.IsSingle()){
860 int xmm_reg;
861 if(IsXmmReg(reg2)) xmm_reg=reg2;
862 else xmm_reg=REG_XMM5;
863 ChangeTypeToXmm_Single(type2.GetBasicType(),xmm_reg,reg2);
[3]864
[408]865 //movss xmm4,dword ptr[rsp+offset] ※スタックフレームから参照
866 pobj_sf->ref(REG_XMM4,sizeof(float));
[3]867
[408]868 //comiss xmm_reg1,xmm_reg2
869 compiler.codeGenerator.op_comiss(xmm_reg,REG_XMM4);
870 }
871 else{
872 //その他整数型
[3]873
[408]874 i2=NeutralizationType(type1.GetBasicType(),-1,type2.GetBasicType(),-1);
875
876 //mov r14,qword ptr[rsp+offset] ※スタックフレームから参照
877 pobj_sf->ref(REG_R14);
878
879 //cmp reg2,r14
880 compiler.codeGenerator.op_cmp_reg(Type(i2).GetSize(),reg2,REG_R14);
881 }
882
883 //je ...
884 selectSchedules.back().casePertialSchedules.push_back(
885 compiler.codeGenerator.op_je( 0, sizeof(long), true )
886 );
[3]887 }
888
[408]889 if(basbuf[i]!=',') break;
[3]890 }
891 }
[408]892 if(basbuf[i]==1&&basbuf[i+1]==ESC_CASEELSE){
893 //jmp ...
894 selectSchedules.back().casePertialSchedules.push_back(
895 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
896 );
897 }
[3]898 }
[408]899
900 //スタックフレームを1スペースだけ解除
901 pobj_sf->pop(REG_NON);
[3]902 }
903
904 //レキシカルスコープをレベルアップ
[308]905 compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_SELECT );
[3]906
907 //Select Case内をコンパイル
908 CompileBuffer(ESC_ENDSELECT,0);
909
910 //jmp EndSelect
[254]911 selectSchedules.back().casePertialSchedules.push_back(
912 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
913 );
[3]914
915 //最終スケジュール
[254]916 for(i=selectSchedules.back().nowCaseSchedule;i<(int)selectSchedules.back().casePertialSchedules.size();i++){
917 compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[i] );
[3]918 }
919
920 //レキシカルスコープをレベルダウン
[254]921 compiler.codeGenerator.lexicalScopes.End();
[3]922
[254]923 selectSchedules.pop_back();
[3]924}
925void OpcodeCase(char *Parameter){
926 int i;
927
[254]928 if(selectSchedules.back().typeSize==-1){
[468]929 compiler.errorMessenger.Output(30,"Case",cp);
[3]930 return;
931 }
932
933 //jmp EndSelect
[254]934 selectSchedules.back().casePertialSchedules.push_back(
935 compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
936 );
[3]937
938 i=0;
939 while(1){
940 //Caseスケジュール
[254]941 compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[selectSchedules.back().nowCaseSchedule] );
942 selectSchedules.back().nowCaseSchedule++;
[3]943
944 i=JumpOneParameter(Parameter,i);
945 if(Parameter[i]=='\0') break;
946 }
947}
948
949void OpcodeGosub(char *Parameter){
[468]950 compiler.errorMessenger.Output(-1,"Gosub ~ Returnステートメントは64ビットコンパイラで利用することはできません。",cp);
[3]951}
952void OpcodeReturn(char *Parameter){
[584]953 if( compiler.IsGlobalAreaCompiling() ){
[468]954 compiler.errorMessenger.Output(62,NULL,cp);
[3]955 }
956 else{
957 //戻り値をセット
958 if(Parameter[0]){
[584]959 const UserProc &proc = compiler.GetCompilingUserProc();
[3]960
[75]961 const char *temp = "_System_ReturnValue";
962 if(proc.GetName()[0]==1&&proc.GetName()[1]==ESC_OPERATOR)
963 {
[40]964 }
965 else{
[75]966 temp=proc.GetName().c_str();
967 }
968
969 char temporary[VN_SIZE];
970 sprintf(temporary,"%s=%s",temp,Parameter);
971 OpcodeCalc(temporary);
[3]972 }
973
974 //プロシージャを抜け出す(C言語のreturnと同様の処理を行う)
975 OpcodeExitSub();
976 }
977}
978
979
980////////////
981// ポインタ
982////////////
983
984void OpcodeSetPtrData(char *Parameter,int type){
[75]985 int i;
[3]986 char temporary[VN_SIZE];
987
988 if(Parameter[0]=='('){
989 i=JumpStringInPare(Parameter,1);
990 if(Parameter[i+1]=='\0'){
991 for(i=0;;i++){
992 Parameter[i]=Parameter[i+1];
993 if(Parameter[i]=='\0') break;
994 }
995 Parameter[i-1]=0;
996 }
997 }
998
999 //第1パラメータを取得
1000 i=GetOneParameter(Parameter,0,temporary);
1001 if(!Parameter[i]){
[468]1002 compiler.errorMessenger.Output(1,NULL,cp);
[3]1003 return;
1004 }
1005
1006 int reg_ptr=REG_RAX;
[75]1007 Type resultType;
1008 if( !NumOpe(&reg_ptr,temporary,Type(),resultType) ){
1009 return;
1010 }
1011 if(!resultType.IsWhole()){
[468]1012 compiler.errorMessenger.Output(11,Parameter,cp);
[3]1013 return;
1014 }
1015
1016 //結果を格納しているレジスタをブロッキング
1017 pobj_BlockReg->lock(reg_ptr);
1018
1019 //第2パラメータを取得
1020 i=GetOneParameter(Parameter,i,temporary);
1021 if(Parameter[i]){
[468]1022 compiler.errorMessenger.Output(1,NULL,cp);
[3]1023 return;
1024 }
1025
1026 int temp_reg=REG_NON;
[75]1027 if( !NumOpe(&temp_reg,temporary,Type(),resultType) ){
1028 return;
1029 }
[3]1030
1031 //レジスタのブロッキングを解除
1032 pobj_BlockReg->clear();
1033
1034 if(type==DEF_DOUBLE){
[75]1035 ChangeTypeToXmm_Double(resultType.GetBasicType(),REG_XMM0,temp_reg);
[3]1036
1037 //movsd qword ptr[reg_ptr],xmm0
[226]1038 compiler.codeGenerator.op_movsd_MR(REG_XMM0,reg_ptr,0,MOD_BASE);
[3]1039 }
1040 else if(type==DEF_SINGLE){
[75]1041 ChangeTypeToXmm_Single(resultType.GetBasicType(),REG_XMM0,temp_reg);
[3]1042
1043 //movss dword ptr[reg_ptr],xmm0
[226]1044 compiler.codeGenerator.op_movss_MR(REG_XMM0,reg_ptr,0,MOD_BASE);
[3]1045 }
1046 else{
[308]1047 ChangeTypeToWhole(resultType,Type(type),REG_RCX,temp_reg);
[3]1048
1049 //mov ptr[reg_ptr],rcx
[308]1050 compiler.codeGenerator.op_mov_MR(Type(type).GetSize(),REG_RCX,reg_ptr,0,MOD_BASE);
[3]1051 }
1052}
Note: See TracBrowser for help on using the repository browser.