#include "stdafx.h" #include "Opcode.h" //変数 // TODO: xml未完成 int AllLocalVarSize; using namespace ActiveBasic::Compiler; void SetRelativeOffset( Type &resultType, RELATIVE_VAR *pRelativeVar,const char *lpPtrOffset){ ///////////////////////////////////////////// // 先頭ポインタをr12に取得してメモリへ退避 ///////////////////////////////////////////// SetReg_WholeVariable(Type(DEF_INT64),pRelativeVar,REG_R11); //mov qword ptr[rsp+offset],r11 ※スタックフレームを利用 pobj_sf->push(REG_R11); //////////////////////////////// // 添え字を計算する //////////////////////////////// int reg=REG_NON; Type type; NumOpe( ®, lpPtrOffset, Type(), type ); if( !type.IsWhole() ){ compiler.errorMessenger.Output(46,NULL,cp); } ExtendTypeTo64(type.GetBasicType(),reg); if(reg==REG_R14){ //mov r14,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R14); } if( resultType.PtrLevel() ){ resultType.PtrLevelDown(); int typeSize = resultType.GetSize(); if(typeSize>=2){ //imul reg,i2 compiler.codeGenerator.op_imul_RV(sizeof(_int64),reg,typeSize); } } else{ //エラー compiler.errorMessenger.Output(1,NULL,cp); return; } ////////////////////////////// // 先頭ポインタに添え字を加算 ////////////////////////////// //mov r11,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R11); //add r11,reg compiler.codeGenerator.op_add_RR(REG_R11,reg); } void SetRelativeOffset( RELATIVE_VAR &relativeVar ){ if(relativeVar.dwKind==VAR_DIRECTMEM){ //mov r11,qword ptr[r11] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_R11,0,MOD_BASE); } else{ //直接参照に切り替え SetVarPtrToReg(REG_R12,&relativeVar); relativeVar.dwKind=VAR_DIRECTMEM; //mov r11,qword ptr[r12] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_R12,0,MOD_BASE); } } bool GetArrayOffset(const Subscripts &subscripts,char *array, const Type &type){ extern HANDLE hHeap; int i,i2,i3,i4; char temporary[VN_SIZE],*pParm[MAX_PARMS]; for(i=0,i2=0,i3=0;;i++,i2++){ if(array[i]=='('){ i4=GetStringInPare(temporary+i2,array+i); i+=i4-1; i2+=i4-1; continue; } if(array[i]=='['){ i4=GetStringInBracket(temporary+i2,array+i); i+=i4-1; i2+=i4-1; continue; } if(array[i]==','||array[i]=='\0'){ if( i3 >= (int)subscripts.size() ) { for(i3--;i3>=0;i3--) HeapDefaultFree(pParm[i3]); return false; } temporary[i2]=0; pParm[i3]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1); lstrcpy(pParm[i3],temporary); i3++; if(array[i]=='\0'){ if( i3 < (int)subscripts.size() ) { for(i3--;i3>=0;i3--) HeapDefaultFree(pParm[i3]); return false; } break; } i2=-1; continue; } temporary[i2]=array[i]; } //mov qword ptr[rsp+offset],r11 ※スタックフレームを利用 pobj_sf->push(REG_R11); //xor r12,r12 compiler.codeGenerator.op_zero_reg(REG_R12); for(i=i3-1;i>=0;i--){ //mov qword ptr[rsp+offset],r12 ※スタックフレームを利用 pobj_sf->push(REG_R12); int reg=REG_NON; Type type; bool isNeedHeapFreeStructure; NumOpe( ®, pParm[i], Type( DEF_LONG ), type, &isNeedHeapFreeStructure ); if( type.IsObject() ) { //キャスト演算子のオーバーロードに対応する CallCastOperatorProc(reg, type, isNeedHeapFreeStructure, Type(DEF_LONG) ); type.SetBasicType( DEF_LONG ); } if( !type.IsWhole() ) { compiler.errorMessenger.Output(46,NULL,cp); } ExtendTypeTo64( type.GetBasicType(), reg ); if(reg==REG_R14){ //mov r14,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R14); } //mov r12,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_R12); for(i2=i+1,i4=1;i2pop(REG_R11); //add r11,r12 compiler.codeGenerator.op_add_RR( REG_R11, REG_R12 ); return true; } bool _member_offset(bool isErrorEnabled, bool isWriteAccess, const Type &classType, const char *member, RELATIVE_VAR *pRelativeVar, Type &resultType, BOOL bPrivateAccess) { const CClass &objClass = classType.GetClass(); ////////////////////////////////////// // クラス、配列の構成要素を解析する ////////////////////////////////////// char VarName[VN_SIZE]; //変数名 char array[VN_SIZE]; //第1次配列 char lpPtrOffset[VN_SIZE]; //第2次配列 char NestMember[VN_SIZE]; //入れ子メンバ ReferenceKind refType; lstrcpy(VarName,member); if(!GetVarFormatString(VarName,array,lpPtrOffset,NestMember,refType)) return false; //////////////////////////// // メンバオフセットを取得 //////////////////////////// const Member *pMember = objClass.FindDynamicMember( VarName ); if( !pMember ) { if(isErrorEnabled) compiler.errorMessenger.Output(103,VarName,cp); return false; } int offset = objClass.GetMemberOffset( VarName ); //アクセシビリティをチェック if( compiler.IsCompilingClass() && &objClass == &compiler.GetCompilingClass() ){ //同一クラスオブジェクトの場合はプライベートアクセスを容認する if(pMember->IsNoneAccess()){ if(isErrorEnabled) compiler.errorMessenger.Output(107,VarName,cp); return false; } } else{ if((bPrivateAccess==0&&pMember->IsPrivate())|| pMember->IsNoneAccess()){ if(isErrorEnabled) compiler.errorMessenger.Output(107,VarName,cp); return false; } else if(bPrivateAccess==0&&pMember->IsProtected()){ if(isErrorEnabled) compiler.errorMessenger.Output(108,VarName,cp); return false; } } //Const定義の場合は書き込みアクセスを制限する //※コンストラクタをコンパイル中の場合は例外的に許可する if( pMember->IsConst() && //定数メンバである isWriteAccess && //書き込みアクセスを要求されている objClass.IsCompilingConstructor() == false //コンストラクタ コンパイル中を除く ){ //Const定義の変数に書き込みアクセスをしようとした場合 compiler.errorMessenger.Output(61,VarName,cp); } resultType = pMember->GetType(); // 型パラメータを解決 ResolveFormalGenericTypeParameter( resultType, classType ); //ポインタ変数の場合 if( resultType.IsPointer() ){ if( pMember->GetSubscripts().size() == 0 ){ lstrcpy(lpPtrOffset,array); array[0]=0; } } else{ if(lpPtrOffset[0]){ if(isErrorEnabled) compiler.errorMessenger.Output(16,member,cp); return false; } } if(offset){ //add r11,offset compiler.codeGenerator.op_add_RV( REG_R11, offset ); } if(array[0]){ //配列オフセット if(!GetArrayOffset(pMember->GetSubscripts(),array,pMember->GetType())){ if(isErrorEnabled) compiler.errorMessenger.Output(14,member,cp); return false; } } else if( pMember->GetSubscripts().size() > 0 ){ resultType.SetBasicType( resultType.GetBasicType() | FLAG_PTR ); } if(NestMember[0]){ //入れ子構造の場合 if( resultType.IsObject() || resultType.IsStruct() ){ if( refType != RefDot ){ if(isErrorEnabled) compiler.errorMessenger.Output(104,member,cp); return false; } if( resultType.IsObject() ){ // 参照内容へのポインタを抽出 SetRelativeOffset( *pRelativeVar ); } } else if( resultType.IsObjectPtr() || resultType.IsStructPtr() ){ //構造体ポインタ型メンバ変数 if(lpPtrOffset[0]){ //pObj[n].member if( ( resultType.IsObjectPtr() || resultType.IsStructPtr() ) && refType != RefDot ){ if(isErrorEnabled) compiler.errorMessenger.Output(104,member,cp); return false; } //直接参照に切り替え SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset); pRelativeVar->dwKind=VAR_DIRECTMEM; lpPtrOffset[0]=0; } else{ //pObj->member if( (resultType.IsObjectPtr() || resultType.IsStructPtr() ) && refType != RefPointer ){ if(isErrorEnabled) compiler.errorMessenger.Output(104,member,cp); return false; } SetRelativeOffset( *pRelativeVar ); } } else if( resultType.GetBasicType() == MAKE_PTR_TYPE(DEF_OBJECT,2) || resultType.GetBasicType() == MAKE_PTR_TYPE(DEF_STRUCT,2)){ //構造体ポインタのポインタ型メンバ変数 if(lpPtrOffset[0]){ //ppObj[n]->member if( refType != RefPointer ){ if(isErrorEnabled) compiler.errorMessenger.Output(104,member,cp); return false; } //直接参照に切り替え SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset); pRelativeVar->dwKind=VAR_DIRECTMEM; lpPtrOffset[0]=0; //mov r11,qword ptr[r11] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_R11,0,MOD_BASE); } else{ if(isErrorEnabled) compiler.errorMessenger.Output(104,member,cp); return false; } } if(!_member_offset( isErrorEnabled, isWriteAccess, pMember->GetType(), NestMember, pRelativeVar, resultType, 0)) return false; } if(lpPtrOffset[0]){ SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset); pRelativeVar->dwKind=VAR_DIRECTMEM; } return true; } int LocalVar_ThisPtrOffset; void SetThisPtrToReg(int reg){ //自身のオブジェクトのThisポインタをregにコピー RELATIVE_VAR RelativeVar; RelativeVar.dwKind=VAR_LOCAL; RelativeVar.bOffsetOffset=0; RelativeVar.offset=-LocalVar_ThisPtrOffset; SetReg_WholeVariable(Type(DEF_PTR_VOID),&RelativeVar,reg); } bool GetVarOffset(bool isErrorEnabled,bool isWriteAccess,const char *NameBuffer,RELATIVE_VAR *pRelativeVar,Type &resultType, Subscripts *pResultSubscripts ){ char variable[VN_SIZE]; if(NameBuffer[0]=='.'){ GetWithName(variable); lstrcat(variable,NameBuffer); } else lstrcpy(variable,NameBuffer); // 名前空間を分離 char namespaceStr[VN_SIZE]="", simpleName[VN_SIZE]; compiler.GetObjectModule().meta.GetNamespaces().SplitNamespace( variable, namespaceStr, simpleName ); // 先頭オブジェクトまたはクラス名と入れ子メンバに分割 ReferenceKind refType; char member[VN_SIZE],array[VN_SIZE],lpPtrOffset[VN_SIZE]; GetVarFormatString(simpleName,array,lpPtrOffset,member,refType); // 名前空間を分離していた場合は結合 char VarName[VN_SIZE]; if( namespaceStr[0] ){ sprintf( VarName, "%s.%s", namespaceStr, simpleName ); } else{ lstrcpy( VarName, simpleName ); } const Subscripts *pSubscripts; bool bConst = false; if( compiler.IsLocalAreaCompiling() ){ ////////////////// // ローカル変数 ////////////////// const Variable *pVar = compiler.GetCompilingUserProc().GetLocalVars().BackSearch( LexicalAnalyzer::FullNameToSymbol( VarName ), compiler.codeGenerator.lexicalScopes.GetNowLevel() ); if( pVar ){ //ポインタ変数の場合 if( pVar->GetType().IsPointer() ){ if( !pVar->IsArray() ){ lstrcpy(lpPtrOffset,array); array[0]=0; } } else{ if(lpPtrOffset[0]){ compiler.errorMessenger.Output(16,variable,cp); pRelativeVar->dwKind=NON_VAR; return false; } } pRelativeVar->offset=-pVar->GetOffsetAddress(); pRelativeVar->bOffsetOffset=0; if( pVar->IsRef() || pVar->IsByValStructParameter() ) { // 参照型 pRelativeVar->dwKind = VAR_REFLOCAL; } else pRelativeVar->dwKind=VAR_LOCAL; resultType = pVar->GetType(); pSubscripts = &pVar->GetSubscripts(); bConst = pVar->IsConst(); ///////////////////////////////////////////////////////// // ☆★☆ ジェネリクスサポート ☆★☆ if( resultType.IsTypeParameter() ) { // 型パラメータだったとき int ptrLevel = PTR_LEVEL( resultType.GetBasicType() ); // 制約クラス(指定されていないときはObjectクラス)にセットする resultType.SetBasicType( DEF_OBJECT ); for( int i=0; idwKind=VAR_DIRECTMEM; resultType.SetType( DEF_OBJECT, &compiler.GetCompilingClass() ); return true; } if(memicmp(variable,"This.",5)==0){ //Thisオブジェクトのメンバを参照するとき SlideString(variable+5,-5); lstrcpy(VarName,variable); } else{ //クラス内の動的メンバを参照するとき(通常) if( !compiler.GetCompilingClass().HasDynamicMember( VarName ) ) { goto NonClassMember; } } //Const修飾子のメソッド内でメンバ書き込みアクセスが発生したとき //(コンストラクタ、デストラクタ内を除く) const CMethod *pMethod = &compiler.GetCompilingUserProc().GetMethod(); if( isWriteAccess && pMethod->IsConst() && compiler.GetCompilingClass().IsCompilingConstructor() == false && compiler.GetCompilingClass().IsCompilingDestructor() == false ){ compiler.errorMessenger.Output(131, NULL, cp ); } //自身のオブジェクトのThisポインタをr11にコピー SetThisPtrToReg(REG_R11); pRelativeVar->dwKind=VAR_DIRECTMEM; if(!_member_offset( isErrorEnabled, isWriteAccess, Type( DEF_OBJECT, compiler.GetCompilingClass() ), variable, pRelativeVar, resultType,1)) return false; return true; } NonClassMember: { const Variable *pVar; ////////////////////////// // 静的ローカル変数 // ※"Static.Object.Method.Variable" ////////////////////////// char temporary[VN_SIZE]; if( compiler.IsLocalAreaCompiling() ){ GetNowStaticVarFullName(VarName,temporary); pVar = compiler.GetObjectModule().meta.GetGlobalVars().Find( LexicalAnalyzer::FullNameToSymbol( temporary ) ); if( pVar ){ goto GlobalOk; } } ////////////////////////// // クラスの静的メンバ ////////////////////////// if(member[0]){ lstrcpy(temporary,member); // TODO: 名前空間を考慮したコードになっていない char tempMember[VN_SIZE]; char tempArray[VN_SIZE]; { ReferenceKind refType; GetVarFormatString(temporary,tempArray,lpPtrOffset,tempMember, refType ); } const TypeDef *pTypeDef = compiler.GetObjectModule().meta.GetTypeDefs().Find( LexicalAnalyzer::FullNameToSymbol( VarName ) ); if( pTypeDef ) { // TypeDef後の型名だったとき lstrcpy( VarName, pTypeDef->GetBaseName().c_str() ); } char temp2[VN_SIZE]; sprintf(temp2,"%s.%s",VarName,temporary); pVar = compiler.GetObjectModule().meta.GetGlobalVars().Find( LexicalAnalyzer::FullNameToSymbol( temp2 ) ); if( pVar ){ lstrcpy(member,tempMember); lstrcpy(array,tempArray); goto GlobalOk; } } if( compiler.IsCompilingClass() ){ //自身のクラスから静的メンバを参照する場合 char temp2[VN_SIZE]; sprintf(temp2,"%s.%s",compiler.GetCompilingClass().GetName().c_str(),VarName); pVar = compiler.GetObjectModule().meta.GetGlobalVars().Find( LexicalAnalyzer::FullNameToSymbol( temp2 ) ); if( pVar ){ goto GlobalOk; } } ///////////////////// // グローバル変数 ///////////////////// pVar = compiler.GetObjectModule().meta.GetGlobalVars().BackSearch( LexicalAnalyzer::FullNameToSymbol( VarName ), compiler.codeGenerator.lexicalScopes.GetNowLevel() ); if( pVar ){ goto GlobalOk; } if(isErrorEnabled) compiler.errorMessenger.Output(3,variable,cp); pRelativeVar->dwKind=NON_VAR; return false; GlobalOk: //ポインタ変数の場合 if( pVar->GetType().IsPointer() ){ if( !pVar->IsArray() ){ lstrcpy(lpPtrOffset,array); array[0]=0; } } else{ if(lpPtrOffset[0]){ compiler.errorMessenger.Output(16,variable,cp); pRelativeVar->dwKind=NON_VAR; return false; } } pRelativeVar->offset=pVar->GetOffsetAddress(); pRelativeVar->bOffsetOffset=0; if( pVar->IsRef() ){ // 参照型 pRelativeVar->dwKind = VAR_REFGLOBAL; } else pRelativeVar->dwKind=VAR_GLOBAL; resultType = pVar->GetType(); pSubscripts=&pVar->GetSubscripts(); bConst = pVar->IsConst(); } ok: if( bConst && isWriteAccess ){ //Const定義の変数に書き込みアクセスをしようとした場合 if( resultType.IsObject() ){ //オブジェクト定数 compiler.errorMessenger.Output(130, VarName, cp ); } else{ //一般のConst変数 compiler.errorMessenger.Output(61,VarName,cp); } } if( array[0] == 0 && pSubscripts->size() > 0 ){ //配列の先頭ポインタを示す場合 resultType.SetBasicType( resultType.GetBasicType() | FLAG_PTR ); if( pResultSubscripts ) { (*pResultSubscripts) = *pSubscripts; } return true; } if( array[0] || member[0] ){ //xor r11,r11(r11を0に初期化する) //※r11は変数ベースアドレスからの相対オフセットを示す compiler.codeGenerator.op_zero_reg(REG_R11); pRelativeVar->bOffsetOffset=1; } if(array[0]){ if(!GetArrayOffset(*pSubscripts,array,resultType)){ compiler.errorMessenger.Output(14,variable,cp); pRelativeVar->dwKind=NON_VAR; return false; } } if(member[0]){ if( resultType.IsObject() || resultType.IsStruct() ){ //実態オブジェクトのメンバを参照(obj.member) if( refType != RefDot ){ compiler.errorMessenger.Output(104,VarName,cp); pRelativeVar->dwKind=NON_VAR; return false; } if( resultType.IsObject() ){ // 参照内容へのポインタを抽出 SetRelativeOffset( *pRelativeVar ); } } else if( resultType.IsObjectPtr() || resultType.IsStructPtr() ){ //ポインタオブジェクトが示すメンバを参照 if(lpPtrOffset[0]){ //pObj[n].member if( refType != RefDot ){ compiler.errorMessenger.Output(104,VarName,cp); pRelativeVar->dwKind=NON_VAR; return false; } SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset); pRelativeVar->dwKind=VAR_DIRECTMEM; } else{ //pObj->member if( refType != RefPointer ){ compiler.errorMessenger.Output(104,VarName,cp); pRelativeVar->dwKind=NON_VAR; return false; } SetVarPtrToReg(REG_R12,pRelativeVar); pRelativeVar->dwKind=VAR_DIRECTMEM; //mov r11,qword ptr[r12] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_R12,0,MOD_BASE); } } else if( resultType.GetBasicType()==MAKE_PTR_TYPE(DEF_OBJECT,2) || resultType.GetBasicType()==MAKE_PTR_TYPE(DEF_STRUCT,2)){ //ポインタオブジェクトが示すメンバを参照 if(lpPtrOffset[0]){ //ppObj[n]->member if( refType != RefPointer ){ compiler.errorMessenger.Output(104,VarName,cp); pRelativeVar->dwKind=NON_VAR; return false; } SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset); pRelativeVar->dwKind=VAR_DIRECTMEM; SetVarPtrToReg(REG_R12,pRelativeVar); //mov r11,qword ptr[r12] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_R12,0,MOD_BASE); } else{ compiler.errorMessenger.Output(104,VarName,cp); pRelativeVar->dwKind=NON_VAR; return false; } } else{ compiler.errorMessenger.Output(102,VarName,cp); pRelativeVar->dwKind=NON_VAR; return false; } if(!_member_offset( isErrorEnabled, isWriteAccess, resultType, member,pRelativeVar,resultType,0)) return false; return true; } if(lpPtrOffset[0]){ SetRelativeOffset(resultType,pRelativeVar,lpPtrOffset); pRelativeVar->dwKind=VAR_DIRECTMEM; } return true; } bool SetInitGlobalData(int offset,const Type &type,const Subscripts &subscripts,const char *lpszInitBuf){ int i2,i3; char temporary[VN_SIZE]; char InitBuf[VN_SIZE]; lstrcpy( InitBuf, lpszInitBuf ); if(InitBuf[0]=='['){ SlideString(InitBuf+1,-1); InitBuf[lstrlen(InitBuf)-1]=0; int typeSize = type.GetSize(); if( subscripts.size() > 0 ){ Subscripts nestSubscripts; for( int i=1; i<(int)subscripts.size(); i++ ) { nestSubscripts.push_back( subscripts[i] ); } typeSize*=JumpSubScripts( nestSubscripts ); { int i=0; i2=0; while(1){ if( subscripts[0] < i2 ){ compiler.errorMessenger.Output(41,0,cp); return 0; } i=GetOneParameter(InitBuf,i,temporary); if(!SetInitGlobalData( offset+i2*typeSize, type, nestSubscripts, temporary)) return false; i2++; if(InitBuf[i]=='\0') break; } } return true; } if(type.IsStruct()){ const CClass &objClass = type.GetClass(); int i = 0; BOOST_FOREACH( Member *pMember, objClass.GetDynamicMembers() ){ if(InitBuf[i]=='\0'){ compiler.errorMessenger.Output(41,0,cp); return false; } i=GetOneParameter(InitBuf,i,temporary); i3=objClass.GetMemberOffset( pMember->GetName().c_str() ); if(!SetInitGlobalData(offset+i3, pMember->GetType(), pMember->GetSubscripts(), temporary)) return false; } return true; } compiler.errorMessenger.Output(41,0,cp); return false; } /////////////////////////////////////// // 単発式([]で囲まれていない) /////////////////////////////////////// if( subscripts.size() > 0 ){ compiler.errorMessenger.Output(41,0,cp); return false; } double dbl; _int64 i64data; Type calcType; if( !StaticCalculation(false, InitBuf,type.GetBasicType(),&i64data,calcType) ){ //動的データだった場合 return false; } if( calcType.IsReal() ){ memcpy(&dbl,&i64data,sizeof(double)); i64data=(_int64)dbl; } else dbl=(double)i64data; //型チェック CheckDifferentType( type, calcType, 0,0); if( type.IsDouble() ){ compiler.GetObjectModule().meta.GetGlobalVars().initAreaBuffer.Overwrite( offset, (const char *)&dbl, sizeof(double) ); } else if( type.IsSingle() ){ float flt = (float)dbl; compiler.GetObjectModule().meta.GetGlobalVars().initAreaBuffer.Overwrite( offset, (const char *)&flt, sizeof(float) ); } else if( type.Is64() || type.IsPointer() ){ if( type.GetBasicType() == typeOfPtrChar && type.GetIndex() == LITERAL_STRING ){ //文字列定数のとき char *temp; temp=(char *)i64data; if( compiler.IsUnicode() ) { i2 = compiler.GetObjectModule().dataTable.AddWString( Jenga::Common::ToWString( temp ) ); } else { i2 = compiler.GetObjectModule().dataTable.AddString( temp ); } HeapDefaultFree(temp); //mov rax,DataPos compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,i2, Schedule::DataTable ); //mov qword ptr[offset],rax compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RAX,0,offset,MOD_DISP32, Schedule::GlobalVar ); } else{ compiler.GetObjectModule().meta.GetGlobalVars().initAreaBuffer.Overwrite( offset, (const char *)&i64data, sizeof(_int64) ); } } else if( type.IsDWord() || type.IsLong() ){ long l = (long)i64data; compiler.GetObjectModule().meta.GetGlobalVars().initAreaBuffer.Overwrite( offset, (const char *)&l, sizeof(long) ); } else if( type.IsWord() || type.IsInteger() ){ short s = (short)i64data; compiler.GetObjectModule().meta.GetGlobalVars().initAreaBuffer.Overwrite( offset, (const char *)&s, sizeof(short) ); } else if( type.IsSByte() || type.IsByte() || type.IsBoolean() ){ char c = (char)i64data; compiler.GetObjectModule().meta.GetGlobalVars().initAreaBuffer.Overwrite( offset, (const char *)&c, sizeof(char) ); } return true; } bool InitLocalVar(int offset,const Type &type,const Subscripts &subscripts,const char *lpszInitBuf){ int i2,i3; char temporary[VN_SIZE]; char InitBuf[VN_SIZE]; lstrcpy( InitBuf, lpszInitBuf ); if(InitBuf[0]=='['){ SlideString(InitBuf+1,-1); InitBuf[lstrlen(InitBuf)-1]=0; int typeSize = type.GetSize(); if( subscripts.size() > 0 ){ Subscripts nestSubscripts; for( int i=1; i<(int)subscripts.size(); i++ ) { nestSubscripts.push_back( subscripts[i] ); } typeSize*=JumpSubScripts( nestSubscripts ); { int i=0; i2=0; while(1){ if( subscripts[0] < i2 ){ compiler.errorMessenger.Output(41,0,cp); return 0; } i=GetOneParameter(InitBuf,i,temporary); if(!InitLocalVar( offset+i2*typeSize, type, nestSubscripts, temporary)) return false; i2++; if(InitBuf[i]=='\0') break; } } return true; } if(type.IsStruct()){ const CClass &objClass = type.GetClass(); int i = 0; BOOST_FOREACH( Member *pMember, objClass.GetDynamicMembers() ){ if(InitBuf[i]=='\0'){ compiler.errorMessenger.Output(41,0,cp); return false; } i=GetOneParameter(InitBuf,i,temporary); i3=objClass.GetMemberOffset( pMember->GetName().c_str() ); if(!InitLocalVar(offset+i3, pMember->GetType(), pMember->GetSubscripts(), temporary)) return false; if(InitBuf[i]=='\0') break; } return true; } compiler.errorMessenger.Output(41,0,cp); return false; } /////////////////////////////////////// // 単発式([]で囲まれていない) /////////////////////////////////////// if( subscripts.size() > 0 ){ compiler.errorMessenger.Output(41,0,cp); return false; } double dbl; _int64 i64data; Type calcType; if( !StaticCalculation(false, InitBuf,type.GetBasicType(),&i64data,calcType) ){ //動的データだった場合 return false; } if( calcType.IsReal() ){ memcpy(&dbl,&i64data,sizeof(double)); i64data=(_int64)dbl; } else dbl=(double)i64data; //型チェック CheckDifferentType( type, calcType, 0,0); if( type.IsDouble() ){ memcpy(&i64data,&dbl,sizeof(double)); //mov rax,i64data compiler.codeGenerator.op_mov_RV64(REG_RAX,i64data); //mov qword ptr[rsp+offset],rax compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RAX,REG_RSP,offset,MOD_BASE_DISP32, Schedule::None, true ) ); } else if( type.IsSingle() ){ float flt; flt=(float)dbl; //mov dword ptr[rsp+offset],value compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MV(sizeof(long),REG_RSP,offset, Schedule::None, true, USE_OFFSET,*(int *)&flt) ); } else if( type.Is64() || type.IsPointer() ){ if( type.GetBasicType() == typeOfPtrChar && type.GetIndex() == LITERAL_STRING ){ //文字列定数のとき char *temp; temp=(char *)i64data; if( compiler.IsUnicode() ) { i2 = compiler.GetObjectModule().dataTable.AddWString( Jenga::Common::ToWString( temp ) ); } else { i2 = compiler.GetObjectModule().dataTable.AddString( temp ); } HeapDefaultFree(temp); //mov rax,i2 compiler.codeGenerator.op_mov_RV(sizeof(_int64),REG_RAX,i2, Schedule::DataTable ); //mov qword ptr[rsp+offset],rax compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RAX,REG_RSP,offset,MOD_BASE_DISP32, Schedule::None, true ) ); } else{ if(i64data&0xFFFFFFFF00000000){ //mov rax,i64data compiler.codeGenerator.op_mov_RV64(REG_RAX,i64data); //mov qword ptr[rsp+offset],rax compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MR(sizeof(_int64),REG_RAX,REG_RSP,offset,MOD_BASE_DISP32, Schedule::None, true ) ); } else{ //mov qword ptr[rsp+offset],value compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MV(sizeof(_int64),REG_RSP,offset, Schedule::None, true, USE_OFFSET,(int)i64data) ); } } } else if( type.IsDWord() || type.IsLong() ){ //mov dword ptr[rsp+offset],value compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MV(sizeof(long),REG_RSP,offset, Schedule::None, true, USE_OFFSET,(int)i64data) ); } else if( type.IsWord() || type.IsInteger() ){ //mov word ptr[rsp+offset],value compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MV(sizeof(short),REG_RSP,offset, Schedule::None, true, USE_OFFSET,(int)i64data) ); } else if( type.IsSByte() || type.IsByte() || type.IsBoolean() ){ //mov byte ptr[rsp+offset],value compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MV(sizeof(char),REG_RSP,offset, Schedule::None, true, USE_OFFSET,(int)i64data) ); } return true; } void dim( char *VarName, const Subscripts &subscripts, const Type &type,const char *InitBuf,const char *ConstractParameter,DWORD dwFlags) { if( compiler.IsGlobalAreaCompiling() ){ ///////////////////////// // グローバル変数 ///////////////////////// AddGlobalVariable(VarName,subscripts,type,InitBuf,ConstractParameter,dwFlags); } else{ ///////////////// // ローカル変数 ///////////////// if( compiler.GetCompilingUserProc().GetLocalVars().DuplicateCheck( LexicalAnalyzer::FullNameToSymbol( VarName ), compiler.codeGenerator.lexicalScopes.GetNowLevel() ) ){ //2重定義のエラー compiler.errorMessenger.Output(15,VarName,cp); return; } bool isConst = ( dwFlags & DIMFLAG_CONST ) ? true:false; Variable *pVar = new Variable( ActiveBasic::Compiler::LexicalAnalyzer::FullNameToSymbol( VarName ), type, isConst, false, ConstractParameter, false ); if( subscripts.size() > 0 ){ //配列あり pVar->SetArray( subscripts ); } //レキシカルスコープ pVar->SetScopeLevel( compiler.codeGenerator.lexicalScopes.GetNowLevel() ); pVar->SetScopeStartAddress( compiler.codeGenerator.lexicalScopes.GetStartAddress() ); pVar->isLiving = true; //エラー用 pVar->source_code_address=cp; // 変数を追加 compiler.GetCompilingUserProc().GetLocalVars().push_back( pVar ); //アラインメントを考慮 if( pVar->GetType().IsStruct() ){ int alignment = pVar->GetType().GetClass().GetFixedAlignment(); if( alignment ){ if( AllLocalVarSize % alignment ){ AllLocalVarSize += alignment - (AllLocalVarSize % alignment); } } if( alignment == PTR_SIZE*2 ){ // ポインタに要するサイズよりも一回り大きなアラインメントが指定されているとき // (例:CONTEXT構造体など) // 呼び出し側のオフセットズレを考慮する if( 0 == ( compiler.GetCompilingUserProc().RealParams().GetMemorySize() + PTR_SIZE /* ret分 */ ) % alignment ){ AllLocalVarSize += PTR_SIZE; } } } AllLocalVarSize += pVar->GetMemorySize(); pVar->SetOffsetAddress( AllLocalVarSize ); //レキシカルスコープ pVar->SetScopeLevel( compiler.codeGenerator.lexicalScopes.GetNowLevel() ); pVar->SetScopeStartAddress( compiler.codeGenerator.lexicalScopes.GetStartAddress() ); pVar->isLiving = true; if(InitBuf[0]){ //初期代入時のみ、書き込みアクセスを許可する if( isConst ){ pVar->ConstOff(); } int result = 0; if( !pVar->GetType().IsObject() ){ result = InitLocalVar(-pVar->GetOffsetAddress(), pVar->GetType(), pVar->GetSubscripts(), InitBuf); } if(!result){ //動的な式だった場合は代入演算を行う char temporary[8192]; sprintf(temporary,"%s=%s",VarName,InitBuf); OpcodeCalc(temporary); } if( isConst ){ pVar->ConstOn(); } } else{ //0初期化 //mov r8, 0 compiler.codeGenerator.op_zero_reg( REG_R8 ); //mov rdx, VarSize compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RDX, pVar->GetMemorySize() ); //mov rcx, rsp compiler.codeGenerator.op_mov_RR( REG_RCX, REG_RSP ); //add rcx, offset compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_add_RV( REG_RCX, -pVar->GetOffsetAddress(), Schedule::None, true ) ); //call FillMemory DllProc *pDllProc; pDllProc=GetDeclareHash("FillMemory"); compiler.codeGenerator.op_call( pDllProc ); } } //New呼び出し if( type.IsObject() && !type.IsInterface() && !type.IsComInterface() &&(dwFlags&DIMFLAG_NONCALL_CONSTRACTOR)==0 &&InitBuf[0]=='\0') { char objectSize[255]; if( subscripts.size() == 0 ){ objectSize[0] = 0; } else{ if( subscripts.size() > 1 ){ compiler.errorMessenger.Output(300,NULL,cp); } sprintf( objectSize, "%d", subscripts[0] ); } Operator_New( type.GetClass(), objectSize, ConstractParameter, type ); Type tempType; RELATIVE_VAR RelativeVar; GetVarOffset( true, false, VarName, &RelativeVar, tempType ); if( RelativeVar.dwKind == VAR_DIRECTMEM ){ compiler.errorMessenger.OutputFatalError(); } SetVariableFromRax( Type( DEF_OBJECT, *compiler.GetObjectModule().meta.GetClasses().GetObjectClassPtr() ), DEF_OBJECT, &RelativeVar ); } } void SetVarPtrToReg(int reg,RELATIVE_VAR *pRelativeVar){ if(!IsGeneralReg(reg)) compiler.errorMessenger.Output(300,NULL,cp); if(pRelativeVar->dwKind==VAR_GLOBAL){ if(pRelativeVar->bOffsetOffset){ //add r11,offset compiler.codeGenerator.op_add_RV( REG_R11, (long)pRelativeVar->offset, Schedule::GlobalVar ); //mov reg,r11 compiler.codeGenerator.op_mov_RR(reg,REG_R11); } else{ //mov reg,offset compiler.codeGenerator.op_mov_RV( sizeof(_int64), reg, (long)pRelativeVar->offset, Schedule::GlobalVar ); } } else if( pRelativeVar->dwKind == VAR_REFGLOBAL ){ if(pRelativeVar->bOffsetOffset){ //add r11,qword ptr[offset] compiler.codeGenerator.op_add_RM( sizeof(_int64), REG_R11, REG_NON, (int)pRelativeVar->offset, MOD_DISP32, Schedule::GlobalVar ); } else{ //mov r11,qword ptr[offset] compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_NON,(int)pRelativeVar->offset,MOD_DISP32, Schedule::GlobalVar ); } goto directmem; } else if(pRelativeVar->dwKind==VAR_LOCAL){ if(pRelativeVar->bOffsetOffset){ //add r11,offset compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_add_RV( REG_R11, (long)pRelativeVar->offset, Schedule::None, true ) ); //add r11,rsp compiler.codeGenerator.op_add_RR(REG_R11,REG_RSP); //mov reg,r11 compiler.codeGenerator.op_mov_RR(reg,REG_R11); } else{ //mov reg,rsp compiler.codeGenerator.op_mov_RR(reg,REG_RSP); //add reg,offset compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_add_RV(reg,(long)pRelativeVar->offset, Schedule::None, true ) ); } } else if( pRelativeVar->dwKind == VAR_REFLOCAL ){ if(pRelativeVar->bOffsetOffset){ //add r11,qword ptr[rsp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_add_RM( sizeof(_int64), REG_R11, REG_RSP, (long)pRelativeVar->offset, MOD_BASE_DISP32, Schedule::None, true ) ); } else{ //mov r11,qword ptr[rsp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_RM(sizeof(_int64),REG_R11,REG_RSP,(int)pRelativeVar->offset,MOD_BASE_DISP32, Schedule::None, true ) ); } goto directmem; } else if(pRelativeVar->dwKind==VAR_DIRECTMEM){ directmem: //mov reg,r11 compiler.codeGenerator.op_mov_RR(reg,REG_R11); } } bool Compile_AddGlobalRootsForGc() { const UserProc *pUserProc_AddGlobalRootPtr = GetClassMethod( "_System_CGarbageCollection", "AddGlobalRootPtr" ); if( !pUserProc_AddGlobalRootPtr ) { compiler.errorMessenger.Output(3, "_System_CGarbageCollection.AddGlobalRootPtr", -1 ); return false; } BOOST_FOREACH( const Variable *pVar, compiler.GetObjectModule().meta.GetGlobalVars() ){ if( pVar->GetType().IsObject() || pVar->GetType().IsPointer() || pVar->GetType().IsStruct() ){ // オブジェクトまたはポインタだったとき // ※構造体も含む(暫定対応) // 変数領域に要するLONG_PTR単位の個数を引き渡す //mov r8,count compiler.codeGenerator.op_mov_RV(sizeof(_int64), REG_R8,pVar->GetMemorySize()/PTR_SIZE); // ルートポインタを引き渡す //mov rdx,offset compiler.codeGenerator.op_mov_RV(sizeof(_int64), REG_RDX,(int)pVar->GetOffsetAddress(), Schedule::GlobalVar ); // Thisポインタを引き渡す SetThisPtrToReg(REG_RCX); // call AddGlobalRootPtr compiler.codeGenerator.op_call( pUserProc_AddGlobalRootPtr ); } } return true; }