#include "../BasicCompiler_Common/common.h" #include "Opcode.h" void SetVariableFromRax(int VarType,int CalcType,RELATIVE_VAR *pRelativeVar){ ///////////////////////////////////////////////// // raxの内容を変数にコピーするコードを抽出 ///////////////////////////////////////////////// if(VarType==DEF_BOOLEAN){ //bool SetBooleanVariable(CalcType,pRelativeVar); } else if( IsRealNumberType( VarType ) ){ // Double/Single型変数へレジスタの値を代入 SetRealVariable(VarType, CalcType, pRelativeVar); } else if( IsWholeNumberType( VarType ) || VarType == DEF_OBJECT ){ int typeSize = GetTypeSize( VarType, -1 ); //整数変数へraxの値を格納する SetWholeVariable( typeSize, CalcType, pRelativeVar ); } else{ SetError(300,NULL,cp); } } void OpcodeCalc(const char *Command){ int i,i2,i3; char variable[VN_SIZE]; ////////////////////////////////////// // インクリメント・デクリメント ////////////////////////////////////// for(i=0;;i++){ if(Command[i]=='\"'){ //ダブルクォートは不正なのでエラー扱い variable[i]=0; SetError(3,variable,cp); return; } if(Command[i]=='('){ i2=GetStringInPare(variable+i,Command+i); i+=i2-1; continue; } if(Command[i]=='['){ i2=GetStringInBracket(variable+i,Command+i); i+=i2-1; continue; } if(Command[i]=='\0'){ /////////////////////////////////// // インクリメント・デクリメント /////////////////////////////////// if(i>2){ if(Command[i-2]=='+'&&Command[i-1]=='+'){ //インクリメント variable[i-2]=0; IncDec(CALC_ADDITION,variable,"1"); return; } else if(Command[i-2]=='-'&&Command[i-1]=='-'){ //デクリメント variable[i-2]=0; IncDec(CALC_SUBTRACTION,variable,"1"); return; } } //先端部分の識別子をエラーキーワードにする for(i=0;;i++){ if(!IsVariableChar(Command[i])){ variable[i]=0; break; } variable[i]=Command[i]; } if(GetVarType(variable,Type(),0)){ //変数リストに該当したとき SetError(1,NULL,cp); } else{ if(GetConstHash(variable)){ //定数リストに該当したとき SetError(1,NULL,cp); } else{ //変数リスト、定数リストに該当しないとき SetError(3,variable,cp); } } return; } i2=GetCalcId(Command+i,&i3); if(i2){ variable[i]=0; if(Command[i]=='=') break; if(Command[i+1+i3]=='='){ IncDec(i2,variable,Command+i+1+i3+1); return; } } variable[i]=Command[i]; } if(Command[i+1]=='\0'){ SetError(1,NULL,cp); return; } /////////////////////////////////////////////////////////////// // インデクサのsetアクセサ([]=演算子のオーバーロードに対応) /////////////////////////////////////////////////////////////// char ObjName[VN_SIZE],array_element[VN_SIZE]; GetArrayElement(variable,ObjName,array_element); if(array_element[0]){ Type varType; if( GetVarType(ObjName,varType,0) && varType.IsObject() ){ char temporary[VN_SIZE]; sprintf(temporary,"%s.%c%c%c",ObjName,1,ESC_OPERATOR,CALC_ARRAY_SET); char temp2[VN_SIZE]; sprintf(temp2,"%s,%s",array_element,Command+i+1); int idProc; void *pProc; idProc=GetProc(temporary,(void **)&pProc); if(idProc){ CallProc(idProc,pProc,temporary,temp2,Type()); return; } } } if( lstrcmpi( variable, "This" ) == 0 ){ SetError(133,NULL,cp); return; } //////////////////////////////////////// // 変数のタイプ型を識別して、演算を行う //////////////////////////////////////// Type varType; //型を識別 if( !GetVarType(variable,varType,false) ){ // プロパティ用のメソッドを呼び出す if(!CallPropertyMethod( variable, Command+i+1, Type() )){ //エラーを表示 GetVarType(variable,varType,true); } return; } extern LONG_PTR ProcPtr_BaseIndex; if(varType.IsProcPtr()) ProcPtr_BaseIndex=varType.GetIndex(); else ProcPtr_BaseIndex=-1; //NumOpe...(rax、またはxmm0に答えが格納される) int reg=REG_RAX; BOOL bCalcUseHeap; Type calcType; if( !NumOpe(®,Command+i+1,varType,calcType,&bCalcUseHeap) ){ return; } if(reg!=REG_RAX&&calcType.IsWhole()|| varType.IsNull()||calcType.IsNull()){ SetError(300,NULL,cp); } //結果を格納しているレジスタをブロッキング pobj_BlockReg->lock(reg); //変数アドレスを取得 RELATIVE_VAR VarRelativeVar; if(!GetVarOffsetReadWrite( variable, &VarRelativeVar, varType)) return; //レジスタのブロッキングを解除 pobj_BlockReg->clear(); if(varType.GetBasicType()&FLAG_PTR){ SetError(14,variable,cp); return; } if( varType.IsStruct() ){ //構造体インスタンスへの代入 SetStructVariableFromRax(varType,calcType,&VarRelativeVar,bCalcUseHeap); return; } if( calcType.IsObject() && !calcType.Equals( varType ) ){ bool isUpCast = false; if( varType.IsObject() ){ if( varType.GetClass().IsEqualsOrSubClass( &calcType.GetClass() ) ){ isUpCast = true; } } if( !isUpCast ){ //キャスト演算子のオーバーロードに対応する CallCastOperatorProc(REG_RAX,calcType,bCalcUseHeap,varType); } } if( varType.IsObject() && Smoothie::Meta::blittableTypes.IsExist( calcType ) ){ // Blittable型をオブジェクトとして扱う vector userProcs; Smoothie::Meta::blittableTypes.GetClass( calcType ).GetStaticMethods().EnumStatic( "_Create", userProcs ); if( userProcs.size() != 1 ){ SetError(); return; } UserProc *pUserProc = userProcs[0]; // mov rcx, rax op_mov_RR( REG_RCX, REG_RAX ); // call System.[TypeClass]._Create op_call( pUserProc ); calcType = pUserProc->ReturnType(); } ///////////////////////////////// // 右辺、左辺の型チェックを行う ///////////////////////////////// CheckDifferentType(varType,calcType,0,0); ///////////////////////////////////////////////// // rax(実数はxmm0)の内容を変数にコピー ///////////////////////////////////////////////// SetVariableFromRax(varType.GetBasicType(),calcType.GetBasicType(),&VarRelativeVar); }