diff options
author | Tomáš Rylek <trylek@microsoft.com> | 2020-12-08 05:19:44 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-08 05:19:44 +0300 |
commit | 69e114c1abf91241a0eeecf1ecceab4711b8aa62 (patch) | |
tree | b81a0b35748f5e598412bcc504335cdbd322cd43 /src/coreclr/ilasm | |
parent | 0ec07945a9759a72a689edbb01e69b232e26e05a (diff) |
December infra rollout - remove duplicated 'src' from coreclr subrepo (src/coreclr/src becomes src/coreclr) (#44973)
* Move src/coreclr/src/Directory.Build.targets to src/coreclr
Merge src/coreclr/src/CMakeLists.txt into src/coreclr/CMakeLists.txt
* Mechanical move of src/coreclr/src to src/coreclr
* Scripts adjustments to reflect the changed paths
Diffstat (limited to 'src/coreclr/ilasm')
28 files changed, 23301 insertions, 0 deletions
diff --git a/src/coreclr/ilasm/CMakeLists.txt b/src/coreclr/ilasm/CMakeLists.txt new file mode 100644 index 00000000000..3e6c15b657a --- /dev/null +++ b/src/coreclr/ilasm/CMakeLists.txt @@ -0,0 +1,130 @@ +project(ilasm) + +add_definitions(-DUNICODE) +add_definitions(-D_UNICODE) +add_definitions(-D_FEATURE_NO_HOST) +add_definitions(-D__ILASM__) +add_definitions(-DFEATURE_METADATA_EMIT_PORTABLE_PDB) + +add_definitions(-DFEATURE_CORECLR) + +include_directories(.) + +set(ILASM_SOURCES + assem.cpp + writer.cpp + writer_enc.cpp + method.cpp + asmman.cpp + main.cpp + assembler.cpp + prebuilt/asmparse.cpp + portable_pdb.cpp +) + +set(ILASM_HEADERS + asmenum.h + asmman.hpp + asmparse.h + asmtemplates.h + assembler.h + binstr.h + class.hpp + ilasmpch.h + method.hpp + nvpair.h + typar.hpp + portable_pdb.h +) + +if(CLR_CMAKE_TARGET_WIN32) + list(APPEND ILASM_SOURCES ${ILASM_HEADERS}) + + set(ILASM_RESOURCES Native.rc) + add_definitions(-DFX_VER_INTERNALNAME_STR=ilasm.exe) +endif(CLR_CMAKE_TARGET_WIN32) + + +if(CLR_CMAKE_HOST_UNIX) + # Need generate a right form of asmparse.cpp to avoid the following options. + # Clang also produces a bad-codegen on this prebuilt file with optimization. + # https://github.com/dotnet/runtime/issues/4776 + add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-Wno-register>") + add_compile_options(-Wno-array-bounds) + add_compile_options(-Wno-unused-label) + set_source_files_properties( prebuilt/asmparse.cpp PROPERTIES COMPILE_FLAGS "-O0" ) +endif(CLR_CMAKE_HOST_UNIX) + +if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) + # This option is necessary to ensure that the overloaded delete operator defined inside + # of the utilcode will be used instead of the standard library delete operator. + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic") + + # The following linked options can be inserted into the linker libraries list to + # ensure proper resolving of circular references between a subset of the libraries. + set(START_LIBRARY_GROUP -Wl,--start-group) + set(END_LIBRARY_GROUP -Wl,--end-group) +endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) + +_add_executable(ilasm + ${ILASM_SOURCES} + ${ILASM_RESOURCES} +) + +set(ILASM_LINK_LIBRARIES + utilcodestaticnohost + mscorpe + ${START_LIBRARY_GROUP} # Start group of libraries that have circular references + mdhotdata_ppdb + mdcompiler_ppdb + mdruntime_ppdb + mdruntimerw_ppdb + mdstaticapi_ppdb + ${END_LIBRARY_GROUP} # End group of libraries that have circular references + ceefgen + corguids +) + +if(CLR_CMAKE_TARGET_WIN32) + list(APPEND ILASM_LINK_LIBRARIES + ${STATIC_MT_CRT_LIB} + ${STATIC_MT_VCRT_LIB} + kernel32.lib + advapi32.lib + ole32.lib + oleaut32.lib + uuid.lib + user32.lib + version.lib + shlwapi.lib + bcrypt.lib + RuntimeObject.lib + ) +else() + list(APPEND ILASM_LINK_LIBRARIES + coreclrpal + mscorrc + palrt + ) +endif(CLR_CMAKE_TARGET_WIN32) + + +if(CLR_CMAKE_HOST_UNIX) + target_link_libraries(ilasm + ${ILASM_LINK_LIBRARIES} + utilcodestaticnohost + mscorrc + coreclrpal + palrt + ${CMAKE_DL_LIBS} + ) +else() + target_link_libraries(ilasm + ${ILASM_LINK_LIBRARIES} + ole32 + oleaut32 + shell32 + ) +endif(CLR_CMAKE_HOST_UNIX) + +install_clr(TARGETS ilasm) diff --git a/src/coreclr/ilasm/Native.rc b/src/coreclr/ilasm/Native.rc new file mode 100644 index 00000000000..b9622b6c47e --- /dev/null +++ b/src/coreclr/ilasm/Native.rc @@ -0,0 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#define FX_VER_FILEDESCRIPTION_STR "Microsoft .NET Framework IL assembler\0" + +#include <fxver.h> +#include <fxver.rc> diff --git a/src/coreclr/ilasm/asmenum.h b/src/coreclr/ilasm/asmenum.h new file mode 100644 index 00000000000..f2e79c81eb9 --- /dev/null +++ b/src/coreclr/ilasm/asmenum.h @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +#ifndef __asmenum_h__ +#define __asmenum_h__ + +#include "openum.h" + +typedef struct +{ + const char * pszName; + OPCODE op; + + BYTE Type; // Inline0 etc. + + BYTE Len; // std mapping + BYTE Std1; + BYTE Std2; +} opcodeinfo_t; + +#ifdef DECLARE_DATA +opcodeinfo_t OpcodeInfo[] = +{ +#define OPALIAS(c,s,real) { s, real, 0, 0, 0, 0 }, +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) { s, c, args,l,s1,s2 }, +#include "opcode.def" +#undef OPDEF +#undef OPALIAS +}; + +unsigned OpcodeInfoLen = sizeof(OpcodeInfo) / sizeof(opcodeinfo_t); +#else +extern opcodeinfo_t OpcodeInfo[]; +extern unsigned OpcodeInfoLen; +#endif + + + +#endif /* __openum_h__ */ + + diff --git a/src/coreclr/ilasm/asmman.cpp b/src/coreclr/ilasm/asmman.cpp new file mode 100644 index 00000000000..dc45b8f9f01 --- /dev/null +++ b/src/coreclr/ilasm/asmman.cpp @@ -0,0 +1,1031 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// asmman.cpp - manifest info handling (implementation of class AsmMan, see asmman.hpp) +// + +// +#include "ilasmpch.h" + +#include "assembler.h" +#include "strongnameinternal.h" +#include <limits.h> +#include <fusion.h> + +extern WCHAR* pwzInputFiles[]; + +BinStr* BinStrToUnicode(BinStr* pSource, bool Swap) +{ + if(pSource) + { + pSource->appendInt8(0); + BinStr* tmp = new BinStr(); + char* pb = (char*)(pSource->ptr()); + int l=pSource->length(), L = sizeof(WCHAR)*l; + if(tmp) + { + WCHAR* wz = (WCHAR*)(tmp->getBuff(L)); + if(wz) + { + memset(wz,0,L); + WszMultiByteToWideChar(g_uCodePage,0,pb,-1,wz,l); + tmp->remove(L-(DWORD)wcslen(wz)*sizeof(WCHAR)); +#if BIGENDIAN + if (Swap) + SwapStringLength(wz, (DWORD)wcslen(wz)); +#endif + delete pSource; + } + else + { + delete tmp; + tmp = NULL; + fprintf(stderr,"\nOut of memory!\n"); + } + } + else + fprintf(stderr,"\nOut of memory!\n"); + return tmp; + } + return NULL; +} + +AsmManFile* AsmMan::GetFileByName(__in __nullterminated char* szFileName) +{ + AsmManFile* ret = NULL; + if(szFileName) + { + //AsmManFile X; + //X.szName = szFileName; + //ret = m_FileLst.FIND(&X); + //X.szName = NULL; + for(int i=0; (ret = m_FileLst.PEEK(i))&&strcmp(ret->szName,szFileName); i++); + } + return ret; +} + +mdToken AsmMan::GetFileTokByName(__in __nullterminated char* szFileName) +{ + AsmManFile* tmp = GetFileByName(szFileName); + return(tmp ? tmp->tkTok : mdFileNil); +} + +AsmManComType* AsmMan::GetComTypeByName(__in_opt __nullterminated char* szComTypeName, + __in_opt __nullterminated char* szComEnclosingTypeName) +{ + AsmManComType* ret = NULL; + if(szComTypeName) + { + //AsmManComType X; + //X.szName = szComTypeName; + //ret = m_ComTypeLst.FIND(&X); + //X.szName = NULL; + for(int i=0; (ret = m_ComTypeLst.PEEK(i)) != NULL; i++) + { + if (strcmp(ret->szName, szComTypeName) == 0) + { + if (ret->szComTypeName == NULL && szComEnclosingTypeName == NULL) + { + break; + } + + if (ret->szComTypeName != NULL && szComEnclosingTypeName != NULL) + { + if (strcmp(ret->szComTypeName, szComEnclosingTypeName) == 0) + { + break; + } + } + } + } + } + return ret; +} + +mdToken AsmMan::GetComTypeTokByName( + __in_opt __nullterminated char* szComTypeName, + __in_opt __nullterminated char* szComEnclosingTypeName) +{ + AsmManComType* tmp = GetComTypeByName(szComTypeName, szComEnclosingTypeName); + return(tmp ? tmp->tkTok : mdExportedTypeNil); +} + +AsmManAssembly* AsmMan::GetAsmRefByName(__in __nullterminated const char* szAsmRefName) +{ + AsmManAssembly* ret = NULL; + if(szAsmRefName) + { + //AsmManAssembly X; + //X.szAlias = szAsmRefName; + //ret = m_AsmRefLst.FIND(&X); + //X.szAlias = NULL; + DWORD L = (DWORD)strlen(szAsmRefName); + for(int i=0; (ret = m_AsmRefLst.PEEK(i))&& + ((ret->dwAlias != L)||strcmp(ret->szAlias,szAsmRefName)); i++); + } + return ret; +} +mdToken AsmMan::GetAsmRefTokByName(__in __nullterminated const char* szAsmRefName) +{ + AsmManAssembly* tmp = GetAsmRefByName(szAsmRefName); + return(tmp ? tmp->tkTok : mdAssemblyRefNil); +} +AsmManAssembly* AsmMan::GetAsmRefByAsmName(__in __nullterminated const char* szAsmName) +{ + AsmManAssembly* ret = NULL; + if(szAsmName) + { + for(int i=0; (ret = m_AsmRefLst.PEEK(i))&& + (strcmp(ret->szName,szAsmName)); i++); + } + return ret; +} + +//============================================================================================================== +void AsmMan::SetModuleName(__inout_opt __nullterminated char* szName) +{ + if(m_szScopeName == NULL) // ignore all duplicate declarations + { + if(szName && *szName) + { + ULONG L = (ULONG)strlen(szName); + if(L >= MAX_SCOPE_LENGTH) + { + ((Assembler*)m_pAssembler)->report->warn("Module name too long (%d chars, max.allowed: %d chars), truncated\n",L,MAX_SCOPE_LENGTH-1); + szName[MAX_SCOPE_LENGTH-1] = 0; + } + m_szScopeName = szName; + strcpy_s(((Assembler*)m_pAssembler)->m_szScopeName, MAX_SCOPE_LENGTH, szName); + } + } +} +//============================================================================================================== + +void AsmMan::AddFile(__in __nullterminated char* szName, DWORD dwAttr, BinStr* pHashBlob) +{ + AsmManFile* tmp = GetFileByName(szName); + Assembler* pAsm = (Assembler*)m_pAssembler; + if(tmp==NULL) + { + tmp = new AsmManFile; + if(tmp==NULL) + { + pAsm->report->error("\nOut of memory!\n"); + return; + } + memset(tmp,0,sizeof(AsmManFile)); + if((dwAttr & 0x80000000)!=0) pAsm->m_fEntryPointPresent = TRUE; + tmp->szName = szName; + tmp->dwAttr = dwAttr; + tmp->pHash = pHashBlob; + tmp->m_fNew = TRUE; + m_FileLst.PUSH(tmp); + tmp->tkTok = TokenFromRid(m_FileLst.COUNT(),mdtFile); + } + pAsm->m_tkCurrentCVOwner = 0; + if(tmp) pAsm->m_pCustomDescrList = &(tmp->m_CustomDescrList); +} +//============================================================================================================== + +void AsmMan::EmitFiles() +{ + AsmManFile* tmp; + Assembler* pAsm = (Assembler*)m_pAssembler; + int i; + HRESULT hr = S_OK; + mdToken tk; + for(i = 0; (tmp=m_FileLst.PEEK(i)) != NULL; i++) + { + BOOL fEntry = ((tmp->dwAttr & 0x80000000)!=0); + + wzUniBuf[0] = 0; + + BYTE* pHash=NULL; + DWORD cbHash= 0; + + if(!tmp->m_fNew) continue; + tmp->m_fNew = FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,tmp->szName,-1,wzUniBuf,dwUniBuf); + if(tmp->pHash==NULL) // if hash not explicitly specified + { + if(m_pAssembly // and assembly is defined + && m_pAssembly->ulHashAlgorithm) // and hash algorithm is defined... + { // then try to compute it + { + pHash = NULL; + cbHash = 0; + } + } + } + else + { + pHash = tmp->pHash->ptr(); + cbHash = tmp->pHash->length(); + } + + hr = m_pAsmEmitter->DefineFile(wzUniBuf, + (const void*)pHash, + cbHash, + tmp->dwAttr & 0x7FFFFFFF, + (mdFile*)&tk); + _ASSERTE(tk == tmp->tkTok); + if(FAILED(hr)) report->error("Failed to define file '%s': 0x%08X\n",tmp->szName,hr); + else + { + if(fEntry) + { + if (FAILED(pAsm->m_pCeeFileGen->SetEntryPoint(pAsm->m_pCeeFile, tmp->tkTok))) + { + pAsm->report->error("Failed to set external entry point for file '%s'\n",tmp->szName); + } + } + pAsm->EmitCustomAttributes(tmp->tkTok, &(tmp->m_CustomDescrList)); + } + } //end for(i = 0; tmp=m_FileLst.PEEK(i); i++) +} + +void AsmMan::StartAssembly(__in __nullterminated char* szName, __in_opt __nullterminated char* szAlias, DWORD dwAttr, BOOL isRef) +{ + if(!isRef && (0==strcmp(szName, "mscorlib"))) ((Assembler*)m_pAssembler)->m_fIsMscorlib = TRUE; + if(!isRef && (m_pAssembly != NULL)) + { + if(strcmp(szName, m_pAssembly->szName)) + report->error("Multiple assembly declarations\n"); + // if name is the same, just ignore it + m_pCurAsmRef = NULL; + } + else + { + if((m_pCurAsmRef = new AsmManAssembly)) + { + memset(m_pCurAsmRef,0,sizeof(AsmManAssembly)); + m_pCurAsmRef->usVerMajor = (USHORT)0xFFFF; + m_pCurAsmRef->usVerMinor = (USHORT)0xFFFF; + m_pCurAsmRef->usBuild = (USHORT)0xFFFF; + m_pCurAsmRef->usRevision = (USHORT)0xFFFF; + m_pCurAsmRef->szName = szName; + m_pCurAsmRef->szAlias = szAlias ? szAlias : szName; + m_pCurAsmRef->dwAlias = (DWORD)strlen(m_pCurAsmRef->szAlias); + m_pCurAsmRef->dwAttr = dwAttr; + m_pCurAsmRef->isRef = isRef; + m_pCurAsmRef->isAutodetect = FALSE; + m_pCurAsmRef->m_fNew = TRUE; + if(!isRef) m_pAssembly = m_pCurAsmRef; + } + else + report->error("Failed to allocate AsmManAssembly structure\n"); + } + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList); + ((Assembler*)m_pAssembler)->m_pCustomDescrList = m_pCurAsmRef ? &(m_pCurAsmRef->m_CustomDescrList) : NULL; + +} +// copied from asmparse.y +static void corEmitInt(BinStr* buff, unsigned data) +{ + unsigned cnt = CorSigCompressData(data, buff->getBuff(5)); + buff->remove(5 - cnt); +} + +void AsmMan::EmitDebuggableAttribute(mdToken tkOwner) +{ + mdToken tkCA; + Assembler* pAsm = (Assembler*)m_pAssembler; + mdToken tkTypeSpec, tkMscorlib, tkParamType; + BinStr *pbsSig = new BinStr(); + BinStr* bsBytes = new BinStr();; + char* szName; + tkMscorlib = pAsm->m_fIsMscorlib ? 1 : pAsm->GetBaseAsmRef(); + tkTypeSpec = pAsm->ResolveClassRef(tkMscorlib,"System.Diagnostics.DebuggableAttribute",NULL); + + EmitAssemblyRefs(); // just in case we gained 'mscorlib' AsmRef in GetAsmRef above + + BOOL fOldStyle = FALSE; + if(tkMscorlib == 1) + fOldStyle = (m_pAssembly->usVerMajor == 1); + else + { + AsmManAssembly *pAssembly = GetAsmRefByName("mscorlib"); + if(pAssembly != NULL) + { + fOldStyle = (pAssembly->usVerMajor == 1); + } + } + + bsBytes->appendInt8(1); + bsBytes->appendInt8(0); + if(fOldStyle) + { + pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS); + corEmitInt(pbsSig,2); + pbsSig->appendInt8(ELEMENT_TYPE_VOID); + pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN); + pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN); + + //New to old: 0x101->(true,true),0x03->(true,false),0x103->(true,true)+warning + bsBytes->appendInt8(1); + bsBytes->appendInt8((pAsm->m_dwIncludeDebugInfo==0x03 ? 0 : 1)); + if(pAsm->m_dwIncludeDebugInfo == 0x103) + { + report->warn("\nOption /DEBUG=IMPL is invalid for legacy DebuggableAttribute, /DEBUG used.\n" ); + } + } + else + { + BinStr bsSigArg; + char buffer[80]; + sprintf_s(buffer,80, + "%s%c%s", + "System.Diagnostics.DebuggableAttribute", + NESTING_SEP, + "DebuggingModes" + ); + + tkParamType = pAsm->ResolveClassRef(tkMscorlib,buffer, NULL); + + bsSigArg.appendInt8(ELEMENT_TYPE_VALUETYPE); + + unsigned cnt = CorSigCompressToken(tkParamType, bsSigArg.getBuff(5)); + bsSigArg.remove(5 - cnt); + + pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS); + corEmitInt(pbsSig,1); + pbsSig->appendInt8(ELEMENT_TYPE_VOID); + pbsSig->append(&bsSigArg); + + bsBytes->appendInt32(pAsm->m_dwIncludeDebugInfo); + } + bsBytes->appendInt8(0); + bsBytes->appendInt8(0); + + szName = new char[16]; + strcpy_s(szName,16,".ctor"); + tkCA = pAsm->MakeMemberRef(tkTypeSpec,szName,pbsSig); + pAsm->DefineCV(new CustomDescr(tkOwner,tkCA,bsBytes)); +} + +void AsmMan::EndAssembly() +{ + if(m_pCurAsmRef) + { + if(m_pCurAsmRef->isRef) + { // list the assembly ref + if(GetAsmRefByName(m_pCurAsmRef->szAlias)) + { + //report->warn("Multiple declarations of Assembly Ref '%s', ignored except the 1st one\n",m_pCurAsmRef->szName); + delete m_pCurAsmRef; + m_pCurAsmRef = NULL; + return; + } + m_AsmRefLst.PUSH(m_pCurAsmRef); + m_pCurAsmRef->tkTok = TokenFromRid(m_AsmRefLst.COUNT(),mdtAssemblyRef); + } + else + { + HRESULT hr = S_OK; + m_pCurAsmRef->tkTok = TokenFromRid(1,mdtAssembly); + + // Determine the strong name public key. This may have been set + // via a directive in the source or from the command line (which + // overrides the directive). From the command line we may have + // been provided with a file or the name of a CAPI key + // container. Either may contain a public key or a full key + // pair. + if (((Assembler*)m_pAssembler)->m_wzKeySourceName) + { + // Key file versus container is determined by the first + // character of the source ('@' for container). + if (*(((Assembler*)m_pAssembler)->m_wzKeySourceName) == L'@') + { + report->error("Error: ilasm on CoreCLR does not support getting public key from container.\n"); + m_pCurAsmRef = NULL; + return; + } + else + { + // Read public key or key pair from file. + HANDLE hFile = WszCreateFile(((Assembler*)m_pAssembler)->m_wzKeySourceName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + hr = GetLastError(); + report->error("Failed to open key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr); + m_pCurAsmRef = NULL; + return; + } + + // Determine file size and allocate an appropriate buffer. + m_sStrongName.m_cbPublicKey = SafeGetFileSize(hFile, NULL); + if (m_sStrongName.m_cbPublicKey == 0xffffffff) { + report->error("File size too large\n"); + m_pCurAsmRef = NULL; + CloseHandle(hFile); + return; + } + + m_sStrongName.m_pbPublicKey = new BYTE[m_sStrongName.m_cbPublicKey]; + if (m_sStrongName.m_pbPublicKey == NULL) { + report->error("Failed to allocate key buffer\n"); + m_pCurAsmRef = NULL; + CloseHandle(hFile); + return; + } + m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedByNew; + + // Read the file into the buffer. + DWORD dwBytesRead; + if (!ReadFile(hFile, m_sStrongName.m_pbPublicKey, m_sStrongName.m_cbPublicKey, &dwBytesRead, NULL)) { + hr = GetLastError(); + report->error("Failed to read key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr); + m_pCurAsmRef = NULL; + CloseHandle(hFile); + return; + } + + CloseHandle(hFile); + + // Guess whether we're full or delay signing based on + // whether the blob passed to us looks like a public + // key. (I.e. we may just have copied a full key pair + // into the public key buffer). + if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) && + (offsetof(PublicKeyBlob, PublicKey) + + ((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey) == m_sStrongName.m_cbPublicKey) + m_sStrongName.m_fFullSign = FALSE; + else + m_sStrongName.m_fFullSign = TRUE; + + // If we really have a key pair, we'll move it into a + // key container so the signing code gets the key pair + // from a consistent place. + if (m_sStrongName.m_fFullSign) + { + report->error("Error: ilasm on CoreCLR does not support full sign.\n"); + m_pCurAsmRef = NULL; + return; + } + } + } + else + { + if (m_pAssembly->pPublicKey) + { + m_sStrongName.m_pbPublicKey = m_pAssembly->pPublicKey->ptr(); + m_sStrongName.m_cbPublicKey = m_pAssembly->pPublicKey->length(); + } + else + { + m_sStrongName.m_pbPublicKey = NULL; + m_sStrongName.m_cbPublicKey = 0; + } + + m_sStrongName.m_wzKeyContainer = NULL; + m_sStrongName.m_fFullSign = FALSE; + m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated; + } + } + m_pCurAsmRef = NULL; + } + ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); +} + +void FillAssemblyMetadata(AsmManAssembly *pAsm, ASSEMBLYMETADATA *pmd) +{ + pmd->usMajorVersion = pAsm->usVerMajor; + pmd->usMinorVersion = pAsm->usVerMinor; + pmd->usBuildNumber = pAsm->usBuild; + pmd->usRevisionNumber = pAsm->usRevision; + if(pmd->usMajorVersion == 0xFFFF) pmd->usMajorVersion = 0; + if(pmd->usMinorVersion == 0xFFFF) pmd->usMinorVersion = 0; + if(pmd->usBuildNumber == 0xFFFF) pmd->usBuildNumber = 0; + if(pmd->usRevisionNumber == 0xFFFF) pmd->usRevisionNumber = 0; + + if(pAsm->pLocale != NULL) + { + pmd->szLocale = (LPWSTR)(pAsm->pLocale->ptr()); + pmd->cbLocale = pAsm->pLocale->length()/((ULONG)sizeof(WCHAR)); + } + else + { + pmd->szLocale = NULL; + pmd->cbLocale = 0; + } + + pmd->rProcessor = NULL; + pmd->rOS = NULL; + pmd->ulProcessor = 0; + pmd->ulOS = 0; +} + +void AsmMan::EmitAssemblyRefs() +{ + int i; + HRESULT hr = S_OK; + ASSEMBLYMETADATA md; + mdToken tk; + + for(i=0; (m_pCurAsmRef=m_AsmRefLst.PEEK(i)) != NULL; i++) + { + if(!m_pCurAsmRef->m_fNew) continue; + m_pCurAsmRef->m_fNew = FALSE; + + wzUniBuf[0] = 0; + FillAssemblyMetadata(m_pCurAsmRef,&md); + + // See if we've got a full public key or the tokenized version (or neither). + BYTE *pbPublicKeyOrToken = NULL; + DWORD cbPublicKeyOrToken = 0; + DWORD dwFlags = m_pCurAsmRef->dwAttr; + if (m_pCurAsmRef->pPublicKeyToken) + { + pbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->ptr(); + cbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->length(); + + } + else if (m_pCurAsmRef->pPublicKey) + { + pbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->ptr(); + cbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->length(); + dwFlags |= afPublicKey; + } + // Convert name to Unicode + WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf); + hr = m_pAsmEmitter->DefineAssemblyRef( // S_OK or error. + pbPublicKeyOrToken, // [IN] Public key or token of the assembly. + cbPublicKeyOrToken, // [IN] Count of bytes in the key or token. + (LPCWSTR)wzUniBuf, // [IN] Name of the assembly being referenced. + (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData. + (m_pCurAsmRef->pHashBlob ? (const void*)(m_pCurAsmRef->pHashBlob->ptr()) : NULL), // [IN] Hash Blob. + (m_pCurAsmRef->pHashBlob ? m_pCurAsmRef->pHashBlob->length() : 0), // [IN] Count of bytes in the Hash Blob. + dwFlags, // [IN] Flags. + (mdAssemblyRef*)&tk); // [OUT] Returned AssemblyRef token. + if(m_pCurAsmRef->tkTok != tk) + { + report->error("AsmRef'%S' tok %8.8X -> %8.8X\n",wzUniBuf,m_pCurAsmRef->tkTok,tk); + } + if(FAILED(hr)) report->error("Failed to define assembly ref '%s': 0x%08X\n",m_pCurAsmRef->szName,hr); + else + { + ((Assembler*)m_pAssembler)->EmitCustomAttributes(m_pCurAsmRef->tkTok, &(m_pCurAsmRef->m_CustomDescrList)); + } + } // end for(i=0; m_pCurAsmRef=m_AsmRefLst.PEEK(i); i++) +} + +void AsmMan::EmitAssembly() +{ + HRESULT hr = S_OK; + ASSEMBLYMETADATA md; + + wzUniBuf[0] = 0; + if(m_pAssembly == NULL) return; + if(!m_pAssembly->m_fNew) return; + m_pAssembly->m_fNew = FALSE; + + FillAssemblyMetadata(m_pAssembly, &md); + + // Convert name to Unicode + WszMultiByteToWideChar(g_uCodePage,0,m_pAssembly->szName,-1,wzUniBuf,dwUniBuf); + + hr = m_pAsmEmitter->DefineAssembly( // S_OK or error. + (const void*)(m_sStrongName.m_pbPublicKey), // [IN] Public key of the assembly. + m_sStrongName.m_cbPublicKey, // [IN] Count of bytes in the public key. + m_pAssembly->ulHashAlgorithm, // [IN] Hash algorithm used to hash the files. + (LPCWSTR)wzUniBuf, // [IN] Name of the assembly. + (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData. + m_pAssembly->dwAttr, // [IN] Flags. + (mdAssembly*)&(m_pAssembly->tkTok)); // [OUT] Returned Assembly token. + + if(FAILED(hr)) report->error("Failed to define assembly '%s': 0x%08X\n",m_pAssembly->szName,hr); + else + { + Assembler* pAsm = ((Assembler*)m_pAssembler); + pAsm->EmitSecurityInfo(m_pAssembly->tkTok, + m_pAssembly->m_pPermissions, + m_pAssembly->m_pPermissionSets); + if(pAsm->m_dwIncludeDebugInfo) + { + EmitDebuggableAttribute(m_pAssembly->tkTok); + } + pAsm->EmitCustomAttributes(m_pAssembly->tkTok, &(m_pAssembly->m_CustomDescrList)); + } +} + +void AsmMan::SetAssemblyPublicKey(BinStr* pPublicKey) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pPublicKey = pPublicKey; + } +} + +void AsmMan::SetAssemblyPublicKeyToken(BinStr* pPublicKeyToken) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pPublicKeyToken = pPublicKeyToken; + } +} + +void AsmMan::SetAssemblyHashAlg(ULONG ulAlgID) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->ulHashAlgorithm = ulAlgID; + } +} + +void AsmMan::SetAssemblyVer(USHORT usMajor, USHORT usMinor, USHORT usBuild, USHORT usRevision) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->usVerMajor = usMajor; + m_pCurAsmRef->usVerMinor = usMinor; + m_pCurAsmRef->usBuild = usBuild; + m_pCurAsmRef->usRevision = usRevision; + } +} + +void AsmMan::SetAssemblyLocale(BinStr* pLocale, BOOL bConvertToUnicode) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pLocale = bConvertToUnicode ? ::BinStrToUnicode(pLocale) : pLocale; + } +} + +void AsmMan::SetAssemblyHashBlob(BinStr* pHashBlob) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pHashBlob = pHashBlob; + } +} + +void AsmMan::SetAssemblyAutodetect() +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->isAutodetect = TRUE; + } +} + +void AsmMan::StartComType(__in __nullterminated char* szName, DWORD dwAttr) +{ + if((m_pCurComType = new AsmManComType)) + { + memset(m_pCurComType,0,sizeof(AsmManComType)); + m_pCurComType->szName = szName; + m_pCurComType->dwAttr = dwAttr; + m_pCurComType->m_fNew = TRUE; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList); + ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurComType->m_CustomDescrList); + } + else + report->error("Failed to allocate AsmManComType structure\n"); +} + +void AsmMan::EndComType() +{ + if(m_pCurComType) + { + if(m_pAssembler) + { + Class* pClass =((Assembler*)m_pAssembler)->m_pCurClass; + if(pClass) + { + m_pCurComType->tkClass = pClass->m_cl; + if(pClass->m_pEncloser) + { + mdTypeDef tkEncloser = pClass->m_pEncloser->m_cl; + AsmManComType* pCT; + for(unsigned i=0; (pCT=m_ComTypeLst.PEEK(i)); i++) + { + if(pCT->tkClass == tkEncloser) + { + m_pCurComType->szComTypeName = pCT->szName; + break; + } + } + } + } + } + + if (IsTdNested(m_pCurComType->dwAttr) && GetComTypeByName(m_pCurComType->szName, m_pCurComType->szComTypeName) != NULL) + { + report->error("Invalid TypeDefID of exported type\n"); + delete m_pCurComType; + } + else + { + m_ComTypeLst.PUSH(m_pCurComType); + } + + m_pCurComType = NULL; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); + } +} + +void AsmMan::SetComTypeFile(__in __nullterminated char* szFileName) +{ + if(m_pCurComType) + { + m_pCurComType->szFileName = szFileName; + } +} + +void AsmMan::SetComTypeAsmRef(__in __nullterminated char* szAsmRefName) +{ + if(m_pCurComType) + { + m_pCurComType->szAsmRefName = szAsmRefName; + } +} + +void AsmMan::SetComTypeComType(__in __nullterminated char* szComTypeName) +{ + if(m_pCurComType) + { + m_pCurComType->szComTypeName = szComTypeName; + } +} +BOOL AsmMan::SetComTypeImplementationTok(mdToken tk) +{ + if(m_pCurComType) + { + switch(TypeFromToken(tk)) + { + case mdtAssemblyRef: + case mdtExportedType: + case mdtFile: + m_pCurComType->tkImpl = tk; + return TRUE; + } + } + return FALSE; +} +BOOL AsmMan::SetComTypeClassTok(mdToken tkClass) +{ + if((m_pCurComType)&&(TypeFromToken(tkClass)==mdtTypeDef)) + { + m_pCurComType->tkClass = tkClass; + return TRUE; + } + return FALSE; +} + +void AsmMan::StartManifestRes(__in __nullterminated char* szName, __in __nullterminated char* szAlias, DWORD dwAttr) +{ + if((m_pCurManRes = new AsmManRes)) + { + m_pCurManRes->szName = szName; + m_pCurManRes->szAlias = szAlias; + m_pCurManRes->dwAttr = dwAttr; + m_pCurManRes->m_fNew = TRUE; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList); + ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurManRes->m_CustomDescrList); + } + else + report->error("Failed to allocate AsmManRes structure\n"); +} + +void AsmMan::EndManifestRes() +{ + if(m_pCurManRes) + { + m_ManResLst.PUSH(m_pCurManRes); + m_pCurManRes = NULL; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); + } +} + + +void AsmMan::SetManifestResFile(__in __nullterminated char* szFileName, ULONG ulOffset) +{ + if(m_pCurManRes) + { + m_pCurManRes->szFileName = szFileName; + m_pCurManRes->ulOffset = ulOffset; + } +} + +void AsmMan::SetManifestResAsmRef(__in __nullterminated char* szAsmRefName) +{ + if(m_pCurManRes) + { + m_pCurManRes->szAsmRefName = szAsmRefName; + } +} + +HRESULT AsmMan::EmitManifest() +{ + //AsmManAssembly* pAsmRef; + AsmManComType* pComType; + AsmManRes* pManRes; + HRESULT hr = S_OK; + + wzUniBuf[0] = 0; + + if(m_pAsmEmitter==NULL) + hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &m_pAsmEmitter); + + if(SUCCEEDED(hr)) + { + EmitFiles(); + EmitAssembly(); + + if((((Assembler*)m_pAssembler)->m_dwIncludeDebugInfo != 0) && (m_pAssembly == NULL) + && !(((Assembler*)m_pAssembler)->m_fENCMode)) + { + mdToken tkOwner, tkMscorlib; + tkMscorlib = ((Assembler*)m_pAssembler)->GetAsmRef("mscorlib"); + tkOwner = ((Assembler*)m_pAssembler)->ResolveClassRef(tkMscorlib, + "System.Runtime.CompilerServices.AssemblyAttributesGoHere", + NULL); + EmitDebuggableAttribute(tkOwner); + } + + // Emit all com types + unsigned i; + for(i = 0; (pComType = m_ComTypeLst.PEEK(i)); i++) + { + if(!pComType->m_fNew) continue; + pComType->m_fNew = FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,pComType->szName,-1,wzUniBuf,dwUniBuf); + mdToken tkImplementation = mdTokenNil; + if(pComType->tkImpl) tkImplementation = pComType->tkImpl; + else if(pComType->szFileName) + { + tkImplementation = GetFileTokByName(pComType->szFileName); + if(tkImplementation==mdFileNil) + { + report->error("Undefined File '%s' in ExportedType '%s'\n",pComType->szFileName,pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + } + else if(pComType->szAsmRefName) + { + tkImplementation = GetAsmRefTokByName(pComType->szAsmRefName); + if(RidFromToken(tkImplementation)==0) + { + report->error("Undefined AssemblyRef '%s' in ExportedType '%s'\n",pComType->szAsmRefName,pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + } + else if(pComType->szComTypeName) + { + char* szLastName = strrchr(pComType->szComTypeName, NESTING_SEP); + + if(szLastName) + { + *szLastName = 0; + szLastName ++; + tkImplementation = GetComTypeTokByName(szLastName, pComType->szComTypeName); + *(szLastName-1) = NESTING_SEP; // not really necessary + } + + else + { + tkImplementation = GetComTypeTokByName(pComType->szComTypeName); + } + + if(tkImplementation==mdExportedTypeNil) + { + report->error("Undefined ExportedType '%s' in ExportedType '%s'\n",pComType->szComTypeName,pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + } + else + { + report->warn("Undefined implementation in ExportedType '%s' -- ExportType not emitted\n",pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + hr = m_pAsmEmitter->DefineExportedType( // S_OK or error. + (LPCWSTR)wzUniBuf, // [IN] Name of the Com Type. + tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the ComType. + (mdTypeDef)pComType->tkClass, // [IN] TypeDef token within the file. + pComType->dwAttr, // [IN] Flags. + (mdExportedType*)&(pComType->tkTok)); // [OUT] Returned ComType token. + if(FAILED(hr)) report->error("Failed to define ExportedType '%s': 0x%08X\n",pComType->szName,hr); + else + { + ((Assembler*)m_pAssembler)->EmitCustomAttributes(pComType->tkTok, &(pComType->m_CustomDescrList)); + } + } + + // Emit all manifest resources + m_dwMResSizeTotal = 0; + m_dwMResNum = 0; + for(i = 0; (pManRes = m_ManResLst.PEEK(i)); i++) + { + BOOL fOK = TRUE; + mdToken tkImplementation = mdFileNil; + + if(!pManRes->m_fNew) continue; + pManRes->m_fNew = FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,pManRes->szAlias,-1,wzUniBuf,dwUniBuf); + if(pManRes->szAsmRefName) + { + tkImplementation = GetAsmRefTokByName(pManRes->szAsmRefName); + if(RidFromToken(tkImplementation)==0) + { + report->error("Undefined AssemblyRef '%s' in MResource '%s'\n",pManRes->szAsmRefName,pManRes->szName); + fOK = FALSE; + } + } + else if(pManRes->szFileName) + { + tkImplementation = GetFileTokByName(pManRes->szFileName); + if(RidFromToken(tkImplementation)==0) + { + report->error("Undefined File '%s' in MResource '%s'\n",pManRes->szFileName,pManRes->szName); + fOK = FALSE; + } + } + else // embedded mgd.resource, go after the file + { + HANDLE hFile = INVALID_HANDLE_VALUE; + int j; + WCHAR wzFileName[2048]; + WCHAR* pwz; + + pManRes->ulOffset = m_dwMResSizeTotal; + for(j=0; (hFile == INVALID_HANDLE_VALUE)&&(pwzInputFiles[j] != NULL); j++) + { + wcscpy_s(wzFileName,2048,pwzInputFiles[j]); + pwz = wcsrchr(wzFileName,DIRECTORY_SEPARATOR_CHAR_A); +#ifdef TARGET_WINDOWS + if(pwz == NULL) pwz = wcsrchr(wzFileName,':'); +#endif + if(pwz == NULL) pwz = &wzFileName[0]; + else pwz++; + wcscpy_s(pwz,2048-(pwz-wzFileName),wzUniBuf); + hFile = WszCreateFile(wzFileName, GENERIC_READ, FILE_SHARE_READ, + 0, OPEN_EXISTING, 0, 0); + } + if (hFile == INVALID_HANDLE_VALUE) + { + report->error("Failed to open managed resource file '%s'\n",pManRes->szAlias); + fOK = FALSE; + } + else + { + if (m_dwMResNum >= MAX_MANIFEST_RESOURCES) + { + report->error("Too many resources (implementation limit: %d); skipping file '%s'\n",MAX_MANIFEST_RESOURCES,pManRes->szAlias); + fOK = FALSE; + } + else + { + m_dwMResSize[m_dwMResNum] = SafeGetFileSize(hFile,NULL); + if(m_dwMResSize[m_dwMResNum] == 0xFFFFFFFF) + { + report->error("Failed to get size of managed resource file '%s'\n",pManRes->szAlias); + fOK = FALSE; + } + else + { + m_dwMResSizeTotal += m_dwMResSize[m_dwMResNum]+sizeof(DWORD); + m_wzMResName[m_dwMResNum] = new WCHAR[wcslen(wzFileName)+1]; + wcscpy_s(m_wzMResName[m_dwMResNum],wcslen(wzFileName)+1,wzFileName); + m_fMResNew[m_dwMResNum] = TRUE; + m_dwMResNum++; + } + CloseHandle(hFile); + } + } + } + if(fOK || ((Assembler*)m_pAssembler)->OnErrGo) + { + WszMultiByteToWideChar(g_uCodePage,0,pManRes->szName,-1,wzUniBuf,dwUniBuf); + hr = m_pAsmEmitter->DefineManifestResource( // S_OK or error. + (LPCWSTR)wzUniBuf, // [IN] Name of the resource. + tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. + pManRes->ulOffset, // [IN] Offset to the beginning of the resource within the file. + pManRes->dwAttr, // [IN] Flags. + (mdManifestResource*)&(pManRes->tkTok)); // [OUT] Returned ManifestResource token. + if(FAILED(hr)) + report->error("Failed to define manifest resource '%s': 0x%08X\n",pManRes->szName,hr); + } + } + + + m_pAsmEmitter->Release(); + m_pAsmEmitter = NULL; + } + else + report->error("Failed to obtain IMetaDataAssemblyEmit interface: 0x%08X\n",hr); + return hr; +} + diff --git a/src/coreclr/ilasm/asmman.hpp b/src/coreclr/ilasm/asmman.hpp new file mode 100644 index 00000000000..1290c9b2707 --- /dev/null +++ b/src/coreclr/ilasm/asmman.hpp @@ -0,0 +1,295 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// asmman.hpp - header file for manifest-related ILASM functions +// + +#ifndef ASMMAN_HPP +#define ASMMAN_HPP + +#include "specstrings.h" + +struct AsmManFile +{ + char* szName; + mdToken tkTok; + DWORD dwAttr; + BinStr* pHash; + BOOL m_fNew; + CustomDescrList m_CustomDescrList; + AsmManFile() + { + szName = NULL; + pHash = NULL; + m_fNew = TRUE; + } + ~AsmManFile() + { + if(szName) delete szName; + if(pHash) delete pHash; + } + int ComparedTo(AsmManFile* pX){ return strcmp(szName,pX->szName); } +}; +//typedef SORTEDARRAY<AsmManFile> AsmManFileList; +typedef FIFO<AsmManFile> AsmManFileList; + +struct AsmManAssembly +{ + BOOL isRef; + BOOL isAutodetect; + char* szName; + char* szAlias; + DWORD dwAlias; + mdToken tkTok; + DWORD dwAttr; + BinStr* pPublicKey; + BinStr* pPublicKeyToken; + ULONG ulHashAlgorithm; + BinStr* pHashBlob; + BinStr* pLocale; + BOOL m_fNew; + // Security attributes + PermissionDecl* m_pPermissions; + PermissionSetDecl* m_pPermissionSets; + CustomDescrList m_CustomDescrList; + USHORT usVerMajor; + USHORT usVerMinor; + USHORT usBuild; + USHORT usRevision; + AsmManAssembly() + { + /* + usVerMajor = usVerMinor = usBuild = usRevision = 0xFFFF; + szName = szAlias = NULL; + dwAlias = dwAttr = 0; + tkTok = 0; + pPublicKey = pPublicKeyToken =pHashBlob = pLocale = NULL; + ulHashAlgorithm = 0; + m_fNew = TRUE; + isAutodetect = isRef = FALSE; + */ + } + ~AsmManAssembly() + { + if(szAlias && (szAlias != szName)) delete [] szAlias; + if(szName) delete [] szName; + if(pPublicKey) delete pPublicKey; + if(pPublicKeyToken) delete pPublicKeyToken; + if(pHashBlob) delete pHashBlob; + if(pLocale) delete pLocale; + } + int ComparedTo(AsmManAssembly* pX){ return strcmp(szAlias,pX->szAlias); } +}; +//typedef SORTEDARRAY<AsmManAssembly> AsmManAssemblyList; +typedef FIFO<AsmManAssembly> AsmManAssemblyList; + +struct AsmManComType +{ + char* szName; + mdToken tkTok; + mdToken tkImpl; + DWORD dwAttr; + char* szFileName; + char* szAsmRefName; + char* szComTypeName; + mdToken tkClass; + BOOL m_fNew; + CustomDescrList m_CustomDescrList; + AsmManComType() + { + szName = szFileName = szAsmRefName = szComTypeName = NULL; + m_fNew = TRUE; + tkImpl = 0; + }; + ~AsmManComType() + { + if(szName) delete szName; + if(szFileName) delete szFileName; + }; + int ComparedTo(AsmManComType* pX){ return strcmp(szName,pX->szName); }; +}; +//typedef SORTEDARRAY<AsmManComType> AsmManComTypeList; +typedef FIFO<AsmManComType> AsmManComTypeList; + + +struct AsmManRes +{ + char* szName; + char* szAlias; + mdToken tkTok; + DWORD dwAttr; + char* szFileName; + ULONG ulOffset; + BOOL m_fNew; + CustomDescrList m_CustomDescrList; + char* szAsmRefName; + AsmManRes() { szName = szAlias = szAsmRefName = szFileName = NULL; ulOffset = 0; tkTok = 0; dwAttr = 0; m_fNew = TRUE; }; + ~AsmManRes() + { + if(szAlias && (szAlias != szName)) delete szAlias; + if(szName) delete szName; + if(szFileName) delete szFileName; + if(szAsmRefName) delete szAsmRefName; + } +}; +typedef FIFO<AsmManRes> AsmManResList; + +struct AsmManModRef +{ + char* szName; + mdToken tkTok; + BOOL m_fNew; + AsmManModRef() {szName = NULL; tkTok = 0; m_fNew = TRUE; }; + ~AsmManModRef() { if(szName) delete szName; }; +}; +typedef FIFO<AsmManModRef> AsmManModRefList; + +struct AsmManStrongName +{ + enum AllocationState + { + NotAllocated = 0, + AllocatedBySNApi, + AllocatedByNew + }; + + BYTE *m_pbSignatureKey; + DWORD m_cbSignatureKey; + BYTE *m_pbPublicKey; + DWORD m_cbPublicKey; + BYTE *m_pbPrivateKey; + DWORD m_cbPrivateKey; + WCHAR *m_wzKeyContainer; + BOOL m_fFullSign; + + // Where has the memory pointed to by m_pbPublicKey been taken from: + AllocationState m_dwPublicKeyAllocated; + + AsmManStrongName() { ZeroMemory(this, sizeof(*this)); } + ~AsmManStrongName() + { + if (m_dwPublicKeyAllocated == AllocatedByNew) + delete [] m_pbPublicKey; + + if (m_pbPrivateKey) + delete [] m_pbPrivateKey; + + if (m_pbSignatureKey) + delete [] m_pbSignatureKey; + } +}; + +class ErrorReporter; + +class AsmMan +{ + AsmManFileList m_FileLst; + AsmManComTypeList m_ComTypeLst; + AsmManResList m_ManResLst; + AsmManModRefList m_ModRefLst; + + AsmManComType* m_pCurComType; + AsmManRes* m_pCurManRes; + ErrorReporter* report; + void* m_pAssembler; + + AsmManFile* GetFileByName(__in __nullterminated char* szFileName); + AsmManAssembly* GetAsmRefByName(__in __nullterminated const char* szAsmRefName); + AsmManComType* GetComTypeByName(__in_opt __nullterminated char* szComTypeName, + __in_opt __nullterminated char* szComEnclosingTypeName = NULL); + mdToken GetComTypeTokByName(__in_opt __nullterminated char* szComTypeName, + __in_opt __nullterminated char* szComEnclosingTypeName = NULL); + + IMetaDataEmit* m_pEmitter; + +public: + IMetaDataAssemblyEmit* m_pAsmEmitter; + AsmManAssemblyList m_AsmRefLst; + AsmManAssembly* m_pAssembly; + AsmManAssembly* m_pCurAsmRef; + char* m_szScopeName; + BinStr* m_pGUID; + AsmManStrongName m_sStrongName; + // Embedded manifest resources paraphernalia: + WCHAR* m_wzMResName[MAX_MANIFEST_RESOURCES]; + DWORD m_dwMResSize[MAX_MANIFEST_RESOURCES]; + BOOL m_fMResNew[MAX_MANIFEST_RESOURCES]; + DWORD m_dwMResNum; + DWORD m_dwMResSizeTotal; + AsmMan() { m_pAssembly = NULL; m_szScopeName = NULL; m_pGUID = NULL; m_pAsmEmitter = NULL; + memset(m_wzMResName,0,sizeof(m_wzMResName)); + memset(m_dwMResSize,0,sizeof(m_dwMResSize)); + m_dwMResNum = m_dwMResSizeTotal = 0; }; + AsmMan(void* pAsm) { m_pAssembly = NULL; m_szScopeName = NULL; m_pGUID = NULL; m_pAssembler = pAsm; m_pAsmEmitter = NULL; + memset(m_wzMResName,0,sizeof(m_wzMResName)); + memset(m_dwMResSize,0,sizeof(m_dwMResSize)); + m_dwMResNum = m_dwMResSizeTotal = 0; }; + AsmMan(ErrorReporter* rpt) { m_pAssembly = NULL; m_szScopeName = NULL; m_pGUID = NULL; report = rpt; m_pAsmEmitter = NULL; + memset(m_wzMResName,0,sizeof(m_wzMResName)); + memset(m_dwMResSize,0,sizeof(m_dwMResSize)); + m_dwMResNum = m_dwMResSizeTotal = 0; }; + ~AsmMan() + { + if(m_pAssembly) delete m_pAssembly; + if(m_szScopeName) delete m_szScopeName; + if(m_pGUID) delete m_pGUID; + }; + void SetErrorReporter(ErrorReporter* rpt) { report = rpt; }; + HRESULT EmitManifest(void); + + void SetEmitter( IMetaDataEmit* pEmitter) { m_pEmitter = pEmitter; }; + + void SetModuleName(__inout_opt __nullterminated char* szName); + + void AddFile(__in __nullterminated char* szName, DWORD dwAttr, BinStr* pHashBlob); + void EmitFiles(); + void EmitDebuggableAttribute(mdToken tkOwner); + + void StartAssembly(__in __nullterminated char* szName, __in_opt __nullterminated char* szAlias, DWORD dwAttr, BOOL isRef); + void EndAssembly(); + void EmitAssemblyRefs(); + void EmitAssembly(); + void SetAssemblyPublicKey(BinStr* pPublicKey); + void SetAssemblyPublicKeyToken(BinStr* pPublicKeyToken); + void SetAssemblyHashAlg(ULONG ulAlgID); + void SetAssemblyVer(USHORT usMajor, USHORT usMinor, USHORT usBuild, USHORT usRevision); + void SetAssemblyLocale(BinStr* pLocale, BOOL bConvertToUnicode); + void SetAssemblyHashBlob(BinStr* pHashBlob); + void SetAssemblyAutodetect(); + + void StartComType(__in __nullterminated char* szName, DWORD dwAttr); + void EndComType(); + void SetComTypeFile(__in __nullterminated char* szFileName); + void SetComTypeAsmRef(__in __nullterminated char* szAsmRefName); + void SetComTypeComType(__in __nullterminated char* szComTypeName); + BOOL SetComTypeImplementationTok(mdToken tk); + BOOL SetComTypeClassTok(mdToken tkClass); + + void StartManifestRes(__in __nullterminated char* szName, __in __nullterminated char* szAlias, DWORD dwAttr); + void EndManifestRes(); + void SetManifestResFile(__in __nullterminated char* szFileName, ULONG ulOffset); + void SetManifestResAsmRef(__in __nullterminated char* szAsmRefName); + + AsmManAssembly* GetAsmRefByAsmName(__in __nullterminated const char* szAsmName); + + mdToken GetFileTokByName(__in __nullterminated char* szFileName); + mdToken GetAsmRefTokByName(__in __nullterminated const char* szAsmRefName); + mdToken GetAsmTokByName(__in __nullterminated const char* szAsmName) + { return (m_pAssembly && (strcmp(m_pAssembly->szName,szAsmName)==0)) ? m_pAssembly->tkTok : 0; }; + + mdToken GetModuleRefTokByName(__in __nullterminated char* szName) + { + if(szName && *szName) + { + AsmManModRef* pMR; + for(unsigned i=0; (pMR=m_ModRefLst.PEEK(i)); i++) + { + if(!strcmp(szName, pMR->szName)) return pMR->tkTok; + } + } + return 0; + }; + +}; + +#endif diff --git a/src/coreclr/ilasm/asmparse.h b/src/coreclr/ilasm/asmparse.h new file mode 100644 index 00000000000..ef377b5e430 --- /dev/null +++ b/src/coreclr/ilasm/asmparse.h @@ -0,0 +1,325 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +/**************************************************************************/ +/* asmParse is basically a wrapper around a YACC grammer COM+ assembly */ + +#ifndef asmparse_h +#define asmparse_h + +#include <stdio.h> // for FILE + +#include "assembler.h" // for ErrorReporter Labels +//class Assembler; +//class BinStr; + + +/**************************************************************************/ +/* an abstraction of a stream of input characters */ +class ReadStream { +public: + + virtual ~ReadStream() = default; + + virtual unsigned getAll(__out char** ppch) = 0; + + // read at most 'buffLen' bytes into 'buff', Return the + // number of characters read. On EOF return 0 + virtual unsigned read(__out_ecount(buffLen) char* buff, unsigned buffLen) = 0; + + // Return the name of the stream, (for error reporting). + //virtual const char* name() = 0; + // Return the Unicode name of the stream + virtual const WCHAR* namew() = 0; + //return ptr to buffer containing specified source line + virtual char* getLine(int lineNum) = 0; +}; + +/**************************************************************************/ +class BinStrStream : public ReadStream { +public: + BinStrStream(BinStr* pbs) + { + m_pStart = (char*)(pbs->ptr()); + m_pCurr = m_pStart; + m_pEnd = m_pStart + pbs->length(); + m_pBS = pbs; + }; + ~BinStrStream() + { + //if(m_pBS) + // delete m_pBS; + }; + unsigned getAll(__out char **ppbuff) + { + *ppbuff = m_pStart; + return m_pBS->length(); + }; + unsigned read(__out_ecount(buffLen) char* buff, unsigned buffLen) + { + _ASSERTE(m_pStart != NULL); + unsigned Remainder = (unsigned)(m_pEnd - m_pCurr); + unsigned Len = buffLen; + if(Len > Remainder) Len = Remainder; + memcpy(buff,m_pCurr,Len); + m_pCurr += Len; + if(Len < buffLen) + { + memset(buff+Len,0,buffLen-Len); + } + return Len; + } + + const WCHAR* namew() + { + return W("local_define"); + } + + BOOL IsValid() + { + return(m_pStart != NULL); + } + + char* getLine(int lineNum) + { + return NULL; // this function is not used + } + +private: + char* m_pStart; + char* m_pEnd; + char* m_pCurr; + BinStr* m_pBS; + + +}; +/**************************************************************************/ +class MappedFileStream : public ReadStream { +public: + MappedFileStream(__in __nullterminated WCHAR* wFileName) + { + fileNameW = wFileName; + m_hFile = INVALID_HANDLE_VALUE; + m_hMapFile = NULL; + m_pStart = open(wFileName); + m_pCurr = m_pStart; + m_pEnd = m_pStart + m_FileSize; + //memset(fileNameANSI,0,MAX_FILENAME_LENGTH*4); + //WszWideCharToMultiByte(CP_ACP,0,wFileName,-1,fileNameANSI,MAX_FILENAME_LENGTH*4,NULL,NULL); + } + ~MappedFileStream() + { + if (m_hFile != INVALID_HANDLE_VALUE) + { + if (m_pStart) + UnmapViewOfFile((void*)m_pStart); + if (m_hMapFile) + CloseHandle(m_hMapFile); + CloseHandle(m_hFile); + + m_pStart = NULL; + m_hMapFile = NULL; + m_hFile = INVALID_HANDLE_VALUE; + m_FileSize = 0; + delete [] fileNameW; + fileNameW = NULL; + } + } + unsigned getAll(__out char** pbuff) + { + *pbuff = m_pStart; + return m_FileSize; + } + unsigned read(__out_ecount(buffLen) char* buff, unsigned buffLen) + { + _ASSERTE(m_pStart != NULL); + unsigned Remainder = (unsigned)(m_pEnd - m_pCurr); + unsigned Len = buffLen; + if(Len > Remainder) Len = Remainder; + memcpy(buff,m_pCurr,Len); + m_pCurr += Len; + if(Len < buffLen) + { + memset(buff+Len,0,buffLen-Len); + } + return Len; + } + + //const char* name() + //{ + // return(&fileNameANSI[0]); + //} + + const WCHAR* namew() + { + return fileNameW; + } + + void set_namew(const WCHAR* namew) + { + fileNameW = namew; + } + + BOOL IsValid() + { + return(m_pStart != NULL); + } + + char* getLine(int lineNum) + { + return NULL; // this function is not used + } + +private: + char* map_file() + { + DWORD dwFileSizeLow; + + dwFileSizeLow = GetFileSize( m_hFile, NULL); + if (dwFileSizeLow == INVALID_FILE_SIZE) + return NULL; + m_FileSize = dwFileSizeLow; + + // No difference between A and W in this case: last param (LPCTSTR) is NULL + m_hMapFile = WszCreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (m_hMapFile == NULL) + return NULL; + + return (char*)(HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0); + } + char* open(const WCHAR* moduleName) + { + _ASSERTE(moduleName); + if (!moduleName) + return NULL; + + m_hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ, + 0, OPEN_EXISTING, 0, 0); + return (m_hFile == INVALID_HANDLE_VALUE) ? NULL : map_file(); + } + + const WCHAR* fileNameW; // FileName (for error reporting) + //char fileNameANSI[MAX_FILENAME_LENGTH*4]; + HANDLE m_hFile; // File we are reading from + DWORD m_FileSize; + HANDLE m_hMapFile; + char* m_pStart; + char* m_pEnd; + char* m_pCurr; + +}; + +typedef LIFO<ARG_NAME_LIST> ARG_NAME_LIST_STACK; + +// functional pointers used in parsing +/*--------------------------------------------------------------------------*/ +typedef char*(*PFN_NEXTCHAR)(char*); + +char* nextcharU(__in __nullterminated char* pos); +char* nextcharW(__in __nullterminated char* pos); + +/*--------------------------------------------------------------------------*/ +typedef unsigned(*PFN_SYM)(char*); + +unsigned SymAU(__in __nullterminated char* curPos); +unsigned SymW(__in __nullterminated char* curPos); +/*--------------------------------------------------------------------------*/ +typedef char*(*PFN_NEWSTRFROMTOKEN)(char*,size_t); + +char* NewStrFromTokenAU(__in_ecount(tokLen) char* curTok, size_t tokLen); +char* NewStrFromTokenW(__in_ecount(tokLen) char* curTok, size_t tokLen); +/*--------------------------------------------------------------------------*/ +typedef char*(*PFN_NEWSTATICSTRFROMTOKEN)(char*,size_t,char*,size_t); + +char* NewStaticStrFromTokenAU(__in_ecount(tokLen) char* curTok, size_t tokLen, __out_ecount(bufSize) char* staticBuf, size_t bufSize); +char* NewStaticStrFromTokenW(__in_ecount(tokLen) char* curTok, size_t tokLen, __out_ecount(bufSize) char* staticBuf, size_t bufSize); +/*--------------------------------------------------------------------------*/ +typedef unsigned(*PFN_GETDOUBLE)(char*,unsigned,double**); + +unsigned GetDoubleAU(__in __nullterminated char* begNum, unsigned L, double** ppRes); +unsigned GetDoubleW(__in __nullterminated char* begNum, unsigned L, double** ppRes); +/*--------------------------------------------------------------------------*/ +struct PARSING_ENVIRONMENT +{ + char* curTok; // The token we are in the process of processing (for error reporting) + char* curPos; // current place in input buffer + char* endPos; // points just past the end of valid data in the buffer + + ReadStream* in; // how we fill up our buffer + + PFN_NEXTCHAR pfn_nextchar; + PFN_SYM pfn_Sym; + PFN_NEWSTRFROMTOKEN pfn_NewStrFromToken; + PFN_NEWSTATICSTRFROMTOKEN pfn_NewStaticStrFromToken; + PFN_GETDOUBLE pfn_GetDouble; + + bool bExternSource; + bool bExternSourceAutoincrement; + unsigned nExtLine; + unsigned nExtCol; + unsigned nExtLineEnd; + unsigned nExtColEnd; + unsigned curLine; // Line number (for error reporting) + + unsigned uCodePage; + + char szFileName[MAX_FILENAME_LENGTH*3+1]; + +}; +typedef LIFO<PARSING_ENVIRONMENT> PARSING_ENVIRONMENT_STACK; + +/**************************************************************************/ +/* AsmParse does all the parsing. It also builds up simple data structures, + (like signatures), but does not do the any 'heavy lifting' like define + methods or classes. Instead it calls to the Assembler object to do that */ + +class AsmParse : public ErrorReporter +{ +public: + AsmParse(ReadStream* stream, Assembler *aAssem); + virtual ~AsmParse(); + void CreateEnvironment(ReadStream* stream); + void ParseFile(ReadStream* stream); + // The parser knows how to put line numbers on things and report the error + virtual void error(const char* fmt, ...); + virtual void warn(const char* fmt, ...); + virtual void msg(const char* fmt, ...); + char *getLine(int lineNum) { return penv->in->getLine(lineNum); }; + unsigned getAll(__out char** pbuff) { return penv->in->getAll(pbuff); }; + bool Success() {return success; }; + void SetIncludePath(__in WCHAR* wz) { wzIncludePath = wz; }; + + ARG_NAME_LIST_STACK m_ANSFirst; + ARG_NAME_LIST_STACK m_ANSLast; + PARSING_ENVIRONMENT *penv; + PARSING_ENVIRONMENT_STACK PEStack; + +private: + BinStr* MakeSig(unsigned callConv, BinStr* retType, BinStr* args, int ntyargs = 0); + BinStr* MakeTypeClass(CorElementType kind, mdToken tk); + BinStr* MakeTypeArray(CorElementType kind, BinStr* elemType, BinStr* bounds); + + char* fillBuff(__in_opt __nullterminated char* curPos); // refill the input buffer + HANDLE hstdout; + HANDLE hstderr; + +private: + friend void yyerror(__in __nullterminated const char* str); + friend int parse_literal(unsigned curSym, __inout __nullterminated char* &curPos, BOOL translate_escapes); + friend int yyparse(); + friend int yylex(); + friend Instr* SetupInstr(unsigned short opcode); + friend int findKeyword(const char* name, size_t nameLen, unsigned short* opcode); + friend TypeDefDescr* findTypedef(__in_ecount(nameLen) char* name, size_t nameLen); + friend char* skipBlanks(__in __nullterminated char*,unsigned*); + friend char* nextBlank(__in __nullterminated char*); + friend int ProcessEOF(); + friend unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType); + friend void FixupConstraints(); + + Assembler* assem; // This does most of the semantic processing + bool success; // overall success of the compilation + WCHAR* wzIncludePath; +}; + +#endif + diff --git a/src/coreclr/ilasm/asmparse.y b/src/coreclr/ilasm/asmparse.y new file mode 100644 index 00000000000..29179ffcec8 --- /dev/null +++ b/src/coreclr/ilasm/asmparse.y @@ -0,0 +1,2063 @@ +%{ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// File asmparse.y +// +#include "ilasmpch.h" + +#include "grammar_before.cpp" + +%} + +%union { + CorRegTypeAttr classAttr; + CorMethodAttr methAttr; + CorFieldAttr fieldAttr; + CorMethodImpl implAttr; + CorEventAttr eventAttr; + CorPropertyAttr propAttr; + CorPinvokeMap pinvAttr; + CorDeclSecurity secAct; + CorFileFlags fileAttr; + CorAssemblyFlags asmAttr; + CorAssemblyFlags asmRefAttr; + CorTypeAttr exptAttr; + CorManifestResourceFlags manresAttr; + double* float64; + __int64* int64; + __int32 int32; + char* string; + BinStr* binstr; + Labels* labels; + Instr* instr; // instruction opcode + NVPair* pair; + pTyParList typarlist; + mdToken token; + TypeDefDescr* tdd; + CustomDescr* cad; + unsigned short opcode; +}; + + /* These are returned by the LEXER and have values */ +%token ERROR_ BAD_COMMENT_ BAD_LITERAL_ /* bad strings, */ +%token <string> ID /* testing343 */ +%token <string> DOTTEDNAME /* System.Object */ +%token <binstr> QSTRING /* "Hello World\n" */ +%token <string> SQSTRING /* 'Hello World\n' */ +%token <int32> INT32 /* 3425 0x34FA 0352 */ +%token <int64> INT64 /* 342534523534534 0x34FA434644554 */ +%token <float64> FLOAT64 /* -334234 24E-34 */ +%token <int32> HEXBYTE /* 05 1A FA */ +%token <tdd> TYPEDEF_T +%token <tdd> TYPEDEF_M +%token <tdd> TYPEDEF_F +%token <tdd> TYPEDEF_TS +%token <tdd> TYPEDEF_MR +%token <tdd> TYPEDEF_CA + + + /* multi-character punctuation */ +%token DCOLON /* :: */ +%token ELIPSIS /* ... */ + + /* Keywords Note the undersores are to avoid collisions as these are common names */ +%token VOID_ BOOL_ CHAR_ UNSIGNED_ INT_ INT8_ INT16_ INT32_ INT64_ FLOAT_ FLOAT32_ FLOAT64_ BYTEARRAY_ +%token UINT_ UINT8_ UINT16_ UINT32_ UINT64_ FLAGS_ CALLCONV_ MDTOKEN_ +%token OBJECT_ STRING_ NULLREF_ + /* misc keywords */ +%token DEFAULT_ CDECL_ VARARG_ STDCALL_ THISCALL_ FASTCALL_ CLASS_ +%token TYPEDREF_ UNMANAGED_ FINALLY_ HANDLER_ CATCH_ FILTER_ FAULT_ +%token EXTENDS_ IMPLEMENTS_ TO_ AT_ TLS_ TRUE_ FALSE_ _INTERFACEIMPL + + /* class, method, field attributes */ + +%token VALUE_ VALUETYPE_ NATIVE_ INSTANCE_ SPECIALNAME_ FORWARDER_ +%token STATIC_ PUBLIC_ PRIVATE_ FAMILY_ FINAL_ SYNCHRONIZED_ INTERFACE_ SEALED_ NESTED_ +%token ABSTRACT_ AUTO_ SEQUENTIAL_ EXPLICIT_ ANSI_ UNICODE_ AUTOCHAR_ IMPORT_ ENUM_ +%token VIRTUAL_ NOINLINING_ AGGRESSIVEINLINING_ NOOPTIMIZATION_ AGGRESSIVEOPTIMIZATION_ UNMANAGEDEXP_ BEFOREFIELDINIT_ +%token STRICT_ RETARGETABLE_ WINDOWSRUNTIME_ NOPLATFORM_ +%token METHOD_ FIELD_ PINNED_ MODREQ_ MODOPT_ SERIALIZABLE_ PROPERTY_ TYPE_ +%token ASSEMBLY_ FAMANDASSEM_ FAMORASSEM_ PRIVATESCOPE_ HIDEBYSIG_ NEWSLOT_ RTSPECIALNAME_ PINVOKEIMPL_ +%token _CTOR _CCTOR LITERAL_ NOTSERIALIZED_ INITONLY_ REQSECOBJ_ + /* method implementation attributes: NATIVE_ and UNMANAGED_ listed above */ +%token CIL_ OPTIL_ MANAGED_ FORWARDREF_ PRESERVESIG_ RUNTIME_ INTERNALCALL_ + /* PInvoke-specific keywords */ +%token _IMPORT NOMANGLE_ LASTERR_ WINAPI_ AS_ BESTFIT_ ON_ OFF_ CHARMAPERROR_ + + /* intruction tokens (actually instruction groupings) */ +%token <opcode> INSTR_NONE INSTR_VAR INSTR_I INSTR_I8 INSTR_R INSTR_BRTARGET INSTR_METHOD INSTR_FIELD +%token <opcode> INSTR_TYPE INSTR_STRING INSTR_SIG INSTR_TOK +%token <opcode> INSTR_SWITCH + + /* assember directives */ +%token _CLASS _NAMESPACE _METHOD _FIELD _DATA _THIS _BASE _NESTER +%token _EMITBYTE _TRY _MAXSTACK _LOCALS _ENTRYPOINT _ZEROINIT +%token _EVENT _ADDON _REMOVEON _FIRE _OTHER +%token _PROPERTY _SET _GET DEFAULT_ +%token _PERMISSION _PERMISSIONSET + + /* security actions */ +%token REQUEST_ DEMAND_ ASSERT_ DENY_ PERMITONLY_ LINKCHECK_ INHERITCHECK_ +%token REQMIN_ REQOPT_ REQREFUSE_ PREJITGRANT_ PREJITDENY_ NONCASDEMAND_ +%token NONCASLINKDEMAND_ NONCASINHERITANCE_ + + /* extern debug info specifier (to be used by precompilers only) */ +%token _LINE P_LINE _LANGUAGE + /* custom value specifier */ +%token _CUSTOM + /* local vars zeroinit specifier */ +%token INIT_ + /* class layout */ +%token _SIZE _PACK +%token _VTABLE _VTFIXUP FROMUNMANAGED_ CALLMOSTDERIVED_ _VTENTRY RETAINAPPDOMAIN_ + /* manifest */ +%token _FILE NOMETADATA_ _HASH _ASSEMBLY _PUBLICKEY _PUBLICKEYTOKEN ALGORITHM_ _VER _LOCALE EXTERN_ +%token _MRESOURCE +%token _MODULE _EXPORT +%token LEGACY_ LIBRARY_ X86_ AMD64_ ARM_ ARM64_ + /* field marshaling */ +%token MARSHAL_ CUSTOM_ SYSSTRING_ FIXED_ VARIANT_ CURRENCY_ SYSCHAR_ DECIMAL_ DATE_ BSTR_ TBSTR_ LPSTR_ +%token LPWSTR_ LPTSTR_ OBJECTREF_ IUNKNOWN_ IDISPATCH_ STRUCT_ SAFEARRAY_ BYVALSTR_ LPVOID_ ANY_ ARRAY_ LPSTRUCT_ +%token IIDPARAM_ + /* parameter keywords */ +%token IN_ OUT_ OPT_ + /* .param directive */ +%token _PARAM + /* method implementations */ +%token _OVERRIDE WITH_ + /* variant type specifics */ +%token NULL_ ERROR_ HRESULT_ CARRAY_ USERDEFINED_ RECORD_ FILETIME_ BLOB_ STREAM_ STORAGE_ +%token STREAMED_OBJECT_ STORED_OBJECT_ BLOB_OBJECT_ CF_ CLSID_ VECTOR_ + /* header flags */ +%token _SUBSYSTEM _CORFLAGS ALIGNMENT_ _IMAGEBASE _STACKRESERVE + + /* syntactic sugar */ +%token _TYPEDEF _TEMPLATE _TYPELIST _MSCORLIB + + /* compilation control directives */ +%token P_DEFINE P_UNDEF P_IFDEF P_IFNDEF P_ELSE P_ENDIF P_INCLUDE + + /* newly added tokens go here */ +%token CONSTRAINT_ + + /* nonTerminals */ +%type <string> dottedName id methodName atOpt slashedName +%type <labels> labels +%type <int32> callConv callKind int32 customHead customHeadWithOwner vtfixupAttr paramAttr ddItemCount variantType repeatOpt truefalse typarAttrib typarAttribs +%type <int32> iidParamIndex genArity genArityNotEmpty +%type <float64> float64 +%type <int64> int64 +%type <binstr> sigArgs0 sigArgs1 sigArg type bound bounds1 bytes hexbytes nativeType marshalBlob initOpt compQstring caValue +%type <binstr> marshalClause +%type <binstr> fieldInit serInit fieldSerInit +%type <binstr> f32seq f64seq i8seq i16seq i32seq i64seq boolSeq sqstringSeq classSeq objSeq +%type <binstr> simpleType +%type <binstr> tyArgs0 tyArgs1 tyArgs2 typeList typeListNotEmpty tyBound +%type <binstr> customBlobDescr serializType customBlobArgs customBlobNVPairs +%type <binstr> secAttrBlob secAttrSetBlob +%type <int32> fieldOrProp intOrWildcard +%type <typarlist> typarsRest typars typarsClause +%type <token> className typeSpec ownerType customType memberRef methodRef mdtoken +%type <classAttr> classAttr +%type <methAttr> methAttr +%type <fieldAttr> fieldAttr +%type <implAttr> implAttr +%type <eventAttr> eventAttr +%type <propAttr> propAttr +%type <pinvAttr> pinvAttr +%type <pair> nameValPairs nameValPair +%type <secAct> secAction +%type <secAct> psetHead +%type <fileAttr> fileAttr +%type <fileAttr> fileEntry +%type <asmAttr> asmAttr +%type <exptAttr> exptAttr +%type <manresAttr> manresAttr +%type <cad> customDescr customDescrWithOwner +%type <instr> instr_none instr_var instr_i instr_i8 instr_r instr_brtarget instr_method instr_field +%type <instr> instr_type instr_string instr_sig instr_tok instr_switch +%type <instr> instr_r_head + +%start decls + +/**************************************************************************/ +%% + +decls : /* EMPTY */ + | decls decl + ; +/* Module-level declarations */ +decl : classHead '{' classDecls '}' { PASM->EndClass(); } + | nameSpaceHead '{' decls '}' { PASM->EndNameSpace(); } + | methodHead methodDecls '}' { if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } + | fieldDecl + | dataDecl + | vtableDecl + | vtfixupDecl + | extSourceSpec + | fileDecl + | assemblyHead '{' assemblyDecls '}' { PASMM->EndAssembly(); } + | assemblyRefHead '{' assemblyRefDecls '}' { PASMM->EndAssembly(); } + | exptypeHead '{' exptypeDecls '}' { PASMM->EndComType(); } + | manifestResHead '{' manifestResDecls '}' { PASMM->EndManifestRes(); } + | moduleHead + | secDecl + | customAttrDecl + | _SUBSYSTEM int32 { +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22011) // Suppress PREFast warning about integer overflow/underflow +#endif + PASM->m_dwSubsystem = $2; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + } + | _CORFLAGS int32 { PASM->m_dwComImageFlags = $2; } + | _FILE ALIGNMENT_ int32 { PASM->m_dwFileAlignment = $3; + if(($3 & ($3 - 1))||($3 < 0x200)||($3 > 0x10000)) + PASM->report->error("Invalid file alignment, must be power of 2 from 0x200 to 0x10000\n");} + | _IMAGEBASE int64 { PASM->m_stBaseAddress = (ULONGLONG)(*($2)); delete $2; + if(PASM->m_stBaseAddress & 0xFFFF) + PASM->report->error("Invalid image base, must be 0x10000-aligned\n");} + | _STACKRESERVE int64 { PASM->m_stSizeOfStackReserve = (size_t)(*($2)); delete $2; } + | languageDecl + | typedefDecl + | compControl + | _TYPELIST '{' classNameSeq '}' + | _MSCORLIB { PASM->m_fIsMscorlib = TRUE; } + ; + +classNameSeq : /* EMPTY */ + | className classNameSeq + ; + +compQstring : QSTRING { $$ = $1; } + | compQstring '+' QSTRING { $$ = $1; $$->append($3); delete $3; } + ; + +languageDecl : _LANGUAGE SQSTRING { LPCSTRToGuid($2,&(PASM->m_guidLang)); } + | _LANGUAGE SQSTRING ',' SQSTRING { LPCSTRToGuid($2,&(PASM->m_guidLang)); + LPCSTRToGuid($4,&(PASM->m_guidLangVendor));} + | _LANGUAGE SQSTRING ',' SQSTRING ',' SQSTRING { LPCSTRToGuid($2,&(PASM->m_guidLang)); + LPCSTRToGuid($4,&(PASM->m_guidLangVendor)); + LPCSTRToGuid($4,&(PASM->m_guidDoc));} + ; +/* Basic tokens */ +id : ID { $$ = $1; } + | SQSTRING { $$ = $1; } + ; + +dottedName : id { $$ = $1; } + | DOTTEDNAME { $$ = $1; } + | dottedName '.' dottedName { $$ = newStringWDel($1, '.', $3); } + ; + +int32 : INT32 { $$ = $1; } + ; + +int64 : INT64 { $$ = $1; } + | INT32 { $$ = neg ? new __int64($1) : new __int64((unsigned)$1); } + ; + +float64 : FLOAT64 { $$ = $1; } + | FLOAT32_ '(' int32 ')' { float f; *((__int32*) (&f)) = $3; $$ = new double(f); } + | FLOAT64_ '(' int64 ')' { $$ = (double*) $3; } + ; + +/* Aliasing of types, type specs, methods, fields and custom attributes */ +typedefDecl : _TYPEDEF type AS_ dottedName { PASM->AddTypeDef($2,$4); } + | _TYPEDEF className AS_ dottedName { PASM->AddTypeDef($2,$4); } + | _TYPEDEF memberRef AS_ dottedName { PASM->AddTypeDef($2,$4); } + | _TYPEDEF customDescr AS_ dottedName { $2->tkOwner = 0; PASM->AddTypeDef($2,$4); } + | _TYPEDEF customDescrWithOwner AS_ dottedName { PASM->AddTypeDef($2,$4); } + ; + +/* Compilation control directives are processed within yylex(), + displayed here just for grammar completeness */ +compControl : P_DEFINE dottedName { DefineVar($2, NULL); } + | P_DEFINE dottedName compQstring { DefineVar($2, $3); } + | P_UNDEF dottedName { UndefVar($2); } + | P_IFDEF dottedName { SkipToken = !IsVarDefined($2); + IfEndif++; + } + | P_IFNDEF dottedName { SkipToken = IsVarDefined($2); + IfEndif++; + } + | P_ELSE { if(IfEndif == 1) SkipToken = !SkipToken;} + | P_ENDIF { if(IfEndif == 0) + PASM->report->error("Unmatched #endif\n"); + else IfEndif--; + } + | P_INCLUDE QSTRING { _ASSERTE(!"yylex should have dealt with this"); } + | ';' { } + ; + +/* Custom attribute declarations */ +customDescr : _CUSTOM customType { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $2, NULL); } + | _CUSTOM customType '=' compQstring { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $2, $4); } + | _CUSTOM customType '=' '{' customBlobDescr '}' { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $2, $5); } + | customHead bytes ')' { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $1, $2); } + ; + +customDescrWithOwner : _CUSTOM '(' ownerType ')' customType { $$ = new CustomDescr($3, $5, NULL); } + | _CUSTOM '(' ownerType ')' customType '=' compQstring { $$ = new CustomDescr($3, $5, $7); } + | _CUSTOM '(' ownerType ')' customType '=' '{' customBlobDescr '}' + { $$ = new CustomDescr($3, $5, $8); } + | customHeadWithOwner bytes ')' { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $1, $2); } + ; + +customHead : _CUSTOM customType '=' '(' { $$ = $2; bParsingByteArray = TRUE; } + ; + +customHeadWithOwner : _CUSTOM '(' ownerType ')' customType '=' '(' + { PASM->m_pCustomDescrList = NULL; + PASM->m_tkCurrentCVOwner = $3; + $$ = $5; bParsingByteArray = TRUE; } + ; + +customType : methodRef { $$ = $1; } + ; + +ownerType : typeSpec { $$ = $1; } + | memberRef { $$ = $1; } + ; + +/* Verbal description of custom attribute initialization blob */ +customBlobDescr : customBlobArgs customBlobNVPairs { $$ = $1; + $$->appendInt16(nCustomBlobNVPairs); + $$->append($2); + nCustomBlobNVPairs = 0; } + ; + +customBlobArgs : /* EMPTY */ { $$ = new BinStr(); $$->appendInt16(VAL16(0x0001)); } + | customBlobArgs serInit { $$ = $1; + $$->appendFrom($2, (*($2->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); } + | customBlobArgs compControl { $$ = $1; } + ; + +customBlobNVPairs : /* EMPTY */ { $$ = new BinStr(); } + | customBlobNVPairs fieldOrProp serializType dottedName '=' serInit + { $$ = $1; $$->appendInt8($2); + $$->append($3); + AppendStringWithLength($$,$4); + $$->appendFrom($6, (*($6->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); + nCustomBlobNVPairs++; } + | customBlobNVPairs compControl { $$ = $1; } + ; + +fieldOrProp : FIELD_ { $$ = SERIALIZATION_TYPE_FIELD; } + | PROPERTY_ { $$ = SERIALIZATION_TYPE_PROPERTY; } + ; + +customAttrDecl : customDescr { if($1->tkOwner && !$1->tkInterfacePair) + PASM->DefineCV($1); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH($1); } + | customDescrWithOwner { PASM->DefineCV($1); } + | TYPEDEF_CA { CustomDescr* pNew = new CustomDescr($1->m_pCA); + if(pNew->tkOwner == 0) pNew->tkOwner = PASM->m_tkCurrentCVOwner; + if(pNew->tkOwner) + PASM->DefineCV(pNew); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(pNew); } + ; + +serializType : simpleType { $$ = $1; } + | TYPE_ { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); } + | OBJECT_ { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); } + | ENUM_ CLASS_ SQSTRING { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength($$,$3); } + | ENUM_ className { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength($$,PASM->ReflectionNotation($2)); } + | serializType '[' ']' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + ; + + +/* Module declaration */ +moduleHead : _MODULE { PASMM->SetModuleName(NULL); PASM->m_tkCurrentCVOwner=1; } + | _MODULE dottedName { PASMM->SetModuleName($2); PASM->m_tkCurrentCVOwner=1; } + | _MODULE EXTERN_ dottedName { BinStr* pbs = new BinStr(); + unsigned L = (unsigned)strlen($3); + memcpy((char*)(pbs->getBuff(L)),$3,L); + PASM->EmitImport(pbs); delete pbs;} + ; + +/* VTable Fixup table declaration */ +vtfixupDecl : _VTFIXUP '[' int32 ']' vtfixupAttr AT_ id { /*PASM->SetDataSection(); PASM->EmitDataLabel($7);*/ + PASM->m_VTFList.PUSH(new VTFEntry((USHORT)$3, (USHORT)$5, $7)); } + ; + +vtfixupAttr : /* EMPTY */ { $$ = 0; } + | vtfixupAttr INT32_ { $$ = $1 | COR_VTABLE_32BIT; } + | vtfixupAttr INT64_ { $$ = $1 | COR_VTABLE_64BIT; } + | vtfixupAttr FROMUNMANAGED_ { $$ = $1 | COR_VTABLE_FROM_UNMANAGED; } + | vtfixupAttr CALLMOSTDERIVED_ { $$ = $1 | COR_VTABLE_CALL_MOST_DERIVED; } + | vtfixupAttr RETAINAPPDOMAIN_ { $$ = $1 | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN; } + ; + +vtableDecl : vtableHead bytes ')' /* deprecated */ { PASM->m_pVTable = $2; } + ; + +vtableHead : _VTABLE '=' '(' /* deprecated */ { bParsingByteArray = TRUE; } + ; + +/* Namespace and class declaration */ +nameSpaceHead : _NAMESPACE dottedName { PASM->StartNameSpace($2); } + ; + +_class : _CLASS { newclass = TRUE; } + ; + +classHeadBegin : _class classAttr dottedName typarsClause { if($4) FixupConstraints(); + PASM->StartClass($3, $2, $4); + TyParFixupList.RESET(false); + newclass = FALSE; + } + ; +classHead : classHeadBegin extendsClause implClause { PASM->AddClass(); } + ; + +classAttr : /* EMPTY */ { $$ = (CorRegTypeAttr) 0; } + | classAttr PUBLIC_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdPublic); } + | classAttr PRIVATE_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNotPublic); } + | classAttr VALUE_ { $$ = (CorRegTypeAttr) ($1 | 0x80000000 | tdSealed); } + | classAttr ENUM_ { $$ = (CorRegTypeAttr) ($1 | 0x40000000); } + | classAttr INTERFACE_ { $$ = (CorRegTypeAttr) ($1 | tdInterface | tdAbstract); } + | classAttr SEALED_ { $$ = (CorRegTypeAttr) ($1 | tdSealed); } + | classAttr ABSTRACT_ { $$ = (CorRegTypeAttr) ($1 | tdAbstract); } + | classAttr AUTO_ { $$ = (CorRegTypeAttr) (($1 & ~tdLayoutMask) | tdAutoLayout); } + | classAttr SEQUENTIAL_ { $$ = (CorRegTypeAttr) (($1 & ~tdLayoutMask) | tdSequentialLayout); } + | classAttr EXPLICIT_ { $$ = (CorRegTypeAttr) (($1 & ~tdLayoutMask) | tdExplicitLayout); } + | classAttr ANSI_ { $$ = (CorRegTypeAttr) (($1 & ~tdStringFormatMask) | tdAnsiClass); } + | classAttr UNICODE_ { $$ = (CorRegTypeAttr) (($1 & ~tdStringFormatMask) | tdUnicodeClass); } + | classAttr AUTOCHAR_ { $$ = (CorRegTypeAttr) (($1 & ~tdStringFormatMask) | tdAutoClass); } + | classAttr IMPORT_ { $$ = (CorRegTypeAttr) ($1 | tdImport); } + | classAttr SERIALIZABLE_ { $$ = (CorRegTypeAttr) ($1 | tdSerializable); } + | classAttr WINDOWSRUNTIME_ { $$ = (CorRegTypeAttr) ($1 | tdWindowsRuntime); } + | classAttr NESTED_ PUBLIC_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedPublic); } + | classAttr NESTED_ PRIVATE_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedPrivate); } + | classAttr NESTED_ FAMILY_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedFamily); } + | classAttr NESTED_ ASSEMBLY_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedAssembly); } + | classAttr NESTED_ FAMANDASSEM_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedFamANDAssem); } + | classAttr NESTED_ FAMORASSEM_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedFamORAssem); } + | classAttr BEFOREFIELDINIT_ { $$ = (CorRegTypeAttr) ($1 | tdBeforeFieldInit); } + | classAttr SPECIALNAME_ { $$ = (CorRegTypeAttr) ($1 | tdSpecialName); } + | classAttr RTSPECIALNAME_ { $$ = (CorRegTypeAttr) ($1); } + | classAttr FLAGS_ '(' int32 ')' { $$ = (CorRegTypeAttr) ($4); } + ; + +extendsClause : /* EMPTY */ + | EXTENDS_ typeSpec { PASM->m_crExtends = $2; } + ; + +implClause : /* EMPTY */ + | IMPLEMENTS_ implList + ; + +classDecls : /* EMPTY */ + | classDecls classDecl + ; + +implList : implList ',' typeSpec { PASM->AddToImplList($3); } + | typeSpec { PASM->AddToImplList($1); } + ; + +/* Generic type parameters declaration */ +typeList : /* EMPTY */ { $$ = new BinStr(); } + | typeListNotEmpty { $$ = $1; } + ; + +typeListNotEmpty : typeSpec { $$ = new BinStr(); $$->appendInt32($1); } + | typeListNotEmpty ',' typeSpec { $$ = $1; $$->appendInt32($3); } + ; + +typarsClause : /* EMPTY */ { $$ = NULL; PASM->m_TyParList = NULL;} + | '<' typars '>' { $$ = $2; PASM->m_TyParList = $2;} + ; + +typarAttrib : '+' { $$ = gpCovariant; } + | '-' { $$ = gpContravariant; } + | CLASS_ { $$ = gpReferenceTypeConstraint; } + | VALUETYPE_ { $$ = gpNotNullableValueTypeConstraint; } + | _CTOR { $$ = gpDefaultConstructorConstraint; } + ; + +typarAttribs : /* EMPTY */ { $$ = 0; } + | typarAttrib typarAttribs { $$ = $1 | $2; } + ; + +typars : typarAttribs tyBound dottedName typarsRest {$$ = new TyParList($1, $2, $3, $4);} + | typarAttribs dottedName typarsRest {$$ = new TyParList($1, NULL, $2, $3);} + ; + +typarsRest : /* EMPTY */ { $$ = NULL; } + | ',' typars { $$ = $2; } + ; + +tyBound : '(' typeList ')' { $$ = $2; } + ; + +genArity : /* EMPTY */ { $$= 0; } + | genArityNotEmpty { $$ = $1; } + ; + +genArityNotEmpty : '<' '[' int32 ']' '>' { $$ = $3; } + ; + +/* Class body declarations */ +classDecl : methodHead methodDecls '}' { if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } + | classHead '{' classDecls '}' { PASM->EndClass(); } + | eventHead '{' eventDecls '}' { PASM->EndEvent(); } + | propHead '{' propDecls '}' { PASM->EndProp(); } + | fieldDecl + | dataDecl + | secDecl + | extSourceSpec + | customAttrDecl + | _SIZE int32 { PASM->m_pCurClass->m_ulSize = $2; } + | _PACK int32 { PASM->m_pCurClass->m_ulPack = $2; } + | exportHead '{' exptypeDecls '}' { PASMM->EndComType(); } + | _OVERRIDE typeSpec DCOLON methodName WITH_ callConv type typeSpec DCOLON methodName '(' sigArgs0 ')' + { BinStr *sig1 = parser->MakeSig($6, $7, $12); + BinStr *sig2 = new BinStr(); sig2->append(sig1); + PASM->AddMethodImpl($2,$4,sig1,$8,$10,sig2); + PASM->ResetArgNameList(); + } + | _OVERRIDE METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' WITH_ METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' + { PASM->AddMethodImpl($5,$7, + ($8==0 ? parser->MakeSig($3,$4,$10) : + parser->MakeSig($3| IMAGE_CEE_CS_CALLCONV_GENERIC,$4,$10,$8)), + $16,$18, + ($19==0 ? parser->MakeSig($14,$15,$21) : + parser->MakeSig($14| IMAGE_CEE_CS_CALLCONV_GENERIC,$15,$21,$19))); + PASM->ResetArgNameList(); + } + | languageDecl + | compControl + | _PARAM TYPE_ '[' int32 ']' { if(($4 > 0) && ($4 <= (int)PASM->m_pCurClass->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[$4-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } + | _PARAM TYPE_ dottedName { int n = PASM->m_pCurClass->FindTyPar($3); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",$3); + } + | _PARAM CONSTRAINT_ '[' int32 ']' ',' typeSpec { PASM->AddGenericParamConstraint($4, 0, $7); } + | _PARAM CONSTRAINT_ dottedName ',' typeSpec { PASM->AddGenericParamConstraint(0, $3, $5); } + | _INTERFACEIMPL TYPE_ typeSpec customDescr { $4->tkInterfacePair = $3; + if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH($4); + } + ; + +/* Field declaration */ +fieldDecl : _FIELD repeatOpt fieldAttr type dottedName atOpt initOpt + { $4->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + PASM->AddField($5, $4, $3, $6, $7, $2); } + ; + +fieldAttr : /* EMPTY */ { $$ = (CorFieldAttr) 0; } + | fieldAttr STATIC_ { $$ = (CorFieldAttr) ($1 | fdStatic); } + | fieldAttr PUBLIC_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdPublic); } + | fieldAttr PRIVATE_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdPrivate); } + | fieldAttr FAMILY_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdFamily); } + | fieldAttr INITONLY_ { $$ = (CorFieldAttr) ($1 | fdInitOnly); } + | fieldAttr RTSPECIALNAME_ { $$ = $1; } /*{ $$ = (CorFieldAttr) ($1 | fdRTSpecialName); }*/ + | fieldAttr SPECIALNAME_ { $$ = (CorFieldAttr) ($1 | fdSpecialName); } + /* <STRIP>commented out because PInvoke for fields is not supported by EE + | fieldAttr PINVOKEIMPL_ '(' compQstring AS_ compQstring pinvAttr ')' + { $$ = (CorFieldAttr) ($1 | fdPinvokeImpl); + PASM->SetPinvoke($4,0,$6,$7); } + | fieldAttr PINVOKEIMPL_ '(' compQstring pinvAttr ')' + { $$ = (CorFieldAttr) ($1 | fdPinvokeImpl); + PASM->SetPinvoke($4,0,NULL,$5); } + | fieldAttr PINVOKEIMPL_ '(' pinvAttr ')' + { PASM->SetPinvoke(new BinStr(),0,NULL,$4); + $$ = (CorFieldAttr) ($1 | fdPinvokeImpl); } + </STRIP>*/ + | fieldAttr MARSHAL_ '(' marshalBlob ')' + { PASM->m_pMarshal = $4; } + | fieldAttr ASSEMBLY_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdAssembly); } + | fieldAttr FAMANDASSEM_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdFamANDAssem); } + | fieldAttr FAMORASSEM_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdFamORAssem); } + | fieldAttr PRIVATESCOPE_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdPrivateScope); } + | fieldAttr LITERAL_ { $$ = (CorFieldAttr) ($1 | fdLiteral); } + | fieldAttr NOTSERIALIZED_ { $$ = (CorFieldAttr) ($1 | fdNotSerialized); } + | fieldAttr FLAGS_ '(' int32 ')' { $$ = (CorFieldAttr) ($4); } + ; + +atOpt : /* EMPTY */ { $$ = 0; } + | AT_ id { $$ = $2; } + ; + +initOpt : /* EMPTY */ { $$ = NULL; } + | '=' fieldInit { $$ = $2; } + ; + +repeatOpt : /* EMPTY */ { $$ = 0xFFFFFFFF; } + | '[' int32 ']' { $$ = $2; } + ; + +/* Method referencing */ +methodRef : callConv type typeSpec DCOLON methodName tyArgs0 '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if ($6 == NULL) + { + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef($3, $5, parser->MakeSig($1|iCallConv, $2, $8)); + } + else + { + mdToken mr; + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef($3, $5, + parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $8, corCountArgs($6))); + $$ = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, $6)); + } + } + | callConv type typeSpec DCOLON methodName genArityNotEmpty '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef($3, $5, + parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $8, $6)); + } + | callConv type methodName tyArgs0 '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if ($4 == NULL) + { + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef(mdTokenNil, $3, parser->MakeSig($1|iCallConv, $2, $6)); + } + else + { + mdToken mr; + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef(mdTokenNil, $3, parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $6, corCountArgs($4))); + $$ = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, $4)); + } + } + | callConv type methodName genArityNotEmpty '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef(mdTokenNil, $3, parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $6, $4)); + } + | mdtoken { $$ = $1; } + | TYPEDEF_M { $$ = $1->m_tkTypeSpec; } + | TYPEDEF_MR { $$ = $1->m_tkTypeSpec; } + ; + +callConv : INSTANCE_ callConv { $$ = ($2 | IMAGE_CEE_CS_CALLCONV_HASTHIS); } + | EXPLICIT_ callConv { $$ = ($2 | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); } + | callKind { $$ = $1; } + | CALLCONV_ '(' int32 ')' { $$ = $3; } + ; + +callKind : /* EMPTY */ { $$ = IMAGE_CEE_CS_CALLCONV_DEFAULT; } + | DEFAULT_ { $$ = IMAGE_CEE_CS_CALLCONV_DEFAULT; } + | VARARG_ { $$ = IMAGE_CEE_CS_CALLCONV_VARARG; } + | UNMANAGED_ CDECL_ { $$ = IMAGE_CEE_CS_CALLCONV_C; } + | UNMANAGED_ STDCALL_ { $$ = IMAGE_CEE_CS_CALLCONV_STDCALL; } + | UNMANAGED_ THISCALL_ { $$ = IMAGE_CEE_CS_CALLCONV_THISCALL; } + | UNMANAGED_ FASTCALL_ { $$ = IMAGE_CEE_CS_CALLCONV_FASTCALL; } + | UNMANAGED_ { $$ = IMAGE_CEE_CS_CALLCONV_UNMANAGED; } + ; + +mdtoken : MDTOKEN_ '(' int32 ')' { $$ = $3; } + ; + +memberRef : methodSpec methodRef { $$ = $2; + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + PASM->SetMemberRefFixup($2,iOpcodeLen); } + | FIELD_ type typeSpec DCOLON dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + $$ = PASM->MakeMemberRef($3, $5, $2); + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | FIELD_ type dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + $$ = PASM->MakeMemberRef(NULL, $3, $2); + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | FIELD_ TYPEDEF_F { $$ = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | FIELD_ TYPEDEF_MR { $$ = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | mdtoken { $$ = $1; + PASM->SetMemberRefFixup($$,iOpcodeLen); } + ; + +/* Event declaration */ +eventHead : _EVENT eventAttr typeSpec dottedName { PASM->ResetEvent($4, $3, $2); } + | _EVENT eventAttr dottedName { PASM->ResetEvent($3, mdTypeRefNil, $2); } + ; + + +eventAttr : /* EMPTY */ { $$ = (CorEventAttr) 0; } + | eventAttr RTSPECIALNAME_ { $$ = $1; }/*{ $$ = (CorEventAttr) ($1 | evRTSpecialName); }*/ + | eventAttr SPECIALNAME_ { $$ = (CorEventAttr) ($1 | evSpecialName); } + ; + +eventDecls : /* EMPTY */ + | eventDecls eventDecl + ; + +eventDecl : _ADDON methodRef { PASM->SetEventMethod(0, $2); } + | _REMOVEON methodRef { PASM->SetEventMethod(1, $2); } + | _FIRE methodRef { PASM->SetEventMethod(2, $2); } + | _OTHER methodRef { PASM->SetEventMethod(3, $2); } + | extSourceSpec + | customAttrDecl + | languageDecl + | compControl + ; + +/* Property declaration */ +propHead : _PROPERTY propAttr callConv type dottedName '(' sigArgs0 ')' initOpt + { PASM->ResetProp($5, + parser->MakeSig((IMAGE_CEE_CS_CALLCONV_PROPERTY | + ($3 & IMAGE_CEE_CS_CALLCONV_HASTHIS)),$4,$7), $2, $9);} + ; + +propAttr : /* EMPTY */ { $$ = (CorPropertyAttr) 0; } + | propAttr RTSPECIALNAME_ { $$ = $1; }/*{ $$ = (CorPropertyAttr) ($1 | prRTSpecialName); }*/ + | propAttr SPECIALNAME_ { $$ = (CorPropertyAttr) ($1 | prSpecialName); } + ; + +propDecls : /* EMPTY */ + | propDecls propDecl + ; + + +propDecl : _SET methodRef { PASM->SetPropMethod(0, $2); } + | _GET methodRef { PASM->SetPropMethod(1, $2); } + | _OTHER methodRef { PASM->SetPropMethod(2, $2); } + | customAttrDecl + | extSourceSpec + | languageDecl + | compControl + ; + +/* Method declaration */ +methodHeadPart1 : _METHOD { PASM->ResetForNextMethod(); + uMethodBeginLine = PASM->m_ulCurLine; + uMethodBeginColumn=PASM->m_ulCurColumn; + } + ; + +marshalClause : /* EMPTY */ { $$ = NULL; } + | MARSHAL_ '(' marshalBlob ')' { $$ = $3; } + ; + +marshalBlob : nativeType { $$ = $1; } + | marshalBlobHead hexbytes '}' { $$ = $2; } + ; + +marshalBlobHead : '{' { bParsingByteArray = TRUE; } + ; + +methodHead : methodHeadPart1 methAttr callConv paramAttr type marshalClause methodName typarsClause'(' sigArgs0 ')' implAttr '{' + { BinStr* sig; + if ($8 == NULL) sig = parser->MakeSig($3, $5, $10); + else { + FixupTyPars($5); + sig = parser->MakeSig($3 | IMAGE_CEE_CS_CALLCONV_GENERIC, $5, $10, $8->Count()); + FixupConstraints(); + } + PASM->StartMethod($7, sig, $2, $6, $4, $8); + TyParFixupList.RESET(false); + PASM->SetImplAttr((USHORT)$12); + PASM->m_pCurMethod->m_ulLines[0] = uMethodBeginLine; + PASM->m_pCurMethod->m_ulColumns[0]=uMethodBeginColumn; + } + ; + +methAttr : /* EMPTY */ { $$ = (CorMethodAttr) 0; } + | methAttr STATIC_ { $$ = (CorMethodAttr) ($1 | mdStatic); } + | methAttr PUBLIC_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdPublic); } + | methAttr PRIVATE_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdPrivate); } + | methAttr FAMILY_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdFamily); } + | methAttr FINAL_ { $$ = (CorMethodAttr) ($1 | mdFinal); } + | methAttr SPECIALNAME_ { $$ = (CorMethodAttr) ($1 | mdSpecialName); } + | methAttr VIRTUAL_ { $$ = (CorMethodAttr) ($1 | mdVirtual); } + | methAttr STRICT_ { $$ = (CorMethodAttr) ($1 | mdCheckAccessOnOverride); } + | methAttr ABSTRACT_ { $$ = (CorMethodAttr) ($1 | mdAbstract); } + | methAttr ASSEMBLY_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdAssem); } + | methAttr FAMANDASSEM_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdFamANDAssem); } + | methAttr FAMORASSEM_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdFamORAssem); } + | methAttr PRIVATESCOPE_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdPrivateScope); } + | methAttr HIDEBYSIG_ { $$ = (CorMethodAttr) ($1 | mdHideBySig); } + | methAttr NEWSLOT_ { $$ = (CorMethodAttr) ($1 | mdNewSlot); } + | methAttr RTSPECIALNAME_ { $$ = $1; }/*{ $$ = (CorMethodAttr) ($1 | mdRTSpecialName); }*/ + | methAttr UNMANAGEDEXP_ { $$ = (CorMethodAttr) ($1 | mdUnmanagedExport); } + | methAttr REQSECOBJ_ { $$ = (CorMethodAttr) ($1 | mdRequireSecObject); } + | methAttr FLAGS_ '(' int32 ')' { $$ = (CorMethodAttr) ($4); } + | methAttr PINVOKEIMPL_ '(' compQstring AS_ compQstring pinvAttr ')' + { PASM->SetPinvoke($4,0,$6,$7); + $$ = (CorMethodAttr) ($1 | mdPinvokeImpl); } + | methAttr PINVOKEIMPL_ '(' compQstring pinvAttr ')' + { PASM->SetPinvoke($4,0,NULL,$5); + $$ = (CorMethodAttr) ($1 | mdPinvokeImpl); } + | methAttr PINVOKEIMPL_ '(' pinvAttr ')' + { PASM->SetPinvoke(new BinStr(),0,NULL,$4); + $$ = (CorMethodAttr) ($1 | mdPinvokeImpl); } + ; + +pinvAttr : /* EMPTY */ { $$ = (CorPinvokeMap) 0; } + | pinvAttr NOMANGLE_ { $$ = (CorPinvokeMap) ($1 | pmNoMangle); } + | pinvAttr ANSI_ { $$ = (CorPinvokeMap) ($1 | pmCharSetAnsi); } + | pinvAttr UNICODE_ { $$ = (CorPinvokeMap) ($1 | pmCharSetUnicode); } + | pinvAttr AUTOCHAR_ { $$ = (CorPinvokeMap) ($1 | pmCharSetAuto); } + | pinvAttr LASTERR_ { $$ = (CorPinvokeMap) ($1 | pmSupportsLastError); } + | pinvAttr WINAPI_ { $$ = (CorPinvokeMap) ($1 | pmCallConvWinapi); } + | pinvAttr CDECL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvCdecl); } + | pinvAttr STDCALL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvStdcall); } + | pinvAttr THISCALL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvThiscall); } + | pinvAttr FASTCALL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvFastcall); } + | pinvAttr BESTFIT_ ':' ON_ { $$ = (CorPinvokeMap) ($1 | pmBestFitEnabled); } + | pinvAttr BESTFIT_ ':' OFF_ { $$ = (CorPinvokeMap) ($1 | pmBestFitDisabled); } + | pinvAttr CHARMAPERROR_ ':' ON_ { $$ = (CorPinvokeMap) ($1 | pmThrowOnUnmappableCharEnabled); } + | pinvAttr CHARMAPERROR_ ':' OFF_ { $$ = (CorPinvokeMap) ($1 | pmThrowOnUnmappableCharDisabled); } + | pinvAttr FLAGS_ '(' int32 ')' { $$ = (CorPinvokeMap) ($4); } + ; + +methodName : _CTOR { $$ = newString(COR_CTOR_METHOD_NAME); } + | _CCTOR { $$ = newString(COR_CCTOR_METHOD_NAME); } + | dottedName { $$ = $1; } + ; + +paramAttr : /* EMPTY */ { $$ = 0; } + | paramAttr '[' IN_ ']' { $$ = $1 | pdIn; } + | paramAttr '[' OUT_ ']' { $$ = $1 | pdOut; } + | paramAttr '[' OPT_ ']' { $$ = $1 | pdOptional; } + | paramAttr '[' int32 ']' { $$ = $3 + 1; } + ; + +implAttr : /* EMPTY */ { $$ = (CorMethodImpl) (miIL | miManaged); } + | implAttr NATIVE_ { $$ = (CorMethodImpl) (($1 & 0xFFF4) | miNative); } + | implAttr CIL_ { $$ = (CorMethodImpl) (($1 & 0xFFF4) | miIL); } + | implAttr OPTIL_ { $$ = (CorMethodImpl) (($1 & 0xFFF4) | miOPTIL); } + | implAttr MANAGED_ { $$ = (CorMethodImpl) (($1 & 0xFFFB) | miManaged); } + | implAttr UNMANAGED_ { $$ = (CorMethodImpl) (($1 & 0xFFFB) | miUnmanaged); } + | implAttr FORWARDREF_ { $$ = (CorMethodImpl) ($1 | miForwardRef); } + | implAttr PRESERVESIG_ { $$ = (CorMethodImpl) ($1 | miPreserveSig); } + | implAttr RUNTIME_ { $$ = (CorMethodImpl) ($1 | miRuntime); } + | implAttr INTERNALCALL_ { $$ = (CorMethodImpl) ($1 | miInternalCall); } + | implAttr SYNCHRONIZED_ { $$ = (CorMethodImpl) ($1 | miSynchronized); } + | implAttr NOINLINING_ { $$ = (CorMethodImpl) ($1 | miNoInlining); } + | implAttr AGGRESSIVEINLINING_ { $$ = (CorMethodImpl) ($1 | miAggressiveInlining); } + | implAttr NOOPTIMIZATION_ { $$ = (CorMethodImpl) ($1 | miNoOptimization); } + | implAttr AGGRESSIVEOPTIMIZATION_ { $$ = (CorMethodImpl) ($1 | miAggressiveOptimization); } + | implAttr FLAGS_ '(' int32 ')' { $$ = (CorMethodImpl) ($4); } + ; + +localsHead : _LOCALS { PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = NULL;PASM->m_lastArgName = NULL; + } + ; + +methodDecls : /* EMPTY */ + | methodDecls methodDecl + ; + +methodDecl : _EMITBYTE int32 { PASM->EmitByte($2); } + | sehBlock { delete PASM->m_SEHD; PASM->m_SEHD = PASM->m_SEHDstack.POP(); } + | _MAXSTACK int32 { PASM->EmitMaxStack($2); } + | localsHead '(' sigArgs0 ')' { PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, $3)); + } + | localsHead INIT_ '(' sigArgs0 ')' { PASM->EmitZeroInit(); + PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, $4)); + } + | _ENTRYPOINT { PASM->EmitEntryPoint(); } + | _ZEROINIT { PASM->EmitZeroInit(); } + | dataDecl + | instr + | id ':' { PASM->AddLabel(PASM->m_CurPC,$1); /*PASM->EmitLabel($1);*/ } + | secDecl + | extSourceSpec + | languageDecl + | customAttrDecl + | compControl + | _EXPORT '[' int32 ']' { if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = $3; + PASM->m_pCurMethod->m_szExportAlias = NULL; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = $3 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } + | _EXPORT '[' int32 ']' AS_ id { if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = $3; + PASM->m_pCurMethod->m_szExportAlias = $6; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = $3 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } + | _VTENTRY int32 ':' int32 { PASM->m_pCurMethod->m_wVTEntry = (WORD)$2; + PASM->m_pCurMethod->m_wVTSlot = (WORD)$4; } + | _OVERRIDE typeSpec DCOLON methodName + { PASM->AddMethodImpl($2,$4,NULL,NULL,NULL,NULL); } + + | _OVERRIDE METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' + { PASM->AddMethodImpl($5,$7, + ($8==0 ? parser->MakeSig($3,$4,$10) : + parser->MakeSig($3| IMAGE_CEE_CS_CALLCONV_GENERIC,$4,$10,$8)) + ,NULL,NULL,NULL); + PASM->ResetArgNameList(); + } + | scopeBlock + | _PARAM TYPE_ '[' int32 ']' { if(($4 > 0) && ($4 <= (int)PASM->m_pCurMethod->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[$4-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } + | _PARAM TYPE_ dottedName { int n = PASM->m_pCurMethod->FindTyPar($3); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",$3); + } + | _PARAM CONSTRAINT_ '[' int32 ']' ',' typeSpec { PASM->m_pCurMethod->AddGenericParamConstraint($4, 0, $7); } + | _PARAM CONSTRAINT_ dottedName ',' typeSpec { PASM->m_pCurMethod->AddGenericParamConstraint(0, $3, $5); } + + | _PARAM '[' int32 ']' initOpt + { if( $3 ) { + ARG_NAME_LIST* pAN=PASM->findArg(PASM->m_pCurMethod->m_firstArgName, $3 - 1); + if(pAN) + { + PASM->m_pCustomDescrList = &(pAN->CustDList); + pAN->pValue = $5; + } + else + { + PASM->m_pCustomDescrList = NULL; + if($5) delete $5; + } + } else { + PASM->m_pCustomDescrList = &(PASM->m_pCurMethod->m_RetCustDList); + PASM->m_pCurMethod->m_pRetValue = $5; + } + PASM->m_tkCurrentCVOwner = 0; + } + ; + +scopeBlock : scopeOpen methodDecls '}' { PASM->m_pCurMethod->CloseScope(); } + ; + +scopeOpen : '{' { PASM->m_pCurMethod->OpenScope(); } + ; + +/* Structured exception handling directives */ +sehBlock : tryBlock sehClauses + ; + +sehClauses : sehClause sehClauses + | sehClause + ; + +tryBlock : tryHead scopeBlock { PASM->m_SEHD->tryTo = PASM->m_CurPC; } + | tryHead id TO_ id { PASM->SetTryLabels($2, $4); } + | tryHead int32 TO_ int32 { if(PASM->m_SEHD) {PASM->m_SEHD->tryFrom = $2; + PASM->m_SEHD->tryTo = $4;} } + ; + +tryHead : _TRY { PASM->NewSEHDescriptor(); + PASM->m_SEHD->tryFrom = PASM->m_CurPC; } + ; + + +sehClause : catchClause handlerBlock { PASM->EmitTry(); } + | filterClause handlerBlock { PASM->EmitTry(); } + | finallyClause handlerBlock { PASM->EmitTry(); } + | faultClause handlerBlock { PASM->EmitTry(); } + ; + + +filterClause : filterHead scopeBlock { PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + | filterHead id { PASM->SetFilterLabel($2); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + | filterHead int32 { PASM->m_SEHD->sehFilter = $2; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +filterHead : FILTER_ { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FILTER; + PASM->m_SEHD->sehFilter = PASM->m_CurPC; } + ; + +catchClause : CATCH_ typeSpec { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_NONE; + PASM->SetCatchClass($2); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +finallyClause : FINALLY_ { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FINALLY; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +faultClause : FAULT_ { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FAULT; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +handlerBlock : scopeBlock { PASM->m_SEHD->sehHandlerTo = PASM->m_CurPC; } + | HANDLER_ id TO_ id { PASM->SetHandlerLabels($2, $4); } + | HANDLER_ int32 TO_ int32 { PASM->m_SEHD->sehHandler = $2; + PASM->m_SEHD->sehHandlerTo = $4; } + ; + +/* Data declaration */ +dataDecl : ddHead ddBody + ; + +ddHead : _DATA tls id '=' { PASM->EmitDataLabel($3); } + | _DATA tls + ; + +tls : /* EMPTY */ { PASM->SetDataSection(); } + | TLS_ { PASM->SetTLSSection(); } + | CIL_ { PASM->SetILSection(); } + ; + +ddBody : '{' ddItemList '}' + | ddItem + ; + +ddItemList : ddItem ',' ddItemList + | ddItem + ; + +ddItemCount : /* EMPTY */ { $$ = 1; } + | '[' int32 ']' { $$ = $2; + if($2 <= 0) { PASM->report->error("Illegal item count: %d\n",$2); + if(!PASM->OnErrGo) $$ = 1; }} + ; + +ddItem : CHAR_ '*' '(' compQstring ')' { PASM->EmitDataString($4); } + | '&' '(' id ')' { PASM->EmitDD($3); } + | bytearrayhead bytes ')' { PASM->EmitData($2->ptr(),$2->length()); } + | FLOAT32_ '(' float64 ')' ddItemCount + { float f = (float) (*$3); float* p = new (nothrow) float[$5]; + if(p != NULL) { + for(int i=0; i < $5; i++) p[i] = f; + PASM->EmitData(p, sizeof(float)*$5); delete $3; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(float)*$5); } + | FLOAT64_ '(' float64 ')' ddItemCount + { double* p = new (nothrow) double[$5]; + if(p != NULL) { + for(int i=0; i<$5; i++) p[i] = *($3); + PASM->EmitData(p, sizeof(double)*$5); delete $3; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(double)*$5); } + | INT64_ '(' int64 ')' ddItemCount + { __int64* p = new (nothrow) __int64[$5]; + if(p != NULL) { + for(int i=0; i<$5; i++) p[i] = *($3); + PASM->EmitData(p, sizeof(__int64)*$5); delete $3; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int64)*$5); } + | INT32_ '(' int32 ')' ddItemCount + { __int32* p = new (nothrow) __int32[$5]; + if(p != NULL) { + for(int i=0; i<$5; i++) p[i] = $3; + PASM->EmitData(p, sizeof(__int32)*$5); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int32)*$5); } + | INT16_ '(' int32 ')' ddItemCount + { __int16 i = (__int16) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); + __int16* p = new (nothrow) __int16[$5]; + if(p != NULL) { + for(int j=0; j<$5; j++) p[j] = i; + PASM->EmitData(p, sizeof(__int16)*$5); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int16)*$5); } + | INT8_ '(' int32 ')' ddItemCount + { __int8 i = (__int8) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); + __int8* p = new (nothrow) __int8[$5]; + if(p != NULL) { + for(int j=0; j<$5; j++) p[j] = i; + PASM->EmitData(p, sizeof(__int8)*$5); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int8)*$5); } + | FLOAT32_ ddItemCount { PASM->EmitData(NULL, sizeof(float)*$2); } + | FLOAT64_ ddItemCount { PASM->EmitData(NULL, sizeof(double)*$2); } + | INT64_ ddItemCount { PASM->EmitData(NULL, sizeof(__int64)*$2); } + | INT32_ ddItemCount { PASM->EmitData(NULL, sizeof(__int32)*$2); } + | INT16_ ddItemCount { PASM->EmitData(NULL, sizeof(__int16)*$2); } + | INT8_ ddItemCount { PASM->EmitData(NULL, sizeof(__int8)*$2); } + ; + +/* Default values declaration for fields, parameters and verbal form of CA blob description */ +fieldSerInit : FLOAT32_ '(' float64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); + float f = (float)(*$3); + $$->appendInt32(*((__int32*)&f)); delete $3; } + | FLOAT64_ '(' float64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); + $$->appendInt64((__int64 *)$3); delete $3; } + | FLOAT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); + $$->appendInt32($3); } + | FLOAT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); + $$->appendInt64((__int64 *)$3); delete $3; } + | INT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I8); + $$->appendInt64((__int64 *)$3); delete $3; } + | INT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I4); + $$->appendInt32($3); } + | INT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I2); + $$->appendInt16($3); } + | INT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I1); + $$->appendInt8($3); } + | UNSIGNED_ INT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); + $$->appendInt64((__int64 *)$4); delete $4; } + | UNSIGNED_ INT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); + $$->appendInt32($4); } + | UNSIGNED_ INT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); + $$->appendInt16($4); } + | UNSIGNED_ INT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); + $$->appendInt8($4); } + | UINT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); + $$->appendInt64((__int64 *)$3); delete $3; } + | UINT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); + $$->appendInt32($3); } + | UINT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); + $$->appendInt16($3); } + | UINT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); + $$->appendInt8($3); } + | CHAR_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_CHAR); + $$->appendInt16($3); } + | BOOL_ '(' truefalse ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_BOOLEAN); + $$->appendInt8($3);} + | bytearrayhead bytes ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); + $$->append($2); delete $2;} + ; + +bytearrayhead : BYTEARRAY_ '(' { bParsingByteArray = TRUE; } + ; + +bytes : /* EMPTY */ { $$ = new BinStr(); } + | hexbytes { $$ = $1; } + ; + +hexbytes : HEXBYTE { __int8 i = (__int8) $1; $$ = new BinStr(); $$->appendInt8(i); } + | hexbytes HEXBYTE { __int8 i = (__int8) $2; $$ = $1; $$->appendInt8(i); } + ; + +/* Field/parameter initialization */ +fieldInit : fieldSerInit { $$ = $1; } + | compQstring { $$ = BinStrToUnicode($1,true); $$->insertInt8(ELEMENT_TYPE_STRING);} + | NULLREF_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_CLASS); + $$->appendInt32(0); } + ; + +/* Values for verbal form of CA blob description */ +serInit : fieldSerInit { $$ = $1; } + | STRING_ '(' NULLREF_ ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); $$->appendInt8(0xFF); } + | STRING_ '(' SQSTRING ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); + AppendStringWithLength($$,$3); delete [] $3;} + | TYPE_ '(' CLASS_ SQSTRING ')' { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength($$,$4); delete [] $4;} + | TYPE_ '(' className ')' { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength($$,PASM->ReflectionNotation($3));} + | TYPE_ '(' NULLREF_ ')' { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); $$->appendInt8(0xFF); } + | OBJECT_ '(' serInit ')' { $$ = $3; $$->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT);} + | FLOAT32_ '[' int32 ']' '(' f32seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_R4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | FLOAT64_ '[' int32 ']' '(' f64seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_R8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT64_ '[' int32 ']' '(' i64seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT32_ '[' int32 ']' '(' i32seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT16_ '[' int32 ']' '(' i16seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I2); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT8_ '[' int32 ']' '(' i8seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I1); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT64_ '[' int32 ']' '(' i64seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT32_ '[' int32 ']' '(' i32seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT16_ '[' int32 ']' '(' i16seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U2); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT8_ '[' int32 ']' '(' i8seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U1); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT64_ '[' int32 ']' '(' i64seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT32_ '[' int32 ']' '(' i32seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT16_ '[' int32 ']' '(' i16seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U2); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT8_ '[' int32 ']' '(' i8seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U1); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | CHAR_ '[' int32 ']' '(' i16seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_CHAR); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | BOOL_ '[' int32 ']' '(' boolSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_BOOLEAN); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | STRING_ '[' int32 ']' '(' sqstringSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_STRING); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | TYPE_ '[' int32 ']' '(' classSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(SERIALIZATION_TYPE_TYPE); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | OBJECT_ '[' int32 ']' '(' objSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + ; + + +f32seq : /* EMPTY */ { $$ = new BinStr(); } + | f32seq float64 { $$ = $1; + float f = (float) (*$2); $$->appendInt32(*((__int32*)&f)); delete $2; } + | f32seq int32 { $$ = $1; + $$->appendInt32($2); } + ; + +f64seq : /* EMPTY */ { $$ = new BinStr(); } + | f64seq float64 { $$ = $1; + $$->appendInt64((__int64 *)$2); delete $2; } + | f64seq int64 { $$ = $1; + $$->appendInt64((__int64 *)$2); delete $2; } + ; + +i64seq : /* EMPTY */ { $$ = new BinStr(); } + | i64seq int64 { $$ = $1; + $$->appendInt64((__int64 *)$2); delete $2; } + ; + +i32seq : /* EMPTY */ { $$ = new BinStr(); } + | i32seq int32 { $$ = $1; $$->appendInt32($2);} + ; + +i16seq : /* EMPTY */ { $$ = new BinStr(); } + | i16seq int32 { $$ = $1; $$->appendInt16($2);} + ; + +i8seq : /* EMPTY */ { $$ = new BinStr(); } + | i8seq int32 { $$ = $1; $$->appendInt8($2); } + ; + +boolSeq : /* EMPTY */ { $$ = new BinStr(); } + | boolSeq truefalse { $$ = $1; + $$->appendInt8($2);} + ; + +sqstringSeq : /* EMPTY */ { $$ = new BinStr(); } + | sqstringSeq NULLREF_ { $$ = $1; $$->appendInt8(0xFF); } + | sqstringSeq SQSTRING { $$ = $1; + AppendStringWithLength($$,$2); delete [] $2;} + ; + +classSeq : /* EMPTY */ { $$ = new BinStr(); } + | classSeq NULLREF_ { $$ = $1; $$->appendInt8(0xFF); } + | classSeq CLASS_ SQSTRING { $$ = $1; + AppendStringWithLength($$,$3); delete [] $3;} + | classSeq className { $$ = $1; + AppendStringWithLength($$,PASM->ReflectionNotation($2));} + ; + +objSeq : /* EMPTY */ { $$ = new BinStr(); } + | objSeq serInit { $$ = $1; $$->append($2); delete $2; } + ; + +/* IL instructions and associated definitions */ +methodSpec : METHOD_ { parser->m_ANSFirst.PUSH(PASM->m_firstArgName); + parser->m_ANSLast.PUSH(PASM->m_lastArgName); + PASM->m_firstArgName = NULL; + PASM->m_lastArgName = NULL; } + ; + +instr_none : INSTR_NONE { $$ = SetupInstr($1); } + ; + +instr_var : INSTR_VAR { $$ = SetupInstr($1); } + ; + +instr_i : INSTR_I { $$ = SetupInstr($1); } + ; + +instr_i8 : INSTR_I8 { $$ = SetupInstr($1); } + ; + +instr_r : INSTR_R { $$ = SetupInstr($1); } + ; + +instr_brtarget : INSTR_BRTARGET { $$ = SetupInstr($1); } + ; + +instr_method : INSTR_METHOD { $$ = SetupInstr($1); + if((!PASM->OnErrGo)&& + (($1 == CEE_NEWOBJ)|| + ($1 == CEE_CALLVIRT))) + iCallConv = IMAGE_CEE_CS_CALLCONV_HASTHIS; + } + ; + +instr_field : INSTR_FIELD { $$ = SetupInstr($1); } + ; + +instr_type : INSTR_TYPE { $$ = SetupInstr($1); } + ; + +instr_string : INSTR_STRING { $$ = SetupInstr($1); } + ; + +instr_sig : INSTR_SIG { $$ = SetupInstr($1); } + ; + +instr_tok : INSTR_TOK { $$ = SetupInstr($1); iOpcodeLen = PASM->OpcodeLen($$); } + ; + +instr_switch : INSTR_SWITCH { $$ = SetupInstr($1); } + ; + +instr_r_head : instr_r '(' { $$ = $1; bParsingByteArray = TRUE; } + ; + + +instr : instr_none { PASM->EmitOpcode($1); } + | instr_var int32 { PASM->EmitInstrVar($1, $2); } + | instr_var id { PASM->EmitInstrVarByName($1, $2); } + | instr_i int32 { PASM->EmitInstrI($1, $2); } + | instr_i8 int64 { PASM->EmitInstrI8($1, $2); } + | instr_r float64 { PASM->EmitInstrR($1, $2); delete ($2);} + | instr_r int64 { double f = (double) (*$2); PASM->EmitInstrR($1, &f); } + | instr_r_head bytes ')' { unsigned L = $2->length(); + FAIL_UNLESS(L >= sizeof(float), ("%d hexbytes, must be at least %d\n", + L,sizeof(float))); + if(L < sizeof(float)) {YYERROR; } + else { + double f = (L >= sizeof(double)) ? *((double *)($2->ptr())) + : (double)(*(float *)($2->ptr())); + PASM->EmitInstrR($1,&f); } + delete $2; } + | instr_brtarget int32 { PASM->EmitInstrBrOffset($1, $2); } + | instr_brtarget id { PASM->EmitInstrBrTarget($1, $2); } + | instr_method methodRef + { PASM->SetMemberRefFixup($2,PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,$2); + PASM->m_tkCurrentCVOwner = $2; + PASM->m_pCustomDescrList = NULL; + iCallConv = 0; + } + | instr_field type typeSpec DCOLON dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef($3, $5, $2); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field type dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef(mdTokenNil, $3, $2); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field mdtoken { mdToken mr = $2; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field TYPEDEF_F { mdToken mr = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field TYPEDEF_MR { mdToken mr = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_type typeSpec { PASM->EmitInstrI($1, $2); + PASM->m_tkCurrentCVOwner = $2; + PASM->m_pCustomDescrList = NULL; + } + | instr_string compQstring { PASM->EmitInstrStringLiteral($1, $2,TRUE); } + | instr_string ANSI_ '(' compQstring ')' + { PASM->EmitInstrStringLiteral($1, $4,FALSE); } + | instr_string bytearrayhead bytes ')' + { PASM->EmitInstrStringLiteral($1, $3,FALSE,TRUE); } + | instr_sig callConv type '(' sigArgs0 ')' + { PASM->EmitInstrSig($1, parser->MakeSig($2, $3, $5)); + PASM->ResetArgNameList(); + } + | instr_tok ownerType /* ownerType ::= memberRef | typeSpec */ + { PASM->EmitInstrI($1,$2); + PASM->m_tkCurrentCVOwner = $2; + PASM->m_pCustomDescrList = NULL; + iOpcodeLen = 0; + } + | instr_switch '(' labels ')' { PASM->EmitInstrSwitch($1, $3); } + ; + +labels : /* empty */ { $$ = 0; } + | id ',' labels { $$ = new Labels($1, $3, TRUE); } + | int32 ',' labels { $$ = new Labels((char *)(UINT_PTR)$1, $3, FALSE); } + | id { $$ = new Labels($1, NULL, TRUE); } + | int32 { $$ = new Labels((char *)(UINT_PTR)$1, NULL, FALSE); } + ; + +/* Signatures */ +tyArgs0 : /* EMPTY */ { $$ = NULL; } + | '<' tyArgs1 '>' { $$ = $2; } + ; + +tyArgs1 : /* EMPTY */ { $$ = NULL; } + | tyArgs2 { $$ = $1; } + ; + +tyArgs2 : type { $$ = $1; } + | tyArgs2 ',' type { $$ = $1; $$->append($3); delete $3; } + ; + + +sigArgs0 : /* EMPTY */ { $$ = new BinStr(); } + | sigArgs1 { $$ = $1;} + ; + +sigArgs1 : sigArg { $$ = $1; } + | sigArgs1 ',' sigArg { $$ = $1; $$->append($3); delete $3; } + ; + +sigArg : ELIPSIS { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_SENTINEL); } + | paramAttr type marshalClause { $$ = new BinStr(); $$->append($2); PASM->addArgName(NULL, $2, $3, $1); } + | paramAttr type marshalClause id { $$ = new BinStr(); $$->append($2); PASM->addArgName($4, $2, $3, $1);} + ; + +/* Class referencing */ +className : '[' dottedName ']' slashedName { $$ = PASM->ResolveClassRef(PASM->GetAsmRef($2), $4, NULL); delete[] $2;} + | '[' mdtoken ']' slashedName { $$ = PASM->ResolveClassRef($2, $4, NULL); } + | '[' '*' ']' slashedName { $$ = PASM->ResolveClassRef(mdTokenNil, $4, NULL); } + | '[' _MODULE dottedName ']' slashedName { $$ = PASM->ResolveClassRef(PASM->GetModRef($3),$5, NULL); delete[] $3;} + | slashedName { $$ = PASM->ResolveClassRef(1,$1,NULL); } + | mdtoken { $$ = $1; } + | TYPEDEF_T { $$ = $1->m_tkTypeSpec; } + | _THIS { if(PASM->m_pCurClass != NULL) $$ = PASM->m_pCurClass->m_cl; + else { $$ = 0; PASM->report->error(".this outside class scope\n"); } + } + | _BASE { if(PASM->m_pCurClass != NULL) { + $$ = PASM->m_pCurClass->m_crExtends; + if(RidFromToken($$) == 0) + PASM->report->error(".base undefined\n"); + } else { $$ = 0; PASM->report->error(".base outside class scope\n"); } + } + | _NESTER { if(PASM->m_pCurClass != NULL) { + if(PASM->m_pCurClass->m_pEncloser != NULL) $$ = PASM->m_pCurClass->m_pEncloser->m_cl; + else { $$ = 0; PASM->report->error(".nester undefined\n"); } + } else { $$ = 0; PASM->report->error(".nester outside class scope\n"); } + } + ; + +slashedName : dottedName { $$ = $1; } + | slashedName '/' dottedName { $$ = newStringWDel($1, NESTING_SEP, $3); } + ; + +typeSpec : className { $$ = $1;} + | '[' dottedName ']' { $$ = PASM->GetAsmRef($2); delete[] $2;} + | '[' _MODULE dottedName ']' { $$ = PASM->GetModRef($3); delete[] $3;} + | type { $$ = PASM->ResolveTypeSpec($1); } + ; + +/* Native types for marshaling signatures */ +nativeType : /* EMPTY */ { $$ = new BinStr(); } + | CUSTOM_ '(' compQstring ',' compQstring ',' compQstring ',' compQstring ')' + { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt($$,$3->length()); $$->append($3); + corEmitInt($$,$5->length()); $$->append($5); + corEmitInt($$,$7->length()); $$->append($7); + corEmitInt($$,$9->length()); $$->append($9); + PASM->report->warn("Deprecated 4-string form of custom marshaler, first two strings ignored\n");} + | CUSTOM_ '(' compQstring ',' compQstring ')' + { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt($$,0); + corEmitInt($$,0); + corEmitInt($$,$3->length()); $$->append($3); + corEmitInt($$,$5->length()); $$->append($5); } + | FIXED_ SYSSTRING_ '[' int32 ']' { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_FIXEDSYSSTRING); + corEmitInt($$,$4); } + | FIXED_ ARRAY_ '[' int32 ']' nativeType + { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_FIXEDARRAY); + corEmitInt($$,$4); $$->append($6); } + | VARIANT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_VARIANT); + PASM->report->warn("Deprecated native type 'variant'\n"); } + | CURRENCY_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_CURRENCY); } + | SYSCHAR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_SYSCHAR); + PASM->report->warn("Deprecated native type 'syschar'\n"); } + | VOID_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_VOID); + PASM->report->warn("Deprecated native type 'void'\n"); } + | BOOL_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_BOOLEAN); } + | INT8_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I1); } + | INT16_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I2); } + | INT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I4); } + | INT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I8); } + | FLOAT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_R4); } + | FLOAT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_R8); } + | ERROR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_ERROR); } + | UNSIGNED_ INT8_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U1); } + | UNSIGNED_ INT16_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U2); } + | UNSIGNED_ INT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U4); } + | UNSIGNED_ INT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U8); } + | UINT8_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U1); } + | UINT16_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U2); } + | UINT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U4); } + | UINT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U8); } + | nativeType '*' { $$ = $1; $$->insertInt8(NATIVE_TYPE_PTR); + PASM->report->warn("Deprecated native type '*'\n"); } + | nativeType '[' ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); } + | nativeType '[' int32 ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt($$,0); + corEmitInt($$,$3); + corEmitInt($$,0); } + | nativeType '[' int32 '+' int32 ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt($$,$5); + corEmitInt($$,$3); + corEmitInt($$,ntaSizeParamIndexSpecified); } + | nativeType '[' '+' int32 ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt($$,$4); } + | DECIMAL_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_DECIMAL); + PASM->report->warn("Deprecated native type 'decimal'\n"); } + | DATE_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_DATE); + PASM->report->warn("Deprecated native type 'date'\n"); } + | BSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_BSTR); } + | LPSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPSTR); } + | LPWSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPWSTR); } + | LPTSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPTSTR); } + | OBJECTREF_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_OBJECTREF); + PASM->report->warn("Deprecated native type 'objectref'\n"); } + | IUNKNOWN_ iidParamIndex { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_IUNKNOWN); + if($2 != -1) corEmitInt($$,$2); } + | IDISPATCH_ iidParamIndex { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_IDISPATCH); + if($2 != -1) corEmitInt($$,$2); } + | STRUCT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_STRUCT); } + | INTERFACE_ iidParamIndex { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_INTF); + if($2 != -1) corEmitInt($$,$2); } + | SAFEARRAY_ variantType { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt($$,$2); + corEmitInt($$,0);} + | SAFEARRAY_ variantType ',' compQstring { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt($$,$2); + corEmitInt($$,$4->length()); $$->append($4); } + + | INT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_INT); } + | UNSIGNED_ INT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_UINT); } + | UINT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_UINT); } + | NESTED_ STRUCT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_NESTEDSTRUCT); + PASM->report->warn("Deprecated native type 'nested struct'\n"); } + | BYVALSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_BYVALSTR); } + | ANSI_ BSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_ANSIBSTR); } + | TBSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_TBSTR); } + | VARIANT_ BOOL_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_VARIANTBOOL); } + | METHOD_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_FUNC); } + | AS_ ANY_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_ASANY); } + | LPSTRUCT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPSTRUCT); } + | TYPEDEF_TS { $$ = new BinStr(); $$->append($1->m_pbsTypeSpec); } + ; + +iidParamIndex : /* EMPTY */ { $$ = -1; } + | '(' IIDPARAM_ '=' int32 ')' { $$ = $4; } + ; + +variantType : /* EMPTY */ { $$ = VT_EMPTY; } + | NULL_ { $$ = VT_NULL; } + | VARIANT_ { $$ = VT_VARIANT; } + | CURRENCY_ { $$ = VT_CY; } + | VOID_ { $$ = VT_VOID; } + | BOOL_ { $$ = VT_BOOL; } + | INT8_ { $$ = VT_I1; } + | INT16_ { $$ = VT_I2; } + | INT32_ { $$ = VT_I4; } + | INT64_ { $$ = VT_I8; } + | FLOAT32_ { $$ = VT_R4; } + | FLOAT64_ { $$ = VT_R8; } + | UNSIGNED_ INT8_ { $$ = VT_UI1; } + | UNSIGNED_ INT16_ { $$ = VT_UI2; } + | UNSIGNED_ INT32_ { $$ = VT_UI4; } + | UNSIGNED_ INT64_ { $$ = VT_UI8; } + | UINT8_ { $$ = VT_UI1; } + | UINT16_ { $$ = VT_UI2; } + | UINT32_ { $$ = VT_UI4; } + | UINT64_ { $$ = VT_UI8; } + | '*' { $$ = VT_PTR; } + | variantType '[' ']' { $$ = $1 | VT_ARRAY; } + | variantType VECTOR_ { $$ = $1 | VT_VECTOR; } + | variantType '&' { $$ = $1 | VT_BYREF; } + | DECIMAL_ { $$ = VT_DECIMAL; } + | DATE_ { $$ = VT_DATE; } + | BSTR_ { $$ = VT_BSTR; } + | LPSTR_ { $$ = VT_LPSTR; } + | LPWSTR_ { $$ = VT_LPWSTR; } + | IUNKNOWN_ { $$ = VT_UNKNOWN; } + | IDISPATCH_ { $$ = VT_DISPATCH; } + | SAFEARRAY_ { $$ = VT_SAFEARRAY; } + | INT_ { $$ = VT_INT; } + | UNSIGNED_ INT_ { $$ = VT_UINT; } + | UINT_ { $$ = VT_UINT; } + | ERROR_ { $$ = VT_ERROR; } + | HRESULT_ { $$ = VT_HRESULT; } + | CARRAY_ { $$ = VT_CARRAY; } + | USERDEFINED_ { $$ = VT_USERDEFINED; } + | RECORD_ { $$ = VT_RECORD; } + | FILETIME_ { $$ = VT_FILETIME; } + | BLOB_ { $$ = VT_BLOB; } + | STREAM_ { $$ = VT_STREAM; } + | STORAGE_ { $$ = VT_STORAGE; } + | STREAMED_OBJECT_ { $$ = VT_STREAMED_OBJECT; } + | STORED_OBJECT_ { $$ = VT_STORED_OBJECT; } + | BLOB_OBJECT_ { $$ = VT_BLOB_OBJECT; } + | CF_ { $$ = VT_CF; } + | CLSID_ { $$ = VT_CLSID; } + ; + +/* Managed types for signatures */ +type : CLASS_ className { if($2 == PASM->m_tkSysString) + { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); } + else if($2 == PASM->m_tkSysObject) + { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_OBJECT); } + else + $$ = parser->MakeTypeClass(ELEMENT_TYPE_CLASS, $2); } + | OBJECT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_OBJECT); } + | VALUE_ CLASS_ className { $$ = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, $3); } + | VALUETYPE_ className { $$ = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, $2); } + | type '[' ']' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | type '[' bounds1 ']' { $$ = parser->MakeTypeArray(ELEMENT_TYPE_ARRAY, $1, $3); } + | type '&' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_BYREF); } + | type '*' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_PTR); } + | type PINNED_ { $$ = $1; $$->insertInt8(ELEMENT_TYPE_PINNED); } + | type MODREQ_ '(' typeSpec ')' { $$ = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_REQD, $4); + $$->append($1); } + | type MODOPT_ '(' typeSpec ')' { $$ = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_OPT, $4); + $$->append($1); } + | methodSpec callConv type '*' '(' sigArgs0 ')' + { $$ = parser->MakeSig($2, $3, $6); + $$->insertInt8(ELEMENT_TYPE_FNPTR); + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + } + | type '<' tyArgs1 '>' { if($3 == NULL) $$ = $1; + else { + $$ = new BinStr(); + $$->appendInt8(ELEMENT_TYPE_GENERICINST); + $$->append($1); + corEmitInt($$, corCountArgs($3)); + $$->append($3); delete $1; delete $3; }} + | '!' '!' int32 { //if(PASM->m_pCurMethod) { + // if(($3 < 0)||((DWORD)$3 >= PASM->m_pCurMethod->m_NumTyPars)) + // PASM->report->error("Invalid method type parameter '%d'\n",$3); + $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_MVAR); corEmitInt($$, $3); + //} else PASM->report->error("Method type parameter '%d' outside method scope\n",$3); + } + | '!' int32 { //if(PASM->m_pCurClass) { + // if(($2 < 0)||((DWORD)$2 >= PASM->m_pCurClass->m_NumTyPars)) + // PASM->report->error("Invalid type parameter '%d'\n",$2); + $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_VAR); corEmitInt($$, $2); + //} else PASM->report->error("Type parameter '%d' outside class scope\n",$2); + } + | '!' '!' dottedName { int eltype = ELEMENT_TYPE_MVAR; + int n=-1; + if(PASM->m_pCurMethod) n = PASM->m_pCurMethod->FindTyPar($3); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf($3); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH($3); + eltype = ELEMENT_TYPE_MVARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid method type parameter '%s'\n",$3); + n = 0x1FFFFFFF; } + $$ = new BinStr(); $$->appendInt8(eltype); corEmitInt($$,n); + } + | '!' dottedName { int eltype = ELEMENT_TYPE_VAR; + int n=-1; + if(PASM->m_pCurClass && !newclass) n = PASM->m_pCurClass->FindTyPar($2); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf($2); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH($2); + eltype = ELEMENT_TYPE_VARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid type parameter '%s'\n",$2); + n = 0x1FFFFFFF; } + $$ = new BinStr(); $$->appendInt8(eltype); corEmitInt($$,n); + } + | TYPEDREF_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_TYPEDBYREF); } + | VOID_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_VOID); } + | NATIVE_ INT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I); } + | NATIVE_ UNSIGNED_ INT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U); } + | NATIVE_ UINT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U); } + | simpleType { $$ = $1; } + | ELIPSIS type { $$ = $2; $$->insertInt8(ELEMENT_TYPE_SENTINEL); } + ; + +simpleType : CHAR_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_CHAR); } + | STRING_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); } + | BOOL_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_BOOLEAN); } + | INT8_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I1); } + | INT16_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I2); } + | INT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I4); } + | INT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I8); } + | FLOAT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); } + | FLOAT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); } + | UNSIGNED_ INT8_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); } + | UNSIGNED_ INT16_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); } + | UNSIGNED_ INT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); } + | UNSIGNED_ INT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); } + | UINT8_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); } + | UINT16_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); } + | UINT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); } + | UINT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); } + | TYPEDEF_TS { $$ = new BinStr(); $$->append($1->m_pbsTypeSpec); } + ; + +bounds1 : bound { $$ = $1; } + | bounds1 ',' bound { $$ = $1; $1->append($3); delete $3; } + ; + +bound : /* EMPTY */ { $$ = new BinStr(); $$->appendInt32(0x7FFFFFFF); $$->appendInt32(0x7FFFFFFF); } + | ELIPSIS { $$ = new BinStr(); $$->appendInt32(0x7FFFFFFF); $$->appendInt32(0x7FFFFFFF); } + | int32 { $$ = new BinStr(); $$->appendInt32(0); $$->appendInt32($1); } + | int32 ELIPSIS int32 { FAIL_UNLESS($1 <= $3, ("lower bound %d must be <= upper bound %d\n", $1, $3)); + if ($1 > $3) { YYERROR; }; + $$ = new BinStr(); $$->appendInt32($1); $$->appendInt32($3-$1+1); } + | int32 ELIPSIS { $$ = new BinStr(); $$->appendInt32($1); $$->appendInt32(0x7FFFFFFF); } + ; + +/* Security declarations */ +secDecl : _PERMISSION secAction typeSpec '(' nameValPairs ')' + { PASM->AddPermissionDecl($2, $3, $5); } + | _PERMISSION secAction typeSpec '=' '{' customBlobDescr '}' + { PASM->AddPermissionDecl($2, $3, $6); } + | _PERMISSION secAction typeSpec { PASM->AddPermissionDecl($2, $3, (NVPair *)NULL); } + | psetHead bytes ')' { PASM->AddPermissionSetDecl($1, $2); } + | _PERMISSIONSET secAction compQstring + { PASM->AddPermissionSetDecl($2,BinStrToUnicode($3,true));} + | _PERMISSIONSET secAction '=' '{' secAttrSetBlob '}' + { BinStr* ret = new BinStr(); + ret->insertInt8('.'); + corEmitInt(ret, nSecAttrBlobs); + ret->append($5); + PASM->AddPermissionSetDecl($2,ret); + nSecAttrBlobs = 0; } + ; + +secAttrSetBlob : /* EMPTY */ { $$ = new BinStr(); nSecAttrBlobs = 0;} + | secAttrBlob { $$ = $1; nSecAttrBlobs = 1; } + | secAttrBlob ',' secAttrSetBlob { $$ = $1; $$->append($3); nSecAttrBlobs++; } + ; + +secAttrBlob : typeSpec '=' '{' customBlobNVPairs '}' + { $$ = PASM->EncodeSecAttr(PASM->ReflectionNotation($1),$4,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } + | CLASS_ SQSTRING '=' '{' customBlobNVPairs '}' + { $$ = PASM->EncodeSecAttr($2,$5,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } + ; + +psetHead : _PERMISSIONSET secAction '=' '(' { $$ = $2; bParsingByteArray = TRUE; } + | _PERMISSIONSET secAction BYTEARRAY_ '(' + { $$ = $2; bParsingByteArray = TRUE; } + ; + +nameValPairs : nameValPair { $$ = $1; } + | nameValPair ',' nameValPairs { $$ = $1->Concat($3); } + ; + +nameValPair : compQstring '=' caValue { $1->appendInt8(0); $$ = new NVPair($1, $3); } + ; + +truefalse : TRUE_ { $$ = 1; } + | FALSE_ { $$ = 0; } + ; + +caValue : truefalse { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_BOOLEAN); + $$->appendInt8($1); } + | int32 { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_I4); + $$->appendInt32($1); } + | INT32_ '(' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_I4); + $$->appendInt32($3); } + | compQstring { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_STRING); + $$->append($1); delete $1; + $$->appendInt8(0); } + | className '(' INT8_ ':' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(1); + $$->appendInt32($5); } + | className '(' INT16_ ':' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(2); + $$->appendInt32($5); } + | className '(' INT32_ ':' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(4); + $$->appendInt32($5); } + | className '(' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(4); + $$->appendInt32($3); } + ; + +secAction : REQUEST_ { $$ = dclRequest; } + | DEMAND_ { $$ = dclDemand; } + | ASSERT_ { $$ = dclAssert; } + | DENY_ { $$ = dclDeny; } + | PERMITONLY_ { $$ = dclPermitOnly; } + | LINKCHECK_ { $$ = dclLinktimeCheck; } + | INHERITCHECK_ { $$ = dclInheritanceCheck; } + | REQMIN_ { $$ = dclRequestMinimum; } + | REQOPT_ { $$ = dclRequestOptional; } + | REQREFUSE_ { $$ = dclRequestRefuse; } + | PREJITGRANT_ { $$ = dclPrejitGrant; } + | PREJITDENY_ { $$ = dclPrejitDenied; } + | NONCASDEMAND_ { $$ = dclNonCasDemand; } + | NONCASLINKDEMAND_ { $$ = dclNonCasLinkDemand; } + | NONCASINHERITANCE_ { $$ = dclNonCasInheritance; } + ; + +/* External source declarations */ +esHead : _LINE { PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = FALSE; } + | P_LINE { PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = TRUE; } + ; + +extSourceSpec : esHead int32 SQSTRING { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($3);} + | esHead int32 { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); } + | esHead int32 ':' int32 SQSTRING { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($5);} + | esHead int32 ':' int32 { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = static_cast<unsigned>(-1);} + | esHead int32 ':' int32 ',' int32 SQSTRING + { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = $6; + PASM->SetSourceFileName($7);} + | esHead int32 ':' int32 ',' int32 + { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = $6; } + | esHead int32 ',' int32 ':' int32 SQSTRING + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($7);} + | esHead int32 ',' int32 ':' int32 + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = static_cast<unsigned>(-1); } + | esHead int32 ',' int32 ':' int32 ',' int32 SQSTRING + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = $8; + PASM->SetSourceFileName($9);} + | esHead int32 ',' int32 ':' int32 ',' int32 + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = $8; } + | esHead int32 QSTRING { PENV->nExtLine = PENV->nExtLineEnd = $2 - 1; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($3);} + ; + +/* Manifest declarations */ +fileDecl : _FILE fileAttr dottedName fileEntry hashHead bytes ')' fileEntry + { PASMM->AddFile($3, $2|$4|$8, $6); } + | _FILE fileAttr dottedName fileEntry { PASMM->AddFile($3, $2|$4, NULL); } + ; + +fileAttr : /* EMPTY */ { $$ = (CorFileFlags) 0; } + | fileAttr NOMETADATA_ { $$ = (CorFileFlags) ($1 | ffContainsNoMetaData); } + ; + +fileEntry : /* EMPTY */ { $$ = (CorFileFlags) 0; } + | _ENTRYPOINT { $$ = (CorFileFlags) 0x80000000; } + ; + +hashHead : _HASH '=' '(' { bParsingByteArray = TRUE; } + ; + +assemblyHead : _ASSEMBLY asmAttr dottedName { PASMM->StartAssembly($3, NULL, (DWORD)$2, FALSE); } + ; + +asmAttr : /* EMPTY */ { $$ = (CorAssemblyFlags) 0; } + | asmAttr RETARGETABLE_ { $$ = (CorAssemblyFlags) ($1 | afRetargetable); } + | asmAttr WINDOWSRUNTIME_ { $$ = (CorAssemblyFlags) ($1 | afContentType_WindowsRuntime); } + | asmAttr NOPLATFORM_ { $$ = (CorAssemblyFlags) ($1 | afPA_NoPlatform); } + | asmAttr LEGACY_ LIBRARY_ { $$ = $1; } + | asmAttr CIL_ { SET_PA($$,$1,afPA_MSIL); } + | asmAttr X86_ { SET_PA($$,$1,afPA_x86); } + | asmAttr AMD64_ { SET_PA($$,$1,afPA_AMD64); } + | asmAttr ARM_ { SET_PA($$,$1,afPA_ARM); } + | asmAttr ARM64_ { SET_PA($$,$1,afPA_ARM64); } + ; + +assemblyDecls : /* EMPTY */ + | assemblyDecls assemblyDecl + ; + +assemblyDecl : _HASH ALGORITHM_ int32 { PASMM->SetAssemblyHashAlg($3); } + | secDecl + | asmOrRefDecl + ; + +intOrWildcard : int32 { $$ = $1; } + | '*' { $$ = 0xFFFF; } + ; + +asmOrRefDecl : publicKeyHead bytes ')' { PASMM->SetAssemblyPublicKey($2); } + | _VER intOrWildcard ':' intOrWildcard ':' intOrWildcard ':' intOrWildcard + { PASMM->SetAssemblyVer((USHORT)$2, (USHORT)$4, (USHORT)$6, (USHORT)$8); } + | _LOCALE compQstring { $2->appendInt8(0); PASMM->SetAssemblyLocale($2,TRUE); } + | localeHead bytes ')' { PASMM->SetAssemblyLocale($2,FALSE); } + | customAttrDecl + | compControl + ; + +publicKeyHead : _PUBLICKEY '=' '(' { bParsingByteArray = TRUE; } + ; + +publicKeyTokenHead : _PUBLICKEYTOKEN '=' '(' { bParsingByteArray = TRUE; } + ; + +localeHead : _LOCALE '=' '(' { bParsingByteArray = TRUE; } + ; + +assemblyRefHead : _ASSEMBLY EXTERN_ asmAttr dottedName + { PASMM->StartAssembly($4, NULL, $3, TRUE); } + | _ASSEMBLY EXTERN_ asmAttr dottedName AS_ dottedName + { PASMM->StartAssembly($4, $6, $3, TRUE); } + ; + +assemblyRefDecls : /* EMPTY */ + | assemblyRefDecls assemblyRefDecl + ; + +assemblyRefDecl : hashHead bytes ')' { PASMM->SetAssemblyHashBlob($2); } + | asmOrRefDecl + | publicKeyTokenHead bytes ')' { PASMM->SetAssemblyPublicKeyToken($2); } + | AUTO_ { PASMM->SetAssemblyAutodetect(); } + ; + +exptypeHead : _CLASS EXTERN_ exptAttr dottedName { PASMM->StartComType($4, $3);} + ; + +exportHead : _EXPORT exptAttr dottedName /* deprecated */ { PASMM->StartComType($3, $2); } + ; + +exptAttr : /* EMPTY */ { $$ = (CorTypeAttr) 0; } + | exptAttr PRIVATE_ { $$ = (CorTypeAttr) ($1 | tdNotPublic); } + | exptAttr PUBLIC_ { $$ = (CorTypeAttr) ($1 | tdPublic); } + | exptAttr FORWARDER_ { $$ = (CorTypeAttr) ($1 | tdForwarder); } + | exptAttr NESTED_ PUBLIC_ { $$ = (CorTypeAttr) ($1 | tdNestedPublic); } + | exptAttr NESTED_ PRIVATE_ { $$ = (CorTypeAttr) ($1 | tdNestedPrivate); } + | exptAttr NESTED_ FAMILY_ { $$ = (CorTypeAttr) ($1 | tdNestedFamily); } + | exptAttr NESTED_ ASSEMBLY_ { $$ = (CorTypeAttr) ($1 | tdNestedAssembly); } + | exptAttr NESTED_ FAMANDASSEM_ { $$ = (CorTypeAttr) ($1 | tdNestedFamANDAssem); } + | exptAttr NESTED_ FAMORASSEM_ { $$ = (CorTypeAttr) ($1 | tdNestedFamORAssem); } + ; + +exptypeDecls : /* EMPTY */ + | exptypeDecls exptypeDecl + ; + +exptypeDecl : _FILE dottedName { PASMM->SetComTypeFile($2); } + | _CLASS EXTERN_ slashedName { PASMM->SetComTypeComType($3); } + | _ASSEMBLY EXTERN_ dottedName { PASMM->SetComTypeAsmRef($3); } + | MDTOKEN_ '(' int32 ')' { if(!PASMM->SetComTypeImplementationTok($3)) + PASM->report->error("Invalid implementation of exported type\n"); } + | _CLASS int32 { if(!PASMM->SetComTypeClassTok($2)) + PASM->report->error("Invalid TypeDefID of exported type\n"); } + | customAttrDecl + | compControl + ; + +manifestResHead : _MRESOURCE manresAttr dottedName { PASMM->StartManifestRes($3, $3, $2); } + | _MRESOURCE manresAttr dottedName AS_ dottedName + { PASMM->StartManifestRes($3, $5, $2); } + ; + +manresAttr : /* EMPTY */ { $$ = (CorManifestResourceFlags) 0; } + | manresAttr PUBLIC_ { $$ = (CorManifestResourceFlags) ($1 | mrPublic); } + | manresAttr PRIVATE_ { $$ = (CorManifestResourceFlags) ($1 | mrPrivate); } + ; + +manifestResDecls : /* EMPTY */ + | manifestResDecls manifestResDecl + ; + +manifestResDecl : _FILE dottedName AT_ int32 { PASMM->SetManifestResFile($2, (ULONG)$4); } + | _ASSEMBLY EXTERN_ dottedName { PASMM->SetManifestResAsmRef($3); } + | customAttrDecl + | compControl + ; + +%% + +#include "grammar_after.cpp" diff --git a/src/coreclr/ilasm/asmtemplates.h b/src/coreclr/ilasm/asmtemplates.h new file mode 100644 index 00000000000..0393c71a4f2 --- /dev/null +++ b/src/coreclr/ilasm/asmtemplates.h @@ -0,0 +1,795 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef ASMTEMPLATES_H +#define ASMTEMPLATES_H + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow" +#endif + +inline ULONG GrowBuffer(ULONG startingSize) +{ + int toAdd = startingSize >> 1; + if (toAdd < 8) + toAdd = 8; + if (toAdd > 2048) + toAdd = 2048; + return startingSize + toAdd; +} + +/*****************************************************************************/ +/* LIFO (stack) and FIFO (queue) templates (must precede #include "method.h")*/ +template <class T> +class LIST_EL +{ +public: + T* m_Ptr; + LIST_EL <T> *m_Next; + LIST_EL(T *item) {m_Next = NULL; m_Ptr = item; }; +}; + +template <class T> +class LIFO +{ +public: + inline LIFO() { m_pHead = NULL; }; + inline ~LIFO() {T *val; while((val = POP()) != NULL) delete val; }; + void PUSH(T *item) + { + m_pTemp = new LIST_EL <T>(item); + m_pTemp->m_Next = m_pHead; + m_pHead = m_pTemp; + }; + T* POP() + { + T* ret = NULL; + if((m_pTemp = m_pHead) != NULL) + { + m_pHead = m_pHead->m_Next; + ret = m_pTemp->m_Ptr; + delete m_pTemp; + } + return ret; + }; +private: + LIST_EL <T> *m_pHead; + LIST_EL <T> *m_pTemp; +}; + + +template <class T> +class FIFO +{ +public: + FIFO() { m_Arr = NULL; m_ulArrLen = 0; m_ulCount = 0; m_ulOffset = 0; }; + ~FIFO() { + if(m_Arr) { + for(ULONG i=0; i < m_ulCount; i++) { + if(m_Arr[i+m_ulOffset]) delete m_Arr[i+m_ulOffset]; + } + delete [] m_Arr; + } + }; + void RESET(bool DeleteElements = true) { + if(m_Arr) { + for(ULONG i=0; i < m_ulCount; i++) { + if(DeleteElements) delete m_Arr[i+m_ulOffset]; + m_Arr[i+m_ulOffset] = NULL; + } + m_ulCount = 0; + m_ulOffset= 0; + } + }; + void PUSH(T *item) + { + if(item) + { + if(m_ulCount+m_ulOffset >= m_ulArrLen) + { + if(m_ulOffset) + { + memcpy(m_Arr,&m_Arr[m_ulOffset],m_ulCount*sizeof(T*)); + m_ulOffset = 0; + } + else + { + m_ulArrLen = GrowBuffer(m_ulArrLen); + T** tmp = new T*[m_ulArrLen]; + if(tmp) + { + if(m_Arr) + { + memcpy(tmp,m_Arr,m_ulCount*sizeof(T*)); + delete [] m_Arr; + } + m_Arr = tmp; + } + else fprintf(stderr,"\nOut of memory!\n"); + } + } + m_Arr[m_ulOffset+m_ulCount] = item; + m_ulCount++; + } + }; + ULONG COUNT() { return m_ulCount; }; + T* POP() + { + T* ret = NULL; + if(m_ulCount) + { + ret = m_Arr[m_ulOffset++]; + m_ulCount--; + } + return ret; + }; + T* PEEK(ULONG idx) { return (idx < m_ulCount) ? m_Arr[m_ulOffset+idx] : NULL; }; +private: + T** m_Arr; + ULONG m_ulCount; + ULONG m_ulOffset; + ULONG m_ulArrLen; +}; + + +template <class T> struct Indx256 +{ + void* table[256]; + Indx256() { memset(table,0,sizeof(table)); }; + ~Indx256() + { + ClearAll(true); + for(int i = 1; i < 256; i++) delete ((Indx256*)(table[i])); + }; + T** IndexString(BYTE* psz, T* pObj) + { + if(*psz == 0) + { + table[0] = (void*)pObj; + return (T**)table; + } + else + { + Indx256* pInd = (Indx256*)(table[*psz]); + if(pInd == NULL) + { + pInd = new Indx256; + if(pInd) + table[*psz] = pInd; + else + { + _ASSERTE(!"Out of memory in Indx256::IndexString!"); + fprintf(stderr,"\nOut of memory in Indx256::IndexString!\n"); + return NULL; + } + } + return pInd->IndexString(psz+1,pObj); + } + }; + T* FindString(BYTE* psz) + { + if(*psz > 0) + { + Indx256* pInd = (Indx256*)(table[*psz]); + return (pInd == NULL) ? NULL : pInd->FindString(psz+1); + } + return (T*)(table[0]); // if i==0 + }; + + void ClearAll(bool DeleteObj) + { + if(DeleteObj) delete (T*)(table[0]); + table[0] = NULL; + for(unsigned i = 1; i < 256; i++) + { + if(table[i]) + { + Indx256* pInd = (Indx256*)(table[i]); + pInd->ClearAll(DeleteObj); + //delete pInd; + //table[i] = NULL; + } + } + }; +}; + +// +// Template intended for named objects, that expose function char* NameOf() +// +template <class T> +class FIFO_INDEXED +{ +public: + FIFO_INDEXED() { m_Arr = NULL; m_ulArrLen = 0; m_ulCount = 0; m_ulOffset = 0; }; + ~FIFO_INDEXED() { + if(m_Arr) + { + RESET(true); + delete [] m_Arr; + } + }; + void RESET(bool DeleteElements = true) { + if(m_Arr) { + unsigned i; + if(DeleteElements) + { + for(i=m_ulOffset; i < m_ulOffset+m_ulCount; i++) + { + T** ppT = m_Arr[i]; + delete *ppT; + } + } + for(i=m_ulOffset; i < m_ulOffset+m_ulCount; i++) + { + *m_Arr[i] = NULL; + } + memset(&m_Arr[m_ulOffset],0,m_ulCount*sizeof(void*)); + m_ulCount = 0; + m_ulOffset= 0; + } + }; + void PUSH(T *item) + { + if(item) + { + T** itemaddr = m_Index.IndexString((BYTE*)(item->NameOf()),item); + if(m_ulCount+m_ulOffset >= m_ulArrLen) + { + if(m_ulOffset) + { + memcpy(m_Arr,&m_Arr[m_ulOffset],m_ulCount*sizeof(T*)); + m_ulOffset = 0; + } + else + { + m_ulArrLen = GrowBuffer(m_ulArrLen); + T*** tmp = new T**[m_ulArrLen]; + if(tmp) + { + if(m_Arr) + { + memcpy(tmp,m_Arr,m_ulCount*sizeof(T**)); + delete [] m_Arr; + } + m_Arr = tmp; + } + else fprintf(stderr,"\nOut of memory!\n"); + } + } + m_Arr[m_ulOffset+m_ulCount] = itemaddr; + m_ulCount++; + } + }; + ULONG COUNT() { return m_ulCount; }; + T* POP() + { + T* ret = NULL; + if(m_ulCount) + { + ret = *(m_Arr[m_ulOffset]); + *m_Arr[m_ulOffset] = NULL; + m_ulOffset++; + m_ulCount--; + } + return ret; + }; + T* PEEK(ULONG idx) { return (idx < m_ulCount) ? *(m_Arr[m_ulOffset+idx]) : NULL; }; + T* FIND(T* item) { return m_Index.FindString((BYTE*)(item->NameOf())); }; +private: + T*** m_Arr; + ULONG m_ulCount; + ULONG m_ulOffset; + ULONG m_ulArrLen; + Indx256<T> m_Index; +}; + +template <class T> +class SORTEDARRAY +{ +public: + SORTEDARRAY() { m_Arr = NULL; m_ulArrLen = 0; m_ulCount = 0; m_ulOffset = 0; }; + ~SORTEDARRAY() { + if(m_Arr) { + for(ULONG i=0; i < m_ulCount; i++) { + if(m_Arr[i+m_ulOffset]) delete m_Arr[i+m_ulOffset]; + } + delete [] m_Arr; + } + }; + void RESET(bool DeleteElements = true) { + if(m_Arr) { + if(DeleteElements) + { + for(ULONG i=0; i < m_ulCount; i++) { + delete m_Arr[i+m_ulOffset]; + } + } + memset(m_Arr,0,m_ulArrLen*sizeof(T*)); + m_ulCount = 0; + m_ulOffset= 0; + } + }; + void PUSH(T *item) + { + if(item) + { + if(m_ulCount+m_ulOffset >= m_ulArrLen) + { + if(m_ulOffset) + { + memcpy(m_Arr,&m_Arr[m_ulOffset],m_ulCount*sizeof(T*)); + m_ulOffset = 0; + } + else + { + m_ulArrLen = GrowBuffer(m_ulArrLen); + T** tmp = new T*[m_ulArrLen]; + if(tmp) + { + if(m_Arr) + { + memcpy(tmp,m_Arr,m_ulCount*sizeof(T*)); + delete [] m_Arr; + } + m_Arr = tmp; + } + else fprintf(stderr,"\nOut of memory!\n"); + } + } + if(m_ulCount) + { + // find 1st arr.element > item + T** low = &m_Arr[m_ulOffset]; + T** high = &m_Arr[m_ulOffset+m_ulCount-1]; + T** mid; + + if(item->ComparedTo(*high) > 0) mid = high+1; + else if(item->ComparedTo(*low) < 0) mid = low; + else for(;;) + { + mid = &low[(high - low) >> 1]; + + int cmp = item->ComparedTo(*mid); + + if (mid == low) + { + if(cmp > 0) mid++; + break; + } + + if (cmp > 0) low = mid; + else high = mid; + } + + ///////////////////////////////////////////// + memmove(mid+1,mid,(BYTE*)&m_Arr[m_ulOffset+m_ulCount]-(BYTE*)mid); + *mid = item; + } + else m_Arr[m_ulOffset+m_ulCount] = item; + m_ulCount++; + } + }; + ULONG COUNT() { return m_ulCount; }; + T* POP() + { + T* ret = NULL; + if(m_ulCount) + { + ret = m_Arr[m_ulOffset++]; + m_ulCount--; + } + return ret; + }; + T* PEEK(ULONG idx) { return (idx < m_ulCount) ? m_Arr[m_ulOffset+idx] : NULL; }; + T* FIND(T* item) + { + if(m_ulCount) + { + T** low = &m_Arr[m_ulOffset]; + T** high = &m_Arr[m_ulOffset+m_ulCount-1]; + T** mid; + if(item->ComparedTo(*high) == 0) return(*high); + for(;;) + { + mid = &low[(high - low) >> 1]; + int cmp = item->ComparedTo(*mid); + if (cmp == 0) return(*mid); + if (mid == low) break; + if (cmp > 0) low = mid; + else high = mid; + } + } + return NULL; + }; + /* + T* FIND(U item) + { + if(m_ulCount) + { + T** low = &m_Arr[m_ulOffset]; + T** high = &m_Arr[m_ulOffset+m_ulCount-1]; + T** mid; + if((*high)->Compare(item) == 0) return(*high); + for(;;) + { + mid = &low[(high - low) >> 1]; + int cmp = (*mid)->Compare(item); + if (cmp == 0) return(*mid); + if (mid == low) break; + if (cmp > 0) low = mid; + else high = mid; + } + } + return NULL; + }; + */ + BOOL DEL(T* item) + { + if(m_ulCount) + { + T** low = &m_Arr[m_ulOffset]; + T** high = &m_Arr[m_ulOffset+m_ulCount-1]; + T** mid; + if(item->ComparedTo(*high) == 0) + { + delete (*high); + m_ulCount--; + return TRUE; + } + for(;;) + { + mid = &low[(high - low) >> 1]; + int cmp = item->ComparedTo(*mid); + if (cmp == 0) + { + delete (*mid); + memcpy(mid,mid+1,(BYTE*)&m_Arr[m_ulOffset+m_ulCount]-(BYTE*)mid-1); + m_ulCount--; + return TRUE; + } + if (mid == low) break; + if (cmp > 0) low = mid; + else high = mid; + } + } + return FALSE; + }; +private: + T** m_Arr; + ULONG m_ulCount; + ULONG m_ulOffset; + ULONG m_ulArrLen; +}; + +template <class T> struct RBNODE +{ +private: + DWORD dwRed; +public: + DWORD dwInUse; + T* tVal; + RBNODE<T>* pLeft; + RBNODE<T>* pRight; + RBNODE<T>* pParent; + RBNODE() + { + pLeft = pRight = pParent = NULL; + tVal = NULL; + dwRed = dwInUse = 0; + }; + RBNODE(T* pVal, DWORD dwColor) + { + pLeft = pRight = pParent = NULL; + tVal = pVal; + dwRed = dwColor; + dwInUse = 0; + }; + bool IsRed() { return (dwRed != 0); }; + void SetRed() { dwRed = 1; }; + void SetBlack() { dwRed = 0; }; +}; + +#define BUCKETCOUNT 512 + +template <class T> class RBNODEBUCKET +{ +private: + RBNODEBUCKET<T>* pNext; + RBNODE<T> bucket[BUCKETCOUNT]; + unsigned alloc_count; + +public: + RBNODEBUCKET() + { + alloc_count = 0; + pNext = NULL; + }; + + ~RBNODEBUCKET() { if(pNext) delete pNext; }; + + bool CanAlloc() { return (alloc_count < BUCKETCOUNT); }; + + RBNODE<T>* AllocNode() + { + RBNODE<T>* pRet; + for(unsigned i = 0; i < BUCKETCOUNT; i++) + { + if(bucket[i].dwInUse == 0) + { + alloc_count++; + pRet = &bucket[i]; + memset(pRet, 0, sizeof(RBNODE<T>)); + pRet->dwInUse = 1; + return pRet; + } + } + _ASSERTE(!"AllocNode returns NULL"); + return NULL; + }; + + bool FreeNode(RBNODE<T>* ptr) + { + size_t idx = ((size_t)ptr - (size_t)bucket)/sizeof(RBNODE<T>); + if(idx < BUCKETCOUNT) + { + bucket[idx].dwInUse = 0; + alloc_count--; + return true; + } + return false; + }; + + RBNODEBUCKET<T>* Next() { return pNext; }; + + void Append(RBNODEBUCKET<T>* ptr) { pNext = ptr; }; +}; + +template <class T> class RBNODEPOOL +{ +private: + RBNODEBUCKET<T> base; + +public: + RBNODEPOOL() + { + memset(&base,0,sizeof(RBNODEBUCKET<T>)); + }; + + RBNODE<T>* AllocNode() + { + RBNODEBUCKET<T>* pBucket = &base; + RBNODEBUCKET<T>* pLastBucket = &base; + do + { + if(pBucket->CanAlloc()) + { + return pBucket->AllocNode(); + } + pLastBucket = pBucket; + pBucket = pBucket->Next(); + } + while (pBucket != NULL); + pLastBucket->Append(new RBNODEBUCKET<T>); + return pLastBucket->Next()->AllocNode(); + }; + + void FreeNode(RBNODE<T>* ptr) + { + RBNODEBUCKET<T>* pBucket = &base; + do + { + if(pBucket->FreeNode(ptr)) + break; + pBucket = pBucket->Next(); + } + while (pBucket != NULL); + }; +}; + +template <class T> class RBTREE +{ +private: + RBNODE<T>* pRoot; + RBNODE<T>* pNil; + RBNODEPOOL<T> NodePool; + void RotateLeft(RBNODE<T>* pX) + { + RBNODE<T>* pY; + + pY = pX->pRight; + pX->pRight = pY->pLeft; + + if(pY->pLeft != pNil) + pY->pLeft->pParent = pX; + + pY->pParent = pX->pParent; + + if(pX == pX->pParent->pLeft) + pX->pParent->pLeft = pY; + else + pX->pParent->pRight = pY; + + pY->pLeft = pX; + pX->pParent = pY; + }; + + void RotateRight(RBNODE<T>* pX) + { + RBNODE<T>* pY; + + pY = pX->pLeft; + pX->pLeft = pY->pRight; + + if(pY->pRight != pNil) + pY->pRight->pParent = pX; + + pY->pParent = pX->pParent; + + if(pX == pX->pParent->pLeft) + pX->pParent->pLeft = pY; + else + pX->pParent->pRight = pY; + + pY->pRight = pX; + pX->pParent = pY; + + }; + + void InsertNode(RBNODE<T>* pZ) + { + RBNODE<T>* pX; + RBNODE<T>* pY; + + pZ->pLeft = pZ->pRight = pNil; + pY = pRoot; + pX = pRoot->pLeft; + + if(pX != pY) + { + while(pX != pNil) + { + pY = pX; + if(pX->tVal->ComparedTo(pZ->tVal) > 0) + pX = pX->pLeft; + else + pX = pX->pRight; + } + } + pZ->pParent = pY; + if((pY == pRoot) || (pY->tVal->ComparedTo(pZ->tVal) > 0)) + pY->pLeft = pZ; + else + pY->pRight = pZ; + }; + + void InitSpecNode(RBNODE<T>* pNode) + { + pNode->pLeft = pNode->pRight = pNode->pParent = pNode; + }; + + void DeleteNode(RBNODE<T>* pNode, bool DeletePayload = true) + { + if((pNode != pNil)&&(pNode != pRoot)) + { + DeleteNode(pNode->pLeft, DeletePayload); + DeleteNode(pNode->pRight, DeletePayload); + if(DeletePayload) + delete pNode->tVal; + NodePool.FreeNode(pNode); + } + }; + +public: + RBTREE() + { + pRoot = NodePool.AllocNode(); + InitSpecNode(pRoot); + + pNil = NodePool.AllocNode(); + InitSpecNode(pNil); + }; + + ~RBTREE() + { + //RESET(false); + //NodePool.FreeNode(pRoot); + //NodePool.FreeNode(pNil); + }; + + void RESET(bool DeletePayload = true) + { + DeleteNode(pRoot->pLeft, DeletePayload); + InitSpecNode(pRoot); + InitSpecNode(pNil); + }; + + void PUSH(T* pT) + { + RBNODE<T>* pX; + RBNODE<T>* pY; + RBNODE<T>* pNewNode = NodePool.AllocNode(); + + pNewNode->tVal = pT; + pNewNode->SetRed(); + + InsertNode(pNewNode); + + for(pX = pNewNode; pX->pParent->IsRed();) + { + if(pX->pParent == pX->pParent->pLeft) + { + pY = pX->pParent->pRight; + if(pY->IsRed()) + { + pX->pParent->SetBlack(); + pY->SetBlack(); + pX->pParent->pParent->SetRed(); + pX = pX->pParent->pParent; + } + else + { + if(pX == pX->pParent->pRight) + { + pX = pX->pParent; + RotateLeft(pX); + } + pX->pParent->SetBlack(); + pX->pParent->pParent->SetRed(); + RotateRight(pX->pParent->pParent); + } + } + else // if(pX->pParent == pX->pParent->pRight) + { + pY = pX->pParent->pParent->pLeft; + if(pY->IsRed()) + { + pX->pParent->SetBlack(); + pY->SetBlack(); + pX->pParent->pParent->SetRed(); + pX = pX->pParent->pParent; + } + else + { + if(pX == pX->pParent->pLeft) + { + pX = pX->pParent; + RotateRight(pX); + } + pX->pParent->SetBlack(); + pX->pParent->pParent->SetRed(); + RotateLeft(pX->pParent->pParent); + } + }// end if(pX->pParent == pX->pParent->pLeft) -- else + } // end for(pX = pNewNode; pX->pParent->IsRed();) + pRoot->pLeft->SetBlack(); + }; + + T* FIND(T* pT) + { + RBNODE<T>* pX = pRoot->pLeft; + if((pX != pNil) && (pX != pRoot)) + { + int cmp = pX->tVal->ComparedTo(pT); + while(cmp != 0) + { + if(cmp > 0) + pX = pX->pLeft; + else + pX = pX->pRight; + if(pX == pNil) + return NULL; + cmp = pX->tVal->ComparedTo(pT); + } + return pX->tVal; + } + return NULL; + }; +}; + +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +#endif //ASMTEMPLATES_H + diff --git a/src/coreclr/ilasm/assem.cpp b/src/coreclr/ilasm/assem.cpp new file mode 100644 index 00000000000..bfe765c5499 --- /dev/null +++ b/src/coreclr/ilasm/assem.cpp @@ -0,0 +1,1641 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// File: assem.cpp +// + +// +// COM+ IL assembler +// +#include "ilasmpch.h" + +#define INITGUID + +#define DECLARE_DATA + +#include "assembler.h" + +void indexKeywords(Indx* indx); // defined in asmparse.y + +unsigned int g_uCodePage = CP_ACP; +unsigned int g_uConsoleCP = CP_ACP; + +char g_szSourceFileName[MAX_FILENAME_LENGTH*3]; + +WCHAR wzUniBuf[dwUniBuf]; // Unicode conversion global buffer + +Assembler::Assembler() +{ + m_pDisp = NULL; + m_pEmitter = NULL; + m_pImporter = NULL; + + m_fCPlusPlus = FALSE; + m_fWindowsCE = FALSE; + char* pszFQN = new char[16]; + strcpy_s(pszFQN,16,"<Module>"); + m_pModuleClass = new Class(pszFQN); + m_lstClass.PUSH(m_pModuleClass); + m_hshClass.PUSH(m_pModuleClass); + m_pModuleClass->m_cl = mdTokenNil; + m_pModuleClass->m_bIsMaster = FALSE; + + m_fStdMapping = FALSE; + m_fDisplayTraceOutput= FALSE; + m_fENCMode = FALSE; + m_fTolerateDupMethods = FALSE; + + m_pCurOutputPos = NULL; + + m_CurPC = 0; // PC offset in method + m_pCurMethod = NULL; + m_pCurClass = NULL; + m_pCurEvent = NULL; + m_pCurProp = NULL; + + m_wzMetadataVersion = NULL; + m_wMSVmajor = 0xFFFF; + m_wMSVminor = 0xFFFF; + + m_wSSVersionMajor = 4; + m_wSSVersionMinor = 0; + m_fAppContainer = FALSE; + m_fHighEntropyVA = FALSE; + + m_pCeeFileGen = NULL; + m_pCeeFile = 0; + + m_pManifest = NULL; + + m_pCustomDescrList = NULL; + + m_pGlobalDataSection = NULL; + m_pILSection = NULL; + m_pTLSSection = NULL; + + m_fDidCoInitialise = FALSE; + + m_fDLL = FALSE; + m_fEntryPointPresent = FALSE; + m_fHaveFieldsWithRvas = FALSE; + m_fFoldCode = FALSE; + m_dwMethodsFolded = 0; + + m_szScopeName[0] = 0; + m_crExtends = mdTypeDefNil; + + m_nImplList = 0; + m_TyParList = NULL; + + m_SEHD = NULL; + m_firstArgName = NULL; + m_lastArgName = NULL; + m_szNamespace = new char[2]; + m_szNamespace[0] = 0; + m_NSstack.PUSH(m_szNamespace); + + m_szFullNS = new char[MAX_NAMESPACE_LENGTH]; + memset(m_szFullNS,0,MAX_NAMESPACE_LENGTH); + m_ulFullNSLen = MAX_NAMESPACE_LENGTH; + + m_State = STATE_OK; + m_fInitialisedMetaData = FALSE; + m_fAutoInheritFromObject = TRUE; + + m_ulLastDebugLine = 0xFFFFFFFF; + m_ulLastDebugColumn = 0xFFFFFFFF; + m_ulLastDebugLineEnd = 0xFFFFFFFF; + m_ulLastDebugColumnEnd = 0xFFFFFFFF; + m_pSymWriter = NULL; + m_pSymDocument = NULL; + m_dwIncludeDebugInfo = 0; + m_fGeneratePDB = FALSE; + m_fIsMscorlib = FALSE; + m_fOptimize = FALSE; + m_tkSysObject = 0; + m_tkSysString = 0; + m_tkSysValue = 0; + m_tkSysEnum = 0; + + m_pVTable = NULL; + m_pMarshal = NULL; + m_pPInvoke = NULL; + + m_fReportProgress = TRUE; + m_tkCurrentCVOwner = 1; // module + m_pOutputBuffer = NULL; + + m_dwSubsystem = (DWORD)-1; + m_dwComImageFlags = COMIMAGE_FLAGS_ILONLY; + m_dwFileAlignment = 0; + m_stBaseAddress = 0; + m_stSizeOfStackReserve = 0; + m_dwCeeFileFlags = ICEE_CREATE_FILE_PURE_IL; + + g_szSourceFileName[0] = 0; + + m_guidLang = CorSym_LanguageType_ILAssembly; + m_guidLangVendor = CorSym_LanguageVendor_Microsoft; + m_guidDoc = CorSym_DocumentType_Text; + for(int i=0; i<INSTR_POOL_SIZE; i++) m_Instr[i].opcode = -1; + m_wzResourceFile = NULL; + m_wzKeySourceName = NULL; + OnErrGo = false; + bClock = NULL; + + m_pbsMD = NULL; + + m_pOutputBuffer = new BYTE[OUTPUT_BUFFER_SIZE]; + + m_pCurOutputPos = m_pOutputBuffer; + m_pEndOutputPos = m_pOutputBuffer + OUTPUT_BUFFER_SIZE; + + m_crImplList = new mdTypeRef[MAX_INTERFACES_IMPLEMENTED]; + m_nImplListSize = MAX_INTERFACES_IMPLEMENTED; + + m_pManifest = new AsmMan((void*)this); + + dummyClass = new Class(NULL); + indexKeywords(&indxKeywords); + + m_pdbFormat = CLASSIC; + m_pPortablePdbWriter = NULL; +} + + +Assembler::~Assembler() +{ + if(m_pbsMD) delete m_pbsMD; + + if(m_pMarshal) delete m_pMarshal; + if(m_pManifest) delete m_pManifest; + if(m_pPInvoke) delete m_pPInvoke; + + if(m_pVTable) delete m_pVTable; + + m_lstGlobalLabel.RESET(true); + m_lstGlobalFixup.RESET(true); + m_hshClass.RESET(false); + m_lstClass.RESET(true); + while((m_ClassStack.POP())); + while(m_CustomDescrListStack.POP()); + m_pCurClass = NULL; + dummyClass->m_szFQN = NULL; + delete dummyClass; + + if (m_pOutputBuffer) delete [] m_pOutputBuffer; + if (m_crImplList) delete [] m_crImplList; + if (m_TyParList) delete m_TyParList; + + if (m_pCeeFileGen != NULL) { + if (m_pCeeFile) + m_pCeeFileGen->DestroyCeeFile(&m_pCeeFile); + + DestroyICeeFileGen(&m_pCeeFileGen); + + m_pCeeFileGen = NULL; + } + + while((m_szNamespace = m_NSstack.POP())) ; + delete [] m_szFullNS; + + m_DocWriterList.RESET(true); + + m_MethodBodyList.RESET(true); + + m_TypeDefDList.RESET(true); + + if (m_pSymWriter != NULL) + { + m_pSymWriter->Close(); + m_pSymWriter->Release(); + m_pSymWriter = NULL; + } + if (m_pImporter != NULL) + { + m_pImporter->Release(); + m_pImporter = NULL; + } + if (m_pEmitter != NULL) + { + m_pEmitter->Release(); + m_pEmitter = NULL; + } + if (m_pPortablePdbWriter != NULL) + { + delete m_pPortablePdbWriter; + m_pPortablePdbWriter = NULL; + } + if (m_pDisp != NULL) + { + m_pDisp->Release(); + m_pDisp = NULL; + } +} + + +BOOL Assembler::Init(BOOL generatePdb, PdbFormat pdbFormat) +{ + if (m_pCeeFileGen != NULL) { + if (m_pCeeFile) + m_pCeeFileGen->DestroyCeeFile(&m_pCeeFile); + + DestroyICeeFileGen(&m_pCeeFileGen); + + m_pCeeFileGen = NULL; + } + + if (FAILED(CreateICeeFileGen(&m_pCeeFileGen))) return FALSE; + + if (FAILED(m_pCeeFileGen->CreateCeeFileEx(&m_pCeeFile,(ULONG)m_dwCeeFileFlags))) return FALSE; + + if (FAILED(m_pCeeFileGen->GetSectionCreate(m_pCeeFile, ".il", sdReadOnly, &m_pILSection))) return FALSE; + if (FAILED(m_pCeeFileGen->GetSectionCreate (m_pCeeFile, ".sdata", sdReadWrite, &m_pGlobalDataSection))) return FALSE; + if (FAILED(m_pCeeFileGen->GetSectionCreate (m_pCeeFile, ".tls", sdReadWrite, &m_pTLSSection))) return FALSE; + + m_fGeneratePDB = generatePdb; + m_pdbFormat = pdbFormat; + + return TRUE; +} + +void Assembler::SetDLL(BOOL IsDll) +{ + HRESULT OK; + OK = m_pCeeFileGen->SetDllSwitch(m_pCeeFile, IsDll); + _ASSERTE(SUCCEEDED(OK)); + + m_fDLL = IsDll; +} + +void Assembler::SetOBJ(BOOL IsObj) +{ + HRESULT OK; + OK = m_pCeeFileGen->SetObjSwitch(m_pCeeFile, IsObj); + _ASSERTE(SUCCEEDED(OK)); + + m_fOBJ = IsObj; +} + + +void Assembler::ResetArgNameList() +{ + if(m_firstArgName) delArgNameList(m_firstArgName); + m_firstArgName = NULL; + m_lastArgName = NULL; +} + +void Assembler::ResetForNextMethod() +{ + + ResetArgNameList(); + + m_CurPC = 0; + m_pCurOutputPos = m_pOutputBuffer; + m_State = STATE_OK; + m_pCurMethod = NULL; +} + +void Assembler::ResetLineNumbers() +{ + // reset line number information + m_ulLastDebugLine = 0xFFFFFFFF; + m_ulLastDebugColumn = 0xFFFFFFFF; + m_ulLastDebugLineEnd = 0xFFFFFFFF; + m_ulLastDebugColumnEnd = 0xFFFFFFFF; +} + +BOOL Assembler::AddMethod(Method *pMethod) +{ + BOOL fIsInterface=FALSE, fIsImport=FALSE; + ULONG PEFileOffset=0; + + _ASSERTE(m_pCeeFileGen != NULL); + if (pMethod == NULL) + { + report->error("pMethod == NULL"); + return FALSE; + } + if(pMethod->m_pClass != NULL) + { + fIsInterface = IsTdInterface(pMethod->m_pClass->m_Attr); + fIsImport = IsTdImport(pMethod->m_pClass->m_Attr); + } + if(m_CurPC) + { + char sz[1024]; + sz[0] = 0; + if(fIsImport) strcat_s(sz,1024," imported"); + if(IsMdAbstract(pMethod->m_Attr)) strcat_s(sz,1024," abstract"); + if(IsMdPinvokeImpl(pMethod->m_Attr)) strcat_s(sz,1024," pinvoke"); + if(!IsMiIL(pMethod->m_wImplAttr)) strcat_s(sz,1024," non-IL"); + if(IsMiRuntime(pMethod->m_wImplAttr)) strcat_s(sz,1024," runtime-supplied"); + if(IsMiInternalCall(pMethod->m_wImplAttr)) strcat_s(sz,1024," an internal call"); + if(strlen(sz)) + { + report->error("Method cannot have body if it is%s\n",sz); + } + } + else // method has no body + { + if(fIsImport || IsMdAbstract(pMethod->m_Attr) || IsMdPinvokeImpl(pMethod->m_Attr) + || IsMiRuntime(pMethod->m_wImplAttr) || IsMiInternalCall(pMethod->m_wImplAttr)) return TRUE; + if(OnErrGo) + { + report->error("Method has no body\n"); + return TRUE; + } + else + { + report->warn("Method has no body, 'ret' emitted\n"); + Instr* pIns = GetInstr(); + if(pIns) + { + memset(pIns,0,sizeof(Instr)); + pIns->opcode = CEE_RET; + EmitOpcode(pIns); + } + } + } + + if(pMethod->m_Locals.COUNT()) pMethod->m_LocalsSig=0x11000001; // placeholder, the real token 2b defined in EmitMethod + + COR_ILMETHOD_FAT fatHeader; + fatHeader.SetFlags(pMethod->m_Flags); + fatHeader.SetMaxStack(pMethod->m_MaxStack); + fatHeader.SetLocalVarSigTok(pMethod->m_LocalsSig); + fatHeader.SetCodeSize(m_CurPC); + bool moreSections = (pMethod->m_dwNumExceptions != 0); + + // if max stack is specified <8, force fat header, otherwise (with tiny header) it will default to 8 + if((fatHeader.GetMaxStack() < 8)&&(fatHeader.GetLocalVarSigTok()==0)&&(fatHeader.GetCodeSize()<64)&&(!moreSections)) + fatHeader.SetFlags(fatHeader.GetFlags() | CorILMethod_InitLocals); //forces fat header but does nothing else, since LocalVarSigTok==0 + + unsigned codeSize = m_CurPC; + unsigned codeSizeAligned = codeSize; + if (moreSections) + codeSizeAligned = (codeSizeAligned + 3) & ~3; // to insure EH section aligned + + unsigned headerSize = COR_ILMETHOD::Size(&fatHeader, moreSections); + unsigned ehSize = COR_ILMETHOD_SECT_EH::Size(pMethod->m_dwNumExceptions, pMethod->m_ExceptionList); + unsigned totalSize = headerSize + codeSizeAligned + ehSize; + + BYTE* outBuff; + BYTE* endbuf; + BinStr* pbsBody; + if((pbsBody = new BinStr())==NULL) return FALSE; + if((outBuff = pbsBody->getBuff(totalSize))==NULL) return FALSE; + endbuf = &outBuff[totalSize]; + + // Emit the header + outBuff += COR_ILMETHOD::Emit(headerSize, &fatHeader, moreSections, outBuff); + + pMethod->m_pCode = outBuff; + pMethod->m_headerOffset= PEFileOffset; + pMethod->m_methodOffset= PEFileOffset + headerSize; + pMethod->m_CodeSize = codeSize; + + // Emit the code + if (codeSizeAligned) + { + memset(outBuff,0,codeSizeAligned); + memcpy(outBuff, m_pOutputBuffer, codeSize); + outBuff += codeSizeAligned; + } + + if(pMethod->m_dwNumExceptions) + { + // Validate the eh + COR_ILMETHOD_SECT_EH_CLAUSE_FAT* pEx; + DWORD TryEnd,HandlerEnd, dwEx, dwEf; + for(dwEx = 0, pEx = pMethod->m_ExceptionList; dwEx < pMethod->m_dwNumExceptions; dwEx++, pEx++) + { + if(pEx->GetTryOffset() > m_CurPC) // i.e., pMethod->m_CodeSize + { + report->error("Invalid SEH clause #%d: Try block starts beyond code size\n",dwEx+1); + } + TryEnd = pEx->GetTryOffset()+pEx->GetTryLength(); + if(TryEnd > m_CurPC) + { + report->error("Invalid SEH clause #%d: Try block ends beyond code size\n",dwEx+1); + } + if(pEx->GetHandlerOffset() > m_CurPC) + { + report->error("Invalid SEH clause #%d: Handler block starts beyond code size\n",dwEx+1); + } + HandlerEnd = pEx->GetHandlerOffset()+pEx->GetHandlerLength(); + if(HandlerEnd > m_CurPC) + { + report->error("Invalid SEH clause #%d: Handler block ends beyond code size\n",dwEx+1); + } + if(pEx->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) + { + if(!((pEx->GetFilterOffset() >= TryEnd)||(pEx->GetTryOffset() >= HandlerEnd))) + { + report->error("Invalid SEH clause #%d: Try and Filter/Handler blocks overlap\n",dwEx+1); + } + for(dwEf = 0; dwEf < pMethod->m_dwNumEndfilters; dwEf++) + { + if(pMethod->m_EndfilterOffsetList[dwEf] == pEx->GetHandlerOffset()) break; + } + if(dwEf >= pMethod->m_dwNumEndfilters) + { + report->error("Invalid SEH clause #%d: Filter block separated from Handler, or not ending with endfilter\n",dwEx+1); + } + } + else + if(!((pEx->GetHandlerOffset() >= TryEnd)||(pEx->GetTryOffset() >= HandlerEnd))) + { + report->error("Invalid SEH clause #%d: Try and Handler blocks overlap\n",dwEx+1); + } + + } + // Emit the eh + outBuff += COR_ILMETHOD_SECT_EH::Emit(ehSize, pMethod->m_dwNumExceptions, + pMethod->m_ExceptionList, false, outBuff); + } + _ASSERTE(outBuff == endbuf); + + pMethod->m_pbsBody = pbsBody; + + LocalMemberRefFixup* pMRF; + while((pMRF = pMethod->m_LocalMemberRefFixupList.POP())) + { + pMRF->offset += (size_t)(pMethod->m_pCode); + m_LocalMemberRefFixupList.PUSH(pMRF); // transfer MRF to assembler's list + } + + if(m_fReportProgress) + { + if (pMethod->IsGlobalMethod()) + report->msg("Assembled global method %s\n", pMethod->m_szName); + else report->msg("Assembled method %s::%s\n", pMethod->m_pClass->m_szFQN, + pMethod->m_szName); + } + return TRUE; +} + + +BOOL Assembler::EmitMethodBody(Method* pMethod, BinStr* pbsOut) +{ + HRESULT hr = S_OK; + + if(pMethod) + { + BinStr* pbsBody = pMethod->m_pbsBody; + unsigned totalSize; + if(pbsBody && (totalSize = pbsBody->length())) + { + unsigned headerSize = pMethod->m_methodOffset-pMethod->m_headerOffset; + MethodBody* pMB = NULL; + // ----------emit locals signature------------------- + unsigned uLocals; + if((uLocals = pMethod->m_Locals.COUNT())) + { + VarDescr* pVD; + BinStr* pbsSig = new BinStr(); + unsigned cnt; + DWORD cSig; + const COR_SIGNATURE* mySig; + + pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG); + cnt = CorSigCompressData(uLocals,pbsSig->getBuff(5)); + pbsSig->remove(5-cnt); + for(cnt = 0; (pVD = pMethod->m_Locals.PEEK(cnt)); cnt++) + { + if(pVD->pbsSig) pbsSig->append(pVD->pbsSig); + else + { + report->error("Undefined type of local var slot %d in method %s\n",cnt,pMethod->m_szName); + pbsSig->appendInt8(ELEMENT_TYPE_I4); + } + } + + cSig = pbsSig->length(); + mySig = (const COR_SIGNATURE *)(pbsSig->ptr()); + + if (cSig > 1) // non-empty signature + { + hr = m_pEmitter->GetTokenFromSig(mySig, cSig, &pMethod->m_LocalsSig); + _ASSERTE(SUCCEEDED(hr)); + } + delete pbsSig; + COR_ILMETHOD_FAT* pFH; // Fat header guaranteed, because there are local vars + pFH = (COR_ILMETHOD_FAT*)(pMethod->m_pbsBody->ptr()); + pFH->SetLocalVarSigTok(pMethod->m_LocalsSig); + } + //-------------------------------------------------------------------------------- + if(m_fGeneratePDB) + { + if (m_pSymWriter != NULL) + { + m_pSymWriter->OpenMethod(pMethod->m_Tok); + ULONG N = pMethod->m_LinePCList.COUNT(); + if(pMethod->m_fEntryPoint) m_pSymWriter->SetUserEntryPoint(pMethod->m_Tok); + if(N) + { + LinePC *pLPC; + ULONG32 *offsets=new ULONG32[N], *lines = new ULONG32[N], *columns = new ULONG32[N]; + ULONG32 *endlines=new ULONG32[N], *endcolumns=new ULONG32[N]; + if(offsets && lines && columns && endlines && endcolumns) + { + DocWriter* pDW; + unsigned j=0; + while((pDW = m_DocWriterList.PEEK(j++))) + { + if((m_pSymDocument = pDW->pWriter)) + { + int i, n; + for(i=0, n=0; (pLPC = pMethod->m_LinePCList.PEEK(i)); i++) + { + if(pLPC->pWriter == m_pSymDocument) + { + offsets[n] = pLPC->PC; + lines[n] = pLPC->Line; + columns[n] = pLPC->Column; + endlines[n] = pLPC->LineEnd; + endcolumns[n] = pLPC->ColumnEnd; + n++; + } + } + if(n) m_pSymWriter->DefineSequencePoints(m_pSymDocument,n, + offsets,lines,columns,endlines,endcolumns); + } // end if(pSymDocument) + } // end while(pDW = next doc.writer) + pMethod->m_LinePCList.RESET(true); + } + else report->error("\nOutOfMemory!\n"); + delete [] offsets; + delete [] lines; + delete [] columns; + delete [] endlines; + delete [] endcolumns; + }//enf if(N) + HRESULT hrr; + if(pMethod->m_ulLines[1]) + hrr = m_pSymWriter->SetMethodSourceRange(m_pSymDocument,pMethod->m_ulLines[0], pMethod->m_ulColumns[0], + m_pSymDocument,pMethod->m_ulLines[1], pMethod->m_ulColumns[1]); + EmitScope(&(pMethod->m_MainScope)); // recursively emits all nested scopes + + m_pSymWriter->CloseMethod(); + } + else if (IsPortablePdb()) + { + if (FAILED(m_pPortablePdbWriter->DefineSequencePoints(pMethod))) + return FALSE; + if (FAILED(m_pPortablePdbWriter->DefineLocalScope(pMethod))) + return FALSE; + } + } // end if(fIncludeDebugInfo) + //----------------------------------------------------- + + if(m_fFoldCode) + { + for(int k=0; (pMB = m_MethodBodyList.PEEK(k)) != NULL; k++) + { + if((pMB->pbsBody->length() == totalSize) + && (memcmp(pMB->pbsBody->ptr(), pbsBody->ptr(),totalSize)==0)) + break; + } + if(pMB) + { + pMethod->m_headerOffset= pMB->RVA; + pMethod->m_methodOffset= pMB->RVA + headerSize; + pMethod->m_pCode = pMB->pCode; + delete pbsBody; + pMethod->m_pbsBody = NULL; + m_dwMethodsFolded++; + } + } + if(pMB == NULL) + { + BYTE* outBuff; + unsigned align = (headerSize == 1)? 1 : 4; + ULONG PEFileOffset, methodRVA; + if(m_fENCMode) + { + if(pbsOut) + { + PEFileOffset = pbsOut->length(); + align--; + while(PEFileOffset & align) + { + pbsOut->appendInt8(0); + PEFileOffset++; + } + pbsOut->append(pbsBody); + outBuff = (BYTE*)(pbsOut->ptr()) + (pbsOut->length() - pbsBody->length()); + } + else return FALSE; + + } + else + { + if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, totalSize, + align, (void **) &outBuff))) return FALSE; + memcpy(outBuff,pbsBody->ptr(),totalSize); + // The offset where we start, (not where the alignment bytes start! + if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) + return FALSE; + PEFileOffset -= totalSize; + } + + pMethod->m_pCode = outBuff + headerSize; + pMethod->m_headerOffset= PEFileOffset; + pMethod->m_methodOffset= PEFileOffset + headerSize; + DoDeferredILFixups(pMethod); + + if(m_fENCMode) methodRVA = PEFileOffset; + else m_pCeeFileGen->GetMethodRVA(m_pCeeFile, PEFileOffset,&methodRVA); + + pMethod->m_headerOffset= methodRVA; + pMethod->m_methodOffset= methodRVA + headerSize; + if(m_fFoldCode) + { + if((pMB = new MethodBody)==NULL) return FALSE; + pMB->pbsBody = pbsBody; + pMB->RVA = methodRVA; + pMB->pCode = pMethod->m_pCode; + m_MethodBodyList.PUSH(pMB); + } + //else + // delete pbsBody; + //pMethod->m_pbsBody = NULL; + } + m_pEmitter->SetRVA(pMethod->m_Tok,pMethod->m_headerOffset); + } + return TRUE; + } + else return FALSE; +} + +ImportDescriptor* Assembler::EmitImport(BinStr* DllName) +{ + int i = 0, l = 0; + ImportDescriptor* pID; + char* sz=NULL; + + if(DllName) l = DllName->length(); // No zero terminator here! + if(l) + { + sz = (char*)DllName->ptr(); + while((pID=m_ImportList.PEEK(i++))) + { + if((pID->dwDllName== (DWORD) l)&& !memcmp(pID->szDllName,sz,l)) return pID; + } + } + else + { + while((pID=m_ImportList.PEEK(i++))) + { + if(pID->dwDllName==0) return pID; + } + } + if((pID = new ImportDescriptor(sz,l))) + { + m_ImportList.PUSH(pID); + pID->mrDll = TokenFromRid(m_ImportList.COUNT(),mdtModuleRef); + return pID; + } + else report->error("Failed to allocate import descriptor\n"); + return NULL; +} + +void Assembler::EmitImports() +{ + WCHAR* wzDllName=&wzUniBuf[0]; + ImportDescriptor* pID; + int i; + mdToken tk; + for(i=0; (pID = m_ImportList.PEEK(i)); i++) + { + WszMultiByteToWideChar(g_uCodePage,0,pID->szDllName,-1,wzDllName,dwUniBuf-1); + if(FAILED(m_pEmitter->DefineModuleRef( // S_OK or error. + wzDllName, // [IN] DLL name + &tk))) // [OUT] returned + report->error("Failed to define module ref '%s'\n",pID->szDllName); + else + _ASSERTE(tk == pID->mrDll); + } +} + +HRESULT Assembler::EmitPinvokeMap(mdToken tk, PInvokeDescriptor* pDescr) +{ + WCHAR* wzAlias=&wzUniBuf[0]; + + if(pDescr->szAlias) WszMultiByteToWideChar(g_uCodePage,0,pDescr->szAlias,-1,wzAlias,dwUniBuf-1); + + return m_pEmitter->DefinePinvokeMap( // Return code. + tk, // [IN] FieldDef, MethodDef or MethodImpl. + pDescr->dwAttrs, // [IN] Flags used for mapping. + (LPCWSTR)wzAlias, // [IN] Import name. + pDescr->mrDll); // [IN] ModuleRef token for the target DLL. +} + +void Assembler::EmitScope(Scope* pSCroot) +{ + static ULONG32 scopeID; + static ARG_NAME_LIST *pVarList; + int i; + WCHAR* wzVarName=&wzUniBuf[0]; + char* szPhonyName=(char*)&wzUniBuf[dwUniBuf >> 1]; + Scope* pSC = pSCroot; + if(pSC && m_pSymWriter) + { + if(SUCCEEDED(m_pSymWriter->OpenScope(pSC->dwStart,&scopeID))) + { + if(pSC->pLocals) + { + for(pVarList = pSC->pLocals; pVarList; pVarList = pVarList->pNext) + { + if(pVarList->pSig) + { + if((pVarList->szName)&&(*(pVarList->szName))) strcpy_s(szPhonyName,dwUniBuf >> 1,pVarList->szName); + else sprintf_s(szPhonyName,(dwUniBuf >> 1),"V_%d",pVarList->dwAttr); + + WszMultiByteToWideChar(g_uCodePage,0,szPhonyName,-1,wzVarName,dwUniBuf >> 1); + + m_pSymWriter->DefineLocalVariable(wzVarName,0,pVarList->pSig->length(), + (BYTE*)pVarList->pSig->ptr(),ADDR_IL_OFFSET,pVarList->dwAttr,0,0,0,0); + } + else + { + report->error("Local Var '%s' has no signature\n",pVarList->szName); + } + } + } + for(i = 0; (pSC = pSCroot->SubScope.PEEK(i)); i++) EmitScope(pSC); + m_pSymWriter->CloseScope(pSCroot->dwEnd); + } + } +} + +BOOL Assembler::EmitMethod(Method *pMethod) +{ +// Emit the metadata for a method definition + BOOL fSuccess = FALSE; + WCHAR* wzMemberName=&wzUniBuf[0]; + BOOL fIsInterface; + DWORD cSig; + ULONG methodRVA = 0; + mdMethodDef MethodToken; + mdTypeDef ClassToken = mdTypeDefNil; + char *pszMethodName; + COR_SIGNATURE *mySig; + + _ASSERTE((m_pCeeFileGen != NULL) && (pMethod != NULL)); + fIsInterface = ((pMethod->m_pClass != NULL) && IsTdInterface(pMethod->m_pClass->m_Attr)); + + + pszMethodName = pMethod->m_szName; + mySig = pMethod->m_pMethodSig; + cSig = pMethod->m_dwMethodCSig; + + // If this is an instance method, make certain the signature says so + + if (!(pMethod->m_Attr & mdStatic)) + *mySig |= IMAGE_CEE_CS_CALLCONV_HASTHIS; + + ClassToken = (pMethod->IsGlobalMethod())? mdTokenNil + : pMethod->m_pClass->m_cl; + // Convert name to UNICODE + WszMultiByteToWideChar(g_uCodePage,0,pszMethodName,-1,wzMemberName,dwUniBuf-1); + + if(IsMdPrivateScope(pMethod->m_Attr)) + { + WCHAR* p = wcsstr(wzMemberName,W("$PST06")); + if(p) *p = 0; + } + + if (FAILED(m_pEmitter->DefineMethod(ClassToken, // parent class + wzMemberName, // member name + pMethod->m_Attr & ~mdReservedMask, // member attributes + mySig, // member signature + cSig, + methodRVA, // RVA + pMethod->m_wImplAttr, // implflags + &MethodToken))) + { + report->error("Failed to define method '%s'\n",pszMethodName); + goto exit; + } + pMethod->m_Tok = MethodToken; + //-------------------------------------------------------------------------------- + // the only way to set mdRequireSecObject: + if(pMethod->m_Attr & mdRequireSecObject) + { + mdToken tkPseudoClass; + if(FAILED(m_pEmitter->DefineTypeRefByName(1, COR_REQUIRES_SECOBJ_ATTRIBUTE, &tkPseudoClass))) + report->error("Unable to define type reference '%s'\n", COR_REQUIRES_SECOBJ_ATTRIBUTE_ANSI); + else + { + mdToken tkPseudoCtor; + BYTE bSig[3] = {IMAGE_CEE_CS_CALLCONV_HASTHIS,0,ELEMENT_TYPE_VOID}; + if(FAILED(m_pEmitter->DefineMemberRef(tkPseudoClass, W(".ctor"), (PCCOR_SIGNATURE)bSig, 3, &tkPseudoCtor))) + report->error("Unable to define member reference '%s::.ctor'\n", COR_REQUIRES_SECOBJ_ATTRIBUTE_ANSI); + else DefineCV(new CustomDescr(MethodToken,tkPseudoCtor,NULL)); + } + } + + if (pMethod->m_NumTyPars) + { + ULONG i; + mdToken tkNil = mdTokenNil; + mdGenericParam tkGP = mdTokenNil; + for(i = 0; i < pMethod->m_NumTyPars; i++) + { + if (FAILED(m_pEmitter->DefineGenericParam(MethodToken, i, pMethod->m_TyPars[i].Attrs(), pMethod->m_TyPars[i].Name(), 0, &tkNil, &tkGP))) + { + report->error("Unable to define generic param: %s'\n", pMethod->m_TyPars[i].Name()); + } + else + { + pMethod->m_TyPars[i].Token(tkGP); + EmitCustomAttributes(tkGP, pMethod->m_TyPars[i].CAList()); + } + } + EmitGenericParamConstraints(pMethod->m_NumTyPars, pMethod->m_TyPars, pMethod->m_Tok, &(pMethod->m_GPCList)); + } + //-------------------------------------------------------------------------------- + EmitSecurityInfo(MethodToken, + pMethod->m_pPermissions, + pMethod->m_pPermissionSets); + //-------------------------------------------------------------------------------- + if (pMethod->m_fEntryPoint) + { + if(fIsInterface) report->error("Entrypoint in Interface: Method '%s'\n",pszMethodName); + + if (FAILED(m_pCeeFileGen->SetEntryPoint(m_pCeeFile, MethodToken))) + { + report->error("Failed to set entry point for method '%s'\n",pszMethodName); + goto exit; + } + + } + //-------------------------------------------------------------------------------- + if(IsMdPinvokeImpl(pMethod->m_Attr)) + { + if(pMethod->m_pPInvoke) + { + HRESULT hr; + if(pMethod->m_pPInvoke->szAlias == NULL) pMethod->m_pPInvoke->szAlias = pszMethodName; + hr = EmitPinvokeMap(MethodToken,pMethod->m_pPInvoke); + if(pMethod->m_pPInvoke->szAlias == pszMethodName) pMethod->m_pPInvoke->szAlias = NULL; + + if(FAILED(hr)) + { + report->error("Failed to set PInvoke map for method '%s'\n",pszMethodName); + goto exit; + } + } + } + + { // add parameters to metadata + void const *pValue=NULL; + ULONG cbValue; + DWORD dwCPlusTypeFlag=0; + mdParamDef pdef; + WCHAR* wzParName=&wzUniBuf[0]; + char* szPhonyName=(char*)&wzUniBuf[dwUniBuf >> 1]; + if(pMethod->m_dwRetAttr || pMethod->m_pRetMarshal || pMethod->m_RetCustDList.COUNT()) + { + if(pMethod->m_pRetValue) + { + dwCPlusTypeFlag= (DWORD)*(pMethod->m_pRetValue->ptr()); + pValue = (void const *)(pMethod->m_pRetValue->ptr()+1); + cbValue = pMethod->m_pRetValue->length()-1; + if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING) cbValue /= sizeof(WCHAR); + } + else + { + pValue = NULL; + cbValue = (ULONG)-1; + dwCPlusTypeFlag=0; + } + m_pEmitter->DefineParam(MethodToken,0,NULL,pMethod->m_dwRetAttr,dwCPlusTypeFlag,pValue,cbValue,&pdef); + + if(pMethod->m_pRetMarshal) + { + if(FAILED(m_pEmitter->SetFieldMarshal ( + pdef, // [IN] given a fieldDef or paramDef token + (PCCOR_SIGNATURE)(pMethod->m_pRetMarshal->ptr()), // [IN] native type specification + pMethod->m_pRetMarshal->length()))) // [IN] count of bytes of pvNativeType + report->error("Failed to set param marshaling for return\n"); + + } + EmitCustomAttributes(pdef, &(pMethod->m_RetCustDList)); + } + for(ARG_NAME_LIST *pAN=pMethod->m_firstArgName; pAN; pAN = pAN->pNext) + { + if(pAN->nNum >= 65535) + { + report->error("Method '%s': Param.sequence number (%d) exceeds 65535, unable to define parameter\n",pszMethodName,pAN->nNum+1); + continue; + } + if(pAN->dwName) strcpy_s(szPhonyName,dwUniBuf >> 1,pAN->szName); + else sprintf_s(szPhonyName,(dwUniBuf >> 1),"A_%d",pAN->nNum); + + WszMultiByteToWideChar(g_uCodePage,0,szPhonyName,-1,wzParName,dwUniBuf >> 1); + + if(pAN->pValue) + { + dwCPlusTypeFlag= (DWORD)*(pAN->pValue->ptr()); + pValue = (void const *)(pAN->pValue->ptr()+1); + cbValue = pAN->pValue->length()-1; + if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING) cbValue /= sizeof(WCHAR); + } + else + { + pValue = NULL; + cbValue = (ULONG)-1; + dwCPlusTypeFlag=0; + } + m_pEmitter->DefineParam(MethodToken,pAN->nNum+1,wzParName,pAN->dwAttr,dwCPlusTypeFlag,pValue,cbValue,&pdef); + if(pAN->pMarshal) + { + if(FAILED(m_pEmitter->SetFieldMarshal ( + pdef, // [IN] given a fieldDef or paramDef token + (PCCOR_SIGNATURE)(pAN->pMarshal->ptr()), // [IN] native type specification + pAN->pMarshal->length()))) // [IN] count of bytes of pvNativeType + report->error("Failed to set param marshaling for '%s'\n",pAN->szName); + } + EmitCustomAttributes(pdef, &(pAN->CustDList)); + } + } + fSuccess = TRUE; + //-------------------------------------------------------------------------------- + // Update method implementations for this method + { + MethodImplDescriptor* pMID; + int i; + for(i=0;(pMID = pMethod->m_MethodImplDList.PEEK(i));i++) + { + pMID->m_tkImplementingMethod = MethodToken; + // don't delete it here, it's still in the general list + } + } + //-------------------------------------------------------------------------------- + EmitCustomAttributes(MethodToken, &(pMethod->m_CustomDescrList)); +exit: + if (fSuccess == FALSE) m_State = STATE_FAIL; + return fSuccess; +} + +BOOL Assembler::EmitMethodImpls() +{ + MethodImplDescriptor* pMID; + BOOL ret = TRUE; + int i; + for(i=0; (pMID = m_MethodImplDList.PEEK(i)); i++) + { + if(m_fENCMode && (!pMID->m_fNew)) continue; + pMID->m_tkImplementingMethod = ResolveLocalMemberRef(pMID->m_tkImplementingMethod); + pMID->m_tkImplementedMethod = ResolveLocalMemberRef(pMID->m_tkImplementedMethod); + if(FAILED(m_pEmitter->DefineMethodImpl( pMID->m_tkDefiningClass, + pMID->m_tkImplementingMethod, + pMID->m_tkImplementedMethod))) + { + report->error("Failed to define Method Implementation"); + ret = FALSE; + } + pMID->m_fNew = FALSE; + }// end while + return ret; +} + +mdToken Assembler::ResolveLocalMemberRef(mdToken tok) +{ + if(TypeFromToken(tok) == 0x99000000) + { + tok = RidFromToken(tok); + if(tok) tok = m_LocalMethodRefDList.PEEK(tok-1)->m_tkResolved; + } + else if(TypeFromToken(tok) == 0x98000000) + { + tok = RidFromToken(tok); + if(tok) tok = m_LocalFieldRefDList.PEEK(tok-1)->m_tkResolved; + } + return tok; +} + +BOOL Assembler::EmitEvent(EventDescriptor* pED) +{ + mdMethodDef mdAddOn=mdMethodDefNil, + mdRemoveOn=mdMethodDefNil, + mdFire=mdMethodDefNil, + *mdOthers; + int nOthers; + WCHAR* wzMemberName=&wzUniBuf[0]; + + if(!pED) return FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,pED->m_szName,-1,wzMemberName,dwUniBuf-1); + + mdAddOn = ResolveLocalMemberRef(pED->m_tkAddOn); + if(TypeFromToken(mdAddOn) != mdtMethodDef) + { + report->error("Invalid Add method of event '%s'\n",pED->m_szName); + return FALSE; + } + mdRemoveOn = ResolveLocalMemberRef(pED->m_tkRemoveOn); + if(TypeFromToken(mdRemoveOn) != mdtMethodDef) + { + report->error("Invalid Remove method of event '%s'\n",pED->m_szName); + return FALSE; + } + mdFire = ResolveLocalMemberRef(pED->m_tkFire); + if((RidFromToken(mdFire)!=0)&&(TypeFromToken(mdFire) != mdtMethodDef)) + { + report->error("Invalid Fire method of event '%s'\n",pED->m_szName); + return FALSE; + } + + nOthers = pED->m_tklOthers.COUNT(); + mdOthers = new mdMethodDef[nOthers+1]; + if(mdOthers == NULL) + { + report->error("Failed to allocate Others array for event descriptor\n"); + nOthers = 0; + } + for(int j=0; j < nOthers; j++) + { + mdOthers[j] = ResolveLocalMemberRef((mdToken)(UINT_PTR)(pED->m_tklOthers.PEEK(j))); // @WARNING: casting down from 'mdToken*' to 'mdToken' + } + mdOthers[nOthers] = mdMethodDefNil; // like null-terminator + + if(FAILED(m_pEmitter->DefineEvent( pED->m_tdClass, + wzMemberName, + pED->m_dwAttr, + pED->m_tkEventType, + mdAddOn, + mdRemoveOn, + mdFire, + mdOthers, + &(pED->m_edEventTok)))) + { + report->error("Failed to define event '%s'.\n",pED->m_szName); + delete [] mdOthers; + return FALSE; + } + EmitCustomAttributes(pED->m_edEventTok, &(pED->m_CustomDescrList)); + return TRUE; +} + +BOOL Assembler::EmitProp(PropDescriptor* pPD) +{ + mdMethodDef mdSet, mdGet, *mdOthers; + int nOthers; + WCHAR* wzMemberName=&wzUniBuf[0]; + + if(!pPD) return FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,pPD->m_szName,-1,wzMemberName,dwUniBuf-1); + + mdSet = ResolveLocalMemberRef(pPD->m_tkSet); + if((RidFromToken(mdSet)!=0)&&(TypeFromToken(mdSet) != mdtMethodDef)) + { + report->error("Invalid Set method of property '%s'\n",pPD->m_szName); + return FALSE; + } + mdGet = ResolveLocalMemberRef(pPD->m_tkGet); + if((RidFromToken(mdGet)!=0)&&(TypeFromToken(mdGet) != mdtMethodDef)) + { + report->error("Invalid Get method of property '%s'\n",pPD->m_szName); + return FALSE; + } + + nOthers = pPD->m_tklOthers.COUNT(); + mdOthers = new mdMethodDef[nOthers+1]; + if(mdOthers == NULL) + { + report->error("Failed to allocate Others array for prop descriptor\n"); + nOthers = 0; + } + for(int j=0; j < nOthers; j++) + { + mdOthers[j] = ResolveLocalMemberRef((mdToken)(UINT_PTR)(pPD->m_tklOthers.PEEK(j))); // @WARNING: casting down from 'mdToken*' to 'mdToken' + + if((RidFromToken(mdOthers[j])!=0)&&(TypeFromToken(mdOthers[j]) != mdtMethodDef)) + { + report->error("Invalid Other method of property '%s'\n",pPD->m_szName); + delete [] mdOthers; + return FALSE; + } + + } + mdOthers[nOthers] = mdMethodDefNil; // like null-terminator + + if(FAILED(m_pEmitter->DefineProperty( pPD->m_tdClass, + wzMemberName, + pPD->m_dwAttr, + pPD->m_pSig, + pPD->m_dwCSig, + pPD->m_dwCPlusTypeFlag, + pPD->m_pValue, + pPD->m_cbValue, + mdSet, + mdGet, + mdOthers, + &(pPD->m_pdPropTok)))) + { + report->error("Failed to define property '%s'.\n",pPD->m_szName); + delete [] mdOthers; + return FALSE; + } + EmitCustomAttributes(pPD->m_pdPropTok, &(pPD->m_CustomDescrList)); + return TRUE; +} + +Class *Assembler::FindCreateClass(__in __nullterminated const char *pszFQN) +{ + Class *pSearch = NULL; + + if(pszFQN) + { + dummyClass->m_szFQN = pszFQN; + dummyClass->m_Hash = hash((BYTE*)pszFQN, (unsigned)strlen(pszFQN), 10); + pSearch = m_hshClass.FIND(dummyClass); + dummyClass->m_szFQN = NULL; + dummyClass->m_Hash = 0; + + if(!pSearch) + { + char* pch; + DWORD dwFQN = (DWORD)strlen(pszFQN); + + Class *pEncloser = NULL; + char* pszNewFQN = new char[dwFQN+1]; + strcpy_s(pszNewFQN,dwFQN+1,pszFQN); + if((pch = strrchr(pszNewFQN, NESTING_SEP)) != NULL) + { + *pch = 0; + pEncloser = FindCreateClass(pszNewFQN); + *pch = NESTING_SEP; + } + pSearch = new Class(pszNewFQN); + if (pSearch == NULL) + report->error("Failed to create class '%s'\n",pszNewFQN); + else + { + pSearch->m_pEncloser = pEncloser; + m_lstClass.PUSH(pSearch); + pSearch->m_cl = mdtTypeDef | m_lstClass.COUNT(); + m_hshClass.PUSH(pSearch); + } + } + } + + return pSearch; +} + + +BOOL Assembler::EmitClass(Class *pClass) +{ + LPCUTF8 szFullName; + WCHAR* wzFullName=&wzUniBuf[0]; + HRESULT hr = E_FAIL; + GUID guid; + size_t L; + mdToken tok; + + if(pClass == NULL) return FALSE; + + hr = CoCreateGuid(&guid); + if (FAILED(hr)) + { + printf("Unable to create GUID\n"); + m_State = STATE_FAIL; + return FALSE; + } + + if(pClass->m_pEncloser) + szFullName = strrchr(pClass->m_szFQN,NESTING_SEP) + 1; + else + szFullName = pClass->m_szFQN; + + WszMultiByteToWideChar(g_uCodePage,0,szFullName,-1,wzFullName,dwUniBuf); + + L = wcslen(wzFullName); + if((L==0)||(wzFullName[L-1]==L'.')) // Missing class name! + { + wcscat_s(wzFullName,dwUniBuf,W("$UNNAMED_TYPE$")); + } + + pClass->m_Attr = CheckClassFlagsIfNested(pClass->m_pEncloser, pClass->m_Attr); + + if (pClass->m_pEncloser) + { + hr = m_pEmitter->DefineNestedType( wzFullName, + pClass->m_Attr, // attributes + pClass->m_crExtends, // CR extends class + pClass->m_crImplements,// implements + pClass->m_pEncloser->m_cl, // Enclosing class. + &tok); + } + else + { + hr = m_pEmitter->DefineTypeDef( wzFullName, + pClass->m_Attr, // attributes + pClass->m_crExtends, // CR extends class + pClass->m_crImplements,// implements + &tok); + } + _ASSERTE(tok == pClass->m_cl); + if (FAILED(hr)) goto exit; + if (pClass->m_NumTyPars) + { + ULONG i; + mdToken tkNil = mdTokenNil; + mdGenericParam tkGP = mdTokenNil; + for(i = 0; i < pClass->m_NumTyPars; i++) + { + if (FAILED(m_pEmitter->DefineGenericParam(pClass->m_cl, i, pClass->m_TyPars[i].Attrs(), pClass->m_TyPars[i].Name(), 0, &tkNil, &tkGP))) + { + report->error("Unable to define generic param: %s'\n", pClass->m_TyPars[i].Name()); + } + else + { + pClass->m_TyPars[i].Token(tkGP); + EmitCustomAttributes(tkGP, pClass->m_TyPars[i].CAList()); + } + } + EmitGenericParamConstraints(pClass->m_NumTyPars, pClass->m_TyPars, pClass->m_cl, &(pClass->m_GPCList)); + } + + EmitCustomAttributes(pClass->m_cl, &(pClass->m_CustDList)); + hr = S_OK; + +exit: + return SUCCEEDED(hr); +} + +BOOL Assembler::DoGlobalFixups() +{ + GlobalFixup *pSearch; + + for (int i=0; (pSearch = m_lstGlobalFixup.PEEK(i)); i++) + { + GlobalLabel * pLabel = FindGlobalLabel(pSearch->m_szLabel); + if (pLabel == NULL) + { + report->error("Unable to find forward reference global label '%s'\n", + pSearch->m_szLabel); + + m_State = STATE_FAIL; + return FALSE; + } + //BYTE * pReference = pSearch->m_pReference; + //DWORD GlobalOffset = pLabel->m_GlobalOffset; + //memcpy(pReference,&GlobalOffset,4); + SET_UNALIGNED_VAL32(pSearch->m_pReference,pLabel->m_GlobalOffset); + } + + return TRUE; +} + +state_t Assembler::AddGlobalLabel(__in __nullterminated char *pszName, HCEESECTION section) +{ + if (FindGlobalLabel(pszName) != NULL) + { + report->error("Duplicate global label '%s'\n", pszName); + m_State = STATE_FAIL; + return m_State; + } + + ULONG GlobalOffset; + + HRESULT hr; + hr = m_pCeeFileGen->GetSectionDataLen(section, &GlobalOffset); + _ASSERTE(SUCCEEDED(hr)); + + GlobalLabel *pNew = new GlobalLabel(pszName, GlobalOffset, section); + if (pNew == 0) + { + report->error("Failed to allocate global label '%s'\n",pszName); + m_State = STATE_FAIL; + return m_State; + } + + m_lstGlobalLabel.PUSH(pNew); + return m_State; +} + +void Assembler::AddLabel(DWORD CurPC, __in __nullterminated char *pszName) +{ + if (m_pCurMethod->FindLabel(pszName) != NULL) + { + report->error("Duplicate label: '%s'\n", pszName); + + m_State = STATE_FAIL; + } + else + { + Label *pNew = new Label(pszName, CurPC); + + if (pNew != NULL) + //m_pCurMethod->m_lstLabel.PUSH(pNew); + m_lstLabel.PUSH(pNew); + else + { + report->error("Failed to allocate label '%s'\n",pszName); + m_State = STATE_FAIL; + } + } +} + +void Assembler::DoDeferredILFixups(Method* pMethod) +{ // Now that we know where in the file the code bytes will wind up, + // we can update the RVAs and offsets. + ILFixup *pSearch; + HRESULT hr; + GlobalFixup *Fix = NULL; + int i; + for (i=0;(pSearch = pMethod->m_lstILFixup.PEEK(i));i++) + { + switch(pSearch->m_Kind) + { + case ilGlobal: + Fix = pSearch->m_Fixup; + _ASSERTE(Fix != NULL); + Fix->m_pReference = pMethod->m_pCode+pSearch->m_OffsetInMethod; + break; + + case ilToken: + hr = m_pCeeFileGen->AddSectionReloc(m_pILSection, + pSearch->m_OffsetInMethod+pMethod->m_methodOffset, + m_pILSection, + srRelocMapToken); + _ASSERTE(SUCCEEDED(hr)); + break; + + case ilRVA: + hr = m_pCeeFileGen->AddSectionReloc(m_pILSection, + pSearch->m_OffsetInMethod+pMethod->m_methodOffset, + m_pGlobalDataSection, + srRelocAbsolute); + _ASSERTE(SUCCEEDED(hr)); + break; + + default: + ; + } + } +} +/**************************************************************************/ +BOOL Assembler::DoFixups(Method* pMethod) +{ + Fixup *pSearch; + + for (int i=0; (pSearch = pMethod->m_lstFixup.PEEK(i)); i++) + { + Label * pLabel = pMethod->FindLabel(pSearch->m_szLabel); + long offset; + + if (pLabel == NULL) + { + report->error("Unable to find forward reference label '%s' called from PC=%d\n", + pSearch->m_szLabel, pSearch->m_RelativeToPC); + + //m_State = STATE_FAIL; + return FALSE; + } + + offset = pLabel->m_PC - pSearch->m_RelativeToPC; + + if (pSearch->m_FixupSize == 1) + { + if (offset > 127 || offset < -128) + { + report->error("Offset of forward reference label '%s' called from PC=%d is too large for 1 byte pcrel\n", + pLabel->m_szName, pSearch->m_RelativeToPC); + + //m_State = STATE_FAIL; + return FALSE; + } + + *pSearch->m_pBytes = (BYTE) offset; + } + else if (pSearch->m_FixupSize == 4) + { + SET_UNALIGNED_VAL32(pSearch->m_pBytes,offset); + } + } + + return TRUE; +} + + +OPCODE Assembler::DecodeOpcode(const BYTE *pCode, DWORD *pdwLen) +{ + OPCODE opcode; + + *pdwLen = 1; + opcode = OPCODE(pCode[0]); + switch(opcode) { + case CEE_PREFIX1: + opcode = OPCODE(pCode[1] + 256); + if (opcode < 0 || opcode >= CEE_COUNT) + return CEE_COUNT; + *pdwLen = 2; + break; + + case CEE_PREFIXREF: + case CEE_PREFIX2: + case CEE_PREFIX3: + case CEE_PREFIX4: + case CEE_PREFIX5: + case CEE_PREFIX6: + case CEE_PREFIX7: + return CEE_COUNT; + default: + break; + } + return opcode; +} + +char* Assembler::ReflectionNotation(mdToken tk) +{ + char *sz = (char*)&wzUniBuf[dwUniBuf>>1], *pc; + *sz=0; + switch(TypeFromToken(tk)) + { + case mdtTypeDef: + { + Class *pClass = m_lstClass.PEEK(RidFromToken(tk)-1); + if(pClass) + { + strcpy_s(sz,dwUniBuf>>1,pClass->m_szFQN); + pc = sz; + while((pc = strchr(pc,NESTING_SEP)) != NULL) + { + *pc = '+'; + pc++; + } + } + } + break; + + case mdtTypeRef: + { + ULONG N; + mdToken tkResScope; + if(SUCCEEDED(m_pImporter->GetTypeRefProps(tk,&tkResScope,wzUniBuf,dwUniBuf>>1,&N))) + { + WszWideCharToMultiByte(CP_UTF8,0,wzUniBuf,-1,sz,dwUniBuf>>1,NULL,NULL); + if(TypeFromToken(tkResScope)==mdtAssemblyRef) + { + AsmManAssembly *pAsmRef = m_pManifest->m_AsmRefLst.PEEK(RidFromToken(tkResScope)-1); + if(pAsmRef) + { + pc = &sz[strlen(sz)]; + pc+=sprintf_s(pc,(dwUniBuf >> 1),", %s, Version=%d.%d.%d.%d, Culture=",pAsmRef->szName, + pAsmRef->usVerMajor,pAsmRef->usVerMinor,pAsmRef->usBuild,pAsmRef->usRevision); + ULONG L=0; + if(pAsmRef->pLocale && (L=pAsmRef->pLocale->length())) + { + memcpy(wzUniBuf,pAsmRef->pLocale->ptr(),L); + wzUniBuf[L>>1] = 0; + WszWideCharToMultiByte(CP_UTF8,0,wzUniBuf,-1,pc,dwUniBuf>>1,NULL,NULL); + } + else pc+=sprintf_s(pc,(dwUniBuf >> 1),"neutral"); + pc = &sz[strlen(sz)]; + if(pAsmRef->pPublicKeyToken && (L=pAsmRef->pPublicKeyToken->length())) + { + pc+=sprintf_s(pc,(dwUniBuf >> 1),", Publickeytoken="); + BYTE* pb = (BYTE*)(pAsmRef->pPublicKeyToken->ptr()); + for(N=0; N<L; N++,pb++) pc+=sprintf_s(pc,(dwUniBuf >> 1),"%2.2x",*pb); + } + } + } + } + } + break; + + default: + break; + } + return sz; +} + +/* +-------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. +For every delta with one or two bits set, and the deltas of all three + high bits or all three low bits, whether the original value of a,b,c + is almost all zero or is uniformly distributed, +* If mix() is run forward or backward, at least 32 bits in a,b,c + have at least 1/4 probability of changing. +* If mix() is run forward, every bit of c will change between 1/3 and + 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.) +mix() was built out of 36 single-cycle latency instructions in a + structure that could supported 2x parallelism, like so: + a -= b; + a -= c; x = (c>>13); + b -= c; a ^= x; + b -= a; x = (a<<8); + c -= a; b ^= x; + c -= b; x = (b>>13); + ... + Unfortunately, superscalar Pentiums and Sparcs can't take advantage + of that parallelism. They've also turned some of those single-cycle + latency instructions into multi-cycle latency instructions. Still, + this is the fastest good hash I could find. There were about 2^^68 + to choose from. I only looked at a billion or so. +-------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c >> 13); \ + b -= c; b -= a; b ^= (a << 8); \ + c -= a; c -= b; c ^= (b >> 13); \ + a -= b; a -= c; a ^= (c >> 12); \ + b -= c; b -= a; b ^= (a << 16); \ + c -= a; c -= b; c ^= (b >> 5); \ + a -= b; a -= c; a ^= (c >> 3); \ + b -= c; b -= a; b ^= (a << 10); \ + c -= a; c -= b; c ^= (b >> 15); \ +} + +/* +-------------------------------------------------------------------- +hash() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + len : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Every 1-bit and 2-bit delta achieves avalanche. +About 6*len+35 instructions. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (ub1 **)k, do it like this: + for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h); + +By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this +code any way you wish, private, educational, or commercial. It's free. + +See http://burtleburtle.net/bob/hash/evahash.html +Use for hash table lookup, or anything where one collision in 2^^32 is +acceptable. Do NOT use for cryptographic purposes. +-------------------------------------------------------------------- +*/ + +unsigned hash( + __in_ecount(length) const BYTE *k, /* the key */ + unsigned length, /* the length of the key */ + unsigned initval) /* the previous hash, or an arbitrary value */ +{ + register unsigned a,b,c,len; + + /* Set up the internal state */ + len = length; + a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + c = initval; /* the previous hash value */ + + /*---------------------------------------- handle most of the key */ + while (len >= 12) + { + a += (k[0] + ((unsigned)k[1] << 8) + ((unsigned)k[2] << 16) + ((unsigned)k[3] << 24)); + b += (k[4] + ((unsigned)k[5] << 8) + ((unsigned)k[6] << 16) + ((unsigned)k[7] << 24)); + c += (k[8] + ((unsigned)k[9] << 8) + ((unsigned)k[10] << 16) + ((unsigned)k[11] << 24)); + mix(a,b,c); + k += 12; len -= 12; + } + + /*------------------------------------- handle the last 11 bytes */ + c += length; + switch(len) /* all the case statements fall through */ + { + case 11: c+=((unsigned)k[10] << 24); + FALLTHROUGH; + case 10: c+=((unsigned)k[9] << 16); + FALLTHROUGH; + case 9 : c+=((unsigned)k[8] << 8); + FALLTHROUGH; + /* the first byte of c is reserved for the length */ + case 8 : b+=((unsigned)k[7] << 24); + FALLTHROUGH; + case 7 : b+=((unsigned)k[6] << 16); + FALLTHROUGH; + case 6 : b+=((unsigned)k[5] << 8); + FALLTHROUGH; + case 5 : b+=k[4]; + FALLTHROUGH; + case 4 : a+=((unsigned)k[3] << 24); + FALLTHROUGH; + case 3 : a+=((unsigned)k[2] << 16); + FALLTHROUGH; + case 2 : a+=((unsigned)k[1] << 8); + FALLTHROUGH; + case 1 : a+=k[0]; + /* case 0: nothing left to add */ + } + mix(a,b,c); + /*-------------------------------------------- report the result */ + return c; +} + diff --git a/src/coreclr/ilasm/assembler.cpp b/src/coreclr/ilasm/assembler.cpp new file mode 100644 index 00000000000..b9bc13fbaa4 --- /dev/null +++ b/src/coreclr/ilasm/assembler.cpp @@ -0,0 +1,2792 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// File: assembler.cpp +// + +// + +#include "ilasmpch.h" + +#include "assembler.h" +#include "binstr.h" +#include "nvpair.h" + +#define FAIL_UNLESS(x, y) if (!(x)) { report->error y; return; } + +/**************************************************************************/ +void Assembler::StartNameSpace(__in __nullterminated char* name) +{ + m_NSstack.PUSH(m_szNamespace); + m_szNamespace = name; + unsigned L = (unsigned)strlen(m_szFullNS); + unsigned l = (unsigned)strlen(name); + if(L+l+1 >= m_ulFullNSLen) + { + char* pch = new char[((L+l)/MAX_NAMESPACE_LENGTH + 1)*MAX_NAMESPACE_LENGTH]; + if(pch) + { + memcpy(pch,m_szFullNS,L+1); + delete [] m_szFullNS; + m_szFullNS = pch; + m_ulFullNSLen = ((L+l)/MAX_NAMESPACE_LENGTH + 1)*MAX_NAMESPACE_LENGTH; + } + else report->error("Failed to reallocate the NameSpace buffer\n"); + } + if(L) m_szFullNS[L] = NAMESPACE_SEPARATOR_CHAR; + else L = 0xFFFFFFFF; + memcpy(&m_szFullNS[L+1],m_szNamespace, l+1); +} + +/**************************************************************************/ +void Assembler::EndNameSpace() +{ + char *p = &m_szFullNS[strlen(m_szFullNS)-strlen(m_szNamespace)]; + if(p > m_szFullNS) p--; + *p = 0; + delete [] m_szNamespace; + if((m_szNamespace = m_NSstack.POP())==NULL) + { + m_szNamespace = new char[2]; + m_szNamespace[0] = 0; + } +} + +/**************************************************************************/ +void Assembler::ClearImplList(void) +{ + while(m_nImplList) m_crImplList[--m_nImplList] = mdTypeRefNil; +} +/**************************************************************************/ +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow" +#endif +void Assembler::AddToImplList(mdToken tk) +{ + if(m_nImplList+1 >= m_nImplListSize) + { + mdToken *ptr = new mdToken[m_nImplListSize + MAX_INTERFACES_IMPLEMENTED]; + if(ptr == NULL) + { + report->error("Failed to reallocate Impl List from %d to %d bytes\n", + m_nImplListSize*sizeof(mdToken), + (m_nImplListSize+MAX_INTERFACES_IMPLEMENTED)*sizeof(mdToken)); + return; + } + memcpy(ptr,m_crImplList,m_nImplList*sizeof(mdToken)); + delete m_crImplList; + m_crImplList = ptr; + m_nImplListSize += MAX_INTERFACES_IMPLEMENTED; + } + m_crImplList[m_nImplList++] = tk; + m_crImplList[m_nImplList] = mdTypeRefNil; +} +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +void Assembler::ClearBoundList(void) +{ + m_TyParList = NULL; +} +/**************************************************************************/ +mdToken Assembler::ResolveClassRef(mdToken tkResScope, __in __nullterminated const char *pszFullClassName, Class** ppClass) +{ + Class *pClass = NULL; + mdToken tkRet = mdTokenNil; + mdToken *ptkSpecial = NULL; + + if(pszFullClassName == NULL) return mdTokenNil; + + switch(strlen(pszFullClassName)) + { + case 11: + if(strcmp(pszFullClassName,"System.Enum")==0) ptkSpecial = &m_tkSysEnum; + break; + case 13: + if(strcmp(pszFullClassName,"System.Object")==0) ptkSpecial = &m_tkSysObject; + else if(strcmp(pszFullClassName,"System.String")==0) ptkSpecial = &m_tkSysString; + break; + case 16: + if(strcmp(pszFullClassName,"System.ValueType")==0) ptkSpecial = &m_tkSysValue; + break; + } + if(ptkSpecial) // special token + { + if(*ptkSpecial) // already resolved + { + tkRet = *ptkSpecial; + if(ppClass) + { + if(TypeFromToken(tkRet)==mdtTypeDef) + *ppClass = m_lstClass.PEEK(RidFromToken(tkRet)-1); + else *ppClass = NULL; + } + return tkRet; + } + else // needs to be resolved + if(!m_fIsMscorlib) tkResScope = GetBaseAsmRef(); + } + if(tkResScope == 1) + { + if((pClass = FindCreateClass(pszFullClassName)) != NULL) tkRet = pClass->m_cl; + } + else + { + tkRet = MakeTypeRef(tkResScope, pszFullClassName); + pClass = NULL; + } + if(ppClass) *ppClass = pClass; + if(ptkSpecial) *ptkSpecial = tkRet; + return tkRet; +} + +class TypeSpecContainer +{ +private: + // Contain a BinStr + unsigned __int8 *ptr_; + unsigned len_; + // Hash the BinStr, just for speed of lookup + unsigned hash_; + // The value we're looking for + mdToken token_; +public: + // Constructor for a 'lookup' object + TypeSpecContainer(BinStr *typeSpec) : + ptr_(typeSpec->ptr()), + len_(typeSpec->length()), + hash_(typeSpec->length()), + token_(mdTokenNil) + { + for (unsigned i = 0; i < len_; i++) + hash_ = (hash_ * 257) ^ ((i + 1) * (ptr_[i] ^ 0xA5)); + } + // Constructor for a 'permanent' object + // Don't bother re-hashing, since we will always have already constructed the lookup object + TypeSpecContainer(const TypeSpecContainer &t, mdToken tk) : + ptr_(new unsigned __int8[t.len_]), + len_(t.len_), + hash_(t.hash_), + token_(tk) + { + _ASSERT(tk != mdTokenNil); + _ASSERT(t.token_ == mdTokenNil); + memcpy(ptr_, t.ptr_, len_); + } + ~TypeSpecContainer() + { + if (token_ != mdTokenNil) + // delete any memory for a 'permanent' object + delete[] ptr_; + } + // this is the operator for a RBTREE + int ComparedTo(TypeSpecContainer *t) const + { + // If they don't hash the same, just diff the hashes + if (hash_ != t->hash_) + return hash_ - t->hash_; + if (len_ != t->len_) + return len_ - t->len_; + return memcmp(ptr_, t->ptr_, len_); + } + // The only public data we need + mdToken Token() const { return token_; } +}; + +static RBTREE<TypeSpecContainer> typeSpecCache; + +extern FIFO<char> TyParFixupList; + +/**************************************************************************/ +mdToken Assembler::ResolveTypeSpec(BinStr* typeSpec) +{ + mdToken tk; + + // It is safe to use the cache only if there are no pending fixups + if (TyParFixupList.COUNT() != 0) + { + if (FAILED(m_pEmitter->GetTokenFromTypeSpec(typeSpec->ptr(), typeSpec->length(), &tk))) + return mdTokenNil; + return tk; + } + + TypeSpecContainer tsc(typeSpec); + + // GetTokenFromTypeSpec is a linear search through an unsorted list + // Instead of doing that all the time, look this thing up in a cache + TypeSpecContainer *res = typeSpecCache.FIND(&tsc); + if (res != NULL) + { +#ifdef _DEBUG + // Verify that the cache is in sync with the master copy in metadata + PCOR_SIGNATURE pSig; + ULONG cSig; + m_pImporter->GetTypeSpecFromToken(res->Token(),(PCCOR_SIGNATURE*)&pSig,&cSig); + _ASSERTE(typeSpec->length() == cSig); + _ASSERTE(memcmp(typeSpec->ptr(), pSig, cSig) == 0); +#endif + + return res->Token(); + } + + if (FAILED(m_pEmitter->GetTokenFromTypeSpec(typeSpec->ptr(), typeSpec->length(), &tk))) + return mdTokenNil; + + typeSpecCache.PUSH(new TypeSpecContainer(tsc, tk)); + return tk; +} + +/**************************************************************************/ +mdToken Assembler::GetAsmRef(__in __nullterminated const char* szName) +{ + mdToken tkResScope = 0; + if(strcmp(szName,"*")==0) tkResScope = mdTokenNil; + else + { + tkResScope = m_pManifest->GetAsmRefTokByName(szName); + if(RidFromToken(tkResScope)==0) + { + // emit the AssemblyRef + // if it's not self, try to get attributes with Autodetect + unsigned L = (unsigned)strlen(szName)+1; + char *sz = new char[L]; + if(sz) + { + memcpy(sz,szName,L); + AsmManAssembly *pAsmRef = m_pManifest->m_pCurAsmRef; + m_pManifest->StartAssembly(sz,NULL,0,TRUE); + if(RidFromToken(m_pManifest->GetAsmTokByName(szName))==0) + { + report->warn("Reference to undeclared extern assembly '%s'. Attempting autodetect\n",szName); + m_pManifest->SetAssemblyAutodetect(); + } + m_pManifest->EndAssembly(); + tkResScope = m_pManifest->GetAsmRefTokByName(szName); + m_pManifest->m_pCurAsmRef = pAsmRef; + } + else + report->error("\nOut of memory!\n"); + } + } + return tkResScope; +} + +mdToken Assembler::GetBaseAsmRef() +{ + // First we check for "System.Private.CoreLib" as the base or System assembly + // + AsmManAssembly* coreLibAsm = m_pManifest->GetAsmRefByAsmName("System.Private.CoreLib"); + if(coreLibAsm != NULL) + { + return GetAsmRef(coreLibAsm->szAlias ? coreLibAsm->szAlias : coreLibAsm->szName); + } + + AsmManAssembly* sysRuntime = m_pManifest->GetAsmRefByAsmName("System.Runtime"); + if(sysRuntime != NULL) + { + return GetAsmRef(sysRuntime->szAlias ? sysRuntime->szAlias : sysRuntime->szName); + } + + AsmManAssembly* mscorlibAsm = m_pManifest->GetAsmRefByAsmName("mscorlib"); + if(mscorlibAsm != NULL) + { + return GetAsmRef(mscorlibAsm->szAlias ? mscorlibAsm->szAlias : mscorlibAsm->szName); + } + + AsmManAssembly* netstandardAsm = m_pManifest->GetAsmRefByAsmName("netstandard"); + if (netstandardAsm != NULL) + { + return GetAsmRef(netstandardAsm->szAlias ? netstandardAsm->szAlias : netstandardAsm->szName); + } + + return GetAsmRef("mscorlib"); +} + +mdToken Assembler::GetInterfaceImpl(mdToken tsClass, mdToken tsInterface) +{ + mdToken result = mdTokenNil; + HCORENUM iiEnum = 0; + ULONG actualInterfaces; + mdInterfaceImpl impls; + + while (SUCCEEDED(m_pImporter->EnumInterfaceImpls(&iiEnum, tsClass, &impls, 1, &actualInterfaces))) + { + if (actualInterfaces == 1) + { + mdToken classToken, interfaceToken; + if (FAILED(m_pImporter->GetInterfaceImplProps(impls, &classToken, &interfaceToken))) + break; + if (classToken == tsClass && interfaceToken == tsInterface) + { + result = impls; + break; + } + } + } + m_pImporter->CloseEnum(iiEnum); + return result; +} + +/**************************************************************************/ +mdToken Assembler::GetModRef(__in __nullterminated char* szName) +{ + mdToken tkResScope = 0; + if(!strcmp(szName,m_szScopeName)) + tkResScope = 1; // scope is "this module" + else + { + ImportDescriptor* pID; + int i = 0; + tkResScope = mdModuleRefNil; + DWORD L = (DWORD)strlen(szName); + while((pID=m_ImportList.PEEK(i++))) + { + if(pID->dwDllName != L) continue; + if((L > 0) && (strcmp(pID->szDllName,szName)!=0)) continue; + tkResScope = pID->mrDll; + break; + } + if(RidFromToken(tkResScope)==0) + report->error("Undefined module ref '%s'\n",szName); + } + return tkResScope; +} +/**************************************************************************/ +mdToken Assembler::MakeTypeRef(mdToken tkResScope, LPCUTF8 pszFullClassName) +{ + mdToken tkRet = mdTokenNil; + if(pszFullClassName && *pszFullClassName) + { + LPCUTF8 pc; + if((pc = strrchr(pszFullClassName,NESTING_SEP))) // scope: enclosing class + { + LPUTF8 szScopeName; + DWORD L = (DWORD)(pc-pszFullClassName); + if((szScopeName = new char[L+1]) != NULL) + { + memcpy(szScopeName,pszFullClassName,L); + szScopeName[L] = 0; + tkResScope = MakeTypeRef(tkResScope,szScopeName); + delete [] szScopeName; + } + else + report->error("\nOut of memory!\n"); + pc++; + } + else pc = pszFullClassName; + if(*pc) + { + // convert name to widechar + WszMultiByteToWideChar(g_uCodePage,0,pc,-1,wzUniBuf,dwUniBuf); + if(FAILED(m_pEmitter->DefineTypeRefByName(tkResScope, wzUniBuf, &tkRet))) tkRet = mdTokenNil; + } + } + return tkRet; +} +/**************************************************************************/ + +DWORD Assembler::CheckClassFlagsIfNested(Class* pEncloser, DWORD attr) +{ + DWORD wasAttr = attr; + if(pEncloser && (!IsTdNested(attr))) + { + if(OnErrGo) + report->error("Nested class has non-nested visibility (0x%08X)\n",attr); + else + { + attr &= ~tdVisibilityMask; + attr |= (IsTdPublic(wasAttr) ? tdNestedPublic : tdNestedPrivate); + report->warn("Nested class has non-nested visibility (0x%08X), changed to nested (0x%08X)\n",wasAttr,attr); + } + } + else if((pEncloser==NULL) && IsTdNested(attr)) + { + if(OnErrGo) + report->error("Non-nested class has nested visibility (0x%08X)\n",attr); + else + { + attr &= ~tdVisibilityMask; + attr |= (IsTdNestedPublic(wasAttr) ? tdPublic : tdNotPublic); + report->warn("Non-nested class has nested visibility (0x%08X), changed to non-nested (0x%08X)\n",wasAttr,attr); + } + } + return attr; +} + +/**************************************************************************/ + +void Assembler::StartClass(__in __nullterminated char* name, DWORD attr, TyParList *typars) +{ + Class *pEnclosingClass = m_pCurClass; + char *szFQN; + ULONG LL; + + m_TyParList = typars; + + if (m_pCurMethod != NULL) + { + report->error("Class cannot be declared within a method scope\n"); + } + if(pEnclosingClass) + { + LL = pEnclosingClass->m_dwFQN+(ULONG)strlen(name)+2; + if((szFQN = new char[LL])) + sprintf_s(szFQN,LL,"%s%c%s",pEnclosingClass->m_szFQN,NESTING_SEP,name); + else + report->error("\nOut of memory!\n"); + } + else + { + unsigned L = (unsigned)strlen(m_szFullNS); + unsigned LLL = (unsigned)strlen(name); + LL = L + LLL + (L ? 2 : 1); + if((szFQN = new char[LL])) + { + if(L) sprintf_s(szFQN,LL,"%s.%s",m_szFullNS,name); + else memcpy(szFQN,name,LL); + if(LL > MAX_CLASSNAME_LENGTH) + { + report->error("Full class name too long (%d characters, %d allowed).\n",LL-1,MAX_CLASSNAME_LENGTH-1); + } + } + else + report->error("\nOut of memory!\n"); + } + if(szFQN == NULL) return; + + mdToken tkThis; + if(m_fIsMscorlib) + tkThis = ResolveClassRef(1,szFQN,&m_pCurClass); // boils down to FindCreateClass(szFQN) + else + { + m_pCurClass = FindCreateClass(szFQN); + tkThis = m_pCurClass->m_cl; + } + if(m_pCurClass->m_bIsMaster) + { + m_pCurClass->m_Attr = CheckClassFlagsIfNested(pEnclosingClass, attr); + + if (m_TyParList) + { + m_pCurClass->m_NumTyPars = m_TyParList->ToArray(&(m_pCurClass->m_TyPars)); + delete m_TyParList; + m_TyParList = NULL; + RecordTypeConstraints(&m_pCurClass->m_GPCList, m_pCurClass->m_NumTyPars, m_pCurClass->m_TyPars); + } + else m_pCurClass->m_NumTyPars = 0; + m_pCurClass->m_pEncloser = pEnclosingClass; + } // end if(old class) else + m_tkCurrentCVOwner = 0; + m_CustomDescrListStack.PUSH(m_pCustomDescrList); + m_pCustomDescrList = &(m_pCurClass->m_CustDList); + + m_ClassStack.PUSH(pEnclosingClass); + ClearBoundList(); +} + +/**************************************************************************/ + +void Assembler::AddClass() +{ + mdTypeRef crExtends = mdTypeRefNil; + BOOL bIsEnum = FALSE; + BOOL bIsValueType = FALSE; + + if(m_pCurClass->m_bIsMaster) + { + DWORD attr = m_pCurClass->m_Attr; + if(!IsNilToken(m_crExtends)) + { + // has a superclass + if(IsTdInterface(attr)) report->error("Base class in interface\n"); + bIsValueType = (m_crExtends == m_tkSysValue)&&(m_pCurClass->m_cl != m_tkSysEnum); + bIsEnum = (m_crExtends == m_tkSysEnum); + crExtends = m_crExtends; + } + else + { + bIsEnum = ((attr & 0x40000000) != 0); + bIsValueType = ((attr & 0x80000000) != 0); + } + attr &= 0x3FFFFFFF; + if (m_fAutoInheritFromObject && (crExtends == mdTypeRefNil) && (!IsTdInterface(attr))) + { + mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetBaseAsmRef(); + crExtends = bIsEnum ? + ResolveClassRef(tkMscorlib,"System.Enum",NULL) + :( bIsValueType ? + ResolveClassRef(tkMscorlib,"System.ValueType",NULL) + : ResolveClassRef(tkMscorlib, "System.Object",NULL)); + } + m_pCurClass->m_Attr = attr; + m_pCurClass->m_crExtends = (m_pCurClass->m_cl == m_tkSysObject)? mdTypeRefNil : crExtends; + + if ((m_pCurClass->m_dwNumInterfaces = m_nImplList) != NULL) + { + if(bIsEnum) report->error("Enum implementing interface(s)\n"); + if((m_pCurClass->m_crImplements = new mdTypeRef[m_nImplList+1]) != NULL) + memcpy(m_pCurClass->m_crImplements, m_crImplList, (m_nImplList+1)*sizeof(mdTypeRef)); + else + { + report->error("Failed to allocate Impl List for class '%s'\n", m_pCurClass->m_szFQN); + m_pCurClass->m_dwNumInterfaces = 0; + } + } + else m_pCurClass->m_crImplements = NULL; + if(bIsValueType) + { + if(!IsTdSealed(attr)) + { + if(OnErrGo) report->error("Non-sealed value class\n"); + else + { + report->warn("Non-sealed value class, made sealed\n"); + m_pCurClass->m_Attr |= tdSealed; + } + } + } + m_pCurClass->m_bIsMaster = FALSE; + } // end if(old class) else + ClearImplList(); + m_crExtends = mdTypeRefNil; +} + +/**************************************************************************/ +void Assembler::EndClass() +{ + m_pCurClass = m_ClassStack.POP(); + m_tkCurrentCVOwner = 0; + m_pCustomDescrList = m_CustomDescrListStack.POP(); +} + +/**************************************************************************/ +void Assembler::SetPinvoke(BinStr* DllName, int Ordinal, BinStr* Alias, int Attrs) +{ + if(m_pPInvoke) delete m_pPInvoke; + if(DllName->length()) + { + if((m_pPInvoke = new PInvokeDescriptor)) + { + unsigned l; + ImportDescriptor* pID; + if((pID = EmitImport(DllName))) + { + m_pPInvoke->mrDll = pID->mrDll; + m_pPInvoke->szAlias = NULL; + if(Alias) + { + l = Alias->length(); + if((m_pPInvoke->szAlias = new char[l+1])) + { + memcpy(m_pPInvoke->szAlias,Alias->ptr(),l); + m_pPInvoke->szAlias[l] = 0; + } + else report->error("\nOut of memory!\n"); + } + m_pPInvoke->dwAttrs = (DWORD)Attrs; + } + else + { + delete m_pPInvoke; + m_pPInvoke = NULL; + report->error("PInvoke refers to undefined imported DLL\n"); + } + } + else + report->error("Failed to allocate PInvokeDescriptor\n"); + } + else + { + m_pPInvoke = NULL; // No DLL name, it's "local" (IJW) PInvoke + report->error("Local (embedded native) PInvoke method, the resulting PE file is unusable\n"); + } + if(DllName) delete DllName; + if(Alias) delete Alias; +} + +/**************************************************************************/ +void Assembler::StartMethod(__in __nullterminated char* name, BinStr* sig, CorMethodAttr flags, BinStr* retMarshal, DWORD retAttr, TyParList *typars) +{ + if (m_pCurMethod != NULL) + { + report->error("Cannot declare a method '%s' within another method\n",name); + } + if (!m_fInitialisedMetaData) + { + if (FAILED(InitMetaData())) // impl. see WRITER.CPP + { + _ASSERTE(0); + } + } + size_t namelen = strlen(name); + if(namelen >= MAX_CLASSNAME_LENGTH) + { + char c = name[MAX_CLASSNAME_LENGTH-1]; + name[MAX_CLASSNAME_LENGTH-1] = 0; + report->error("Method '%s...' -- name too long (%d characters).\n",name,namelen); + name[MAX_CLASSNAME_LENGTH-1] = c; + } + if (!(flags & mdStatic)) + *(sig->ptr()) |= IMAGE_CEE_CS_CALLCONV_HASTHIS; + else if(*(sig->ptr()) & (IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)) + { + if(OnErrGo) report->error("Method '%s' -- both static and instance\n", name); + else + { + report->warn("Method '%s' -- both static and instance, set to static\n", name); + *(sig->ptr()) &= ~(IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); + } + } + + if(!IsMdPrivateScope(flags)) + { + Method* pMethod; + Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass); + DWORD L = (DWORD)strlen(name); + for(int j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++) + { + if( (pMethod->m_dwName == L) && + (!strcmp(pMethod->m_szName,name)) && + (pMethod->m_dwMethodCSig == sig->length()) && + (!memcmp(pMethod->m_pMethodSig,sig->ptr(),sig->length())) + &&(!IsMdPrivateScope(pMethod->m_Attr))) + { + if(m_fTolerateDupMethods) + { + // reset for new body + pMethod->m_lstFixup.RESET(true); + //pMethod->m_lstLabel.RESET(true); + m_lstLabel.RESET(true); + pMethod->m_Locals.RESET(true); + delArgNameList(pMethod->m_firstArgName); + delArgNameList(pMethod->m_firstVarName); + pMethod->m_pCurrScope = &(pMethod->m_MainScope); + pMethod->m_pCurrScope->Reset(); + pMethod->m_firstArgName = getArgNameList(); + pMethod->m_dwNumExceptions = 0; + pMethod->m_dwNumEndfilters = 0; + if(pMethod->m_pRetMarshal) delete pMethod->m_pRetMarshal; + if(pMethod->m_pRetValue) delete pMethod->m_pRetValue; + + pMethod->m_MethodImplDList.RESET(false); // ptrs in m_MethodImplDList are dups of those in Assembler + + pMethod->m_CustomDescrList.RESET(true); + + if(pMethod->m_fEntryPoint) + { + pMethod->m_fEntryPoint = FALSE; + m_fEntryPointPresent = FALSE; + } + + if(pMethod->m_pbsBody) + { + // no need to remove relevant MemberRef Fixups from the Assembler list: + // their m_fNew flag is set to FALSE anyway. + // Just get rid of old method body + delete pMethod->m_pbsBody; + pMethod->m_pbsBody = NULL; + } + + pMethod->m_fNewBody = TRUE; + m_pCurMethod = pMethod; + } + else + report->error("Duplicate method declaration\n"); + break; + } + } + } + if(m_pCurMethod == NULL) + { + if(m_pCurClass) + { // instance method + if(IsMdAbstract(flags) && !IsTdAbstract(m_pCurClass->m_Attr)) + { + report->error("Abstract method '%s' in non-abstract class '%s'\n",name,m_pCurClass->m_szFQN); + } + if(m_pCurClass->m_crExtends == m_tkSysEnum) report->error("Method in enum\n"); + + if(!strcmp(name,COR_CTOR_METHOD_NAME)) + { + flags = (CorMethodAttr)(flags | mdSpecialName); + if(IsTdInterface(m_pCurClass->m_Attr)) report->error("Instance constructor in interface\n"); + } + m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags); + } + else + { + if(IsMdAbstract(flags)) + { + if(OnErrGo) report->error("Global method '%s' can't be abstract\n",name); + else + { + report->warn("Global method '%s' can't be abstract, flag removed\n",name); + flags = (CorMethodAttr)(((int) flags) &~mdAbstract); + } + } + if(!IsMdStatic(flags)) + { + if(OnErrGo) report->error("Non-static global method '%s'\n",name); + else + { + report->warn("Non-static global method '%s', made static\n",name); + flags = (CorMethodAttr)(flags | mdStatic); + *((BYTE*)(sig->ptr())) &= ~(IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); + } + } + m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags); + if (m_pCurMethod) + { + m_pCurMethod->SetIsGlobalMethod(); + if (m_fInitialisedMetaData == FALSE) InitMetaData(); + } + } + if(m_pCurMethod) + { + if(!OnErrGo) + { + if(m_pCurMethod->m_firstArgName) + { + for(ARG_NAME_LIST *pAN=m_pCurMethod->m_firstArgName; pAN; pAN = pAN->pNext) + { + if(pAN->dwName) + { + int k = m_pCurMethod->findArgNum(pAN->pNext,pAN->szName,pAN->dwName); + if(k >= 0) + report->warn("Duplicate param name '%s' in method '%s'\n",pAN->szName,name); + } + } + } + } + m_pCurMethod->m_pRetMarshal = retMarshal; + m_pCurMethod->m_dwRetAttr = retAttr; + m_tkCurrentCVOwner = 0; + m_CustomDescrListStack.PUSH(m_pCustomDescrList); + m_pCustomDescrList = &(m_pCurMethod->m_CustomDescrList); + m_pCurMethod->m_MainScope.dwStart = m_CurPC; + if (typars) + { + m_pCurMethod->m_NumTyPars = typars->ToArray(&(m_pCurMethod->m_TyPars)); + delete typars; + m_TyParList = NULL; + RecordTypeConstraints(&m_pCurMethod->m_GPCList, m_pCurMethod->m_NumTyPars, m_pCurMethod->m_TyPars); + } + else m_pCurMethod->m_NumTyPars = 0; + } + else report->error("Failed to allocate Method class\n"); + } // end if new method +} + +/**************************************************************************/ +void Assembler::EndMethod() +{ + + if(m_pCurMethod->m_pCurrScope != &(m_pCurMethod->m_MainScope)) + { + report->error("Invalid lexical scope structure in method %s\n",m_pCurMethod->m_szName); + } + m_pCurMethod->m_pCurrScope->dwEnd = m_CurPC; + if (DoFixups(m_pCurMethod)) AddMethod(m_pCurMethod); //AddMethod - see ASSEM.CPP + else + { + report->error("Method '%s' compilation failed.\n",m_pCurMethod->m_szName); + } + //m_pCurMethod->m_lstLabel.RESET(true); + m_lstLabel.RESET(true); + m_tkCurrentCVOwner = 0; + m_pCustomDescrList = m_CustomDescrListStack.POP(); + ResetForNextMethod(); // see ASSEM.CPP +} +/**************************************************************************/ +/* rvaLabel is the optional label that indicates this field points at a particular RVA */ +void Assembler::AddField(__inout_z __inout char* name, BinStr* sig, CorFieldAttr flags, __in __nullterminated char* rvaLabel, BinStr* pVal, ULONG ulOffset) +{ + FieldDescriptor* pFD; + ULONG i,n; + mdToken tkParent = mdTokenNil; + Class* pClass; + + if (m_pCurMethod) + report->error("Field cannot be declared within a method\n"); + + if(strlen(name) >= MAX_CLASSNAME_LENGTH) + { + char c = name[MAX_CLASSNAME_LENGTH-1]; + name[MAX_CLASSNAME_LENGTH-1] = 0; + report->error("Field '%s...' -- name too long (%d characters).\n",name,strlen(name)); + name[MAX_CLASSNAME_LENGTH-1] = c; + } + + if(sig && (sig->length() >= 2)) + { + if(sig->ptr()[1] == ELEMENT_TYPE_VOID) + report->error("Illegal use of type 'void'\n"); + } + + if (m_pCurClass) + { + tkParent = m_pCurClass->m_cl; + + if(IsTdInterface(m_pCurClass->m_Attr)) + { + if(!IsFdStatic(flags)) + { + report->warn("Instance field in interface (CLS violation)\n"); + if(!IsFdPublic(flags)) report->error("Non-public instance field in interface\n"); + } + } + } + else + { + if(ulOffset != 0xFFFFFFFF) + { + report->warn("Offset in global field '%s' is ignored\n",name); + ulOffset = 0xFFFFFFFF; + } + if(!IsFdStatic(flags)) + { + if(OnErrGo) report->error("Non-static global field\n"); + else + { + report->warn("Non-static global field, made static\n"); + flags = (CorFieldAttr)(flags | fdStatic); + } + } + } + pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass); + n = pClass->m_FieldDList.COUNT(); + DWORD L = (DWORD)strlen(name); + for(i = 0; i < n; i++) + { + pFD = pClass->m_FieldDList.PEEK(i); + if((pFD->m_tdClass == tkParent)&&(L==pFD->m_dwName)&&(!strcmp(pFD->m_szName,name)) + &&(pFD->m_pbsSig->length() == sig->length()) + &&(memcmp(pFD->m_pbsSig->ptr(),sig->ptr(),sig->length())==0)) + { + report->error("Duplicate field declaration: '%s'\n",name); + break; + } + } + if (rvaLabel && !IsFdStatic(flags)) + report->error("Only static fields can have 'at' clauses\n"); + + if(i >= n) + { + if((pFD = new FieldDescriptor)) + { + pFD->m_tdClass = tkParent; + pFD->m_szName = name; + pFD->m_dwName = L; + pFD->m_fdFieldTok = mdTokenNil; + if((pFD->m_ulOffset = ulOffset) != 0xFFFFFFFF) pClass->m_dwNumFieldsWithOffset++; + pFD->m_rvaLabel = rvaLabel; + pFD->m_pbsSig = sig; + pFD->m_pClass = pClass; + pFD->m_pbsValue = pVal; + pFD->m_pbsMarshal = m_pMarshal; + pFD->m_pPInvoke = m_pPInvoke; + pFD->m_dwAttr = flags; + + m_tkCurrentCVOwner = 0; + m_pCustomDescrList = &(pFD->m_CustomDescrList); + + pClass->m_FieldDList.PUSH(pFD); + pClass->m_fNewMembers = TRUE; + } + else + report->error("Failed to allocate Field Descriptor\n"); + } + else + { + if(pVal) delete pVal; + if(m_pPInvoke) delete m_pPInvoke; + if(m_pMarshal) delete m_pMarshal; + delete name; + } + m_pPInvoke = NULL; + m_pMarshal = NULL; +} + +BOOL Assembler::EmitField(FieldDescriptor* pFD) +{ + WCHAR* wzFieldName=&wzUniBuf[0]; + HRESULT hr; + DWORD cSig; + COR_SIGNATURE* mySig; + mdFieldDef mb; + BYTE ValType = ELEMENT_TYPE_VOID; + void * pValue = NULL; + unsigned lVal = 0; + BOOL ret = TRUE; + + cSig = pFD->m_pbsSig->length(); + mySig = (COR_SIGNATURE*)(pFD->m_pbsSig->ptr()); + + WszMultiByteToWideChar(g_uCodePage,0,pFD->m_szName,-1,wzFieldName,dwUniBuf); //int)cFieldNameLength); + if(IsFdPrivateScope(pFD->m_dwAttr)) + { + WCHAR* p = wcsstr(wzFieldName,W("$PST04")); + if(p) *p = 0; + } + + if(pFD->m_pbsValue && pFD->m_pbsValue->length()) + { + ValType = *(pFD->m_pbsValue->ptr()); + lVal = pFD->m_pbsValue->length() - 1; // 1 is type byte + pValue = (void*)(pFD->m_pbsValue->ptr() + 1); + if(ValType == ELEMENT_TYPE_STRING) + { + //while(lVal % sizeof(WCHAR)) { pFD->m_pbsValue->appendInt8(0); lVal++; } + lVal /= sizeof(WCHAR); + +#if defined(ALIGN_ACCESS) || BIGENDIAN + void* pValueTemp = _alloca(lVal * sizeof(WCHAR)); + memcpy(pValueTemp, pValue, lVal * sizeof(WCHAR)); + pValue = pValueTemp; + + SwapStringLength((WCHAR*)pValue, lVal); +#endif + } + } + + hr = m_pEmitter->DefineField( + pFD->m_tdClass, + wzFieldName, + pFD->m_dwAttr, + mySig, + cSig, + ValType, + pValue, + lVal, + &mb + ); + if (FAILED(hr)) + { + report->error("Failed to define field '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr); + ret = FALSE; + } + else + { + //-------------------------------------------------------------------------------- + if(IsFdPinvokeImpl(pFD->m_dwAttr)&&(pFD->m_pPInvoke)) + { + if(pFD->m_pPInvoke->szAlias == NULL) pFD->m_pPInvoke->szAlias = pFD->m_szName; + if(FAILED(EmitPinvokeMap(mb,pFD->m_pPInvoke))) + { + report->error("Failed to define PInvoke map of .field '%s'\n",pFD->m_szName); + ret = FALSE; + } + } + //-------------------------------------------------------------------------- + if(pFD->m_pbsMarshal) + { + if(FAILED(hr = m_pEmitter->SetFieldMarshal ( + mb, // [IN] given a fieldDef or paramDef token + (PCCOR_SIGNATURE)(pFD->m_pbsMarshal->ptr()), // [IN] native type specification + pFD->m_pbsMarshal->length()))) // [IN] count of bytes of pvNativeType + { + report->error("Failed to set field marshaling for '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr); + ret = FALSE; + } + } + //-------------------------------------------------------------------------------- + // Set the the RVA to a dummy value. later it will be fixed + // up to be something correct, but if we don't emit something + // the size of the meta-data will not be correct + if (pFD->m_rvaLabel) + { + m_fHaveFieldsWithRvas = TRUE; + hr = m_pEmitter->SetFieldRVA(mb, 0xCCCCCCCC); + if (FAILED(hr)) + { + report->error("Failed to set RVA for field '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr); + ret = FALSE; + } + } + //-------------------------------------------------------------------------------- + EmitCustomAttributes(mb, &(pFD->m_CustomDescrList)); + + } + pFD->m_fdFieldTok = mb; + return ret; +} + +/**************************************************************************/ +void Assembler::EmitByte(int val) +{ + char ch = (char)val; + //if((val < -128)||(val > 127)) + // report->warn("Emitting 0x%X as a byte: data truncated to 0x%X\n",(unsigned)val,(BYTE)ch); + EmitBytes((BYTE *)&ch,1); +} + +/**************************************************************************/ +void Assembler::NewSEHDescriptor(void) //sets m_SEHD +{ + m_SEHDstack.PUSH(m_SEHD); + m_SEHD = new SEH_Descriptor; + if(m_SEHD == NULL) report->error("Failed to allocate SEH descriptor\n"); +} +/**************************************************************************/ +void Assembler::SetTryLabels(__in __nullterminated char * szFrom, __in __nullterminated char *szTo) +{ + if(!m_SEHD) return; + Label *pLbl = m_pCurMethod->FindLabel(szFrom); + if(pLbl) + { + m_SEHD->tryFrom = pLbl->m_PC; + if((pLbl = m_pCurMethod->FindLabel(szTo))) m_SEHD->tryTo = pLbl->m_PC; //FindLabel: Method.CPP + else report->error("Undefined 2nd label in 'try <label> to <label>'\n"); + } + else report->error("Undefined 1st label in 'try <label> to <label>'\n"); +} +/**************************************************************************/ +void Assembler::SetFilterLabel(__in __nullterminated char *szFilter) +{ + if(!m_SEHD) return; + Label *pLbl = m_pCurMethod->FindLabel(szFilter); + if(pLbl) m_SEHD->sehFilter = pLbl->m_PC; + else report->error("Undefined label in 'filter <label>'\n"); +} +/**************************************************************************/ +void Assembler::SetCatchClass(mdToken catchClass) +{ + if(!m_SEHD) return; + m_SEHD->cException = catchClass; + +} +/**************************************************************************/ +void Assembler::SetHandlerLabels(__in __nullterminated char *szHandlerFrom, __in __nullterminated char *szHandlerTo) +{ + if(!m_SEHD) return; + Label *pLbl = m_pCurMethod->FindLabel(szHandlerFrom); + if(pLbl) + { + m_SEHD->sehHandler = pLbl->m_PC; + if(szHandlerTo) + { + pLbl = m_pCurMethod->FindLabel(szHandlerTo); + if(pLbl) + { + m_SEHD->sehHandlerTo = pLbl->m_PC; + return; + } + } + else + { + m_SEHD->sehHandlerTo = m_SEHD->sehHandler - 1; + return; + } + } + report->error("Undefined label in 'handler <label> to <label>'\n"); +} +/**************************************************************************/ +void Assembler::EmitTry(void) //enum CorExceptionFlag kind, char* beginLabel, char* endLabel, char* handleLabel, char* filterOrClass) +{ + if(m_SEHD) + { + bool isFilter=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FILTER), + isFault=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FAULT), + isFinally=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FINALLY); + + AddException(m_SEHD->tryFrom, m_SEHD->tryTo, m_SEHD->sehHandler, m_SEHD->sehHandlerTo, + m_SEHD->cException, isFilter, isFault, isFinally); + } + else report->error("Attempt to EmitTry with NULL SEH descriptor\n"); +} +/**************************************************************************/ + +void Assembler::AddException(DWORD pcStart, DWORD pcEnd, DWORD pcHandler, DWORD pcHandlerTo, mdTypeRef crException, BOOL isFilter, BOOL isFault, BOOL isFinally) +{ + if (m_pCurMethod == NULL) + { + report->error("Exceptions can be declared only when in a method scope\n"); + return; + } + + if (m_pCurMethod->m_dwNumExceptions >= m_pCurMethod->m_dwMaxNumExceptions) + { + COR_ILMETHOD_SECT_EH_CLAUSE_FAT *ptr = + new COR_ILMETHOD_SECT_EH_CLAUSE_FAT[m_pCurMethod->m_dwMaxNumExceptions+MAX_EXCEPTIONS]; + if(ptr == NULL) + { + report->error("Failed to reallocate SEH buffer\n"); + return; + } + memcpy(ptr,m_pCurMethod->m_ExceptionList,m_pCurMethod->m_dwNumExceptions*sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT)); + delete [] m_pCurMethod->m_ExceptionList; + m_pCurMethod->m_ExceptionList = ptr; + m_pCurMethod->m_dwMaxNumExceptions += MAX_EXCEPTIONS; + } + + COR_ILMETHOD_SECT_EH_CLAUSE_FAT *clause = &m_pCurMethod->m_ExceptionList[m_pCurMethod->m_dwNumExceptions]; + clause->SetTryOffset(pcStart); + clause->SetTryLength(pcEnd - pcStart); + clause->SetHandlerOffset(pcHandler); + clause->SetHandlerLength(pcHandlerTo - pcHandler); + clause->SetClassToken(crException); + + int flags = COR_ILEXCEPTION_CLAUSE_OFFSETLEN; + if (isFilter) { + flags |= COR_ILEXCEPTION_CLAUSE_FILTER; + } + if (isFault) { + flags |= COR_ILEXCEPTION_CLAUSE_FAULT; + } + if (isFinally) { + flags |= COR_ILEXCEPTION_CLAUSE_FINALLY; + } + clause->SetFlags((CorExceptionFlag)flags); + + m_pCurMethod->m_dwNumExceptions++; +} + +/**************************************************************************/ +void Assembler::EmitMaxStack(unsigned val) +{ + if(val > 0xFFFF) report->warn(".maxstack parameter exceeds 65535, truncated to %d\n",val&0xFFFF); + if (m_pCurMethod) m_pCurMethod->m_MaxStack = val&0xFFFF; + else report->error(".maxstack can be used only within a method scope\n"); +} + +/**************************************************************************/ +void Assembler::EmitLocals(BinStr* sig) +{ + if(sig) + { + if (m_pCurMethod) + { + ARG_NAME_LIST *pAN, *pList= getArgNameList(); + if(pList) + { + VarDescr* pVD; + for(pAN=pList; pAN; pAN = pAN->pNext) + { + if(pAN->dwAttr == 0) pAN->dwAttr = m_pCurMethod->m_Locals.COUNT() +1; + (pAN->dwAttr)--; + if((pVD = m_pCurMethod->m_Locals.PEEK(pAN->dwAttr))) + { + if(pVD->bInScope) + { + report->warn("Local var slot %d is in use\n",pAN->dwAttr); + } + if(pVD->pbsSig && ((pVD->pbsSig->length() != pAN->pSig->length()) || + (memcmp(pVD->pbsSig->ptr(),pAN->pSig->ptr(),pVD->pbsSig->length())))) + { + report->error("Local var slot %d: type conflict\n",pAN->dwAttr); + } + } + else + { // create new entry: + for(unsigned n = m_pCurMethod->m_Locals.COUNT(); n <= pAN->dwAttr; n++) + { + pVD = new VarDescr; + if(pVD != NULL) m_pCurMethod->m_Locals.PUSH(pVD); + else + { + report->error("Out of memory allocating local var descriptor\n"); + delete sig; + return; + } + } + } + pVD->dwSlot = pAN->dwAttr; + pVD->pbsSig = pAN->pSig; + pVD->bInScope = TRUE; + } + if(pVD->pbsSig && (pVD->pbsSig->length() == 1)) + { + if(pVD->pbsSig->ptr()[0] == ELEMENT_TYPE_VOID) + report->error("Illegal local var type: 'void'\n"); + } + m_pCurMethod->m_pCurrScope->pLocals = + m_pCurMethod->catArgNameList(m_pCurMethod->m_pCurrScope->pLocals, pList); + } + } + else report->error(".locals can be used only within a method scope\n"); + delete sig; + } + else report->error("Attempt to EmitLocals with NULL argument\n"); +} + +/**************************************************************************/ +void Assembler::EmitEntryPoint() +{ + if (m_pCurMethod) + { + if(!m_fEntryPointPresent) + { + if(IsMdStatic(m_pCurMethod->m_Attr)) + { + m_pCurMethod->m_fEntryPoint = TRUE; + m_fEntryPointPresent = TRUE; + } + else report->error("Non-static method as entry point\n"); + } + else report->error("Multiple .entrypoint declarations\n"); + } + else report->error(".entrypoint can be used only within a method scope\n"); +} + +/**************************************************************************/ +void Assembler::EmitZeroInit() +{ + if (m_pCurMethod) m_pCurMethod->m_Flags |= CorILMethod_InitLocals; + else report->error(".zeroinit can be used only within a method scope\n"); +} + +/**************************************************************************/ +void Assembler::SetImplAttr(unsigned short attrval) +{ + if (m_pCurMethod) + { + if(IsMiNative(attrval)||IsMiOPTIL(attrval)||IsMiUnmanaged(attrval)) + report->error("Cannot compile native/unmanaged method\n"); + m_pCurMethod->m_wImplAttr = attrval; + } +} + +/**************************************************************************/ +void Assembler::EmitData(__in_opt void *buffer, unsigned len) +{ + if (len != 0) + { + void* ptr; + HRESULT hr = m_pCeeFileGen->GetSectionBlock(m_pCurSection, len, 1, &ptr); + if (FAILED(hr)) + { + report->error("Could not extend data section (out of memory?)"); + exit(1); + } + + if (buffer != NULL) + { + memcpy(ptr, buffer, len); + } + else + { + memset(ptr, 0, len); + } + } +} + +/**************************************************************************/ +void Assembler::EmitDD(__in __nullterminated char *str) +{ + DWORD dwAddr = 0; + GlobalLabel *pLabel = FindGlobalLabel(str); + + ULONG loc; + HRESULT hr = m_pCeeFileGen->GetSectionDataLen(m_pCurSection, &loc); + _ASSERTE(SUCCEEDED(hr)); + + DWORD* ptr; + DWORD sizeofptr = (DWORD)((m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) ? sizeof(DWORD) : sizeof(__int64)); + hr = m_pCeeFileGen->GetSectionBlock(m_pCurSection, sizeofptr, 1, (void**) &ptr); + if (FAILED(hr)) + { + report->error("Could not extend data section (out of memory?)"); + exit(1); + } + + if (pLabel != 0) { + dwAddr = pLabel->m_GlobalOffset; + if (pLabel->m_Section != m_pGlobalDataSection) { + report->error("For '&label', label must be in data section"); + m_State = STATE_FAIL; + } + } + else + AddDeferredGlobalFixup(str, (BYTE*) ptr); + + hr = m_pCeeFileGen->AddSectionReloc(m_pCurSection, loc, m_pGlobalDataSection, srRelocHighLow); + _ASSERTE(SUCCEEDED(hr)); + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS) + { + report->error("Base relocations are emitted, while /STRIPRELOC option has been specified"); + } + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) + { + m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY; + if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386) + COR_SET_32BIT_REQUIRED(m_dwComImageFlags); + *ptr = dwAddr; + } + else + { + m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY; + *((__int64*)ptr) = (__int64)dwAddr; + } +} + +/**************************************************************************/ +GlobalLabel *Assembler::FindGlobalLabel(LPCUTF8 pszName) +{ + GlobalLabel lSearch(pszName,0,NULL), *pL; + pL = m_lstGlobalLabel.FIND(&lSearch); + lSearch.m_szName = NULL; + return pL; + //return m_lstGlobalLabel.FIND(pszName); +} + +/**************************************************************************/ + +GlobalFixup *Assembler::AddDeferredGlobalFixup(__in __nullterminated char *pszLabel, BYTE* pReference) +{ + GlobalFixup *pNew = new GlobalFixup(pszLabel, (BYTE*) pReference); + if (pNew == NULL) + { + report->error("Failed to allocate global fixup\n"); + m_State = STATE_FAIL; + } + else + m_lstGlobalFixup.PUSH(pNew); + + return pNew; +} + +/**************************************************************************/ +void Assembler::AddDeferredILFixup(ILFixupType Kind) +{ + _ASSERTE(Kind != ilGlobal); + AddDeferredILFixup(Kind, NULL); +} +/**************************************************************************/ + +void Assembler::AddDeferredILFixup(ILFixupType Kind, + GlobalFixup *GFixup) +{ + ILFixup *pNew = new ILFixup(m_CurPC, Kind, GFixup); + + _ASSERTE(m_pCurMethod != NULL); + if (pNew == NULL) + { + report->error("Failed to allocate IL fixup\n"); + m_State = STATE_FAIL; + } + else + m_pCurMethod->m_lstILFixup.PUSH(pNew); +} + +/**************************************************************************/ +void Assembler::EmitDataString(BinStr* str) +{ + if(str) + { + str->appendInt8(0); + DWORD DataLen = str->length(); + char *pb = (char*)(str->ptr()); + WCHAR *UnicodeString = (DataLen >= dwUniBuf) ? new WCHAR[DataLen] : &wzUniBuf[0]; + + if(UnicodeString) + { + WszMultiByteToWideChar(g_uCodePage,0,pb,-1,UnicodeString,DataLen); + EmitData(UnicodeString,DataLen*sizeof(WCHAR)); + if(DataLen >= dwUniBuf) delete [] UnicodeString; + } + else report->error("\nOut of memory!\n"); + delete str; + } +} + + + +/**************************************************************************/ +unsigned Assembler::OpcodeLen(Instr* instr) +{ + return (m_fStdMapping ? OpcodeInfo[instr->opcode].Len : 3); +} +/**************************************************************************/ +void Assembler::EmitOpcode(Instr* instr) +{ + if(m_fGeneratePDB && + ((instr->linenum != m_ulLastDebugLine) + ||(instr->column != m_ulLastDebugColumn) + ||(instr->linenum_end != m_ulLastDebugLineEnd) + ||(instr->column_end != m_ulLastDebugColumnEnd))) + { + if(m_pCurMethod) + { + LinePC *pLPC = new LinePC; + if(pLPC) + { + pLPC->Line = instr->linenum; + pLPC->Column = instr->column; + pLPC->LineEnd = instr->linenum_end; + pLPC->ColumnEnd = instr->column_end; + pLPC->PC = m_CurPC; + pLPC->pWriter = instr->pWriter; + + pLPC->pOwnerDocument = instr->pOwnerDocument; + if (0xfeefee == instr->linenum && + 0xfeefee == instr->linenum_end && + 0 == instr->column && + 0 == instr->column_end) + { + pLPC->IsHidden = TRUE; + } + else + { + pLPC->IsHidden = FALSE; + } + + m_pCurMethod->m_LinePCList.PUSH(pLPC); + } + else report->error("\nOut of memory!\n"); + } + m_ulLastDebugLine = instr->linenum; + m_ulLastDebugColumn = instr->column; + m_ulLastDebugLineEnd = instr->linenum_end; + m_ulLastDebugColumnEnd = instr->column_end; + } + if(instr->opcode == CEE_ENDFILTER) + { + if(m_pCurMethod) + { + if(m_pCurMethod->m_dwNumEndfilters >= m_pCurMethod->m_dwMaxNumEndfilters) + { + DWORD *pdw = new DWORD[m_pCurMethod->m_dwMaxNumEndfilters+MAX_EXCEPTIONS]; + if(pdw == NULL) + { + report->error("Failed to reallocate auxiliary SEH buffer\n"); + instr->opcode = -1; + return; + } + memcpy(pdw,m_pCurMethod->m_EndfilterOffsetList,m_pCurMethod->m_dwNumEndfilters*sizeof(DWORD)); + delete m_pCurMethod->m_EndfilterOffsetList; + m_pCurMethod->m_EndfilterOffsetList = pdw; + m_pCurMethod->m_dwMaxNumEndfilters += MAX_EXCEPTIONS; + } + m_pCurMethod->m_EndfilterOffsetList[m_pCurMethod->m_dwNumEndfilters++] = m_CurPC+2; + } + } + if (m_fStdMapping) + { + if (OpcodeInfo[instr->opcode].Len == 2) + EmitByte(OpcodeInfo[instr->opcode].Std1); + EmitByte(OpcodeInfo[instr->opcode].Std2); + } + else + { + unsigned short us = (unsigned short)instr->opcode; + EmitByte(REFPRE); + EmitBytes((BYTE *)&us,2); + } + instr->opcode = -1; +} + +/**************************************************************************/ +//void Assembler::OptimizeInstr(Instr* instr, int var) +//{ + +//} +/**************************************************************************/ +unsigned Assembler::ShortOf(unsigned opcode) +{ + unsigned retcode; + switch(opcode) + { + case CEE_LDARG: retcode=CEE_LDARG_S; break; + case CEE_LDARGA: retcode=CEE_LDARGA_S; break; + case CEE_STARG: retcode=CEE_STARG_S; break; + + case CEE_LDLOC: retcode=CEE_LDLOC_S; break; + case CEE_LDLOCA: retcode=CEE_LDLOCA_S; break; + case CEE_STLOC: retcode=CEE_STLOC_S; break; + + case CEE_BR: retcode=CEE_BR_S; break; + case CEE_BRFALSE: retcode=CEE_BRFALSE_S; break; + case CEE_BRTRUE: retcode=CEE_BRTRUE_S; break; + case CEE_BEQ: retcode=CEE_BEQ_S; break; + case CEE_BGE: retcode=CEE_BGE_S; break; + case CEE_BGT: retcode=CEE_BGT_S; break; + case CEE_BLE: retcode=CEE_BLE_S; break; + case CEE_BLT: retcode=CEE_BLT_S; break; + case CEE_BNE_UN: retcode=CEE_BNE_UN_S; break; + case CEE_BGE_UN: retcode=CEE_BGE_UN_S; break; + case CEE_BGT_UN: retcode=CEE_BGT_UN_S; break; + case CEE_BLE_UN: retcode=CEE_BLE_UN_S; break; + case CEE_BLT_UN: retcode=CEE_BLT_UN_S; break; + case CEE_LEAVE: retcode=CEE_LEAVE_S; break; + + case CEE_LDC_I4: retcode=CEE_LDC_I4_S; break; + case CEE_LDC_R8: retcode=CEE_LDC_R4; break; + + + default: retcode = opcode; break; + } + return retcode; +} + +/**************************************************************************/ +void Assembler::EmitInstrVar(Instr* instr, int var) +{ + unsigned opc = instr->opcode; + if(m_fOptimize) + { + if(var < 4) + { + switch(opc) + { + case CEE_LDARG: + case CEE_LDARG_S: opc = CEE_LDARG_0 + var; break; + + case CEE_LDLOC: + case CEE_LDLOC_S: opc = CEE_LDLOC_0 + var; break; + + case CEE_STLOC: + case CEE_STLOC_S: opc = CEE_STLOC_0 + var; break; + + default: break; + } + if(opc != (unsigned) instr->opcode) + { + instr->opcode = opc; + EmitOpcode(instr); + return; + } + } + if(var <= 0xFF) + { + opc = instr->opcode = ShortOf(opc); + } + } + EmitOpcode(instr); + if (isShort(opc)) + { + EmitByte(var); + } + else + { + short sh = (short)var; + EmitBytes((BYTE *)&sh,2); + } +} + +/**************************************************************************/ +void Assembler::EmitInstrVarByName(Instr* instr, __in __nullterminated char* label) +{ + int idx = -1, nArgVarFlag=0; + switch(instr->opcode) + { + case CEE_LDARGA: + case CEE_LDARGA_S: + case CEE_LDARG: + case CEE_LDARG_S: + case CEE_STARG: + case CEE_STARG_S: + nArgVarFlag++; + FALLTHROUGH; + case CEE_LDLOCA: + case CEE_LDLOCA_S: + case CEE_LDLOC: + case CEE_LDLOC_S: + case CEE_STLOC: + case CEE_STLOC_S: + + if(m_pCurMethod) + { + DWORD L = (DWORD)strlen(label); + if(nArgVarFlag == 1) + { + idx = m_pCurMethod->findArgNum(m_pCurMethod->m_firstArgName,label,L); + } + else + { + for(Scope* pSC = m_pCurMethod->m_pCurrScope; pSC; pSC=pSC->pSuperScope) + { + idx = m_pCurMethod->findLocSlot(pSC->pLocals,label,L); + if(idx >= 0) break; + } + } + if(idx >= 0) EmitInstrVar(instr, + ((nArgVarFlag==0)||(m_pCurMethod->m_Attr & mdStatic))? idx : idx+1); + else report->error("Undeclared identifier %s\n",label); + } + else + report->error("Instructions can be used only when in a method scope\n"); + break; + default: + report->error("Named argument illegal for this instruction\n"); + } + instr->opcode = -1; // in case we got here with error +} + +/**************************************************************************/ +void Assembler::EmitInstrI(Instr* instr, int val) +{ + int opc = instr->opcode; + if(m_fOptimize) + { + if((val >= -1)&&(val <= 8)) + { + switch(opc) + { + case CEE_LDC_I4: + case CEE_LDC_I4_S: opc = CEE_LDC_I4_M1 + (val+1); break; + + default: break; + } + if(opc != instr->opcode) + { + instr->opcode = opc; + EmitOpcode(instr); + return; + } + } + if((-128 <= val)&&(val <= 127)) + { + opc = instr->opcode = ShortOf(opc); + } + } + EmitOpcode(instr); + if (isShort(opc)) + { + EmitByte(val); + } + else + { + int i = val; + EmitBytes((BYTE *)&i,sizeof(int)); + } +} + +/**************************************************************************/ +void Assembler::EmitInstrI8(Instr* instr, __int64* val) +{ + EmitOpcode(instr); + EmitBytes((BYTE *)val, sizeof(__int64)); + delete val; +} + +/**************************************************************************/ +void Assembler::EmitInstrR(Instr* instr, double* pval) +{ + unsigned opc = instr->opcode; + EmitOpcode(instr); + if (isShort(opc)) + { + float val = (float)*pval; + EmitBytes((BYTE *)&val, sizeof(float)); + } + else + EmitBytes((BYTE *)pval, sizeof(double)); +} + +/**************************************************************************/ +void Assembler::EmitInstrBrTarget(Instr* instr, __in __nullterminated char* label) +{ + Label * pLabel = m_pCurMethod->FindLabel(label); + int offset=0; + if (pLabel == NULL) // branching forward -- no optimization + { + int pcrelsize = 1+(isShort(instr->opcode) ? 1 : 4); //size of the instruction plus argument + AddDeferredFixup(label, m_pCurOutputPos+1, + (m_CurPC + pcrelsize), pcrelsize-1); + } + else + { + offset = pLabel->m_PC - m_CurPC; + if(m_fOptimize) + { + if((-128 <= offset-5)&&(offset-2 <= 127)) //need to take into account the argument size (worst cases) + { + instr->opcode = ShortOf(instr->opcode); + } + } + if(isShort(instr->opcode)) + { + offset -= 2; + if((-128 > offset)||(offset > 127)) + report->error("Offset too large for short branching instruction, truncated\n"); + } + else + offset -= 5; + delete [] label; + } + int opc = instr->opcode; + EmitOpcode(instr); + if(isShort(opc)) EmitByte(offset); + else EmitBytes((BYTE *)&offset,4); +} +/**************************************************************************/ +void Assembler::AddDeferredFixup(__in __nullterminated char *pszLabel, BYTE *pBytes, DWORD RelativeToPC, BYTE FixupSize) +{ + Fixup *pNew = new Fixup(pszLabel, pBytes, RelativeToPC, FixupSize); + + if (pNew == NULL) + { + report->error("Failed to allocate deferred fixup\n"); + m_State = STATE_FAIL; + } + else + m_pCurMethod->m_lstFixup.PUSH(pNew); +} +/**************************************************************************/ +void Assembler::EmitInstrBrOffset(Instr* instr, int offset) +{ + unsigned opc=instr->opcode; + if(m_fOptimize) + { + if((-128 <= offset)&&(offset <= 127)) + { + opc = instr->opcode = ShortOf(opc); + } + } + EmitOpcode(instr); + if(isShort(opc)) EmitByte(offset); + else + { + int i = offset; + EmitBytes((BYTE *)&i,4); + } +} + +/**************************************************************************/ +mdToken Assembler::MakeMemberRef(mdToken cr, __in __nullterminated char* pszMemberName, BinStr* sig) +{ + DWORD cSig = sig->length(); + COR_SIGNATURE* mySig = (COR_SIGNATURE *)(sig->ptr()); + mdToken mr = mdMemberRefNil; + Class* pClass = NULL; + if(cr == 0x00000001) cr = mdTokenNil; // Module -> nil for globals + if(TypeFromToken(cr) == mdtTypeDef) pClass = m_lstClass.PEEK(RidFromToken(cr)-1); + if((TypeFromToken(cr) == mdtTypeDef)||(cr == mdTokenNil)) + { + MemberRefDescriptor* pMRD = new MemberRefDescriptor; + if(pMRD) + { + pMRD->m_tdClass = cr; + pMRD->m_pClass = pClass; + pMRD->m_szName = pszMemberName; + pMRD->m_dwName = (DWORD)strlen(pszMemberName); + pMRD->m_pSigBinStr = sig; + pMRD->m_tkResolved = 0; + if(*(sig->ptr())== IMAGE_CEE_CS_CALLCONV_FIELD) + { + m_LocalFieldRefDList.PUSH(pMRD); + mr = 0x98000000 | m_LocalFieldRefDList.COUNT(); + } + else + { + m_LocalMethodRefDList.PUSH(pMRD); + mr = 0x99000000 | m_LocalMethodRefDList.COUNT(); + } + } + else + { + report->error("Failed to allocate MemberRef Descriptor\n"); + return 0; + } + } + else + { + WszMultiByteToWideChar(g_uCodePage,0,pszMemberName,-1,wzUniBuf,dwUniBuf); + + if(cr == mdTokenNil) cr = mdTypeRefNil; + if(TypeFromToken(cr) == mdtAssemblyRef) + { + report->error("Cross-assembly global references are not supported ('%s')\n", pszMemberName); + mr = 0; + } + else + { + HRESULT hr = m_pEmitter->DefineMemberRef(cr, wzUniBuf, mySig, cSig, &mr); + if(FAILED(hr)) + { + report->error("Unable to define member reference '%s'\n", pszMemberName); + mr = 0; + } + } + //if(m_fOBJ) m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,mr)); + delete [] pszMemberName; + delete sig; + } + return mr; +} +/**************************************************************************/ +void Assembler::SetMemberRefFixup(mdToken tk, unsigned opcode_len) +{ + if(opcode_len) + { + switch(TypeFromToken(tk)) + { + case 0x98000000: + case 0x99000000: + case 0x9A000000: + if(m_pCurMethod != NULL) + m_pCurMethod->m_LocalMemberRefFixupList.PUSH( + new LocalMemberRefFixup(tk,(size_t)(m_CurPC + opcode_len))); + break; + } + } +} + +/**************************************************************************/ +mdToken Assembler::MakeMethodSpec(mdToken tkParent, BinStr* sig) +{ + DWORD cSig = sig->length(); + COR_SIGNATURE* mySig = (COR_SIGNATURE *)(sig->ptr()); + mdMethodSpec mi = mdMethodSpecNil; + if(TypeFromToken(tkParent) == 0x99000000) // Local MemberRef: postpone until resolved + { + MemberRefDescriptor* pMRD = new MemberRefDescriptor; + if(pMRD) + { + memset(pMRD,0,sizeof(MemberRefDescriptor)); + pMRD->m_tdClass = tkParent; + pMRD->m_pSigBinStr = sig; + m_MethodSpecList.PUSH(pMRD); + mi = 0x9A000000 | m_MethodSpecList.COUNT(); + } + else + { + report->error("Failed to allocate MemberRef Descriptor\n"); + return 0; + } + } + else + { + HRESULT hr = m_pEmitter->DefineMethodSpec(tkParent, mySig, cSig, &mi); + if(FAILED(hr)) + { + report->error("Unable to define method instantiation"); + return 0; + } + } + return mi; +} + +/**************************************************************************/ +void Assembler::EndEvent(void) +{ + Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass); + if(m_pCurEvent->m_tkAddOn == 0) + report->error("Event %s of class %s has no Add method. Event not emitted.", + m_pCurEvent->m_szName,pClass->m_szFQN); + else if(m_pCurEvent->m_tkRemoveOn == 0) + report->error("Event %s of class %s has no Remove method. Event not emitted.", + m_pCurEvent->m_szName,pClass->m_szFQN); + else + { + pClass->m_EventDList.PUSH(m_pCurEvent); + pClass->m_fNewMembers = TRUE; + } + m_pCurEvent = NULL; + m_tkCurrentCVOwner = 0; + m_pCustomDescrList = m_CustomDescrListStack.POP(); +} + +void Assembler::ResetEvent(__inout_z __inout char* szName, mdToken typeSpec, DWORD dwAttr) +{ + if(strlen(szName) >= MAX_CLASSNAME_LENGTH) + { + char c = szName[MAX_CLASSNAME_LENGTH-1]; + szName[MAX_CLASSNAME_LENGTH-1] = 0; + report->error("Event '%s...' -- name too long (%d characters).\n",szName,strlen(szName)); + szName[MAX_CLASSNAME_LENGTH-1] = c; + } + if((m_pCurEvent = new EventDescriptor)) + { + memset(m_pCurEvent,0,sizeof(EventDescriptor)); + m_pCurEvent->m_tdClass = m_pCurClass->m_cl; + m_pCurEvent->m_szName = szName; + m_pCurEvent->m_dwAttr = dwAttr; + m_pCurEvent->m_tkEventType = typeSpec; + m_pCurEvent->m_fNew = TRUE; + m_tkCurrentCVOwner = 0; + m_CustomDescrListStack.PUSH(m_pCustomDescrList); + m_pCustomDescrList = &(m_pCurEvent->m_CustomDescrList); + } + else report->error("Failed to allocate Event Descriptor\n"); +} + +void Assembler::SetEventMethod(int MethodCode, mdToken tk) +{ + switch(MethodCode) + { + case 0: + m_pCurEvent->m_tkAddOn = tk; + break; + case 1: + m_pCurEvent->m_tkRemoveOn = tk; + break; + case 2: + m_pCurEvent->m_tkFire = tk; + break; + case 3: + m_pCurEvent->m_tklOthers.PUSH((mdToken*)(UINT_PTR)tk); + break; + } +} +/**************************************************************************/ + +void Assembler::EndProp(void) +{ + Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass); + pClass->m_PropDList.PUSH(m_pCurProp); + pClass->m_fNewMembers = TRUE; + m_pCurProp = NULL; + m_tkCurrentCVOwner = 0; + m_pCustomDescrList = m_CustomDescrListStack.POP(); +} + +void Assembler::ResetProp(__inout_z __inout char * szName, BinStr* bsType, DWORD dwAttr, BinStr* pValue) +{ + DWORD cSig = bsType->length(); + COR_SIGNATURE* mySig = (COR_SIGNATURE *)(bsType->ptr()); + + if(strlen(szName) >= MAX_CLASSNAME_LENGTH) + { + char c = szName[MAX_CLASSNAME_LENGTH-1]; + szName[MAX_CLASSNAME_LENGTH-1] = 0; + report->error("Property '%s...' -- name too long (%d characters).\n",szName,strlen(szName)); + szName[MAX_CLASSNAME_LENGTH-1] = c; + } + m_pCurProp = new PropDescriptor; + if(m_pCurProp == NULL) + { + report->error("Failed to allocate Property Descriptor\n"); + return; + } + memset(m_pCurProp,0,sizeof(PropDescriptor)); + m_pCurProp->m_tdClass = m_pCurClass->m_cl; + m_pCurProp->m_szName = szName; + m_pCurProp->m_dwAttr = dwAttr; + m_pCurProp->m_fNew = TRUE; + + m_pCurProp->m_pSig = new COR_SIGNATURE[cSig]; + if(m_pCurProp->m_pSig == NULL) + { + report->error("\nOut of memory!\n"); + return; + } + memcpy(m_pCurProp->m_pSig,mySig,cSig); + m_pCurProp->m_dwCSig = cSig; + + if(pValue && pValue->length()) + { + BYTE* pch = pValue->ptr(); + m_pCurProp->m_dwCPlusTypeFlag = (DWORD)(*pch); + m_pCurProp->m_cbValue = pValue->length() - 1; + m_pCurProp->m_pValue = (PVOID)(pch+1); + if(m_pCurProp->m_dwCPlusTypeFlag == ELEMENT_TYPE_STRING) m_pCurProp->m_cbValue /= sizeof(WCHAR); + m_pCurProp->m_dwAttr |= prHasDefault; + } + else + { + m_pCurProp->m_dwCPlusTypeFlag = ELEMENT_TYPE_VOID; + m_pCurProp->m_pValue = NULL; + m_pCurProp->m_cbValue = 0; + } + m_tkCurrentCVOwner = 0; + m_CustomDescrListStack.PUSH(m_pCustomDescrList); + m_pCustomDescrList = &(m_pCurProp->m_CustomDescrList); +} + +void Assembler::SetPropMethod(int MethodCode, mdToken tk) +{ + switch(MethodCode) + { + case 0: + m_pCurProp->m_tkSet = tk; + break; + case 1: + m_pCurProp->m_tkGet = tk; + break; + case 2: + m_pCurProp->m_tklOthers.PUSH((mdToken*)(UINT_PTR)tk); + break; + } +} + +/**************************************************************************/ +void Assembler::EmitInstrStringLiteral(Instr* instr, BinStr* literal, BOOL ConvertToUnicode, BOOL Swap /*=FALSE*/) +{ + DWORD DataLen = literal->length(),L; + unsigned __int8 *pb = literal->ptr(); + HRESULT hr = S_OK; + mdToken tk; + WCHAR *UnicodeString; + if(DataLen == 0) + { + //report->warn("Zero length string emitted\n"); + ConvertToUnicode = FALSE; + } + if(ConvertToUnicode) + { + UnicodeString = (DataLen >= dwUniBuf) ? new WCHAR[DataLen+1] : &wzUniBuf[0]; + literal->appendInt8(0); + pb = literal->ptr(); + // convert string to Unicode + L = UnicodeString ? WszMultiByteToWideChar(g_uCodePage,0,(char*)pb,-1,UnicodeString,DataLen+1) : 0; + if(L == 0) + { + const char* sz=NULL; + DWORD dw; + switch(dw=GetLastError()) + { + case ERROR_INSUFFICIENT_BUFFER: sz = "ERROR_INSUFFICIENT_BUFFER"; break; + case ERROR_INVALID_FLAGS: sz = "ERROR_INVALID_FLAGS"; break; + case ERROR_INVALID_PARAMETER: sz = "ERROR_INVALID_PARAMETER"; break; + case ERROR_NO_UNICODE_TRANSLATION: sz = "ERROR_NO_UNICODE_TRANSLATION"; break; + } + if(sz) report->error("Failed to convert string '%s' to Unicode: %s\n",(char*)pb,sz); + else report->error("Failed to convert string '%s' to Unicode: error 0x%08X\n",(char*)pb,dw); + goto OuttaHere; + } + L--; + } + else + { + if(DataLen & 1) + { + literal->appendInt8(0); + pb = literal->ptr(); + DataLen++; + } + UnicodeString = (WCHAR*)pb; + L = DataLen/sizeof(WCHAR); + +#if BIGENDIAN + if (Swap) + SwapStringLength(UnicodeString, L); +#endif + } + // Add the string data to the metadata, which will fold dupes. + hr = m_pEmitter->DefineUserString( + UnicodeString, + L, + &tk + ); + if (FAILED(hr)) + { + report->error("Failed to add user string using DefineUserString, hr=0x%08x, data: '%S'\n", + hr, UnicodeString); + } + else + { + EmitOpcode(instr); + if(m_fOBJ) m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,tk)); + + EmitBytes((BYTE *)&tk,sizeof(mdToken)); + } +OuttaHere: + delete literal; + if(((void*)UnicodeString != (void*)pb)&&(DataLen >= dwUniBuf)) delete [] UnicodeString; + instr->opcode = -1; // in case we got here with error +} + +/**************************************************************************/ +void Assembler::EmitInstrSig(Instr* instr, BinStr* sig) +{ + mdSignature MetadataToken; + DWORD cSig = sig->length(); + COR_SIGNATURE* mySig = (COR_SIGNATURE *)(sig->ptr()); + + if (FAILED(m_pEmitter->GetTokenFromSig(mySig, cSig, &MetadataToken))) + { + report->error("Unable to convert signature to metadata token.\n"); + } + else + { + EmitOpcode(instr); + if(m_fOBJ) m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,MetadataToken)); + EmitBytes((BYTE *)&MetadataToken, sizeof(mdSignature)); + } + delete sig; + instr->opcode = -1; // in case we got here with error +} + +/**************************************************************************/ +void Assembler::EmitInstrSwitch(Instr* instr, Labels* targets) +{ + Labels *pLbls; + int NumLabels; + Label *pLabel; + UINT offset; + + EmitOpcode(instr); + + // count # labels + for(pLbls = targets, NumLabels = 0; pLbls; pLbls = pLbls->Next, NumLabels++); + + EmitBytes((BYTE *)&NumLabels,sizeof(int)); + DWORD PC_nextInstr = m_CurPC + 4*NumLabels; + for(pLbls = targets; pLbls; pLbls = pLbls->Next) + { + if(pLbls->isLabel) + { + if((pLabel = m_pCurMethod->FindLabel(pLbls->Label))) + { + offset = pLabel->m_PC - PC_nextInstr; + if (m_fDisplayTraceOutput) report->msg("%d\n", offset); + } + else + { + // defer until we find the label + AddDeferredFixup(pLbls->Label, m_pCurOutputPos, PC_nextInstr, 4 /* pcrelsize */ ); + offset = 0; + pLbls->Label = NULL; + if (m_fDisplayTraceOutput) report->msg("forward label %s\n", pLbls->Label); + } + } + else + { + offset = (UINT)(UINT_PTR)pLbls->Label; + if (m_fDisplayTraceOutput) report->msg("%d\n", offset); + } + EmitBytes((BYTE *)&offset, sizeof(UINT)); + } + delete targets; +} + +/**************************************************************************/ +void Assembler::EmitLabel(__in __nullterminated char* label) +{ + _ASSERTE(m_pCurMethod); + AddLabel(m_CurPC, label); +} +/**************************************************************************/ +void Assembler::EmitDataLabel(__in __nullterminated char* label) +{ + AddGlobalLabel(label, m_pCurSection); +} + +/**************************************************************************/ +void Assembler::EmitBytes(BYTE *p, unsigned len) +{ + if(m_pCurOutputPos + len >= m_pEndOutputPos) + { + size_t buflen = m_pEndOutputPos - m_pOutputBuffer; + size_t newlen = buflen+(len/OUTPUT_BUFFER_INCREMENT + 1)*OUTPUT_BUFFER_INCREMENT; + BYTE *pb = new BYTE[newlen]; + if(pb == NULL) + { + report->error("Failed to extend output buffer from %d to %d bytes. Aborting\n", + buflen, newlen); + exit(1); + } + size_t delta = pb - m_pOutputBuffer; + int i; + Fixup* pSearch; + GlobalFixup *pGSearch; + for (i=0; (pSearch = m_pCurMethod->m_lstFixup.PEEK(i)); i++) pSearch->m_pBytes += delta; + for (i=0; (pGSearch = m_lstGlobalFixup.PEEK(i)); i++) //need to move only those pointing to output buffer + { + if((pGSearch->m_pReference >= m_pOutputBuffer)&&(pGSearch->m_pReference <= m_pEndOutputPos)) + pGSearch->m_pReference += delta; + } + + + memcpy(pb,m_pOutputBuffer,m_CurPC); + delete [] m_pOutputBuffer; + m_pOutputBuffer = pb; + m_pCurOutputPos = &m_pOutputBuffer[m_CurPC]; + m_pEndOutputPos = &m_pOutputBuffer[newlen]; + + } + + switch (len) + { + case 1: + *m_pCurOutputPos = *p; + break; + case 2: + SET_UNALIGNED_VAL16(m_pCurOutputPos, GET_UNALIGNED_16(p)); + break; + case 4: + SET_UNALIGNED_VAL32(m_pCurOutputPos, GET_UNALIGNED_32(p)); + break; + case 8: + SET_UNALIGNED_VAL64(m_pCurOutputPos, GET_UNALIGNED_64(p)); + break; + default: + _ASSERTE(!"NYI"); + break; + } + + m_pCurOutputPos += len; + m_CurPC += len; +} +/**************************************************************************/ +BinStr* Assembler::EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps) +{ + unsigned cnt; + + // build the blob As BinStr + unsigned L = (unsigned) strlen(szReflName); + BYTE* pb = NULL; + BinStr* pbsRet = new BinStr(); + // encode the Reflection name length + cnt = CorSigCompressData(L, pbsRet->getBuff(5)); + pbsRet->remove(5 - cnt); + //put the name in + if((pb = pbsRet->getBuff(L)) != NULL) + memcpy(pb,szReflName,L); + // find out the size of compressed nProps + cnt = CorSigCompressData(nProps, pbsRet->getBuff(5)); + pbsRet->remove(5); + // encode blob size + unsigned nSize = cnt + pbsSecAttrBlob->length(); + cnt = CorSigCompressData(nSize, pbsRet->getBuff(5)); + pbsRet->remove(5 - cnt); + // actually encode nProps + cnt = CorSigCompressData(nProps, pbsRet->getBuff(5)); + pbsRet->remove(5 - cnt); + // append the props/values blob + pbsRet->append(pbsSecAttrBlob); + delete pbsSecAttrBlob; + return pbsRet; +} +/**************************************************************************/ +void Assembler::EmitSecurityInfo(mdToken token, + PermissionDecl* pPermissions, + PermissionSetDecl* pPermissionSets) +{ + PermissionDecl *pPerm, *pPermNext; + PermissionSetDecl *pPset, *pPsetNext; + unsigned uCount = 0; + COR_SECATTR *pAttrs; + unsigned i; + unsigned uLength; + mdTypeRef tkTypeRef; + BinStr *pSig; + char *szMemberName; + DWORD dwErrorIndex = 0; + + if (pPermissions) { + + for (pPerm = pPermissions; pPerm; pPerm = pPerm->m_Next) + uCount++; + + _ASSERTE(uCount > 0); + // uCount is expected to be positive all the time. The if statement is here to please prefast. + if (uCount > 0) + { + if((pAttrs = new COR_SECATTR[uCount])==NULL) + { + report->error("\nOut of memory!\n"); + return; + } + + mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetAsmRef("mscorlib"); + tkTypeRef = ResolveClassRef(tkMscorlib,"System.Security.Permissions.SecurityAction", NULL); + for (pPerm = pPermissions, i = 0; pPerm; pPerm = pPermNext, i++) { + pPermNext = pPerm->m_Next; + + pSig = new BinStr(); + pSig->appendInt8(IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS); + pSig->appendInt8(1); + pSig->appendInt8(ELEMENT_TYPE_VOID); + pSig->appendInt8(ELEMENT_TYPE_VALUETYPE); + uLength = CorSigCompressToken(tkTypeRef, pSig->getBuff(5)); + pSig->remove(5 - uLength); + + uLength = (unsigned)strlen(COR_CTOR_METHOD_NAME) + 1; + if((szMemberName = new char[uLength])) + { + memcpy(szMemberName, COR_CTOR_METHOD_NAME, uLength); + pAttrs[i].tkCtor = MakeMemberRef(pPerm->m_TypeSpec, szMemberName, pSig); + pAttrs[i].pCustomAttribute = (const void *)pPerm->m_Blob; + pAttrs[i].cbCustomAttribute = pPerm->m_BlobLength; + } + else report->error("\nOut of memory!\n"); + } + + if (FAILED(m_pEmitter->DefineSecurityAttributeSet(token, + pAttrs, + uCount, + &dwErrorIndex))) + { + _ASSERT(uCount >= dwErrorIndex); + if (dwErrorIndex == uCount) + { + report->error("Failed to define security attribute set for 0x%08X\n", token); + } + else + { + report->error("Failed to define security attribute set for 0x%08X\n (error in permission %u)\n", + token, uCount - dwErrorIndex); + } + } + delete [] pAttrs; + for (pPerm = pPermissions, i = 0; pPerm; pPerm = pPermNext, i++) { + pPermNext = pPerm->m_Next; + delete pPerm; + } + } + } + + for (pPset = pPermissionSets; pPset; pPset = pPsetNext) { + pPsetNext = pPset->m_Next; + if(FAILED(m_pEmitter->DefinePermissionSet(token, + pPset->m_Action, + pPset->m_Value->ptr(), + pPset->m_Value->length(), + NULL))) + report->error("Failed to define security permission set for 0x%08X\n", token); + delete pPset; + } +} + +void Assembler::AddMethodImpl(mdToken tkImplementedTypeSpec, __in __nullterminated char* szImplementedName, BinStr* pImplementedSig, + mdToken tkImplementingTypeSpec, __in_opt __nullterminated char* szImplementingName, BinStr* pImplementingSig) +{ + if(m_pCurClass) + { + MethodImplDescriptor* pMID = new MethodImplDescriptor; + if(pMID == NULL) + { + report->error("Failed to allocate MethodImpl Descriptor\n"); + return; + } + pMID->m_fNew = TRUE; + pMID->m_tkDefiningClass = m_pCurClass->m_cl; + if(szImplementingName) //called from class scope, overriding method specified + { + pMID->m_tkImplementedMethod = MakeMemberRef(tkImplementedTypeSpec,szImplementedName,pImplementedSig); + pMID->m_tkImplementingMethod = MakeMemberRef(tkImplementingTypeSpec,szImplementingName,pImplementingSig); + } + else //called from method scope, use current method as overriding + { + if(m_pCurMethod) + { + if (pImplementedSig == NULL) + { + pImplementedSig = new BinStr(); + memcpy(pImplementedSig->getBuff(m_pCurMethod->m_dwMethodCSig), m_pCurMethod->m_pMethodSig,m_pCurMethod->m_dwMethodCSig); + } + pMID->m_tkImplementedMethod = MakeMemberRef(tkImplementedTypeSpec,szImplementedName,pImplementedSig); + pMID->m_tkImplementingMethod = 0; + + m_pCurMethod->m_MethodImplDList.PUSH(pMID); // copy goes to method's own list (ptr only) + } + else + { + report->error("No overriding method specified"); + delete pMID; + return; + } + } + m_MethodImplDList.PUSH(pMID); + } + else + report->error(".override directive outside class scope"); +} +// source file name paraphernalia +void Assembler::SetSourceFileName(__in __nullterminated char* szName) +{ + if(szName) + { + if(*szName) + { + if(strcmp(m_szSourceFileName,szName)) + { + strcpy_s(m_szSourceFileName,MAX_FILENAME_LENGTH*3+1,szName); + WszMultiByteToWideChar(g_uCodePage,0,szName,-1,m_wzSourceFileName,MAX_FILENAME_LENGTH); + } + if(m_fGeneratePDB) + { + if (IsPortablePdb()) + { + if (FAILED(m_pPortablePdbWriter->DefineDocument(szName, &m_guidLang))) + { + report->error("Failed to define a document: '%s'", szName); + } + delete[] szName; + } + else + { + DocWriter* pDW; + unsigned i = 0; + while ((pDW = m_DocWriterList.PEEK(i++)) != NULL) + { + if (!strcmp(szName, pDW->Name)) break; + } + if (pDW) + { + m_pSymDocument = pDW->pWriter; + delete[] szName; + } + else if (m_pSymWriter) + { + HRESULT hr; + WszMultiByteToWideChar(g_uCodePage, 0, szName, -1, wzUniBuf, dwUniBuf); + if (FAILED(hr = m_pSymWriter->DefineDocument(wzUniBuf, &m_guidLang, + &m_guidLangVendor, &m_guidDoc, &m_pSymDocument))) + { + m_pSymDocument = NULL; + report->error("Failed to define a document writer"); + } + if ((pDW = new DocWriter()) != NULL) + { + pDW->Name = szName; + pDW->pWriter = m_pSymDocument; + m_DocWriterList.PUSH(pDW); + } + else + { + report->error("Out of memory"); + delete[] szName; + } + } + else delete[] szName; + } + } + else delete [] szName; + } + else delete [] szName; + } +} +void Assembler::SetSourceFileName(BinStr* pbsName) +{ + ULONG L; + if(pbsName && (L = (ULONG)(pbsName->length()))) + { + pbsName->appendInt8(0); + char* sz = new char[L+1]; + memcpy(sz,pbsName->ptr(),L+1); + SetSourceFileName(sz); + delete pbsName; + } +} + +// Portable PDB paraphernalia +void Assembler::SetPdbFileName(__in __nullterminated char* szName) +{ + if (szName) + { + if (*szName) + { + strcpy_s(m_szPdbFileName, MAX_FILENAME_LENGTH * 3 + 1, szName); + WszMultiByteToWideChar(g_uCodePage, 0, szName, -1, m_wzPdbFileName, MAX_FILENAME_LENGTH); + } + } +} +HRESULT Assembler::SavePdbFile() +{ + HRESULT hr = S_OK; + mdMethodDef entryPoint; + + if (m_pdbFormat == PORTABLE) + { + if (FAILED(hr = (m_pPortablePdbWriter == NULL ? E_FAIL : S_OK))) goto exit; + if (FAILED(hr = (m_pPortablePdbWriter->GetEmitter() == NULL ? E_FAIL : S_OK))) goto exit; + if (FAILED(hr = m_pCeeFileGen->GetEntryPoint(m_pCeeFile, &entryPoint))) goto exit; + if (FAILED(hr = m_pPortablePdbWriter->BuildPdbStream(m_pEmitter, entryPoint))) goto exit; + if (FAILED(hr = m_pPortablePdbWriter->GetEmitter()->Save(m_wzPdbFileName, NULL))) goto exit; + } +exit: + return hr; +} +BOOL Assembler::IsPortablePdb() +{ + return (m_pdbFormat == PORTABLE) && (m_pPortablePdbWriter != NULL); +} + +// This method is called after we have parsed the generic type parameters for either +// a generic class or a generic method. It calls CheckAddGenericParamConstraint on +// each generic parameter constraint that was recorded. +// +void Assembler::RecordTypeConstraints(GenericParamConstraintList* pGPCList, int numTyPars, TyParDescr* tyPars) +{ + if (numTyPars > 0) + { + for (int i = 0; i < numTyPars; i++) + { + // Decode any type constraints held by tyPars[i].Bounds() + BinStr* typeConstraints = tyPars[i].Bounds(); + _ASSERTE((typeConstraints->length() % 4) == 0); + int numConstraints = (typeConstraints->length() / 4) - 1; + if (numConstraints > 0) + { + mdToken* ptk = (mdToken*)typeConstraints->ptr(); + for (int j = 0; j < numConstraints; j++) + { + mdToken tkTypeConstraint = ptk[j]; + + // pass false for isParamDirective, these constraints are from the class or method definition + // + CheckAddGenericParamConstraint(pGPCList, i, tkTypeConstraint, false); + } + } + } + } +} + +// AddGenericParamConstraint is called when we have a .param constraint directive after a class definition +// +void Assembler::AddGenericParamConstraint(int index, char * pStrGenericParam, mdToken tkTypeConstraint) +{ + if (!m_pCurClass) + { + report->error(".parm constraint directive outside class scope"); + return; + } + if (index > 0) + { + if (pStrGenericParam != 0) + { + report->error("LOGIC ERROR - we have both an index and a pStrGenericParam"); + return; + } + if (index > (int)m_pCurClass->m_NumTyPars) + { + report->error("Type parameter index out of range\n"); + return; + } + index = index - 1; + } + else // index was 0, so a name must be supplied by pStrGenericParam + { + if (pStrGenericParam == 0) + { + report->error("LOGIC ERROR - we have neither an index or a pStrGenericParam"); + return; + } + index = m_pCurClass->FindTyPar(pStrGenericParam); + if (index == -1) + { + report->error("Type parameter '%s' undefined\n", pStrGenericParam); + return; + } + } + + // pass true for isParamDirective, we are parsing a .param directive for a class here + // + CheckAddGenericParamConstraint(&m_pCurClass->m_GPCList, index, tkTypeConstraint, true); +} + +// CheckAddGenericParamConstraint is called when we have to handle a generic parameter constraint +// When parsing a generic class/method definition isParamDirective is false - we have a generic type constaint +// for this case we do not setup m_pCustomDescrList as a .custom after a generic class/method definition is +// for the class/method +// When isParamDirective is true, we have a .param constraint directive and we will setup m_pCustomDescrList +// and any subsequent .custom is for the generic parameter constrant +// +void Assembler::CheckAddGenericParamConstraint(GenericParamConstraintList* pGPCList, int index, mdToken tkTypeConstraint, bool isParamDirective) +{ + _ASSERTE(tkTypeConstraint != 0); + _ASSERTE(index >= 0); + + // Look for an existing match in m_pCurClass->m_GPCList + // + // Iterate the GenericParamConstraints list + // + bool match = false; + GenericParamConstraintDescriptor *pGPC = nullptr; + for (int listIndex = 0; (pGPC = pGPCList->PEEK(listIndex)) != nullptr; listIndex++) + { + int curParamIndex = pGPC->GetParamIndex(); + if (curParamIndex == index) + { + mdToken curTypeConstraint = pGPC->GetTypeConstraint(); + if (curTypeConstraint == tkTypeConstraint) + { + match = true; + break; + } + } + } + + if (match) + { + // Found an existing generic parameter constraint + // + if (isParamDirective) + { + // Setup the custom descr list so that we can record + // custom attributes on this generic param contraint + // + m_pCustomDescrList = pGPC->CAList(); + } + } + else + { + // not found - add it to our pGPCList + // + GenericParamConstraintDescriptor* pNewGPCDescr = new GenericParamConstraintDescriptor(); + pNewGPCDescr->Init(index, tkTypeConstraint); + pGPCList->PUSH(pNewGPCDescr); + if (isParamDirective) + { + // Setup the custom descr list so that we can record + // custom attributes on this generic param contraint + // + m_pCustomDescrList = pNewGPCDescr->CAList(); + } + } +} + +// Emit the proper metadata for the generic parameter type constraints +// This will create one GenericParamConstraint tokens for each type constraint. +// Finally associate any custom attributes with their GenericParamConstraint +// and emit them as well +// +void Assembler::EmitGenericParamConstraints(int numTyPars, TyParDescr* pTyPars, mdToken tkOwner, GenericParamConstraintList* pGPCL) +{ + // If we haver no generic parameters, or a null or empty list of generic param constraints + // then we can early out and just return. + // + if ((numTyPars == 0) || (pGPCL == NULL) || (pGPCL->COUNT() == 0)) + { + return; + } + + int* nConstraintsArr = new int[numTyPars]; + int* nConstraintIndexArr = new int[numTyPars]; + mdToken** pConstraintsArr = new mdToken*[numTyPars]; + mdGenericParamConstraint** pGPConstraintsArr = new mdToken*[numTyPars]; + + // Zero initialize the arrays that we just created + int paramIndex; + for (paramIndex = 0; paramIndex < numTyPars; paramIndex++) + { + nConstraintsArr[paramIndex] = 0; + nConstraintIndexArr[paramIndex] = 0; + pConstraintsArr[paramIndex] = nullptr; + pGPConstraintsArr[paramIndex] = nullptr; + } + + // Set all the owner tokens and calculate the number of constraints for each type parameter + GenericParamConstraintDescriptor *pGPC; + int listIndex; + for (listIndex = 0; (pGPC = pGPCL->PEEK(listIndex)) != nullptr; listIndex++) + { + pGPC->SetOwner(tkOwner); + paramIndex = pGPC->GetParamIndex(); + nConstraintsArr[paramIndex]++; + } + + // Allocate an appropriately sized array of type constraints for each generic type param + // If the generic type param has no type constraints we will just leave the value + // of pConstraintsArr[paramIndex] (and pGPConstraintsArr[]) as nullptr + for (paramIndex = 0; paramIndex < numTyPars; paramIndex++) + { + // How many constraints are there for this generic parameter? + int currNumConstraints = nConstraintsArr[paramIndex]; + if (currNumConstraints > 0) + { + // We are required to have an extra mdTokenNil as the last element in the array + int currConstraintArraySize = currNumConstraints + 1; + + mdToken* currConstraintsArr = new mdToken[currConstraintArraySize]; + mdToken* currGPConstraintsArr = new mdToken[currConstraintArraySize]; + + // initialize this new array to all mdTokenNil + for (int i = 0; i < currConstraintArraySize; i++) + { + currConstraintsArr[i] = mdTokenNil; + currGPConstraintsArr[i] = mdTokenNil; + } + + // Assign these empty arrays to the proper elements of pConstraintsArr[] and pConstraintsArr[] + pConstraintsArr[paramIndex] = currConstraintsArr; + pGPConstraintsArr[paramIndex] = currGPConstraintsArr; + } + } + + // Iterate the GenericParamConstraints list again and + // record the type constraints in the pConstraintsArr[][] + for (listIndex = 0; (pGPC = pGPCL->PEEK(listIndex)) != nullptr; listIndex++) + { + paramIndex = pGPC->GetParamIndex(); + + mdToken currTypeConstraint = pGPC->GetTypeConstraint(); + mdToken* currConstraintArr = pConstraintsArr[paramIndex]; + _ASSERTE(currConstraintArr != nullptr); + int constraintArrayLast = nConstraintsArr[paramIndex]; + int currConstraintArrIndex = nConstraintIndexArr[paramIndex]; + _ASSERTE(currConstraintArrIndex < constraintArrayLast); + + currConstraintArr[currConstraintArrIndex++] = currTypeConstraint; + _ASSERTE(currConstraintArr[currConstraintArrIndex] == mdTokenNil); // the last element must be mdTokenNil + nConstraintIndexArr[paramIndex] = currConstraintArrIndex; + } + + // Next emit the metadata for the Generic parameter type constraints + // + for (paramIndex = 0; paramIndex < numTyPars; paramIndex++) + { + int currParamNumConstraints = nConstraintIndexArr[paramIndex]; + + if (currParamNumConstraints > 0) + { + mdGenericParam tkGenericParam = pTyPars[paramIndex].Token(); + DWORD paramAttrs = pTyPars[paramIndex].Attrs(); + ULONG currNumConstraints = (ULONG) nConstraintsArr[paramIndex]; + mdToken* currConstraintArr = pConstraintsArr[paramIndex]; + mdGenericParamConstraint* currGPConstraintArr = pGPConstraintsArr[paramIndex]; + + // call SetGenericParamProps for each generic parameter that has a non-zero count of constraints + // to record each generic parameters tyupe constraints. + // + // Pass the paramAttrs, these contain values in CorGenericParamAttr such as: + // gpReferenceTypeConstraint = 0x0004, // type argument must be a reference type + // gpNotNullableValueTypeConstraint = 0x0008, // type argument must be a value type but not Nullable + // gpDefaultConstructorConstraint = 0x0010, // type argument must have a public default constructor + // + // This Metadata operation will also create a new GenericParamConstraint token + // for each of the generic parameters type constraints. + // + if (FAILED(m_pEmitter->SetGenericParamProps(tkGenericParam, paramAttrs, NULL, 0, currConstraintArr))) + { + report->error("Failed in SetGenericParamProp"); + } + else + { + // We now need to fetch the values of the new GenericParamConstraint tokens + // that were created by the call to SetGenericParamProps + // + // These tokens are the token owners for the custom attributes + // such as NulableAttribute and TupleElementNamesAttribute + // + HCORENUM hEnum = NULL; + ULONG uCount = 0; + if (FAILED(m_pImporter->EnumGenericParamConstraints(&hEnum, tkGenericParam, currGPConstraintArr, (ULONG)currNumConstraints, &uCount))) + { + report->error("Failed in EnumGenericParamConstraints"); + } + else + { + _ASSERTE(uCount == currNumConstraints); + m_pImporter->CloseEnum(hEnum); + } + } + } + } + + // Emit any Custom Attributes associated with these Generic Paaram Constraints + // + while ((pGPC = pGPCL->POP())) + { + paramIndex = pGPC->GetParamIndex(); + + mdToken tkTypeConstraint = pGPC->GetTypeConstraint(); + int currNumConstraints = nConstraintsArr[paramIndex]; + mdToken* currConstraintArr = pConstraintsArr[paramIndex]; + mdGenericParamConstraint* currGPConstraintArr = pGPConstraintsArr[paramIndex]; + mdGenericParamConstraint tkOwnerOfCA = mdTokenNil; + + // find the matching type constraint and fetch the GenericParamConstraint + // + for (int i = 0; i < currNumConstraints; i++) + { + if (currConstraintArr[i] == tkTypeConstraint) + { + tkOwnerOfCA = currGPConstraintArr[i]; + break; + } + } + _ASSERTE(tkOwnerOfCA != mdTokenNil); + + // Record the Generic Param Constraint token + // and supply it as the owner for the list of Custom attributes. + // + pGPC->Token(tkOwnerOfCA); + EmitCustomAttributes(tkOwnerOfCA, pGPC->CAList()); + } +} diff --git a/src/coreclr/ilasm/assembler.h b/src/coreclr/ilasm/assembler.h new file mode 100644 index 00000000000..8f87df66645 --- /dev/null +++ b/src/coreclr/ilasm/assembler.h @@ -0,0 +1,1304 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +/************************************************************************/ +/* Assembler.h */ +/************************************************************************/ + +#ifndef Assember_h +#define Assember_h + +#define NEW_INLINE_NAMES + +#include "binstr.h" + +#include "specstrings.h" + +#include "asmenum.h" +#include "asmtemplates.h" + +#include "portable_pdb.h" +#include "portablepdbmdi.h" + +// Disable the "initialization of static local vars is no thread safe" error +#ifdef _MSC_VER +#pragma warning(disable : 4640) +#endif + +#ifdef ResetEvent +#undef ResetEvent +#endif + +#define OUTPUT_BUFFER_SIZE 8192 // initial size of asm code for a single method +#define OUTPUT_BUFFER_INCREMENT 1024 // size of code buffer increment when it's full +#define MAX_FILENAME_LENGTH 2048 //256 +#define MAX_SIGNATURE_LENGTH 256 // unused +#define MAX_LABEL_SIZE 256 //64 +#define MAX_CALL_SIG_SIZE 32 // unused +#define MAX_SCOPE_LENGTH _MAX_PATH // follow the RegMeta::SetModuleProps limitation + +#define MAX_NAMESPACE_LENGTH 1024 //256 //64 +#define MAX_MEMBER_NAME_LENGTH 1024 //256 //64 + +#define MAX_INTERFACES_IMPLEMENTED 16 // initial number; extended by 16 when needed +#define GLOBAL_DATA_SIZE 8192 // initial size of global data buffer +#define GLOBAL_DATA_INCREMENT 1024 // size of global data buffer increment when it's full +#define MAX_METHODS 1024 // unused +#define MAX_INPUT_LINE_LEN 1024 // unused +#define MAX_TYPAR 8 +#define BASE_OBJECT_CLASSNAME "System.Object" +#define MAX_MANIFEST_RESOURCES 1024 + +// Fully-qualified class name separators: +#define NESTING_SEP ((char)0xF8) + +#define dwUniBuf 16384 + +#ifdef TARGET_UNIX +extern char *g_pszExeFile; +#endif + +extern WCHAR wzUniBuf[]; // Unicode conversion global buffer (assem.cpp) + +class Class; +class Method; +class PermissionDecl; +class PermissionSetDecl; + +unsigned hash( // defined in assem.cpp + __in_ecount(length) const BYTE *k, /* the key */ + unsigned length, /* the length of the key */ + unsigned initval); /* the previous hash, or an arbitrary value */ + +struct MemberRefDescriptor +{ + mdToken m_tdClass; + Class* m_pClass; + char* m_szName; + DWORD m_dwName; + BinStr* m_pSigBinStr; + mdToken m_tkResolved; +}; +typedef FIFO<MemberRefDescriptor> MemberRefDList; + + +struct MethodImplDescriptor +{ + mdToken m_tkImplementedMethod; + mdToken m_tkImplementingMethod; + mdToken m_tkDefiningClass; + BOOL m_fNew; +}; +typedef FIFO<MethodImplDescriptor> MethodImplDList; + +struct LocalMemberRefFixup +{ + mdToken tk; + size_t offset; + BOOL m_fNew; + LocalMemberRefFixup(mdToken TK, size_t Offset) + { + tk = TK; + offset = Offset; + m_fNew = TRUE; + } +}; +typedef FIFO<LocalMemberRefFixup> LocalMemberRefFixupList; + +struct CustomDescr +{ + mdToken tkType; + mdToken tkOwner; + mdToken tkInterfacePair; // Needed for InterfaceImpl CA's + BinStr* pBlob; + + CustomDescr(mdToken tko, mdToken tk, BinStr* pblob) + { + tkType = tk; + pBlob = pblob; + tkOwner = tko; + tkInterfacePair = 0; + }; + CustomDescr(mdToken tk, BinStr* pblob) + { + tkType = tk; + pBlob = pblob; + tkOwner = 0; + tkInterfacePair = 0; + }; + CustomDescr(CustomDescr* pOrig) + { + tkType = pOrig->tkType; + pBlob = new BinStr(); + pBlob->append(pOrig->pBlob); + tkOwner = pOrig->tkOwner; + tkInterfacePair = pOrig->tkInterfacePair; + }; + ~CustomDescr() + { + if(pBlob) + delete pBlob; + }; +}; +typedef FIFO<CustomDescr> CustomDescrList; +typedef LIFO<CustomDescrList> CustomDescrListStack; + +class GenericParamConstraintDescriptor +{ +public: + GenericParamConstraintDescriptor() + { + m_tk = mdTokenNil; + m_tkOwner = mdTokenNil; + m_iGenericParamIndex = -1; + m_tkTypeConstraint = mdTokenNil; + }; + ~GenericParamConstraintDescriptor() + { + m_lstCA.RESET(true); + }; + void Init(int index, mdToken typeConstraint) + { + m_iGenericParamIndex = index; + m_tkTypeConstraint = typeConstraint; + }; + void Token(mdToken tk) + { + m_tk = tk; + }; + mdToken Token() + { + return m_tk; + }; + void SetOwner(mdToken tk) + { + m_tkOwner = tk; + }; + mdToken GetOwner() + { + return m_tkOwner; + }; + int GetParamIndex() + { + return m_iGenericParamIndex; + }; + mdToken GetTypeConstraint() + { + return m_tkTypeConstraint; + }; + CustomDescrList* CAList() + { + return &m_lstCA; + }; + +private: + mdGenericParamConstraint m_tk; + mdToken m_tkOwner; + int m_iGenericParamIndex; + mdToken m_tkTypeConstraint; + + CustomDescrList m_lstCA; +}; +typedef FIFO<GenericParamConstraintDescriptor> GenericParamConstraintList; +/**************************************************************************/ +#include "typar.hpp" +#include "method.hpp" +#include "iceefilegen.h" +#include "asmman.hpp" + +#include "nvpair.h" + + +typedef enum +{ + STATE_OK, + STATE_FAIL, + STATE_ENDMETHOD, + STATE_ENDFILE +} state_t; + + +class GlobalLabel +{ +public: + LPCUTF8 m_szName; + DWORD m_GlobalOffset; + HCEESECTION m_Section; + unsigned m_Hash; + + GlobalLabel(LPCUTF8 pszName, DWORD GlobalOffset, HCEESECTION section) + { + m_GlobalOffset = GlobalOffset; + m_Section = section; + m_szName = pszName; + m_Hash = hash((const BYTE*)pszName, (unsigned)strlen(pszName),10); + } + + ~GlobalLabel(){ delete [] m_szName; } + + int ComparedTo(GlobalLabel* L) + { + return (m_Hash == L->m_Hash) ? strcmp(m_szName, L->m_szName) + : ((m_Hash > L->m_Hash) ? 1 : -1); + } + + //int ComparedTo(GlobalLabel* L) { return strcmp(m_szName,L->m_szName); }; + //int Compare(char* L) { return strcmp(L, m_szNam); }; + //char* NameOf() { return m_szName; }; +}; +//typedef SORTEDARRAY<GlobalLabel> GlobalLabelList; +typedef RBTREE<GlobalLabel> GlobalLabelList; +//typedef FIFO_INDEXED<GlobalLabel> GlobalLabelList; + +class CeeFileGenWriter; +class CeeSection; + +class BinStr; + +/************************************************************************/ +/* represents an object that knows how to report errors back to the user */ + +class ErrorReporter +{ +public: + virtual void error(const char* fmt, ...) = 0; + virtual void warn(const char* fmt, ...) = 0; + virtual void msg(const char* fmt, ...) = 0; +}; + +/**************************************************************************/ +/* represents a switch table before the lables are bound */ + +struct Labels { + Labels(__in __nullterminated char* aLabel, Labels* aNext, bool aIsLabel) : Label(aLabel), Next(aNext), isLabel(aIsLabel) {} + ~Labels() { if(isLabel && Label) delete [] Label; delete Next; } + + char* Label; + Labels* Next; + bool isLabel; +}; + +/**************************************************************************/ +/* descriptor of the structured exception handling construct */ +struct SEH_Descriptor +{ + DWORD sehClause; // catch/filter/finally + DWORD tryFrom; // start of try block + DWORD tryTo; // end of try block + DWORD sehHandler; // start of exception handler + DWORD sehHandlerTo; // end of exception handler + union { + DWORD sehFilter; // start of filter block + mdTypeRef cException; // what to catch + }; + + SEH_Descriptor() + { + memset(this, 0, sizeof(*this)); + } +}; + + +typedef LIFO<char> StringStack; +typedef LIFO<SEH_Descriptor> SEHD_Stack; + +typedef FIFO<Method> MethodList; +//typedef SORTEDARRAY<Method> MethodSortedList; +typedef FIFO<mdToken> TokenList; +/**************************************************************************/ +/* The field, event and property descriptor structures */ + +struct FieldDescriptor +{ + mdTypeDef m_tdClass; + char* m_szName; + DWORD m_dwName; + mdFieldDef m_fdFieldTok; + ULONG m_ulOffset; + char* m_rvaLabel; // if field has RVA associated with it, label for it goes here. + BinStr* m_pbsSig; + Class* m_pClass; + BinStr* m_pbsValue; + BinStr* m_pbsMarshal; + PInvokeDescriptor* m_pPInvoke; + CustomDescrList m_CustomDescrList; + DWORD m_dwAttr; + BOOL m_fNew; + // Security attributes + PermissionDecl* m_pPermissions; + PermissionSetDecl* m_pPermissionSets; + FieldDescriptor() { m_szName = NULL; m_pbsSig = NULL; m_fNew = TRUE; }; + ~FieldDescriptor() { if(m_szName) delete [] m_szName; if(m_pbsSig) delete m_pbsSig; }; +}; +typedef FIFO<FieldDescriptor> FieldDList; + +struct EventDescriptor +{ + mdTypeDef m_tdClass; + char* m_szName; + DWORD m_dwAttr; + mdToken m_tkEventType; + mdToken m_tkAddOn; + mdToken m_tkRemoveOn; + mdToken m_tkFire; + TokenList m_tklOthers; + mdEvent m_edEventTok; + BOOL m_fNew; + CustomDescrList m_CustomDescrList; + ~EventDescriptor() { m_tklOthers.RESET(false); }; +}; +typedef FIFO<EventDescriptor> EventDList; + +struct PropDescriptor +{ + mdTypeDef m_tdClass; + char* m_szName; + DWORD m_dwAttr; + COR_SIGNATURE* m_pSig; + DWORD m_dwCSig; + DWORD m_dwCPlusTypeFlag; + PVOID m_pValue; + DWORD m_cbValue; + mdToken m_tkSet; + mdToken m_tkGet; + TokenList m_tklOthers; + mdProperty m_pdPropTok; + BOOL m_fNew; + CustomDescrList m_CustomDescrList; + ~PropDescriptor() { m_tklOthers.RESET(false); }; +}; +typedef FIFO<PropDescriptor> PropDList; + +struct ImportDescriptor +{ + char* szDllName; +// char szDllName[MAX_FILENAME_LENGTH]; + DWORD dwDllName; + mdModuleRef mrDll; + ImportDescriptor(__in __nullterminated char* sz, DWORD l) + { + if((sz != NULL)&&(l > 0)) + { + szDllName = new char[l+1]; + if(szDllName != NULL) + { + memcpy(szDllName,sz,l); + szDllName[l] = 0; + dwDllName = l; + } + } + else + { + szDllName = NULL; + dwDllName = 0; + } + }; + ~ImportDescriptor() { delete [] szDllName; }; +}; +typedef FIFO<ImportDescriptor> ImportList; + + +/**************************************************************************/ +#include "class.hpp" +typedef LIFO<Class> ClassStack; +typedef FIFO<Class> ClassList; +//typedef SORTEDARRAY<Class> ClassHash; +typedef RBTREE<Class> ClassHash; +//typedef FIFO_INDEXED<Class> ClassHash; + +/**************************************************************************/ +/* Classes to hold lists of security permissions and permission sets. We build + these lists as we find security directives in the input stream and drain + them every time we see a class or method declaration (to which the + security info is attached). */ + +class PermissionDecl +{ +public: + PermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs) + { + m_Action = action; + m_TypeSpec = type; + m_pbsBlob = NULL; + BuildConstructorBlob(action, pairs); + m_Next = NULL; + } + + PermissionDecl(CorDeclSecurity action, mdToken type, BinStr* pbsPairs) + { + m_Action = action; + m_TypeSpec = type; + + m_pbsBlob = new BinStr(); + m_pbsBlob->appendInt16(VAL16(1)); // prolog 0x01 0x00 + m_pbsBlob->appendInt32((int)action); // 4-byte action + if(pbsPairs) // name-value pairs if any + { + if(pbsPairs->length() > 2) + m_pbsBlob->appendFrom(pbsPairs,2); + delete pbsPairs; + } + if(m_pbsBlob->length() == 6) // no pairs added + m_pbsBlob->appendInt16(0); + m_Blob = m_pbsBlob->ptr(); + m_BlobLength = m_pbsBlob->length(); + m_Next = NULL; + } + + ~PermissionDecl() + { + if(m_pbsBlob) delete m_pbsBlob; + else delete [] m_Blob; + } + + CorDeclSecurity m_Action; + mdToken m_TypeSpec; + BYTE *m_Blob; + BinStr *m_pbsBlob; + long m_BlobLength; + PermissionDecl *m_Next; + +private: + void BuildConstructorBlob(CorDeclSecurity action, NVPair *pairs) + { + NVPair *p = pairs; + int count = 0; + int bytes = 8; + int length; + int i; + BYTE *pBlob; + + // Calculate number of name/value pairs and the memory required for the + // custom attribute blob. + while (p) { + BYTE *pVal = (BYTE*)p->Value()->ptr(); + count++; + bytes += 2; // One byte field/property specifier, one byte type code + + length = (int)strlen((const char *)p->Name()->ptr()); + bytes += CPackedLen::Size(length) + length; + + switch (pVal[0]) { + case SERIALIZATION_TYPE_BOOLEAN: + bytes += 1; + break; + case SERIALIZATION_TYPE_I4: + bytes += 4; + break; + case SERIALIZATION_TYPE_STRING: + length = (int)strlen((const char *)&pVal[1]); + bytes += CPackedLen::Size(length) + length; + break; + case SERIALIZATION_TYPE_ENUM: + length = (int)strlen((const char *)&pVal[1]); + bytes += CPackedLen::Size((ULONG)length) + length; + bytes += 4; + break; + } + p = p->Next(); + } + + m_Blob = new BYTE[bytes]; + if(m_Blob==NULL) + { + fprintf(stderr,"\nOut of memory!\n"); + return; + } + + m_Blob[0] = 0x01; // Version + m_Blob[1] = 0x00; + m_Blob[2] = (BYTE)action; // Constructor arg (security action code) + m_Blob[3] = 0x00; + m_Blob[4] = 0x00; + m_Blob[5] = 0x00; + m_Blob[6] = (BYTE)count; // Property/field count + m_Blob[7] = (BYTE)(count >> 8); + + for (i = 0, pBlob = &m_Blob[8], p = pairs; i < count; i++, p = p->Next()) { + BYTE *pVal = (BYTE*)p->Value()->ptr(); + char *szType; + + // Set field/property setter type. + *pBlob++ = SERIALIZATION_TYPE_PROPERTY; + + // Set type code. There's additional info for enums (the enum class + // name). + *pBlob++ = pVal[0]; + if (pVal[0] == SERIALIZATION_TYPE_ENUM) { + szType = (char *)&pVal[1]; + length = (int)strlen(szType); + pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length); + strcpy_s((char *)pBlob, bytes, szType); + pBlob += length; + } + + // Record the field/property name. + length = (int)strlen((const char *)p->Name()->ptr()); + pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length); + strcpy_s((char *)pBlob, bytes-(pBlob-m_Blob), (const char *)p->Name()->ptr()); + pBlob += length; + + // Record the serialized value. + switch (pVal[0]) { + case SERIALIZATION_TYPE_BOOLEAN: + *pBlob++ = pVal[1]; + break; + case SERIALIZATION_TYPE_I4: + *(__int32*)pBlob = *(__int32*)&pVal[1]; + pBlob += 4; + break; + case SERIALIZATION_TYPE_STRING: + length = (int)strlen((const char *)&pVal[1]); + pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length); + strcpy_s((char *)pBlob, bytes-(pBlob-m_Blob), (const char *)&pVal[1]); + pBlob += length; + break; + case SERIALIZATION_TYPE_ENUM: + length = (int)strlen((const char *)&pVal[1]); + // We can have enums with base type of I1, I2 and I4. + switch (pVal[1 + length + 1]) { + case 1: + *(__int8*)pBlob = *(__int8*)&pVal[1 + length + 2]; + pBlob += 1; + break; + case 2: + *(__int16*)pBlob = *(__int16*)&pVal[1 + length + 2]; + pBlob += 2; + break; + case 4: + *(__int32*)pBlob = *(__int32*)&pVal[1 + length + 2]; + pBlob += 4; + break; + default: + _ASSERTE(!"Invalid enum size"); + } + break; + } + + } + + _ASSERTE((pBlob - m_Blob) == bytes); + + m_BlobLength = (long)bytes; + } +}; + +class PermissionSetDecl +{ +public: + PermissionSetDecl(CorDeclSecurity action, BinStr *value) + { + m_Action = action; + m_Value = value; + m_Next = NULL; + } + + ~PermissionSetDecl() + { + delete m_Value; + } + + CorDeclSecurity m_Action; + BinStr *m_Value; + PermissionSetDecl *m_Next; +}; + +struct VTFEntry +{ + char* m_szLabel; + WORD m_wCount; + WORD m_wType; + VTFEntry(WORD wCount, WORD wType, __in __nullterminated char* szLabel) { m_wCount = wCount; m_wType = wType; m_szLabel = szLabel; } + ~VTFEntry() { delete m_szLabel; } +}; +typedef FIFO<VTFEntry> VTFList; + +struct EATEntry +{ + DWORD dwStubRVA; + DWORD dwOrdinal; + char* szAlias; +}; +typedef FIFO<EATEntry> EATList; + +struct DocWriter +{ + char* Name; + ISymUnmanagedDocumentWriter* pWriter; + DocWriter() { Name=NULL; pWriter=NULL; }; + ~DocWriter() { delete [] Name; if(pWriter) pWriter->Release();}; +}; +typedef FIFO<DocWriter> DocWriterList; +/**************************************************************************/ +/* The assembler object does all the code generation (dealing with meta-data) + writing a PE file etc etc. But does NOT deal with syntax (that is what + AsmParse is for). Thus the API below is how AsmParse 'controls' the + Assember. Note that the Assembler object does know about the + AsmParse object (that is Assember is more fundamental than AsmParse) */ +struct Instr +{ + int opcode; + unsigned linenum; + unsigned column; + unsigned linenum_end; + unsigned column_end; + unsigned pc; + ISymUnmanagedDocumentWriter* pWriter; + Document* pOwnerDocument; +}; +#define INSTR_POOL_SIZE 16 + +// For code folding: +struct MethodBody +{ + BinStr* pbsBody; + unsigned RVA; + BYTE* pCode; +}; +typedef FIFO<MethodBody> MethodBodyList; + +struct Clockwork +{ + DWORD cBegin; + DWORD cEnd; + DWORD cParsBegin; + DWORD cParsEnd; + DWORD cMDInitBegin; + DWORD cMDInitEnd; + DWORD cMDEmitBegin; + DWORD cMDEmitEnd; + DWORD cMDEmit1; + DWORD cMDEmit2; + DWORD cMDEmit3; + DWORD cMDEmit4; + DWORD cRef2DefBegin; + DWORD cRef2DefEnd; + DWORD cFilegenBegin; + DWORD cFilegenEnd; +}; + +struct TypeDefDescr +{ + char* m_szName; + union + { + BinStr* m_pbsTypeSpec; + CustomDescr* m_pCA; + }; + mdToken m_tkTypeSpec; + TypeDefDescr(__in_opt __nullterminated char *pszName, BinStr* pbsTypeSpec, mdToken tkTypeSpec) + { + m_szName = pszName; + m_pbsTypeSpec = pbsTypeSpec; + m_tkTypeSpec = tkTypeSpec; + }; + ~TypeDefDescr() { delete [] m_szName; delete m_pbsTypeSpec; }; + int ComparedTo(TypeDefDescr* T) { return strcmp(m_szName,T->m_szName); }; + //int Compare(char* T) { return strcmp(T,m_szName); }; +}; +typedef SORTEDARRAY<TypeDefDescr> TypeDefDList; + +struct Indx +{ + void* table[128]; + Indx() { memset(table,0,sizeof(table)); }; + ~Indx() + { + for(int i = 1; i < 128; i++) delete ((Indx*)(table[i])); + }; + void IndexString(__in_z __in char* psz, void* pkywd) + { + int i = (int) *psz; + if(i == 0) + table[0] = pkywd; + else + { + _ASSERTE((i > 0)&&(i <= 127)); + Indx* pInd = (Indx*)(table[i]); + if(pInd == NULL) + { + pInd = new Indx; + _ASSERTE(pInd); + table[i] = pInd; + } + pInd->IndexString(psz+1,pkywd); + } + } + void* FindString(__in __nullterminated char* psz) + { + if(*psz > 0) + { + unsigned char uch = (unsigned char) *psz; + if(table[uch] != NULL) + return ((Indx*)(table[uch]))->FindString(psz+1); + } + else if(*psz == 0) return table[0]; + return NULL; + } +}; + +typedef enum { + CLASSIC, // default - classic PDB format, currently not supported for CoreCLR + PORTABLE, + // EMBEDDED // for future use +} PdbFormat; + +class Assembler { +public: + Assembler(); + ~Assembler(); + //-------------------------------------------------------- + GlobalLabelList m_lstGlobalLabel; + GlobalFixupList m_lstGlobalFixup; + + LabelList m_lstLabel; + + Class * m_pModuleClass; + ClassList m_lstClass; + ClassHash m_hshClass; + + Indx indxKeywords; + + BYTE * m_pOutputBuffer; + BYTE * m_pCurOutputPos; + BYTE * m_pEndOutputPos; + + + DWORD m_CurPC; + BOOL m_fStdMapping; + BOOL m_fDisplayTraceOutput; + BOOL m_fInitialisedMetaData; + BOOL m_fAutoInheritFromObject; + BOOL m_fReportProgress; + BOOL m_fIsMscorlib; + BOOL m_fTolerateDupMethods; + BOOL m_fENCMode; + BOOL m_fOptimize; + mdToken m_tkSysObject; + mdToken m_tkSysString; + mdToken m_tkSysValue; + mdToken m_tkSysEnum; + BOOL m_fDidCoInitialise; + + IMetaDataDispenserEx2 *m_pDisp; + IMetaDataEmit3 *m_pEmitter; + ICeeFileGen *m_pCeeFileGen; + IMetaDataImport2 *m_pImporter; // Import interface. + HCEEFILE m_pCeeFile; + HCEESECTION m_pGlobalDataSection; + HCEESECTION m_pILSection; + HCEESECTION m_pTLSSection; + HCEESECTION m_pCurSection; // The section EmitData* things go to + + AsmMan* m_pManifest; + + char m_szScopeName[MAX_SCOPE_LENGTH]; + char *m_szNamespace; //[MAX_NAMESPACE_LENGTH]; + char *m_szFullNS; //[MAX_NAMESPACE_LENGTH]; + unsigned m_ulFullNSLen; + + WCHAR *m_wzMetadataVersion; + + StringStack m_NSstack; + mdTypeSpec m_crExtends; + + // char m_szExtendsClause[MAX_CLASSNAME_LENGTH]; + + // The (resizable) array of "implements" types + mdToken *m_crImplList; + int m_nImplList; + int m_nImplListSize; + + TyParList *m_TyParList; + + Method *m_pCurMethod; + Class *m_pCurClass; + ClassStack m_ClassStack; // for nested classes + Class *dummyClass; // for FindCreateClass + + // moved to Class + //MethodList m_MethodList; + + BOOL m_fCPlusPlus; + BOOL m_fWindowsCE; + BOOL m_fDLL; + BOOL m_fOBJ; + BOOL m_fEntryPointPresent; + BOOL m_fHaveFieldsWithRvas; + BOOL m_fFoldCode; + DWORD m_dwMethodsFolded; + + state_t m_State; + + BinStr* m_pbsMD; + + Instr m_Instr[INSTR_POOL_SIZE]; // 16 + inline Instr* GetInstr() + { + int i; + for(i=0; (i<INSTR_POOL_SIZE)&&(m_Instr[i].opcode != -1); i++); + if(i<INSTR_POOL_SIZE) return &m_Instr[i]; + report->error("Instruction pool exhausted: source contains invalid instructions\n"); + return NULL; + } + // Labels, fixups and IL fixups are defined in Method.hpp,.cpp + void AddLabel(DWORD CurPC, __in __nullterminated char *pszName); + void AddDeferredFixup(__in __nullterminated char *pszLabel, BYTE *pBytes, DWORD RelativeToPC, BYTE FixupSize); + void AddDeferredILFixup(ILFixupType Kind); + void AddDeferredILFixup(ILFixupType Kind, GlobalFixup *GFixup); + void DoDeferredILFixups(Method* pMethod); + BOOL DoFixups(Method* pMethod); + //-------------------------------------------------------------------------------- + void ClearImplList(void); + void AddToImplList(mdToken); + void ClearBoundList(void); + //-------------------------------------------------------------------------------- + BOOL Init(BOOL generatePdb, PdbFormat pdbFormat); + void ProcessLabel(__in_z __in char *pszName); + GlobalLabel *FindGlobalLabel(LPCUTF8 pszName); + GlobalFixup *AddDeferredGlobalFixup(__in __nullterminated char *pszLabel, BYTE* reference); + //void AddDeferredDescrFixup(__in __nullterminated char *pszLabel); + BOOL DoGlobalFixups(); + BOOL DoDescrFixups(); + OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen); + BOOL AddMethod(Method *pMethod); + void SetTLSSection() { m_pCurSection = m_pTLSSection; } + void SetILSection() { m_pCurSection = m_pILSection; } + void SetDataSection() { m_pCurSection = m_pGlobalDataSection; } + BOOL EmitMethod(Method *pMethod); + BOOL EmitMethodBody(Method* pMethod, BinStr* pbsOut); + BOOL EmitClass(Class *pClass); + HRESULT CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename); + HRESULT CreateTLSDirectory(); + HRESULT CreateDebugDirectory(); + HRESULT InitMetaData(); + Class *FindCreateClass(__in __nullterminated const char *pszFQN); + BOOL EmitFieldRef(__in_z __in char *pszArg, int opcode); + BOOL EmitSwitchData(__in_z __in char *pszArg); + mdToken ResolveClassRef(mdToken tkResScope, __in __nullterminated const char *pszClassName, Class** ppClass); + mdToken ResolveTypeSpec(BinStr* typeSpec); + mdToken GetBaseAsmRef(); + mdToken GetAsmRef(__in __nullterminated const char* szName); + mdToken GetModRef(__in __nullterminated char* szName); + mdToken GetInterfaceImpl(mdToken tsClass, mdToken tsInterface); + char* ReflectionNotation(mdToken tk); + HRESULT ConvLocalSig(__in char* localsSig, CQuickBytes* corSig, DWORD* corSigLen, BYTE*& localTypes); + DWORD GetCurrentILSectionOffset(); + BOOL EmitCALLISig(__in char *p); + void AddException(DWORD pcStart, DWORD pcEnd, DWORD pcHandler, DWORD pcHandlerTo, mdTypeRef crException, BOOL isFilter, BOOL isFault, BOOL isFinally); + state_t CheckLocalTypeConsistancy(int instr, unsigned arg); + state_t AddGlobalLabel(__in __nullterminated char *pszName, HCEESECTION section); + void SetDLL(BOOL); + void SetOBJ(BOOL); + void ResetForNextMethod(); + void ResetLineNumbers(); + void SetStdMapping(BOOL val = TRUE) { m_fStdMapping = val; }; + + //-------------------------------------------------------------------------------- + BOOL isShort(unsigned instr) { return ((OpcodeInfo[instr].Type & 16) != 0); }; + unsigned ShortOf(unsigned opcode); + void SetErrorReporter(ErrorReporter* aReport) { report = aReport; if(m_pManifest) m_pManifest->SetErrorReporter(aReport); } + + void StartNameSpace(__in __nullterminated char* name); + void EndNameSpace(); + void StartClass(__in __nullterminated char* name, DWORD attr, TyParList *typars); + DWORD CheckClassFlagsIfNested(Class* pEncloser, DWORD attr); + void AddClass(); + void EndClass(); + void StartMethod(__in __nullterminated char* name, BinStr* sig, CorMethodAttr flags, BinStr* retMarshal, DWORD retAttr, TyParList *typars = NULL); + void EndMethod(); + + void AddField(__inout_z __inout char* name, BinStr* sig, CorFieldAttr flags, __in __nullterminated char* rvaLabel, BinStr* pVal, ULONG ulOffset); + BOOL EmitField(FieldDescriptor* pFD); + void EmitByte(int val); + //void EmitTry(enum CorExceptionFlag kind, char* beginLabel, char* endLabel, char* handleLabel, char* filterOrClass); + void EmitMaxStack(unsigned val); + void EmitLocals(BinStr* sig); + void EmitEntryPoint(); + void EmitZeroInit(); + void SetImplAttr(unsigned short attrval); + + // Emits zeros if the buffer parameter is NULL. + void EmitData(__in_opt void *buffer, unsigned len); + + void EmitDD(__in __nullterminated char *str); + void EmitDataString(BinStr* str); + + void EmitInstrVar(Instr* instr, int var); + void EmitInstrVarByName(Instr* instr, __in __nullterminated char* label); + void EmitInstrI(Instr* instr, int val); + void EmitInstrI8(Instr* instr, __int64* val); + void EmitInstrR(Instr* instr, double* val); + void EmitInstrBrOffset(Instr* instr, int offset); + void EmitInstrBrTarget(Instr* instr, __in __nullterminated char* label); + mdToken MakeMemberRef(mdToken typeSpec, __in __nullterminated char* name, BinStr* sig); + mdToken MakeMethodSpec(mdToken tkParent, BinStr* sig); + void SetMemberRefFixup(mdToken tk, unsigned opcode_len); + mdToken MakeTypeRef(mdToken tkResScope, LPCUTF8 szFullName); + void EmitInstrStringLiteral(Instr* instr, BinStr* literal, BOOL ConvertToUnicode, BOOL Swap = FALSE); + void EmitInstrSig(Instr* instr, BinStr* sig); + void EmitInstrSwitch(Instr* instr, Labels* targets); + void EmitLabel(__in __nullterminated char* label); + void EmitDataLabel(__in __nullterminated char* label); + + unsigned OpcodeLen(Instr* instr); //returns opcode length + // Emit just the opcode (no parameters to the instruction stream. + void EmitOpcode(Instr* instr); + + // Emit primitive types to the instruction stream. + void EmitBytes(BYTE*, unsigned len); + + ErrorReporter* report; + + BOOL EmitFieldsMethods(Class* pClass); + BOOL EmitEventsProps(Class* pClass); + + // named args/vars paraphernalia: +public: + void addArgName(__in_opt __nullterminated char *szNewName, BinStr* pbSig, BinStr* pbMarsh, DWORD dwAttr) + { + if(pbSig && (*(pbSig->ptr()) == ELEMENT_TYPE_VOID)) + report->error("Illegal use of type 'void'\n"); + if(m_lastArgName) + { + m_lastArgName->pNext = new ARG_NAME_LIST(m_lastArgName->nNum+1,szNewName,pbSig,pbMarsh,dwAttr); + m_lastArgName = m_lastArgName->pNext; + } + else + { + m_lastArgName = new ARG_NAME_LIST(0,szNewName,pbSig,pbMarsh,dwAttr); + m_firstArgName = m_lastArgName; + } + }; + ARG_NAME_LIST *getArgNameList(void) + { ARG_NAME_LIST *pRet = m_firstArgName; m_firstArgName=NULL; m_lastArgName=NULL; return pRet;}; + // Added because recursive destructor of ARG_NAME_LIST may overflow the system stack + void delArgNameList(ARG_NAME_LIST *pFirst) + { + ARG_NAME_LIST *pArgList=pFirst, *pArgListNext; + for(; pArgList; pArgListNext=pArgList->pNext, + delete pArgList, + pArgList=pArgListNext); + }; + + ARG_NAME_LIST *findArg(ARG_NAME_LIST *pFirst, int num) + { + ARG_NAME_LIST *pAN; + for(pAN=pFirst; pAN; pAN = pAN->pNext) + { + if(pAN->nNum == num) return pAN; + } + return NULL; + }; + ARG_NAME_LIST *m_firstArgName; + ARG_NAME_LIST *m_lastArgName; + void ResetArgNameList(); + + // Structured exception handling paraphernalia: +public: + SEH_Descriptor *m_SEHD; // current descriptor ptr + void NewSEHDescriptor(void); //sets m_SEHD + void SetTryLabels(__in __nullterminated char * szFrom, __in __nullterminated char *szTo); + void SetFilterLabel(__in __nullterminated char *szFilter); + void SetCatchClass(mdToken catchClass); + void SetHandlerLabels(__in __nullterminated char *szHandlerFrom, __in __nullterminated char *szHandlerTo); + void EmitTry(void); //uses m_SEHD + +//private: + SEHD_Stack m_SEHDstack; + + // Events and Properties paraphernalia: +public: + void EndEvent(void); //emits event definition + void EndProp(void); //emits property definition + void ResetEvent(__inout_z __inout char * szName, mdToken typeSpec, DWORD dwAttr); + void ResetProp(__inout_z __inout char * szName, BinStr* bsType, DWORD dwAttr, BinStr* bsValue); + void SetEventMethod(int MethodCode, mdToken tk); + void SetPropMethod(int MethodCode, mdToken tk); + BOOL EmitEvent(EventDescriptor* pED); // impl. in ASSEM.CPP + BOOL EmitProp(PropDescriptor* pPD); // impl. in ASSEM.CPP + EventDescriptor* m_pCurEvent; + PropDescriptor* m_pCurProp; + +private: + MemberRefDList m_LocalMethodRefDList; + MemberRefDList m_LocalFieldRefDList; + LocalMemberRefFixupList m_LocalMemberRefFixupList; + MethodBodyList m_MethodBodyList; + MemberRefDList m_MethodSpecList; +public: + HRESULT ResolveLocalMemberRefs(); + HRESULT DoLocalMemberRefFixups(); + mdToken ResolveLocalMemberRef(mdToken tok); + + // PInvoke paraphernalia +public: + PInvokeDescriptor* m_pPInvoke; + ImportList m_ImportList; + void SetPinvoke(BinStr* DllName, int Ordinal, BinStr* Alias, int Attrs); + HRESULT EmitPinvokeMap(mdToken tk, PInvokeDescriptor* pDescr); + ImportDescriptor* EmitImport(BinStr* DllName); + void EmitImports(); + + // Debug metadata paraphernalia +public: + ISymUnmanagedWriter* m_pSymWriter; + ISymUnmanagedDocumentWriter* m_pSymDocument; + DocWriterList m_DocWriterList; + ULONG m_ulCurLine; // set by Parser + ULONG m_ulCurColumn; // set by Parser + ULONG m_ulLastDebugLine; + ULONG m_ulLastDebugColumn; + ULONG m_ulLastDebugLineEnd; + ULONG m_ulLastDebugColumnEnd; + DWORD m_dwIncludeDebugInfo; + BOOL m_fGeneratePDB; + char m_szSourceFileName[MAX_FILENAME_LENGTH*3+1]; + WCHAR m_wzOutputFileName[MAX_FILENAME_LENGTH]; + WCHAR m_wzSourceFileName[MAX_FILENAME_LENGTH]; + GUID m_guidLang; + GUID m_guidLangVendor; + GUID m_guidDoc; + + // Portable PDB paraphernalia +public: + PdbFormat m_pdbFormat; + PortablePdbWriter* m_pPortablePdbWriter; + char m_szPdbFileName[MAX_FILENAME_LENGTH * 3 + 1]; + WCHAR m_wzPdbFileName[MAX_FILENAME_LENGTH]; + + // Sets the pdb file name of the assembled file. + void SetPdbFileName(__in __nullterminated char* szName); + // Saves the pdb file. + HRESULT SavePdbFile(); + // Checks whether pdb generation is portable + BOOL IsPortablePdb(); + + // Security paraphernalia +public: + void AddPermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs) + { + PermissionDecl *decl = new PermissionDecl(action, type, pairs); + if(decl==NULL) + { + report->error("\nOut of memory!\n"); + return; + } + if (m_pCurMethod) { + decl->m_Next = m_pCurMethod->m_pPermissions; + m_pCurMethod->m_pPermissions = decl; + } else if (m_pCurClass) { + decl->m_Next = m_pCurClass->m_pPermissions; + m_pCurClass->m_pPermissions = decl; + } else if (m_pManifest && m_pManifest->m_pAssembly) { + decl->m_Next = m_pManifest->m_pAssembly->m_pPermissions; + m_pManifest->m_pAssembly->m_pPermissions = decl; + } else { + report->error("Cannot declare security permissions without the owner\n"); + delete decl; + } + }; + + void AddPermissionDecl(CorDeclSecurity action, mdToken type, BinStr *pbsPairs) + { + PermissionDecl *decl = new PermissionDecl(action, type, pbsPairs); + if(decl==NULL) + { + report->error("\nOut of memory!\n"); + return; + } + if (m_pCurMethod) { + decl->m_Next = m_pCurMethod->m_pPermissions; + m_pCurMethod->m_pPermissions = decl; + } else if (m_pCurClass) { + decl->m_Next = m_pCurClass->m_pPermissions; + m_pCurClass->m_pPermissions = decl; + } else if (m_pManifest && m_pManifest->m_pAssembly) { + decl->m_Next = m_pManifest->m_pAssembly->m_pPermissions; + m_pManifest->m_pAssembly->m_pPermissions = decl; + } else { + report->error("Cannot declare security permissions without the owner\n"); + delete decl; + } + }; + + void AddPermissionSetDecl(CorDeclSecurity action, BinStr *value) + { + PermissionSetDecl *decl = new PermissionSetDecl(action, value); + if(decl==NULL) + { + report->error("\nOut of memory!\n"); + return; + } + if (m_pCurMethod) { + decl->m_Next = m_pCurMethod->m_pPermissionSets; + m_pCurMethod->m_pPermissionSets = decl; + } else if (m_pCurClass) { + decl->m_Next = m_pCurClass->m_pPermissionSets; + m_pCurClass->m_pPermissionSets = decl; + } else if (m_pManifest && m_pManifest->m_pAssembly) { + decl->m_Next = m_pManifest->m_pAssembly->m_pPermissionSets; + m_pManifest->m_pAssembly->m_pPermissionSets = decl; + } else { + report->error("Cannot declare security permission sets without the owner\n"); + delete decl; + } + }; + void EmitSecurityInfo(mdToken token, + PermissionDecl* pPermissions, + PermissionSetDecl*pPermissionSets); + BinStr* EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps); + + HRESULT AllocateStrongNameSignature(); + + // Custom values paraphernalia: +public: + mdToken m_tkCurrentCVOwner; + CustomDescrList* m_pCustomDescrList; + CustomDescrListStack m_CustomDescrListStack; + CustomDescrList m_CustomDescrList; + + void DefineCV(CustomDescr* pCD) + { + if(pCD) + { + ULONG cTemp = 0; + void * pBlobBody = NULL; + mdToken cv; + mdToken tkOwnerType, tkTypeType = TypeFromToken(pCD->tkType); + + if((tkTypeType != 0x99000000)&&(tkTypeType != 0x98000000)) + { + tkOwnerType = TypeFromToken(pCD->tkOwner); + if((tkOwnerType != 0x99000000)&&(tkOwnerType != 0x98000000)) + { + if(pCD->pBlob) + { + pBlobBody = (void *)(pCD->pBlob->ptr()); + cTemp = pCD->pBlob->length(); + } + if (pCD->tkInterfacePair) + { + pCD->tkOwner = GetInterfaceImpl(pCD->tkOwner, pCD->tkInterfacePair); + } + m_pEmitter->DefineCustomAttribute(pCD->tkOwner,pCD->tkType,pBlobBody,cTemp,&cv); + + delete pCD; + return; + } + } + m_CustomDescrList.PUSH(pCD); + } + }; + void EmitCustomAttributes(mdToken tok, CustomDescrList* pCDL) + { + CustomDescr *pCD; + if(pCDL == NULL || RidFromToken(tok)==0) return; + while((pCD = pCDL->POP())) + { + pCD->tkOwner = tok; + DefineCV(pCD); + } + }; + void EmitUnresolvedCustomAttributes(); // implementation: writer.cpp + // VTable blob (if any) +public: + BinStr *m_pVTable; + // Field marshaling + BinStr *m_pMarshal; + // VTable fixup list + VTFList m_VTFList; + // Export Address Table entries list + EATList m_EATList; + HRESULT CreateExportDirectory(); + DWORD EmitExportStub(DWORD dwVTFSlotRVA); + + // Method implementation paraphernalia: +private: + MethodImplDList m_MethodImplDList; +public: + void AddMethodImpl(mdToken tkImplementedTypeSpec, __in __nullterminated char* szImplementedName, BinStr* pImplementedSig, + mdToken tkImplementingTypeSpec, __in_opt __nullterminated char* szImplementingName, BinStr* pImplementingSig); + BOOL EmitMethodImpls(); + // lexical scope handling paraphernalia: + void EmitScope(Scope* pSCroot); // struct Scope - see Method.hpp + // source file name paraphernalia + BOOL m_fSourceFileSet; + void SetSourceFileName(__in __nullterminated char* szName); + void SetSourceFileName(BinStr* pbsName); + // header flags + DWORD m_dwSubsystem; + WORD m_wSSVersionMajor; + WORD m_wSSVersionMinor; + DWORD m_dwComImageFlags; + DWORD m_dwFileAlignment; + ULONGLONG m_stBaseAddress; + size_t m_stSizeOfStackReserve; + DWORD m_dwCeeFileFlags; + WORD m_wMSVmajor; + WORD m_wMSVminor; + BOOL m_fAppContainer; + BOOL m_fHighEntropyVA; + + // Former globals + WCHAR *m_wzResourceFile; + WCHAR *m_wzKeySourceName; + bool OnErrGo; + void SetCodePage(unsigned val) { g_uCodePage = val; }; + Clockwork* bClock; + void SetClock(Clockwork* val) { bClock = val; }; + // ENC paraphernalia + HRESULT InitMetaDataForENC(__in __nullterminated WCHAR* wzOrigFileName, BOOL generatePdb, PdbFormat pdbFormat); + BOOL EmitFieldsMethodsENC(Class* pClass); + BOOL EmitEventsPropsENC(Class* pClass); + HRESULT CreateDeltaFiles(__in __nullterminated WCHAR *pwzOutputFilename); + + // Syntactic sugar paraphernalia +private: + TypeDefDList m_TypeDefDList; +public: + void AddTypeDef(BinStr* pbsTypeSpec, __in_z __in char* szName) + { + m_TypeDefDList.PUSH(new TypeDefDescr(szName, pbsTypeSpec, ResolveTypeSpec(pbsTypeSpec))); + }; + void AddTypeDef(mdToken tkTypeSpec, __in_z __in char* szName) + { + m_TypeDefDList.PUSH(new TypeDefDescr(szName, NULL, tkTypeSpec)); + }; + void AddTypeDef(CustomDescr* pCA, __in_z __in char* szName) + { + TypeDefDescr* pNew = new TypeDefDescr(szName,NULL,mdtCustomAttribute); + pNew->m_pCA = pCA; + m_TypeDefDList.PUSH(pNew); + }; + TypeDefDescr* FindTypeDef(__in_z __in char* szName) + { + CHECK_LOCAL_STATIC_VAR(static TypeDefDescr X(NULL, NULL, 0)); + + X.m_szName = szName; + TypeDefDescr* Y = m_TypeDefDList.FIND(&X); + X.m_szName = NULL; // to avoid deletion when X goes out of scope + return Y; + //return m_TypeDefDList.FIND(szName); + }; + unsigned NumTypeDefs() {return m_TypeDefDList.COUNT();}; +private: + HRESULT GetCAName(mdToken tkCA, __out LPWSTR *ppszName); + +public: + void RecordTypeConstraints(GenericParamConstraintList* pGPCList, int numTyPars, TyParDescr* tyPars); + + void AddGenericParamConstraint(int index, char * pStrGenericParam, mdToken tkTypeConstraint); + + void CheckAddGenericParamConstraint(GenericParamConstraintList* pGPCList, int index, mdToken tkTypeConstraint, bool isParamDirective); + + void EmitGenericParamConstraints(int numTyPars, TyParDescr* pTyPars, mdToken tkOwner, GenericParamConstraintList* pGPCL); + +}; + +#endif // Assember_h + +#ifdef _MSC_VER +#pragma warning(default : 4640) +#endif + + diff --git a/src/coreclr/ilasm/binstr.h b/src/coreclr/ilasm/binstr.h new file mode 100644 index 00000000000..d0e8da1e490 --- /dev/null +++ b/src/coreclr/ilasm/binstr.h @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +/**************************************************************************/ +/* a binary string (blob) class */ + +#ifndef BINSTR_H +#define BINSTR_H + +#include <string.h> // for memmove, memcpy ... + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow" +#endif + +class BinStr { +public: + BinStr() { len = 0L; max = 8L; ptr_ = buff; } + BinStr(BYTE* pb, DWORD cb) { len = cb; max = cb+8; ptr_ = pb; } + ~BinStr() { if (ptr_ != buff) delete [] ptr_; } + + void insertInt8(int val) { if (len >= max) Realloc(); memmove(ptr_+1, ptr_, len); *ptr_ = val; len++; } + void insertInt32(int val) { if (len + 4 > max) Realloc(); memmove(ptr_+4, ptr_, len); SET_UNALIGNED_32(&ptr_[0], val); len+=4; } + void appendInt8(int val) { if (len >= max) Realloc(); ptr_[len++] = val; } + void appendInt16(int val) { if (len + 2 > max) Realloc(); SET_UNALIGNED_16(&ptr_[len], val); len += 2; } + void appendInt32(int val) { if (len + 4 > max) Realloc(); SET_UNALIGNED_32(&ptr_[len], val); len += 4; } + void appendInt64(__int64 *pval) { if (len + 8 > max) Realloc(8); SET_UNALIGNED_64(&ptr_[len],(*pval)); len += 8; } + unsigned __int8* getBuff(unsigned size) { + if (len + size > max) Realloc(size); + _ASSERTE(len + size <= max); + unsigned __int8* ret = &ptr_[len]; + len += size; + return(ret); + } + void append(BinStr* str) { + memcpy(getBuff(str->length()), str->ptr(), str->length()); + } + + void appendFrom(BinStr* str, unsigned ix) { + _ASSERTE(str->length() >= ix); + if (str->length() >= ix) + { + memcpy(getBuff(str->length()-ix), str->ptr()+ix, str->length()-ix); + } + } + + void remove(unsigned size) { _ASSERTE(len >= size); len -= size; } + + unsigned __int8* ptr() { return(ptr_); } + unsigned length() { return(len); } + +private: + void Realloc(unsigned atLeast = 4) { + max = max * 2; + if (max < atLeast + len) + max = atLeast + len; + _ASSERTE(max >= len + atLeast); + unsigned __int8* newPtr = new unsigned __int8[max]; + memcpy(newPtr, ptr_, len); + if (ptr_ != buff) delete [] ptr_; + ptr_ = newPtr; + } + +private: + unsigned len; + unsigned max; + unsigned __int8 *ptr_; + unsigned __int8 buff[8]; +}; +BinStr* BinStrToUnicode(BinStr* pSource, bool Swap = false); +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +#endif + diff --git a/src/coreclr/ilasm/class.hpp b/src/coreclr/ilasm/class.hpp new file mode 100644 index 00000000000..b8675895700 --- /dev/null +++ b/src/coreclr/ilasm/class.hpp @@ -0,0 +1,119 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// class.hpp +// + +#ifndef _CLASS_HPP +#define _CLASS_HPP + +class PermissionDecl; +class PermissionSetDecl; + +extern unsigned int g_uCodePage; +extern WCHAR wzUniBuf[]; + +class Class +{ +public: + Class * m_pEncloser; + LPCUTF8 m_szFQN; + DWORD m_dwFQN; + unsigned m_Hash; + mdTypeDef m_cl; + mdTypeRef m_crExtends; + mdTypeRef *m_crImplements; + TyParDescr* m_TyPars; + DWORD m_NumTyPars; + GenericParamConstraintList m_GPCList; + + DWORD m_Attr; + DWORD m_dwNumInterfaces; + DWORD m_dwNumFieldsWithOffset; + PermissionDecl* m_pPermissions; + PermissionSetDecl* m_pPermissionSets; + ULONG m_ulSize; + ULONG m_ulPack; + BOOL m_bIsMaster; + BOOL m_fNew; + BOOL m_fNewMembers; + + MethodList m_MethodList; + //MethodSortedList m_MethodSList; + FieldDList m_FieldDList; + EventDList m_EventDList; + PropDList m_PropDList; + CustomDescrList m_CustDList; + + Class(LPCUTF8 pszFQN) + { + m_pEncloser = NULL; + m_cl = mdTypeDefNil; + m_crExtends = mdTypeRefNil; + m_NumTyPars = 0; + m_TyPars = NULL; + m_dwNumInterfaces = 0; + m_dwNumFieldsWithOffset = 0; + m_crImplements = NULL; + m_szFQN = pszFQN; + m_dwFQN = pszFQN ? (DWORD)strlen(pszFQN) : 0; + m_Hash = pszFQN ? hash((const BYTE*)pszFQN, m_dwFQN, 10) : 0; + + m_Attr = tdPublic; + + m_bIsMaster = TRUE; + m_fNew = TRUE; + + m_pPermissions = NULL; + m_pPermissionSets = NULL; + + m_ulPack = 0; + m_ulSize = 0xFFFFFFFF; + } + + ~Class() + { + delete [] m_szFQN; + delete [] m_crImplements; + delete [] m_TyPars; + } + + int FindTyPar(LPCWSTR wz) + { + int i,retval=-1; + for(i=0; i < (int)m_NumTyPars; i++) + { + if(!wcscmp(wz,m_TyPars[i].Name())) + { + retval = i; + break; + } + } + return retval; + }; + int FindTyPar(LPCUTF8 sz) + { + if(sz) + { + wzUniBuf[0] = 0; + WszMultiByteToWideChar(g_uCodePage,0,sz,-1,wzUniBuf,dwUniBuf); + return FindTyPar(wzUniBuf); + } + else return -1; + }; + int ComparedTo(Class* T) + { + if (m_Hash == T->m_Hash) + { + // Properly handle hash conflict + return (m_szFQN == T->m_szFQN) ? 0 : strcmp(m_szFQN, T->m_szFQN); + } else + { + return (m_Hash > T->m_Hash) ? 1 : -1; + } + } +}; + + +#endif /* _CLASS_HPP */ + diff --git a/src/coreclr/ilasm/extractGrammar.pl b/src/coreclr/ilasm/extractGrammar.pl new file mode 100644 index 00000000000..0c2019ef98b --- /dev/null +++ b/src/coreclr/ilasm/extractGrammar.pl @@ -0,0 +1,59 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# +# a simple script that extracts the grammar from a yacc file + +undef $/; # read in the whole file +my $file = <>; +$file =~ /^(.*)%%(.*)%%/s || die "Could not find %% markers"; +my $prefix = $1; +my $grammar = $2; + +#my $line; +#foreach $line (split /\n/s, $prefix) { +# if ($line =~ /^\s*%token/) { +# $line =~ s/\s*<.*>//g; +# print "$line\n" +# } +#} + + # remove any text in {} +while ($grammar =~ s/\s*([^']){[^{}]*}/$1/sg) {} + + # change keyword identifiers into the string they represent +$grammar =~ s/\b([A-Z0-9_]+)_\b/'\L$1\E'/sg; + + # change assembler directives into their string +$grammar =~ s/\b_([A-Z0-9]+)\b/'\L.$1\E'/sg; + + # do the special punctuation by hand +$grammar =~ s/\bELIPSIS\b/'...'/sg; +$grammar =~ s/\bDCOLON\b/'::'/sg; + +#<STRIP> + # remove TODO comments +$grammar =~ s/\n\s*\/\*[^\n]*TODO[^\n]*\*\/\s*\n/\n/sg; +#</STRIP> + +print "Lexical tokens\n"; +print " ID - C style alphaNumeric identifier (e.g. Hello_There2)\n"; +print " DOTTEDNAME - Sequence of dot-separated IDs (e.g. System.Object)\n"; +print " QSTRING - C style quoted string (e.g. \"hi\\n\")\n"; +print " SQSTRING - C style singlely quoted string(e.g. 'hi')\n"; +print " INT32 - C style 32 bit integer (e.g. 235, 03423, 0x34FFF)\n"; +print " INT64 - C style 64 bit integer (e.g. -2353453636235234, 0x34FFFFFFFFFF)\n"; +print " FLOAT64 - C style floating point number (e.g. -0.2323, 354.3423, 3435.34E-5)\n"; +print " INSTR_* - IL instructions of a particular class (see opcode.def).\n"; +print " HEXBYTE - 1- or 2-digit hexadecimal number (e.g., A2, F0).\n"; +print "Auxiliary lexical tokens\n"; +print " TYPEDEF_T - Aliased class (TypeDef or TypeRef).\n"; +print " TYPEDEF_M - Aliased method.\n"; +print " TYPEDEF_F - Aliased field.\n"; +print " TYPEDEF_TS - Aliased type specification (TypeSpec).\n"; +print " TYPEDEF_MR - Aliased field/method reference (MemberRef).\n"; +print " TYPEDEF_CA - Aliased Custom Attribute.\n"; +print "----------------------------------------------------------------------------------\n"; +print "START : decls\n"; +print " ;"; + +print $grammar; diff --git a/src/coreclr/ilasm/grammar_after.cpp b/src/coreclr/ilasm/grammar_after.cpp new file mode 100644 index 00000000000..1fcb1bf9049 --- /dev/null +++ b/src/coreclr/ilasm/grammar_after.cpp @@ -0,0 +1,1695 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +/********************************************************************************/ +/* Code goes here */ + +/********************************************************************************/ +extern int yyparse(); + +struct Keywords { + const char* name; + unsigned short token; + unsigned short tokenVal;// this holds the instruction enumeration for those keywords that are instrs + size_t stname; +}; + +#define NO_VALUE ((unsigned short)-1) // The token has no value + +static Keywords keywords[] = { +// Attention! Because of aliases, the instructions MUST go first! +// Redefine all the instructions (defined in assembler.h <- asmenum.h <- opcode.def) +#undef InlineNone +#undef InlineVar +#undef ShortInlineVar +#undef InlineI +#undef ShortInlineI +#undef InlineI8 +#undef InlineR +#undef ShortInlineR +#undef InlineBrTarget +#undef ShortInlineBrTarget +#undef InlineMethod +#undef InlineField +#undef InlineType +#undef InlineString +#undef InlineSig +#undef InlineTok +#undef InlineSwitch +#undef InlineVarTok + + +#define InlineNone INSTR_NONE +#define InlineVar INSTR_VAR +#define ShortInlineVar INSTR_VAR +#define InlineI INSTR_I +#define ShortInlineI INSTR_I +#define InlineI8 INSTR_I8 +#define InlineR INSTR_R +#define ShortInlineR INSTR_R +#define InlineBrTarget INSTR_BRTARGET +#define ShortInlineBrTarget INSTR_BRTARGET +#define InlineMethod INSTR_METHOD +#define InlineField INSTR_FIELD +#define InlineType INSTR_TYPE +#define InlineString INSTR_STRING +#define InlineSig INSTR_SIG +#define InlineTok INSTR_TOK +#define InlineSwitch INSTR_SWITCH + +#define InlineVarTok 0 +#define NEW_INLINE_NAMES + // The volatile instruction collides with the volatile keyword, so + // we treat it as a keyword everywhere and modify the grammar accordingly (Yuck!) +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) { s, args, c, lengthof(s)-1 }, +#define OPALIAS(alias_c, s, c) { s, NO_VALUE, c, lengthof(s)-1 }, +#include "opcode.def" +#undef OPALIAS +#undef OPDEF + + /* keywords */ +#define KYWD(name, sym, val) { name, sym, val, lengthof(name)-1 }, +#include "il_kywd.h" +#undef KYWD + +}; + +/********************************************************************************/ +/* File encoding-dependent functions */ +/*--------------------------------------------------------------------------*/ +char* nextcharU(__in __nullterminated char* pos) +{ + return ++pos; +} + +char* nextcharW(__in __nullterminated char* pos) +{ + return (pos+2); +} +/*--------------------------------------------------------------------------*/ +unsigned SymAU(__in __nullterminated char* curPos) +{ + return (unsigned)*curPos; +} + +unsigned SymW(__in __nullterminated char* curPos) +{ + return (unsigned)*((WCHAR*)curPos); +} +/*--------------------------------------------------------------------------*/ +char* NewStrFromTokenAU(__in_ecount(tokLen) char* curTok, size_t tokLen) +{ + char *nb = new char[tokLen+1]; + if(nb != NULL) + { + memcpy(nb, curTok, tokLen); + nb[tokLen] = 0; + } + return nb; +} +char* NewStrFromTokenW(__in_ecount(tokLen) char* curTok, size_t tokLen) +{ + WCHAR* wcurTok = (WCHAR*)curTok; + char *nb = new char[(tokLen<<1) + 2]; + if(nb != NULL) + { + tokLen = WszWideCharToMultiByte(CP_UTF8,0,(LPCWSTR)wcurTok,(int)(tokLen >> 1),nb,(int)(tokLen<<1) + 2,NULL,NULL); + nb[tokLen] = 0; + } + return nb; +} +/*--------------------------------------------------------------------------*/ +char* NewStaticStrFromTokenAU(__in_ecount(tokLen) char* curTok, size_t tokLen, __out_ecount(bufSize) char* staticBuf, size_t bufSize) +{ + if(tokLen >= bufSize) return NULL; + memcpy(staticBuf, curTok, tokLen); + staticBuf[tokLen] = 0; + return staticBuf; +} +char* NewStaticStrFromTokenW(__in_ecount(tokLen) char* curTok, size_t tokLen, __out_ecount(bufSize) char* staticBuf, size_t bufSize) +{ + WCHAR* wcurTok = (WCHAR*)curTok; + if(tokLen >= bufSize/2) return NULL; + tokLen = WszWideCharToMultiByte(CP_UTF8,0,(LPCWSTR)wcurTok,(int)(tokLen >> 1),staticBuf,(int)bufSize,NULL,NULL); + staticBuf[tokLen] = 0; + return staticBuf; +} +/*--------------------------------------------------------------------------*/ +unsigned GetDoubleAU(__in __nullterminated char* begNum, unsigned L, double** ppRes) +{ + static char dbuff[128]; + char* pdummy; + if(L > 127) L = 127; + memcpy(dbuff,begNum,L); + dbuff[L] = 0; + *ppRes = new double(strtod(dbuff, &pdummy)); + return ((unsigned)(pdummy - dbuff)); +} + +unsigned GetDoubleW(__in __nullterminated char* begNum, unsigned L, double** ppRes) +{ + static char dbuff[256]; + char* pdummy; + if(L > 254) L = 254; + memcpy(dbuff,begNum,L); + dbuff[L] = 0; + dbuff[L+1] = 0; + *ppRes = new double(wcstod((const WCHAR*)dbuff, (WCHAR**)&pdummy)); + return ((unsigned)(pdummy - dbuff)); +} +/*--------------------------------------------------------------------------*/ +char* yygetline(int Line) +{ + static char buff[0x4000]; + char *pLine=NULL, *pNextLine=NULL; + char *pBegin=NULL, *pEnd = NULL; + unsigned uCount = parser->getAll(&pBegin); + pEnd = pBegin + uCount; + buff[0] = 0; + for(uCount=0, pLine=pBegin; pLine < pEnd; pLine = nextchar(pLine)) + { + if(Sym(pLine) == '\n') uCount++; + if(uCount == (unsigned int)(Line-1)) break; + } + pLine = nextchar(pLine); + if(pLine < pEnd) + { + for(pNextLine = pLine; pNextLine < pEnd; pNextLine = nextchar(pNextLine)) + { + if(Sym(pNextLine) == '\n') break; + } + if(Sym == SymW) // Unicode file + { + if(*((WCHAR*)pNextLine - 1) == '\r') pNextLine -= 2; + uCount = (unsigned)(pNextLine - pLine); + uCount &= 0x1FFF; // limit: 8K wchars + WCHAR* wzBuff = (WCHAR*)buff; + memcpy(buff,pLine,uCount); + wzBuff[uCount >> 1] = 0; + } + else + { + if(*(pNextLine-1)=='\r') pNextLine--; + uCount = (unsigned)(pNextLine - pLine); + uCount &= 0x3FFF; // limit: 16K chars + memcpy(buff,pLine,uCount); + buff[uCount]=0; + } + } + return buff; +} + +void yyerror(__in __nullterminated const char* str) { + char tokBuff[64]; + WCHAR *wzfile = (WCHAR*)(PENV->in->namew()); + int iline = PENV->curLine; + + size_t len = PENV->curPos - PENV->curTok; + if (len > 62) len = 62; + memcpy(tokBuff, PENV->curTok, len); + tokBuff[len] = 0; + tokBuff[len+1] = 0; + if(PENV->bExternSource) + { + wzfile = PASM->m_wzSourceFileName; + iline = PENV->nExtLine; + } + if(Sym == SymW) // Unicode file + fprintf(stderr, "%S(%d) : error : %s at token '%S' in: %S\n", + wzfile, iline, str, (WCHAR*)tokBuff, (WCHAR*)yygetline(PENV->curLine)); + else + fprintf(stderr, "%S(%d) : error : %s at token '%s' in: %s\n", + wzfile, iline, str, tokBuff, yygetline(PENV->curLine)); + parser->success = false; +} + +/********************************************************************************/ +/* looks up the typedef 'name' of length 'nameLen' (name does not need to be + null terminated) Returns 0 on failure */ +TypeDefDescr* findTypedef(__in_ecount(NameLen) char* name, size_t NameLen) +{ + TypeDefDescr* pRet = NULL; + static char Name[4096]; + if(PASM->NumTypeDefs()) + { + if(NewStaticStrFromToken(name,NameLen,Name,4096)) + pRet = PASM->FindTypeDef(Name); + } + return pRet; +} + +int TYPEDEF(TypeDefDescr* pTDD) +{ + switch(TypeFromToken(pTDD->m_tkTypeSpec)) + { + case mdtTypeDef: + case mdtTypeRef: + return TYPEDEF_T; + case mdtMethodDef: + case 0x99000000: + return TYPEDEF_M; + case mdtFieldDef: + case 0x98000000: + return TYPEDEF_F; + case mdtMemberRef: + return TYPEDEF_MR; + case mdtTypeSpec: + return TYPEDEF_TS; + case mdtCustomAttribute: + return TYPEDEF_CA; + } + return ERROR_; + +} + +/********************************************************************************/ +void indexKeywords(Indx* indx) // called in Assembler constructor (assem.cpp) +{ + Keywords* low = keywords; + Keywords* high = keywords + (sizeof(keywords) / sizeof(Keywords)); + Keywords* mid; + for(mid = low; mid < high; mid++) + { + indx->IndexString((char*)(mid->name),mid); + } +} + +Instr* SetupInstr(unsigned short opcode) +{ + Instr* pVal = NULL; + if((pVal = PASM->GetInstr())) + { + pVal->opcode = opcode; + if((pVal->pWriter = PASM->m_pSymDocument)!=NULL || PASM->IsPortablePdb()) + { + if(PENV->bExternSource) + { + pVal->linenum = PENV->nExtLine; + pVal->column = PENV->nExtCol; + pVal->linenum_end = PENV->nExtLineEnd; + pVal->column_end = PENV->nExtColEnd; + pVal->pc = nCurrPC; + } + else + { + pVal->linenum = PENV->curLine; + pVal->column = 1; + pVal->linenum_end = PENV->curLine; + // Portable PDB rule: + // - If Start Line is equal to End Line then End Column is greater than Start Column. + // To fulfill this condition the column_end is set to 2 instead of 0 + pVal->column_end = PASM->IsPortablePdb() ? 2 : 0; + pVal->pc = PASM->m_CurPC; + } + pVal->pOwnerDocument = PASM->IsPortablePdb() ? PASM->m_pPortablePdbWriter->GetCurrentDocument() : NULL; + } + } + return pVal; +} +/* looks up the keyword 'name' of length 'nameLen' (name does not need to be + null terminated) Returns 0 on failure */ +int findKeyword(const char* name, size_t nameLen, unsigned short* pOpcode) +{ + static char Name[128]; + Keywords* mid; + + if(NULL == NewStaticStrFromToken((char*)name,nameLen,Name,128)) return 0; // can't be a keyword + mid = (Keywords*)(PASM->indxKeywords.FindString(Name)); + if(mid == NULL) return 0; + *pOpcode = mid->tokenVal; + + return(mid->token); +} + +/********************************************************************************/ +/* convert str to a uint64 */ +unsigned digits[128]; +void Init_str2uint64() +{ + int i; + memset(digits,255,sizeof(digits)); + for(i='0'; i <= '9'; i++) digits[i] = i - '0'; + for(i='A'; i <= 'Z'; i++) digits[i] = i + 10 - 'A'; + for(i='a'; i <= 'z'; i++) digits[i] = i + 10 - 'a'; +} +static unsigned __int64 str2uint64(const char* str, const char** endStr, unsigned radix) +{ + unsigned __int64 ret = 0; + unsigned digit,ix; + _ASSERTE(radix <= 36); + for(;;str = nextchar((char*)str)) + { + ix = Sym((char*)str); + if(ix <= 0x7F) + { + digit = digits[ix]; + if(digit < radix) + { + ret = ret * radix + digit; + continue; + } + } + *endStr = str; + return(ret); + } +} +/********************************************************************************/ +/* Append an UTF-8 string preceded by compressed length, no zero terminator, to a BinStr */ +static void AppendStringWithLength(BinStr* pbs, __in __nullterminated char* sz) +{ + if((pbs != NULL) && (sz != NULL)) + { + unsigned L = (unsigned) strlen(sz); + BYTE* pb = NULL; + corEmitInt(pbs,L); + if((pb = pbs->getBuff(L)) != NULL) + memcpy(pb,sz,L); + } +} + +/********************************************************************************/ +/* fetch the next token, and return it Also set the yylval.union if the + lexical token also has a value */ + + +BOOL _Alpha[128]; +BOOL _Digit[128]; +BOOL _AlNum[128]; +BOOL _ValidSS[128]; +BOOL _ValidCS[128]; +void SetSymbolTables() +{ + unsigned i; + memset(_Alpha,0,sizeof(_Alpha)); + memset(_Digit,0,sizeof(_Digit)); + memset(_AlNum,0,sizeof(_AlNum)); + memset(_ValidSS,0,sizeof(_ValidSS)); + memset(_ValidCS,0,sizeof(_ValidCS)); + for(i = 'A'; i <= 'Z'; i++) + { + _Alpha[i] = TRUE; + _AlNum[i] = TRUE; + _ValidSS[i] = TRUE; + _ValidCS[i] = TRUE; + } + for(i = 'a'; i <= 'z'; i++) + { + _Alpha[i] = TRUE; + _AlNum[i] = TRUE; + _ValidSS[i] = TRUE; + _ValidCS[i] = TRUE; + } + for(i = '0'; i <= '9'; i++) + { + _Digit[i] = TRUE; + _AlNum[i] = TRUE; + _ValidCS[i] = TRUE; + } + _ValidSS[(unsigned char)'_'] = TRUE; + _ValidSS[(unsigned char)'#'] = TRUE; + _ValidSS[(unsigned char)'$'] = TRUE; + _ValidSS[(unsigned char)'@'] = TRUE; + + _ValidCS[(unsigned char)'_'] = TRUE; + _ValidCS[(unsigned char)'?'] = TRUE; + _ValidCS[(unsigned char)'$'] = TRUE; + _ValidCS[(unsigned char)'@'] = TRUE; + _ValidCS[(unsigned char)'`'] = TRUE; +} +BOOL IsAlpha(unsigned x) { return (x < 128)&&_Alpha[x]; } +BOOL IsDigit(unsigned x) { return (x < 128)&&_Digit[x]; } +BOOL IsAlNum(unsigned x) { return (x < 128)&&_AlNum[x]; } +BOOL IsValidStartingSymbol(unsigned x) { return (x < 128)&&_ValidSS[x]; } +BOOL IsValidContinuingSymbol(unsigned x) { return (x < 128)&&_ValidCS[x]; } + + +char* nextBlank(__in __nullterminated char* curPos) +{ + for(;;) + { + switch(Sym(curPos)) + { + case '/' : + if ((Sym(nextchar(curPos)) == '/')|| (Sym(nextchar(curPos)) == '*')) + return curPos; + else + { + curPos = nextchar(curPos); + break; + } + case 0: + case '\n': + case '\r': + case ' ' : + case '\t': + case '\f': + return curPos; + + default: + curPos = nextchar(curPos); + } + } +} + +char* skipBlanks(__in __nullterminated char* curPos, unsigned* pstate) +{ + const unsigned eolComment = 1; + const unsigned multiComment = 2; + unsigned nextSym, state = *pstate; + char* nextPos; + for(;;) + { // skip whitespace and comments + if (curPos >= PENV->endPos) + { + *pstate = state; + return NULL; + } + switch(Sym(curPos)) + { + case 0: + return NULL; // EOF + case '\n': + state &= ~eolComment; + PENV->curLine++; + if(PENV->bExternSource) + { + if(PENV->bExternSourceAutoincrement) PENV->nExtLine++; + PASM->m_ulCurLine = PENV->nExtLine; + PASM->m_ulCurColumn = PENV->nExtCol; + } + else + { + PASM->m_ulCurLine = PENV->curLine; + PASM->m_ulCurColumn = 1; + } + break; + case '\r': + case ' ' : + case '\t': + case '\f': + break; + + case '*' : + if(state == 0) goto PAST_WHITESPACE; + if(state & multiComment) + { + nextPos = nextchar(curPos); + if (Sym(nextPos) == '/') + { + curPos = nextPos; + state &= ~multiComment; + } + } + break; + + case '/' : + if(state == 0) + { + nextPos = nextchar(curPos); + nextSym = Sym(nextPos); + if (nextSym == '/') + { + curPos = nextPos; + state |= eolComment; + } + else if (nextSym == '*') + { + curPos = nextPos; + state |= multiComment; + } + else goto PAST_WHITESPACE; + } + break; + + default: + if (state == 0) goto PAST_WHITESPACE; + } + curPos = nextchar(curPos); + } +PAST_WHITESPACE: + *pstate = state; + return curPos; +} + +char* FullFileName(__in __nullterminated WCHAR* wzFileName, unsigned uCodePage); + +int ProcessEOF() +{ + PARSING_ENVIRONMENT* prev_penv = parser->PEStack.POP(); + if(prev_penv != NULL) + { + //delete [] (WCHAR*)(PENV->in->namew()); + delete PENV->in; + delete PENV; + parser->penv = prev_penv; + SetFunctionPtrs(); + char* szFileName = new char[strlen(PENV->szFileName)+1]; + strcpy_s(szFileName,strlen(PENV->szFileName)+1,PENV->szFileName); + PASM->SetSourceFileName(szFileName); // deletes the argument! + return ';'; + } + //PENV->in = NULL; + return 0; +} + +#define NEXT_TOKEN {state=0; curPos=PENV->curPos; goto NextToken;} + +int parse_literal(unsigned curSym, __inout __nullterminated char* &curPos, BOOL translate_escapes) +{ + unsigned quote = curSym; + curPos = nextchar(curPos); + char* fromPtr = curPos; + bool escape = false; + + for(;;) + { // Find matching quote + curSym = (curPos >= PENV->endPos) ? 0 : Sym(curPos); + if(curSym == 0) + { + PENV->curPos = curPos; + return(BAD_LITERAL_); + } + else if(curSym == '\\') + escape = !escape; + else + { + if(curSym == '\n') + { + PENV->curLine++; + if(PENV->bExternSource) + { + if(PENV->bExternSourceAutoincrement) PENV->nExtLine++; + PASM->m_ulCurLine = PENV->nExtLine; + PASM->m_ulCurColumn = PENV->nExtCol; + } + else + { + PASM->m_ulCurLine = PENV->curLine; + PASM->m_ulCurColumn = 1; + } + if (!escape) { PENV->curPos = curPos; return(BAD_LITERAL_); } + } + else if ((curSym == quote) && (!escape)) break; + escape = false; + } + curPos = nextchar(curPos); + } + // translate escaped characters + unsigned tokLen = (unsigned)(curPos - fromPtr); + char* newstr = NewStrFromToken(fromPtr, tokLen); + char* toPtr; + curPos = nextchar(curPos); // skip closing quote + if(translate_escapes) + { + fromPtr = newstr; + //_ASSERTE(0); + tokLen = (unsigned)strlen(newstr); + toPtr = new char[tokLen+1]; + if(toPtr==NULL) return BAD_LITERAL_; + yylval.string = toPtr; + char* endPtr = fromPtr+tokLen; + while(fromPtr < endPtr) + { + if (*fromPtr == '\\') + { + fromPtr++; + switch(*fromPtr) + { + case 't': + *toPtr++ = '\t'; + break; + case 'n': + *toPtr++ = '\n'; + break; + case 'b': + *toPtr++ = '\b'; + break; + case 'f': + *toPtr++ = '\f'; + break; + case 'v': + *toPtr++ = '\v'; + break; + case '?': + *toPtr++ = '\?'; + break; + case 'r': + *toPtr++ = '\r'; + break; + case 'a': + *toPtr++ = '\a'; + break; + case '\n': + do fromPtr++; + while(isspace(*fromPtr)); + --fromPtr; // undo the increment below + break; + case '0': + case '1': + case '2': + case '3': + if (IsDigit(fromPtr[1]) && IsDigit(fromPtr[2])) + { + *toPtr++ = ((fromPtr[0] - '0') * 8 + (fromPtr[1] - '0')) * 8 + (fromPtr[2] - '0'); + fromPtr+= 2; + } + else if(*fromPtr == '0') *toPtr++ = 0; + else *toPtr++ = *fromPtr; + break; + default: + *toPtr++ = *fromPtr; + } + fromPtr++; + } + else + // *toPtr++ = *fromPtr++; + { + char* tmpPtr = fromPtr; + fromPtr = (nextchar == nextcharW) ? nextcharU(fromPtr) : nextchar(fromPtr); + while(tmpPtr < fromPtr) *toPtr++ = *tmpPtr++; + } + + } //end while(fromPtr < endPtr) + *toPtr = 0; // terminate string + delete [] newstr; + } + else + { + yylval.string = newstr; + toPtr = newstr + strlen(newstr); + } + + PENV->curPos = curPos; + if(quote == '"') + { + BinStr* pBS = new BinStr(); + unsigned size = (unsigned)(toPtr - yylval.string); + memcpy(pBS->getBuff(size),yylval.string,size); + delete [] yylval.string; + yylval.binstr = pBS; + return QSTRING; + } + else + { + if(PASM->NumTypeDefs()) + { + TypeDefDescr* pTDD = PASM->FindTypeDef(yylval.string); + if(pTDD != NULL) + { + delete [] yylval.string; + yylval.tdd = pTDD; + return(TYPEDEF(pTDD)); + } + } + return SQSTRING; + } +} + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:21000) // Suppress PREFast warning about overly large function +#endif +int yylex() +{ + char* curPos = PENV->curPos; + unsigned state = 0; + const unsigned multiComment = 2; + unsigned curSym; + + char* newstr; + +NextToken: + // Skip any leading whitespace and comments + curPos = skipBlanks(curPos, &state); + if(curPos == NULL) + { + if (state & multiComment) return (BAD_COMMENT_); + if(ProcessEOF() == 0) return 0; // EOF + NEXT_TOKEN; + } + char* curTok = curPos; + PENV->curTok = curPos; + PENV->curPos = curPos; + int tok = ERROR_; + yylval.string = 0; + + curSym = Sym(curPos); + if(bParsingByteArray) // only hexadecimals w/o 0x, ')' and white space allowed! + { + int i,s=0; + for(i=0; i<2; i++, curPos = nextchar(curPos), curSym = Sym(curPos)) + { + if(('0' <= curSym)&&(curSym <= '9')) s = s*16+(curSym - '0'); + else if(('A' <= curSym)&&(curSym <= 'F')) s = s*16+(curSym - 'A' + 10); + else if(('a' <= curSym)&&(curSym <= 'f')) s = s*16+(curSym - 'a' + 10); + else break; // don't increase curPos! + } + if(i) + { + tok = HEXBYTE; + yylval.int32 = s; + } + else + { + if(curSym == ')' || curSym == '}') + { + bParsingByteArray = FALSE; + goto Just_A_Character; + } + } + PENV->curPos = curPos; + return(tok); + } + if(curSym == '?') // '?' may be part of an identifier, if it's not followed by punctuation + { + if(IsValidContinuingSymbol(Sym(nextchar(curPos)))) goto Its_An_Id; + goto Just_A_Character; + } + + if (IsValidStartingSymbol(curSym)) + { // is it an ID +Its_An_Id: + size_t offsetDot = (size_t)-1; // first appearance of '.' + size_t offsetDotDigit = (size_t)-1; // first appearance of '.<digit>' (not DOTTEDNAME!) + do + { + curPos = nextchar(curPos); + if (Sym(curPos) == '.') + { + if (offsetDot == (size_t)-1) offsetDot = curPos - curTok; + curPos = nextchar(curPos); + if((offsetDotDigit==(size_t)-1)&&(Sym(curPos) >= '0')&&(Sym(curPos) <= '9')) + offsetDotDigit = curPos - curTok - 1; + } + } while(IsValidContinuingSymbol(Sym(curPos))); + + size_t tokLen = curPos - curTok; + // check to see if it is a keyword + int token = findKeyword(curTok, tokLen, &yylval.opcode); + if (token != 0) + { + //printf("yylex: TOK = %d, curPos=0x%8.8X\n",token,curPos); + PENV->curPos = curPos; + PENV->curTok = curTok; + if(!SkipToken) + { + switch(token) + { + case P_INCLUDE: + //if(include_first_pass) + //{ + // PENV->curPos = curTok; + // include_first_pass = FALSE; + // return ';'; + //} + //include_first_pass = TRUE; + curPos = skipBlanks(curPos,&state); + if(curPos == NULL) + { + if (state & multiComment) return (BAD_COMMENT_); + if(ProcessEOF() == 0) return 0; // EOF + NEXT_TOKEN; + } + if(Sym(curPos) != '"') return ERROR_; + curPos = nextchar(curPos); + curTok = curPos; + PENV->curTok = curPos; + while(Sym(curPos) != '"') + { + curPos = nextchar(curPos); + if(curPos >= PENV->endPos) return ERROR_; + PENV->curPos = curPos; + } + tokLen = PENV->curPos - curTok; + curPos = nextchar(curPos); + PENV->curPos = curPos; + { + WCHAR* wzFile=NULL; + if(Sym == SymW) + { + if((wzFile = new WCHAR[tokLen/2 + 1]) != NULL) + { + memcpy(wzFile,curTok,tokLen); + wzFile[tokLen/2] = 0; + } + } + else + { + if((wzFile = new WCHAR[tokLen+1]) != NULL) + { + tokLen = WszMultiByteToWideChar(g_uCodePage,0,curTok,(int)tokLen,wzFile,(int)tokLen+1); + wzFile[tokLen] = 0; + } + } + if(wzFile != NULL) + { + if((parser->wzIncludePath != NULL) + &&(wcschr(wzFile,DIRECTORY_SEPARATOR_CHAR_A)==NULL) +#ifdef TARGET_WINDOWS + &&(wcschr(wzFile,':')==NULL) +#endif + ) + { + PathString wzFullName; + + WCHAR* pwz; + DWORD dw = WszSearchPath(parser->wzIncludePath,wzFile,NULL, + TRUE, wzFullName,&pwz); + if(dw != 0) + { + delete [] wzFile; + + wzFile = wzFullName.GetCopyOfUnicodeString(); + } + + } + if(PASM->m_fReportProgress) + parser->msg("\nIncluding '%S'\n",wzFile); + MappedFileStream *pIn = new MappedFileStream(wzFile); + if((pIn != NULL)&&pIn->IsValid()) + { + parser->PEStack.PUSH(PENV); + PASM->SetSourceFileName(FullFileName(wzFile,CP_UTF8)); // deletes the argument! + parser->CreateEnvironment(pIn); + NEXT_TOKEN; + } + else + { + delete [] wzFile; + PASM->report->error("#include failed\n"); + return ERROR_; + } + } + else + { + PASM->report->error("Out of memory\n"); + return ERROR_; + } + } + curPos = PENV->curPos; + curTok = PENV->curTok; + break; + case P_IFDEF: + case P_IFNDEF: + case P_DEFINE: + case P_UNDEF: + curPos = skipBlanks(curPos,&state); + if(curPos == NULL) + { + if (state & multiComment) return (BAD_COMMENT_); + if(ProcessEOF() == 0) return 0; // EOF + NEXT_TOKEN; + } + curTok = curPos; + PENV->curTok = curPos; + PENV->curPos = curPos; + if (!IsValidStartingSymbol(Sym(curPos))) return ERROR_; + do + { + curPos = nextchar(curPos); + } while(IsValidContinuingSymbol(Sym(curPos))); + tokLen = curPos - curTok; + + newstr = NewStrFromToken(curTok, tokLen); + if((token==P_DEFINE)||(token==P_UNDEF)) + { + if(token == P_DEFINE) + { + curPos = skipBlanks(curPos,&state); + if ((curPos == NULL) && (ProcessEOF() == 0)) + { + DefineVar(newstr, NULL); + return 0; + } + curSym = Sym(curPos); + if(curSym != '"') + DefineVar(newstr, NULL); + else + { + tok = parse_literal(curSym, curPos, FALSE); + if(tok == QSTRING) + { + yylval.binstr->appendInt8(' '); + DefineVar(newstr, yylval.binstr); + } + else + return tok; + } + } + else UndefVar(newstr); + } + else + { + SkipToken = IsVarDefined(newstr); + if(token == P_IFDEF) SkipToken = !SkipToken; + IfEndif++; + if(SkipToken) IfEndifSkip=IfEndif; + } + break; + case P_ELSE: + SkipToken = TRUE; + IfEndifSkip=IfEndif; + break; + case P_ENDIF: + if(IfEndif == 0) + { + PASM->report->error("Unmatched #endif\n"); + return ERROR_; + } + IfEndif--; + break; + default: + return(token); + } + goto NextToken; + } + if(SkipToken) + { + switch(token) + { + case P_IFDEF: + case P_IFNDEF: + IfEndif++; + break; + case P_ELSE: + if(IfEndif == IfEndifSkip) SkipToken = FALSE; + break; + case P_ENDIF: + if(IfEndif == IfEndifSkip) SkipToken = FALSE; + IfEndif--; + break; + default: + break; + } + //if(yylval.instr) yylval.instr->opcode = -1; + goto NextToken; + } + return(token); + } // end if token != 0 + if(SkipToken) { curPos = nextBlank(curPos); goto NextToken; } + + VarName* pVarName = FindVarDef(NewStrFromToken(curTok, tokLen)); + if(pVarName != NULL) + { + if(pVarName->pbody != NULL) + { + BinStrStream *pIn = new BinStrStream(pVarName->pbody); + if((pIn != NULL)&&pIn->IsValid()) + { + PENV->curPos = curPos; + parser->PEStack.PUSH(PENV); + parser->CreateEnvironment(pIn); + NEXT_TOKEN; + } + } + } + + TypeDefDescr* pTDD = findTypedef(curTok,tokLen); + + if(pTDD != NULL) + { + yylval.tdd = pTDD; + PENV->curPos = curPos; + PENV->curTok = curTok; + return(TYPEDEF(pTDD)); + } + if(Sym(curTok) == '#') + { + PENV->curPos = curPos; + PENV->curTok = curTok; + return(ERROR_); + } + // Not a keyword, normal identifiers don't have '.' in them + if (offsetDot < (size_t)-1) + { + if(offsetDotDigit < (size_t)-1) + { + curPos = curTok+offsetDotDigit; + tokLen = offsetDotDigit; + } + // protection against something like Foo.Bar..123 or Foo.Bar. + unsigned D = (Sym == SymW) ? 2 : 1; // Unicode or ANSI/UTF8! + while((Sym(curPos-D)=='.')&&(tokLen)) + { + curPos -= D; + tokLen -= D; + } + } + if((yylval.string = NewStrFromToken(curTok,tokLen))) + { + tok = (offsetDot == (size_t)(-1))? ID : DOTTEDNAME; + //printf("yylex: ID = '%s', curPos=0x%8.8X\n",yylval.string,curPos); + } + else return BAD_LITERAL_; + } + else if(SkipToken) { curPos = nextBlank(curPos); goto NextToken; } + else if (IsDigit(curSym) + || (curSym == '.' && IsDigit(Sym(nextchar(curPos)))) + || (curSym == '-' && IsDigit(Sym(nextchar(curPos))))) + { + const char* begNum = curPos; + unsigned radix = 10; + + neg = (curSym == '-'); // always make it unsigned + if (neg) curPos = nextchar(curPos); + + if (Sym(curPos) == '0' && Sym(nextchar(curPos)) != '.') + { + curPos = nextchar(curPos); + radix = 8; + if (Sym(curPos) == 'x' || Sym(curPos) == 'X') + { + curPos = nextchar(curPos); + radix = 16; + } + } + begNum = curPos; + { + unsigned __int64 i64 = str2uint64(begNum, const_cast<const char**>(&curPos), radix); + unsigned __int64 mask64 = neg ? UI64(0xFFFFFFFF80000000) : UI64(0xFFFFFFFF00000000); + unsigned __int64 largestNegVal32 = UI64(0x0000000080000000); + if ((i64 & mask64) && (i64 != largestNegVal32)) + { + yylval.int64 = new __int64(i64); + tok = INT64; + if (neg) *yylval.int64 = -*yylval.int64; + } + else + { + yylval.int32 = (__int32)i64; + tok = INT32; + if(neg) yylval.int32 = -yylval.int32; + } + } + if (radix == 10 && ((Sym(curPos) == '.' && Sym(nextchar(curPos)) != '.') || Sym(curPos) == 'E' || Sym(curPos) == 'e')) + { + unsigned L = (unsigned)(PENV->endPos - begNum); + curPos = (char*)begNum + GetDouble((char*)begNum,L,&yylval.float64); + if (neg) *yylval.float64 = -*yylval.float64; + tok = FLOAT64; + } + } + else + { // punctuation + if (curSym == '"' || curSym == '\'') + { + return parse_literal(curSym, curPos, TRUE); + } // end if (*curPos == '"' || *curPos == '\'') + else if (curSym==':' && Sym(nextchar(curPos))==':') + { + curPos = nextchar(nextchar(curPos)); + tok = DCOLON; + } + else if(curSym == '.') + { + if (Sym(nextchar(curPos))=='.' && Sym(nextchar(nextchar(curPos)))=='.') + { + curPos = nextchar(nextchar(nextchar(curPos))); + tok = ELIPSIS; + } + else + { + do + { + curPos = nextchar(curPos); + if (curPos >= PENV->endPos) + return ERROR_; + curSym = Sym(curPos); + } + while(IsAlNum(curSym) || curSym == '_' || curSym == '$'|| curSym == '@'|| curSym == '?'); + size_t tokLen = curPos - curTok; + + // check to see if it is a keyword + int token = findKeyword(curTok, tokLen, &yylval.opcode); + if(token) + { + //printf("yylex: TOK = %d, curPos=0x%8.8X\n",token,curPos); + PENV->curPos = curPos; + PENV->curTok = curTok; + return(token); + } + tok = '.'; + curPos = nextchar(curTok); + } + } + else + { +Just_A_Character: + tok = curSym; + curPos = nextchar(curPos); + } + //printf("yylex: PUNCT curPos=0x%8.8X\n",curPos); + } + dbprintf((" Line %d token %d (%c) val = %s\n", PENV->curLine, tok, + (tok < 128 && isprint(tok)) ? tok : ' ', + (tok > 255 && tok != INT32 && tok != INT64 && tok!= FLOAT64) ? yylval.string : "")); + + PENV->curPos = curPos; + PENV->curTok = curTok; + return(tok); +} +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +/**************************************************************************/ +static char* newString(__in __nullterminated const char* str1) +{ + char* ret = new char[strlen(str1)+1]; + if(ret) strcpy_s(ret, strlen(str1)+1, str1); + return(ret); +} + +/**************************************************************************/ +/* concatenate strings and release them */ + +static char* newStringWDel(__in __nullterminated char* str1, char delimiter, __in __nullterminated char* str3) +{ + size_t len1 = strlen(str1); + size_t len = len1+2; + if (str3) len += strlen(str3); + char* ret = new char[len]; + if(ret) + { + strcpy_s(ret, len, str1); + delete [] str1; + ret[len1] = delimiter; + ret[len1+1] = 0; + if (str3) + { + strcat_s(ret, len, str3); + delete [] str3; + } + } + return(ret); +} + +/**************************************************************************/ +static void corEmitInt(BinStr* buff, unsigned data) +{ + unsigned cnt = CorSigCompressData(data, buff->getBuff(5)); + buff->remove(5 - cnt); +} + + +/**************************************************************************/ +/* move 'ptr past the exactly one type description */ + +unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType) +{ + mdToken tk; +AGAIN: + switch(*ptr++) { + case ELEMENT_TYPE_VOID : + case ELEMENT_TYPE_BOOLEAN : + case ELEMENT_TYPE_CHAR : + case ELEMENT_TYPE_I1 : + case ELEMENT_TYPE_U1 : + case ELEMENT_TYPE_I2 : + case ELEMENT_TYPE_U2 : + case ELEMENT_TYPE_I4 : + case ELEMENT_TYPE_U4 : + case ELEMENT_TYPE_I8 : + case ELEMENT_TYPE_U8 : + case ELEMENT_TYPE_R4 : + case ELEMENT_TYPE_R8 : + case ELEMENT_TYPE_U : + case ELEMENT_TYPE_I : + case ELEMENT_TYPE_STRING : + case ELEMENT_TYPE_OBJECT : + case ELEMENT_TYPE_TYPEDBYREF : + case ELEMENT_TYPE_SENTINEL : + /* do nothing */ + break; + + case ELEMENT_TYPE_VALUETYPE : + case ELEMENT_TYPE_CLASS : + ptr += CorSigUncompressToken(ptr, &tk); + break; + + case ELEMENT_TYPE_CMOD_REQD : + case ELEMENT_TYPE_CMOD_OPT : + ptr += CorSigUncompressToken(ptr, &tk); + goto AGAIN; + + case ELEMENT_TYPE_ARRAY : + { + ptr = skipType(ptr, fFixupType); // element Type + unsigned rank = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); + if (rank != 0) + { + unsigned numSizes = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); + while(numSizes > 0) + { + CorSigUncompressData((PCCOR_SIGNATURE&) ptr); + --numSizes; + } + unsigned numLowBounds = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); + while(numLowBounds > 0) + { + CorSigUncompressData((PCCOR_SIGNATURE&) ptr); + --numLowBounds; + } + } + } + break; + + // Modifiers or dependent types + case ELEMENT_TYPE_PINNED : + case ELEMENT_TYPE_PTR : + case ELEMENT_TYPE_BYREF : + case ELEMENT_TYPE_SZARRAY : + // tail recursion optimization + // ptr = skipType(ptr, fFixupType); + // break + goto AGAIN; + + case ELEMENT_TYPE_VAR: + case ELEMENT_TYPE_MVAR: + CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // bound + break; + + case ELEMENT_TYPE_VARFIXUP: + case ELEMENT_TYPE_MVARFIXUP: + if(fFixupType) + { + BYTE* pb = ptr-1; // ptr incremented in switch + unsigned __int8* ptr_save = ptr; + int n = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // fixup # + int compressed_size_n = (int)(ptr - ptr_save); // ptr was updated by CorSigUncompressData() + int m = -1; + if(PASM->m_TyParList) + m = PASM->m_TyParList->IndexOf(TyParFixupList.PEEK(n)); + if(m == -1) + { + PASM->report->error("(fixupType) Invalid %stype parameter '%s'\n", + (*pb == ELEMENT_TYPE_MVARFIXUP)? "method ": "", + TyParFixupList.PEEK(n)); + m = 0; + } + *pb = (*pb == ELEMENT_TYPE_MVARFIXUP)? ELEMENT_TYPE_MVAR : ELEMENT_TYPE_VAR; + int compressed_size_m = (int)CorSigCompressData(m,pb+1); + + // Note that CorSigCompressData() (and hence, CorSigUncompressData()) store a number + // 0 <= x <= 0x1FFFFFFF in 1, 2, or 4 bytes. Above, 'n' is the fixup number being read, + // and 'm' is the generic parameter number being written out (in the same place where 'n' + // came from). If 'n' takes more space to compress than 'm' (e.g., 0x80 <= n <= 0x3fff so + // it takes 2 bytes, and m < 0x80 so it takes one byte), then when we overwrite the fixup + // number with the generic parameter number, we'll leave extra bytes in the signature following + // the written generic parameter number. Thus, we do something of a hack to ensure that the + // compressed number is correctly readable even if 'm' compresses smaller than 'n' did: we + // recompress 'm' to use the same amount of space as 'n' used. This is possible because smaller + // numbers can still be compressed in a larger amount of space, even though it's not optimal (and + // CorSigCompressData() would never do it). If, however, the compressed sizes are the other + // way around (m takes more space to compress than n), then we've already corrupted the + // signature that we're reading by writing beyond what we should (is there some reason why + // this is not possible?). + // Note that 'ptr' has already been adjusted, above, to point to the next type after this one. + // There is no need to update it when recompressing the data. + + if (compressed_size_m > compressed_size_n) + { + // We've got a problem: we just corrupted the rest of the signature! + // (Can this ever happen in practice?) + PASM->report->error("(fixupType) Too many %stype parameters\n", + (*pb == ELEMENT_TYPE_MVARFIXUP)? "method ": ""); + } + else if (compressed_size_m < compressed_size_n) + { + // We didn't write out as much data as we read. This will leave extra bytes in the + // signature that will be incorrectly recognized. Ideally, we would just shrink the + // signature. That's not easy to do here. Instead, pad the bytes to force it to use + // a larger encoding than needed. This assumes knowledge of the CorSigCompressData() + // encoding. + // + // The cases: + // compressed_size_m m bytes compressed_size_n result bytes + // 1 m1 2 0x80 m1 + // 1 m1 4 0xC0 0x00 0x00 m1 + // 2 m1 m2 4 0xC0 0x00 (m1 & 0x7f) m2 + + _ASSERTE((compressed_size_m == 1) || (compressed_size_m == 2) || (compressed_size_m == 4)); + _ASSERTE((compressed_size_n == 1) || (compressed_size_n == 2) || (compressed_size_n == 4)); + + if ((compressed_size_m == 1) && + (compressed_size_n == 2)) + { + unsigned __int8 m1 = *(pb + 1); + _ASSERTE(m1 < 0x80); + *(pb + 1) = 0x80; + *(pb + 2) = m1; + } + else + if ((compressed_size_m == 1) && + (compressed_size_n == 4)) + { + unsigned __int8 m1 = *(pb + 1); + _ASSERTE(m1 < 0x80); + *(pb + 1) = 0xC0; + *(pb + 2) = 0x00; + *(pb + 3) = 0x00; + *(pb + 4) = m1; + } + else + if ((compressed_size_m == 2) && + (compressed_size_n == 4)) + { + unsigned __int8 m1 = *(pb + 1); + unsigned __int8 m2 = *(pb + 2); + _ASSERTE(m1 >= 0x80); + m1 &= 0x7f; // strip the bit indicating it's a 2-byte thing + *(pb + 1) = 0xC0; + *(pb + 2) = 0x00; + *(pb + 3) = m1; + *(pb + 4) = m2; + } + } + } + else + CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // bound + break; + + case ELEMENT_TYPE_FNPTR: + { + CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // calling convention + unsigned argCnt = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // arg count + ptr = skipType(ptr, fFixupType); // return type + while(argCnt > 0) + { + ptr = skipType(ptr, fFixupType); + --argCnt; + } + } + break; + + case ELEMENT_TYPE_GENERICINST: + { + ptr = skipType(ptr, fFixupType); // type constructor + unsigned argCnt = CorSigUncompressData((PCCOR_SIGNATURE&)ptr); // arg count + while(argCnt > 0) { + ptr = skipType(ptr, fFixupType); + --argCnt; + } + } + break; + + default: + case ELEMENT_TYPE_END : + _ASSERTE(!"Unknown Type"); + break; + } + return(ptr); +} + +/**************************************************************************/ +void FixupTyPars(PCOR_SIGNATURE pSig, ULONG cSig) +{ + if(TyParFixupList.COUNT() > 0) + { + BYTE* ptr = (BYTE*)pSig; + BYTE* ptrEnd = ptr + cSig; + while(ptr < ptrEnd) + { + ptr = skipType(ptr, TRUE); + } // end while + } // end if(COUNT>0) +} +void FixupTyPars(BinStr* pbstype) +{ + FixupTyPars((PCOR_SIGNATURE)(pbstype->ptr()),(ULONG)(pbstype->length())); +} +/**************************************************************************/ +static unsigned corCountArgs(BinStr* args) +{ + unsigned __int8* ptr = args->ptr(); + unsigned __int8* end = &args->ptr()[args->length()]; + unsigned ret = 0; + while(ptr < end) + { + if (*ptr != ELEMENT_TYPE_SENTINEL) + { + ptr = skipType(ptr, FALSE); + ret++; + } + else ptr++; + } + return(ret); +} + +/********************************************************************************/ +AsmParse::AsmParse(ReadStream* aIn, Assembler *aAssem) +{ +#ifdef DEBUG_PARSING + extern int yydebug; + yydebug = 1; +#endif + + assem = aAssem; + assem->SetErrorReporter((ErrorReporter *)this); + + assem->m_ulCurLine = 1; + assem->m_ulCurColumn = 1; + + wzIncludePath = NULL; + penv = NULL; + + hstdout = GetStdHandle(STD_OUTPUT_HANDLE); + hstderr = GetStdHandle(STD_ERROR_HANDLE); + + success = true; + _ASSERTE(parser == 0); // Should only be one parser instance at a time + + // Resolve aliases + for (unsigned int i = 0; i < sizeof(keywords) / sizeof(Keywords); i++) + { + if (keywords[i].token == NO_VALUE) + keywords[i].token = keywords[keywords[i].tokenVal].token; + } + SetSymbolTables(); + Init_str2uint64(); + parser = this; + //yyparse(); +} + +/********************************************************************************/ +AsmParse::~AsmParse() +{ + parser = 0; + delete penv; + while(m_ANSLast.POP()); +} + +/**************************************************************************/ +void AsmParse::CreateEnvironment(ReadStream* stream) +{ + penv = new PARSING_ENVIRONMENT; + memset(penv,0,sizeof(PARSING_ENVIRONMENT)); + penv->in = stream; + penv->curLine = 1; + strcpy_s(penv->szFileName, MAX_FILENAME_LENGTH*3+1,assem->m_szSourceFileName); + + penv->curPos = fillBuff(NULL); + penv->uCodePage = g_uCodePage; + + SetFunctionPtrs(); +}; + +/**************************************************************************/ +void AsmParse::ParseFile(ReadStream* stream) +{ + CreateEnvironment(stream); + yyparse(); + penv->in = NULL; +}; + +/**************************************************************************/ +char* AsmParse::fillBuff(__in_opt __nullterminated char* pos) +{ + int iPutToBuffer; + g_uCodePage = CP_UTF8; + iPutToBuffer = (int)penv->in->getAll(&(penv->curPos)); + + penv->endPos = penv->curPos + iPutToBuffer; + if(iPutToBuffer > 128) iPutToBuffer = 128; + if(iPutToBuffer >= 4 && (penv->curPos[0] & 0xFF) == 0xFF && (penv->curPos[1] & 0xFF) == 0xFE) + { + // U+FFFE followed by U+0000 is UTF-32 LE, any other value than 0 is a true UTF-16 LE + if((penv->curPos[2] & 0xFF) == 0x00 && (penv->curPos[3] & 0xFF) == 0x00) + { + error("UTF-32 LE is not supported\n\n"); + return NULL; + } + + penv->curPos += 2; // skip signature + if(assem->m_fReportProgress) printf("Source file is UNICODE\n\n"); + penv->pfn_Sym = SymW; + penv->pfn_nextchar = nextcharW; + penv->pfn_NewStrFromToken = NewStrFromTokenW; + penv->pfn_NewStaticStrFromToken = NewStaticStrFromTokenW; + penv->pfn_GetDouble = GetDoubleW; + } + else + { + if((penv->curPos[0] & 0xFF) == 0xEF && (penv->curPos[1] & 0xFF) == 0xBB && (penv->curPos[2] & 0xFF) == 0xBF) + { + penv->curPos += 3; + } + + if(assem->m_fReportProgress) printf("Source file is UTF-8\n\n"); + penv->pfn_nextchar = nextcharU; + penv->pfn_Sym = SymAU; + penv->pfn_NewStrFromToken = NewStrFromTokenAU; + penv->pfn_NewStaticStrFromToken = NewStaticStrFromTokenAU; + penv->pfn_GetDouble = GetDoubleAU; + } + return(penv->curPos); +} + +/********************************************************************************/ +BinStr* AsmParse::MakeSig(unsigned callConv, BinStr* retType, BinStr* args, int ntyargs) +{ + _ASSERTE((ntyargs != 0) == ((callConv & IMAGE_CEE_CS_CALLCONV_GENERIC) != 0)); + BinStr* ret = new BinStr(); + if(ret) + { + //if (retType != 0) + ret->insertInt8(callConv); + if (ntyargs != 0) + corEmitInt(ret, ntyargs); + corEmitInt(ret, corCountArgs(args)); + + if (retType != 0) + { + ret->append(retType); + delete retType; + } + ret->append(args); + } + else + error("\nOut of memory!\n"); + + delete args; + return(ret); +} + +/********************************************************************************/ +BinStr* AsmParse::MakeTypeArray(CorElementType kind, BinStr* elemType, BinStr* bounds) +{ + // 'bounds' is a binary buffer, that contains an array of 'struct Bounds' + struct Bounds { + int lowerBound; + unsigned numElements; + }; + + _ASSERTE(bounds->length() % sizeof(Bounds) == 0); + unsigned boundsLen = bounds->length() / sizeof(Bounds); + _ASSERTE(boundsLen > 0); + Bounds* boundsArr = (Bounds*) bounds->ptr(); + + BinStr* ret = new BinStr(); + + ret->appendInt8(kind); + ret->append(elemType); + corEmitInt(ret, boundsLen); // emit the rank + + unsigned lowerBoundsDefined = 0; + unsigned numElementsDefined = 0; + unsigned i; + for(i=0; i < boundsLen; i++) + { + if(boundsArr[i].lowerBound < 0x7FFFFFFF) lowerBoundsDefined = i+1; + else boundsArr[i].lowerBound = 0; + + if(boundsArr[i].numElements < 0x7FFFFFFF) numElementsDefined = i+1; + else boundsArr[i].numElements = 0; + } + + corEmitInt(ret, numElementsDefined); // emit number of bounds + + for(i=0; i < numElementsDefined; i++) + { + _ASSERTE (boundsArr[i].numElements >= 0); // enforced at rule time + corEmitInt(ret, boundsArr[i].numElements); + + } + + corEmitInt(ret, lowerBoundsDefined); // emit number of lower bounds + for(i=0; i < lowerBoundsDefined; i++) + { + unsigned cnt = CorSigCompressSignedInt(boundsArr[i].lowerBound, ret->getBuff(5)); + ret->remove(5 - cnt); + } + delete elemType; + delete bounds; + return(ret); +} + +/********************************************************************************/ +BinStr* AsmParse::MakeTypeClass(CorElementType kind, mdToken tk) +{ + + BinStr* ret = new BinStr(); + _ASSERTE(kind == ELEMENT_TYPE_CLASS || kind == ELEMENT_TYPE_VALUETYPE || + kind == ELEMENT_TYPE_CMOD_REQD || kind == ELEMENT_TYPE_CMOD_OPT); + ret->appendInt8(kind); + unsigned cnt = CorSigCompressToken(tk, ret->getBuff(5)); + ret->remove(5 - cnt); + return(ret); +} +/**************************************************************************/ +void PrintANSILine(FILE* pF, __in __nullterminated char* sz) +{ + WCHAR *wz = &wzUniBuf[0]; + if(g_uCodePage != CP_ACP) + { + memset(wz,0,dwUniBuf); // dwUniBuf/2 WCHARs = dwUniBuf bytes + WszMultiByteToWideChar(g_uCodePage,0,sz,-1,wz,(dwUniBuf >> 1)-1); + + memset(sz,0,dwUniBuf); + WszWideCharToMultiByte(g_uConsoleCP,0,wz,-1,sz,dwUniBuf-1,NULL,NULL); + } + fprintf(pF,"%s",sz); +} +/**************************************************************************/ +void AsmParse::error(const char* fmt, ...) +{ + char *sz = (char*)(&wzUniBuf[(dwUniBuf >> 1)]); + char *psz=&sz[0]; + FILE* pF = ((!assem->m_fReportProgress)&&(assem->OnErrGo)) ? stdout : stderr; + success = false; + va_list args; + va_start(args, fmt); + + if((penv) && (penv->in)) psz+=sprintf_s(psz, (dwUniBuf >> 1), "%S(%d) : ", penv->in->namew(), penv->curLine); + psz+=sprintf_s(psz, (dwUniBuf >> 1), "error : "); + _vsnprintf_s(psz, (dwUniBuf >> 1),(dwUniBuf >> 1)-strlen(sz)-1, fmt, args); + PrintANSILine(pF,sz); +} + +/**************************************************************************/ +void AsmParse::warn(const char* fmt, ...) +{ + char *sz = (char*)(&wzUniBuf[(dwUniBuf >> 1)]); + char *psz=&sz[0]; + FILE* pF = ((!assem->m_fReportProgress)&&(assem->OnErrGo)) ? stdout : stderr; + va_list args; + va_start(args, fmt); + + if((penv) && (penv->in)) psz+=sprintf_s(psz, (dwUniBuf >> 1), "%S(%d) : ", penv->in->namew(), penv->curLine); + psz+=sprintf_s(psz, (dwUniBuf >> 1), "warning : "); + _vsnprintf_s(psz, (dwUniBuf >> 1),(dwUniBuf >> 1)-strlen(sz)-1, fmt, args); + PrintANSILine(pF,sz); +} +/**************************************************************************/ +void AsmParse::msg(const char* fmt, ...) +{ + char *sz = (char*)(&wzUniBuf[(dwUniBuf >> 1)]); + va_list args; + va_start(args, fmt); + + _vsnprintf_s(sz, (dwUniBuf >> 1),(dwUniBuf >> 1)-1, fmt, args); + PrintANSILine(stdout,sz); +} + +#ifdef _MSC_VER +#pragma warning(default : 4640) +#endif diff --git a/src/coreclr/ilasm/grammar_before.cpp b/src/coreclr/ilasm/grammar_before.cpp new file mode 100644 index 00000000000..43b45bf36b9 --- /dev/null +++ b/src/coreclr/ilasm/grammar_before.cpp @@ -0,0 +1,137 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +#include <asmparse.h> +#include <assembler.h> + +// Disable the "initialization of static local vars is no thread safe" error +#ifdef _MSC_VER +#pragma warning(disable : 4640) +#endif + +#define YYMAXDEPTH 0x80000 +#define YYLOCAL int +//#define YYRECURSIVE + +//#define DEBUG_PARSING +#ifdef DEBUG_PARSING +bool parseDBFlag = true; +#define dbprintf(x) if (parseDBFlag) printf x +#define YYDEBUG 1 +#else +#define dbprintf(x) +#endif + +#define FAIL_UNLESS(cond, msg) if (!(cond)) { parser->success = false; parser->error msg; } + +static AsmParse* parser = 0; +#define PASM (parser->assem) +#define PASMM (parser->assem->m_pManifest) +#define PENV (parser->penv) + + + +PFN_NEXTCHAR nextchar; +PFN_SYM Sym; +PFN_NEWSTRFROMTOKEN NewStrFromToken; +PFN_NEWSTATICSTRFROMTOKEN NewStaticStrFromToken; +PFN_GETDOUBLE GetDouble; + +void SetFunctionPtrs() +{ + nextchar = PENV->pfn_nextchar; + Sym = PENV->pfn_Sym; + NewStrFromToken = PENV->pfn_NewStrFromToken; + NewStaticStrFromToken = PENV->pfn_NewStaticStrFromToken; + GetDouble = PENV->pfn_GetDouble; +} + + +static char* newStringWDel(__in __nullterminated char* str1, char delimiter, __in __nullterminated char* str3 = 0); +static char* newString(__in __nullterminated const char* str1); +static void corEmitInt(BinStr* buff, unsigned data); +static void AppendStringWithLength(BinStr* pbs, __in __nullterminated char* sz); +bool bParsingByteArray = FALSE; +int iOpcodeLen = 0; +int iCallConv = 0; +unsigned IfEndif = 0; +unsigned IfEndifSkip = 0; +unsigned nCustomBlobNVPairs = 0; +unsigned nSecAttrBlobs = 0; +unsigned nCurrPC = 0; +BOOL SkipToken = FALSE; +BOOL neg = FALSE; +BOOL newclass = FALSE; + +extern unsigned int g_uConsoleCP; + +struct VarName +{ + char* name; + BinStr* pbody; + VarName(__in_opt __nullterminated char* sz, BinStr* pbs) { name = sz; pbody = pbs; }; + ~VarName() { delete [] name; delete pbody; }; + int ComparedTo(VarName* pN) { return strcmp(name,pN->name); }; +}; +SORTEDARRAY<VarName> VarNameList; +void DefineVar(__in __nullterminated char* sz, BinStr* pbs) { VarNameList.PUSH(new VarName(sz,pbs)); }; +void UndefVar(__in __nullterminated char* sz) +{ + CHECK_LOCAL_STATIC_VAR(static VarName VN(NULL,NULL)); + + VN.name = sz; + VarNameList.DEL(&VN); + VN.name = NULL; + delete [] sz; +} +VarName* FindVarDef(__in __nullterminated char* sz) +{ + CHECK_LOCAL_STATIC_VAR(static VarName VN(NULL,NULL)); + + VarName* Ret = NULL; + VN.name = sz; + Ret = VarNameList.FIND(&VN); + VN.name = NULL; + delete [] sz; + return Ret; +} +BOOL IsVarDefined(__in __nullterminated char* sz) +{ + return (FindVarDef(sz) != NULL); +} + +int nTemp=0; + +unsigned int uMethodBeginLine,uMethodBeginColumn; + +#define ELEMENT_TYPE_VARFIXUP (ELEMENT_TYPE_MAX+2) +#define ELEMENT_TYPE_MVARFIXUP (ELEMENT_TYPE_MAX+3) + +FIFO<char> TyParFixupList; +void FixupTyPars(PCOR_SIGNATURE pSig, ULONG cSig); +void FixupTyPars(BinStr* pbstype); +void FixupConstraints() +{ + if((TyParFixupList.COUNT()) && (PASM->m_TyParList)) + { + TyParList* pTPL; + for(pTPL = PASM->m_TyParList; pTPL; pTPL=pTPL->Next()) + { + mdToken* ptk; + for(ptk = (mdToken*)(pTPL->Bound()->ptr()); *ptk; ptk++) + { + if(TypeFromToken(*ptk)==mdtTypeSpec) + { + PCOR_SIGNATURE pSig; + ULONG cSig; + PASM->m_pImporter->GetTypeSpecFromToken(*ptk,(PCCOR_SIGNATURE*)&pSig,&cSig); + if((pSig)&&(cSig)) + { + FixupTyPars(pSig,cSig); + } // end if((pSig)&&(cSig)) + } // end if(TypeFromToken(*ptk)==mdtTypeSpec) + } //end for(ptk + } // end for(pTPL + } //end if((TyParFixupList.COUNT()) +} + +#define SET_PA(x,y,z) {x = (CorAssemblyFlags)(((y) & ~afPA_FullMask)|(z)|afPA_Specified);} diff --git a/src/coreclr/ilasm/ilasmpch.h b/src/coreclr/ilasm/ilasmpch.h new file mode 100644 index 00000000000..ece4130ae57 --- /dev/null +++ b/src/coreclr/ilasm/ilasmpch.h @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if !defined(_ILASMPCH_H) +#define _ILASMPCH_H +#define NEW_INLINE_NAMES + +#include "cor.h" // for CorMethodAttr ... +#include <crtdbg.h> // For _ASSERTE +#include <corsym.h> + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include "utilcode.h" +#include "debugmacros.h" +#include "corpriv.h" + +#include "specstrings.h" +#include <string.h> // for strcmp +#include <ctype.h> // for isspace +#include "openum.h" // for CEE_* +#include <stdarg.h> // for vararg macros + +#include "mdfileformat.h" +#include "stgpooli.h" + +#endif diff --git a/src/coreclr/ilasm/main.cpp b/src/coreclr/ilasm/main.cpp new file mode 100644 index 00000000000..82a93d7eb52 --- /dev/null +++ b/src/coreclr/ilasm/main.cpp @@ -0,0 +1,1010 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// File: main.cpp +// + +// + +#include "ilasmpch.h" + +#include "asmparse.h" +#include "clrversion.h" +#include "shimload.h" + +#include "strsafe.h" +#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr)) + +WCHAR* EqualOrColon(__in __nullterminated WCHAR* szArg) +{ + WCHAR* pchE = wcschr(szArg,L'='); + WCHAR* pchC = wcschr(szArg,L':'); + WCHAR* ret; + if(pchE == NULL) ret = pchC; + else if(pchC == NULL) ret = pchE; + else ret = (pchE < pchC)? pchE : pchC; + return ret; +} + +static DWORD g_dwSubsystem=(DWORD)-1,g_dwComImageFlags=(DWORD)-1,g_dwFileAlignment=0,g_dwTestRepeat=0; +static ULONGLONG g_stBaseAddress=0; +static size_t g_stSizeOfStackReserve=0; +extern unsigned int g_uConsoleCP; +#ifdef TARGET_UNIX +char * g_pszExeFile; +#endif + +void MakeTestFile(__in __nullterminated char* szFileName) +{ + if(g_dwTestRepeat) + { + FILE* pF = NULL; + if(fopen_s(&pF,szFileName,"wt")==0 && pF != NULL) + { + printf("Making test file\n"); + fprintf(pF,".assembly extern mscorlib {}\n"); + fprintf(pF,".assembly test%d {}\n",g_dwTestRepeat); + fprintf(pF,".module test%d.exe\n",g_dwTestRepeat); + fprintf(pF,".method public static void Exec() { .entrypoint\n"); + for(unsigned i=0; i<g_dwTestRepeat*1000; i++) + { + fprintf(pF,"ldc.i4.1\ncall void [mscorlib]System.Console::WriteLine(int32)\n"); + } + fprintf(pF,"ret }\n"); + fclose(pF); + } + } +} + +void MakeProperSourceFileName(__in __nullterminated WCHAR* wzOrigName, + unsigned uCodePage, + __out_ecount(MAX_FILENAME_LENGTH) WCHAR* wzProperName, + __out_ecount(MAX_FILENAME_LENGTH*3) char* szProperName) +{ + wcscpy_s(wzProperName,MAX_FILENAME_LENGTH, wzOrigName); + size_t j = wcslen(wzProperName); + do + { + j--; + if(wzProperName[j] == '.') break; + if((wzProperName[j] == DIRECTORY_SEPARATOR_CHAR_A)||(j == 0)) + { + wcscat_s(wzProperName,MAX_FILENAME_LENGTH,W(".il")); + break; + } + } + while(j); + WszWideCharToMultiByte(uCodePage,0,wzProperName,-1,szProperName,MAX_FILENAME_LENGTH*3-1,NULL,NULL); +} + +char* FullFileName(__in __nullterminated WCHAR* wzFileName, unsigned uCodePage) +{ + static WCHAR wzFullPath[MAX_FILENAME_LENGTH]; + WCHAR* pwz; + WszGetFullPathName(wzFileName,MAX_FILENAME_LENGTH,wzFullPath,&pwz); + char szFullPath[MAX_FILENAME_LENGTH*3]; + WszWideCharToMultiByte(uCodePage,0,wzFullPath,-1,szFullPath,MAX_FILENAME_LENGTH*3-1,NULL,NULL); + char* sz = new char[strlen(szFullPath)+1]; + if(sz) strcpy_s(sz,strlen(szFullPath)+1,szFullPath); + return sz; +} + +WCHAR *pwzInputFiles[1024]; +WCHAR *pwzDeltaFiles[1024]; + +char szInputFilename[MAX_FILENAME_LENGTH*3]; +WCHAR wzInputFilename[MAX_FILENAME_LENGTH]; +WCHAR wzOutputFilename[MAX_FILENAME_LENGTH]; +WCHAR wzPdbFilename[MAX_FILENAME_LENGTH]; + + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:21000) // Suppress PREFast warning about overly large function +#endif + +extern "C" int _cdecl wmain(int argc, __in WCHAR **argv) +{ + int i, NumFiles = 0, NumDeltaFiles = 0; + bool IsDLL = false, IsOBJ = false; + Assembler *pAsm; + MappedFileStream *pIn; + AsmParse *pParser; + int exitval=1; + bool bLogo = TRUE; + bool bReportProgress = TRUE; + BOOL bGeneratePdb = FALSE; + PdbFormat pdbFormat = CLASSIC; + WCHAR* wzIncludePath = NULL; + int exitcode = 0; + unsigned uCodePage; + + bool bClock = false; + Clockwork cw; + +#ifdef HOST_WINDOWS + // SWI has requested that the exact form of the function call below be used. For details + // see http://swi/SWI%20Docs/Detecting%20Heap%20Corruption.doc + (void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); +#endif + + memset(pwzInputFiles,0,1024*sizeof(WCHAR*)); + memset(pwzDeltaFiles,0,1024*sizeof(WCHAR*)); + memset(&cw,0,sizeof(Clockwork)); + cw.cBegin = GetTickCount(); + + g_uConsoleCP = GetConsoleOutputCP(); + memset(wzOutputFilename,0,sizeof(wzOutputFilename)); + memset(wzPdbFilename, 0, sizeof(wzPdbFilename)); + +#ifdef _DEBUG + DisableThrowCheck(); + //CONTRACT_VIOLATION(ThrowsViolation); +#endif + + if(argc < 2) goto ErrorExit; +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:26000) // "Suppress prefast warning about index overflow" +#endif + if (! wcscmp(argv[1], W("/?")) || ! wcscmp(argv[1],W("-?"))) +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + { + printf("\nMicrosoft (R) .NET IL Assembler version " CLR_PRODUCT_VERSION); + printf("\n%S\n\n", VER_LEGALCOPYRIGHT_LOGO_STR_L); + goto PrintUsageAndExit; + + ErrorExit: + exitcode = 1; + PrintUsageAndExit: + printf("\n\nUsage: ilasm [Options] <sourcefile> [Options]"); + printf("\n\nOptions:"); + printf("\n/NOLOGO Don't type the logo"); + printf("\n/QUIET Don't report assembly progress"); + printf("\n/NOAUTOINHERIT Disable inheriting from System.Object by default"); + printf("\n/DLL Compile to .dll"); + printf("\n/EXE Compile to .exe (default)"); + printf("\n/PDB Create the PDB file without enabling debug info tracking"); + printf("\n/PDBFMT=CLASSIC Use classic PDB format for PDB file generation (default)"); + printf("\n/PDBFMT=PORTABLE Use portable PDB format for PDB file generation"); + printf("\n/APPCONTAINER Create an AppContainer exe or dll"); + printf("\n/DEBUG Disable JIT optimization, create PDB file, use sequence points from PDB"); + printf("\n/DEBUG=IMPL Disable JIT optimization, create PDB file, use implicit sequence points"); + printf("\n/DEBUG=OPT Enable JIT optimization, create PDB file, use implicit sequence points"); + printf("\n/OPTIMIZE Optimize long instructions to short"); + printf("\n/FOLD Fold the identical method bodies into one"); + printf("\n/CLOCK Measure and report compilation times"); +// printf("\n/ERROR Try to create .exe or .dll file despite errors reported"); +// printf("\n Warning! Results are unpredictable, use this option at your own risk!"); + printf("\n/OUTPUT=<targetfile> Compile to file with specified name \n\t\t\t(user must provide extension, if any)"); + printf("\n/KEY=<keyfile> Compile with strong signature \n\t\t\t(<keyfile> contains private key)"); + printf("\n/KEY=@<keysource> Compile with strong signature \n\t\t\t(<keysource> is the private key source name)"); + printf("\n/INCLUDE=<path> Set path to search for #include'd files"); + printf("\n/SUBSYSTEM=<int> Set Subsystem value in the NT Optional header"); + printf("\n/SSVER=<int>.<int> Set Subsystem version number in the NT Optional header"); + printf("\n/FLAGS=<int> Set CLR ImageFlags value in the CLR header"); + printf("\n/ALIGNMENT=<int> Set FileAlignment value in the NT Optional header"); + printf("\n/BASE=<int> Set ImageBase value in the NT Optional header (max 2GB for 32-bit images)"); + printf("\n/STACK=<int> Set SizeOfStackReserve value in the NT Optional header"); + printf("\n/MDV=<version_string> Set Metadata version string"); + printf("\n/MSV=<int>.<int> Set Metadata stream version (<major>.<minor>)"); + printf("\n/PE64 Create a 64bit image (PE32+)"); + printf("\n/HIGHENTROPYVA Set High Entropy Virtual Address capable PE32+ images (default for /APPCONTAINER)"); + printf("\n/NOCORSTUB Suppress generation of CORExeMain stub"); + printf("\n/STRIPRELOC Indicate that no base relocations are needed"); + printf("\n/X64 Target processor: 64bit AMD processor"); + printf("\n/ARM Target processor: ARM (AArch32) processor"); + printf("\n/ARM64 Target processor: ARM64 (AArch64) processor"); + printf("\n/32BITPREFERRED Create a 32BitPreferred image (PE32)"); + printf("\n/ENC=<file> Create Edit-and-Continue deltas from specified source file"); + + printf("\n\nKey may be '-' or '/'\nOptions are recognized by first 3 characters (except ARM/ARM64)\nDefault source file extension is .il\n"); + + printf("\nTarget defaults:"); + printf("\n/PE64 => /PE64 /X64"); + printf("\n/X64 => /PE64 /X64"); + printf("\n/ARM64 => /PE64 /ARM64"); + + printf("\n\n"); + exit(exitcode); + } + + uCodePage = CP_UTF8; + WszSetEnvironmentVariable(W("COMP_ENC_OPENSCOPE"), W("")); + WszSetEnvironmentVariable(W("COMP_ENC_EMIT"), W("")); + if((pAsm = new Assembler())) + { + pAsm->SetCodePage(uCodePage); + //if(pAsm->Init()) + { + pAsm->SetStdMapping(1); + //------------------------------------------------- + for (i = 1; i < argc; i++) + { +#ifdef TARGET_UNIX + if(argv[i][0] == L'-') +#else + if((argv[i][0] == L'/') || (argv[i][0] == L'-')) +#endif + { + char szOpt[3 + 1] = { 0 }; + WszWideCharToMultiByte(uCodePage, 0, &argv[i][1], 3, szOpt, sizeof(szOpt), NULL, NULL); + if (!_stricmp(szOpt, "NOA")) + { + pAsm->m_fAutoInheritFromObject = FALSE; + } + else if (!_stricmp(szOpt, "QUI")) + { + pAsm->m_fReportProgress = FALSE; + bReportProgress = FALSE; + bLogo = FALSE; + } + else if (!_stricmp(szOpt, "NOL")) + { + bLogo = FALSE; + } + else if (!_stricmp(szOpt, "FOL")) + { + pAsm->m_fFoldCode = TRUE; + } + else if (!_stricmp(szOpt, "DEB")) + { + bGeneratePdb = TRUE; + + pAsm->m_dwIncludeDebugInfo = 0x101; + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr != NULL) + { + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no suboption + else + { + WCHAR wzSubOpt[8]; + wcsncpy_s(wzSubOpt,8,pStr,3); + wzSubOpt[3] = 0; + if(0 == _wcsicmp(wzSubOpt,W("OPT"))) + pAsm->m_dwIncludeDebugInfo = 0x3; + else if(0 == _wcsicmp(wzSubOpt,W("IMP"))) + pAsm->m_dwIncludeDebugInfo = 0x103; + else + { + const WCHAR *pFmt =((*pStr == '0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld"); + if(swscanf_s(pStr,pFmt,&(pAsm->m_dwIncludeDebugInfo))!=1) + goto InvalidOption; // bad subooption + } + } + } + } + else if (!_stricmp(szOpt, "PDB")) + { + bGeneratePdb = TRUE; + + // check for /PDBFMT= command line option + char szOpt2[3 + 1] = { 0 }; + WszWideCharToMultiByte(uCodePage, 0, &argv[i][4], 3, szOpt2, sizeof(szOpt2), NULL, NULL); + if (!_stricmp(szOpt2, "FMT")) + { + WCHAR* pStr = EqualOrColon(argv[i]); + if (pStr != NULL) + { + for (pStr++; *pStr == L' '; pStr++); //skip the blanks + if (wcslen(pStr) == 0) + { + goto InvalidOption; //if no suboption + } + else + { + WCHAR wzSubOpt[8 + 1]; + wcsncpy_s(wzSubOpt, 8 + 1, pStr, 8); + wzSubOpt[8] = 0; + if (0 == _wcsicmp(wzSubOpt, W("CLASSIC"))) + pdbFormat = CLASSIC; + else if (0 == _wcsicmp(wzSubOpt, W("PORTABLE"))) + pdbFormat = PORTABLE; + else + goto InvalidOption; // bad subooption + } + } + else + { + goto InvalidOption; // bad subooption + } + } + else if (*szOpt2) + { + goto InvalidOption; // bad subooption + } + } + else if (!_stricmp(szOpt, "CLO")) + { + bClock = true; + pAsm->SetClock(&cw); + } + else if (!_stricmp(szOpt, "DLL")) + { + IsDLL = true; IsOBJ = false; + } + else if (!_stricmp(szOpt, "OBJ")) + { + //IsOBJ = true; IsDLL = false; + printf("Option /OBJECT is not supported.\n"); + goto ErrorExit; + } + else if (!_stricmp(szOpt, "ERR")) + { + pAsm->OnErrGo = true; + } + else if (!_stricmp(szOpt, "EXE")) + { + IsDLL = false; + } + else if (!_stricmp(szOpt, "APP")) + { + pAsm->m_fAppContainer = TRUE; + } + else if (!_stricmp(szOpt, "HIG")) + { + pAsm->m_fHighEntropyVA = TRUE; + } + else if (!_stricmp(szOpt, "OPT")) + { + pAsm->m_fOptimize = TRUE; + } + else if (!_stricmp(szOpt, "X64")) + { + pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK; + pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_AMD64; + } + else if (!_stricmp(szOpt, "ARM")) + { + // szOpt is only 3 characters long. That is not enough to distinguish "ARM" and "ARM64". + // We could change it to be longer, but that would affect the existing usability (ARM64 was + // added much later). Thus, just distinguish the two here. + char szOpt2[5 + 1] = { 0 }; + WszWideCharToMultiByte(uCodePage, 0, &argv[i][1], 5, szOpt2, sizeof(szOpt2), NULL, NULL); + if (!_stricmp(szOpt2, "ARM")) + { + pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK; + pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_ARM; + } + else if (!_stricmp(szOpt2, "ARM64")) + { + pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK; + pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_ARM64; + } + else + { + goto InvalidOption; + } + } + else if (!_stricmp(szOpt, "32B")) + { + if (g_dwComImageFlags == (DWORD)-1) + g_dwComImageFlags = pAsm->m_dwComImageFlags; + COR_SET_32BIT_PREFERRED(g_dwComImageFlags); + } + else if (!_stricmp(szOpt, "PE6")) + { + pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_PE32; + pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_PE64; + } + else if (!_stricmp(szOpt, "NOC")) + { + pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_CORMAIN_STUB; + } + else if (!_stricmp(szOpt, "STR")) + { + pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_STRIP_RELOCS; + } + else if (!_stricmp(szOpt, "OPT")) + { + pAsm->m_fOptimize = TRUE; + } + else if (!_stricmp(szOpt, "LIS")) + { + printf("Option /LISTING is not supported, use ILDASM.EXE\n"); + } + else if (!_stricmp(szOpt, "RES")) + { + if(pAsm->m_wzResourceFile==NULL) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto ErrorExit; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no file name + pAsm->m_wzResourceFile = pStr; + } + else + printf("Multiple resource files not allowed. Option %ls skipped\n",argv[i]); + } + else if (!_stricmp(szOpt, "KEY")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no file name + pAsm->m_wzKeySourceName = pStr; + } + else if (!_stricmp(szOpt, "INC")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no file name + wzIncludePath = pStr; + } + else if (!_stricmp(szOpt, "OUT")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no file name + if(wcslen(pStr) >= MAX_FILENAME_LENGTH) + { + fprintf(stderr,"\nError: Output file name exceeds %d characters\n",MAX_FILENAME_LENGTH-1); + goto ErrorExit; + } + wcscpy_s(wzOutputFilename,MAX_FILENAME_LENGTH,pStr); + } + else if (!_stricmp(szOpt, "MDV")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no version string + pAsm->m_wzMetadataVersion = pStr; + } + else if (!_stricmp(szOpt, "MSV")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no version + { + int major=-1,minor=-1; + if(swscanf_s(pStr,W("%d.%d"),&major, &minor)==2) + { + if((major >= 0)&&(major < 0xFF)) + pAsm->m_wMSVmajor = (WORD)major; + if((minor >= 0)&&(minor < 0xFF)) + pAsm->m_wMSVminor = (WORD)minor; + } + } + } + else if (!_stricmp(szOpt, "ENC")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no file name + pwzDeltaFiles[NumDeltaFiles++] = pStr; + pAsm->m_fTolerateDupMethods = TRUE; + } + else if (!_stricmp(szOpt, "SUB")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + pStr++; + const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld"); + if(swscanf_s(pStr,pFmt,&g_dwSubsystem)!=1) goto InvalidOption; + } + else if (!_stricmp(szOpt, "SSV")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + for(pStr++; *pStr == L' '; pStr++); //skip the blanks + if(wcslen(pStr)==0) goto InvalidOption; //if no version + { + int major=-1,minor=-1; + if(swscanf_s(pStr,W("%d.%d"),&major, &minor)==2) + { + if((major >= 0)&&(major < 0xFFFF)) + pAsm->m_wSSVersionMajor = (WORD)major; + if((minor >= 0)&&(minor < 0xFFFF)) + pAsm->m_wSSVersionMinor = (WORD)minor; + } else + goto InvalidOption; + } + } + else if (!_stricmp(szOpt, "ALI")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + pStr++; + const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld"); + if(swscanf_s(pStr,pFmt,&g_dwFileAlignment)!=1) goto InvalidOption; + if((g_dwFileAlignment & (g_dwFileAlignment-1)) + || (g_dwFileAlignment < 0x200) || (g_dwFileAlignment > 0x10000)) + { + fprintf(stderr,"\nFile Alignment must be power of 2 from 0x200 to 0x10000\n"); + if(!pAsm->OnErrGo) goto InvalidOption; + } + } + else if (!_stricmp(szOpt, "FLA")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + pStr++; + const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld"); + if(swscanf_s(pStr,pFmt,&g_dwComImageFlags)!=1) goto InvalidOption; + } + else if (!_stricmp(szOpt, "BAS")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + pStr++; + const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%I64x") : W("%I64d"); + if(swscanf_s(pStr,pFmt,&g_stBaseAddress)!=1) goto InvalidOption; + if(g_stBaseAddress & 0xFFFF) + { + fprintf(stderr,"\nBase address must be 0x10000-aligned\n"); + if(!pAsm->OnErrGo) goto InvalidOption; + } + } + else if (!_stricmp(szOpt, "STA")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + pStr++; + const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld"); + if(swscanf_s(pStr,pFmt,&g_stSizeOfStackReserve)!=1) goto InvalidOption; + } +#ifdef _SPECIAL_INTERNAL_USE_ONLY + else if (!_stricmp(szOpt, "TES")) + { + WCHAR *pStr = EqualOrColon(argv[i]); + if(pStr == NULL) goto InvalidOption; + pStr++; + WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%ld"; + if(swscanf_s(pStr,pFmt,&g_dwTestRepeat)!=1) goto InvalidOption; + } +#endif + else + { + InvalidOption: + fprintf(stderr, "Error : Invalid Option: %LS\n", argv[i]); + goto ErrorExit; + } + } + else + { + if(wcslen(argv[i]) >= MAX_FILENAME_LENGTH) + { + printf("\nError: Input file name exceeds %d characters\n",MAX_FILENAME_LENGTH-1); + goto ErrorExit; + } + pwzInputFiles[NumFiles++] = argv[i]; + if(NumFiles == 1) + { + MakeProperSourceFileName(argv[i], uCodePage, wzInputFilename, szInputFilename); + } + } + + } + if(NumFiles == 0) + { + delete pAsm; + goto ErrorExit; + } + if(pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64) + { + if((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386) + ||(pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM)) + { + printf("\nMachine type /ARM64 or /X64 must be specified for 64 bit targets."); + if(!pAsm->OnErrGo) + { + pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK; + pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_AMD64; + printf(" Type set to X64."); + } + printf("\n"); + } + } + else + { + if((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM64) + ||(pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_AMD64)) + { + printf("\n64 bit target must be specified for machine type /ARM64 or /X64."); + if(!pAsm->OnErrGo) + { + pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_PE32; + pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_PE64; + printf(" Target set to 64 bit."); + } + printf("\n"); + } + } + if(pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) + { + if(g_stBaseAddress > 0x80000000) + { + fprintf(stderr,"Invalid Image Base specified for 32-bit target\n"); + delete pAsm; + goto ErrorExit; + } + } + if (COR_IS_32BIT_PREFERRED(pAsm->m_dwComImageFlags) && + ((pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64) || + ((pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) == 0) || + ((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386) == 0) || + ((pAsm->m_dwComImageFlags & COMIMAGE_FLAGS_ILONLY) == 0))) + { + fprintf(stderr,"/32BITPREFERRED valid only with PE32/X86/ILONLY images\n"); + delete pAsm; + goto ErrorExit; + } + if (bGeneratePdb && CLASSIC == pdbFormat) + { + // Classic PDB format is not supported on CoreCLR + // https://github.com/dotnet/runtime/issues/5051 + + printf("WARNING: Classic PDB format is not supported on CoreCLR.\n"); + printf("Use '/PDBFMT=PORTABLE' option in order to generate portable PDB format. \n"); + } + if (!pAsm->Init(bGeneratePdb, pdbFormat)) + { + fprintf(stderr,"Failed to initialize Assembler\n"); + delete pAsm; + goto ErrorExit; + } + if(g_dwTestRepeat) + MakeTestFile(szInputFilename); + + if(wzOutputFilename[0] == 0) + { + wcscpy_s(wzOutputFilename,MAX_FILENAME_LENGTH,pwzInputFiles[0]); + size_t j = wcslen(wzOutputFilename); + do + { + j--; + if(wzOutputFilename[j] == L'.') + { + wzOutputFilename[j] = 0; + break; + } + } + while(j); + wcscat_s(wzOutputFilename, MAX_FILENAME_LENGTH,(IsDLL ? W(".dll") : (IsOBJ ? W(".obj") : W(".exe")))); + } + if (pAsm->m_fGeneratePDB) + { + wcscpy_s(wzPdbFilename, MAX_FILENAME_LENGTH, wzOutputFilename); + WCHAR* extPos = wcsrchr(wzPdbFilename, L'.'); + if (extPos != NULL) + *extPos = 0; + wcscat_s(wzPdbFilename, MAX_FILENAME_LENGTH, W(".pdb")); + char* pszPdbFilename = FullFileName(wzPdbFilename, uCodePage); + pAsm->SetPdbFileName(pszPdbFilename); + delete[] pszPdbFilename; + } + if(wzIncludePath == NULL) + { + PathString wzIncludePathBuffer; + if (0 != WszGetEnvironmentVariable(W("ILASM_INCLUDE"), wzIncludePathBuffer)) + { + wzIncludePath = wzIncludePathBuffer.GetCopyOfUnicodeString(); + + } + } + //------------ Assembler initialization done. Now, to business ----------------------- + if((pParser = new AsmParse(NULL, pAsm))) + { + uCodePage = CP_UTF8; + pAsm->SetCodePage(uCodePage); + pParser->SetIncludePath(wzIncludePath); + //====================================================================== + if(bLogo) + { + printf("\nMicrosoft (R) .NET IL Assembler. Version " CLR_PRODUCT_VERSION); + printf("\n%S", VER_LEGALCOPYRIGHT_LOGO_STR_L); + } + + pAsm->SetDLL(IsDLL); + pAsm->SetOBJ(IsOBJ); + wcscpy_s(pAsm->m_wzOutputFileName,MAX_FILENAME_LENGTH,wzOutputFilename); + strcpy_s(pAsm->m_szSourceFileName,MAX_FILENAME_LENGTH*3+1,szInputFilename); + + if (SUCCEEDED(pAsm->InitMetaData())) + { + int iFile; + BOOL fAllFilesPresent = TRUE; + if(bClock) cw.cParsBegin = GetTickCount(); + for(iFile = 0; iFile < NumFiles; iFile++) + { + uCodePage = CP_UTF8; + pAsm->SetCodePage(uCodePage); + if(iFile) // for the first file, it's already done + { + MakeProperSourceFileName(pwzInputFiles[iFile], uCodePage, wzInputFilename, szInputFilename); + } + if(pAsm->m_fReportProgress) + { + pParser->msg("\nAssembling '%s' ", szInputFilename); + if(pAsm->m_fCPlusPlus) pParser->msg(" C++"); + if(pAsm->m_fWindowsCE) pParser->msg(" WINCE"); + if(!pAsm->m_fAutoInheritFromObject) pParser->msg(" NOAUTOINHERIT"); + pParser->msg(IsDLL ? " to DLL" : (IsOBJ? " to OBJ" : " to EXE")); + //====================================================================== + if (pAsm->m_fStdMapping == FALSE) + pParser->msg(", with REFERENCE mapping"); + + { + char szOutputFilename[MAX_FILENAME_LENGTH*3]; + memset(szOutputFilename,0,sizeof(szOutputFilename)); + WszWideCharToMultiByte(uCodePage,0,wzOutputFilename,-1,szOutputFilename,MAX_FILENAME_LENGTH*3-1,NULL,NULL); + pParser->msg(" --> '%s'\n", szOutputFilename); + } + } + + pIn = new MappedFileStream(wzInputFilename); + + if ((!pIn) || !(pIn->IsValid())) + { + pParser->msg("Could not open %s\n", szInputFilename); + fAllFilesPresent = FALSE; + } + else + { +#ifndef TARGET_UNIX + DWORD dwBinType; + if(GetBinaryTypeA(szInputFilename,&dwBinType)) + { + pParser->msg("%s is not a text file\n",szInputFilename); + fAllFilesPresent = FALSE; + } + else +#endif + { + pAsm->SetSourceFileName(FullFileName(wzInputFilename,uCodePage)); // deletes the argument! + + pParser->ParseFile(pIn); + } + } + if(pIn) + { + pIn->set_namew(NULL); + delete pIn; + } + } // end for(iFile) + if(bClock) cw.cParsEnd = GetTickCount(); + if ((pParser->Success() && fAllFilesPresent) || pAsm->OnErrGo) + { + HRESULT hr; + if(g_dwSubsystem != (DWORD)-1) pAsm->m_dwSubsystem = g_dwSubsystem; + if(g_dwComImageFlags != (DWORD)-1) pAsm->m_dwComImageFlags = g_dwComImageFlags; + if(g_dwFileAlignment) pAsm->m_dwFileAlignment = g_dwFileAlignment; + if(g_stBaseAddress) pAsm->m_stBaseAddress = g_stBaseAddress; + if(g_stSizeOfStackReserve) pAsm->m_stSizeOfStackReserve = g_stSizeOfStackReserve; + if(FAILED(hr=pAsm->CreatePEFile(wzOutputFilename))) + pParser->msg("Could not create output file, error code=0x%08X\n",hr); + else + { + if(pAsm->m_fFoldCode && pAsm->m_fReportProgress) + pParser->msg("%d methods folded\n",pAsm->m_dwMethodsFolded); + if(pParser->Success() && fAllFilesPresent) exitval = 0; + else + { + pParser->msg("Output file contains errors\n"); + if(pAsm->OnErrGo) exitval = 0; + } + if(exitval == 0) // Write the output file + { + if(bClock) cw.cFilegenEnd = GetTickCount(); + if(pAsm->m_fReportProgress) pParser->msg("Writing %s file\n", pAsm->m_fOBJ ? "COFF" : "PE"); + // Generate the file + if (FAILED(hr = pAsm->m_pCeeFileGen->GenerateCeeFile(pAsm->m_pCeeFile))) + { + exitval = 1; + pParser->msg("Failed to write output file, error code=0x%08X\n",hr); + } + // Generate PDB file + if (pAsm->m_fGeneratePDB) + { + if (pAsm->m_fReportProgress) pParser->msg("Writing PDB file: %s\n", pAsm->m_szPdbFileName); + if (FAILED(hr = pAsm->SavePdbFile())) + { + exitval = 1; + pParser->msg("Failed to write PDB file, error code=0x%08X\n", hr); + } + } + if(bClock) cw.cEnd = GetTickCount(); +#define ENC_ENABLED + if(exitval==0) + { + pAsm->m_fENCMode = TRUE; + WCHAR wzNewOutputFilename[MAX_FILENAME_LENGTH+16]; + for(iFile = 0; iFile < NumDeltaFiles; iFile++) + { + wcscpy_s(wzNewOutputFilename,MAX_FILENAME_LENGTH+16,wzOutputFilename); + exitval = _snwprintf_s(&wzNewOutputFilename[wcslen(wzNewOutputFilename)], 32, _TRUNCATE, + W(".%d"),iFile+1); + MakeProperSourceFileName(pwzDeltaFiles[iFile], uCodePage, wzInputFilename, szInputFilename); + if(pAsm->m_fReportProgress) + { + pParser->msg("\nAssembling delta '%s' ", szInputFilename); + if(pAsm->m_fCPlusPlus) pParser->msg(" C++"); + if(pAsm->m_fWindowsCE) pParser->msg(" WINCE"); + if(!pAsm->m_fAutoInheritFromObject) pParser->msg(" NOAUTOINHERIT"); + pParser->msg(" to DMETA,DIL"); + //====================================================================== + if (pAsm->m_fStdMapping == FALSE) + pParser->msg(", with REFERENCE mapping"); + + pParser->msg(" --> '%S.*'\n", wzNewOutputFilename); + } + exitval = 0; + pIn = new MappedFileStream(wzInputFilename); + + if ((!pIn) || !(pIn->IsValid())) + { + pParser->msg("Could not open %s\n", szInputFilename); + fAllFilesPresent = FALSE; + } + else + { +#ifndef TARGET_UNIX + DWORD dwBinType; + if(GetBinaryTypeA(szInputFilename,&dwBinType)) + { + pParser->msg("%s is not a text file\n",szInputFilename); + fAllFilesPresent = FALSE; + } + else +#endif + if (SUCCEEDED(pAsm->InitMetaDataForENC(wzNewOutputFilename, bGeneratePdb, pdbFormat))) + { + pAsm->SetSourceFileName(FullFileName(wzInputFilename,uCodePage)); // deletes the argument! + + pParser->ParseFile(pIn); + if (pParser->Success() || pAsm->OnErrGo) + { + exitval = 1; + if(FAILED(hr=pAsm->CreateDeltaFiles(wzNewOutputFilename))) + pParser->msg("Could not create output delta files, error code=0x%08X\n",hr); + else + { + if(pAsm->m_fFoldCode && pAsm->m_fReportProgress) + pParser->msg("%d methods folded\n",pAsm->m_dwMethodsFolded); + if(pParser->Success()) exitval = 0; + else pParser->msg("Output delta files contain errors\n"); + +#ifdef GENERATE_SUMMARY_PE_FILE + if(pAsm->OnErrGo) exitval = 0; + + //if(FAILED(hr=pAsm->CreatePEFile(wzOutputFilename))) + // pParser->msg("Could not create output file, error code=0x%08X\n",hr); + //else + { + if(pAsm->m_fReportProgress) pParser->msg("Writing %s file\n", pAsm->m_fOBJ ? "COFF" : "PE"); + // Generate the file + if (FAILED(hr = pAsm->m_pCeeFileGen->GenerateCeeFile(pAsm->m_pCeeFile))) + { + exitval = 1; + pParser->msg("Failed to write output file, error code=0x%08X\n",hr); + } + else if (pAsm->m_pManifest->m_sStrongName.m_fFullSign) + { + // Strong name sign the resultant assembly. + if(pAsm->m_fReportProgress) pParser->msg("Signing file with strong name\n"); + if (FAILED(hr=pAsm->StrongNameSign())) + { + exitval = 1; + pParser->msg("Failed to strong name sign output file, error code=0x%08X\n",hr); + } + } + } +#endif + } + } // end if (pParser->Success() || pAsm->OnErrGo) + } //end if (SUCCEEDED(pAsm->InitMetaDataForENC())) + } // end if ((!pIn) || !(pIn->IsValid())) -- else + if(pIn) + { + pIn->set_namew(NULL); + delete pIn; + } + } // end for(iFile) + } // end if(exitval==0) + } + + } + } + } + else pParser->msg("Failed to initialize Meta Data\n"); + delete pParser; + } + else printf("Could not create parser\n"); + } + //else printf("Failed to initialize Assembler\n"); + delete pAsm; + } + else printf("Insufficient memory\n"); + + WszSetEnvironmentVariable(W("COMP_ENC_OPENSCOPE"), W("")); + WszSetEnvironmentVariable(W("COMP_ENC_EMIT"), W("")); + + if (exitval || !bGeneratePdb) + { + // PE file was not created, or no debug info required. Kill PDB if any + WCHAR* pc = wcsrchr(wzOutputFilename,L'.'); + if(pc==NULL) + { + pc = &wzOutputFilename[wcslen(wzOutputFilename)]; + *pc = L'.'; + } + wcscpy_s(pc+1,4,W("PDB")); +#undef DeleteFileW + DeleteFileW(wzOutputFilename); + } + if (exitval == 0) + { + if(bReportProgress) printf("Operation completed successfully\n"); + if(bClock) + { + printf("Timing (msec): Total run %d\n",(cw.cEnd-cw.cBegin)); + printf(" Startup %d\n",(cw.cParsBegin-cw.cBegin)); + printf(" - MD initialization %d\n",(cw.cMDInitEnd - cw.cMDInitBegin)); + printf(" Parsing %d\n",(cw.cParsEnd - cw.cParsBegin)); + printf(" Emitting MD %d\n",(cw.cMDEmitEnd - cw.cRef2DefEnd)+(cw.cRef2DefBegin - cw.cMDEmitBegin)); + //printf(" - global fixups %d\n",(cw.cMDEmit1 - cw.cMDEmitBegin)); + printf(" - SN sig alloc %d\n",(cw.cMDEmit2 - cw.cMDEmitBegin)); + printf(" - Classes,Methods,Fields %d\n",(cw.cRef2DefBegin - cw.cMDEmit2)); + printf(" - Events,Properties %d\n",(cw.cMDEmit3 - cw.cRef2DefEnd)); + printf(" - MethodImpls %d\n",(cw.cMDEmit4 - cw.cMDEmit3)); + printf(" - Manifest,CAs %d\n",(cw.cMDEmitEnd - cw.cMDEmit4)); + printf(" Ref to Def resolution %d\n",(cw.cRef2DefEnd - cw.cRef2DefBegin)); + printf(" Fixup and linking %d\n",(cw.cFilegenBegin - cw.cMDEmitEnd)); + printf(" CEE file generation %d\n",(cw.cFilegenEnd - cw.cFilegenBegin)); + printf(" PE file writing %d\n",(cw.cEnd - cw.cFilegenEnd)); + } + } + else + { + printf("\n***** FAILURE ***** \n"); + } + exit(exitval); + return exitval; +} +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + + +#ifdef TARGET_UNIX +int main(int argc, char* str[]) +{ + g_pszExeFile = str[0]; + if (0 != PAL_Initialize(argc, str)) + { + fprintf(stderr,"Error: Fail to PAL_Initialize\n"); + exit(1); + } + + WCHAR **argv = new WCHAR*[argc]; + for (int i = 0; i < argc; i++) { + int length = MultiByteToWideChar(CP_ACP, 0, str[i], -1, NULL, 0); + ASSERTE_ALL_BUILDS(length != 0); + + LPWSTR result = new (nothrow) WCHAR[length]; + ASSERTE_ALL_BUILDS(result != NULL); + + length = MultiByteToWideChar(CP_ACP, 0, str[i], -1, result, length); + ASSERTE_ALL_BUILDS (length != 0); + + argv[i] = result; + } + + int ret = wmain(argc, argv); + + for (int i = 0 ; i < argc; i++) { + delete[] argv[i]; + } + delete[] argv; + + return ret; +} +#endif // TARGET_UNIX + diff --git a/src/coreclr/ilasm/method.cpp b/src/coreclr/ilasm/method.cpp new file mode 100644 index 00000000000..10fd7537f32 --- /dev/null +++ b/src/coreclr/ilasm/method.cpp @@ -0,0 +1,176 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// file: method.cpp +// + +// +#include "ilasmpch.h" +#include "assembler.h" + +Method::Method(Assembler *pAssembler, Class *pClass, __in __nullterminated char *pszName, BinStr* pbsSig, DWORD Attr) +{ + + // default values + m_pClass = pClass; + m_MaxStack = 8; + m_Flags = 0; + m_LocalsSig = 0; + m_dwNumExceptions = 0; + m_dwNumEndfilters = 0; + m_firstArgName = NULL; + m_firstVarName = NULL; + m_pMethodSig = NULL; + m_wImplAttr = miIL; //default, if native or optil are not specified + m_wVTEntry = 0; + m_wVTSlot = 0; + m_pAssembler = pAssembler; + m_pCurrScope = &m_MainScope; + m_pRetMarshal = NULL; + m_pRetValue = NULL; + m_szExportAlias = NULL; + m_dwExportOrdinal = 0xFFFFFFFF; + m_ulLines[0]=m_ulLines[1]=0; + m_ulColumns[0]=m_ulColumns[1]=0; + m_pbsBody = NULL; + m_fNewBody = TRUE; + m_fNew = TRUE; + + // move the PInvoke descriptor (if any) from Assembler + // (Assembler gets the descriptor BEFORE it calls new Method) + m_pPInvoke = pAssembler->m_pPInvoke; + pAssembler->m_pPInvoke = NULL; + + _ASSERTE(pszName); + if (!pszName) return; + + m_szName = pszName; + m_dwName = (DWORD)strlen(pszName); + + m_ExceptionList = new COR_ILMETHOD_SECT_EH_CLAUSE_FAT[MAX_EXCEPTIONS]; + m_EndfilterOffsetList = new DWORD[MAX_EXCEPTIONS]; + if((m_ExceptionList==NULL)||(m_EndfilterOffsetList==NULL)) + { + fprintf(stderr,"\nOutOfMemory!\n"); + return; + } + m_dwMaxNumExceptions = MAX_EXCEPTIONS; + m_dwMaxNumEndfilters = MAX_EXCEPTIONS; + + m_Attr = Attr; + if((!strcmp(pszName,COR_CCTOR_METHOD_NAME))||(!strcmp(pszName,COR_CTOR_METHOD_NAME))) + m_Attr |= mdSpecialName; + m_fEntryPoint = FALSE; + m_fGlobalMethod = FALSE; + + if(pbsSig) + { + m_dwMethodCSig = pbsSig->length(); + m_pMethodSig = (COR_SIGNATURE*)(pbsSig->ptr()); + m_pbsMethodSig = pbsSig; + } + + m_firstArgName = pAssembler->getArgNameList(); + if(pClass == NULL) pClass = pAssembler->m_pModuleClass; // fake "class" <Module> + pClass->m_MethodList.PUSH(this); + pClass->m_fNewMembers = TRUE; + + + m_pPermissions = NULL; + m_pPermissionSets = NULL; + + m_TyPars = NULL; + m_NumTyPars = 0; +} + + +// lexical scope handling +void Method::OpenScope() +{ + Scope* psc = new Scope; + if(psc) + { + psc->dwStart = m_pAssembler->m_CurPC; + psc->pSuperScope = m_pCurrScope; + m_pCurrScope->SubScope.PUSH(psc); + m_pCurrScope = psc; + } +} +void Method::CloseScope() +{ + VarDescr* pVD; + ARG_NAME_LIST* pAN; + for(pAN=m_pCurrScope->pLocals; pAN; pAN = pAN->pNext) + { + if((pVD = m_Locals.PEEK(pAN->dwAttr))) pVD->bInScope = FALSE; + } + m_pCurrScope->dwEnd = m_pAssembler->m_CurPC; + m_pCurrScope = m_pCurrScope->pSuperScope; +} + +Label *Method::FindLabel(LPCUTF8 pszName) +{ + Label lSearch(pszName,0), *pL; + lSearch.m_szName = pszName; + //pL = m_lstLabel.FIND(&lSearch); + pL = m_pAssembler->m_lstLabel.FIND(&lSearch); + lSearch.m_szName = NULL; + return pL; + //return m_lstLabel.FIND(pszName); +} + + +Label *Method::FindLabel(DWORD PC) +{ + Label *pSearch; + + //for (int i = 0; (pSearch = m_lstLabel.PEEK(i)); i++) + for (int i = 0; (pSearch = m_pAssembler->m_lstLabel.PEEK(i)); i++) + { + if (pSearch->m_PC == PC) + return pSearch; + } + + return NULL; +} + +// Method::AddGenericParamConstraint is called when we have a .param constraint directive after a method definition +// +void Method::AddGenericParamConstraint(int index, char * pStrGenericParam, mdToken tkTypeConstraint) +{ + if (index > 0) + { + if (pStrGenericParam != 0) + { + m_pAssembler->report->error("LOGIC ERROR - we have both an index and a pStrGenericParam"); + return; + } + if (index > (int)m_NumTyPars) + { + m_pAssembler->report->error("Type parameter index out of range: 1.. %d\n", m_NumTyPars); + return; + } + index = index - 1; + } + else // index was 0, so a name must be supplied by pStrGenericParam + { + if (pStrGenericParam == 0) + { + m_pAssembler->report->error("LOGIC ERROR - we have neither an index or a pStrGenericParam"); + return; + } + index = FindTyPar(pStrGenericParam); + if (index == -1) + { + m_pAssembler->report->error("Type parameter '%s' undefined\n", pStrGenericParam); + return; + } + } + + // pass true for isParamDirective, we are parsing a .param directive for a method here + // + m_pAssembler->CheckAddGenericParamConstraint(&m_GPCList, index, tkTypeConstraint, true); +} + + + diff --git a/src/coreclr/ilasm/method.hpp b/src/coreclr/ilasm/method.hpp new file mode 100644 index 00000000000..c52a3a41e81 --- /dev/null +++ b/src/coreclr/ilasm/method.hpp @@ -0,0 +1,385 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// method.hpp +// +#ifndef _METHOD_HPP +#define _METHOD_HPP + +class Assembler; +class PermissionDecl; +class PermissionSetDecl; + +#define MAX_EXCEPTIONS 16 // init.number; increased by 16 when needed + +extern unsigned int g_uCodePage; +extern WCHAR wzUniBuf[]; + +/**************************************************************************/ +struct LinePC +{ + ULONG Line; + ULONG Column; + ULONG LineEnd; + ULONG ColumnEnd; + ULONG PC; + ISymUnmanagedDocumentWriter* pWriter; + Document* pOwnerDocument; + BOOL IsHidden; +}; +typedef FIFO<LinePC> LinePCList; + + +struct PInvokeDescriptor +{ + mdModuleRef mrDll; + char* szAlias; + DWORD dwAttrs; +}; + +struct TokenRelocDescr // for OBJ generation only! +{ + DWORD offset; + mdToken token; + TokenRelocDescr(DWORD off, mdToken tk) { offset = off; token = tk; }; +}; +typedef FIFO<TokenRelocDescr> TRDList; +/* structure - element of [local] signature name list */ + +struct ARG_NAME_LIST +{ + LPCUTF8 szName; //szName[1024]; + DWORD dwName; + BinStr* pSig; // argument's signature ptr + BinStr* pMarshal; + BinStr* pValue; + int nNum; + DWORD dwAttr; + CustomDescrList CustDList; + ARG_NAME_LIST *pNext; + __forceinline ARG_NAME_LIST(int i, LPCUTF8 sz, BinStr *pbSig, BinStr *pbMarsh, DWORD attr) + { + nNum = i; + //dwName = (DWORD)strlen(sz); + //strcpy(szName,sz); + szName = sz; + dwName = (sz == NULL) ? 0 : (DWORD)strlen(sz); + pNext = NULL; + pSig=pbSig; + pMarshal = pbMarsh; + dwAttr = attr; + pValue=NULL; + }; + inline ~ARG_NAME_LIST() + { + if(pSig) delete pSig; + if(pMarshal) delete pMarshal; + if(pValue) delete pValue; + if(szName) delete [] szName; + } +}; + +class Scope; +typedef FIFO<Scope> ScopeList; +class Scope +{ +public: + DWORD dwStart; + DWORD dwEnd; + ARG_NAME_LIST* pLocals; + ScopeList SubScope; + Scope* pSuperScope; + Scope() { dwStart = dwEnd = 0; pLocals = NULL; pSuperScope = NULL; }; + ~Scope() { Reset(); }; + void Reset() + { + ARG_NAME_LIST* pNext; + while(pLocals) { pNext = pLocals->pNext; delete pLocals; pLocals = pNext; } + Scope* pS; + while((pS = SubScope.POP()) != NULL) delete pS; + pSuperScope = NULL; + dwStart = dwEnd = 0; + }; +}; +struct VarDescr +{ + DWORD dwSlot; + BinStr* pbsSig; + BOOL bInScope; + VarDescr() { dwSlot = (DWORD) -1; pbsSig = NULL; bInScope = FALSE; }; +}; +typedef FIFO<VarDescr> VarDescrList; + + +struct Label +{ +//public: + LPCUTF8 m_szName; + DWORD m_PC; + + Label() :m_szName(NULL),m_PC(0){}; + Label(LPCUTF8 pszName, DWORD PC):m_szName(pszName),m_PC(PC){}; + ~Label(){ delete [] m_szName; }; + int ComparedTo(Label* L) { return strcmp(m_szName,L->m_szName); }; + //int Compare(char* L) { return strcmp(L,m_szName); }; + LPCUTF8 NameOf() { return m_szName; }; +}; +//typedef SORTEDARRAY<Label> LabelList; +typedef FIFO_INDEXED<Label> LabelList; + +class GlobalFixup +{ +public: + LPCUTF8 m_szLabel; + BYTE * m_pReference; // The place to fix up + + GlobalFixup(LPCUTF8 pszName, BYTE* pReference) + { + m_pReference = pReference; + m_szLabel = pszName; + } + ~GlobalFixup(){ delete [] m_szLabel; } +}; +typedef FIFO<GlobalFixup> GlobalFixupList; + + +class Fixup +{ +public: + LPCUTF8 m_szLabel; + BYTE * m_pBytes; // where to make the fixup + DWORD m_RelativeToPC; + BYTE m_FixupSize; + + Fixup(LPCUTF8 pszName, BYTE *pBytes, DWORD RelativeToPC, BYTE FixupSize) + { + m_pBytes = pBytes; + m_RelativeToPC = RelativeToPC; + m_FixupSize = FixupSize; + m_szLabel = pszName; + } + ~Fixup(){ delete [] m_szLabel; } +}; +typedef FIFO<Fixup> FixupList; + +typedef enum { ilRVA, ilToken, ilGlobal} ILFixupType; + +class ILFixup +{ +public: + ILFixupType m_Kind; + DWORD m_OffsetInMethod; + GlobalFixup * m_Fixup; + + ILFixup(DWORD Offset, ILFixupType Kind, GlobalFixup *Fix) + { + m_Kind = Kind; + m_OffsetInMethod = Offset; + m_Fixup = Fix; + } +}; +typedef FIFO<ILFixup> ILFixupList; + +class Method +{ +public: + Class *m_pClass; + //BinStr **m_TyParBounds; + //LPCWSTR *m_TyParNames; + TyParDescr* m_TyPars; + DWORD m_NumTyPars; + GenericParamConstraintList m_GPCList; + + DWORD m_SigInfoCount; + USHORT m_MaxStack; + mdSignature m_LocalsSig; + DWORD m_Flags; + char* m_szName; + DWORD m_dwName; + char* m_szExportAlias; + DWORD m_dwExportOrdinal; + COR_ILMETHOD_SECT_EH_CLAUSE_FAT *m_ExceptionList; + DWORD m_dwNumExceptions; + DWORD m_dwMaxNumExceptions; + DWORD* m_EndfilterOffsetList; + DWORD m_dwNumEndfilters; + DWORD m_dwMaxNumEndfilters; + DWORD m_Attr; + BOOL m_fEntryPoint; + BOOL m_fGlobalMethod; + BOOL m_fNewBody; + BOOL m_fNew; + DWORD m_methodOffset; + DWORD m_headerOffset; + BYTE * m_pCode; + DWORD m_CodeSize; + WORD m_wImplAttr; + ULONG m_ulLines[2]; + ULONG m_ulColumns[2]; + // PInvoke attributes + PInvokeDescriptor* m_pPInvoke; + // Security attributes + PermissionDecl* m_pPermissions; + PermissionSetDecl* m_pPermissionSets; + // VTable attributes + WORD m_wVTEntry; + WORD m_wVTSlot; + // Return marshaling + BinStr* m_pRetMarshal; + BinStr* m_pRetValue; + DWORD m_dwRetAttr; + CustomDescrList m_RetCustDList; + ILFixupList m_lstILFixup; + FixupList m_lstFixup; +// LabelList m_lstLabel; + // Member ref fixups + LocalMemberRefFixupList m_LocalMemberRefFixupList; + // Method body (header+code+EH) + BinStr* m_pbsBody; + mdToken m_Tok; + Method(Assembler *pAssembler, Class *pClass, __in __nullterminated char *pszName, BinStr* pbsSig, DWORD Attr); + ~Method() + { + m_lstFixup.RESET(true); + //m_lstLabel.RESET(true); + delete [] m_szName; + if(m_szExportAlias) delete [] m_szExportAlias; + delArgNameList(m_firstArgName); + delArgNameList(m_firstVarName); + delete m_pbsMethodSig; + delete [] m_ExceptionList; + delete [] m_EndfilterOffsetList; + if(m_pRetMarshal) delete m_pRetMarshal; + if(m_pRetValue) delete m_pRetValue; + while(m_MethodImplDList.POP()); // ptrs in m_MethodImplDList are dups of those in Assembler + if(m_pbsBody) delete m_pbsBody; + if(m_TyPars) delete [] m_TyPars; + }; + + BOOL IsGlobalMethod() + { + return m_fGlobalMethod; + }; + + void SetIsGlobalMethod() + { + m_fGlobalMethod = TRUE; + }; + + void delArgNameList(ARG_NAME_LIST *pFirst) + { + ARG_NAME_LIST *pArgList=pFirst, *pArgListNext; + for(; pArgList; pArgListNext=pArgList->pNext, + delete pArgList, + pArgList=pArgListNext); + }; + + ARG_NAME_LIST *catArgNameList(ARG_NAME_LIST *pBase, ARG_NAME_LIST *pAdd) + { + if(pAdd) //even if nothing to concatenate, result == head + { + ARG_NAME_LIST *pAN = pBase; + if(pBase) + { + int i; + for(; pAN->pNext; pAN = pAN->pNext) ; + pAN->pNext = pAdd; + i = pAN->nNum; + for(pAN = pAdd; pAN; pAN->nNum = ++i, pAN = pAN->pNext); + } + else pBase = pAdd; //nothing to concatenate to, result == tail + } + return pBase; + }; + + int findArgNum(ARG_NAME_LIST *pFirst, LPCUTF8 szArgName, DWORD dwArgName) + { + int ret=-1; + if(dwArgName) + { + ARG_NAME_LIST *pAN; + for(pAN=pFirst; pAN; pAN = pAN->pNext) + { + if((pAN->dwName == dwArgName)&& ((dwArgName==0)||(!strcmp(pAN->szName,szArgName)))) + { + ret = pAN->nNum; + break; + } + } + } + return ret; + }; + + int findLocSlot(ARG_NAME_LIST *pFirst, LPCUTF8 szArgName, DWORD dwArgName) + { + int ret=-1; + if(dwArgName) + { + ARG_NAME_LIST *pAN; + for(pAN=pFirst; pAN; pAN = pAN->pNext) + { + if((pAN->dwName == dwArgName)&& ((dwArgName==0)||(!strcmp(pAN->szName,szArgName)))) + { + ret = (int)(pAN->dwAttr); + break; + } + } + } + return ret; + }; + + BinStr *m_pbsMethodSig; + COR_SIGNATURE* m_pMethodSig; + DWORD m_dwMethodCSig; + ARG_NAME_LIST *m_firstArgName; + ARG_NAME_LIST *m_firstVarName; + // to call error() from Method: + const char* m_FileName; + unsigned m_LineNum; + // debug info + LinePCList m_LinePCList; + // custom values + CustomDescrList m_CustomDescrList; + // token relocs (used for OBJ generation only) + TRDList m_TRDList; + // method's own list of method impls + MethodImplDList m_MethodImplDList; + // lexical scope handling + Assembler* m_pAssembler; + Scope m_MainScope; + Scope* m_pCurrScope; + VarDescrList m_Locals; + void OpenScope(); + void CloseScope(); + + Label *FindLabel(LPCUTF8 pszName); + Label *FindLabel(DWORD PC); + + int FindTyPar(__in __nullterminated WCHAR* wz) + { + int i,retval=-1; + for(i=0; i < (int)m_NumTyPars; i++) + { + if(!wcscmp(wz,m_TyPars[i].Name())) + { + retval = i; + } + } + return retval; + }; + int FindTyPar(__in __nullterminated char* sz) + { + if(sz) + { + wzUniBuf[0] = 0; + WszMultiByteToWideChar(g_uCodePage,0,sz,-1,wzUniBuf,dwUniBuf); + return FindTyPar(wzUniBuf); + } + else return -1; + }; + + void AddGenericParamConstraint(int index, char * pStrGenericParam, mdToken tkTypeConstraint); +}; + +#endif /* _METHOD_HPP */ + diff --git a/src/coreclr/ilasm/nvpair.h b/src/coreclr/ilasm/nvpair.h new file mode 100644 index 00000000000..158df000aa4 --- /dev/null +++ b/src/coreclr/ilasm/nvpair.h @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +/***************************************************************************/ +/* Name value pair (both strings) which can be linked into a list of pairs */ + +#ifndef NVPAIR_H +#define NVPAIR_H + +#include "binstr.h" + +class NVPair +{ +public: + + NVPair(BinStr *name, BinStr *value) + { + m_Name = name; + m_Value = value; + m_Tail = NULL; + } + + ~NVPair() + { + delete m_Name; + delete m_Value; + delete m_Tail; + } + + NVPair *Concat(NVPair *list) + { + m_Tail = list; + return this; + } + + BinStr *Name() { return m_Name; } + BinStr *Value() { return m_Value; } + NVPair *Next() { return m_Tail; } + +private: + BinStr *m_Name; + BinStr *m_Value; + NVPair *m_Tail; +}; + +#endif diff --git a/src/coreclr/ilasm/portable_pdb.cpp b/src/coreclr/ilasm/portable_pdb.cpp new file mode 100644 index 00000000000..8da13f2e5d8 --- /dev/null +++ b/src/coreclr/ilasm/portable_pdb.cpp @@ -0,0 +1,398 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "portable_pdb.h" +#include <time.h> +#include "assembler.h" + +//***************************************************************************** +// Document +//***************************************************************************** +Document::Document() +{ + m_name = NULL; + m_token = mdDocumentNil; +} + +Document::~Document() +{ + if (m_name) + { + delete[] m_name; + m_name = NULL; + } + m_token = mdDocumentNil; +}; + +char* Document::GetName() +{ + return m_name; +} + +void Document::SetName(char* name) +{ + m_name = new char[strlen(name) + 1]; + strcpy_s(m_name, strlen(name) + 1, name); +} + +mdDocument Document::GetToken() +{ + return m_token; +} + +void Document::SetToken(mdDocument token) +{ + m_token = token; +} + + +//***************************************************************************** +// PortablePdbWriter +//***************************************************************************** +PortablePdbWriter::PortablePdbWriter() +{ + m_pdbStream.id.pdbGuid = { 0 }; + m_pdbStream.id.pdbTimeStamp = 0; + m_pdbStream.entryPoint = mdMethodDefNil; + m_pdbStream.referencedTypeSystemTables = 0UL; + m_pdbStream.typeSystemTableRows = new ULONG[TBL_COUNT]; + m_pdbStream.typeSystemTableRowsSize = 0; + m_currentDocument = NULL; + m_pdbEmitter = NULL; +} + +PortablePdbWriter::~PortablePdbWriter() +{ + if (m_pdbEmitter != NULL) + { + m_pdbEmitter->Release(); + m_pdbEmitter = NULL; + } + if (m_pdbStream.typeSystemTableRows != NULL) + { + delete[] m_pdbStream.typeSystemTableRows; + m_pdbStream.typeSystemTableRows = NULL; + } + + m_documentList.RESET(true); +} + +HRESULT PortablePdbWriter::Init(IMetaDataDispenserEx2* mdDispenser) +{ + HRESULT hr = S_OK; + if (m_pdbEmitter != NULL) + { + m_pdbEmitter->Release(); + m_pdbEmitter = NULL; + } + m_currentDocument = NULL; + m_documentList.RESET(true); + + memset(m_pdbStream.typeSystemTableRows, 0, sizeof(ULONG) * TBL_COUNT); + time_t now; + time(&now); + m_pdbStream.id.pdbTimeStamp = (ULONG)now; + hr = CoCreateGuid(&m_pdbStream.id.pdbGuid); + + if (FAILED(hr)) goto exit; + + hr = mdDispenser->DefinePortablePdbScope( + CLSID_CorMetaDataRuntime, + 0, + IID_IMetaDataEmit3, + (IUnknown**)&m_pdbEmitter); +exit: + return hr; +} + +IMetaDataEmit3* PortablePdbWriter::GetEmitter() +{ + return m_pdbEmitter; +} + +GUID* PortablePdbWriter::GetGuid() +{ + return &m_pdbStream.id.pdbGuid; +} + +ULONG PortablePdbWriter::GetTimestamp() +{ + return m_pdbStream.id.pdbTimeStamp; +} + +Document* PortablePdbWriter::GetCurrentDocument() +{ + return m_currentDocument; +} + +HRESULT PortablePdbWriter::BuildPdbStream(IMetaDataEmit3* peEmitter, mdMethodDef entryPoint) +{ + HRESULT hr = S_OK; + + m_pdbStream.entryPoint = entryPoint; + + if (FAILED(hr = peEmitter->GetReferencedTypeSysTables( + &m_pdbStream.referencedTypeSystemTables, + m_pdbStream.typeSystemTableRows, + TBL_COUNT, + &m_pdbStream.typeSystemTableRowsSize))) goto exit; + + if (FAILED(hr = m_pdbEmitter->DefinePdbStream(&m_pdbStream))) goto exit; + +exit: + return hr; +} + +HRESULT PortablePdbWriter::DefineDocument(char* name, GUID* language) +{ + HRESULT hr = S_OK; + Document* document = NULL; + unsigned i = 0; + + // did we already add a document with this name + while ((document = m_documentList.PEEK(i++)) != NULL) + { + if (!strcmp(name, document->GetName())) + break; + } + + if (document) + { + // found one in the list + // set it as current + m_currentDocument = document; + } + else + { + // define a new document + document = new Document(); + // save the document name, the 'name' parameter will be overriten - tokenized + document->SetName(name); + + // TODO: make use of hash algorithm and hash value + GUID hashAlgorithmUnknown = { 0 }; + BYTE* hashValue = NULL; + ULONG cbHashValue = 0; + mdDocument docToken = mdDocumentNil; + + if (FAILED(hr = m_pdbEmitter->DefineDocument( + name, // will be tokenized + &hashAlgorithmUnknown, + hashValue, + cbHashValue, + language, + &docToken))) + { + delete document; + m_currentDocument = NULL; + hr = E_FAIL; + } + else + { + document->SetToken(docToken); + m_currentDocument = document; + m_documentList.PUSH(document); + } + } + + return hr; +} + +HRESULT PortablePdbWriter::DefineSequencePoints(Method* method) +{ + HRESULT hr = S_OK; + BinStr* blob = new BinStr(); + + // Blob ::= header SequencePointRecord (SequencePointRecord | document-record)* + // SequencePointRecord :: = sequence-point-record | hidden-sequence-point-record + + // header ::= {LocalSignature, InitialDocument} + // LocalSignature + ULONG localSigRid = RidFromToken(method->m_LocalsSig); + CompressUnsignedLong(localSigRid, blob); + // InitialDocument TODO: skip this for now + + // SequencePointRecord + ULONG offset = 0; + ULONG deltaLines = 0; + LONG deltaColumns = 0; + LONG deltaStartLine = 0; + LONG deltaStartColumn = 0; + LinePC* currSeqPoint = NULL; + LinePC* prevSeqPoint = NULL; + LinePC* prevNonHiddenSeqPoint = NULL; + LinePC* nextSeqPoint = NULL; + BOOL isValid = TRUE; + + for (UINT32 i = 0; i < method->m_LinePCList.COUNT(); i++) + { + currSeqPoint = method->m_LinePCList.PEEK(i); + if (i < (method->m_LinePCList.COUNT() - 1)) + nextSeqPoint = method->m_LinePCList.PEEK(i + 1); + else + nextSeqPoint = NULL; + + isValid = VerifySequencePoint(currSeqPoint, nextSeqPoint); + if (!isValid) + { + method->m_pAssembler->report->warn("Sequence point at line: [0x%x] and offset: [0x%x] in method '%s' is not valid!\n", + currSeqPoint->Line, + currSeqPoint->PC, + method->m_szName); + hr = E_FAIL; + break; // TODO: break or ignore? + } + + if (!currSeqPoint->IsHidden) + { + //offset + offset = (i == 0) ? currSeqPoint->PC : currSeqPoint->PC - prevSeqPoint->PC; + CompressUnsignedLong(offset, blob); + + //delta lines + deltaLines = currSeqPoint->LineEnd - currSeqPoint->Line; + CompressUnsignedLong(deltaLines, blob); + + //delta columns + deltaColumns = currSeqPoint->ColumnEnd - currSeqPoint->Column; + if (deltaLines == 0) + CompressUnsignedLong(deltaColumns, blob); + else + CompressSignedLong(deltaColumns, blob); + + //delta start line + if (prevNonHiddenSeqPoint == NULL) + { + deltaStartLine = currSeqPoint->Line; + CompressUnsignedLong(deltaStartLine, blob); + } + else + { + deltaStartLine = currSeqPoint->Line - prevNonHiddenSeqPoint->Line; + CompressSignedLong(deltaStartLine, blob); + } + + //delta start column + if (prevNonHiddenSeqPoint == NULL) + { + deltaStartColumn = currSeqPoint->Column; + CompressUnsignedLong(deltaStartColumn, blob); + } + else + { + deltaStartColumn = currSeqPoint->Column - prevNonHiddenSeqPoint->Column; + CompressSignedLong(deltaStartColumn, blob); + } + + prevNonHiddenSeqPoint = currSeqPoint; + } + else + { + //offset + offset = (i == 0) ? currSeqPoint->PC : currSeqPoint->PC - prevSeqPoint->PC; + CompressUnsignedLong(offset, blob); + + //delta lines + deltaLines = 0; + CompressUnsignedLong(deltaLines, blob); + + //delta lines + deltaColumns = 0; + CompressUnsignedLong(deltaColumns, blob); + } + prevSeqPoint = currSeqPoint; + } + + // finally define sequence points for the method + if (isValid && currSeqPoint != NULL) + { + ULONG documentRid = RidFromToken(currSeqPoint->pOwnerDocument->GetToken()); + hr = m_pdbEmitter->DefineSequencePoints(documentRid, blob->ptr(), blob->length()); + } + + delete blob; + return hr; +} + +HRESULT PortablePdbWriter::DefineLocalScope(Method* method) +{ + if (!_DefineLocalScope(method->m_Tok, &method->m_MainScope)) + return E_FAIL; + else + return S_OK; +} + +BOOL PortablePdbWriter::_DefineLocalScope(mdMethodDef methodDefToken, Scope* currScope) +{ + BOOL fSuccess = FALSE; + ARG_NAME_LIST* pLocalVar = currScope->pLocals; + ULONG methodRid = RidFromToken(methodDefToken); + ULONG importScopeRid = RidFromToken(mdImportScopeNil); // TODO: not supported for now + ULONG firstLocalVarRid = 0; + ULONG firstLocalConstRid = RidFromToken(mdLocalConstantNil); // TODO: not supported for now + ULONG start = 0; + ULONG length = 0; + mdLocalVariable firstLocVarToken = mdLocalScopeNil; + + while (pLocalVar != NULL) + { + mdLocalVariable locVarToken = mdLocalScopeNil; + USHORT attribute = 0; // TODO: not supported for now + USHORT index = pLocalVar->dwAttr & 0xffff; // slot + if (FAILED(m_pdbEmitter->DefineLocalVariable(attribute, index, (char*)pLocalVar->szName, &locVarToken))) goto exit; + + if (firstLocVarToken == mdLocalScopeNil) + firstLocVarToken = locVarToken; + + pLocalVar = pLocalVar->pNext; + } + + if (firstLocVarToken != mdLocalScopeNil) + { + firstLocalVarRid = RidFromToken(firstLocVarToken); + start = currScope->dwStart; + length = currScope->dwEnd - currScope->dwStart; + if (FAILED(m_pdbEmitter->DefineLocalScope(methodRid, importScopeRid, firstLocalVarRid, firstLocalConstRid, start, length))) goto exit; + } + + fSuccess = TRUE; + for (ULONG i = 0; i < currScope->SubScope.COUNT(); i++) + fSuccess &= _DefineLocalScope(methodDefToken, currScope->SubScope.PEEK(i)); + +exit: + return fSuccess; +} + +BOOL PortablePdbWriter::VerifySequencePoint(LinePC* curr, LinePC* next) +{ + if (!curr->IsHidden) + { + if ((curr->PC >= 0 && curr->PC < 0x20000000) && + (next == NULL || (next != NULL && curr->PC < next->PC)) && + (curr->Line >= 0 && curr->Line < 0x20000000 && curr->Line != 0xfeefee) && + (curr->LineEnd >= 0 && curr->LineEnd < 0x20000000 && curr->LineEnd != 0xfeefee) && + (curr->Column >= 0 && curr->Column < 0x10000) && + (curr->ColumnEnd >= 0 && curr->ColumnEnd < 0x10000) && + (curr->LineEnd > curr->Line || (curr->Line == curr->LineEnd && curr->ColumnEnd > curr->Column))) + { + return TRUE; + } + else + { + return FALSE; + } + } + return TRUE; +} + +void PortablePdbWriter::CompressUnsignedLong(ULONG srcData, BinStr* dstBuffer) +{ + ULONG cnt = CorSigCompressData(srcData, dstBuffer->getBuff(sizeof(ULONG) + 1)); + dstBuffer->remove((sizeof(ULONG) + 1) - cnt); +} + +void PortablePdbWriter::CompressSignedLong(LONG srcData, BinStr* dstBuffer) +{ + ULONG cnt = CorSigCompressSignedInt(srcData, dstBuffer->getBuff(sizeof(LONG) + 1)); + dstBuffer->remove((sizeof(LONG) + 1) - cnt); +} diff --git a/src/coreclr/ilasm/portable_pdb.h b/src/coreclr/ilasm/portable_pdb.h new file mode 100644 index 00000000000..46bd1f14920 --- /dev/null +++ b/src/coreclr/ilasm/portable_pdb.h @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef PORTABLE_PDB_H +#define PORTABLE_PDB_H + +#include "ilasmpch.h" +#include "asmtemplates.h" +#include "portablepdbmdds.h" +#include "portablepdbmdi.h" + +//***************************************************************************** +// Document +//***************************************************************************** +class Document +{ +public: + Document(); + ~Document(); + char* GetName(); + void SetName(char* name); + mdDocument GetToken(); + void SetToken(mdDocument token); + +private: + char* m_name; + mdDocument m_token; +}; + +typedef FIFO<Document> DocumentList; + +class BinStr; +class Method; +class Scope; +struct LinePC; + +//***************************************************************************** +// PortablePdbWriter +//***************************************************************************** +class PortablePdbWriter +{ +public: + PortablePdbWriter(); + ~PortablePdbWriter(); + HRESULT Init(IMetaDataDispenserEx2* mdDispenser); + IMetaDataEmit3* GetEmitter(); + GUID* GetGuid(); + ULONG GetTimestamp(); + Document* GetCurrentDocument(); + HRESULT BuildPdbStream(IMetaDataEmit3* peEmitter, mdMethodDef entryPoint); + HRESULT DefineDocument(char* name, GUID* language); + HRESULT DefineSequencePoints(Method* method); + HRESULT DefineLocalScope(Method* method); + +private: + BOOL VerifySequencePoint(LinePC* curr, LinePC* next); + void CompressUnsignedLong(ULONG srcData, BinStr* dstBuffer); + void CompressSignedLong(LONG srcData, BinStr* dstBuffer); + BOOL _DefineLocalScope(mdMethodDef methodDefToken, Scope* currScope); + +private: + IMetaDataEmit3* m_pdbEmitter; + PORT_PDB_STREAM m_pdbStream; + DocumentList m_documentList; + Document* m_currentDocument; +}; + +#endif diff --git a/src/coreclr/ilasm/prebuilt/asmparse.cpp b/src/coreclr/ilasm/prebuilt/asmparse.cpp new file mode 100644 index 00000000000..4e7131a90a7 --- /dev/null +++ b/src/coreclr/ilasm/prebuilt/asmparse.cpp @@ -0,0 +1,4949 @@ +/* + * Created by Microsoft VCBU Internal YACC from "asmparse.y" + */ + +#line 2 "asmparse.y" + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// File asmparse.y +// +#include "ilasmpch.h" + +#include "grammar_before.cpp" + + +#line 16 "asmparse.y" + +#define UNION 1 +typedef union { + CorRegTypeAttr classAttr; + CorMethodAttr methAttr; + CorFieldAttr fieldAttr; + CorMethodImpl implAttr; + CorEventAttr eventAttr; + CorPropertyAttr propAttr; + CorPinvokeMap pinvAttr; + CorDeclSecurity secAct; + CorFileFlags fileAttr; + CorAssemblyFlags asmAttr; + CorAssemblyFlags asmRefAttr; + CorTypeAttr exptAttr; + CorManifestResourceFlags manresAttr; + double* float64; + __int64* int64; + __int32 int32; + char* string; + BinStr* binstr; + Labels* labels; + Instr* instr; // instruction opcode + NVPair* pair; + pTyParList typarlist; + mdToken token; + TypeDefDescr* tdd; + CustomDescr* cad; + unsigned short opcode; +} YYSTYPE; +# define ERROR_ 257 +# define BAD_COMMENT_ 258 +# define BAD_LITERAL_ 259 +# define ID 260 +# define DOTTEDNAME 261 +# define QSTRING 262 +# define SQSTRING 263 +# define INT32 264 +# define INT64 265 +# define FLOAT64 266 +# define HEXBYTE 267 +# define TYPEDEF_T 268 +# define TYPEDEF_M 269 +# define TYPEDEF_F 270 +# define TYPEDEF_TS 271 +# define TYPEDEF_MR 272 +# define TYPEDEF_CA 273 +# define DCOLON 274 +# define ELIPSIS 275 +# define VOID_ 276 +# define BOOL_ 277 +# define CHAR_ 278 +# define UNSIGNED_ 279 +# define INT_ 280 +# define INT8_ 281 +# define INT16_ 282 +# define INT32_ 283 +# define INT64_ 284 +# define FLOAT_ 285 +# define FLOAT32_ 286 +# define FLOAT64_ 287 +# define BYTEARRAY_ 288 +# define UINT_ 289 +# define UINT8_ 290 +# define UINT16_ 291 +# define UINT32_ 292 +# define UINT64_ 293 +# define FLAGS_ 294 +# define CALLCONV_ 295 +# define MDTOKEN_ 296 +# define OBJECT_ 297 +# define STRING_ 298 +# define NULLREF_ 299 +# define DEFAULT_ 300 +# define CDECL_ 301 +# define VARARG_ 302 +# define STDCALL_ 303 +# define THISCALL_ 304 +# define FASTCALL_ 305 +# define CLASS_ 306 +# define TYPEDREF_ 307 +# define UNMANAGED_ 308 +# define FINALLY_ 309 +# define HANDLER_ 310 +# define CATCH_ 311 +# define FILTER_ 312 +# define FAULT_ 313 +# define EXTENDS_ 314 +# define IMPLEMENTS_ 315 +# define TO_ 316 +# define AT_ 317 +# define TLS_ 318 +# define TRUE_ 319 +# define FALSE_ 320 +# define _INTERFACEIMPL 321 +# define VALUE_ 322 +# define VALUETYPE_ 323 +# define NATIVE_ 324 +# define INSTANCE_ 325 +# define SPECIALNAME_ 326 +# define FORWARDER_ 327 +# define STATIC_ 328 +# define PUBLIC_ 329 +# define PRIVATE_ 330 +# define FAMILY_ 331 +# define FINAL_ 332 +# define SYNCHRONIZED_ 333 +# define INTERFACE_ 334 +# define SEALED_ 335 +# define NESTED_ 336 +# define ABSTRACT_ 337 +# define AUTO_ 338 +# define SEQUENTIAL_ 339 +# define EXPLICIT_ 340 +# define ANSI_ 341 +# define UNICODE_ 342 +# define AUTOCHAR_ 343 +# define IMPORT_ 344 +# define ENUM_ 345 +# define VIRTUAL_ 346 +# define NOINLINING_ 347 +# define AGGRESSIVEINLINING_ 348 +# define NOOPTIMIZATION_ 349 +# define AGGRESSIVEOPTIMIZATION_ 350 +# define UNMANAGEDEXP_ 351 +# define BEFOREFIELDINIT_ 352 +# define STRICT_ 353 +# define RETARGETABLE_ 354 +# define WINDOWSRUNTIME_ 355 +# define NOPLATFORM_ 356 +# define METHOD_ 357 +# define FIELD_ 358 +# define PINNED_ 359 +# define MODREQ_ 360 +# define MODOPT_ 361 +# define SERIALIZABLE_ 362 +# define PROPERTY_ 363 +# define TYPE_ 364 +# define ASSEMBLY_ 365 +# define FAMANDASSEM_ 366 +# define FAMORASSEM_ 367 +# define PRIVATESCOPE_ 368 +# define HIDEBYSIG_ 369 +# define NEWSLOT_ 370 +# define RTSPECIALNAME_ 371 +# define PINVOKEIMPL_ 372 +# define _CTOR 373 +# define _CCTOR 374 +# define LITERAL_ 375 +# define NOTSERIALIZED_ 376 +# define INITONLY_ 377 +# define REQSECOBJ_ 378 +# define CIL_ 379 +# define OPTIL_ 380 +# define MANAGED_ 381 +# define FORWARDREF_ 382 +# define PRESERVESIG_ 383 +# define RUNTIME_ 384 +# define INTERNALCALL_ 385 +# define _IMPORT 386 +# define NOMANGLE_ 387 +# define LASTERR_ 388 +# define WINAPI_ 389 +# define AS_ 390 +# define BESTFIT_ 391 +# define ON_ 392 +# define OFF_ 393 +# define CHARMAPERROR_ 394 +# define INSTR_NONE 395 +# define INSTR_VAR 396 +# define INSTR_I 397 +# define INSTR_I8 398 +# define INSTR_R 399 +# define INSTR_BRTARGET 400 +# define INSTR_METHOD 401 +# define INSTR_FIELD 402 +# define INSTR_TYPE 403 +# define INSTR_STRING 404 +# define INSTR_SIG 405 +# define INSTR_TOK 406 +# define INSTR_SWITCH 407 +# define _CLASS 408 +# define _NAMESPACE 409 +# define _METHOD 410 +# define _FIELD 411 +# define _DATA 412 +# define _THIS 413 +# define _BASE 414 +# define _NESTER 415 +# define _EMITBYTE 416 +# define _TRY 417 +# define _MAXSTACK 418 +# define _LOCALS 419 +# define _ENTRYPOINT 420 +# define _ZEROINIT 421 +# define _EVENT 422 +# define _ADDON 423 +# define _REMOVEON 424 +# define _FIRE 425 +# define _OTHER 426 +# define _PROPERTY 427 +# define _SET 428 +# define _GET 429 +# define _PERMISSION 430 +# define _PERMISSIONSET 431 +# define REQUEST_ 432 +# define DEMAND_ 433 +# define ASSERT_ 434 +# define DENY_ 435 +# define PERMITONLY_ 436 +# define LINKCHECK_ 437 +# define INHERITCHECK_ 438 +# define REQMIN_ 439 +# define REQOPT_ 440 +# define REQREFUSE_ 441 +# define PREJITGRANT_ 442 +# define PREJITDENY_ 443 +# define NONCASDEMAND_ 444 +# define NONCASLINKDEMAND_ 445 +# define NONCASINHERITANCE_ 446 +# define _LINE 447 +# define P_LINE 448 +# define _LANGUAGE 449 +# define _CUSTOM 450 +# define INIT_ 451 +# define _SIZE 452 +# define _PACK 453 +# define _VTABLE 454 +# define _VTFIXUP 455 +# define FROMUNMANAGED_ 456 +# define CALLMOSTDERIVED_ 457 +# define _VTENTRY 458 +# define RETAINAPPDOMAIN_ 459 +# define _FILE 460 +# define NOMETADATA_ 461 +# define _HASH 462 +# define _ASSEMBLY 463 +# define _PUBLICKEY 464 +# define _PUBLICKEYTOKEN 465 +# define ALGORITHM_ 466 +# define _VER 467 +# define _LOCALE 468 +# define EXTERN_ 469 +# define _MRESOURCE 470 +# define _MODULE 471 +# define _EXPORT 472 +# define LEGACY_ 473 +# define LIBRARY_ 474 +# define X86_ 475 +# define AMD64_ 476 +# define ARM_ 477 +# define ARM64_ 478 +# define MARSHAL_ 479 +# define CUSTOM_ 480 +# define SYSSTRING_ 481 +# define FIXED_ 482 +# define VARIANT_ 483 +# define CURRENCY_ 484 +# define SYSCHAR_ 485 +# define DECIMAL_ 486 +# define DATE_ 487 +# define BSTR_ 488 +# define TBSTR_ 489 +# define LPSTR_ 490 +# define LPWSTR_ 491 +# define LPTSTR_ 492 +# define OBJECTREF_ 493 +# define IUNKNOWN_ 494 +# define IDISPATCH_ 495 +# define STRUCT_ 496 +# define SAFEARRAY_ 497 +# define BYVALSTR_ 498 +# define LPVOID_ 499 +# define ANY_ 500 +# define ARRAY_ 501 +# define LPSTRUCT_ 502 +# define IIDPARAM_ 503 +# define IN_ 504 +# define OUT_ 505 +# define OPT_ 506 +# define _PARAM 507 +# define _OVERRIDE 508 +# define WITH_ 509 +# define NULL_ 510 +# define HRESULT_ 511 +# define CARRAY_ 512 +# define USERDEFINED_ 513 +# define RECORD_ 514 +# define FILETIME_ 515 +# define BLOB_ 516 +# define STREAM_ 517 +# define STORAGE_ 518 +# define STREAMED_OBJECT_ 519 +# define STORED_OBJECT_ 520 +# define BLOB_OBJECT_ 521 +# define CF_ 522 +# define CLSID_ 523 +# define VECTOR_ 524 +# define _SUBSYSTEM 525 +# define _CORFLAGS 526 +# define ALIGNMENT_ 527 +# define _IMAGEBASE 528 +# define _STACKRESERVE 529 +# define _TYPEDEF 530 +# define _TEMPLATE 531 +# define _TYPELIST 532 +# define _MSCORLIB 533 +# define P_DEFINE 534 +# define P_UNDEF 535 +# define P_IFDEF 536 +# define P_IFNDEF 537 +# define P_ELSE 538 +# define P_ENDIF 539 +# define P_INCLUDE 540 +# define CONSTRAINT_ 541 +#define yyclearin yychar = -1 +#define yyerrok yyerrflag = 0 +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 150 +#endif +YYSTYPE yylval, yyval; +#ifndef YYFARDATA +#define YYFARDATA /*nothing*/ +#endif +#if ! defined YYSTATIC +#define YYSTATIC /*nothing*/ +#endif +#if ! defined YYCONST +#define YYCONST /*nothing*/ +#endif +#ifndef YYACT +#define YYACT yyact +#endif +#ifndef YYPACT +#define YYPACT yypact +#endif +#ifndef YYPGO +#define YYPGO yypgo +#endif +#ifndef YYR1 +#define YYR1 yyr1 +#endif +#ifndef YYR2 +#define YYR2 yyr2 +#endif +#ifndef YYCHK +#define YYCHK yychk +#endif +#ifndef YYDEF +#define YYDEF yydef +#endif +#ifndef YYV +#define YYV yyv +#endif +#ifndef YYS +#define YYS yys +#endif +#ifndef YYLOCAL +#define YYLOCAL +#endif +#ifndef YYR_T +#define YYR_T int +#endif +typedef YYR_T yyr_t; +#ifndef YYEXIND_T +#define YYEXIND_T unsigned int +#endif +typedef YYEXIND_T yyexind_t; +#ifndef YYOPTTIME +#define YYOPTTIME 0 +#endif +# define YYERRCODE 256 + +#line 2062 "asmparse.y" + + +#include "grammar_after.cpp" +YYSTATIC YYCONST short yyexca[] = { +#if !(YYOPTTIME) +-1, 1, +#endif + 0, -1, + -2, 0, +#if !(YYOPTTIME) +-1, 452, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 622, +#endif + 274, 555, + 47, 555, + -2, 230, +#if !(YYOPTTIME) +-1, 643, +#endif + 40, 310, + 60, 310, + -2, 555, +#if !(YYOPTTIME) +-1, 665, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 690, +#endif + 274, 555, + 47, 555, + -2, 516, +#if !(YYOPTTIME) +-1, 809, +#endif + 123, 235, + -2, 555, +#if !(YYOPTTIME) +-1, 836, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 961, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 994, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 995, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1323, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1324, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1331, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1339, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1465, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1497, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1564, +#endif + 41, 538, + -2, 311, +#if !(YYOPTTIME) +-1, 1581, +#endif + 41, 538, + -2, 311, + +}; + +# define YYNPROD 844 +#if YYOPTTIME +YYSTATIC YYCONST yyexind_t yyexcaind[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 46, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 54, 0, 0, 0, 0, 0, + 0, 58, 0, 0, 0, 0, 0, 0, 0, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 78 +}; +#endif +# define YYLAST 3922 + +YYSTATIC YYCONST short YYFARDATA YYACT[] = { + 703, 1484, 414, 1416, 1133, 640, 660, 191, 1482, 1485, + 886, 1036, 971, 1483, 702, 788, 779, 885, 974, 729, + 73, 75, 150, 625, 1521, 536, 1417, 792, 755, 190, + 760, 757, 478, 176, 107, 972, 1146, 110, 106, 694, + 1077, 275, 860, 604, 662, 599, 273, 78, 81, 219, + 44, 24, 780, 262, 516, 214, 204, 7, 301, 188, + 654, 76, 6, 991, 85, 5, 1569, 3, 1206, 1253, + 220, 1125, 18, 1257, 115, 677, 1069, 264, 153, 1254, + 307, 133, 74, 178, 179, 180, 181, 272, 1123, 218, + 136, 10, 221, 300, 26, 137, 1070, 98, 278, 139, + 217, 1124, 17, 202, 203, 581, 269, 74, 719, 716, + 322, 265, 461, 113, 112, 700, 520, 939, 940, 352, + 343, 88, 87, 353, 89, 462, 1255, 452, 1025, 268, + 676, 338, 56, 537, 68, 1243, 1244, 305, 591, 88, + 87, 357, 89, 277, 225, 327, 277, 368, 339, 1031, + 342, 938, 361, 366, 185, 154, 1241, 1242, 98, 360, + 359, 358, 277, 56, 88, 87, 345, 89, 656, 1573, + 192, 782, 351, 783, 348, 365, 1537, 277, 86, 1039, + 369, 310, 312, 314, 316, 318, 374, 277, 362, 198, + 1038, 364, 699, 373, 199, 271, 200, 698, 1432, 84, + 105, 379, 201, 417, 418, 363, 376, 1138, 1139, 450, + 387, 451, 615, 88, 87, 186, 89, 388, 480, 195, + 814, 1071, 663, 1505, 456, 767, 1279, 457, 1578, 999, + 258, 473, 475, 416, 196, 1496, 484, 655, 481, 482, + 470, 491, 468, 472, 471, 501, 346, 216, 495, 1329, + 597, 1214, 192, 493, 441, 24, 833, 476, 479, 375, + 433, 7, 1278, 56, 801, 813, 486, 432, 664, 74, + 428, 492, 429, 483, 541, 436, 18, 641, 642, 487, + 586, 376, 585, 584, 544, 56, 1354, 1355, 1356, 587, + 941, 942, 267, 943, 435, 10, 154, 442, 26, 1337, + 1336, 1335, 1334, 494, 791, 434, 17, 777, 542, 572, + 74, 545, 714, 668, 575, 268, 576, 1249, 577, 1517, + 499, 600, 862, 863, 864, 579, 580, 371, 370, 1009, + 116, 511, 511, 528, 534, 108, 574, 372, 258, 571, + 266, 549, 573, 192, 488, 367, 88, 87, 154, 89, + 321, 1559, 601, 512, 512, 529, 535, 80, 79, 480, + 198, 505, 152, 410, 1435, 199, 74, 200, 613, 1560, + 348, 582, 583, 201, 74, 1130, 480, 46, 498, 481, + 482, 375, 621, 88, 596, 459, 89, 624, 80, 79, + 195, 1563, 607, 608, 609, 610, 481, 482, 1562, 606, + 420, 614, 421, 422, 423, 196, 745, 1368, 612, 474, + 611, 619, 620, 622, 485, 340, 341, 678, 1352, 639, + 644, 74, 1561, 500, 88, 87, 1248, 89, 1128, 955, + 56, 1153, 600, 595, 784, 135, 1154, 759, 649, 650, + 354, 355, 356, 652, 635, 1507, 1536, 348, 884, 182, + 643, 785, 56, 704, 1138, 1139, 666, 1408, 855, 321, + 177, 88, 674, 1140, 89, 74, 669, 1531, 970, 1514, + 685, 682, 951, 347, 566, 88, 1246, 46, 89, 74, + 538, 1506, 1267, 569, 1528, 867, 1362, 747, 88, 87, + 689, 89, 74, 671, 673, 1192, 1358, 1142, 696, 88, + 87, 786, 89, 990, 989, 988, 588, 983, 982, 981, + 980, 758, 978, 979, 105, 706, 987, 986, 985, 984, + 537, 690, 1468, 977, 975, 651, 715, 1001, 1002, 1003, + 1004, 88, 87, 692, 954, 177, 376, 693, 453, 155, + 648, 705, 80, 79, 480, 683, 701, 546, 727, 707, + 805, 61, 62, 47, 63, 709, 803, 710, 713, 1256, + 861, 539, 460, 645, 481, 482, 718, 177, 1520, 647, + 56, 1530, 88, 87, 225, 89, 74, 723, 1191, 659, + 728, 646, 967, 730, 277, 1529, 724, 597, 725, 675, + 976, 720, 80, 79, 1129, 762, 679, 680, 681, 413, + 734, 82, 506, 1526, 56, 768, 769, 49, 50, 51, + 52, 53, 54, 55, 74, 639, 1262, 1258, 1259, 1260, + 1261, 74, 754, 1524, 601, 744, 733, 748, 749, 750, + 1013, 98, 1011, 1012, 787, 543, 502, 72, 49, 50, + 51, 52, 53, 54, 55, 74, 643, 74, 684, 1522, + 477, 61, 62, 47, 63, 88, 87, 542, 89, 807, + 808, 802, 71, 751, 752, 753, 812, 793, 821, 74, + 514, 825, 819, 826, 822, 74, 695, 216, 70, 830, + 1184, 1183, 1182, 1181, 156, 157, 158, 831, 804, 806, + 74, 809, 74, 815, 480, 773, 774, 775, 790, 325, + 841, 842, 823, 797, 69, 800, 818, 80, 79, 67, + 377, 824, 832, 324, 481, 482, 348, 348, 854, 88, + 87, 225, 89, 834, 858, 88, 87, 865, 89, 1153, + 375, 672, 66, 930, 1154, 627, 628, 629, 49, 50, + 51, 52, 53, 54, 55, 192, 944, 945, 868, 56, + 853, 1153, 277, 856, 88, 87, 1154, 89, 74, 857, + 49, 50, 51, 52, 53, 54, 55, 601, 957, 600, + 1457, 630, 631, 632, 950, 1076, 1072, 1073, 1074, 1075, + 1455, 946, 152, 1344, 46, 382, 383, 384, 385, 111, + 177, 80, 79, 852, 74, 88, 87, 993, 89, 859, + 348, 773, 88, 87, 1021, 89, 1022, 1019, 74, 1453, + 362, 963, 956, 960, 966, 1018, 1451, 932, 46, 933, + 934, 935, 936, 937, 216, 823, 74, 1032, 1434, 593, + 1035, 637, 276, 1343, 968, 823, 606, 766, 997, 696, + 696, 496, 1026, 1044, 1020, 1425, 74, 441, 1007, 1016, + 1424, 1422, 1407, 433, 1027, 962, 1049, 829, 1024, 1047, + 432, 1029, 1028, 428, 517, 429, 1051, 1042, 436, 1006, + 1014, 528, 74, 1405, 80, 79, 480, 840, 1045, 1046, + 1395, 145, 973, 519, 1411, 670, 765, 435, 1005, 1015, + 442, 1008, 1017, 529, 823, 1062, 481, 482, 434, 1057, + 88, 87, 337, 89, 1393, 49, 50, 51, 52, 53, + 54, 55, 592, 277, 636, 277, 1391, 326, 323, 56, + 152, 1389, 1067, 1387, 1385, 277, 1383, 49, 50, 51, + 52, 53, 54, 55, 1381, 1379, 1376, 1373, 962, 1371, + 1367, 41, 43, 1351, 1327, 1209, 1208, 1056, 996, 1055, + 1134, 88, 87, 1315, 89, 762, 1079, 1054, 1080, 155, + 776, 63, 722, 46, 1053, 543, 1034, 1033, 1144, 828, + 1150, 1252, 616, 504, 820, 513, 737, 1131, 508, 509, + 618, 1136, 617, 1141, 578, 522, 527, 177, 565, 1065, + 1251, 308, 455, 1313, 109, 63, 1137, 1197, 92, 1145, + 1198, 1195, 1196, 964, 1316, 770, 1037, 520, 1311, 513, + 521, 1349, 508, 509, 1309, 1187, 1143, 695, 695, 992, + 1194, 1193, 145, 1207, 1190, 953, 1210, 1185, 1, 1418, + 1189, 1199, 1200, 1201, 1202, 1179, 1177, 1175, 1066, 589, + 1234, 1203, 1204, 1205, 1314, 49, 50, 51, 52, 53, + 54, 55, 712, 348, 88, 87, 1217, 89, 626, 1312, + 590, 1211, 1245, 1063, 1152, 1310, 1188, 1247, 152, 1218, + 1239, 1173, 1171, 1169, 145, 1238, 1237, 1240, 1186, 49, + 50, 51, 52, 53, 54, 55, 1180, 1178, 1176, 88, + 87, 348, 89, 74, 1167, 1165, 205, 155, 525, 352, + 1250, 711, 708, 353, 156, 157, 158, 1163, 192, 192, + 192, 192, 1135, 634, 277, 1161, 277, 1127, 192, 192, + 192, 357, 1174, 1172, 1170, 177, 591, 412, 378, 1433, + 626, 1263, 192, 46, 1159, 187, 794, 97, 88, 87, + 63, 89, 1157, 1430, 949, 1168, 1166, 1508, 1138, 1139, + 524, 1155, 351, 526, 317, 1266, 527, 1280, 1164, 1284, + 315, 1286, 1288, 1289, 1270, 1292, 1162, 1294, 1295, 1296, + 1297, 1298, 1299, 1300, 1274, 1302, 1303, 1304, 1305, 1306, + 1307, 1308, 1269, 1429, 313, 1160, 1317, 1318, 1291, 1320, + 1293, 1428, 1319, 1158, 1287, 1285, 1290, 152, 1301, 311, + 1419, 1236, 1156, 309, 1282, 308, 1060, 1322, 1212, 306, + 1213, 308, 1059, 844, 1328, 746, 667, 1233, 1333, 352, + 1332, 45, 94, 353, 49, 50, 51, 52, 53, 54, + 55, 454, 328, 329, 330, 308, 415, 88, 87, 277, + 89, 357, 156, 157, 158, 155, 591, 1558, 823, 1345, + 308, 1338, 1347, 1348, 308, 352, 1331, 332, 1330, 353, + 308, 56, 277, 152, 1272, 1353, 1357, 1147, 525, 277, + 140, 1215, 351, 177, 952, 1360, 1283, 357, 948, 1023, + 1359, 277, 827, 1281, 277, 138, 1350, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 1470, 839, 591, 1469, 838, 1361, 351, 817, + 63, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 591, 1346, + 524, 771, 764, 526, 1364, 258, 721, 796, 567, 117, + 1409, 1410, 349, 1414, 1396, 1413, 352, 1571, 1415, 591, + 772, 1043, 591, 591, 56, 1421, 1420, 931, 1583, 591, + 1426, 331, 303, 333, 334, 335, 336, 1574, 357, 1152, + 1572, 1565, 1541, 823, 1504, 1503, 88, 87, 1502, 89, + 1412, 1472, 1467, 134, 155, 1464, 1341, 96, 1423, 1461, + 104, 103, 102, 101, 1460, 99, 100, 105, 1456, 351, + 156, 157, 158, 1454, 49, 50, 51, 52, 53, 54, + 55, 1452, 177, 1450, 1437, 1509, 1431, 1427, 258, 1581, + 697, 1406, 1510, 1404, 1394, 1462, 1392, 1463, 1390, 1388, + 354, 355, 356, 97, 352, 1386, 836, 56, 353, 1473, + 1474, 1475, 88, 87, 1466, 89, 1471, 1384, 531, 1382, + 155, 88, 87, 1380, 89, 1378, 357, 1377, 1375, 1374, + 1488, 350, 1152, 1372, 1370, 1486, 56, 1369, 1366, 1489, + 1494, 1487, 88, 1365, 1566, 89, 1342, 1340, 177, 1476, + 1326, 1325, 1499, 1321, 1271, 46, 1498, 351, 1363, 1268, + 1235, 1516, 56, 1126, 1523, 1525, 1527, 1064, 1523, 1525, + 1527, 258, 1050, 206, 1534, 1525, 1048, 1041, 1040, 1532, + 1538, 1501, 1539, 1535, 1540, 1533, 1519, 1030, 969, 959, + 958, 947, 866, 1515, 1518, 1513, 849, 848, 846, 156, + 157, 158, 449, 843, 193, 1511, 837, 194, 835, 816, + 823, 795, 778, 742, 1523, 1525, 1527, 741, 740, 739, + 354, 355, 356, 738, 736, 88, 735, 688, 89, 638, + 198, 177, 570, 425, 424, 199, 344, 200, 46, 320, + 1564, 1497, 1493, 201, 1492, 1491, 1490, 1570, 1465, 1459, + 1458, 1568, 1449, 1448, 1447, 1446, 354, 355, 356, 1577, + 195, 1575, 1445, 1580, 1579, 156, 157, 158, 1582, 1444, + 1567, 1443, 1442, 1441, 1440, 196, 1439, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 1438, 1436, 823, 1315, 59, 523, 1313, 1576, 208, 259, + 210, 228, 212, 213, 1311, 1309, 1339, 56, 88, 882, + 1187, 89, 41, 43, 56, 1185, 876, 1179, 877, 878, + 879, 46, 1177, 1175, 1173, 1171, 515, 1169, 1167, 61, + 62, 47, 63, 1165, 1163, 1161, 1324, 354, 355, 356, + 223, 1323, 1265, 96, 1264, 56, 104, 103, 102, 101, + 46, 99, 100, 105, 222, 1078, 871, 872, 873, 1068, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 998, 1061, 1052, 46, 59, 995, 994, + 426, 208, 259, 210, 228, 212, 213, 961, 851, 226, + 224, 1058, 850, 847, 845, 41, 43, 732, 731, 717, + 691, 687, 870, 874, 875, 686, 880, 665, 633, 881, + 603, 530, 61, 62, 47, 63, 49, 50, 51, 52, + 53, 54, 55, 223, 602, 354, 355, 356, 594, 568, + 548, 547, 497, 419, 411, 386, 319, 222, 304, 518, + 302, 510, 507, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 503, 36, 184, 93, + 59, 33, 469, 467, 208, 259, 210, 228, 212, 213, + 466, 465, 226, 224, 95, 464, 244, 463, 41, 43, + 227, 243, 215, 209, 1098, 38, 30, 58, 32, 59, + 207, 211, 887, 31, 1010, 61, 62, 47, 63, 49, + 50, 51, 52, 53, 54, 55, 223, 41, 43, 1000, + 439, 38, 30, 58, 32, 59, 869, 799, 431, 798, + 222, 46, 430, 427, 61, 62, 47, 63, 46, 540, + 270, 60, 35, 41, 43, 83, 29, 21, 57, 34, + 37, 25, 16, 263, 15, 189, 14, 39, 40, 261, + 61, 62, 47, 63, 13, 226, 224, 60, 35, 46, + 260, 12, 11, 21, 9, 8, 37, 4, 2, 444, + 234, 242, 241, 39, 40, 240, 444, 239, 238, 237, + 236, 235, 49, 50, 51, 52, 53, 54, 55, 233, + 232, 231, 230, 229, 114, 77, 42, 756, 658, 657, + 1500, 299, 19, 20, 90, 22, 23, 48, 183, 27, + 28, 49, 50, 51, 52, 53, 54, 55, 1151, 761, + 789, 1273, 965, 1149, 1148, 605, 1479, 1478, 19, 20, + 1477, 22, 23, 48, 1495, 27, 28, 49, 50, 51, + 52, 53, 54, 55, 882, 1481, 1480, 1216, 1132, 598, + 661, 876, 781, 877, 878, 879, 448, 91, 58, 32, + 59, 1081, 743, 448, 65, 58, 32, 59, 64, 197, + 445, 883, 0, 0, 0, 446, 0, 445, 41, 43, + 929, 0, 446, 0, 0, 41, 43, 0, 0, 0, + 0, 871, 872, 873, 0, 61, 62, 47, 63, 1109, + 437, 438, 61, 62, 47, 63, 0, 437, 438, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1085, 1086, + 447, 1093, 1107, 1087, 1088, 1089, 1090, 447, 1091, 1092, + 0, 1108, 1094, 1095, 1096, 1097, 63, 870, 874, 875, + 0, 880, 0, 0, 881, 0, 532, 0, 0, 533, + 0, 0, 0, 0, 0, 443, 440, 0, 0, 0, + 0, 0, 443, 440, 0, 0, 0, 0, 0, 882, + 0, 0, 0, 0, 193, 0, 876, 194, 877, 878, + 879, 0, 49, 50, 51, 52, 53, 54, 55, 49, + 50, 51, 52, 53, 54, 55, 0, 0, 0, 0, + 198, 177, 0, 0, 0, 199, 0, 200, 0, 0, + 0, 0, 0, 201, 901, 0, 871, 872, 873, 0, + 49, 50, 51, 52, 53, 54, 55, 146, 928, 0, + 195, 0, 0, 893, 894, 0, 902, 919, 895, 896, + 897, 898, 0, 899, 900, 196, 920, 903, 904, 905, + 906, 0, 0, 0, 0, 348, 0, 0, 0, 0, + 0, 0, 870, 874, 875, 0, 880, 0, 0, 881, + 1232, 1231, 1226, 0, 1225, 1224, 1223, 1222, 0, 1220, + 1221, 105, 0, 1230, 1229, 1228, 1227, 0, 0, 0, + 0, 917, 1219, 921, 0, 990, 989, 988, 923, 983, + 982, 981, 980, 0, 978, 979, 105, 0, 987, 986, + 985, 984, 0, 0, 925, 977, 975, 0, 1542, 0, + 0, 0, 0, 0, 0, 1083, 1084, 0, 1099, 1100, + 1101, 0, 1102, 1103, 0, 0, 1104, 1105, 0, 1106, + 0, 0, 0, 0, 0, 0, 0, 926, 0, 0, + 0, 0, 1082, 1110, 1111, 1112, 1113, 1114, 1115, 1116, + 1117, 1118, 1119, 1120, 1121, 1122, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 901, + 0, 0, 976, 0, 0, 1512, 0, 0, 0, 0, + 0, 0, 0, 928, 0, 0, 0, 0, 893, 894, + 0, 902, 919, 895, 896, 897, 898, 0, 899, 900, + 0, 920, 903, 904, 905, 906, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 146, 0, 0, 0, 0, 888, 0, 889, + 890, 891, 892, 907, 908, 909, 924, 910, 911, 912, + 913, 914, 915, 916, 918, 922, 917, 0, 921, 927, + 0, 0, 0, 923, 0, 175, 0, 0, 0, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 925, + 168, 169, 0, 0, 171, 172, 173, 174, 564, 1557, + 152, 142, 162, 0, 0, 0, 0, 0, 0, 0, + 141, 147, 0, 1547, 0, 0, 0, 0, 0, 0, + 0, 0, 926, 0, 0, 0, 143, 144, 149, 1543, + 556, 0, 550, 551, 552, 553, 0, 0, 1552, 0, + 0, 146, 0, 0, 0, 0, 352, 0, 0, 0, + 772, 0, 1553, 1554, 1555, 1556, 0, 0, 0, 0, + 0, 160, 0, 0, 0, 0, 0, 0, 357, 558, + 559, 560, 561, 0, 0, 555, 0, 0, 0, 562, + 563, 554, 0, 0, 1544, 1545, 1546, 1548, 1549, 1550, + 1551, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 888, 0, 889, 890, 891, 892, 907, 908, + 909, 924, 910, 911, 912, 913, 914, 915, 916, 918, + 922, 990, 989, 988, 927, 983, 982, 981, 980, 0, + 978, 979, 105, 0, 987, 986, 985, 984, 0, 0, + 0, 977, 975, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, + 87, 0, 89, 0, 0, 0, 0, 155, 0, 0, + 175, 0, 0, 557, 151, 148, 163, 161, 170, 0, + 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, + 172, 173, 174, 146, 0, 177, 142, 162, 352, 0, + 0, 0, 353, 0, 0, 141, 147, 0, 976, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 357, 143, 144, 149, 0, 0, 175, 0, 0, 0, + 0, 0, 163, 161, 170, 0, 164, 165, 166, 167, + 0, 168, 169, 0, 0, 171, 172, 173, 174, 0, + 0, 623, 1276, 162, 0, 0, 160, 159, 88, 87, + 0, 89, 0, 0, 0, 0, 155, 0, 0, 175, + 0, 0, 0, 151, 148, 163, 161, 170, 0, 164, + 165, 166, 167, 0, 168, 169, 0, 0, 171, 172, + 173, 174, 0, 0, 177, 142, 162, 0, 0, 0, + 1277, 0, 0, 0, 141, 147, 0, 0, 0, 0, + 297, 198, 156, 157, 158, 0, 199, 0, 200, 1275, + 143, 144, 149, 0, 201, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 146, 0, 0, 0, 0, 352, + 0, 195, 284, 353, 279, 280, 281, 282, 283, 63, + 0, 0, 0, 287, 0, 160, 196, 354, 355, 356, + 0, 357, 285, 0, 0, 0, 0, 295, 0, 286, + 0, 641, 642, 0, 0, 0, 0, 0, 0, 0, + 0, 288, 289, 290, 291, 292, 293, 294, 298, 0, + 0, 0, 623, 0, 296, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 156, 157, 158, 0, 0, 0, 0, 0, 0, + 88, 87, 0, 89, 0, 0, 0, 0, 155, 146, + 0, 175, 0, 0, 0, 151, 148, 163, 161, 170, + 0, 164, 165, 166, 167, 0, 168, 169, 0, 0, + 171, 172, 173, 174, 0, 0, 177, 142, 162, 0, + 0, 0, 0, 0, 0, 0, 141, 147, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 143, 144, 149, 0, 0, 274, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 160, 0, 354, + 355, 356, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 641, 642, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, + 0, 88, 87, 0, 89, 0, 0, 0, 0, 155, + 0, 0, 175, 156, 157, 158, 151, 148, 163, 161, + 170, 0, 164, 165, 166, 167, 0, 168, 169, 0, + 0, 171, 172, 173, 174, 0, 146, 177, 142, 162, + 0, 0, 0, 0, 0, 0, 0, 141, 147, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 143, 144, 149, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 274, 0, 88, 87, 160, 89, + 354, 355, 356, 0, 155, 146, 0, 175, 0, 0, + 0, 151, 148, 163, 161, 170, 0, 164, 165, 166, + 167, 0, 168, 169, 0, 0, 171, 172, 173, 174, + 0, 0, 177, 142, 162, 0, 0, 0, 0, 0, + 0, 0, 141, 147, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 156, 157, 158, 0, 143, 144, + 149, 0, 811, 274, 88, 87, 0, 89, 0, 0, + 0, 0, 155, 0, 0, 175, 0, 146, 0, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, + 168, 169, 0, 160, 171, 172, 173, 174, 0, 0, + 177, 142, 162, 0, 0, 0, 0, 810, 0, 0, + 141, 147, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 143, 144, 149, 0, + 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 146, 0, 0, 156, + 157, 158, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 160, 159, 88, 87, 0, 89, 0, 0, 0, + 0, 155, 0, 0, 175, 0, 0, 0, 151, 148, + 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, + 169, 0, 0, 171, 172, 173, 174, 0, 0, 177, + 142, 162, 0, 0, 274, 0, 0, 0, 0, 141, + 147, 0, 0, 0, 0, 0, 0, 156, 157, 158, + 0, 0, 0, 0, 0, 143, 144, 149, 0, 0, + 0, 0, 88, 87, 0, 89, 0, 0, 0, 0, + 155, 0, 0, 175, 0, 0, 0, 151, 148, 163, + 161, 170, 0, 164, 165, 166, 167, 0, 168, 169, + 160, 0, 171, 172, 173, 174, 0, 0, 177, 142, + 162, 0, 0, 0, 0, 0, 0, 0, 763, 147, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 146, 0, 143, 144, 149, 0, 0, 0, + 0, 0, 0, 0, 88, 87, 0, 89, 0, 0, + 0, 0, 155, 0, 0, 175, 156, 157, 158, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 160, + 168, 169, 0, 0, 171, 172, 173, 174, 0, 0, + 177, 142, 162, 0, 0, 0, 0, 146, 0, 0, + 141, 147, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 143, 144, 149, 0, + 0, 0, 0, 88, 87, 0, 89, 0, 0, 0, + 0, 155, 0, 0, 175, 156, 157, 158, 151, 148, + 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, + 169, 653, 146, 171, 172, 173, 174, 0, 0, 177, + 142, 162, 88, 87, 0, 89, 0, 0, 0, 141, + 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 143, 144, 149, 0, 0, + 0, 0, 0, 0, 0, 0, 409, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 156, 157, 158, + 996, 0, 0, 146, 0, 0, 0, 0, 0, 0, + 458, 0, 0, 0, 391, 0, 0, 0, 407, 0, + 0, 389, 390, 0, 0, 0, 393, 394, 405, 395, + 396, 397, 398, 399, 400, 401, 402, 392, 0, 0, + 0, 0, 0, 0, 406, 0, 0, 404, 0, 0, + 0, 0, 0, 0, 403, 0, 0, 146, 0, 0, + 0, 726, 0, 408, 0, 0, 156, 157, 158, 489, + 175, 490, 0, 0, 151, 148, 163, 161, 170, 0, + 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, + 172, 173, 174, 0, 0, 177, 142, 162, 0, 0, + 0, 0, 0, 0, 0, 141, 147, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 143, 144, 149, 380, 175, 381, 0, 0, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, + 168, 169, 0, 0, 171, 172, 173, 174, 0, 0, + 0, 142, 162, 0, 0, 0, 160, 0, 0, 0, + 141, 147, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 143, 144, 149, 0, + 175, 0, 0, 0, 151, 148, 163, 161, 170, 0, + 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, + 172, 173, 174, 0, 0, 0, 142, 162, 0, 0, + 0, 160, 0, 0, 0, 141, 147, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 143, 144, 149, 0, 0, 0, 0, 0, 0, + 0, 175, 0, 0, 0, 151, 148, 163, 161, 170, + 0, 164, 165, 166, 167, 0, 168, 169, 0, 0, + 171, 172, 173, 174, 0, 0, 160, 142, 162, 0, + 0, 0, 0, 0, 0, 0, 141, 147, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 143, 144, 149, 175, 0, 0, 0, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, + 168, 169, 0, 0, 171, 172, 173, 174, 0, 0, + 0, 142, 162, 0, 0, 0, 0, 160, 0, 0, + 141, 147, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 143, 144, 149, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 160 +}; + +YYSTATIC YYCONST short YYFARDATA YYPACT[] = { +-1000, 1423,-1000, 609, 586,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 581, 555, 539, 514,-1000,-1000,-1000, 102, + 102, -466, 124, 124,-1000,-1000,-1000, 478,-1000, -115, + 535,-1000, 907, 1099, 68, 903, 102, -355, -356,-1000, + -139, 855, 68, 855,-1000,-1000,-1000, 172, 2319, 535, + 535, 535, 535,-1000,-1000, 187,-1000,-1000,-1000, -164, + 1074,-1000,-1000, 1825, 68, 68,-1000,-1000, 1368,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, 102, -121,-1000,-1000, +-1000,-1000, 691, -120, 2983, 1193,-1000,-1000,-1000,-1000, + 2436,-1000, 102,-1000, 1385,-1000, 1310, 1718, 68, 1169, + 1163, 1159, 1144, 1120, 1114, 1716, 1518, 83,-1000, 102, + 655, 878,-1000,-1000, 86, 1193, 535, 2983,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000, 1515, 185, 1288, 1061, -229, -230, -231, + -238, 691,-1000, -101, 691, 1255, 312,-1000,-1000, 48, +-1000, 3564, 239, 1081,-1000,-1000,-1000,-1000,-1000, 3394, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 504,-1000,-1000,-1000,-1000,-1000, 1193, 1715, 538, 1193, + 1193, 1193,-1000, 3232, 123,-1000,-1000, 1714, 1066, 2884, +-1000, 3564,-1000,-1000,-1000, 65, 65,-1000, 1713,-1000, +-1000, 99, 1513, 1512, 1575, 1397,-1000,-1000, 102,-1000, + 102, 87,-1000,-1000,-1000,-1000, 1173,-1000,-1000,-1000, +-1000,-1000, 901, 102, 3193,-1000, 21, -69,-1000,-1000, + 201, 102, 124, 610, 68, 201, 1255, 3339, 2983, -88, + 65, 2884, 1712,-1000, 215,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 511, 545, 860, 1606,-1000, 100,-1000, 355, 691,-1000, +-1000, 2983,-1000,-1000, 164, 1217, 65, 535,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000, 1711, 1710, 2114, + 895, 349, 1284, 1709, 123, 1511, -48,-1000, 102, -48, +-1000, 124,-1000, 102,-1000, 102,-1000, 102,-1000,-1000, +-1000,-1000, 891,-1000, 102, 102,-1000, 1193,-1000,-1000, +-1000, -369,-1000,-1000,-1000,-1000,-1000, 878, -47, 116, +-1000,-1000, 1193, 999,-1000, 1299, 789, 1708,-1000, 170, + 535, 157,-1000,-1000,-1000, 1704, 1690, 3564, 535, 535, + 535, 535,-1000, 691,-1000,-1000, 3564, 228,-1000, 1193, +-1000, -68,-1000, 1217, 879, 889, 887, 535, 535, 2721, +-1000,-1000,-1000,-1000,-1000,-1000, 102, 1299, 1070,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000, 406,-1000,-1000,-1000, 1688, + 1052,-1000, 791, 1508,-1000,-1000, 2580,-1000,-1000, 102, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 458, + 446, 417,-1000,-1000,-1000,-1000,-1000, 102, 102, 402, + 3124,-1000,-1000, -304, -196,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, -53, 1687,-1000, 102, 1158, 39, 65, 794, + 640, 102,-1000, -69, 107, 107, 107, 107, 2983, 215, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000, 1685, 1681, 1506,-1000,-1000,-1000, 2721,-1000,-1000, +-1000,-1000, 1299, 1680, 68, 3564,-1000, 201, 1285,-1000, + -119, -124,-1000,-1000, -351,-1000,-1000, 68, 411, 454, + 68,-1000,-1000, 1041,-1000,-1000, 68,-1000, 68,-1000, + 1040, 991,-1000,-1000, 535, -157, -360, 1679,-1000,-1000, +-1000,-1000, 535, -361,-1000,-1000, -346,-1000,-1000,-1000, + 1282,-1000, 869, 535, 3564, 1193, 3510, 102, 108, 1181, +-1000,-1000,-1000,-1000,-1000,-1000,-1000, 1678,-1000,-1000, +-1000,-1000,-1000,-1000, 1677,-1000,-1000, 1385, 108, 1505, +-1000, 1503, 883, 1502, 1498, 1497, 1496, 1492,-1000, 362, + 1157,-1000, 97, 1193,-1000,-1000,-1000, 298, 535, 108, + 388, 175, 3052,-1000,-1000, 1278, 1193,-1000, 793,-1000, +-1000, -50, 2983, 2983, 943, 1277, 1217, 1193, 1193, 1193, + 1193,-1000, 2418,-1000, 1193,-1000, 535, 535, 535, 867, + 1193, 33, 1193, 494, 1491,-1000, 128,-1000,-1000,-1000, +-1000,-1000,-1000, 102,-1000, 1299,-1000,-1000, 1255, 30, + 1076,-1000,-1000, 1193, 1490, 1202,-1000,-1000,-1000,-1000, +-1000,-1000, -10, 65, 465, 459, 2983, 2816, -106, -47, + 1488, 1265,-1000,-1000, 3510, -53, 881, 102, -96, 3564, + 102, 1193, 102, 1238, 876,-1000,-1000,-1000, 201,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, 102, 124,-1000, -18, + 1193, 108, 1487, 1386, 1485, 1262, 1259,-1000, 123, 102, + 102, 1482, 1155,-1000,-1000, 1299, 1674, 1477, 1673, 1476, + 1475, 1672, 1668, 1193, 535,-1000, 535, 102, 141, 535, + 68, 2983, 535, 706, 1298, 81, -182, 1471, 95, 1795, + 131, 1877, 102,-1000, 1306,-1000, 900,-1000, 900, 900, + 900, 900, 900, -166,-1000, 102, 102, 535,-1000,-1000, +-1000,-1000,-1000,-1000, 1193, 1470, 1234, 1083,-1000,-1000, + 347, 1230, 964, 271, 166,-1000, 46, 102, 1469, 1468, +-1000, 3564, 1667, 1081, 1081, 1081, 535, 535,-1000, 941, + 542, 128,-1000,-1000,-1000,-1000,-1000, 1467, 343, 226, + 958, -96, 1659, 1658, 3449,-1000,-1000, 1568, 104, 204, + 690, -96, 3564, 102, 1193, 102, 1235, -322, 535, 1193, +-1000,-1000, 3564,-1000,-1000, 1193,-1000, -53, 81, 1466, + -241,-1000,-1000, 1193, 2721, 874, 873, 2983, 945, -126, + -137, 1457, 1456, 535, 1300,-1000, -53,-1000, 201, 201, +-1000,-1000,-1000,-1000, 411,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 1081, 1193, 1455, 102, 1193, 1451,-1000, 535, + -96, 1655, 871, 864, 856, 854,-1000, 108, 1670,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 1154, 1148, 1654, 945, 123, 1446, 947, 68, 1639, -405, + -56,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 495,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000, 1635, 1635,-1000, 1635, 1762,-1000, +-1000, -408,-1000, -387,-1000,-1000, -429,-1000,-1000,-1000, + 1442,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 123,-1000, +-1000,-1000,-1000,-1000, 165, 331, 1193,-1000, 108, 829, + 338,-1000, 3052, 374, 955,-1000,-1000,-1000,-1000,-1000, + 1217, -53, 1081, 1193,-1000, 535, 1223, 2983,-1000,-1000, +-1000, 393,-1000,-1000,-1000, 1111, 1102, 1094, 1075, 1067, + 1055, 1054, 1033, 1032, 1031, 997, 996, 995, 399, 987, + 975, 68, 455, 1076, -53, -53, 102, 938,-1000,-1000, +-1000, 1255, 1255, 1255, 1255,-1000,-1000,-1000,-1000,-1000, +-1000, 1255, 1255, 1255,-1000,-1000,-1000,-1000,-1000, -441, + 2721, 853, 852, 2983,-1000, 1255, 1193, 1181,-1000, 123, +-1000, 123, -23,-1000, 1227,-1000,-1000, 1913, 123, 102, +-1000,-1000, 1193,-1000, 1439,-1000,-1000, 1143,-1000,-1000, + -287, 998, 1877,-1000,-1000,-1000,-1000, 1299,-1000, -236, + -257, 102,-1000,-1000,-1000,-1000, 383, 192, 108, 899, + 880,-1000,-1000,-1000,-1000,-1000,-1000,-1000, -434,-1000, +-1000, 35,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000, 336,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 102,-1000,-1000,-1000,-1000, 1624, 1299, 1622,-1000,-1000, +-1000,-1000,-1000, 359, 1438, 1223,-1000, 128, 1433, 1220, +-1000, 2375,-1000,-1000,-1000, -37, 102, 977, 102, 1938, + 102, 110, 102, 93, 102, 124, 102, 102, 102, 102, + 102, 102, 102, 124, 102, 102, 102, 102, 102, 102, + 102, 974, 968, 953, 913, 102, 102, -112, 102, 1432, + 1299,-1000,-1000, 1621, 1616, 1430, 1429, 851,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, 65, -25,-1000, 1214, +-1000, 1216,-1000,-1000, -96, 2983,-1000,-1000, 1299,-1000, + 1615, 1614, 1613, 1608, 1607, 1605, 18, 1604, 1603, 1602, + 1597, 1595, 1590,-1000,-1000,-1000, 411,-1000, 1586, 1426, + 1335,-1000,-1000,-1000,-1000, 1425,-1000, 740, 102,-1000, + 1275, 102, 102, 950, 108, 850,-1000,-1000,-1000,-1000, +-1000,-1000,-1000, 155, 102, 5, 371,-1000,-1000,-1000, +-1000,-1000, 2983, 395,-1000,-1000,-1000, 1172, 1422, 1417, + 847, 144, 1416, 1413, 846, 1412, 844, 1408, 1407, 843, + 1406, 1404, 842, 1402, 841, 1398, 833, 1396, 831, 1384, + 830, 1378, 828, 1377, 823, 1375, 811, 1373, 787, 124, + 102, 102, 102, 102, 102, 102, 102, 1372, 780, 1370, + 759,-1000, 332, -53, -53,-1000,-1000, 822, 3564, -96, + 2983, -53, 969,-1000, 1585, 1584, 1576, 1573, 1142, -53, +-1000,-1000,-1000,-1000, 102, 758, 108, 757, 752, 102, + 1299,-1000,-1000, 1366, 1133, 1125, 1085, 1365,-1000, 73, +-1000, 1068, 735, 101,-1000,-1000,-1000, 1571, 1363,-1000, +-1000, 1570,-1000, 1556,-1000,-1000, 1554,-1000,-1000, 1553, +-1000, 1552,-1000, 1551,-1000, 1549,-1000, 1542,-1000, 1535, +-1000, 1534,-1000, 1533,-1000, 1532, 1362, 723, 1360, 716, + 1352, 687, 1347, 677,-1000, 1530,-1000, 1529,-1000, 1343, + 1338,-1000, 2721, 969,-1000, 1334, 1528,-1000, 857, 411, + 1331, 429,-1000, 1261,-1000, 2042, 1330,-1000, 102, 102, + 102,-1000,-1000, 1938,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000, 1526,-1000, 1525,-1000, 1524,-1000, 1522,-1000,-1000, +-1000,-1000, -39, 1521, 945, -53,-1000,-1000,-1000, 108, +-1000, 947,-1000, 1327, 1324, 1323,-1000, 182, 1106, 2264, + 428, 278, 527, 608, 582, 562, 443, 544, 530, 426, +-1000,-1000,-1000,-1000, 405, 135, -96, -53,-1000, 1321, + 2115, 1203,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 88,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 328, 381, 357, 350,-1000,-1000,-1000, 1520, + 1320,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000, 1424, 108,-1000, +-1000,-1000,-1000,-1000, -53, -443, 102, 1296, 1319, -188, + 1316,-1000,-1000, 65,-1000, 3564, 2721, -46, -96, 969, + 1369, -53, 1307,-1000 +}; + +YYSTATIC YYCONST short YYFARDATA YYPGO[] = { + 0, 33, 178, 5, 1991, 78, 39, 7, 1989, 0, + 1988, 1984, 1982, 268, 80, 1981, 1977, 4, 1972, 52, + 40, 3, 26, 32, 24, 6, 1970, 44, 41, 45, + 1969, 38, 34, 10, 17, 11, 31, 1968, 42, 1967, + 35, 18, 1966, 1965, 9, 1, 13, 8, 1954, 1950, + 1947, 1946, 22, 27, 43, 1945, 1944, 1943, 1942, 15, + 1941, 1940, 12, 1939, 30, 1938, 14, 36, 16, 23, + 46, 2, 599, 59, 1236, 29, 106, 1928, 1924, 1921, + 1920, 1919, 1918, 19, 28, 1917, 1329, 1916, 1915, 25, + 789, 131, 1914, 50, 1221, 1913, 1912, 1911, 1910, 1909, + 1901, 1900, 1899, 1898, 1897, 1895, 1892, 1891, 1890, 1028, + 1888, 67, 56, 1887, 65, 134, 62, 55, 1885, 1884, + 89, 1882, 1881, 1880, 1874, 1869, 1866, 53, 1864, 1863, + 1862, 100, 70, 49, 1861, 92, 292, 1859, 1858, 1856, + 1855, 1850, 1849, 1843, 1842, 1839, 1838, 1837, 1830, 832, + 1829, 1814, 1813, 1812, 1811, 1810, 1803, 1802, 75, 1801, + 1800, 125, 1797, 1796, 1795, 130, 1791, 1790, 1783, 1782, + 1781, 1779, 1778, 58, 1760, 63, 1777, 54, 1776, 602, + 1762, 1761, 1759, 1646, 1615, 1438 +}; +YYSTATIC YYCONST yyr_t YYFARDATA YYR1[]={ + + 0, 109, 109, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 136, + 136, 36, 36, 133, 133, 133, 2, 2, 1, 1, + 1, 9, 24, 24, 23, 23, 23, 134, 134, 134, + 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 93, 93, 93, 93, 94, 94, 94, 94, 10, + 11, 73, 72, 72, 59, 61, 61, 61, 62, 62, + 62, 65, 65, 132, 132, 132, 60, 60, 60, 60, + 60, 60, 130, 130, 130, 119, 12, 12, 12, 12, + 12, 12, 118, 137, 113, 138, 139, 111, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 140, 140, 141, 141, 112, + 112, 142, 142, 56, 56, 57, 57, 69, 69, 18, + 18, 18, 18, 18, 19, 19, 68, 68, 67, 67, + 58, 21, 21, 22, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 116, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 4, 4, 35, 35, 16, 16, 75, 75, + 75, 75, 75, 75, 75, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 76, 74, 74, + 74, 74, 74, 74, 144, 144, 81, 81, 81, 145, + 145, 150, 150, 150, 150, 150, 150, 150, 150, 146, + 82, 82, 82, 147, 147, 151, 151, 151, 151, 151, + 151, 151, 152, 38, 38, 34, 34, 153, 114, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 3, 3, + 3, 13, 13, 13, 13, 13, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 154, 115, 115, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 158, 159, 156, 161, 161, 160, 160, 160, 163, + 162, 162, 162, 162, 166, 166, 166, 169, 164, 167, + 168, 165, 165, 165, 117, 170, 170, 172, 172, 172, + 171, 171, 173, 173, 14, 14, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 175, 31, 31, 32, 32, 39, 39, 39, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 42, 42, 42, 43, 43, 43, + 47, 47, 46, 46, 45, 45, 44, 44, 48, 48, + 49, 49, 49, 50, 50, 50, 50, 51, 51, 149, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 6, 6, 6, + 6, 6, 53, 53, 54, 54, 55, 55, 25, 25, + 26, 26, 27, 27, 27, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 5, 5, 71, 71, 71, + 71, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 20, 20, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 30, + 30, 29, 29, 29, 29, 29, 131, 131, 131, 131, + 131, 131, 64, 64, 64, 63, 63, 87, 87, 84, + 84, 85, 17, 17, 37, 37, 37, 37, 37, 37, + 37, 37, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 176, 176, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 121, 121, 88, 88, 89, 89, 177, 122, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 123, 123, + 178, 178, 178, 66, 66, 179, 179, 179, 179, 179, + 179, 180, 182, 181, 124, 124, 125, 125, 183, 183, + 183, 183, 126, 148, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 127, 127, 184, 184, 184, 184, + 184, 184, 184, 128, 128, 92, 92, 92, 129, 129, + 185, 185, 185, 185 }; +YYSTATIC YYCONST yyr_t YYFARDATA YYR2[]={ + + 0, 0, 2, 4, 4, 3, 1, 1, 1, 1, + 1, 1, 4, 4, 4, 4, 1, 1, 1, 2, + 2, 3, 2, 2, 1, 1, 1, 4, 1, 0, + 2, 1, 3, 2, 4, 6, 1, 1, 1, 1, + 3, 1, 1, 1, 1, 4, 4, 4, 4, 4, + 4, 4, 2, 3, 2, 2, 2, 1, 1, 2, + 1, 2, 4, 6, 3, 5, 7, 9, 3, 4, + 7, 1, 1, 1, 2, 0, 2, 2, 0, 6, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 2, 3, 1, 2, 3, 7, 0, 2, 2, 2, + 2, 2, 3, 3, 2, 1, 4, 3, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 2, 2, 2, 5, 0, 2, 0, 2, 0, + 2, 3, 1, 0, 1, 1, 3, 0, 3, 1, + 1, 1, 1, 1, 0, 2, 4, 3, 0, 2, + 3, 0, 1, 5, 3, 4, 4, 4, 1, 1, + 1, 1, 1, 2, 2, 4, 13, 22, 1, 1, + 5, 3, 7, 5, 4, 7, 0, 2, 2, 2, + 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, + 2, 5, 0, 2, 0, 2, 0, 3, 9, 9, + 7, 7, 1, 1, 1, 2, 2, 1, 4, 0, + 1, 1, 2, 2, 2, 2, 1, 4, 2, 5, + 3, 2, 2, 1, 4, 3, 0, 2, 2, 0, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 9, + 0, 2, 2, 0, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 0, 4, 1, 3, 1, 13, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 5, 8, + 6, 5, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 4, 4, 4, 4, 5, 1, 1, + 1, 0, 4, 4, 4, 4, 0, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 5, 1, 0, 2, 2, 1, 2, 4, 5, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 4, 6, 4, 4, 11, 1, 5, 3, 7, 5, + 5, 3, 1, 2, 2, 1, 2, 4, 4, 1, + 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, + 1, 1, 4, 4, 2, 4, 2, 0, 1, 1, + 3, 1, 3, 1, 0, 3, 5, 4, 3, 5, + 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, + 2, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, + 2, 0, 1, 1, 2, 1, 1, 1, 1, 4, + 4, 5, 4, 4, 4, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 7, + 7, 7, 7, 7, 0, 2, 2, 0, 2, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 2, 0, 2, 3, 2, 0, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, + 2, 3, 2, 2, 2, 5, 3, 2, 2, 2, + 2, 2, 5, 4, 6, 2, 4, 0, 3, 3, + 1, 1, 0, 3, 0, 1, 1, 3, 0, 1, + 1, 3, 1, 3, 4, 4, 4, 4, 5, 1, + 1, 1, 1, 1, 1, 1, 3, 1, 3, 4, + 1, 0, 10, 6, 5, 6, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 1, 1, 1, 1, 2, 3, 4, 6, + 5, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 1, 2, 2, 4, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 1, 0, 5, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 1, 1, 1, 1, 1, 3, + 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, + 2, 3, 4, 2, 2, 2, 5, 5, 7, 4, + 3, 2, 3, 2, 1, 1, 2, 3, 2, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 3, 0, 1, 1, 3, 2, 6, 7, 3, 3, + 3, 6, 0, 1, 3, 5, 6, 4, 4, 1, + 3, 3, 1, 1, 1, 1, 4, 1, 6, 6, + 6, 4, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 2, 5, 4, 7, 6, 7, 6, 9, 8, 3, + 8, 4, 0, 2, 0, 1, 3, 3, 0, 2, + 2, 2, 3, 2, 2, 2, 2, 2, 0, 2, + 3, 1, 1, 1, 1, 3, 8, 2, 3, 1, + 1, 3, 3, 3, 4, 6, 0, 2, 3, 1, + 3, 1, 4, 3, 0, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 0, 2, 2, 3, 3, 4, + 2, 1, 1, 3, 5, 0, 2, 2, 0, 2, + 4, 3, 1, 1 }; +YYSTATIC YYCONST short YYFARDATA YYCHK[]={ + +-1000,-109,-110,-111,-113,-114,-116,-117,-118,-119, +-120,-121,-122,-124,-126,-128,-130,-131,-132, 525, + 526, 460, 528, 529,-133,-134,-135, 532, 533,-139, + 409,-152, 411,-170,-137, 455,-176, 463, 408, 470, + 471, 430, -87, 431, -93, -94, 273, 449, 530, 534, + 535, 536, 537, 538, 539, 540, 59,-138, 410, 412, + 454, 447, 448, 450, -10, -11, 123, 123,-115, 123, + 123, 123, 123, -9, 264, -9, 527, -88, -24, 265, + 264, -24, 123,-140, 314, -1, -2, 261, 260, 263, + -78, -16, 91,-171, 123,-174, 278, 38,-175, 286, + 287, 284, 283, 282, 281, 288, -31, -32, 267, 91, + -9, -90, 469, 469, -92, -1, 469, -86, 432, 433, + 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, -31, -86, 263, -28, -70, -74, -93, + -94, 306, 297, 322, 323,-149, 33, 307, 276, 324, + -52, 275, 91, -5, -76, 268, 413, 414, 415, 358, + 357, 278, 298, 277, 281, 282, 283, 284, 286, 287, + 279, 290, 291, 292, 293, 271, -1, 296, -1, -1, + -1, -1, 262, -77,-172, 318, 379, 61, -73, 40, + -75, -7, -76, 269, 272, 325, 340, -8, 295, 300, + 302, 308, -31, -31,-112,-109, 125,-155, 416,-156, + 418,-154, 420, 421,-117,-157, -2,-131,-120,-133, +-132,-135, 472, 458, 508,-158, 507,-160, 419, -95, + -96, -97, -98, -99,-108,-100,-101,-102,-103,-104, +-105,-106,-107,-159,-163, 395, 396, 397, 398, 399, + 400, 401, 402, 403, 404, 405, 406, 407, 123, 417, +-123,-125,-127,-129, -9, -1, 461,-136, -70, -76, +-141, 315, -71, -70, 91, -28,-149, 46, -7, 328, + 329, 330, 331, 332, 326, 346, 353, 337, 365, 366, + 367, 368, 369, 370, 371, 351, 378, 294, 372, -79, + -9,-173,-174, 42, 40, -31, 40, -14, 91, 40, + -14, 40, -14, 40, -14, 40, -14, 40, -14, 40, + 41, 267, -9, 263, 58, 44, 262, -1, 354, 355, + 356, 473, 379, 475, 476, 477, 478, -90, -91, -1, + 329, 330, -1, -71, 41, -36, 61, 288, 262, 44, + 390, 91, 38, 42, 359, 360, 361, 60, 390, 390, + 390, 390, -70, 306, -70, -75, -7, 33, -9, -1, + 280, 279, 289, -28, -1, -76, 42, 471, 47, -28, + 270, 272, 281, 282, 283, 284, 40, -36, -1, 329, + 330, 322, 345, 334, 335, 337, 338, 339, 340, 341, + 342, 343, 344, 362, 355, 336, 352, 326, 371, 294, + -2, 40, 61, -72, -71, -74, -28, -7, -7, 40, + 301, 303, 304, 305, 41, 41, 125,-143,-114,-111, +-144,-146,-116,-117,-131,-120,-132, 452, 453,-148, + 508,-133,-135, 507, 321, 422, 427, 472, 408, 125, + -9, -9, 40, 451, 58, 91, -9, -71, 357, 364, + 541, 91,-161,-162,-164,-166,-167,-168, 311,-169, + 309, 313, 312, -9, -2, -9, -24, 40, -23, -24, + 266, 286, 287, -31, -9, -2, -75, -28, -76, 270, + 272, -71, -36, 341,-175, -7, -72, 40,-115,-158, + -2, -9, 125,-178, 462,-131,-179,-180, 467, 468, +-181,-132,-135, 464, 125,-183,-177,-179,-182, 338, + 462, 465, 125,-184, 460, 408, 463, 296,-132,-135, + 125,-185, 460, 463,-132,-135, -89, 420, 125,-136, +-142, -71, -1, 471, -7, -1, -13, 40, 40, -28, + 328, 329, 330, 331, 377, 371, 326, 479, 365, 366, + 367, 368, 375, 376, 294, 93, 125, 44, 40, -2, + 41, -23, -9, -23, -24, -9, -9, -9, 93, -9, + -9, 474, -1, -1, 330, 329, 327, 336, 390, 40, + 61, 43, 123, 40, 40, 263, -1, 93, -30, -29, + 275, -9, 40, 40, -54, -55, -28, -1, -1, -1, + -1, -70, -28, -9, -1, 280, 93, 93, 93, -1, + -1, -71, -1, 91, -9, -69, 60, 329, 330, 331, + 365, 366, 367, 40, 61, -36, 123, 40, 41, -71, + -3, 373, 374, -1, -9,-115, 123, 123, 123, -9, + -9, 123, -71, 357, 364, 541, 364, -81, -82, -91, + -25, -26, -27, 275, -13, 40, -9, 58, 274, -7, + 91, -1, 91, -1, -9,-161,-165,-158, 310,-165, +-165,-165, -71,-158, -2, -9, 40, 40, 41, -71, + -1, 40, -31, -28, -6, -2, -9, 125, 316, 316, + 466, -31, -66, -9, 42, -36, 61, -31, 61, -31, + -31, 61, 61, -1, 469, -9, 469, 40, -1, 469, +-177, 44, 93, -1, -28, -28, 91, -9, -36, -83, + -1, 40, 40,-173, -36, 41, 41, 93, 41, 41, + 41, 41, 41, -12, 263, 44, 58, 390, 329, 330, + 331, 365, 366, 367, -1, -84, -85, -36, 123, 262, + -64, -63, -71, 306, 44, 93, 44, 275, -71, -71, + 62, 44, 42, -5, -5, -5, 93, 274, 41, -68, + -19, -18, 43, 45, 306, 323, 373, -9, -59, -61, + -73, 274, -53, -22, 60, 41, 125,-112,-145,-147, +-127, 274, -7, 91, -1, 91, -1, -71, -71, -1, + 371, 326, -7, 371, 326, -1, 41, 44, -28, -25, + 93, -9, -3, -1, -28, -9, -9, 44, 93, -2, + -9, -9, -24, 274, -36, 41, 40, 41, 44, 44, + -2, -9, -9, 41, 58, 40, 41, 40, 41, 41, + 40, 40, -5, -1, -9, 317, -1, -31, -71, 93, + -38, 479, 504, 505, 506, -9, 41, 390, -83, 41, + 387, 341, 342, 343, 388, 389, 301, 303, 304, 305, + 391, 394, 294, -4, 317, -34, -33,-153, 480, 482, + 483, 484, 485, 276, 277, 281, 282, 283, 284, 286, + 287, 257, 279, 290, 291, 292, 293, 486, 487, 488, + 490, 491, 492, 493, 494, 495, 496, 334, 497, 280, + 289, 336, 498, 341, 489, 357, 390, 502, 271, 123, + -9, 41, -14, -14, -14, -14, -14, -14, 317, 283, + 284, 456, 457, 459, -9, -9, -1, 41, 44, 61, + -59, 125, 44, 61, 263, 263, -29, -9, 41, 41, + -28, 40, -5, -1, 62, -58, -1, 40, -19, 41, + 125, -62, -40,-135, -41, 298, 364, 297, 286, 287, + 284, 283, 282, 281, 293, 292, 291, 290, 279, 278, + 277,-175, 61, -3, 40, 40, 91, -54, 125, 125, +-150, 423, 424, 425, 426,-120,-132,-133,-135, 125, +-151, 428, 429, 426,-132,-120,-133,-135, 125, -3, + -28, -9, -9, 44, -93, 450, -1, -28, -27, -38, + 41, 390, -71, 93, 93, -71, -35, 61, 316, 316, + 41, 41, -1, 41, -25, -6, -6, -66, 41, -9, + 41, -3, 40, 93, 93, 93, 93, -36, 41, 58, + 58, 40, -35, -2, 41, 42, 91, -32, 40, 481, + 501, 277, 281, 282, 283, 284, 280, -20, 40, -20, + -20, -15, 510, 483, 484, 276, 277, 281, 282, 283, + 284, 286, 287, 279, 290, 291, 292, 293, 42, 486, + 487, 488, 490, 491, 494, 495, 497, 280, 289, 257, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, + 521, 522, 523, 496, 488, 500, 41, -2, 263, 263, + 44, -84, -37, -17, -9, 283, -36, -70, 319, 320, + 125, -64, 123, 61, -25, -1, -67, 44, -56, -57, + -71, -65,-135, 358, 363, 40, 91, 40, 91, 40, + 91, 40, 91, 40, 91, 40, 91, 40, 91, 40, + 91, 40, 91, 40, 91, 40, 91, 40, 91, 40, + 91, 284, 283, 282, 281, 40, 91, 40, 91, -31, + -36, 123, 40, -53, -22, -25, -25, -9, 62, -75, + -75, -75, -75, -75, -75, -75, 509, -71, 93, 93, + -71, -1, -2, -2, 274, 44, -39, -41, -36, 299, + 286, 287, 284, 283, 282, 281, 279, 293, 292, 291, + 290, 278, 277, -2, -9, 41, 58, -89, -69, -34, + -83, 392, 393, 392, 393, -9, 93, -9, 43, 125, + -36, 91, 91, 503, 44, 91, 524, 38, 281, 282, + 283, 284, 280, -9, 40, 40, -62, 123, 41, -67, + -68, 41, 44, -60, -52, 364, 297, 345, 299, 263, + -9, 306, -70, 299, -9, -40, -9, -23, -9, -9, + -23, -24, -9, -24, -9, -9, -9, -9, -9, -9, + -9, -24, -9, -9, -9, -9, -9, -9, -9, 40, + 91, 40, 91, 40, 91, 40, 91, -9, -9, -17, + -9, 41, -59, 40, 40, 41, 41, 93, -7, 274, + 44, 40, -3, -71, 284, 283, 282, 281, -66, 40, + 41, 41, 41, 93, 43, -9, 44, -9, -9, 61, + -36, 93, 263, -9, 281, 282, 283, -9, 125, -62, + -71, -1, 91, 306, -70, 41, 41, 93, 263, 41, + 41, 93, 41, 93, 41, 41, 93, 41, 41, 93, + 41, 93, 41, 93, 41, 93, 41, 93, 41, 93, + 41, 93, 41, 93, 41, 93, -24, -9, -9, -9, + -9, -9, -9, -9, 41, 93, 41, 93, 125, -25, + -25, 62, -28, -3, -71, -25, -21, -22, 60, 58, + -25, -9, 93, -36, 93, 93, -9, 41, 58, 58, + 58, 41, 125, 61, 93, 263, 40, 41, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 41, 93, 41, 93, 41, 93, 41, 93, 40, 40, + 41, 41, -71, -21, 41, 40, -66, 41, 93, 44, + 41, -33, 41, -9, -9, -9, -40, -49, -50, -51, + -42, -43, -47, -46, -45, -44, -47, -46, -45, -44, + 40, 40, 40, 40, -45, -48, 274, 40, -35, -25, + -80, -36, 41, 41, 41, 41, 299, 263, 41, 299, + 306, -70, 41, -40, 41, -23, -9, 41, -23, -24, + 41, -24, 41, -9, 41, -9, 41, -9, 41, 41, + 41, 41, -47, -46, -45, -44, 41, 41, -17, -3, + -25, 41, 123, 324, 379, 380, 381, 308, 382, 383, + 384, 385, 333, 347, 348, 349, 350, 294, 44, 263, + 41, 41, 41, 41, 40, 41, 40, -36, -25, 509, + -9, 41, 41, 357, 41, -7, -28, -71, 274, -3, + -21, 40, -25, 41 }; +YYSTATIC YYCONST short YYFARDATA YYDEF[]={ + + 1, -2, 2, 0, 0, 333, 6, 7, 8, 9, + 10, 11, 0, 0, 0, 0, 16, 17, 18, 0, + 0, 772, 0, 0, 24, 25, 26, 0, 28, 135, + 0, 269, 206, 0, 431, 0, 0, 778, 105, 835, + 92, 0, 431, 0, 83, 84, 85, 0, 0, 0, + 0, 0, 0, 57, 58, 0, 60, 108, 262, 387, + 0, 757, 758, 219, 431, 431, 139, 1, 0, 788, + 806, 824, 838, 19, 41, 20, 0, 0, 22, 42, + 43, 23, 29, 137, 0, 104, 38, 39, 36, 37, + 219, 186, 0, 384, 0, 391, 0, 0, 431, 394, + 394, 394, 394, 394, 394, 0, 0, 432, 433, 0, + 760, 0, 778, 814, 0, 93, 0, 0, 742, 743, + 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, + 754, 755, 756, 0, 0, 33, 0, 0, 0, 0, + 0, 0, 668, 0, 0, 219, 0, 684, 685, 0, + 689, 0, 0, 549, 233, 551, 552, 553, 554, 0, + 489, 691, 692, 693, 694, 695, 696, 697, 698, 699, + 0, 704, 705, 706, 707, 708, 555, 0, 52, 54, + 55, 56, 59, 0, 386, 388, 389, 0, 61, 0, + 71, 0, 212, 213, 214, 219, 219, 217, 0, 220, + 221, 226, 0, 0, 0, 0, 5, 334, 0, 336, + 0, 0, 340, 341, 342, 343, 0, 345, 346, 347, + 348, 349, 0, 0, 0, 355, 0, 0, 332, 504, + 0, 0, 0, 0, 431, 0, 219, 0, 0, 0, + 219, 0, 0, 333, 0, 490, 491, 492, 493, 494, + 495, 496, 497, 498, 499, 500, 501, 502, 362, 369, + 0, 0, 0, 0, 21, 774, 773, 0, 29, 550, + 107, 0, 136, 557, 0, 560, 219, 0, 311, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 0, 0, 0, + 0, 0, 393, 0, 0, 0, 0, 405, 0, 0, + 406, 0, 407, 0, 408, 0, 409, 0, 410, 430, + 102, 434, 0, 759, 0, 0, 769, 777, 779, 780, + 781, 0, 783, 784, 785, 786, 787, 0, 0, 833, + 836, 837, 94, 718, 719, 720, 0, 0, 31, 0, + 0, 711, 673, 674, 675, 0, 0, 534, 0, 0, + 0, 0, 667, 0, 670, 228, 0, 0, 681, 683, + 686, 0, 688, 690, 0, 0, 0, 0, 0, 0, + 231, 232, 700, 701, 702, 703, 0, 53, 147, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 0, 131, 132, 133, 0, + 0, 103, 0, 0, 72, 73, 0, 215, 216, 0, + 222, 223, 224, 225, 64, 68, 3, 140, 333, 0, + 0, 0, 168, 169, 170, 171, 172, 0, 0, 0, + 0, 178, 179, 0, 0, 236, 250, 814, 105, 4, + 335, 337, -2, 0, 344, 0, 0, 0, 219, 0, + 0, 0, 363, 365, 0, 0, 0, 0, 0, 0, + 379, 380, 377, 505, 506, 507, 508, 503, 509, 510, + 44, 0, 0, 0, 512, 513, 514, 0, 517, 518, + 519, 520, 521, 0, 431, 0, 525, 527, 0, 366, + 0, 0, 12, 789, 0, 791, 792, 431, 0, 0, + 431, 799, 800, 0, 13, 807, 431, 809, 431, 811, + 0, 0, 14, 825, 0, 0, 0, 0, 831, 832, + 15, 839, 0, 0, 842, 843, 771, 775, 27, 30, + 138, 142, 0, 0, 0, 40, 0, 0, 292, 0, + 187, 188, 189, 190, 191, 192, 193, 0, 195, 196, + 197, 198, 199, 200, 0, 207, 390, 0, 0, 0, + 398, 0, 0, 0, 0, 0, 0, 0, 96, 762, + 0, 782, 804, 812, 815, 816, 817, 0, 0, 0, + 0, 0, 722, 727, 728, 34, 47, 671, 0, 709, + 712, 713, 0, 0, 0, 535, 536, 48, 49, 50, + 51, 669, 0, 680, 682, 687, 0, 0, 0, 0, + 556, 0, -2, 711, 0, 106, 154, 125, 126, 127, + 128, 129, 130, 0, 385, 62, 75, 69, 219, 0, + 532, 308, 309, -2, 0, 0, 139, 239, 253, 173, + 174, 824, 0, 219, 0, 0, 0, 0, 219, 0, + 0, 539, 540, 542, 0, -2, 0, 0, 0, 0, + 0, 357, 0, 0, 0, 364, 370, 381, 0, 371, + 372, 373, 378, 374, 375, 376, 0, 0, 511, 0, + -2, 0, 0, 0, 0, 530, 531, 361, 0, 0, + 0, 0, 0, 793, 794, 797, 0, 0, 0, 0, + 0, 0, 0, 826, 0, 830, 0, 0, 0, 0, + 431, 0, 558, 0, 0, 263, 0, 0, 292, 0, + 202, 561, 0, 392, 0, 397, 394, 395, 394, 394, + 394, 394, 394, 0, 761, 0, 0, 0, 818, 819, + 820, 821, 822, 823, 834, 0, 729, 0, 75, 32, + 0, 723, 0, 0, 0, 672, 711, 715, 0, 0, + 679, 0, 674, 545, 546, 547, 0, 0, 227, 0, + 0, 154, 149, 150, 151, 152, 153, 0, 0, 78, + 65, 0, 0, 0, 534, 218, 164, 0, 0, 0, + 0, 0, 0, 0, 181, 0, 0, 0, 0, -2, + 237, 238, 0, 251, 252, 813, 338, 311, 263, 0, + 350, 352, 353, 310, 0, 0, 0, 0, 204, 0, + 0, 0, 0, 0, 0, 523, -2, 526, 527, 527, + 367, 368, 790, 795, 0, 803, 798, 801, 808, 810, + 776, 802, 827, 828, 0, 0, 841, 0, 141, 559, + 0, 0, 0, 0, 0, 0, 288, 0, 0, 291, + 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, + 0, 0, 0, 204, 0, 0, 265, 0, 0, 0, + 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, + 576, 577, 0, 582, 583, 584, 585, 591, 592, 593, + 594, 595, 596, 597, 616, 616, 600, 616, 618, 604, + 606, 0, 608, 0, 610, 612, 0, 614, 615, 267, + 0, 396, 399, 400, 401, 402, 403, 404, 0, 97, + 98, 99, 100, 101, 764, 766, 805, 716, 0, 0, + 0, 721, 722, 0, 37, 35, 710, 714, 676, 677, + 537, -2, 548, 229, 148, 0, 158, 143, 155, 134, + 63, 74, 76, 77, 438, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 431, 0, 532, -2, -2, 0, 0, 165, 166, + 240, 219, 219, 219, 219, 245, 246, 247, 248, 167, + 254, 219, 219, 219, 258, 259, 260, 261, 175, 0, + 0, 0, 0, 0, 184, 219, 234, 0, 541, 543, + 339, 0, 0, 356, 0, 359, 360, 0, 0, 0, + 45, 46, 515, 522, 0, 528, 529, 0, 829, 840, + 774, 147, 561, 312, 313, 314, 315, 292, 290, 0, + 0, 0, 185, 203, 194, 586, 0, 0, 0, 0, + 0, 611, 578, 579, 580, 581, 605, 598, 0, 599, + 601, 602, 619, 620, 621, 622, 623, 624, 625, 626, + 627, 628, 629, 0, 634, 635, 636, 637, 638, 642, + 643, 644, 645, 646, 647, 648, 649, 650, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 607, 609, 613, 201, 95, 763, 765, + 0, 730, 731, 734, 735, 0, 737, 0, 732, 733, + 717, 724, 78, 0, 0, 158, 157, 154, 0, 144, + 145, 0, 80, 81, 82, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 66, 75, 70, 0, 0, 0, 0, 0, 533, 241, + 242, 243, 244, 255, 256, 257, 219, 0, 180, 0, + 183, 0, 544, 351, 0, 0, 205, 435, 436, 437, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 382, 383, 524, 0, 770, 0, 0, + 0, 303, 304, 305, 306, 0, 587, 0, 0, 266, + 0, 0, 0, 0, 0, 0, 640, 641, 630, 631, + 632, 633, 651, 768, 0, 0, 0, 78, 678, 156, + 159, 160, 0, 0, 86, 87, 88, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 429, 0, -2, -2, 210, 211, 0, 0, 0, + 0, -2, 161, 358, 0, 0, 0, 0, 0, -2, + 264, 289, 307, 588, 0, 0, 0, 0, 0, 0, + 603, 639, 767, 0, 0, 0, 0, 0, 725, 0, + 146, 0, 0, 0, 90, 439, 440, 0, 0, 442, + 443, 0, 444, 0, 411, 413, 0, 412, 414, 0, + 415, 0, 416, 0, 417, 0, 418, 0, 423, 0, + 424, 0, 425, 0, 426, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 427, 0, 428, 0, 67, 0, + 0, 163, 0, 161, 182, 0, 0, 162, 0, 0, + 0, 0, 590, 0, 564, 561, 0, 736, 0, 0, + 0, 741, 726, 0, 91, 89, 480, 441, 483, 487, + 464, 467, 470, 472, 474, 476, 470, 472, 474, 476, + 419, 0, 420, 0, 421, 0, 422, 0, 474, 478, + 208, 209, 0, 0, 204, -2, 796, 316, 589, 0, + 563, 565, 617, 0, 0, 0, 79, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 470, 472, 474, 476, 0, 0, 0, -2, 249, 0, + 0, 0, 738, 739, 740, 461, 481, 482, 462, 484, + 0, 486, 463, 488, 445, 465, 466, 446, 468, 469, + 447, 471, 448, 473, 449, 475, 450, 477, 451, 452, + 453, 454, 0, 0, 0, 0, 459, 460, 479, 0, + 0, 354, 268, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 0, 0, 485, + 455, 456, 457, 458, -2, 0, 0, 0, 0, 0, + 0, 562, 176, 219, 331, 0, 0, 0, 0, 161, + 0, -2, 0, 177 }; +#ifdef YYRECOVER +YYSTATIC YYCONST short yyrecover[] = { +-1000 +}; +#endif + +/* SCCSWHAT( "@(#)yypars.c 3.1 88/11/16 22:00:49 " ) */ +#line 3 "F:\\NetFXDev1\\src\\tools\\devdiv\\amd64\\yypars.c" +#if ! defined(YYAPI_PACKAGE) +/* +** YYAPI_TOKENNAME : name used for return value of yylex +** YYAPI_TOKENTYPE : type of the token +** YYAPI_TOKENEME(t) : the value of the token that the parser should see +** YYAPI_TOKENNONE : the representation when there is no token +** YYAPI_VALUENAME : the name of the value of the token +** YYAPI_VALUETYPE : the type of the value of the token (if null, then the value is derivable from the token itself) +** YYAPI_VALUEOF(v) : how to get the value of the token. +*/ +#define YYAPI_TOKENNAME yychar +#define YYAPI_TOKENTYPE int +#define YYAPI_TOKENEME(t) (t) +#define YYAPI_TOKENNONE -1 +#define YYAPI_TOKENSTR(t) (sprintf_s(yytokbuf, _countof(yytokbuf), "%d", t), yytokbuf) +#define YYAPI_VALUENAME yylval +#define YYAPI_VALUETYPE YYSTYPE +#define YYAPI_VALUEOF(v) (v) +#endif +#if ! defined(YYAPI_CALLAFTERYYLEX) +#define YYAPI_CALLAFTERYYLEX +#endif + +# define YYFLAG -1000 +# define YYERROR goto yyerrlab +# define YYACCEPT return(0) +# define YYABORT return(1) + +#ifdef YYDEBUG /* RRR - 10/9/85 */ +char yytokbuf[20]; +# ifndef YYDBFLG +# define YYDBFLG (yydebug) +# endif +# define yyprintf(a, b, c, d) if (YYDBFLG) YYPRINT(a, b, c, d) +#else +# define yyprintf(a, b, c, d) +#endif + +#ifndef YYPRINT +#define YYPRINT printf +#endif + +/* parser for yacc output */ + +#ifdef YYDUMP +int yydump = 1; /* 1 for dumping */ +void yydumpinfo(void); +#endif +#ifdef YYDEBUG +YYSTATIC int yydebug = 0; /* 1 for debugging */ +#endif +YYSTATIC YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ +YYSTATIC short yys[YYMAXDEPTH]; /* the parse stack */ + +#if ! defined(YYRECURSIVE) +YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; +#if defined(YYAPI_VALUETYPE) +// YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; FIX +#endif +YYSTATIC int yynerrs = 0; /* number of errors */ +YYSTATIC short yyerrflag = 0; /* error recovery flag */ +#endif + +#ifdef YYRECOVER +/* +** yyscpy : copy f onto t and return a ptr to the null terminator at the +** end of t. +*/ +YYSTATIC char *yyscpy(register char*t, register char*f) + { + while(*t = *f++) + t++; + return(t); /* ptr to the null char */ + } +#endif + +#ifndef YYNEAR +#define YYNEAR +#endif +#ifndef YYPASCAL +#define YYPASCAL +#endif +#ifndef YYLOCAL +#define YYLOCAL +#endif +#if ! defined YYPARSER +#define YYPARSER yyparse +#endif +#if ! defined YYLEX +#define YYLEX yylex +#endif + +#if defined(YYRECURSIVE) + + YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; + #if defined(YYAPI_VALUETYPE) + YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; + #endif + YYSTATIC int yynerrs = 0; /* number of errors */ + YYSTATIC short yyerrflag = 0; /* error recovery flag */ + + YYSTATIC short yyn; + YYSTATIC short yystate = 0; + YYSTATIC short *yyps= &yys[-1]; + YYSTATIC YYSTYPE *yypv= &yyv[-1]; + YYSTATIC short yyj; + YYSTATIC short yym; + +#endif + +#pragma warning(disable:102) +YYLOCAL YYNEAR YYPASCAL YYPARSER() +{ +#if ! defined(YYRECURSIVE) + + register short yyn; + short yystate, *yyps; + YYSTYPE *yypv; + short yyj, yym; + + YYAPI_TOKENNAME = YYAPI_TOKENNONE; + yystate = 0; + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:6200) // Index '-1' is out of valid index range...for non-stack buffer... +#endif + yyps= &yys[-1]; + yypv= &yyv[-1]; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +#endif + +#ifdef YYDUMP + yydumpinfo(); +#endif + yystack: /* put a state and value onto the stack */ + +#ifdef YYDEBUG + if(YYAPI_TOKENNAME == YYAPI_TOKENNONE) { + yyprintf( "state %d, token # '%d'\n", yystate, -1, 0 ); + } + else { + yyprintf( "state %d, token # '%s'\n", yystate, YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0 ); + } +#endif + if( ++yyps > &yys[YYMAXDEPTH] ) { + yyerror( "yacc stack overflow" ); + return(1); + } + *yyps = yystate; + ++yypv; + + *yypv = yyval; + +yynewstate: + + yyn = YYPACT[yystate]; + + if( yyn <= YYFLAG ) { /* simple state, no lookahead */ + goto yydefault; + } + if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { /* need a lookahead */ + YYAPI_TOKENNAME = YYLEX(); + YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); + } + if( ((yyn += YYAPI_TOKENEME(YYAPI_TOKENNAME)) < 0) || (yyn >= YYLAST) ) { + goto yydefault; + } + if( YYCHK[ yyn = YYACT[ yyn ] ] == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { /* valid shift */ + yyval = YYAPI_VALUEOF(YYAPI_VALUENAME); + yystate = yyn; + yyprintf( "SHIFT: saw token '%s', now in state %4d\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), yystate, 0 ); + YYAPI_TOKENNAME = YYAPI_TOKENNONE; + if( yyerrflag > 0 ) { + --yyerrflag; + } + goto yystack; + } + + yydefault: + /* default state action */ + + if( (yyn = YYDEF[yystate]) == -2 ) { + register YYCONST short *yyxi; + + if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { + YYAPI_TOKENNAME = YYLEX(); + YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); + yyprintf("LOOKAHEAD: token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0); + } +/* +** search exception table, we find a -1 followed by the current state. +** if we find one, we'll look through terminal,state pairs. if we find +** a terminal which matches the current one, we have a match. +** the exception table is when we have a reduce on a terminal. +*/ + +#if YYOPTTIME + yyxi = yyexca + yyexcaind[yystate]; + while(( *yyxi != YYAPI_TOKENEME(YYAPI_TOKENNAME) ) && ( *yyxi >= 0 )){ + yyxi += 2; + } +#else + for(yyxi = yyexca; + (*yyxi != (-1)) || (yyxi[1] != yystate); + yyxi += 2 + ) { + ; /* VOID */ + } + + while( *(yyxi += 2) >= 0 ){ + if( *yyxi == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { + break; + } + } +#endif + if( (yyn = yyxi[1]) < 0 ) { + return(0); /* accept */ + } + } + + if( yyn == 0 ){ /* error */ + /* error ... attempt to resume parsing */ + + switch( yyerrflag ){ + + case 0: /* brand new error */ +#ifdef YYRECOVER + { + register int i,j; + + for(i = 0; + (yyrecover[i] != -1000) && (yystate > yyrecover[i]); + i += 3 + ) { + ; + } + if(yystate == yyrecover[i]) { + yyprintf("recovered, from state %d to state %d on token # %d\n", + yystate,yyrecover[i+2],yyrecover[i+1] + ); + j = yyrecover[i + 1]; + if(j < 0) { + /* + ** here we have one of the injection set, so we're not quite + ** sure that the next valid thing will be a shift. so we'll + ** count it as an error and continue. + ** actually we're not absolutely sure that the next token + ** we were supposed to get is the one when j > 0. for example, + ** for(+) {;} error recovery with yyerrflag always set, stops + ** after inserting one ; before the +. at the point of the +, + ** we're pretty sure the caller wants a 'for' loop. without + ** setting the flag, when we're almost absolutely sure, we'll + ** give them one, since the only thing we can shift on this + ** error is after finding an expression followed by a + + */ + yyerrflag++; + j = -j; + } + if(yyerrflag <= 1) { /* only on first insertion */ + yyrecerr(YYAPI_TOKENNAME, j); /* what was, what should be first */ + } + yyval = yyeval(j); + yystate = yyrecover[i + 2]; + goto yystack; + } + } +#endif + yyerror("syntax error"); + + yyerrlab: + ++yynerrs; + FALLTHROUGH; + + case 1: + case 2: /* incompletely recovered error ... try again */ + + yyerrflag = 3; + + /* find a state where "error" is a legal shift action */ + + while ( yyps >= yys ) { + yyn = YYPACT[*yyps] + YYERRCODE; + if( yyn>= 0 && yyn < YYLAST && YYCHK[YYACT[yyn]] == YYERRCODE ){ + yystate = YYACT[yyn]; /* simulate a shift of "error" */ + yyprintf( "SHIFT 'error': now in state %4d\n", yystate, 0, 0 ); + goto yystack; + } + yyn = YYPACT[*yyps]; + + /* the current yyps has no shift onn "error", pop stack */ + + yyprintf( "error recovery pops state %4d, uncovers %4d\n", *yyps, yyps[-1], 0 ); + --yyps; + --yypv; + } + + /* there is no state on the stack with an error shift ... abort */ + + yyabort: + return(1); + + + case 3: /* no shift yet; clobber input char */ + + yyprintf( "error recovery discards token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0 ); + + if( YYAPI_TOKENEME(YYAPI_TOKENNAME) == 0 ) goto yyabort; /* don't discard EOF, quit */ + YYAPI_TOKENNAME = YYAPI_TOKENNONE; + goto yynewstate; /* try again in the same state */ + } + } + + /* reduction by production yyn */ +yyreduce: + { + register YYSTYPE *yypvt; + yypvt = yypv; + yyps -= YYR2[yyn]; + yypv -= YYR2[yyn]; + yyval = yypv[1]; + yyprintf("REDUCE: rule %4d, popped %2d tokens, uncovered state %4d, ",yyn, YYR2[yyn], *yyps); + yym = yyn; + yyn = YYR1[yyn]; /* consult goto table to find next state */ + yyj = YYPGO[yyn] + *yyps + 1; + if( (yyj >= YYLAST) || (YYCHK[ yystate = YYACT[yyj] ] != -yyn) ) { + yystate = YYACT[YYPGO[yyn]]; + } + yyprintf("goto state %4d\n", yystate, 0, 0); +#ifdef YYDUMP + yydumpinfo(); +#endif + switch(yym){ + +case 3: +#line 194 "asmparse.y" +{ PASM->EndClass(); } break; +case 4: +#line 195 "asmparse.y" +{ PASM->EndNameSpace(); } break; +case 5: +#line 196 "asmparse.y" +{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } break; +case 12: +#line 206 "asmparse.y" +{ PASMM->EndAssembly(); } break; +case 13: +#line 207 "asmparse.y" +{ PASMM->EndAssembly(); } break; +case 14: +#line 208 "asmparse.y" +{ PASMM->EndComType(); } break; +case 15: +#line 209 "asmparse.y" +{ PASMM->EndManifestRes(); } break; +case 19: +#line 213 "asmparse.y" +{ +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22011) // Suppress PREFast warning about integer overflow/underflow +#endif + PASM->m_dwSubsystem = yypvt[-0].int32; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + } break; +case 20: +#line 223 "asmparse.y" +{ PASM->m_dwComImageFlags = yypvt[-0].int32; } break; +case 21: +#line 224 "asmparse.y" +{ PASM->m_dwFileAlignment = yypvt[-0].int32; + if((yypvt[-0].int32 & (yypvt[-0].int32 - 1))||(yypvt[-0].int32 < 0x200)||(yypvt[-0].int32 > 0x10000)) + PASM->report->error("Invalid file alignment, must be power of 2 from 0x200 to 0x10000\n");} break; +case 22: +#line 227 "asmparse.y" +{ PASM->m_stBaseAddress = (ULONGLONG)(*(yypvt[-0].int64)); delete yypvt[-0].int64; + if(PASM->m_stBaseAddress & 0xFFFF) + PASM->report->error("Invalid image base, must be 0x10000-aligned\n");} break; +case 23: +#line 230 "asmparse.y" +{ PASM->m_stSizeOfStackReserve = (size_t)(*(yypvt[-0].int64)); delete yypvt[-0].int64; } break; +case 28: +#line 235 "asmparse.y" +{ PASM->m_fIsMscorlib = TRUE; } break; +case 31: +#line 242 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 32: +#line 243 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 33: +#line 246 "asmparse.y" +{ LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLang)); } break; +case 34: +#line 247 "asmparse.y" +{ LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLang)); + LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLangVendor));} break; +case 35: +#line 249 "asmparse.y" +{ LPCSTRToGuid(yypvt[-4].string,&(PASM->m_guidLang)); + LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLangVendor)); + LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidDoc));} break; +case 36: +#line 254 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 37: +#line 255 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 38: +#line 258 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 39: +#line 259 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 40: +#line 260 "asmparse.y" +{ yyval.string = newStringWDel(yypvt[-2].string, '.', yypvt[-0].string); } break; +case 41: +#line 263 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 42: +#line 266 "asmparse.y" +{ yyval.int64 = yypvt[-0].int64; } break; +case 43: +#line 267 "asmparse.y" +{ yyval.int64 = neg ? new __int64(yypvt[-0].int32) : new __int64((unsigned)yypvt[-0].int32); } break; +case 44: +#line 270 "asmparse.y" +{ yyval.float64 = yypvt[-0].float64; } break; +case 45: +#line 271 "asmparse.y" +{ float f; *((__int32*) (&f)) = yypvt[-1].int32; yyval.float64 = new double(f); } break; +case 46: +#line 272 "asmparse.y" +{ yyval.float64 = (double*) yypvt[-1].int64; } break; +case 47: +#line 276 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].binstr,yypvt[-0].string); } break; +case 48: +#line 277 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; +case 49: +#line 278 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; +case 50: +#line 279 "asmparse.y" +{ yypvt[-2].cad->tkOwner = 0; PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; +case 51: +#line 280 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; +case 52: +#line 285 "asmparse.y" +{ DefineVar(yypvt[-0].string, NULL); } break; +case 53: +#line 286 "asmparse.y" +{ DefineVar(yypvt[-1].string, yypvt[-0].binstr); } break; +case 54: +#line 287 "asmparse.y" +{ UndefVar(yypvt[-0].string); } break; +case 55: +#line 288 "asmparse.y" +{ SkipToken = !IsVarDefined(yypvt[-0].string); + IfEndif++; + } break; +case 56: +#line 291 "asmparse.y" +{ SkipToken = IsVarDefined(yypvt[-0].string); + IfEndif++; + } break; +case 57: +#line 294 "asmparse.y" +{ if(IfEndif == 1) SkipToken = !SkipToken;} break; +case 58: +#line 295 "asmparse.y" +{ if(IfEndif == 0) + PASM->report->error("Unmatched #endif\n"); + else IfEndif--; + } break; +case 59: +#line 299 "asmparse.y" +{ _ASSERTE(!"yylex should have dealt with this"); } break; +case 60: +#line 300 "asmparse.y" +{ } break; +case 61: +#line 304 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-0].token, NULL); } break; +case 62: +#line 305 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].token, yypvt[-0].binstr); } break; +case 63: +#line 306 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-4].token, yypvt[-1].binstr); } break; +case 64: +#line 307 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; +case 65: +#line 310 "asmparse.y" +{ yyval.cad = new CustomDescr(yypvt[-2].token, yypvt[-0].token, NULL); } break; +case 66: +#line 311 "asmparse.y" +{ yyval.cad = new CustomDescr(yypvt[-4].token, yypvt[-2].token, yypvt[-0].binstr); } break; +case 67: +#line 313 "asmparse.y" +{ yyval.cad = new CustomDescr(yypvt[-6].token, yypvt[-4].token, yypvt[-1].binstr); } break; +case 68: +#line 314 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; +case 69: +#line 317 "asmparse.y" +{ yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; +case 70: +#line 321 "asmparse.y" +{ PASM->m_pCustomDescrList = NULL; + PASM->m_tkCurrentCVOwner = yypvt[-4].token; + yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; +case 71: +#line 326 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 72: +#line 329 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 73: +#line 330 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 74: +#line 334 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt16(nCustomBlobNVPairs); + yyval.binstr->append(yypvt[-0].binstr); + nCustomBlobNVPairs = 0; } break; +case 75: +#line 340 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt16(VAL16(0x0001)); } break; +case 76: +#line 341 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); } break; +case 77: +#line 343 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 78: +#line 346 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 79: +#line 348 "asmparse.y" +{ yyval.binstr = yypvt[-5].binstr; yyval.binstr->appendInt8(yypvt[-4].int32); + yyval.binstr->append(yypvt[-3].binstr); + AppendStringWithLength(yyval.binstr,yypvt[-2].string); + yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); + nCustomBlobNVPairs++; } break; +case 80: +#line 353 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 81: +#line 356 "asmparse.y" +{ yyval.int32 = SERIALIZATION_TYPE_FIELD; } break; +case 82: +#line 357 "asmparse.y" +{ yyval.int32 = SERIALIZATION_TYPE_PROPERTY; } break; +case 83: +#line 360 "asmparse.y" +{ if(yypvt[-0].cad->tkOwner && !yypvt[-0].cad->tkInterfacePair) + PASM->DefineCV(yypvt[-0].cad); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); } break; +case 84: +#line 364 "asmparse.y" +{ PASM->DefineCV(yypvt[-0].cad); } break; +case 85: +#line 365 "asmparse.y" +{ CustomDescr* pNew = new CustomDescr(yypvt[-0].tdd->m_pCA); + if(pNew->tkOwner == 0) pNew->tkOwner = PASM->m_tkCurrentCVOwner; + if(pNew->tkOwner) + PASM->DefineCV(pNew); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(pNew); } break; +case 86: +#line 373 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 87: +#line 374 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); } break; +case 88: +#line 375 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); } break; +case 89: +#line 376 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength(yyval.binstr,yypvt[-0].string); } break; +case 90: +#line 378 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token)); } break; +case 91: +#line 380 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 92: +#line 385 "asmparse.y" +{ PASMM->SetModuleName(NULL); PASM->m_tkCurrentCVOwner=1; } break; +case 93: +#line 386 "asmparse.y" +{ PASMM->SetModuleName(yypvt[-0].string); PASM->m_tkCurrentCVOwner=1; } break; +case 94: +#line 387 "asmparse.y" +{ BinStr* pbs = new BinStr(); + unsigned L = (unsigned)strlen(yypvt[-0].string); + memcpy((char*)(pbs->getBuff(L)),yypvt[-0].string,L); + PASM->EmitImport(pbs); delete pbs;} break; +case 95: +#line 394 "asmparse.y" +{ /*PASM->SetDataSection(); PASM->EmitDataLabel($7);*/ + PASM->m_VTFList.PUSH(new VTFEntry((USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, yypvt[-0].string)); } break; +case 96: +#line 398 "asmparse.y" +{ yyval.int32 = 0; } break; +case 97: +#line 399 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_32BIT; } break; +case 98: +#line 400 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_64BIT; } break; +case 99: +#line 401 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED; } break; +case 100: +#line 402 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_CALL_MOST_DERIVED; } break; +case 101: +#line 403 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN; } break; +case 102: +#line 406 "asmparse.y" +{ PASM->m_pVTable = yypvt[-1].binstr; } break; +case 103: +#line 409 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 104: +#line 413 "asmparse.y" +{ PASM->StartNameSpace(yypvt[-0].string); } break; +case 105: +#line 416 "asmparse.y" +{ newclass = TRUE; } break; +case 106: +#line 419 "asmparse.y" +{ if(yypvt[-0].typarlist) FixupConstraints(); + PASM->StartClass(yypvt[-1].string, yypvt[-2].classAttr, yypvt[-0].typarlist); + TyParFixupList.RESET(false); + newclass = FALSE; + } break; +case 107: +#line 425 "asmparse.y" +{ PASM->AddClass(); } break; +case 108: +#line 428 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) 0; } break; +case 109: +#line 429 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdPublic); } break; +case 110: +#line 430 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdNotPublic); } break; +case 111: +#line 431 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x80000000 | tdSealed); } break; +case 112: +#line 432 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x40000000); } break; +case 113: +#line 433 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdInterface | tdAbstract); } break; +case 114: +#line 434 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSealed); } break; +case 115: +#line 435 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdAbstract); } break; +case 116: +#line 436 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdAutoLayout); } break; +case 117: +#line 437 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdSequentialLayout); } break; +case 118: +#line 438 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdExplicitLayout); } break; +case 119: +#line 439 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAnsiClass); } break; +case 120: +#line 440 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdUnicodeClass); } break; +case 121: +#line 441 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAutoClass); } break; +case 122: +#line 442 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdImport); } break; +case 123: +#line 443 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSerializable); } break; +case 124: +#line 444 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdWindowsRuntime); } break; +case 125: +#line 445 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPublic); } break; +case 126: +#line 446 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPrivate); } break; +case 127: +#line 447 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamily); } break; +case 128: +#line 448 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedAssembly); } break; +case 129: +#line 449 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamANDAssem); } break; +case 130: +#line 450 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamORAssem); } break; +case 131: +#line 451 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdBeforeFieldInit); } break; +case 132: +#line 452 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSpecialName); } break; +case 133: +#line 453 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr); } break; +case 134: +#line 454 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].int32); } break; +case 136: +#line 458 "asmparse.y" +{ PASM->m_crExtends = yypvt[-0].token; } break; +case 141: +#line 469 "asmparse.y" +{ PASM->AddToImplList(yypvt[-0].token); } break; +case 142: +#line 470 "asmparse.y" +{ PASM->AddToImplList(yypvt[-0].token); } break; +case 143: +#line 474 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 144: +#line 475 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 145: +#line 478 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-0].token); } break; +case 146: +#line 479 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->appendInt32(yypvt[-0].token); } break; +case 147: +#line 482 "asmparse.y" +{ yyval.typarlist = NULL; PASM->m_TyParList = NULL;} break; +case 148: +#line 483 "asmparse.y" +{ yyval.typarlist = yypvt[-1].typarlist; PASM->m_TyParList = yypvt[-1].typarlist;} break; +case 149: +#line 486 "asmparse.y" +{ yyval.int32 = gpCovariant; } break; +case 150: +#line 487 "asmparse.y" +{ yyval.int32 = gpContravariant; } break; +case 151: +#line 488 "asmparse.y" +{ yyval.int32 = gpReferenceTypeConstraint; } break; +case 152: +#line 489 "asmparse.y" +{ yyval.int32 = gpNotNullableValueTypeConstraint; } break; +case 153: +#line 490 "asmparse.y" +{ yyval.int32 = gpDefaultConstructorConstraint; } break; +case 154: +#line 493 "asmparse.y" +{ yyval.int32 = 0; } break; +case 155: +#line 494 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | yypvt[-0].int32; } break; +case 156: +#line 497 "asmparse.y" +{yyval.typarlist = new TyParList(yypvt[-3].int32, yypvt[-2].binstr, yypvt[-1].string, yypvt[-0].typarlist);} break; +case 157: +#line 498 "asmparse.y" +{yyval.typarlist = new TyParList(yypvt[-2].int32, NULL, yypvt[-1].string, yypvt[-0].typarlist);} break; +case 158: +#line 501 "asmparse.y" +{ yyval.typarlist = NULL; } break; +case 159: +#line 502 "asmparse.y" +{ yyval.typarlist = yypvt[-0].typarlist; } break; +case 160: +#line 505 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 161: +#line 508 "asmparse.y" +{ yyval.int32= 0; } break; +case 162: +#line 509 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 163: +#line 512 "asmparse.y" +{ yyval.int32 = yypvt[-2].int32; } break; +case 164: +#line 516 "asmparse.y" +{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } break; +case 165: +#line 520 "asmparse.y" +{ PASM->EndClass(); } break; +case 166: +#line 521 "asmparse.y" +{ PASM->EndEvent(); } break; +case 167: +#line 522 "asmparse.y" +{ PASM->EndProp(); } break; +case 173: +#line 528 "asmparse.y" +{ PASM->m_pCurClass->m_ulSize = yypvt[-0].int32; } break; +case 174: +#line 529 "asmparse.y" +{ PASM->m_pCurClass->m_ulPack = yypvt[-0].int32; } break; +case 175: +#line 530 "asmparse.y" +{ PASMM->EndComType(); } break; +case 176: +#line 532 "asmparse.y" +{ BinStr *sig1 = parser->MakeSig(yypvt[-7].int32, yypvt[-6].binstr, yypvt[-1].binstr); + BinStr *sig2 = new BinStr(); sig2->append(sig1); + PASM->AddMethodImpl(yypvt[-11].token,yypvt[-9].string,sig1,yypvt[-5].token,yypvt[-3].string,sig2); + PASM->ResetArgNameList(); + } break; +case 177: +#line 538 "asmparse.y" +{ PASM->AddMethodImpl(yypvt[-17].token,yypvt[-15].string, + (yypvt[-14].int32==0 ? parser->MakeSig(yypvt[-19].int32,yypvt[-18].binstr,yypvt[-12].binstr) : + parser->MakeSig(yypvt[-19].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-18].binstr,yypvt[-12].binstr,yypvt[-14].int32)), + yypvt[-6].token,yypvt[-4].string, + (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : + parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32))); + PASM->ResetArgNameList(); + } break; +case 180: +#line 548 "asmparse.y" +{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurClass->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[yypvt[-1].int32-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } break; +case 181: +#line 553 "asmparse.y" +{ int n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); + } break; +case 182: +#line 559 "asmparse.y" +{ PASM->AddGenericParamConstraint(yypvt[-3].int32, 0, yypvt[-0].token); } break; +case 183: +#line 560 "asmparse.y" +{ PASM->AddGenericParamConstraint(0, yypvt[-2].string, yypvt[-0].token); } break; +case 184: +#line 561 "asmparse.y" +{ yypvt[-0].cad->tkInterfacePair = yypvt[-1].token; + if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); + } break; +case 185: +#line 569 "asmparse.y" +{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + PASM->AddField(yypvt[-2].string, yypvt[-3].binstr, yypvt[-4].fieldAttr, yypvt[-1].string, yypvt[-0].binstr, yypvt[-5].int32); } break; +case 186: +#line 573 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) 0; } break; +case 187: +#line 574 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdStatic); } break; +case 188: +#line 575 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPublic); } break; +case 189: +#line 576 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivate); } break; +case 190: +#line 577 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamily); } break; +case 191: +#line 578 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdInitOnly); } break; +case 192: +#line 579 "asmparse.y" +{ yyval.fieldAttr = yypvt[-1].fieldAttr; } break; +case 193: +#line 580 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdSpecialName); } break; +case 194: +#line 593 "asmparse.y" +{ PASM->m_pMarshal = yypvt[-1].binstr; } break; +case 195: +#line 594 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdAssembly); } break; +case 196: +#line 595 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamANDAssem); } break; +case 197: +#line 596 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamORAssem); } break; +case 198: +#line 597 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivateScope); } break; +case 199: +#line 598 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdLiteral); } break; +case 200: +#line 599 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdNotSerialized); } break; +case 201: +#line 600 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].int32); } break; +case 202: +#line 603 "asmparse.y" +{ yyval.string = 0; } break; +case 203: +#line 604 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 204: +#line 607 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 205: +#line 608 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 206: +#line 611 "asmparse.y" +{ yyval.int32 = 0xFFFFFFFF; } break; +case 207: +#line 612 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; } break; +case 208: +#line 617 "asmparse.y" +{ PASM->ResetArgNameList(); + if (yypvt[-3].binstr == NULL) + { + if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, parser->MakeSig(yypvt[-8].int32|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr)); + } + else + { + mdToken mr; + if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, + parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); + yyval.token = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); + } + } break; +case 209: +#line 634 "asmparse.y" +{ PASM->ResetArgNameList(); + if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, + parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, yypvt[-3].int32)); + } break; +case 210: +#line 640 "asmparse.y" +{ PASM->ResetArgNameList(); + if (yypvt[-3].binstr == NULL) + { + if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr)); + } + else + { + mdToken mr; + if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); + yyval.token = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); + } + } break; +case 211: +#line 656 "asmparse.y" +{ PASM->ResetArgNameList(); + if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, yypvt[-3].int32)); + } break; +case 212: +#line 660 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 213: +#line 661 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; +case 214: +#line 662 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; +case 215: +#line 665 "asmparse.y" +{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_HASTHIS); } break; +case 216: +#line 666 "asmparse.y" +{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); } break; +case 217: +#line 667 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 218: +#line 668 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; } break; +case 219: +#line 671 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; +case 220: +#line 672 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; +case 221: +#line 673 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_VARARG; } break; +case 222: +#line 674 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_C; } break; +case 223: +#line 675 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_STDCALL; } break; +case 224: +#line 676 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_THISCALL; } break; +case 225: +#line 677 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_FASTCALL; } break; +case 226: +#line 678 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_UNMANAGED; } break; +case 227: +#line 681 "asmparse.y" +{ yyval.token = yypvt[-1].int32; } break; +case 228: +#line 684 "asmparse.y" +{ yyval.token = yypvt[-0].token; + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + PASM->SetMemberRefFixup(yypvt[-0].token,iOpcodeLen); } break; +case 229: +#line 690 "asmparse.y" +{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + yyval.token = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 230: +#line 694 "asmparse.y" +{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + yyval.token = PASM->MakeMemberRef(NULL, yypvt[-0].string, yypvt[-1].binstr); + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 231: +#line 697 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 232: +#line 699 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 233: +#line 701 "asmparse.y" +{ yyval.token = yypvt[-0].token; + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 234: +#line 706 "asmparse.y" +{ PASM->ResetEvent(yypvt[-0].string, yypvt[-1].token, yypvt[-2].eventAttr); } break; +case 235: +#line 707 "asmparse.y" +{ PASM->ResetEvent(yypvt[-0].string, mdTypeRefNil, yypvt[-1].eventAttr); } break; +case 236: +#line 711 "asmparse.y" +{ yyval.eventAttr = (CorEventAttr) 0; } break; +case 237: +#line 712 "asmparse.y" +{ yyval.eventAttr = yypvt[-1].eventAttr; } break; +case 238: +#line 713 "asmparse.y" +{ yyval.eventAttr = (CorEventAttr) (yypvt[-1].eventAttr | evSpecialName); } break; +case 241: +#line 720 "asmparse.y" +{ PASM->SetEventMethod(0, yypvt[-0].token); } break; +case 242: +#line 721 "asmparse.y" +{ PASM->SetEventMethod(1, yypvt[-0].token); } break; +case 243: +#line 722 "asmparse.y" +{ PASM->SetEventMethod(2, yypvt[-0].token); } break; +case 244: +#line 723 "asmparse.y" +{ PASM->SetEventMethod(3, yypvt[-0].token); } break; +case 249: +#line 732 "asmparse.y" +{ PASM->ResetProp(yypvt[-4].string, + parser->MakeSig((IMAGE_CEE_CS_CALLCONV_PROPERTY | + (yypvt[-6].int32 & IMAGE_CEE_CS_CALLCONV_HASTHIS)),yypvt[-5].binstr,yypvt[-2].binstr), yypvt[-7].propAttr, yypvt[-0].binstr);} break; +case 250: +#line 737 "asmparse.y" +{ yyval.propAttr = (CorPropertyAttr) 0; } break; +case 251: +#line 738 "asmparse.y" +{ yyval.propAttr = yypvt[-1].propAttr; } break; +case 252: +#line 739 "asmparse.y" +{ yyval.propAttr = (CorPropertyAttr) (yypvt[-1].propAttr | prSpecialName); } break; +case 255: +#line 747 "asmparse.y" +{ PASM->SetPropMethod(0, yypvt[-0].token); } break; +case 256: +#line 748 "asmparse.y" +{ PASM->SetPropMethod(1, yypvt[-0].token); } break; +case 257: +#line 749 "asmparse.y" +{ PASM->SetPropMethod(2, yypvt[-0].token); } break; +case 262: +#line 757 "asmparse.y" +{ PASM->ResetForNextMethod(); + uMethodBeginLine = PASM->m_ulCurLine; + uMethodBeginColumn=PASM->m_ulCurColumn; + } break; +case 263: +#line 763 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 264: +#line 764 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 265: +#line 767 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 266: +#line 768 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 267: +#line 771 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 268: +#line 775 "asmparse.y" +{ BinStr* sig; + if (yypvt[-5].typarlist == NULL) sig = parser->MakeSig(yypvt[-10].int32, yypvt[-8].binstr, yypvt[-3].binstr); + else { + FixupTyPars(yypvt[-8].binstr); + sig = parser->MakeSig(yypvt[-10].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC, yypvt[-8].binstr, yypvt[-3].binstr, yypvt[-5].typarlist->Count()); + FixupConstraints(); + } + PASM->StartMethod(yypvt[-6].string, sig, yypvt[-11].methAttr, yypvt[-7].binstr, yypvt[-9].int32, yypvt[-5].typarlist); + TyParFixupList.RESET(false); + PASM->SetImplAttr((USHORT)yypvt[-1].implAttr); + PASM->m_pCurMethod->m_ulLines[0] = uMethodBeginLine; + PASM->m_pCurMethod->m_ulColumns[0]=uMethodBeginColumn; + } break; +case 269: +#line 790 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) 0; } break; +case 270: +#line 791 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdStatic); } break; +case 271: +#line 792 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPublic); } break; +case 272: +#line 793 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivate); } break; +case 273: +#line 794 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamily); } break; +case 274: +#line 795 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdFinal); } break; +case 275: +#line 796 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdSpecialName); } break; +case 276: +#line 797 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdVirtual); } break; +case 277: +#line 798 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdCheckAccessOnOverride); } break; +case 278: +#line 799 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdAbstract); } break; +case 279: +#line 800 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdAssem); } break; +case 280: +#line 801 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamANDAssem); } break; +case 281: +#line 802 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamORAssem); } break; +case 282: +#line 803 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivateScope); } break; +case 283: +#line 804 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdHideBySig); } break; +case 284: +#line 805 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdNewSlot); } break; +case 285: +#line 806 "asmparse.y" +{ yyval.methAttr = yypvt[-1].methAttr; } break; +case 286: +#line 807 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdUnmanagedExport); } break; +case 287: +#line 808 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdRequireSecObject); } break; +case 288: +#line 809 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].int32); } break; +case 289: +#line 811 "asmparse.y" +{ PASM->SetPinvoke(yypvt[-4].binstr,0,yypvt[-2].binstr,yypvt[-1].pinvAttr); + yyval.methAttr = (CorMethodAttr) (yypvt[-7].methAttr | mdPinvokeImpl); } break; +case 290: +#line 814 "asmparse.y" +{ PASM->SetPinvoke(yypvt[-2].binstr,0,NULL,yypvt[-1].pinvAttr); + yyval.methAttr = (CorMethodAttr) (yypvt[-5].methAttr | mdPinvokeImpl); } break; +case 291: +#line 817 "asmparse.y" +{ PASM->SetPinvoke(new BinStr(),0,NULL,yypvt[-1].pinvAttr); + yyval.methAttr = (CorMethodAttr) (yypvt[-4].methAttr | mdPinvokeImpl); } break; +case 292: +#line 821 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) 0; } break; +case 293: +#line 822 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmNoMangle); } break; +case 294: +#line 823 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAnsi); } break; +case 295: +#line 824 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetUnicode); } break; +case 296: +#line 825 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAuto); } break; +case 297: +#line 826 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmSupportsLastError); } break; +case 298: +#line 827 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvWinapi); } break; +case 299: +#line 828 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvCdecl); } break; +case 300: +#line 829 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvStdcall); } break; +case 301: +#line 830 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvThiscall); } break; +case 302: +#line 831 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvFastcall); } break; +case 303: +#line 832 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitEnabled); } break; +case 304: +#line 833 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitDisabled); } break; +case 305: +#line 834 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharEnabled); } break; +case 306: +#line 835 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharDisabled); } break; +case 307: +#line 836 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].int32); } break; +case 308: +#line 839 "asmparse.y" +{ yyval.string = newString(COR_CTOR_METHOD_NAME); } break; +case 309: +#line 840 "asmparse.y" +{ yyval.string = newString(COR_CCTOR_METHOD_NAME); } break; +case 310: +#line 841 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 311: +#line 844 "asmparse.y" +{ yyval.int32 = 0; } break; +case 312: +#line 845 "asmparse.y" +{ yyval.int32 = yypvt[-3].int32 | pdIn; } break; +case 313: +#line 846 "asmparse.y" +{ yyval.int32 = yypvt[-3].int32 | pdOut; } break; +case 314: +#line 847 "asmparse.y" +{ yyval.int32 = yypvt[-3].int32 | pdOptional; } break; +case 315: +#line 848 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 + 1; } break; +case 316: +#line 851 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (miIL | miManaged); } break; +case 317: +#line 852 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miNative); } break; +case 318: +#line 853 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miIL); } break; +case 319: +#line 854 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miOPTIL); } break; +case 320: +#line 855 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miManaged); } break; +case 321: +#line 856 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miUnmanaged); } break; +case 322: +#line 857 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miForwardRef); } break; +case 323: +#line 858 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miPreserveSig); } break; +case 324: +#line 859 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miRuntime); } break; +case 325: +#line 860 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miInternalCall); } break; +case 326: +#line 861 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miSynchronized); } break; +case 327: +#line 862 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoInlining); } break; +case 328: +#line 863 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miAggressiveInlining); } break; +case 329: +#line 864 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoOptimization); } break; +case 330: +#line 865 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miAggressiveOptimization); } break; +case 331: +#line 866 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].int32); } break; +case 332: +#line 869 "asmparse.y" +{ PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = NULL;PASM->m_lastArgName = NULL; + } break; +case 335: +#line 877 "asmparse.y" +{ PASM->EmitByte(yypvt[-0].int32); } break; +case 336: +#line 878 "asmparse.y" +{ delete PASM->m_SEHD; PASM->m_SEHD = PASM->m_SEHDstack.POP(); } break; +case 337: +#line 879 "asmparse.y" +{ PASM->EmitMaxStack(yypvt[-0].int32); } break; +case 338: +#line 880 "asmparse.y" +{ PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); + } break; +case 339: +#line 882 "asmparse.y" +{ PASM->EmitZeroInit(); + PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); + } break; +case 340: +#line 885 "asmparse.y" +{ PASM->EmitEntryPoint(); } break; +case 341: +#line 886 "asmparse.y" +{ PASM->EmitZeroInit(); } break; +case 344: +#line 889 "asmparse.y" +{ PASM->AddLabel(PASM->m_CurPC,yypvt[-1].string); /*PASM->EmitLabel($1);*/ } break; +case 350: +#line 895 "asmparse.y" +{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-1].int32; + PASM->m_pCurMethod->m_szExportAlias = NULL; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = yypvt[-1].int32 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } break; +case 351: +#line 905 "asmparse.y" +{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-3].int32; + PASM->m_pCurMethod->m_szExportAlias = yypvt[-0].string; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = yypvt[-3].int32 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } break; +case 352: +#line 915 "asmparse.y" +{ PASM->m_pCurMethod->m_wVTEntry = (WORD)yypvt[-2].int32; + PASM->m_pCurMethod->m_wVTSlot = (WORD)yypvt[-0].int32; } break; +case 353: +#line 918 "asmparse.y" +{ PASM->AddMethodImpl(yypvt[-2].token,yypvt[-0].string,NULL,NULL,NULL,NULL); } break; +case 354: +#line 921 "asmparse.y" +{ PASM->AddMethodImpl(yypvt[-6].token,yypvt[-4].string, + (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : + parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32)) + ,NULL,NULL,NULL); + PASM->ResetArgNameList(); + } break; +case 356: +#line 928 "asmparse.y" +{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurMethod->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[yypvt[-1].int32-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } break; +case 357: +#line 933 "asmparse.y" +{ int n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); + } break; +case 358: +#line 939 "asmparse.y" +{ PASM->m_pCurMethod->AddGenericParamConstraint(yypvt[-3].int32, 0, yypvt[-0].token); } break; +case 359: +#line 940 "asmparse.y" +{ PASM->m_pCurMethod->AddGenericParamConstraint(0, yypvt[-2].string, yypvt[-0].token); } break; +case 360: +#line 943 "asmparse.y" +{ if( yypvt[-2].int32 ) { + ARG_NAME_LIST* pAN=PASM->findArg(PASM->m_pCurMethod->m_firstArgName, yypvt[-2].int32 - 1); + if(pAN) + { + PASM->m_pCustomDescrList = &(pAN->CustDList); + pAN->pValue = yypvt[-0].binstr; + } + else + { + PASM->m_pCustomDescrList = NULL; + if(yypvt[-0].binstr) delete yypvt[-0].binstr; + } + } else { + PASM->m_pCustomDescrList = &(PASM->m_pCurMethod->m_RetCustDList); + PASM->m_pCurMethod->m_pRetValue = yypvt[-0].binstr; + } + PASM->m_tkCurrentCVOwner = 0; + } break; +case 361: +#line 963 "asmparse.y" +{ PASM->m_pCurMethod->CloseScope(); } break; +case 362: +#line 966 "asmparse.y" +{ PASM->m_pCurMethod->OpenScope(); } break; +case 366: +#line 977 "asmparse.y" +{ PASM->m_SEHD->tryTo = PASM->m_CurPC; } break; +case 367: +#line 978 "asmparse.y" +{ PASM->SetTryLabels(yypvt[-2].string, yypvt[-0].string); } break; +case 368: +#line 979 "asmparse.y" +{ if(PASM->m_SEHD) {PASM->m_SEHD->tryFrom = yypvt[-2].int32; + PASM->m_SEHD->tryTo = yypvt[-0].int32;} } break; +case 369: +#line 983 "asmparse.y" +{ PASM->NewSEHDescriptor(); + PASM->m_SEHD->tryFrom = PASM->m_CurPC; } break; +case 370: +#line 988 "asmparse.y" +{ PASM->EmitTry(); } break; +case 371: +#line 989 "asmparse.y" +{ PASM->EmitTry(); } break; +case 372: +#line 990 "asmparse.y" +{ PASM->EmitTry(); } break; +case 373: +#line 991 "asmparse.y" +{ PASM->EmitTry(); } break; +case 374: +#line 995 "asmparse.y" +{ PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 375: +#line 996 "asmparse.y" +{ PASM->SetFilterLabel(yypvt[-0].string); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 376: +#line 998 "asmparse.y" +{ PASM->m_SEHD->sehFilter = yypvt[-0].int32; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 377: +#line 1002 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FILTER; + PASM->m_SEHD->sehFilter = PASM->m_CurPC; } break; +case 378: +#line 1006 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_NONE; + PASM->SetCatchClass(yypvt[-0].token); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 379: +#line 1011 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FINALLY; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 380: +#line 1015 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FAULT; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 381: +#line 1019 "asmparse.y" +{ PASM->m_SEHD->sehHandlerTo = PASM->m_CurPC; } break; +case 382: +#line 1020 "asmparse.y" +{ PASM->SetHandlerLabels(yypvt[-2].string, yypvt[-0].string); } break; +case 383: +#line 1021 "asmparse.y" +{ PASM->m_SEHD->sehHandler = yypvt[-2].int32; + PASM->m_SEHD->sehHandlerTo = yypvt[-0].int32; } break; +case 385: +#line 1029 "asmparse.y" +{ PASM->EmitDataLabel(yypvt[-1].string); } break; +case 387: +#line 1033 "asmparse.y" +{ PASM->SetDataSection(); } break; +case 388: +#line 1034 "asmparse.y" +{ PASM->SetTLSSection(); } break; +case 389: +#line 1035 "asmparse.y" +{ PASM->SetILSection(); } break; +case 394: +#line 1046 "asmparse.y" +{ yyval.int32 = 1; } break; +case 395: +#line 1047 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; + if(yypvt[-1].int32 <= 0) { PASM->report->error("Illegal item count: %d\n",yypvt[-1].int32); + if(!PASM->OnErrGo) yyval.int32 = 1; }} break; +case 396: +#line 1052 "asmparse.y" +{ PASM->EmitDataString(yypvt[-1].binstr); } break; +case 397: +#line 1053 "asmparse.y" +{ PASM->EmitDD(yypvt[-1].string); } break; +case 398: +#line 1054 "asmparse.y" +{ PASM->EmitData(yypvt[-1].binstr->ptr(),yypvt[-1].binstr->length()); } break; +case 399: +#line 1056 "asmparse.y" +{ float f = (float) (*yypvt[-2].float64); float* p = new (nothrow) float[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; i < yypvt[-0].int32; i++) p[i] = f; + PASM->EmitData(p, sizeof(float)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(float)*yypvt[-0].int32); } break; +case 400: +#line 1063 "asmparse.y" +{ double* p = new (nothrow) double[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; i<yypvt[-0].int32; i++) p[i] = *(yypvt[-2].float64); + PASM->EmitData(p, sizeof(double)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(double)*yypvt[-0].int32); } break; +case 401: +#line 1070 "asmparse.y" +{ __int64* p = new (nothrow) __int64[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; i<yypvt[-0].int32; i++) p[i] = *(yypvt[-2].int64); + PASM->EmitData(p, sizeof(__int64)*yypvt[-0].int32); delete yypvt[-2].int64; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int64)*yypvt[-0].int32); } break; +case 402: +#line 1077 "asmparse.y" +{ __int32* p = new (nothrow) __int32[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; i<yypvt[-0].int32; i++) p[i] = yypvt[-2].int32; + PASM->EmitData(p, sizeof(__int32)*yypvt[-0].int32); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int32)*yypvt[-0].int32); } break; +case 403: +#line 1084 "asmparse.y" +{ __int16 i = (__int16) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); + __int16* p = new (nothrow) __int16[yypvt[-0].int32]; + if(p != NULL) { + for(int j=0; j<yypvt[-0].int32; j++) p[j] = i; + PASM->EmitData(p, sizeof(__int16)*yypvt[-0].int32); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int16)*yypvt[-0].int32); } break; +case 404: +#line 1092 "asmparse.y" +{ __int8 i = (__int8) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); + __int8* p = new (nothrow) __int8[yypvt[-0].int32]; + if(p != NULL) { + for(int j=0; j<yypvt[-0].int32; j++) p[j] = i; + PASM->EmitData(p, sizeof(__int8)*yypvt[-0].int32); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int8)*yypvt[-0].int32); } break; +case 405: +#line 1099 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(float)*yypvt[-0].int32); } break; +case 406: +#line 1100 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(double)*yypvt[-0].int32); } break; +case 407: +#line 1101 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int64)*yypvt[-0].int32); } break; +case 408: +#line 1102 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int32)*yypvt[-0].int32); } break; +case 409: +#line 1103 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int16)*yypvt[-0].int32); } break; +case 410: +#line 1104 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int8)*yypvt[-0].int32); } break; +case 411: +#line 1108 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); + float f = (float)(*yypvt[-1].float64); + yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-1].float64; } break; +case 412: +#line 1111 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].float64); delete yypvt[-1].float64; } break; +case 413: +#line 1113 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 414: +#line 1115 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 415: +#line 1117 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 416: +#line 1119 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 417: +#line 1121 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 418: +#line 1123 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); + yyval.binstr->appendInt8(yypvt[-1].int32); } break; +case 419: +#line 1125 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 420: +#line 1127 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 421: +#line 1129 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 422: +#line 1131 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); + yyval.binstr->appendInt8(yypvt[-1].int32); } break; +case 423: +#line 1133 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 424: +#line 1135 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 425: +#line 1137 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 426: +#line 1139 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); + yyval.binstr->appendInt8(yypvt[-1].int32); } break; +case 427: +#line 1141 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 428: +#line 1143 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); + yyval.binstr->appendInt8(yypvt[-1].int32);} break; +case 429: +#line 1145 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); + yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-1].binstr;} break; +case 430: +#line 1149 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 431: +#line 1152 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 432: +#line 1153 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 433: +#line 1156 "asmparse.y" +{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = new BinStr(); yyval.binstr->appendInt8(i); } break; +case 434: +#line 1157 "asmparse.y" +{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(i); } break; +case 435: +#line 1161 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 436: +#line 1162 "asmparse.y" +{ yyval.binstr = BinStrToUnicode(yypvt[-0].binstr,true); yyval.binstr->insertInt8(ELEMENT_TYPE_STRING);} break; +case 437: +#line 1163 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CLASS); + yyval.binstr->appendInt32(0); } break; +case 438: +#line 1168 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 439: +#line 1169 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); yyval.binstr->appendInt8(0xFF); } break; +case 440: +#line 1170 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); + AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; +case 441: +#line 1172 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; +case 442: +#line 1174 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-1].token));} break; +case 443: +#line 1176 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); yyval.binstr->appendInt8(0xFF); } break; +case 444: +#line 1177 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT);} break; +case 445: +#line 1179 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_R4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 446: +#line 1183 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_R8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 447: +#line 1187 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 448: +#line 1191 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 449: +#line 1195 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I2); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 450: +#line 1199 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I1); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 451: +#line 1203 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 452: +#line 1207 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 453: +#line 1211 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U2); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 454: +#line 1215 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U1); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 455: +#line 1219 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 456: +#line 1223 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 457: +#line 1227 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U2); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 458: +#line 1231 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U1); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 459: +#line 1235 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_CHAR); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 460: +#line 1239 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_BOOLEAN); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 461: +#line 1243 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_STRING); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 462: +#line 1247 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(SERIALIZATION_TYPE_TYPE); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 463: +#line 1251 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 464: +#line 1257 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 465: +#line 1258 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + float f = (float) (*yypvt[-0].float64); yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-0].float64; } break; +case 466: +#line 1260 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt32(yypvt[-0].int32); } break; +case 467: +#line 1264 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 468: +#line 1265 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt64((__int64 *)yypvt[-0].float64); delete yypvt[-0].float64; } break; +case 469: +#line 1267 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; +case 470: +#line 1271 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 471: +#line 1272 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; +case 472: +#line 1276 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 473: +#line 1277 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt32(yypvt[-0].int32);} break; +case 474: +#line 1280 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 475: +#line 1281 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt16(yypvt[-0].int32);} break; +case 476: +#line 1284 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 477: +#line 1285 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(yypvt[-0].int32); } break; +case 478: +#line 1288 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 479: +#line 1289 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt8(yypvt[-0].int32);} break; +case 480: +#line 1293 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 481: +#line 1294 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; +case 482: +#line 1295 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; +case 483: +#line 1299 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 484: +#line 1300 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; +case 485: +#line 1301 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; + AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; +case 486: +#line 1303 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token));} break; +case 487: +#line 1307 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 488: +#line 1308 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 489: +#line 1312 "asmparse.y" +{ parser->m_ANSFirst.PUSH(PASM->m_firstArgName); + parser->m_ANSLast.PUSH(PASM->m_lastArgName); + PASM->m_firstArgName = NULL; + PASM->m_lastArgName = NULL; } break; +case 490: +#line 1318 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 491: +#line 1321 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 492: +#line 1324 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 493: +#line 1327 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 494: +#line 1330 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 495: +#line 1333 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 496: +#line 1336 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); + if((!PASM->OnErrGo)&& + ((yypvt[-0].opcode == CEE_NEWOBJ)|| + (yypvt[-0].opcode == CEE_CALLVIRT))) + iCallConv = IMAGE_CEE_CS_CALLCONV_HASTHIS; + } break; +case 497: +#line 1344 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 498: +#line 1347 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 499: +#line 1350 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 500: +#line 1353 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 501: +#line 1356 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); iOpcodeLen = PASM->OpcodeLen(yyval.instr); } break; +case 502: +#line 1359 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 503: +#line 1362 "asmparse.y" +{ yyval.instr = yypvt[-1].instr; bParsingByteArray = TRUE; } break; +case 504: +#line 1366 "asmparse.y" +{ PASM->EmitOpcode(yypvt[-0].instr); } break; +case 505: +#line 1367 "asmparse.y" +{ PASM->EmitInstrVar(yypvt[-1].instr, yypvt[-0].int32); } break; +case 506: +#line 1368 "asmparse.y" +{ PASM->EmitInstrVarByName(yypvt[-1].instr, yypvt[-0].string); } break; +case 507: +#line 1369 "asmparse.y" +{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].int32); } break; +case 508: +#line 1370 "asmparse.y" +{ PASM->EmitInstrI8(yypvt[-1].instr, yypvt[-0].int64); } break; +case 509: +#line 1371 "asmparse.y" +{ PASM->EmitInstrR(yypvt[-1].instr, yypvt[-0].float64); delete (yypvt[-0].float64);} break; +case 510: +#line 1372 "asmparse.y" +{ double f = (double) (*yypvt[-0].int64); PASM->EmitInstrR(yypvt[-1].instr, &f); } break; +case 511: +#line 1373 "asmparse.y" +{ unsigned L = yypvt[-1].binstr->length(); + FAIL_UNLESS(L >= sizeof(float), ("%d hexbytes, must be at least %d\n", + L,sizeof(float))); + if(L < sizeof(float)) {YYERROR; } + else { + double f = (L >= sizeof(double)) ? *((double *)(yypvt[-1].binstr->ptr())) + : (double)(*(float *)(yypvt[-1].binstr->ptr())); + PASM->EmitInstrR(yypvt[-2].instr,&f); } + delete yypvt[-1].binstr; } break; +case 512: +#line 1382 "asmparse.y" +{ PASM->EmitInstrBrOffset(yypvt[-1].instr, yypvt[-0].int32); } break; +case 513: +#line 1383 "asmparse.y" +{ PASM->EmitInstrBrTarget(yypvt[-1].instr, yypvt[-0].string); } break; +case 514: +#line 1385 "asmparse.y" +{ PASM->SetMemberRefFixup(yypvt[-0].token,PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); + PASM->m_tkCurrentCVOwner = yypvt[-0].token; + PASM->m_pCustomDescrList = NULL; + iCallConv = 0; + } break; +case 515: +#line 1392 "asmparse.y" +{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-4].instr)); + PASM->EmitInstrI(yypvt[-4].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 516: +#line 1400 "asmparse.y" +{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-0].string, yypvt[-1].binstr); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-2].instr)); + PASM->EmitInstrI(yypvt[-2].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 517: +#line 1407 "asmparse.y" +{ mdToken mr = yypvt[-0].token; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 518: +#line 1413 "asmparse.y" +{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 519: +#line 1419 "asmparse.y" +{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 520: +#line 1425 "asmparse.y" +{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].token); + PASM->m_tkCurrentCVOwner = yypvt[-0].token; + PASM->m_pCustomDescrList = NULL; + } break; +case 521: +#line 1429 "asmparse.y" +{ PASM->EmitInstrStringLiteral(yypvt[-1].instr, yypvt[-0].binstr,TRUE); } break; +case 522: +#line 1431 "asmparse.y" +{ PASM->EmitInstrStringLiteral(yypvt[-4].instr, yypvt[-1].binstr,FALSE); } break; +case 523: +#line 1433 "asmparse.y" +{ PASM->EmitInstrStringLiteral(yypvt[-3].instr, yypvt[-1].binstr,FALSE,TRUE); } break; +case 524: +#line 1435 "asmparse.y" +{ PASM->EmitInstrSig(yypvt[-5].instr, parser->MakeSig(yypvt[-4].int32, yypvt[-3].binstr, yypvt[-1].binstr)); + PASM->ResetArgNameList(); + } break; +case 525: +#line 1439 "asmparse.y" +{ PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); + PASM->m_tkCurrentCVOwner = yypvt[-0].token; + PASM->m_pCustomDescrList = NULL; + iOpcodeLen = 0; + } break; +case 526: +#line 1444 "asmparse.y" +{ PASM->EmitInstrSwitch(yypvt[-3].instr, yypvt[-1].labels); } break; +case 527: +#line 1447 "asmparse.y" +{ yyval.labels = 0; } break; +case 528: +#line 1448 "asmparse.y" +{ yyval.labels = new Labels(yypvt[-2].string, yypvt[-0].labels, TRUE); } break; +case 529: +#line 1449 "asmparse.y" +{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-2].int32, yypvt[-0].labels, FALSE); } break; +case 530: +#line 1450 "asmparse.y" +{ yyval.labels = new Labels(yypvt[-0].string, NULL, TRUE); } break; +case 531: +#line 1451 "asmparse.y" +{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-0].int32, NULL, FALSE); } break; +case 532: +#line 1455 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 533: +#line 1456 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 534: +#line 1459 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 535: +#line 1460 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 536: +#line 1463 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 537: +#line 1464 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 538: +#line 1468 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 539: +#line 1469 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr;} break; +case 540: +#line 1472 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 541: +#line 1473 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 542: +#line 1476 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_SENTINEL); } break; +case 543: +#line 1477 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-1].binstr); PASM->addArgName(NULL, yypvt[-1].binstr, yypvt[-0].binstr, yypvt[-2].int32); } break; +case 544: +#line 1478 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-2].binstr); PASM->addArgName(yypvt[-0].string, yypvt[-2].binstr, yypvt[-1].binstr, yypvt[-3].int32);} break; +case 545: +#line 1482 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(PASM->GetAsmRef(yypvt[-2].string), yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; +case 546: +#line 1483 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(yypvt[-2].token, yypvt[-0].string, NULL); } break; +case 547: +#line 1484 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(mdTokenNil, yypvt[-0].string, NULL); } break; +case 548: +#line 1485 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(PASM->GetModRef(yypvt[-2].string),yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; +case 549: +#line 1486 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(1,yypvt[-0].string,NULL); } break; +case 550: +#line 1487 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 551: +#line 1488 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; +case 552: +#line 1489 "asmparse.y" +{ if(PASM->m_pCurClass != NULL) yyval.token = PASM->m_pCurClass->m_cl; + else { yyval.token = 0; PASM->report->error(".this outside class scope\n"); } + } break; +case 553: +#line 1492 "asmparse.y" +{ if(PASM->m_pCurClass != NULL) { + yyval.token = PASM->m_pCurClass->m_crExtends; + if(RidFromToken(yyval.token) == 0) + PASM->report->error(".base undefined\n"); + } else { yyval.token = 0; PASM->report->error(".base outside class scope\n"); } + } break; +case 554: +#line 1498 "asmparse.y" +{ if(PASM->m_pCurClass != NULL) { + if(PASM->m_pCurClass->m_pEncloser != NULL) yyval.token = PASM->m_pCurClass->m_pEncloser->m_cl; + else { yyval.token = 0; PASM->report->error(".nester undefined\n"); } + } else { yyval.token = 0; PASM->report->error(".nester outside class scope\n"); } + } break; +case 555: +#line 1505 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 556: +#line 1506 "asmparse.y" +{ yyval.string = newStringWDel(yypvt[-2].string, NESTING_SEP, yypvt[-0].string); } break; +case 557: +#line 1509 "asmparse.y" +{ yyval.token = yypvt[-0].token;} break; +case 558: +#line 1510 "asmparse.y" +{ yyval.token = PASM->GetAsmRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; +case 559: +#line 1511 "asmparse.y" +{ yyval.token = PASM->GetModRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; +case 560: +#line 1512 "asmparse.y" +{ yyval.token = PASM->ResolveTypeSpec(yypvt[-0].binstr); } break; +case 561: +#line 1516 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 562: +#line 1518 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt(yyval.binstr,yypvt[-7].binstr->length()); yyval.binstr->append(yypvt[-7].binstr); + corEmitInt(yyval.binstr,yypvt[-5].binstr->length()); yyval.binstr->append(yypvt[-5].binstr); + corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); + corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); + PASM->report->warn("Deprecated 4-string form of custom marshaler, first two strings ignored\n");} break; +case 563: +#line 1525 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt(yyval.binstr,0); + corEmitInt(yyval.binstr,0); + corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); + corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); } break; +case 564: +#line 1530 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDSYSSTRING); + corEmitInt(yyval.binstr,yypvt[-1].int32); } break; +case 565: +#line 1533 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDARRAY); + corEmitInt(yyval.binstr,yypvt[-2].int32); yyval.binstr->append(yypvt[-0].binstr); } break; +case 566: +#line 1535 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANT); + PASM->report->warn("Deprecated native type 'variant'\n"); } break; +case 567: +#line 1537 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CURRENCY); } break; +case 568: +#line 1538 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SYSCHAR); + PASM->report->warn("Deprecated native type 'syschar'\n"); } break; +case 569: +#line 1540 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VOID); + PASM->report->warn("Deprecated native type 'void'\n"); } break; +case 570: +#line 1542 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BOOLEAN); } break; +case 571: +#line 1543 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I1); } break; +case 572: +#line 1544 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I2); } break; +case 573: +#line 1545 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I4); } break; +case 574: +#line 1546 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I8); } break; +case 575: +#line 1547 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R4); } break; +case 576: +#line 1548 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R8); } break; +case 577: +#line 1549 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ERROR); } break; +case 578: +#line 1550 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; +case 579: +#line 1551 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; +case 580: +#line 1552 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; +case 581: +#line 1553 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; +case 582: +#line 1554 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; +case 583: +#line 1555 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; +case 584: +#line 1556 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; +case 585: +#line 1557 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; +case 586: +#line 1558 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(NATIVE_TYPE_PTR); + PASM->report->warn("Deprecated native type '*'\n"); } break; +case 587: +#line 1560 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); } break; +case 588: +#line 1562 "asmparse.y" +{ yyval.binstr = yypvt[-3].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt(yyval.binstr,0); + corEmitInt(yyval.binstr,yypvt[-1].int32); + corEmitInt(yyval.binstr,0); } break; +case 589: +#line 1567 "asmparse.y" +{ yyval.binstr = yypvt[-5].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt(yyval.binstr,yypvt[-1].int32); + corEmitInt(yyval.binstr,yypvt[-3].int32); + corEmitInt(yyval.binstr,ntaSizeParamIndexSpecified); } break; +case 590: +#line 1572 "asmparse.y" +{ yyval.binstr = yypvt[-4].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt(yyval.binstr,yypvt[-1].int32); } break; +case 591: +#line 1575 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DECIMAL); + PASM->report->warn("Deprecated native type 'decimal'\n"); } break; +case 592: +#line 1577 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DATE); + PASM->report->warn("Deprecated native type 'date'\n"); } break; +case 593: +#line 1579 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BSTR); } break; +case 594: +#line 1580 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTR); } break; +case 595: +#line 1581 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPWSTR); } break; +case 596: +#line 1582 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPTSTR); } break; +case 597: +#line 1583 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_OBJECTREF); + PASM->report->warn("Deprecated native type 'objectref'\n"); } break; +case 598: +#line 1585 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IUNKNOWN); + if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; +case 599: +#line 1587 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IDISPATCH); + if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; +case 600: +#line 1589 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_STRUCT); } break; +case 601: +#line 1590 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INTF); + if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; +case 602: +#line 1592 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt(yyval.binstr,yypvt[-0].int32); + corEmitInt(yyval.binstr,0);} break; +case 603: +#line 1595 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt(yyval.binstr,yypvt[-2].int32); + corEmitInt(yyval.binstr,yypvt[-0].binstr->length()); yyval.binstr->append(yypvt[-0].binstr); } break; +case 604: +#line 1599 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INT); } break; +case 605: +#line 1600 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; +case 606: +#line 1601 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; +case 607: +#line 1602 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_NESTEDSTRUCT); + PASM->report->warn("Deprecated native type 'nested struct'\n"); } break; +case 608: +#line 1604 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BYVALSTR); } break; +case 609: +#line 1605 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ANSIBSTR); } break; +case 610: +#line 1606 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_TBSTR); } break; +case 611: +#line 1607 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANTBOOL); } break; +case 612: +#line 1608 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FUNC); } break; +case 613: +#line 1609 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ASANY); } break; +case 614: +#line 1610 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTRUCT); } break; +case 615: +#line 1611 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; +case 616: +#line 1614 "asmparse.y" +{ yyval.int32 = -1; } break; +case 617: +#line 1615 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; } break; +case 618: +#line 1618 "asmparse.y" +{ yyval.int32 = VT_EMPTY; } break; +case 619: +#line 1619 "asmparse.y" +{ yyval.int32 = VT_NULL; } break; +case 620: +#line 1620 "asmparse.y" +{ yyval.int32 = VT_VARIANT; } break; +case 621: +#line 1621 "asmparse.y" +{ yyval.int32 = VT_CY; } break; +case 622: +#line 1622 "asmparse.y" +{ yyval.int32 = VT_VOID; } break; +case 623: +#line 1623 "asmparse.y" +{ yyval.int32 = VT_BOOL; } break; +case 624: +#line 1624 "asmparse.y" +{ yyval.int32 = VT_I1; } break; +case 625: +#line 1625 "asmparse.y" +{ yyval.int32 = VT_I2; } break; +case 626: +#line 1626 "asmparse.y" +{ yyval.int32 = VT_I4; } break; +case 627: +#line 1627 "asmparse.y" +{ yyval.int32 = VT_I8; } break; +case 628: +#line 1628 "asmparse.y" +{ yyval.int32 = VT_R4; } break; +case 629: +#line 1629 "asmparse.y" +{ yyval.int32 = VT_R8; } break; +case 630: +#line 1630 "asmparse.y" +{ yyval.int32 = VT_UI1; } break; +case 631: +#line 1631 "asmparse.y" +{ yyval.int32 = VT_UI2; } break; +case 632: +#line 1632 "asmparse.y" +{ yyval.int32 = VT_UI4; } break; +case 633: +#line 1633 "asmparse.y" +{ yyval.int32 = VT_UI8; } break; +case 634: +#line 1634 "asmparse.y" +{ yyval.int32 = VT_UI1; } break; +case 635: +#line 1635 "asmparse.y" +{ yyval.int32 = VT_UI2; } break; +case 636: +#line 1636 "asmparse.y" +{ yyval.int32 = VT_UI4; } break; +case 637: +#line 1637 "asmparse.y" +{ yyval.int32 = VT_UI8; } break; +case 638: +#line 1638 "asmparse.y" +{ yyval.int32 = VT_PTR; } break; +case 639: +#line 1639 "asmparse.y" +{ yyval.int32 = yypvt[-2].int32 | VT_ARRAY; } break; +case 640: +#line 1640 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | VT_VECTOR; } break; +case 641: +#line 1641 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | VT_BYREF; } break; +case 642: +#line 1642 "asmparse.y" +{ yyval.int32 = VT_DECIMAL; } break; +case 643: +#line 1643 "asmparse.y" +{ yyval.int32 = VT_DATE; } break; +case 644: +#line 1644 "asmparse.y" +{ yyval.int32 = VT_BSTR; } break; +case 645: +#line 1645 "asmparse.y" +{ yyval.int32 = VT_LPSTR; } break; +case 646: +#line 1646 "asmparse.y" +{ yyval.int32 = VT_LPWSTR; } break; +case 647: +#line 1647 "asmparse.y" +{ yyval.int32 = VT_UNKNOWN; } break; +case 648: +#line 1648 "asmparse.y" +{ yyval.int32 = VT_DISPATCH; } break; +case 649: +#line 1649 "asmparse.y" +{ yyval.int32 = VT_SAFEARRAY; } break; +case 650: +#line 1650 "asmparse.y" +{ yyval.int32 = VT_INT; } break; +case 651: +#line 1651 "asmparse.y" +{ yyval.int32 = VT_UINT; } break; +case 652: +#line 1652 "asmparse.y" +{ yyval.int32 = VT_UINT; } break; +case 653: +#line 1653 "asmparse.y" +{ yyval.int32 = VT_ERROR; } break; +case 654: +#line 1654 "asmparse.y" +{ yyval.int32 = VT_HRESULT; } break; +case 655: +#line 1655 "asmparse.y" +{ yyval.int32 = VT_CARRAY; } break; +case 656: +#line 1656 "asmparse.y" +{ yyval.int32 = VT_USERDEFINED; } break; +case 657: +#line 1657 "asmparse.y" +{ yyval.int32 = VT_RECORD; } break; +case 658: +#line 1658 "asmparse.y" +{ yyval.int32 = VT_FILETIME; } break; +case 659: +#line 1659 "asmparse.y" +{ yyval.int32 = VT_BLOB; } break; +case 660: +#line 1660 "asmparse.y" +{ yyval.int32 = VT_STREAM; } break; +case 661: +#line 1661 "asmparse.y" +{ yyval.int32 = VT_STORAGE; } break; +case 662: +#line 1662 "asmparse.y" +{ yyval.int32 = VT_STREAMED_OBJECT; } break; +case 663: +#line 1663 "asmparse.y" +{ yyval.int32 = VT_STORED_OBJECT; } break; +case 664: +#line 1664 "asmparse.y" +{ yyval.int32 = VT_BLOB_OBJECT; } break; +case 665: +#line 1665 "asmparse.y" +{ yyval.int32 = VT_CF; } break; +case 666: +#line 1666 "asmparse.y" +{ yyval.int32 = VT_CLSID; } break; +case 667: +#line 1670 "asmparse.y" +{ if(yypvt[-0].token == PASM->m_tkSysString) + { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } + else if(yypvt[-0].token == PASM->m_tkSysObject) + { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } + else + yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CLASS, yypvt[-0].token); } break; +case 668: +#line 1676 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } break; +case 669: +#line 1677 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; +case 670: +#line 1678 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; +case 671: +#line 1679 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 672: +#line 1680 "asmparse.y" +{ yyval.binstr = parser->MakeTypeArray(ELEMENT_TYPE_ARRAY, yypvt[-3].binstr, yypvt[-1].binstr); } break; +case 673: +#line 1681 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_BYREF); } break; +case 674: +#line 1682 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PTR); } break; +case 675: +#line 1683 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PINNED); } break; +case 676: +#line 1684 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_REQD, yypvt[-1].token); + yyval.binstr->append(yypvt[-4].binstr); } break; +case 677: +#line 1686 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_OPT, yypvt[-1].token); + yyval.binstr->append(yypvt[-4].binstr); } break; +case 678: +#line 1689 "asmparse.y" +{ yyval.binstr = parser->MakeSig(yypvt[-5].int32, yypvt[-4].binstr, yypvt[-1].binstr); + yyval.binstr->insertInt8(ELEMENT_TYPE_FNPTR); + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + } break; +case 679: +#line 1695 "asmparse.y" +{ if(yypvt[-1].binstr == NULL) yyval.binstr = yypvt[-3].binstr; + else { + yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(ELEMENT_TYPE_GENERICINST); + yyval.binstr->append(yypvt[-3].binstr); + corEmitInt(yyval.binstr, corCountArgs(yypvt[-1].binstr)); + yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-3].binstr; delete yypvt[-1].binstr; }} break; +case 680: +#line 1702 "asmparse.y" +{ //if(PASM->m_pCurMethod) { + // if(($3 < 0)||((DWORD)$3 >= PASM->m_pCurMethod->m_NumTyPars)) + // PASM->report->error("Invalid method type parameter '%d'\n",$3); + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_MVAR); corEmitInt(yyval.binstr, yypvt[-0].int32); + //} else PASM->report->error("Method type parameter '%d' outside method scope\n",$3); + } break; +case 681: +#line 1708 "asmparse.y" +{ //if(PASM->m_pCurClass) { + // if(($2 < 0)||((DWORD)$2 >= PASM->m_pCurClass->m_NumTyPars)) + // PASM->report->error("Invalid type parameter '%d'\n",$2); + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VAR); corEmitInt(yyval.binstr, yypvt[-0].int32); + //} else PASM->report->error("Type parameter '%d' outside class scope\n",$2); + } break; +case 682: +#line 1714 "asmparse.y" +{ int eltype = ELEMENT_TYPE_MVAR; + int n=-1; + if(PASM->m_pCurMethod) n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH(yypvt[-0].string); + eltype = ELEMENT_TYPE_MVARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid method type parameter '%s'\n",yypvt[-0].string); + n = 0x1FFFFFFF; } + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); + } break; +case 683: +#line 1729 "asmparse.y" +{ int eltype = ELEMENT_TYPE_VAR; + int n=-1; + if(PASM->m_pCurClass && !newclass) n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH(yypvt[-0].string); + eltype = ELEMENT_TYPE_VARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid type parameter '%s'\n",yypvt[-0].string); + n = 0x1FFFFFFF; } + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); + } break; +case 684: +#line 1744 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_TYPEDBYREF); } break; +case 685: +#line 1745 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VOID); } break; +case 686: +#line 1746 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I); } break; +case 687: +#line 1747 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; +case 688: +#line 1748 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; +case 689: +#line 1749 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 690: +#line 1750 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SENTINEL); } break; +case 691: +#line 1753 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); } break; +case 692: +#line 1754 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } break; +case 693: +#line 1755 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); } break; +case 694: +#line 1756 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); } break; +case 695: +#line 1757 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); } break; +case 696: +#line 1758 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); } break; +case 697: +#line 1759 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); } break; +case 698: +#line 1760 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); } break; +case 699: +#line 1761 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); } break; +case 700: +#line 1762 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; +case 701: +#line 1763 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; +case 702: +#line 1764 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; +case 703: +#line 1765 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; +case 704: +#line 1766 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; +case 705: +#line 1767 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; +case 706: +#line 1768 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; +case 707: +#line 1769 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; +case 708: +#line 1770 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; +case 709: +#line 1773 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 710: +#line 1774 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yypvt[-2].binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 711: +#line 1777 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; +case 712: +#line 1778 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; +case 713: +#line 1779 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0); yyval.binstr->appendInt32(yypvt[-0].int32); } break; +case 714: +#line 1780 "asmparse.y" +{ FAIL_UNLESS(yypvt[-2].int32 <= yypvt[-0].int32, ("lower bound %d must be <= upper bound %d\n", yypvt[-2].int32, yypvt[-0].int32)); + if (yypvt[-2].int32 > yypvt[-0].int32) { YYERROR; }; + yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-2].int32); yyval.binstr->appendInt32(yypvt[-0].int32-yypvt[-2].int32+1); } break; +case 715: +#line 1783 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-1].int32); yyval.binstr->appendInt32(0x7FFFFFFF); } break; +case 716: +#line 1788 "asmparse.y" +{ PASM->AddPermissionDecl(yypvt[-4].secAct, yypvt[-3].token, yypvt[-1].pair); } break; +case 717: +#line 1790 "asmparse.y" +{ PASM->AddPermissionDecl(yypvt[-5].secAct, yypvt[-4].token, yypvt[-1].binstr); } break; +case 718: +#line 1791 "asmparse.y" +{ PASM->AddPermissionDecl(yypvt[-1].secAct, yypvt[-0].token, (NVPair *)NULL); } break; +case 719: +#line 1792 "asmparse.y" +{ PASM->AddPermissionSetDecl(yypvt[-2].secAct, yypvt[-1].binstr); } break; +case 720: +#line 1794 "asmparse.y" +{ PASM->AddPermissionSetDecl(yypvt[-1].secAct,BinStrToUnicode(yypvt[-0].binstr,true));} break; +case 721: +#line 1796 "asmparse.y" +{ BinStr* ret = new BinStr(); + ret->insertInt8('.'); + corEmitInt(ret, nSecAttrBlobs); + ret->append(yypvt[-1].binstr); + PASM->AddPermissionSetDecl(yypvt[-4].secAct,ret); + nSecAttrBlobs = 0; } break; +case 722: +#line 1804 "asmparse.y" +{ yyval.binstr = new BinStr(); nSecAttrBlobs = 0;} break; +case 723: +#line 1805 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; nSecAttrBlobs = 1; } break; +case 724: +#line 1806 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); nSecAttrBlobs++; } break; +case 725: +#line 1810 "asmparse.y" +{ yyval.binstr = PASM->EncodeSecAttr(PASM->ReflectionNotation(yypvt[-4].token),yypvt[-1].binstr,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } break; +case 726: +#line 1813 "asmparse.y" +{ yyval.binstr = PASM->EncodeSecAttr(yypvt[-4].string,yypvt[-1].binstr,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } break; +case 727: +#line 1817 "asmparse.y" +{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; +case 728: +#line 1819 "asmparse.y" +{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; +case 729: +#line 1822 "asmparse.y" +{ yyval.pair = yypvt[-0].pair; } break; +case 730: +#line 1823 "asmparse.y" +{ yyval.pair = yypvt[-2].pair->Concat(yypvt[-0].pair); } break; +case 731: +#line 1826 "asmparse.y" +{ yypvt[-2].binstr->appendInt8(0); yyval.pair = new NVPair(yypvt[-2].binstr, yypvt[-0].binstr); } break; +case 732: +#line 1829 "asmparse.y" +{ yyval.int32 = 1; } break; +case 733: +#line 1830 "asmparse.y" +{ yyval.int32 = 0; } break; +case 734: +#line 1833 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_BOOLEAN); + yyval.binstr->appendInt8(yypvt[-0].int32); } break; +case 735: +#line 1836 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); + yyval.binstr->appendInt32(yypvt[-0].int32); } break; +case 736: +#line 1839 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 737: +#line 1842 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_STRING); + yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; + yyval.binstr->appendInt8(0); } break; +case 738: +#line 1846 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-5].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(1); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 739: +#line 1852 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-5].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(2); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 740: +#line 1858 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-5].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 741: +#line 1864 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-3].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 742: +#line 1872 "asmparse.y" +{ yyval.secAct = dclRequest; } break; +case 743: +#line 1873 "asmparse.y" +{ yyval.secAct = dclDemand; } break; +case 744: +#line 1874 "asmparse.y" +{ yyval.secAct = dclAssert; } break; +case 745: +#line 1875 "asmparse.y" +{ yyval.secAct = dclDeny; } break; +case 746: +#line 1876 "asmparse.y" +{ yyval.secAct = dclPermitOnly; } break; +case 747: +#line 1877 "asmparse.y" +{ yyval.secAct = dclLinktimeCheck; } break; +case 748: +#line 1878 "asmparse.y" +{ yyval.secAct = dclInheritanceCheck; } break; +case 749: +#line 1879 "asmparse.y" +{ yyval.secAct = dclRequestMinimum; } break; +case 750: +#line 1880 "asmparse.y" +{ yyval.secAct = dclRequestOptional; } break; +case 751: +#line 1881 "asmparse.y" +{ yyval.secAct = dclRequestRefuse; } break; +case 752: +#line 1882 "asmparse.y" +{ yyval.secAct = dclPrejitGrant; } break; +case 753: +#line 1883 "asmparse.y" +{ yyval.secAct = dclPrejitDenied; } break; +case 754: +#line 1884 "asmparse.y" +{ yyval.secAct = dclNonCasDemand; } break; +case 755: +#line 1885 "asmparse.y" +{ yyval.secAct = dclNonCasLinkDemand; } break; +case 756: +#line 1886 "asmparse.y" +{ yyval.secAct = dclNonCasInheritance; } break; +case 757: +#line 1890 "asmparse.y" +{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = FALSE; } break; +case 758: +#line 1891 "asmparse.y" +{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = TRUE; } break; +case 759: +#line 1894 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 760: +#line 1897 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-0].int32; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); } break; +case 761: +#line 1899 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-3].int32; + PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 762: +#line 1902 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-2].int32; + PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast<unsigned>(-1);} break; +case 763: +#line 1905 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-5].int32; + PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 764: +#line 1909 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-4].int32; + PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; +case 765: +#line 1912 "asmparse.y" +{ PENV->nExtLine = yypvt[-5].int32; PENV->nExtLineEnd = yypvt[-3].int32; + PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 766: +#line 1916 "asmparse.y" +{ PENV->nExtLine = yypvt[-4].int32; PENV->nExtLineEnd = yypvt[-2].int32; + PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast<unsigned>(-1); } break; +case 767: +#line 1919 "asmparse.y" +{ PENV->nExtLine = yypvt[-7].int32; PENV->nExtLineEnd = yypvt[-5].int32; + PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 768: +#line 1923 "asmparse.y" +{ PENV->nExtLine = yypvt[-6].int32; PENV->nExtLineEnd = yypvt[-4].int32; + PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; +case 769: +#line 1925 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32 - 1; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName(yypvt[-0].binstr);} break; +case 770: +#line 1932 "asmparse.y" +{ PASMM->AddFile(yypvt[-5].string, yypvt[-6].fileAttr|yypvt[-4].fileAttr|yypvt[-0].fileAttr, yypvt[-2].binstr); } break; +case 771: +#line 1933 "asmparse.y" +{ PASMM->AddFile(yypvt[-1].string, yypvt[-2].fileAttr|yypvt[-0].fileAttr, NULL); } break; +case 772: +#line 1936 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) 0; } break; +case 773: +#line 1937 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) (yypvt[-1].fileAttr | ffContainsNoMetaData); } break; +case 774: +#line 1940 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) 0; } break; +case 775: +#line 1941 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) 0x80000000; } break; +case 776: +#line 1944 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 777: +#line 1947 "asmparse.y" +{ PASMM->StartAssembly(yypvt[-0].string, NULL, (DWORD)yypvt[-1].asmAttr, FALSE); } break; +case 778: +#line 1950 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) 0; } break; +case 779: +#line 1951 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afRetargetable); } break; +case 780: +#line 1952 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afContentType_WindowsRuntime); } break; +case 781: +#line 1953 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afPA_NoPlatform); } break; +case 782: +#line 1954 "asmparse.y" +{ yyval.asmAttr = yypvt[-2].asmAttr; } break; +case 783: +#line 1955 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_MSIL); } break; +case 784: +#line 1956 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_x86); } break; +case 785: +#line 1957 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_AMD64); } break; +case 786: +#line 1958 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_ARM); } break; +case 787: +#line 1959 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_ARM64); } break; +case 790: +#line 1966 "asmparse.y" +{ PASMM->SetAssemblyHashAlg(yypvt[-0].int32); } break; +case 793: +#line 1971 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 794: +#line 1972 "asmparse.y" +{ yyval.int32 = 0xFFFF; } break; +case 795: +#line 1975 "asmparse.y" +{ PASMM->SetAssemblyPublicKey(yypvt[-1].binstr); } break; +case 796: +#line 1977 "asmparse.y" +{ PASMM->SetAssemblyVer((USHORT)yypvt[-6].int32, (USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, (USHORT)yypvt[-0].int32); } break; +case 797: +#line 1978 "asmparse.y" +{ yypvt[-0].binstr->appendInt8(0); PASMM->SetAssemblyLocale(yypvt[-0].binstr,TRUE); } break; +case 798: +#line 1979 "asmparse.y" +{ PASMM->SetAssemblyLocale(yypvt[-1].binstr,FALSE); } break; +case 801: +#line 1984 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 802: +#line 1987 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 803: +#line 1990 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 804: +#line 1994 "asmparse.y" +{ PASMM->StartAssembly(yypvt[-0].string, NULL, yypvt[-1].asmAttr, TRUE); } break; +case 805: +#line 1996 "asmparse.y" +{ PASMM->StartAssembly(yypvt[-2].string, yypvt[-0].string, yypvt[-3].asmAttr, TRUE); } break; +case 808: +#line 2003 "asmparse.y" +{ PASMM->SetAssemblyHashBlob(yypvt[-1].binstr); } break; +case 810: +#line 2005 "asmparse.y" +{ PASMM->SetAssemblyPublicKeyToken(yypvt[-1].binstr); } break; +case 811: +#line 2006 "asmparse.y" +{ PASMM->SetAssemblyAutodetect(); } break; +case 812: +#line 2009 "asmparse.y" +{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr);} break; +case 813: +#line 2012 "asmparse.y" +{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr); } break; +case 814: +#line 2015 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) 0; } break; +case 815: +#line 2016 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdNotPublic); } break; +case 816: +#line 2017 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdPublic); } break; +case 817: +#line 2018 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdForwarder); } break; +case 818: +#line 2019 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPublic); } break; +case 819: +#line 2020 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPrivate); } break; +case 820: +#line 2021 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamily); } break; +case 821: +#line 2022 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedAssembly); } break; +case 822: +#line 2023 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamANDAssem); } break; +case 823: +#line 2024 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamORAssem); } break; +case 826: +#line 2031 "asmparse.y" +{ PASMM->SetComTypeFile(yypvt[-0].string); } break; +case 827: +#line 2032 "asmparse.y" +{ PASMM->SetComTypeComType(yypvt[-0].string); } break; +case 828: +#line 2033 "asmparse.y" +{ PASMM->SetComTypeAsmRef(yypvt[-0].string); } break; +case 829: +#line 2034 "asmparse.y" +{ if(!PASMM->SetComTypeImplementationTok(yypvt[-1].int32)) + PASM->report->error("Invalid implementation of exported type\n"); } break; +case 830: +#line 2036 "asmparse.y" +{ if(!PASMM->SetComTypeClassTok(yypvt[-0].int32)) + PASM->report->error("Invalid TypeDefID of exported type\n"); } break; +case 833: +#line 2042 "asmparse.y" +{ PASMM->StartManifestRes(yypvt[-0].string, yypvt[-0].string, yypvt[-1].manresAttr); } break; +case 834: +#line 2044 "asmparse.y" +{ PASMM->StartManifestRes(yypvt[-2].string, yypvt[-0].string, yypvt[-3].manresAttr); } break; +case 835: +#line 2047 "asmparse.y" +{ yyval.manresAttr = (CorManifestResourceFlags) 0; } break; +case 836: +#line 2048 "asmparse.y" +{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPublic); } break; +case 837: +#line 2049 "asmparse.y" +{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPrivate); } break; +case 840: +#line 2056 "asmparse.y" +{ PASMM->SetManifestResFile(yypvt[-2].string, (ULONG)yypvt[-0].int32); } break; +case 841: +#line 2057 "asmparse.y" +{ PASMM->SetManifestResAsmRef(yypvt[-0].string); } break;/* End of actions */ +#line 329 "F:\\NetFXDev1\\src\\tools\\devdiv\\amd64\\yypars.c" + } + } + goto yystack; /* stack new state and value */ + } +#pragma warning(default:102) + + +#ifdef YYDUMP +YYLOCAL void YYNEAR YYPASCAL yydumpinfo(void) +{ + short stackindex; + short valindex; + + //dump yys + printf("short yys[%d] {\n", YYMAXDEPTH); + for (stackindex = 0; stackindex < YYMAXDEPTH; stackindex++){ + if (stackindex) + printf(", %s", stackindex % 10 ? "\0" : "\n"); + printf("%6d", yys[stackindex]); + } + printf("\n};\n"); + + //dump yyv + printf("YYSTYPE yyv[%d] {\n", YYMAXDEPTH); + for (valindex = 0; valindex < YYMAXDEPTH; valindex++){ + if (valindex) + printf(", %s", valindex % 5 ? "\0" : "\n"); + printf("%#*x", 3+sizeof(YYSTYPE), yyv[valindex]); + } + printf("\n};\n"); + } +#endif diff --git a/src/coreclr/ilasm/prebuilt/asmparse.grammar b/src/coreclr/ilasm/prebuilt/asmparse.grammar new file mode 100644 index 00000000000..82dac9517f7 --- /dev/null +++ b/src/coreclr/ilasm/prebuilt/asmparse.grammar @@ -0,0 +1,1280 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +Lexical tokens + ID - C style alphaNumeric identifier (e.g. Hello_There2) + DOTTEDNAME - Sequence of dot-separated IDs (e.g. System.Object) + QSTRING - C style quoted string (e.g. "hi\n") + SQSTRING - C style singlely quoted string(e.g. 'hi') + INT32 - C style 32 bit integer (e.g. 235, 03423, 0x34FFF) + INT64 - C style 64 bit integer (e.g. -2353453636235234, 0x34FFFFFFFFFF) + FLOAT64 - C style floating point number (e.g. -0.2323, 354.3423, 3435.34E-5) + INSTR_* - IL instructions of a particular class (see opcode.def). + HEXBYTE - 1- or 2-digit hexadecimal number (e.g., A2, F0). +Auxiliary lexical tokens + TYPEDEF_T - Aliased class (TypeDef or TypeRef). + TYPEDEF_M - Aliased method. + TYPEDEF_F - Aliased field. + TYPEDEF_TS - Aliased type specification (TypeSpec). + TYPEDEF_MR - Aliased field/method reference (MemberRef). + TYPEDEF_CA - Aliased Custom Attribute. +---------------------------------------------------------------------------------- +START : decls + ; + +decls : /* EMPTY */ + | decls decl + ; +/* Module-level declarations */ +decl : classHead '{' classDecls '}' + | nameSpaceHead '{' decls '}' + | methodHead methodDecls '}' + | fieldDecl + | dataDecl + | vtableDecl + | vtfixupDecl + | extSourceSpec + | fileDecl + | assemblyHead '{' assemblyDecls '}' + | assemblyRefHead '{' assemblyRefDecls '}' + | exptypeHead '{' exptypeDecls '}' + | manifestResHead '{' manifestResDecls '}' + | moduleHead + | secDecl + | customAttrDecl + | '.subsystem' int32 + | '.corflags' int32 + | '.file' 'alignment' int32 + | '.imagebase' int64 + | '.stackreserve' int64 + | languageDecl + | typedefDecl + | compControl + | '.typelist' '{' classNameSeq '}' + | '.mscorlib' + ; + +classNameSeq : /* EMPTY */ + | className classNameSeq + ; + +compQstring : QSTRING + | compQstring '+' QSTRING + ; + +languageDecl : '.language' SQSTRING + | '.language' SQSTRING ',' SQSTRING + | '.language' SQSTRING ',' SQSTRING ',' SQSTRING + ; +/* Basic tokens */ +id : ID + | SQSTRING + ; + +dottedName : id + | DOTTEDNAME + | dottedName '.' dottedName + ; + +int32 : INT32 + ; + +int64 : INT64 + | INT32 + ; + +float64 : FLOAT64 + | 'float32' '(' int32 ')' + | 'float64' '(' int64 ')' + ; + +/* Aliasing of types, type specs, methods, fields and custom attributes */ +typedefDecl : '.typedef' type 'as' dottedName + | '.typedef' className 'as' dottedName + | '.typedef' memberRef 'as' dottedName + | '.typedef' customDescr 'as' dottedName + | '.typedef' customDescrWithOwner 'as' dottedName + ; + +/* Compilation control directives are processed within yylex(), + displayed here just for grammar completeness */ +compControl : P_DEFINE dottedName + | P_DEFINE dottedName compQstring + | P_UNDEF dottedName + | P_IFDEF dottedName + | P_IFNDEF dottedName + | P_ELSE + | P_ENDIF + | P_INCLUDE QSTRING + | ';' + ; + +/* Custom attribute declarations */ +customDescr : '.custom' customType + | '.custom' customType '=' compQstring + | '.custom' customType '=' '{' customBlobDescr '}' + | customHead bytes ')' + ; + +customDescrWithOwner : '.custom' '(' ownerType ')' customType + | '.custom' '(' ownerType ')' customType '=' compQstring + | '.custom' '(' ownerType ')' customType '=' '{' customBlobDescr '}' + | customHeadWithOwner bytes ')' + ; + +customHead : '.custom' customType '=' '(' + ; + +customHeadWithOwner : '.custom' '(' ownerType ')' customType '=' '(' + ; + +customType : methodRef + ; + +ownerType : typeSpec + | memberRef + ; + +/* Verbal description of custom attribute initialization blob */ +customBlobDescr : customBlobArgs customBlobNVPairs + ; + +customBlobArgs : /* EMPTY */ + | customBlobArgs serInit + | customBlobArgs compControl + ; + +customBlobNVPairs : /* EMPTY */ + | customBlobNVPairs fieldOrProp serializType dottedName '=' serInit + | customBlobNVPairs compControl + ; + +fieldOrProp : 'field' + | 'property' + ; + +customAttrDecl : customDescr + | customDescrWithOwner + | TYPEDEF_CA + ; + +serializType : simpleType + | 'type' + | 'object' + | 'enum' 'class' SQSTRING + | 'enum' className + | serializType '[' ']' + ; + + +/* Module declaration */ +moduleHead : '.module' + | '.module' dottedName + | '.module' 'extern' dottedName + ; + +/* VTable Fixup table declaration */ +vtfixupDecl : '.vtfixup' '[' int32 ']' vtfixupAttr 'at' id + ; + +vtfixupAttr : /* EMPTY */ + | vtfixupAttr 'int32' + | vtfixupAttr 'int64' + | vtfixupAttr 'fromunmanaged' + | vtfixupAttr 'callmostderived' + | vtfixupAttr 'retainappdomain' + ; + +vtableDecl : vtableHead bytes ')' /* deprecated */ + ; + +vtableHead : '.vtable' '=' '(' /* deprecated */ + ; + +/* Namespace and class declaration */ +nameSpaceHead : '.namespace' dottedName + ; + +_class : '.class' + ; + +classHeadBegin : _class classAttr dottedName typarsClause + ; +classHead : classHeadBegin extendsClause implClause + ; + +classAttr : /* EMPTY */ + | classAttr 'public' + | classAttr 'private' + | classAttr 'value' + | classAttr 'enum' + | classAttr 'interface' + | classAttr 'sealed' + | classAttr 'abstract' + | classAttr 'auto' + | classAttr 'sequential' + | classAttr 'explicit' + | classAttr 'ansi' + | classAttr 'unicode' + | classAttr 'autochar' + | classAttr 'import' + | classAttr 'serializable' + | classAttr 'windowsruntime' + | classAttr 'nested' 'public' + | classAttr 'nested' 'private' + | classAttr 'nested' 'family' + | classAttr 'nested' 'assembly' + | classAttr 'nested' 'famandassem' + | classAttr 'nested' 'famorassem' + | classAttr 'beforefieldinit' + | classAttr 'specialname' + | classAttr 'rtspecialname' + | classAttr 'flags' '(' int32 ')' + ; + +extendsClause : /* EMPTY */ + | 'extends' typeSpec + ; + +implClause : /* EMPTY */ + | 'implements' implList + ; + +classDecls : /* EMPTY */ + | classDecls classDecl + ; + +implList : implList ',' typeSpec + | typeSpec + ; + +/* Generic type parameters declaration */ +typeList : /* EMPTY */ + | typeListNotEmpty + ; + +typeListNotEmpty : typeSpec + | typeListNotEmpty ',' typeSpec + ; + +typarsClause : /* EMPTY */ + | '<' typars '>' + ; + +typarAttrib : '+' + | '-' + | 'class' + | 'valuetype' + | '.ctor' + ; + +typarAttribs : /* EMPTY */ + | typarAttrib typarAttribs + ; + +typars : typarAttribs tyBound dottedName typarsRest + | typarAttribs dottedName typarsRest + ; + +typarsRest : /* EMPTY */ + | ',' typars + ; + +tyBound : '(' typeList ')' + ; + +genArity : /* EMPTY */ + | genArityNotEmpty + ; + +genArityNotEmpty : '<' '[' int32 ']' '>' + ; + +/* Class body declarations */ +classDecl : methodHead methodDecls '}' + | classHead '{' classDecls '}' + | eventHead '{' eventDecls '}' + | propHead '{' propDecls '}' + | fieldDecl + | dataDecl + | secDecl + | extSourceSpec + | customAttrDecl + | '.size' int32 + | '.pack' int32 + | exportHead '{' exptypeDecls '}' + | '.override' typeSpec '::' methodName 'with' callConv type typeSpec '::' methodName '(' sigArgs0 ')' + | '.override' 'method' callConv type typeSpec '::' methodName genArity '(' sigArgs0 ')' 'with' 'method' callConv type typeSpec '::' methodName genArity '(' sigArgs0 ')' + | languageDecl + | compControl + | '.param' 'type' '[' int32 ']' + | '.param' 'type' dottedName + | '.param' 'constraint' '[' int32 ']' ',' typeSpec + | '.param' 'constraint' dottedName ',' typeSpec + | '.interfaceimpl' 'type' typeSpec customDescr + ; + +/* Field declaration */ +fieldDecl : '.field' repeatOpt fieldAttr type dottedName atOpt initOpt + ; + +fieldAttr : /* EMPTY */ + | fieldAttr 'static' + | fieldAttr 'public' + | fieldAttr 'private' + | fieldAttr 'family' + | fieldAttr 'initonly' + | fieldAttr 'rtspecialname' /**/ + | fieldAttr 'specialname' + /* <STRIP>commented out because PInvoke for fields is not supported by EE + | fieldAttr 'pinvokeimpl' '(' compQstring 'as' compQstring pinvAttr ')' + | fieldAttr 'pinvokeimpl' '(' compQstring pinvAttr ')' + | fieldAttr 'pinvokeimpl' '(' pinvAttr ')' + </STRIP>*/ + | fieldAttr 'marshal' '(' marshalBlob ')' + | fieldAttr 'assembly' + | fieldAttr 'famandassem' + | fieldAttr 'famorassem' + | fieldAttr 'privatescope' + | fieldAttr 'literal' + | fieldAttr 'notserialized' + | fieldAttr 'flags' '(' int32 ')' + ; + +atOpt : /* EMPTY */ + | 'at' id + ; + +initOpt : /* EMPTY */ + | '=' fieldInit + ; + +repeatOpt : /* EMPTY */ + | '[' int32 ']' + ; + +/* Method referencing */ +methodRef : callConv type typeSpec '::' methodName tyArgs0 '(' sigArgs0 ')' + | callConv type typeSpec '::' methodName genArityNotEmpty '(' sigArgs0 ')' + | callConv type methodName tyArgs0 '(' sigArgs0 ')' + | callConv type methodName genArityNotEmpty '(' sigArgs0 ')' + | mdtoken + | TYPEDEF_M + | TYPEDEF_MR + ; + +callConv : 'instance' callConv + | 'explicit' callConv + | callKind + | 'callconv' '(' int32 ')' + ; + +callKind : /* EMPTY */ + | 'default' + | 'vararg' + | 'unmanaged' 'cdecl' + | 'unmanaged' 'stdcall' + | 'unmanaged' 'thiscall' + | 'unmanaged' 'fastcall' + | 'unmanaged' + ; + +mdtoken : 'mdtoken' '(' int32 ')' + ; + +memberRef : methodSpec methodRef + | 'field' type typeSpec '::' dottedName + | 'field' type dottedName + | 'field' TYPEDEF_F + | 'field' TYPEDEF_MR + | mdtoken + ; + +/* Event declaration */ +eventHead : '.event' eventAttr typeSpec dottedName + | '.event' eventAttr dottedName + ; + + +eventAttr : /* EMPTY */ + | eventAttr 'rtspecialname' /**/ + | eventAttr 'specialname' + ; + +eventDecls : /* EMPTY */ + | eventDecls eventDecl + ; + +eventDecl : '.addon' methodRef + | '.removeon' methodRef + | '.fire' methodRef + | '.other' methodRef + | extSourceSpec + | customAttrDecl + | languageDecl + | compControl + ; + +/* Property declaration */ +propHead : '.property' propAttr callConv type dottedName '(' sigArgs0 ')' initOpt + ; + +propAttr : /* EMPTY */ + | propAttr 'rtspecialname' /**/ + | propAttr 'specialname' + ; + +propDecls : /* EMPTY */ + | propDecls propDecl + ; + + +propDecl : '.set' methodRef + | '.get' methodRef + | '.other' methodRef + | customAttrDecl + | extSourceSpec + | languageDecl + | compControl + ; + +/* Method declaration */ +methodHeadPart1 : '.method' + ; + +marshalClause : /* EMPTY */ + | 'marshal' '(' marshalBlob ')' + ; + +marshalBlob : nativeType + | marshalBlobHead hexbytes '}' + ; + +marshalBlobHead : '{' + ; + +methodHead : methodHeadPart1 methAttr callConv paramAttr type marshalClause methodName typarsClause'(' sigArgs0 ')' implAttr '{' + ; + +methAttr : /* EMPTY */ + | methAttr 'static' + | methAttr 'public' + | methAttr 'private' + | methAttr 'family' + | methAttr 'final' + | methAttr 'specialname' + | methAttr 'virtual' + | methAttr 'strict' + | methAttr 'abstract' + | methAttr 'assembly' + | methAttr 'famandassem' + | methAttr 'famorassem' + | methAttr 'privatescope' + | methAttr 'hidebysig' + | methAttr 'newslot' + | methAttr 'rtspecialname' /**/ + | methAttr 'unmanagedexp' + | methAttr 'reqsecobj' + | methAttr 'flags' '(' int32 ')' + | methAttr 'pinvokeimpl' '(' compQstring 'as' compQstring pinvAttr ')' + | methAttr 'pinvokeimpl' '(' compQstring pinvAttr ')' + | methAttr 'pinvokeimpl' '(' pinvAttr ')' + ; + +pinvAttr : /* EMPTY */ + | pinvAttr 'nomangle' + | pinvAttr 'ansi' + | pinvAttr 'unicode' + | pinvAttr 'autochar' + | pinvAttr 'lasterr' + | pinvAttr 'winapi' + | pinvAttr 'cdecl' + | pinvAttr 'stdcall' + | pinvAttr 'thiscall' + | pinvAttr 'fastcall' + | pinvAttr 'bestfit' ':' 'on' + | pinvAttr 'bestfit' ':' 'off' + | pinvAttr 'charmaperror' ':' 'on' + | pinvAttr 'charmaperror' ':' 'off' + | pinvAttr 'flags' '(' int32 ')' + ; + +methodName : '.ctor' + | '.cctor' + | dottedName + ; + +paramAttr : /* EMPTY */ + | paramAttr '[' 'in' ']' + | paramAttr '[' 'out' ']' + | paramAttr '[' 'opt' ']' + | paramAttr '[' int32 ']' + ; + +implAttr : /* EMPTY */ + | implAttr 'native' + | implAttr 'cil' + | implAttr 'optil' + | implAttr 'managed' + | implAttr 'unmanaged' + | implAttr 'forwardref' + | implAttr 'preservesig' + | implAttr 'runtime' + | implAttr 'internalcall' + | implAttr 'synchronized' + | implAttr 'noinlining' + | implAttr 'aggressiveinlining' + | implAttr 'nooptimization' + | implAttr 'aggressiveoptimization' + | implAttr 'flags' '(' int32 ')' + ; + +localsHead : '.locals' + ; + +methodDecls : /* EMPTY */ + | methodDecls methodDecl + ; + +methodDecl : '.emitbyte' int32 + | sehBlock + | '.maxstack' int32 + | localsHead '(' sigArgs0 ')' + | localsHead 'init' '(' sigArgs0 ')' + | '.entrypoint' + | '.zeroinit' + | dataDecl + | instr + | id ':' + | secDecl + | extSourceSpec + | languageDecl + | customAttrDecl + | compControl + | '.export' '[' int32 ']' + | '.export' '[' int32 ']' 'as' id + | '.vtentry' int32 ':' int32 + | '.override' typeSpec '::' methodName + + | '.override' 'method' callConv type typeSpec '::' methodName genArity '(' sigArgs0 ')' + | scopeBlock + | '.param' 'type' '[' int32 ']' + | '.param' 'type' dottedName + | '.param' 'constraint' '[' int32 ']' ',' typeSpec + | '.param' 'constraint' dottedName ',' typeSpec + + | '.param' '[' int32 ']' initOpt + ; + +scopeBlock : scopeOpen methodDecls '}' + ; + +scopeOpen : '{' + ; + +/* Structured exception handling directives */ +sehBlock : tryBlock sehClauses + ; + +sehClauses : sehClause sehClauses + | sehClause + ; + +tryBlock : tryHead scopeBlock + | tryHead id 'to' id + | tryHead int32 'to' int32 + ; + +tryHead : '.try' + ; + + +sehClause : catchClause handlerBlock + | filterClause handlerBlock + | finallyClause handlerBlock + | faultClause handlerBlock + ; + + +filterClause : filterHead scopeBlock + | filterHead id + | filterHead int32 + ; + +filterHead : 'filter' + ; + +catchClause : 'catch' typeSpec + ; + +finallyClause : 'finally' + ; + +faultClause : 'fault' + ; + +handlerBlock : scopeBlock + | 'handler' id 'to' id + | 'handler' int32 'to' int32 + ; + +/* Data declaration */ +dataDecl : ddHead ddBody + ; + +ddHead : '.data' tls id '=' + | '.data' tls + ; + +tls : /* EMPTY */ + | 'tls' + | 'cil' + ; + +ddBody : '{' ddItemList '}' + | ddItem + ; + +ddItemList : ddItem ',' ddItemList + | ddItem + ; + +ddItemCount : /* EMPTY */ + | '[' int32 ']' + ; + +ddItem : 'char' '*' '(' compQstring ')' + | '&' '(' id ')' + | bytearrayhead bytes ')' + | 'float32' '(' float64 ')' ddItemCount + | 'float64' '(' float64 ')' ddItemCount + | 'int64' '(' int64 ')' ddItemCount + | 'int32' '(' int32 ')' ddItemCount + | 'int16' '(' int32 ')' ddItemCount + | 'int8' '(' int32 ')' ddItemCount + | 'float32' ddItemCount + | 'float64' ddItemCount + | 'int64' ddItemCount + | 'int32' ddItemCount + | 'int16' ddItemCount + | 'int8' ddItemCount + ; + +/* Default values declaration for fields, parameters and verbal form of CA blob description */ +fieldSerInit : 'float32' '(' float64 ')' + | 'float64' '(' float64 ')' + | 'float32' '(' int32 ')' + | 'float64' '(' int64 ')' + | 'int64' '(' int64 ')' + | 'int32' '(' int32 ')' + | 'int16' '(' int32 ')' + | 'int8' '(' int32 ')' + | 'unsigned' 'int64' '(' int64 ')' + | 'unsigned' 'int32' '(' int32 ')' + | 'unsigned' 'int16' '(' int32 ')' + | 'unsigned' 'int8' '(' int32 ')' + | 'uint64' '(' int64 ')' + | 'uint32' '(' int32 ')' + | 'uint16' '(' int32 ')' + | 'uint8' '(' int32 ')' + | 'char' '(' int32 ')' + | 'bool' '(' truefalse ')' + | bytearrayhead bytes ')' + ; + +bytearrayhead : 'bytearray' '(' + ; + +bytes : /* EMPTY */ + | hexbytes + ; + +hexbytes : HEXBYTE + | hexbytes HEXBYTE + ; + +/* Field/parameter initialization */ +fieldInit : fieldSerInit + | compQstring + | 'nullref' + ; + +/* Values for verbal form of CA blob description */ +serInit : fieldSerInit + | 'string' '(' 'nullref' ')' + | 'string' '(' SQSTRING ')' + | 'type' '(' 'class' SQSTRING ')' + | 'type' '(' className ')' + | 'type' '(' 'nullref' ')' + | 'object' '(' serInit ')' + | 'float32' '[' int32 ']' '(' f32seq ')' + | 'float64' '[' int32 ']' '(' f64seq ')' + | 'int64' '[' int32 ']' '(' i64seq ')' + | 'int32' '[' int32 ']' '(' i32seq ')' + | 'int16' '[' int32 ']' '(' i16seq ')' + | 'int8' '[' int32 ']' '(' i8seq ')' + | 'uint64' '[' int32 ']' '(' i64seq ')' + | 'uint32' '[' int32 ']' '(' i32seq ')' + | 'uint16' '[' int32 ']' '(' i16seq ')' + | 'uint8' '[' int32 ']' '(' i8seq ')' + | 'unsigned' 'int64' '[' int32 ']' '(' i64seq ')' + | 'unsigned' 'int32' '[' int32 ']' '(' i32seq ')' + | 'unsigned' 'int16' '[' int32 ']' '(' i16seq ')' + | 'unsigned' 'int8' '[' int32 ']' '(' i8seq ')' + | 'char' '[' int32 ']' '(' i16seq ')' + | 'bool' '[' int32 ']' '(' boolSeq ')' + | 'string' '[' int32 ']' '(' sqstringSeq ')' + | 'type' '[' int32 ']' '(' classSeq ')' + | 'object' '[' int32 ']' '(' objSeq ')' + ; + + +f32seq : /* EMPTY */ + | f32seq float64 + | f32seq int32 + ; + +f64seq : /* EMPTY */ + | f64seq float64 + | f64seq int64 + ; + +i64seq : /* EMPTY */ + | i64seq int64 + ; + +i32seq : /* EMPTY */ + | i32seq int32 + ; + +i16seq : /* EMPTY */ + | i16seq int32 + ; + +i8seq : /* EMPTY */ + | i8seq int32 + ; + +boolSeq : /* EMPTY */ + | boolSeq truefalse + ; + +sqstringSeq : /* EMPTY */ + | sqstringSeq 'nullref' + | sqstringSeq SQSTRING + ; + +classSeq : /* EMPTY */ + | classSeq 'nullref' + | classSeq 'class' SQSTRING + | classSeq className + ; + +objSeq : /* EMPTY */ + | objSeq serInit + ; + +/* IL instructions and associated definitions */ +methodSpec : 'method' + ; + +instr_none : INSTR_NONE + ; + +instr_var : INSTR_VAR + ; + +instr_i : INSTR_I + ; + +instr_i8 : INSTR_I8 + ; + +instr_r : INSTR_R + ; + +instr_brtarget : INSTR_BRTARGET + ; + +instr_method : INSTR_METHOD + ; + +instr_field : INSTR_FIELD + ; + +instr_type : INSTR_TYPE + ; + +instr_string : INSTR_STRING + ; + +instr_sig : INSTR_SIG + ; + +instr_tok : INSTR_TOK + ; + +instr_switch : INSTR_SWITCH + ; + +instr_r_head : instr_r '(' + ; + + +instr : instr_none + | instr_var int32 + | instr_var id + | instr_i int32 + | instr_i8 int64 + | instr_r float64 + | instr_r int64 + | instr_r_head bytes ')' + | instr_brtarget int32 + | instr_brtarget id + | instr_method methodRef + | instr_field type typeSpec '::' dottedName + | instr_field type dottedName + | instr_field mdtoken + | instr_field TYPEDEF_F + | instr_field TYPEDEF_MR + | instr_type typeSpec + | instr_string compQstring + | instr_string 'ansi' '(' compQstring ')' + | instr_string bytearrayhead bytes ')' + | instr_sig callConv type '(' sigArgs0 ')' + | instr_tok ownerType /* ownerType ::= memberRef | typeSpec */ + | instr_switch '(' labels ')' + ; + +labels : /* empty */ + | id ',' labels + | int32 ',' labels + | id + | int32 + ; + +/* Signatures */ +tyArgs0 : /* EMPTY */ + | '<' tyArgs1 '>' + ; + +tyArgs1 : /* EMPTY */ + | tyArgs2 + ; + +tyArgs2 : type + | tyArgs2 ',' type + ; + + +sigArgs0 : /* EMPTY */ + | sigArgs1 + ; + +sigArgs1 : sigArg + | sigArgs1 ',' sigArg + ; + +sigArg : '...' + | paramAttr type marshalClause + | paramAttr type marshalClause id + ; + +/* Class referencing */ +className : '[' dottedName ']' slashedName + | '[' mdtoken ']' slashedName + | '[' '*' ']' slashedName + | '[' '.module' dottedName ']' slashedName + | slashedName + | mdtoken + | TYPEDEF_T + | '.this' + | '.base' + | '.nester' + ; + +slashedName : dottedName + | slashedName '/' dottedName + ; + +typeSpec : className + | '[' dottedName ']' + | '[' '.module' dottedName ']' + | type + ; + +/* Native types for marshaling signatures */ +nativeType : /* EMPTY */ + | 'custom' '(' compQstring ',' compQstring ',' compQstring ',' compQstring ')' + | 'custom' '(' compQstring ',' compQstring ')' + | 'fixed' 'sysstring' '[' int32 ']' + | 'fixed' 'array' '[' int32 ']' nativeType + | 'variant' + | 'currency' + | 'syschar' + | 'void' + | 'bool' + | 'int8' + | 'int16' + | 'int32' + | 'int64' + | 'float32' + | 'float64' + | 'error' + | 'unsigned' 'int8' + | 'unsigned' 'int16' + | 'unsigned' 'int32' + | 'unsigned' 'int64' + | 'uint8' + | 'uint16' + | 'uint32' + | 'uint64' + | nativeType '*' + | nativeType '[' ']' + | nativeType '[' int32 ']' + | nativeType '[' int32 '+' int32 ']' + | nativeType '[' '+' int32 ']' + | 'decimal' + | 'date' + | 'bstr' + | 'lpstr' + | 'lpwstr' + | 'lptstr' + | 'objectref' + | 'iunknown' iidParamIndex + | 'idispatch' iidParamIndex + | 'struct' + | 'interface' iidParamIndex + | 'safearray' variantType + | 'safearray' variantType ',' compQstring + + | 'int' + | 'unsigned' 'int' + | 'uint' + | 'nested' 'struct' + | 'byvalstr' + | 'ansi' 'bstr' + | 'tbstr' + | 'variant' 'bool' + | 'method' + | 'as' 'any' + | 'lpstruct' + | TYPEDEF_TS + ; + +iidParamIndex : /* EMPTY */ + | '(' 'iidparam' '=' int32 ')' + ; + +variantType : /* EMPTY */ + | 'null' + | 'variant' + | 'currency' + | 'void' + | 'bool' + | 'int8' + | 'int16' + | 'int32' + | 'int64' + | 'float32' + | 'float64' + | 'unsigned' 'int8' + | 'unsigned' 'int16' + | 'unsigned' 'int32' + | 'unsigned' 'int64' + | 'uint8' + | 'uint16' + | 'uint32' + | 'uint64' + | '*' + | variantType '[' ']' + | variantType 'vector' + | variantType '&' + | 'decimal' + | 'date' + | 'bstr' + | 'lpstr' + | 'lpwstr' + | 'iunknown' + | 'idispatch' + | 'safearray' + | 'int' + | 'unsigned' 'int' + | 'uint' + | 'error' + | 'hresult' + | 'carray' + | 'userdefined' + | 'record' + | 'filetime' + | 'blob' + | 'stream' + | 'storage' + | 'streamed_object' + | 'stored_object' + | 'blob_object' + | 'cf' + | 'clsid' + ; + +/* Managed types for signatures */ +type : 'class' className + | 'object' + | 'value' 'class' className + | 'valuetype' className + | type '[' ']' + | type '[' bounds1 ']' + | type '&' + | type '*' + | type 'pinned' + | type 'modreq' '(' typeSpec ')' + | type 'modopt' '(' typeSpec ')' + | methodSpec callConv type '*' '(' sigArgs0 ')' + | type '<' tyArgs1 '>' + | '!' '!' int32 + | '!' int32 + | '!' '!' dottedName + | '!' dottedName + | 'typedref' + | 'void' + | 'native' 'int' + | 'native' 'unsigned' 'int' + | 'native' 'uint' + | simpleType + | '...' type + ; + +simpleType : 'char' + | 'string' + | 'bool' + | 'int8' + | 'int16' + | 'int32' + | 'int64' + | 'float32' + | 'float64' + | 'unsigned' 'int8' + | 'unsigned' 'int16' + | 'unsigned' 'int32' + | 'unsigned' 'int64' + | 'uint8' + | 'uint16' + | 'uint32' + | 'uint64' + | TYPEDEF_TS + ; + +bounds1 : bound + | bounds1 ',' bound + ; + +bound : /* EMPTY */ + | '...' + | int32 + | int32 '...' int32 + | int32 '...' + ; + +/* Security declarations */ +secDecl : '.permission' secAction typeSpec '(' nameValPairs ')' + | '.permission' secAction typeSpec '=' '{' customBlobDescr '}' + | '.permission' secAction typeSpec + | psetHead bytes ')' + | '.permissionset' secAction compQstring + | '.permissionset' secAction '=' '{' secAttrSetBlob '}' + ; + +secAttrSetBlob : /* EMPTY */ + | secAttrBlob + | secAttrBlob ',' secAttrSetBlob + ; + +secAttrBlob : typeSpec '=' '{' customBlobNVPairs '}' + | 'class' SQSTRING '=' '{' customBlobNVPairs '}' + ; + +psetHead : '.permissionset' secAction '=' '(' + | '.permissionset' secAction 'bytearray' '(' + ; + +nameValPairs : nameValPair + | nameValPair ',' nameValPairs + ; + +nameValPair : compQstring '=' caValue + ; + +truefalse : 'true' + | 'false' + ; + +caValue : truefalse + | int32 + | 'int32' '(' int32 ')' + | compQstring + | className '(' 'int8' ':' int32 ')' + | className '(' 'int16' ':' int32 ')' + | className '(' 'int32' ':' int32 ')' + | className '(' int32 ')' + ; + +secAction : 'request' + | 'demand' + | 'assert' + | 'deny' + | 'permitonly' + | 'linkcheck' + | 'inheritcheck' + | 'reqmin' + | 'reqopt' + | 'reqrefuse' + | 'prejitgrant' + | 'prejitdeny' + | 'noncasdemand' + | 'noncaslinkdemand' + | 'noncasinheritance' + ; + +/* External source declarations */ +esHead : '.line' + | P_LINE + ; + +extSourceSpec : esHead int32 SQSTRING + | esHead int32 + | esHead int32 ':' int32 SQSTRING + | esHead int32 ':' int32 + | esHead int32 ':' int32 ',' int32 SQSTRING + | esHead int32 ':' int32 ',' int32 + | esHead int32 ',' int32 ':' int32 SQSTRING + | esHead int32 ',' int32 ':' int32 + | esHead int32 ',' int32 ':' int32 ',' int32 SQSTRING + | esHead int32 ',' int32 ':' int32 ',' int32 + | esHead int32 QSTRING + ; + +/* Manifest declarations */ +fileDecl : '.file' fileAttr dottedName fileEntry hashHead bytes ')' fileEntry + | '.file' fileAttr dottedName fileEntry + ; + +fileAttr : /* EMPTY */ + | fileAttr 'nometadata' + ; + +fileEntry : /* EMPTY */ + | '.entrypoint' + ; + +hashHead : '.hash' '=' '(' + ; + +assemblyHead : '.assembly' asmAttr dottedName + ; + +asmAttr : /* EMPTY */ + | asmAttr 'retargetable' + | asmAttr 'windowsruntime' + | asmAttr 'noplatform' + | asmAttr 'legacy' 'library' + | asmAttr 'cil' + | asmAttr 'x86' + | asmAttr 'amd64' + | asmAttr 'arm' + | asmAttr 'arm64' + ; + +assemblyDecls : /* EMPTY */ + | assemblyDecls assemblyDecl + ; + +assemblyDecl : '.hash' 'algorithm' int32 + | secDecl + | asmOrRefDecl + ; + +intOrWildcard : int32 + | '*' + ; + +asmOrRefDecl : publicKeyHead bytes ')' + | '.ver' intOrWildcard ':' intOrWildcard ':' intOrWildcard ':' intOrWildcard + | '.locale' compQstring + | localeHead bytes ')' + | customAttrDecl + | compControl + ; + +publicKeyHead : '.publickey' '=' '(' + ; + +publicKeyTokenHead : '.publickeytoken' '=' '(' + ; + +localeHead : '.locale' '=' '(' + ; + +assemblyRefHead : '.assembly' 'extern' asmAttr dottedName + | '.assembly' 'extern' asmAttr dottedName 'as' dottedName + ; + +assemblyRefDecls : /* EMPTY */ + | assemblyRefDecls assemblyRefDecl + ; + +assemblyRefDecl : hashHead bytes ')' + | asmOrRefDecl + | publicKeyTokenHead bytes ')' + | 'auto' + ; + +exptypeHead : '.class' 'extern' exptAttr dottedName + ; + +exportHead : '.export' exptAttr dottedName /* deprecated */ + ; + +exptAttr : /* EMPTY */ + | exptAttr 'private' + | exptAttr 'public' + | exptAttr 'forwarder' + | exptAttr 'nested' 'public' + | exptAttr 'nested' 'private' + | exptAttr 'nested' 'family' + | exptAttr 'nested' 'assembly' + | exptAttr 'nested' 'famandassem' + | exptAttr 'nested' 'famorassem' + ; + +exptypeDecls : /* EMPTY */ + | exptypeDecls exptypeDecl + ; + +exptypeDecl : '.file' dottedName + | '.class' 'extern' slashedName + | '.assembly' 'extern' dottedName + | 'mdtoken' '(' int32 ')' + | '.class' int32 + | customAttrDecl + | compControl + ; + +manifestResHead : '.mresource' manresAttr dottedName + | '.mresource' manresAttr dottedName 'as' dottedName + ; + +manresAttr : /* EMPTY */ + | manresAttr 'public' + | manresAttr 'private' + ; + +manifestResDecls : /* EMPTY */ + | manifestResDecls manifestResDecl + ; + +manifestResDecl : '.file' dottedName 'at' int32 + | '.assembly' 'extern' dottedName + | customAttrDecl + | compControl + ; + diff --git a/src/coreclr/ilasm/typar.hpp b/src/coreclr/ilasm/typar.hpp new file mode 100644 index 00000000000..aee0c32c452 --- /dev/null +++ b/src/coreclr/ilasm/typar.hpp @@ -0,0 +1,182 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +/**************************************************************************/ +/* a type parameter list */ + +#ifndef TYPAR_H +#define TYPAR_H +#include "binstr.h" + +extern unsigned int g_uCodePage; + +class TyParDescr +{ +public: + TyParDescr() + { + m_pbsBounds = NULL; + m_wzName = NULL; + m_dwAttrs = 0; + }; + ~TyParDescr() + { + delete m_pbsBounds; + delete [] m_wzName; + m_lstCA.RESET(true); + }; + void Init(BinStr* bounds, LPCUTF8 name, DWORD attrs) + { + m_pbsBounds = bounds; + ULONG cTemp = (ULONG)strlen(name)+1; + WCHAR *pwzName; + m_wzName = pwzName = new WCHAR[cTemp]; + if(pwzName) + { + memset(pwzName,0,sizeof(WCHAR)*cTemp); + WszMultiByteToWideChar(g_uCodePage,0,name,-1,pwzName,cTemp); + } + m_dwAttrs = attrs; + }; + BinStr* Bounds() { return m_pbsBounds; }; + LPCWSTR Name() { return m_wzName; }; + DWORD Attrs() { return m_dwAttrs; }; + mdToken Token() { return m_token; }; + void Token(mdToken value) + { + m_token = value; + }; + CustomDescrList* CAList() { return &m_lstCA; }; + +private: + BinStr* m_pbsBounds; + LPCWSTR m_wzName; + DWORD m_dwAttrs; + mdToken m_token; + CustomDescrList m_lstCA; +}; + +class TyParList { +public: + TyParList(DWORD a, BinStr* b, LPCUTF8 n, TyParList* nx = NULL) + { + bound = (b == NULL) ? new BinStr() : b; + bound->appendInt32(0); // zero terminator + attrs = a; name = n; next = nx; + }; + ~TyParList() + { + if( bound) delete bound; + + // To avoid excessive stack usage (especially in debug builds), we break the next chain + // and delete as we traverse the link list + TyParList *pCur = next; + while (pCur != NULL) + { + TyParList *pTmp = pCur->next; + pCur->next = NULL; + delete pCur; + pCur = pTmp; + } + }; + int Count() + { + TyParList* tp = this; + int n; + for(n = 1; (tp = tp->next) != NULL; n++); + return n; + }; + int IndexOf(LPCUTF8 name) + { + TyParList* tp = this; + int n; + int ret = -1; + for(n=0; tp != NULL; n++, tp = tp->next) + { + if(tp->name == NULL) + { + if(name == NULL) ret = n; + } + else + { + if(name == NULL) continue; + if(0 == strcmp(name,tp->name)) ret = n; + } + } + return ret; + }; + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:6211) // "Leaking memory 'b' due to an exception. Consider using a local catch block to clean up memory" +#endif /*_PREFAST_ */ + + int ToArray(BinStr ***bounds, LPCWSTR** names, DWORD **attrs) + { + int n = Count(); + BinStr **b = new BinStr* [n]; + LPCWSTR *nam = new LPCWSTR [n]; + DWORD *attr = attrs ? new DWORD [n] : NULL; + TyParList *tp = this; + int i = 0; + while (tp) + { + ULONG cTemp = (ULONG)strlen(tp->name)+1; + WCHAR* wzDllName = new WCHAR [cTemp]; + // Convert name to UNICODE + memset(wzDllName,0,sizeof(WCHAR)*cTemp); + WszMultiByteToWideChar(g_uCodePage,0,tp->name,-1,wzDllName,cTemp); + nam[i] = (LPCWSTR)wzDllName; + b[i] = tp->bound; + if (attr) + attr[i] = tp->attrs; + tp->bound = 0; // to avoid deletion by destructor + i++; + tp = tp->next; + } + *bounds = b; + *names = nam; + if (attrs) + *attrs = attr; + return n; + }; + +#ifdef _PREFAST_ +#pragma warning(pop) +#endif /*_PREFAST_*/ + + int ToArray(TyParDescr **ppTPD) + { + int n = Count(); + TyParDescr *pTPD = NULL; + if(n) + { + pTPD = new TyParDescr[n]; + if(pTPD) + { + int i = 0; + TyParList *tp = this; + while (tp) + { + pTPD[i].Init(tp->bound,tp->name,tp->attrs); + tp->bound = 0; // to avoid deletion by destructor + i++; + tp = tp->next; + } + } + } + *ppTPD = pTPD; + return n; + }; + TyParList* Next() { return next; }; + BinStr* Bound() { return bound; }; +private: + BinStr* bound; + LPCUTF8 name; + TyParList* next; + DWORD attrs; +}; + +typedef TyParList* pTyParList; + +#endif + diff --git a/src/coreclr/ilasm/writer.cpp b/src/coreclr/ilasm/writer.cpp new file mode 100644 index 00000000000..0bff54b603d --- /dev/null +++ b/src/coreclr/ilasm/writer.cpp @@ -0,0 +1,1663 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// writer.cpp +// + +#include "ilasmpch.h" + +#include "assembler.h" + +#include "ceefilegenwriter.h" + +#ifndef _MSC_VER +//cloned definition from ntimage.h that is removed for non MSVC builds +typedef VOID +(NTAPI *PIMAGE_TLS_CALLBACK) ( + PVOID DllHandle, + ULONG Reason, + PVOID Reserved + ); +#endif //_MSC_VER + + +HRESULT Assembler::InitMetaData() +{ + HRESULT hr = E_FAIL; + + if(m_fInitialisedMetaData) return S_OK; + + if(bClock) bClock->cMDInitBegin = GetTickCount(); + + hr = MetaDataGetDispenser(CLSID_CorMetaDataDispenser, + IID_IMetaDataDispenserEx2, (void **)&m_pDisp); + if (FAILED(hr)) + goto exit; + + if(m_wzMetadataVersion) + { + VARIANT encOption; + BSTR bstr; + V_VT(&encOption) = VT_BSTR; + V_BSTR(&encOption) = bstr = ::SysAllocString(m_wzMetadataVersion); + hr = m_pDisp->SetOption(MetaDataRuntimeVersion, &encOption); + ::SysFreeString(bstr); + } + hr = m_pDisp->DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataEmit3, + (IUnknown **)&m_pEmitter); + if (FAILED(hr)) + goto exit; + + m_pManifest->SetEmitter(m_pEmitter); + if(FAILED(hr = m_pEmitter->QueryInterface(IID_IMetaDataImport2, (void**)&m_pImporter))) + goto exit; + + if (m_pdbFormat == PdbFormat::PORTABLE) + { + m_pPortablePdbWriter = new PortablePdbWriter(); + if (FAILED(hr = m_pPortablePdbWriter->Init(m_pDisp))) goto exit; + } + + //m_Parser = new AsmParse(m_pEmitter); + m_fInitialisedMetaData = TRUE; + + hr = S_OK; + +exit: + if(bClock) bClock->cMDInitEnd = GetTickCount(); + return hr; +} +/*********************************************************************************/ +/* if we have any Thread local store data, make the TLS directory record for it */ + +HRESULT Assembler::CreateTLSDirectory() { + + ULONG tlsEnd; + HRESULT hr; + if (FAILED(hr=m_pCeeFileGen->GetSectionDataLen(m_pTLSSection, &tlsEnd))) return(hr); + + if (tlsEnd == 0) // No TLS data, we are done + return(S_OK); + + // place to put the TLS directory + HCEESECTION tlsDirSec = m_pGlobalDataSection; + + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) + { + DWORD sizeofptr = (DWORD)sizeof(DWORD); + DWORD sizeofdir = (DWORD)sizeof(IMAGE_TLS_DIRECTORY32); + DWORD offsetofStartAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, StartAddressOfRawData); + DWORD offsetofEndAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, EndAddressOfRawData); + DWORD offsetofAddressOfIndex = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, AddressOfIndex); + DWORD offsetofAddressOfCallBacks = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, AddressOfCallBacks); + + // Get memory for for the TLS directory block,as well as a spot for callback chain + IMAGE_TLS_DIRECTORY32* tlsDir; + if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(tlsDirSec, sizeofdir + sizeofptr, sizeofptr, (void**) &tlsDir))) return(hr); + DWORD* callBackChain = (DWORD*) &tlsDir[1]; + *callBackChain = 0; + + // Find out where the tls directory will end up + ULONG tlsDirOffset; + if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsDirOffset))) return(hr); + tlsDirOffset -= (sizeofdir + sizeofptr); + + // Set the start of the TLS data (offset 0 of hte TLS section) + tlsDir->StartAddressOfRawData = 0; + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofStartAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr); + + // Set the end of the TLS data + tlsDir->EndAddressOfRawData = VALPTR(tlsEnd); + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofEndAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr); + + // Allocate space for the OS to put the TLS index for this PE file (needs to be Read/Write?) + DWORD* tlsIndex; + if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pGlobalDataSection, sizeof(DWORD), sizeof(DWORD), (void**) &tlsIndex))) return(hr); + *tlsIndex = 0xCCCCCCCC; // Does't really matter, the OS will fill it in + + // Find out where tlsIndex index is + ULONG tlsIndexOffset; + if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsIndexOffset))) return(hr); + tlsIndexOffset -= sizeof(DWORD); + + // Set the address of the TLS index + tlsDir->AddressOfIndex = VALPTR(tlsIndexOffset); + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfIndex, m_pGlobalDataSection, srRelocHighLow))) return(hr); + + // Set addres of callbacks chain + tlsDir->AddressOfCallBacks = VALPTR((DWORD)(DWORD_PTR)(PIMAGE_TLS_CALLBACK*)(size_t)(tlsDirOffset + sizeofdir)); + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfCallBacks, tlsDirSec, srRelocHighLow))) return(hr); + + // Set the other fields. + tlsDir->SizeOfZeroFill = 0; + tlsDir->Characteristics = 0; + + hr=m_pCeeFileGen->SetDirectoryEntry (m_pCeeFile, tlsDirSec, IMAGE_DIRECTORY_ENTRY_TLS, + sizeofdir, tlsDirOffset); + + if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386) + COR_SET_32BIT_REQUIRED(m_dwComImageFlags); + } + else + { + DWORD sizeofptr = (DWORD)sizeof(__int64); + DWORD sizeofdir = (DWORD)sizeof(IMAGE_TLS_DIRECTORY64); + DWORD offsetofStartAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, StartAddressOfRawData); + DWORD offsetofEndAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, EndAddressOfRawData); + DWORD offsetofAddressOfIndex = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, AddressOfIndex); + DWORD offsetofAddressOfCallBacks = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, AddressOfCallBacks); + + // Get memory for for the TLS directory block,as well as a spot for callback chain + IMAGE_TLS_DIRECTORY64* tlsDir; + if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(tlsDirSec, sizeofdir + sizeofptr, sizeofptr, (void**) &tlsDir))) return(hr); + __int64* callBackChain = (__int64*) &tlsDir[1]; + *callBackChain = 0; + + // Find out where the tls directory will end up + ULONG tlsDirOffset; + if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsDirOffset))) return(hr); + tlsDirOffset -= (sizeofdir + sizeofptr); + + // Set the start of the TLS data (offset 0 of hte TLS section) + tlsDir->StartAddressOfRawData = 0; + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofStartAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr); + + // Set the end of the TLS data + tlsDir->EndAddressOfRawData = VALPTR(tlsEnd); + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofEndAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr); + + // Allocate space for the OS to put the TLS index for this PE file (needs to be Read/Write?) + DWORD* tlsIndex; + if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pGlobalDataSection, sizeof(DWORD), sizeof(DWORD), (void**) &tlsIndex))) return(hr); + *tlsIndex = 0xCCCCCCCC; // Does't really matter, the OS will fill it in + + // Find out where tlsIndex index is + ULONG tlsIndexOffset; + if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsIndexOffset))) return(hr); + tlsIndexOffset -= sizeof(DWORD); + + // Set the address of the TLS index + tlsDir->AddressOfIndex = VALPTR(tlsIndexOffset); + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfIndex, m_pGlobalDataSection, srRelocHighLow))) return(hr); + + // Set address of callbacks chain + tlsDir->AddressOfCallBacks = VALPTR((DWORD)(DWORD_PTR)(PIMAGE_TLS_CALLBACK*)(size_t)(tlsDirOffset + sizeofdir)); + if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfCallBacks, tlsDirSec, srRelocHighLow))) return(hr); + + // Set the other fields. + tlsDir->SizeOfZeroFill = 0; + tlsDir->Characteristics = 0; + + hr=m_pCeeFileGen->SetDirectoryEntry (m_pCeeFile, tlsDirSec, IMAGE_DIRECTORY_ENTRY_TLS, + sizeofdir, tlsDirOffset); + } + + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS) + { + report->error("Base relocations are emitted, while /STRIPRELOC option has been specified"); + } + m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY; + + return(hr); +} + +HRESULT Assembler::CreateDebugDirectory() +{ + HRESULT hr = S_OK; + HCEESECTION sec = m_pILSection; + BYTE *de; + ULONG deOffset; + + // Only emit this if we're also emitting debug info. + if (!(m_fGeneratePDB && (m_pSymWriter || IsPortablePdb()))) + return S_OK; + + IMAGE_DEBUG_DIRECTORY debugDirIDD; + struct Param + { + DWORD debugDirDataSize; + BYTE *debugDirData; + } param; + param.debugDirData = NULL; + + if (m_pSymWriter) // CLASSIC + { + // Get the debug info from the symbol writer. + if (FAILED(hr=m_pSymWriter->GetDebugInfo(NULL, 0, ¶m.debugDirDataSize, NULL))) + return hr; + + // Will there even be any? + if (param.debugDirDataSize == 0) + return S_OK; + + // Make some room for the data. + PAL_TRY(Param *, pParam, ¶m) { + pParam->debugDirData = new BYTE[pParam->debugDirDataSize]; + } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + hr = E_FAIL; + } PAL_ENDTRY + + if(FAILED(hr)) return hr; + // Actually get the data now. + if (FAILED(hr = m_pSymWriter->GetDebugInfo(&debugDirIDD, + param.debugDirDataSize, + NULL, + param.debugDirData))) + goto ErrExit; + + // Grab the timestamp of the PE file. + DWORD fileTimeStamp; + + if (FAILED(hr = m_pCeeFileGen->GetFileTimeStamp(m_pCeeFile, + &fileTimeStamp))) + goto ErrExit; + + // Fill in the directory entry. + debugDirIDD.TimeDateStamp = VAL32(fileTimeStamp); + } + else if (IsPortablePdb()) // PORTABLE + { + // get module ID + DWORD rsds = 0x53445352; + DWORD pdbAge = 0x1; + DWORD len = sizeof(rsds) + sizeof(GUID) + sizeof(pdbAge) + (DWORD)strlen(m_szPdbFileName) + 1; + BYTE* dbgDirData = new BYTE[len]; + + DWORD offset = 0; + memcpy_s(dbgDirData + offset, len, &rsds, sizeof(rsds)); // RSDS + offset += sizeof(rsds); + memcpy_s(dbgDirData + offset, len, m_pPortablePdbWriter->GetGuid(), sizeof(GUID)); // PDB GUID + offset += sizeof(GUID); + memcpy_s(dbgDirData + offset, len, &pdbAge, sizeof(pdbAge)); // PDB AGE + offset += sizeof(pdbAge); + memcpy_s(dbgDirData + offset, len, m_szPdbFileName, strlen(m_szPdbFileName) + 1); // PDB PATH + + debugDirIDD.Characteristics = 0; + debugDirIDD.TimeDateStamp = m_pPortablePdbWriter->GetTimestamp(); + debugDirIDD.MajorVersion = 0x100; + debugDirIDD.MinorVersion = 0x504d; + debugDirIDD.Type = IMAGE_DEBUG_TYPE_CODEVIEW; + debugDirIDD.SizeOfData = len; + debugDirIDD.AddressOfRawData = 0; // will be updated bellow + debugDirIDD.PointerToRawData = 0; // will be updated bellow + + param.debugDirDataSize = len; + + // Make some room for the data. + PAL_TRY(Param*, pParam, ¶m) { + pParam->debugDirData = new BYTE[pParam->debugDirDataSize]; + } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + hr = E_FAIL; + } PAL_ENDTRY + + if (FAILED(hr)) return hr; + + param.debugDirData = dbgDirData; + } + + // Grab memory in the section for our stuff. + // Note that UpdateResource doesn't work correctly if the debug directory is + // in the data section. So instead we put it in the text section (same as + // cs compiler). + if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(sec, + sizeof(debugDirIDD) + + param.debugDirDataSize, + 4, + (void**) &de))) + goto ErrExit; + + // Where did we get that memory? + if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(sec, + &deOffset))) + goto ErrExit; + + deOffset -= (sizeof(debugDirIDD) + param.debugDirDataSize); + + // Setup a reloc so that the address of the raw + // data is setup correctly. + debugDirIDD.PointerToRawData = VAL32(deOffset + sizeof(debugDirIDD)); + + if (FAILED(hr = m_pCeeFileGen->AddSectionReloc( + sec, + deOffset + + offsetof(IMAGE_DEBUG_DIRECTORY, + PointerToRawData), + sec, srRelocFilePos))) + goto ErrExit; + + debugDirIDD.AddressOfRawData = VAL32(deOffset + sizeof(debugDirIDD)); + + if (FAILED(hr = m_pCeeFileGen->AddSectionReloc( + sec, + deOffset + + offsetof(IMAGE_DEBUG_DIRECTORY, + AddressOfRawData), + sec, srRelocAbsolute))) + goto ErrExit; + // Emit the directory entry. + if (FAILED(hr = m_pCeeFileGen->SetDirectoryEntry(m_pCeeFile, + sec, + IMAGE_DIRECTORY_ENTRY_DEBUG, + sizeof(debugDirIDD), + deOffset))) + goto ErrExit; + + // Copy the debug directory into the section. + memcpy(de, &debugDirIDD, sizeof(debugDirIDD)); + memcpy(de + sizeof(debugDirIDD), param.debugDirData, + param.debugDirDataSize); + + if (param.debugDirData) + { + delete [] param.debugDirData; + } + return S_OK; + +ErrExit: + if (param.debugDirData) + { + delete [] param.debugDirData; + } + return hr; +} +//#ifdef EXPORT_DIR_ENABLED +HRESULT Assembler::CreateExportDirectory() +{ + HRESULT hr = S_OK; + DWORD Nentries = m_EATList.COUNT(); + if(Nentries == 0) return S_OK; + + IMAGE_EXPORT_DIRECTORY exportDirIDD; + DWORD exportDirDataSize; + BYTE *exportDirData; + EATEntry *pEATE; + unsigned i, L, ordBase = 0xFFFFFFFF, Ldllname; + // get the DLL name from output file name + char* pszDllName; + Ldllname = (unsigned)wcslen(m_wzOutputFileName)*3+3; + char* szOutputFileName = new char[Ldllname]; + memset(szOutputFileName,0,wcslen(m_wzOutputFileName)*3+3); + WszWideCharToMultiByte(CP_ACP,0,m_wzOutputFileName,-1,szOutputFileName,Ldllname,NULL,NULL); + pszDllName = strrchr(szOutputFileName,DIRECTORY_SEPARATOR_CHAR_A); +#ifdef TARGET_WINDOWS + if(pszDllName == NULL) pszDllName = strrchr(szOutputFileName,':'); +#endif + if(pszDllName == NULL) pszDllName = szOutputFileName; + Ldllname = (unsigned)strlen(pszDllName)+1; + + // Allocate buffer for tables + for(i = 0, L=0; i < Nentries; i++) L += 1+(unsigned)strlen(m_EATList.PEEK(i)->szAlias); + exportDirDataSize = Nentries*5*sizeof(WORD) + L + Ldllname; + exportDirData = new BYTE[exportDirDataSize]; + memset(exportDirData,0,exportDirDataSize); + + // Export address table + DWORD* pEAT = (DWORD*)exportDirData; + // Name pointer table + DWORD* pNPT = pEAT + Nentries; + // Ordinal table + WORD* pOT = (WORD*)(pNPT + Nentries); + // Export name table + char* pENT = (char*)(pOT + Nentries); + // DLL name + char* pDLLName = pENT + L; + + // sort the names/ordinals + char** pAlias = new char*[Nentries]; + for(i = 0; i < Nentries; i++) + { + pEATE = m_EATList.PEEK(i); + pOT[i] = (WORD)pEATE->dwOrdinal; + if(pOT[i] < ordBase) ordBase = pOT[i]; + pAlias[i] = pEATE->szAlias; + } + bool swapped = true; + unsigned j; + char* pch; + while(swapped) + { + swapped = false; + for(i=1; i < Nentries; i++) + { + if(strcmp(pAlias[i-1],pAlias[i]) > 0) + { + swapped = true; + pch = pAlias[i-1]; + pAlias[i-1] = pAlias[i]; + pAlias[i] = pch; + j = pOT[i-1]; + pOT[i-1] = pOT[i]; + pOT[i] = j; + } + } + } + // normalize ordinals + for(i = 0; i < Nentries; i++) pOT[i] -= ordBase; + // fill the export address table +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow" +#endif + for(i = 0; i < Nentries; i++) + { + pEATE = m_EATList.PEEK(i); + pEAT[pEATE->dwOrdinal - ordBase] = pEATE->dwStubRVA; + } +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + // fill the export names table + unsigned l; + for(i = 0, j = 0; i < Nentries; i++) + { + pNPT[i] = j; // relative offset in the table + l = (unsigned)strlen(pAlias[i])+1; + memcpy(&pENT[j],pAlias[i],l); + j+=l; + } + _ASSERTE(j==L); + // fill the DLL name + memcpy(pDLLName,pszDllName,Ldllname); + + // Data blob is ready pending Name Pointer Table values offsetting + + memset(&exportDirIDD,0,sizeof(IMAGE_EXPORT_DIRECTORY)); + // Grab the timestamp of the PE file. + DWORD fileTimeStamp; + if (FAILED(hr = m_pCeeFileGen->GetFileTimeStamp(m_pCeeFile,&fileTimeStamp))) return hr; + // Fill in the directory entry. + // Characteristics, MajorVersion and MinorVersion play no role and stay 0 + exportDirIDD.TimeDateStamp = VAL32(fileTimeStamp); + exportDirIDD.Name = VAL32(exportDirDataSize - Ldllname); // to be offset later + exportDirIDD.Base = VAL32(ordBase); + exportDirIDD.NumberOfFunctions = VAL32(Nentries); + exportDirIDD.NumberOfNames = VAL32(Nentries); + exportDirIDD.AddressOfFunctions = 0; // to be offset later + exportDirIDD.AddressOfNames = VAL32(Nentries*sizeof(DWORD)); // to be offset later + exportDirIDD.AddressOfNameOrdinals = VAL32(Nentries*sizeof(DWORD)*2); // to be offset later + + // Grab memory in the section for our stuff. + HCEESECTION sec = m_pGlobalDataSection; + BYTE *de; + if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(sec, + sizeof(IMAGE_EXPORT_DIRECTORY) + exportDirDataSize, + 4, + (void**) &de))) return hr; + // Where did we get that memory? + ULONG deOffset, deDataOffset; + if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(sec, &deDataOffset))) return hr; + + deDataOffset -= exportDirDataSize; + deOffset = deDataOffset - sizeof(IMAGE_EXPORT_DIRECTORY); + + // Add offsets and set up relocs for header entries + exportDirIDD.Name = VAL32(VAL32(exportDirIDD.Name) + deDataOffset); + if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,Name), + sec, srRelocAbsolute))) return hr; + exportDirIDD.AddressOfFunctions = VAL32(VAL32(exportDirIDD.AddressOfFunctions) + deDataOffset); + if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfFunctions), + sec, srRelocAbsolute))) return hr; + exportDirIDD.AddressOfNames = VAL32(VAL32(exportDirIDD.AddressOfNames) + deDataOffset); + if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNames), + sec, srRelocAbsolute))) return hr; + exportDirIDD.AddressOfNameOrdinals = VAL32(VAL32(exportDirIDD.AddressOfNameOrdinals) + deDataOffset); + if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNameOrdinals), + sec, srRelocAbsolute))) return hr; + + // Add offsets and set up relocs for Name Pointer Table + j = deDataOffset + Nentries*5*sizeof(WORD); // EA, NP and O Tables come first + for(i = 0; i < Nentries; i++) + { + pNPT[i] += j; + if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,exportDirIDD.AddressOfNames+i*sizeof(DWORD), + sec, srRelocAbsolute))) return hr; + } + + + // Emit the directory entry. + if (FAILED(hr = m_pCeeFileGen->SetDirectoryEntry(m_pCeeFile, sec, IMAGE_DIRECTORY_ENTRY_EXPORT, + sizeof(IMAGE_EXPORT_DIRECTORY), deOffset))) return hr; + + // Copy the debug directory into the section. + memcpy(de, &exportDirIDD, sizeof(IMAGE_EXPORT_DIRECTORY)); + memcpy(de + sizeof(IMAGE_EXPORT_DIRECTORY), exportDirData, exportDirDataSize); + delete [] pAlias; + delete [] exportDirData; + return S_OK; +} + +static const BYTE ExportStubAMD64Template[] = +{ + // Jump through VTFixup table + 0x48, 0xA1, // rex.w rex.b mov rax,[following address] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//address of VTFixup slot + 0xFF, 0xE0 // jmp [rax] +}; +static const BYTE ExportStubX86Template[] = +{ + // Jump through VTFixup table + 0xFF, 0x25, // jmp [following address] + 0x00, 0x00, 0x00, 0x00 //address of VTFixup slot +}; +static const WORD ExportStubARMTemplate[] = +{ + // Jump through VTFixup table + 0xf8df, 0xf000, // ldr pc, [pc, #0] + 0x0000, 0x0000 //address of VTFixup slot +}; + +DWORD Assembler::EmitExportStub(DWORD dwVTFSlotRVA) +{ + DWORD EXPORT_STUB_SIZE = (DWORD)(sizeof(WORD)+sizeof(DWORD)); + DWORD OFFSET_OF_ADDR = (DWORD)sizeof(WORD); + DWORD STUB_ALIGNMENT = 16; + BYTE* STUB_TEMPLATE = NULL; + DWORD PEFileOffset; + BYTE* outBuff; + DWORD* pdwVTFSlotRVA; + + if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_AMD64) + { + STUB_TEMPLATE = (BYTE*)&ExportStubAMD64Template[0]; + EXPORT_STUB_SIZE = sizeof(ExportStubAMD64Template); + OFFSET_OF_ADDR = 2; + STUB_ALIGNMENT = 4; + } + else if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386) + { + STUB_TEMPLATE = (BYTE*)&ExportStubX86Template[0]; + EXPORT_STUB_SIZE = sizeof(ExportStubX86Template); + OFFSET_OF_ADDR = 2; + } + else if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM) + { + STUB_TEMPLATE = (BYTE*)&ExportStubARMTemplate[0]; + EXPORT_STUB_SIZE = sizeof(ExportStubARMTemplate); + OFFSET_OF_ADDR = 4; + STUB_ALIGNMENT = 4; + } + else + { + report->error("Unmanaged exports are not implemented for unknown platform"); + return NULL; + } + // Addr must be aligned, not the stub! + if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) return 0; + if((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1)) + { + ULONG L = STUB_ALIGNMENT - ((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1)); + if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, L, 1, (void **) &outBuff))) return 0; + memset(outBuff,0,L); + } + + if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, EXPORT_STUB_SIZE, 1, (void **) &outBuff))) return 0; + memcpy(outBuff,STUB_TEMPLATE,EXPORT_STUB_SIZE); + pdwVTFSlotRVA = (DWORD*)(&outBuff[OFFSET_OF_ADDR]); + *pdwVTFSlotRVA = VAL32(dwVTFSlotRVA); + + // The offset where we start, (not where the alignment bytes start!) + if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) return 0; + + PEFileOffset -= EXPORT_STUB_SIZE; + _ASSERTE(((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1))==0); + m_pCeeFileGen->AddSectionReloc(m_pILSection, PEFileOffset+OFFSET_OF_ADDR,m_pGlobalDataSection, srRelocHighLow); + + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS) + { + report->error("Base relocations are emitted, while /STRIPRELOC option has been specified"); + } + m_pCeeFileGen->GetMethodRVA(m_pCeeFile, PEFileOffset,&PEFileOffset); + return PEFileOffset; +} +//#endif + +HRESULT Assembler::GetCAName(mdToken tkCA, __out LPWSTR *ppszName) +{ + HRESULT hr = S_OK; + DWORD cchName; + LPWSTR name; + + *ppszName = NULL; + + if (TypeFromToken(tkCA) == mdtMemberRef) + { + mdToken parent; + if (FAILED(hr = m_pImporter->GetMemberRefProps( tkCA, &parent, NULL, 0, NULL, NULL, NULL))) + return hr; + tkCA = parent; + } + else if (TypeFromToken(tkCA) == mdtMethodDef) + { + mdToken parent; + if (FAILED(hr = m_pImporter->GetMemberProps( tkCA, &parent, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))) + return hr; + tkCA = parent; + } + + if (TypeFromToken(tkCA) == mdtTypeRef) + { + // A TypeRef + if (FAILED(hr = m_pImporter->GetTypeRefProps(tkCA, NULL, NULL, 0, &cchName))) + return hr; + if ((name = new WCHAR[cchName + 1]) == NULL) + return E_OUTOFMEMORY; + hr = m_pImporter->GetTypeRefProps(tkCA, NULL, name, cchName, &cchName); + } + else + { + hr = m_pImporter->GetTypeDefProps(tkCA, NULL, 0, &cchName, NULL, NULL); + if (hr != S_OK) + return hr; + if ((name = new WCHAR[cchName + 1]) == NULL) + return E_OUTOFMEMORY; + hr = m_pImporter->GetTypeDefProps(tkCA, name, cchName, &cchName, NULL, NULL); + } + if (SUCCEEDED(hr)) + *ppszName = name; + else + delete [] name; + return hr; +} + +BYTE HexToByte (CHAR wc) +{ + if (!iswxdigit(wc)) return (BYTE) 0xff; + if (iswdigit(wc)) return (BYTE) (wc - L'0'); + if (iswupper(wc)) return (BYTE) (wc - L'A' + 10); + return (BYTE) (wc - L'a' + 10); +} + + +BOOL Assembler::EmitFieldsMethods(Class* pClass) +{ + unsigned n; + BOOL ret = TRUE; + // emit all field definition metadata tokens + if((n = pClass->m_FieldDList.COUNT())) + { + FieldDescriptor* pFD; + if(m_fReportProgress) printf("Fields: %d;\t",n); + for(int j=0; (pFD = pClass->m_FieldDList.PEEK(j)); j++) // can't use POP here: we'll need field list for props + { + if(!EmitField(pFD)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pFD->m_fNew = FALSE; + } + } + // Fields are emitted; emit the class layout + { + COR_FIELD_OFFSET *pOffsets = NULL; + ULONG ul = pClass->m_ulPack; + ULONG N = pClass->m_dwNumFieldsWithOffset; + + EmitSecurityInfo(pClass->m_cl, + pClass->m_pPermissions, + pClass->m_pPermissionSets); + pClass->m_pPermissions = NULL; + pClass->m_pPermissionSets = NULL; + if((pClass->m_ulSize != 0xFFFFFFFF)||(ul != 0)||(N != 0)) + { + if(IsTdAutoLayout(pClass->m_Attr)) report->warn("Layout specified for auto-layout class\n"); + if((ul > 128)||((ul & (ul-1)) !=0 )) + report->error("Invalid packing parameter (%d), must be 1,2,4,8...128\n",pClass->m_ulPack); + if(N) + { + pOffsets = new COR_FIELD_OFFSET[N+1]; + ULONG i,j=0; + FieldDescriptor *pFD; + for(i=0; (pFD = pClass->m_FieldDList.PEEK(i)); i++) + { + if(pFD->m_ulOffset != 0xFFFFFFFF) + { + pOffsets[j].ridOfField = RidFromToken(pFD->m_fdFieldTok); + pOffsets[j].ulOffset = pFD->m_ulOffset; + j++; + } + } + _ASSERTE(j == N); + pOffsets[j].ridOfField = mdFieldDefNil; + } + m_pEmitter->SetClassLayout ( + pClass->m_cl, // [IN] typedef + ul, // [IN] packing size specified as 1, 2, 4, 8, or 16 + pOffsets, // [IN] array of layout specification + pClass->m_ulSize); // [IN] size of the class + if(pOffsets) delete [] pOffsets; + } + } + // emit all method definition metadata tokens + if((n = pClass->m_MethodList.COUNT())) + { + Method* pMethod; + + if(m_fReportProgress) printf("Methods: %d;\t",n); + for(int i=0; (pMethod = pClass->m_MethodList.PEEK(i));i++) + { + if(!EmitMethod(pMethod)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pMethod->m_fNew = FALSE; + } + } + if(m_fReportProgress) printf("\n"); + return ret; +} + +HRESULT Assembler::ResolveLocalMemberRefs() +{ + unsigned ulTotal=0, ulDefs=0, ulRefs=0, ulUnres=0; + MemberRefDList* pList[2] = {&m_LocalMethodRefDList,&m_LocalFieldRefDList}; + + if(pList[0]->COUNT() + pList[1]->COUNT()) + { + MemberRefDescriptor* pMRD; + mdToken tkMemberDef = 0; + int i,j,k; + Class *pSearch; + + if(m_fReportProgress) printf("Resolving local member refs: "); + for(k=0; k<2; k++) + { + for(i=0; (pMRD = pList[k]->PEEK(i)) != NULL; i++) + { + if(pMRD->m_tkResolved) continue; + + tkMemberDef = 0; + Method* pListMD; + char* pMRD_szName = pMRD->m_szName; + DWORD pMRD_dwName = pMRD->m_dwName; + ULONG pMRD_dwCSig = (pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->length() : 0); + PCOR_SIGNATURE pMRD_pSig = (PCOR_SIGNATURE)(pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->ptr() : NULL); + CQuickBytes qbSig; + + ulTotal++; + + pSearch = NULL; + if(pMRD->m_tdClass == mdTokenNil) + pSearch = m_lstClass.PEEK(0); + else if((TypeFromToken(pMRD->m_tdClass) != mdtTypeDef) + ||((pSearch = m_lstClass.PEEK(RidFromToken(pMRD->m_tdClass)-1)) == NULL)) + { + report->msg("Error: bad parent 0x%08X of local member ref '%s'\n", + pMRD->m_tdClass,pMRD->m_szName); + } + if(pSearch) + { + // MemberRef may reference a method or a field + if(k==0) //methods + { + if((*pMRD_pSig & IMAGE_CEE_CS_CALLCONV_MASK)==IMAGE_CEE_CS_CALLCONV_VARARG) + { + ULONG L; + qbSig.Shrink(0); + _GetFixedSigOfVarArg(pMRD_pSig,pMRD_dwCSig,&qbSig,&L); + pMRD_pSig = (PCOR_SIGNATURE)(qbSig.Ptr()); + pMRD_dwCSig = L; + } + for(j=0; (pListMD = pSearch->m_MethodList.PEEK(j)) != NULL; j++) + { + if(pListMD->m_dwName != pMRD_dwName) continue; + if(strcmp(pListMD->m_szName,pMRD_szName)) continue; + if(pListMD->m_dwMethodCSig != pMRD_dwCSig) continue; + if(memcmp(pListMD->m_pMethodSig,pMRD_pSig,pMRD_dwCSig)) continue; + tkMemberDef = pListMD->m_Tok; + ulDefs++; + break; + } + if(tkMemberDef && ((*pMRD_pSig & IMAGE_CEE_CS_CALLCONV_MASK)==IMAGE_CEE_CS_CALLCONV_VARARG)) + { + WszMultiByteToWideChar(g_uCodePage,0,pMRD_szName,-1,wzUniBuf,dwUniBuf); + + if(IsMdPrivateScope(pListMD->m_Attr)) + { + WCHAR* p = wcsstr(wzUniBuf,W("$PST06")); + if(p) *p = 0; + } + + m_pEmitter->DefineMemberRef(tkMemberDef, wzUniBuf, + pMRD->m_pSigBinStr->ptr(), + pMRD->m_pSigBinStr->length(), + &tkMemberDef); + ulDefs--; + ulRefs++; + } + } + else // fields + { + FieldDescriptor* pListFD; + for(j=0; (pListFD = pSearch->m_FieldDList.PEEK(j)) != NULL; j++) + { + if(pListFD->m_dwName != pMRD_dwName) continue; + if(strcmp(pListFD->m_szName,pMRD_szName)) continue; + if(pListFD->m_pbsSig) + { + if(pListFD->m_pbsSig->length() != pMRD_dwCSig) continue; + if(memcmp(pListFD->m_pbsSig->ptr(),pMRD_pSig,pMRD_dwCSig)) continue; + } + else if(pMRD_dwCSig) continue; + tkMemberDef = pListFD->m_fdFieldTok; + ulDefs++; + break; + } + } + } + if(tkMemberDef==0) + { // could not resolve ref to def, make new ref and leave it this way + if((pSearch = pMRD->m_pClass) != NULL) + { + mdToken tkRef = MakeTypeRef(1,pSearch->m_szFQN); + + if(RidFromToken(tkRef)) + { + WszMultiByteToWideChar(g_uCodePage,0,pMRD_szName,-1,wzUniBuf,dwUniBuf); + + m_pEmitter->DefineMemberRef(tkRef, wzUniBuf, pMRD_pSig, + pMRD_dwCSig, &tkMemberDef); + ulRefs++; + } + else + { + report->msg("Error: unresolved member ref '%s' of class 0x%08X\n",pMRD->m_szName,pMRD->m_tdClass); + ulUnres++; + } + } + else + { + report->msg("Error: unresolved global member ref '%s'\n",pMRD->m_szName); + ulUnres++; + } + } + pMRD->m_tkResolved = tkMemberDef; + } + } + for(i=0; (pMRD = m_MethodSpecList.PEEK(i)) != NULL; i++) + { + if(pMRD->m_tkResolved) continue; + tkMemberDef = pMRD->m_tdClass; + if(TypeFromToken(tkMemberDef)==0x99000000) + { + tkMemberDef = m_LocalMethodRefDList.PEEK(RidFromToken(tkMemberDef)-1)->m_tkResolved; + if((TypeFromToken(tkMemberDef)==mdtMethodDef)||(TypeFromToken(tkMemberDef)==mdtMemberRef)) + { + ULONG pMRD_dwCSig = (pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->length() : 0); + PCOR_SIGNATURE pMRD_pSig = (PCOR_SIGNATURE)(pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->ptr() : NULL); + HRESULT hr = m_pEmitter->DefineMethodSpec(tkMemberDef, pMRD_pSig, pMRD_dwCSig, &(pMRD->m_tkResolved)); + if(FAILED(hr)) + report->error("Unable to define method instantiation"); + } + } + if(RidFromToken(pMRD->m_tkResolved)) ulDefs++; + else ulUnres++; + } + if(m_fReportProgress) printf("%d -> %d defs, %d refs, %d unresolved\n",ulTotal,ulDefs,ulRefs,ulUnres); + } + return (ulUnres ? E_FAIL : S_OK); +} + +HRESULT Assembler::DoLocalMemberRefFixups() +{ + MemberRefDList* pList; + unsigned Nlmr = m_LocalMethodRefDList.COUNT() + m_LocalFieldRefDList.COUNT(), + Nlmrf = m_LocalMemberRefFixupList.COUNT(); + HRESULT hr = S_OK; + if(Nlmr) + { + MemberRefDescriptor* pMRD; + LocalMemberRefFixup* pMRF; + int i; + for(i = 0; (pMRF = m_LocalMemberRefFixupList.PEEK(i)) != NULL; i++) + { + if(m_fENCMode && (!pMRF->m_fNew)) continue; + + switch(TypeFromToken(pMRF->tk)) + { + case 0x99000000: pList = &m_LocalMethodRefDList; break; + case 0x98000000: pList = &m_LocalFieldRefDList; break; + case 0x9A000000: pList = &m_MethodSpecList; break; + default: pList = NULL; break; + } + if(pList) + { + if((pMRD = pList->PEEK(RidFromToken(pMRF->tk)-1)) != NULL) + SET_UNALIGNED_VAL32((void *)(pMRF->offset), pMRD->m_tkResolved); + else + { + report->msg("Error: bad local member ref token 0x%08X in LMR fixup\n",pMRF->tk); + hr = E_FAIL; + } + } + pMRF->m_fNew = FALSE; + } + } + else if(Nlmrf) + { + report->msg("Error: %d local member ref fixups, no local member refs\n",Nlmrf); + hr = E_FAIL; + } + return hr; +} +void Assembler::EmitUnresolvedCustomAttributes() +{ + CustomDescr *pCD; + while((pCD = m_CustomDescrList.POP()) != NULL) + { + pCD->tkType = ResolveLocalMemberRef(pCD->tkType); + pCD->tkOwner = ResolveLocalMemberRef(pCD->tkOwner); + // Look for the class'es interfaceimpl if this CA is one of those + if (pCD->tkInterfacePair) + pCD->tkOwner = GetInterfaceImpl(pCD->tkOwner, pCD->tkInterfacePair); + DefineCV(new CustomDescr(pCD->tkOwner,pCD->tkType,pCD->pBlob)); + } +} + +BOOL Assembler::EmitEventsProps(Class* pClass) +{ + unsigned n; + BOOL ret = TRUE; + // emit all event definition metadata tokens + if((n = pClass->m_EventDList.COUNT())) + { + if(m_fReportProgress) printf("Events: %d;\t",n); + EventDescriptor* pED; + for(int j=0; (pED = pClass->m_EventDList.PEEK(j)); j++) // can't use POP here: we'll need event list for props + { + if(!EmitEvent(pED)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pED->m_fNew = FALSE; + } + } + // emit all property definition metadata tokens + if((n = pClass->m_PropDList.COUNT())) + { + if(m_fReportProgress) printf("Props: %d;\t",n); + PropDescriptor* pPD; + + for(int j=0; (pPD = pClass->m_PropDList.PEEK(j)); j++) + { + if(!EmitProp(pPD)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pPD->m_fNew = FALSE; + } + } + if(m_fReportProgress) printf("\n"); + return ret; +} + +HRESULT Assembler::AllocateStrongNameSignature() +{ + HRESULT hr = S_OK; + HCEESECTION hSection; + DWORD dwDataLength; + DWORD dwDataOffset; + DWORD dwDataRVA; + VOID *pvBuffer; + AsmManStrongName *pSN = &m_pManifest->m_sStrongName; + + // pSN->m_cbPublicKey is the length of the m_pbPublicKey + dwDataLength = ((int)pSN->m_cbPublicKey < 128 + 32) ? 128 : (int)pSN->m_cbPublicKey - 32; + + // Grab memory in the section for our stuff. + if (FAILED(hr = m_pCeeFileGen->GetIlSection(m_pCeeFile, + &hSection))) + { + return hr; + } + + if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(hSection, + dwDataLength, + 4, + &pvBuffer))) + { + return hr; + } + + // Where did we get that memory? + if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(hSection, + &dwDataOffset))) + { + return hr; + } + + dwDataOffset -= dwDataLength; + + // Convert to an RVA. + if (FAILED(hr = m_pCeeFileGen->GetMethodRVA(m_pCeeFile, + dwDataOffset, + &dwDataRVA))) + { + return hr; + } + + // Emit the directory entry. + if (FAILED(hr = m_pCeeFileGen->SetStrongNameEntry(m_pCeeFile, + dwDataLength, + dwDataRVA))) + { + return hr; + } + + return S_OK; +} + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:21000) // Suppress PREFast warning about overly large function +#endif +HRESULT Assembler::CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename) +{ + HRESULT hr; + DWORD mresourceSize = 0; + BYTE* mresourceData = NULL; + WCHAR* wzScopeName = NULL; + + if(bClock) bClock->cMDEmitBegin = GetTickCount(); + if(m_fReportProgress) printf("Creating PE file\n"); + if (!m_pEmitter) + { + printf("Error: Cannot create a PE file with no metadata\n"); + return E_FAIL; + } + if(!(m_fDLL || m_fEntryPointPresent)) + { + printf("Error: No entry point declared for executable\n"); + if(!OnErrGo) return E_FAIL; + } + + if(bClock) bClock->cMDEmit1 = GetTickCount(); + + // Allocate space for a strong name signature if we're delay or full + // signing the assembly. + if (m_pManifest->m_sStrongName.m_pbPublicKey) + { + if (FAILED(hr = AllocateStrongNameSignature())) + { + goto exit; + } + } + + if(bClock) bClock->cMDEmit2 = GetTickCount(); + + if(m_VTFList.COUNT()==0) + { + Method* pMD; + Class* pClass; + unsigned N=0, OrdBase=0xFFFFFFFF, i, j; + for(i=0; (pClass = m_lstClass.PEEK(i)) != NULL; i++) + { + for(j = 0; (pMD = pClass->m_MethodList.PEEK(j)) != NULL; j++) + { + if(pMD->m_dwExportOrdinal != 0xFFFFFFFF) + { + N++; + if(pMD->m_dwExportOrdinal < OrdBase) OrdBase = pMD->m_dwExportOrdinal; + } + } + } + if(N) + { + for(i=0; (pClass = m_lstClass.PEEK(i)) != NULL; i++) + { + for(j = 0; (pMD = pClass->m_MethodList.PEEK(j)) != NULL; j++) + { + if(pMD->m_wVTSlot >= 0x8000) + { + pMD->m_wVTSlot -= 0x8000 + OrdBase - 1; + } + } + } + SetDataSection(); + char* sz = new char[20]; + strcpy_s(sz,20,"VTF_EAT_internal"); + EmitDataLabel(sz); + sz = new char[20]; + strcpy_s(sz,20,"VTF_EAT_internal"); + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64) + { + ULONGLONG *pdw = new ULONGLONG[N]; + for(i=0; i<N; i++) pdw[i] = UI64(0xdeadbeefdeadbeef); + EmitData(pdw,sizeof(ULONGLONG)*N); + m_VTFList.PUSH(new VTFEntry((USHORT)N,COR_VTABLE_64BIT|COR_VTABLE_FROM_UNMANAGED,sz)); + delete [] pdw; + } + else + { + unsigned *pdw = new unsigned[N]; + for(i=0; i<N; i++) pdw[i] = 0xdeadbeef; + EmitData(pdw,sizeof(unsigned)*N); + m_VTFList.PUSH(new VTFEntry((USHORT)N,COR_VTABLE_32BIT|COR_VTABLE_FROM_UNMANAGED,sz)); + delete [] pdw; + } + } + } + wzScopeName=&wzUniBuf[0]; + if(m_szScopeName[0]) // default: scope name = output file name + { + WszMultiByteToWideChar(g_uCodePage,0,m_szScopeName,-1,wzScopeName,MAX_SCOPE_LENGTH); + } + else + { + WCHAR* pwc; + if ((pwc = wcsrchr(m_wzOutputFileName, DIRECTORY_SEPARATOR_CHAR_A)) != NULL) pwc++; +#ifdef TARGET_WINDOWS + else if ((pwc = wcsrchr(m_wzOutputFileName, ':')) != NULL) pwc++; +#endif + else pwc = m_wzOutputFileName; + + wcsncpy_s(wzScopeName, MAX_SCOPE_LENGTH, pwc, _TRUNCATE); + } + hr = m_pEmitter->SetModuleProps(wzScopeName); + + if (FAILED(hr)) + goto exit; + + EmitImports(); + if(m_pManifest) + { + hr = S_OK; + if(m_pManifest->m_pAsmEmitter==NULL) + hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &(m_pManifest->m_pAsmEmitter)); + + if(SUCCEEDED(hr)) + { + m_pManifest->EmitAssemblyRefs(); + } + } + // Emit classes, class members and globals: + { + Class *pSearch; + int i; + BOOL bIsUndefClass = FALSE; + if(m_fReportProgress) printf("\nEmitting classes:\n"); + for (i=1; (pSearch = m_lstClass.PEEK(i)); i++) // 0 is <Module> + { + if(m_fReportProgress) + printf("Class %d:\t%s\n",i,pSearch->m_szFQN); + + if(pSearch->m_bIsMaster) + { + report->msg("Error: Reference to undefined class '%s'\n",pSearch->m_szFQN); + bIsUndefClass = TRUE; + } + if(!EmitClass(pSearch)) + { + if(!OnErrGo) return E_FAIL; + } + pSearch->m_fNew = FALSE; + } + if(bIsUndefClass && !OnErrGo) return E_FAIL; + + if(m_fReportProgress) printf("\nEmitting fields and methods:\n"); + for (i=0; (pSearch = m_lstClass.PEEK(i)) != NULL; i++) + { + if(m_fReportProgress) + { + if(i == 0) printf("Global \t"); + else printf("Class %d\t",i); + } + if(!EmitFieldsMethods(pSearch)) + { + if(!OnErrGo) return E_FAIL; + } + } + } + + // All ref'ed items def'ed in this file are emitted, resolve member refs to member defs: + if(bClock) bClock->cRef2DefBegin = GetTickCount(); + hr = ResolveLocalMemberRefs(); + if(bClock) bClock->cRef2DefEnd = GetTickCount(); + if(FAILED(hr) &&(!OnErrGo)) goto exit; + + // Local member refs resolved, emit events, props and method impls + { + Class *pSearch; + int i; + + if(m_fReportProgress) printf("\nEmitting events and properties:\n"); + for (i=0; (pSearch = m_lstClass.PEEK(i)); i++) + { + if(m_fReportProgress) + { + if(i == 0) printf("Global \t"); + else printf("Class %d\t",i); + } + if(!EmitEventsProps(pSearch)) + { + if(!OnErrGo) return E_FAIL; + } + pSearch->m_fNewMembers = FALSE; + } + } + if(bClock) bClock->cMDEmit3 = GetTickCount(); + if(m_MethodImplDList.COUNT()) + { + if(m_fReportProgress) report->msg("Method Implementations (total): %d\n",m_MethodImplDList.COUNT()); + if(!EmitMethodImpls()) + { + if(!OnErrGo) return E_FAIL; + } + } + // Emit the rest of the metadata + if(bClock) bClock->cMDEmit4 = GetTickCount(); + hr = S_OK; + if(m_pManifest) + { + if (FAILED(hr = m_pManifest->EmitManifest())) goto exit; + } + ResolveLocalMemberRefs(); // in case CAs added some + EmitUnresolvedCustomAttributes(); + // Emit typedefs as special TypeSpecs + { +#define ELEMENT_TYPE_TYPEDEF (ELEMENT_TYPE_MAX+1) + TypeDefDescr* pTDD; + unsigned __int8* pb; + unsigned namesize; + while((pTDD = m_TypeDefDList.POP())) + { + BinStr* pbs = new BinStr(); + if(pbs) + { + namesize = 1 + (unsigned)strlen(pTDD->m_szName); + pb = pbs->getBuff(namesize + 1 + sizeof(mdToken)); + *pb = ELEMENT_TYPE_TYPEDEF; + memcpy(++pb,pTDD->m_szName,namesize); + pTDD->m_tkTypeSpec = ResolveLocalMemberRef(pTDD->m_tkTypeSpec); + memcpy(pb+namesize,&(pTDD->m_tkTypeSpec),sizeof(mdToken)); + if(TypeFromToken(pTDD->m_tkTypeSpec)==mdtCustomAttribute) + { + CustomDescr* pCA = pTDD->m_pCA; + pbs->appendInt32(pCA->tkType); + pbs->appendInt32(pCA->tkOwner); + if(pCA->pBlob) pbs->append(pCA->pBlob); + } + ResolveTypeSpec(pbs); + delete pbs; + } + delete pTDD; + } + } + if(bClock) bClock->cMDEmitEnd = GetTickCount(); + + hr = DoLocalMemberRefFixups(); + if(FAILED(hr) &&(!OnErrGo)) goto exit; + // Local member refs resolved and fixed up in BinStr method bodies. Emit the bodies. + { + Class* pClass; + Method* pMethod; + for (int i=0; (pClass = m_lstClass.PEEK(i)); i++) + { + for(int j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++) + { + if(!EmitMethodBody(pMethod,NULL)) + { + report->msg("Error: failed to emit body of '%s'\n",pMethod->m_szName); + hr = E_FAIL; + if(!OnErrGo) goto exit; + } + pMethod->m_fNewBody = FALSE; + } + } + //while(MethodBody* pMB = m_MethodBodyList.POP()) delete pMB; + } + + if (DoGlobalFixups() == FALSE) + return E_FAIL; + + if(m_wzResourceFile) + { +#ifdef TARGET_UNIX + report->msg("Warning: The Win32 resource file '%S' is ignored and not emitted on xPlatform.\n", m_wzResourceFile); +#else + if (FAILED(hr=m_pCeeFileGen->SetResourceFileName(m_pCeeFile, m_wzResourceFile))) + { + report->msg("Warning: failed to set Win32 resource file name '%S', hr=0x%8.8X\n The Win32 resource is not emitted.\n", + m_wzResourceFile, hr); + } +#endif + } + + if (FAILED(hr=CreateTLSDirectory())) goto exit; + + if (FAILED(hr=CreateDebugDirectory())) goto exit; + + if (FAILED(hr=m_pCeeFileGen->SetOutputFileName(m_pCeeFile, pwzOutputFilename))) goto exit; + + // Reserve a buffer for the meta-data + DWORD metaDataSize; + if (FAILED(hr=m_pEmitter->GetSaveSize(cssAccurate, &metaDataSize))) goto exit; + BYTE* metaData; + if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, metaDataSize, sizeof(DWORD), (void**) &metaData))) goto exit; + ULONG metaDataOffset; + if (FAILED(hr=m_pCeeFileGen->GetSectionDataLen(m_pILSection, &metaDataOffset))) goto exit; + metaDataOffset -= metaDataSize; + // set managed resource entry, if any + if(m_pManifest && m_pManifest->m_dwMResSizeTotal) + { + mresourceSize = m_pManifest->m_dwMResSizeTotal; + + if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, mresourceSize, + sizeof(DWORD), (void**) &mresourceData))) goto exit; + if (FAILED(hr=m_pCeeFileGen->SetManifestEntry(m_pCeeFile, mresourceSize, 0))) goto exit; + } + if(m_VTFList.COUNT()) + { + GlobalLabel *pGlobalLabel; + VTFEntry* pVTFEntry; + + if(m_pVTable) delete m_pVTable; // can't have both; list takes precedence + m_pVTable = new BinStr(); + hr = S_OK; + for(WORD k=0; (pVTFEntry = m_VTFList.POP()); k++) + { + if((pGlobalLabel = FindGlobalLabel(pVTFEntry->m_szLabel))) + { + Method* pMD; + Class* pClass; + m_pVTable->appendInt32(pGlobalLabel->m_GlobalOffset); + m_pVTable->appendInt16(pVTFEntry->m_wCount); + m_pVTable->appendInt16(pVTFEntry->m_wType); + for(int i=0; (pClass = m_lstClass.PEEK(i)); i++) + { + for(WORD j = 0; (pMD = pClass->m_MethodList.PEEK(j)); j++) + { + if(pMD->m_wVTEntry == k+1) + { + char* ptr; + if(SUCCEEDED(hr = m_pCeeFileGen->ComputeSectionPointer(m_pGlobalDataSection,pGlobalLabel->m_GlobalOffset,&ptr))) + { + DWORD dwDelta; + if((pVTFEntry->m_wType & COR_VTABLE_32BIT)) + { + dwDelta = (pMD->m_wVTSlot-1)*(DWORD)sizeof(DWORD); + ptr += dwDelta; + DWORD* mptr = (DWORD*)ptr; + *mptr = (DWORD)(pMD->m_Tok); + } + else + { + dwDelta = (pMD->m_wVTSlot-1)*(DWORD)sizeof(ULONGLONG); + ptr += dwDelta; + ULONGLONG* mptr = (ULONGLONG*)ptr; + *mptr = (ULONGLONG)(pMD->m_Tok); + } + if(pMD->m_dwExportOrdinal != 0xFFFFFFFF) + { + EATEntry* pEATE = new EATEntry; + pEATE->dwOrdinal = pMD->m_dwExportOrdinal; + pEATE->szAlias = pMD->m_szExportAlias ? pMD->m_szExportAlias : pMD->m_szName; + pEATE->dwStubRVA = EmitExportStub(pGlobalLabel->m_GlobalOffset+dwDelta); + m_EATList.PUSH(pEATE); + } + } + else + report->msg("Error: Failed to get pointer to label '%s' inVTable fixup\n",pVTFEntry->m_szLabel); + } + } + } + } + else + { + report->msg("Error: Unresolved label '%s' in VTable fixup\n",pVTFEntry->m_szLabel); + hr = E_FAIL; + } + delete pVTFEntry; + } + if(FAILED(hr)) goto exit; + } + if(m_pVTable) + { + ULONG i, N = m_pVTable->length()/sizeof(DWORD); + ULONG ulVTableOffset; + m_pCeeFileGen->GetSectionDataLen (m_pILSection, &ulVTableOffset); + // SetVTableEntry will align VTable on DWORD + ulVTableOffset = (ulVTableOffset + (ULONG)sizeof(DWORD) - 1) & ~((ULONG)sizeof(DWORD) - 1); + if (FAILED(hr=m_pCeeFileGen->SetVTableEntry64(m_pCeeFile, m_pVTable->length(),(void*)(m_pVTable->ptr())))) goto exit; // @WARNING: casting down from pointer-size to DWORD + for(i = 0; i < N; i+=2) + { + m_pCeeFileGen->AddSectionReloc(m_pILSection, + ulVTableOffset+(i*sizeof(DWORD)), + m_pGlobalDataSection, + srRelocAbsolute); + } + } + if(m_EATList.COUNT()) + { + if(FAILED(CreateExportDirectory())) goto exit; + m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY; + if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386) + COR_SET_32BIT_REQUIRED(m_dwComImageFlags); + } + if (m_fWindowsCE) + { + if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, 2, 10))) goto exit; + + if (FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, 0x10000))) goto exit; + } + else + { + if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM || m_fAppContainer) + { + // For AppContainer and ARM, you must have a minimum subsystem version of 6.02 + m_wSSVersionMajor = (m_wSSVersionMajor < 6) ? 6 : m_wSSVersionMajor; + m_wSSVersionMinor = (m_wSSVersionMinor < 2 && m_wSSVersionMajor <= 6) ? 2 : m_wSSVersionMinor; + + } + + // Default the subsystem, instead the user doesn't set it to GUI or CUI + if (m_dwSubsystem == (DWORD)-1) + // The default for ILAsm previously was CUI, so that should be the default behavior... + m_dwSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; + + if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, m_dwSubsystem, m_wSSVersionMajor, m_wSSVersionMinor))) goto exit; + } + + if (FAILED(hr=m_pCeeFileGen->ClearComImageFlags(m_pCeeFile, COMIMAGE_FLAGS_ILONLY))) goto exit; + if (FAILED(hr=m_pCeeFileGen->SetComImageFlags(m_pCeeFile, m_dwComImageFlags & ~COMIMAGE_FLAGS_STRONGNAMESIGNED))) goto exit; + + if(m_dwFileAlignment) + { + if(FAILED(hr=m_pCeeFileGen->SetFileAlignment(m_pCeeFile, m_dwFileAlignment))) goto exit; + } + if(m_stBaseAddress) + { + + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64) + { + if(FAILED(hr=m_pCeeFileGen->SetImageBase64(m_pCeeFile, m_stBaseAddress))) goto exit; + } + else + { + if(FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, (size_t)m_stBaseAddress))) goto exit; + } + } + if(m_stSizeOfStackReserve || m_fAppContainer || m_fHighEntropyVA) + { + PIMAGE_NT_HEADERS pNT; + PIMAGE_SECTION_HEADER pSect; + ULONG ulNumSect; + if(FAILED(hr=m_pCeeFileGen->GetHeaderInfo(m_pCeeFile,&pNT,&pSect,&ulNumSect))) goto exit; + if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64) + { + PIMAGE_OPTIONAL_HEADER64 pOpt = (PIMAGE_OPTIONAL_HEADER64)(&pNT->OptionalHeader); + if (m_stSizeOfStackReserve) + pOpt->SizeOfStackReserve = VAL64(m_stSizeOfStackReserve); + if (m_fAppContainer) + pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_APPCONTAINER; + if (m_fHighEntropyVA) + pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA; + } + else + { + PIMAGE_OPTIONAL_HEADER32 pOpt = (PIMAGE_OPTIONAL_HEADER32)(&pNT->OptionalHeader); + if (m_stSizeOfStackReserve) + pOpt->SizeOfStackReserve = (DWORD)VAL32(m_stSizeOfStackReserve); + if (m_fAppContainer) + pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_APPCONTAINER; + if (m_fHighEntropyVA) + pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA; + } + } + //Compute all the RVAs + if (FAILED(hr=m_pCeeFileGen->LinkCeeFile(m_pCeeFile))) goto exit; + + // Fix up any fields that have RVA associated with them + if (m_fHaveFieldsWithRvas) { + hr = S_OK; + ULONG dataSectionRVA; + if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pGlobalDataSection, &dataSectionRVA))) goto exit; + + ULONG tlsSectionRVA; + if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pTLSSection, &tlsSectionRVA))) goto exit; + + ULONG ilSectionRVA; + if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pILSection, &ilSectionRVA))) goto exit; + + FieldDescriptor* pListFD; + Class* pClass; + for(int i=0; (pClass = m_lstClass.PEEK(i)); i++) + { + for(int j=0; (pListFD = pClass->m_FieldDList.PEEK(j)); j++) + { + if (pListFD->m_rvaLabel != 0) + { + DWORD rva; + if(*(pListFD->m_rvaLabel)=='@') + { + rva = (DWORD)atoi(pListFD->m_rvaLabel + 1); + } + else + { + GlobalLabel *pLabel = FindGlobalLabel(pListFD->m_rvaLabel); + if (pLabel == 0) + { + report->msg("Error:Could not find label '%s' for the field '%s'\n", pListFD->m_rvaLabel, pListFD->m_szName); + hr = E_FAIL; + continue; + } + + rva = pLabel->m_GlobalOffset; + if (pLabel->m_Section == m_pTLSSection) + rva += tlsSectionRVA; + else if (pLabel->m_Section == m_pILSection) + rva += ilSectionRVA; + else { + _ASSERTE(pLabel->m_Section == m_pGlobalDataSection); + rva += dataSectionRVA; + } + } + if (FAILED(m_pEmitter->SetFieldRVA(pListFD->m_fdFieldTok, rva))) goto exit; + } + } + } + if (FAILED(hr)) goto exit; + } + + if(bClock) bClock->cFilegenBegin = GetTickCount(); + // actually output the meta-data + if (FAILED(hr=m_pCeeFileGen->EmitMetaDataAt(m_pCeeFile, m_pEmitter, m_pILSection, metaDataOffset, metaData, metaDataSize))) goto exit; + + if((m_wMSVmajor < 0xFF)&&(m_wMSVminor < 0xFF)) + { + STORAGESIGNATURE *pSSig = (STORAGESIGNATURE *)metaData; + BYTE* pb = metaData; + pb += 3*sizeof(DWORD)+2*sizeof(WORD)+VAL32(pSSig->iVersionString); + pb = (BYTE*)(((size_t)pb + 3) & ~3); + PSTORAGEHEADER pSHdr = (PSTORAGEHEADER)pb; + PSTORAGESTREAM pStr = (PSTORAGESTREAM)(pSHdr+1); + for(short iStr = 1; iStr <= VAL16(pSHdr->iStreams); iStr++) + { + if((strcmp(pStr->rcName,"#-")==0)||(strcmp(pStr->rcName,"#~")==0)) + { + pb = metaData + VAL32(pStr->iOffset); // start of the stream header + pb += sizeof(DWORD); // skip Reserved + *pb = VAL16(m_wMSVmajor)&0xFF; + *(pb+1) = VAL16(m_wMSVminor)&0xFF; + break; + } + pb = (BYTE*)pStr; + pb += 2*sizeof(DWORD)+strlen(pStr->rcName)+1; + pb = (BYTE*)(((size_t)pb + 3) & ~3); + pStr = (PSTORAGESTREAM)pb; + } + } + + if(m_fTolerateDupMethods) // means that there are /ENC files + { + if(m_pbsMD) delete m_pbsMD; + m_pbsMD = new BinStr(); + memcpy(m_pbsMD->getBuff(metaDataSize),metaData,metaDataSize); + } + // actually output the resources + if(mresourceSize && mresourceData) + { + size_t i, N = m_pManifest->m_dwMResNum, sizeread, L; + BYTE *ptr = (BYTE*)mresourceData; + BOOL mrfail = FALSE; + FILE* pFile = NULL; + char sz[2048]; + for(i=0; i < N; i++) + { + m_pManifest->m_fMResNew[i] = FALSE; + memset(sz,0,2048); + WszWideCharToMultiByte(CP_ACP,0,m_pManifest->m_wzMResName[i],-1,sz,2047,NULL,NULL); + L = m_pManifest->m_dwMResSize[i]; + sizeread = 0; + memcpy(ptr,&L,sizeof(DWORD)); + ptr += sizeof(DWORD); + if(fopen_s(&pFile,sz,"rb") == 0) + { + sizeread = fread((void *)ptr,1,L,pFile); + fclose(pFile); + ptr += sizeread; + } + else + { + report->msg("Error: failed to open mgd resource file '%ls'\n",m_pManifest->m_wzMResName[i]); + mrfail = TRUE; + } + if(sizeread < L) + { + report->msg("Error: failed to read expected %d bytes from mgd resource file '%ls'\n",L,m_pManifest->m_wzMResName[i]); + mrfail = TRUE; + L -= sizeread; + memset(ptr,0,L); + ptr += L; + } + } + if(mrfail) + { + hr = E_FAIL; + goto exit; + } + } + /* + if((m_wRTVmajor < 0xFFFF)&&(m_wRTVminor < 0xFFFF)) + { + IMAGE_COR20_HEADER* pCorH; + if(FAILED(hr=m_pCeeFileGen->GetCorHeader(m_pCeeFile,&pCorH))) goto exit; + pCorH->MajorRuntimeVersion = VAL16(m_wRTVmajor); + pCorH->MinorRuntimeVersion = VAL16(m_wRTVminor); + } + */ + // Generate the file -- moved to main + //if (FAILED(hr=m_pCeeFileGen->GenerateCeeFile(m_pCeeFile))) goto exit; + + + hr = S_OK; + +exit: + return hr; +} +#ifdef _PREFAST_ +#pragma warning(pop) +#endif diff --git a/src/coreclr/ilasm/writer_enc.cpp b/src/coreclr/ilasm/writer_enc.cpp new file mode 100644 index 00000000000..96a637b4dec --- /dev/null +++ b/src/coreclr/ilasm/writer_enc.cpp @@ -0,0 +1,608 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// writer_ENC.cpp +// + +// +#include "ilasmpch.h" + +#include "assembler.h" + +int ist=0; +#define REPT_STEP //printf("Step %d\n",++ist); + +HRESULT Assembler::InitMetaDataForENC(__in __nullterminated WCHAR* wzOrigFileName, BOOL generatePdb, PdbFormat pdbFormat) +{ + HRESULT hr = E_FAIL; + + if((wzOrigFileName==NULL)||(*wzOrigFileName == 0)||(m_pDisp==NULL)) return hr; + if (m_pSymWriter != NULL) + { + m_pSymWriter->Close(); + m_pSymWriter->Release(); + m_pSymWriter = NULL; + } + if (m_pImporter != NULL) + { + m_pImporter->Release(); + m_pImporter = NULL; + } + if (m_pEmitter != NULL) + { + m_pEmitter->Release(); + m_pEmitter = NULL; + } + if (m_pPortablePdbWriter != NULL) + { + delete m_pPortablePdbWriter; + m_pPortablePdbWriter = NULL; + } + //WszSetEnvironmentVariable(L"COMP_ENC_OPENSCOPE", wzOrigFileName); + //hr = m_pDisp->DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataEmit2, + // (IUnknown **)&m_pEmitter); + + if((m_pbsMD==NULL)||(m_pbsMD->length()==0)) + { + _ASSERTE(!"NO BASE METADATA!"); + return E_FAIL; + } + + VARIANT encOption; + V_VT(&encOption) = VT_UI4; + V_UI4(&encOption) = MDUpdateENC; + m_pDisp->SetOption(MetaDataSetENC, &encOption); + V_UI4(&encOption) = MDErrorOutOfOrderDefault; + m_pDisp->SetOption(MetaDataErrorIfEmitOutOfOrder, &encOption); + hr = m_pDisp->OpenScopeOnMemory( m_pbsMD->ptr(), + m_pbsMD->length(), + ofWrite, + IID_IMetaDataEmit2, + (IUnknown **)&m_pEmitter); + _ASSERTE(SUCCEEDED(hr)); + if (FAILED(hr)) + goto exit; + + m_pManifest->SetEmitter(m_pEmitter); + if(FAILED(hr = m_pEmitter->QueryInterface(IID_IMetaDataImport2, (void**)&m_pImporter))) + goto exit; + + //WszSetEnvironmentVariable(L"COMP_ENC_EMIT", wzOrigFileName); + if(!Init(generatePdb, pdbFormat)) goto exit; // close and re-open CeeFileGen and CeeFile + hr = S_OK; + + +exit: + return hr; +} +/*********************************************************************************/ + +BOOL Assembler::EmitFieldsMethodsENC(Class* pClass) +{ + unsigned n; + BOOL ret = TRUE; + // emit all field definition metadata tokens + if((pClass->m_FieldDList.COUNT())) + { + FieldDescriptor* pFD; + int j; + for(j=0, n=0; (pFD = pClass->m_FieldDList.PEEK(j)); j++) // can't use POP here: we'll need field list for props + { + if(pFD->m_fNew) + { + if(!EmitField(pFD)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pFD->m_fNew = FALSE; + n++; + } + } + if(m_fReportProgress) printf("Fields: %d;\t",n); + } + // Fields are emitted; emit the class layout + { + COR_FIELD_OFFSET *pOffsets = NULL; + ULONG ul = pClass->m_ulPack; + ULONG N = pClass->m_dwNumFieldsWithOffset; + + EmitSecurityInfo(pClass->m_cl, + pClass->m_pPermissions, + pClass->m_pPermissionSets); + pClass->m_pPermissions = NULL; + pClass->m_pPermissionSets = NULL; + if((pClass->m_ulSize != 0xFFFFFFFF)||(ul != 0)||(N != 0)) + { + if(IsTdAutoLayout(pClass->m_Attr)) report->warn("Layout specified for auto-layout class\n"); + if((ul > 128)||((ul & (ul-1)) !=0 )) + report->error("Invalid packing parameter (%d), must be 1,2,4,8...128\n",pClass->m_ulPack); + if(N) + { + pOffsets = new COR_FIELD_OFFSET[N+1]; + ULONG i,j=0; + FieldDescriptor *pFD; + for(i=0; (pFD = pClass->m_FieldDList.PEEK(i)); i++) + { + if(pFD->m_ulOffset != 0xFFFFFFFF) + { + pOffsets[j].ridOfField = RidFromToken(pFD->m_fdFieldTok); + pOffsets[j].ulOffset = pFD->m_ulOffset; + j++; + } + } + _ASSERTE(j == N); + pOffsets[j].ridOfField = mdFieldDefNil; + } + m_pEmitter->SetClassLayout ( + pClass->m_cl, // [IN] typedef + ul, // [IN] packing size specified as 1, 2, 4, 8, or 16 + pOffsets, // [IN] array of layout specification + pClass->m_ulSize); // [IN] size of the class + if(pOffsets) delete [] pOffsets; + } + } + // emit all method definition metadata tokens + if((pClass->m_MethodList.COUNT())) + { + Method* pMethod; + int i; + + for(i=0, n=0; (pMethod = pClass->m_MethodList.PEEK(i));i++) + { + if(pMethod->m_fNew) + { + if(!EmitMethod(pMethod)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pMethod->m_fNew = FALSE; + n++; + } + } + if(m_fReportProgress) printf("Methods: %d;\t",n); + } + if(m_fReportProgress) printf("\n"); + return ret; +} + +BOOL Assembler::EmitEventsPropsENC(Class* pClass) +{ + unsigned n; + BOOL ret = TRUE; + // emit all event definition metadata tokens + if((pClass->m_EventDList.COUNT())) + { + EventDescriptor* pED; + int j; + for(j=0,n=0; (pED = pClass->m_EventDList.PEEK(j)); j++) // can't use POP here: we'll need event list for props + { + if(pED->m_fNew) + { + if(!EmitEvent(pED)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pED->m_fNew = FALSE; + n++; + } + } + if(m_fReportProgress) printf("Events: %d;\t",n); + } + // emit all property definition metadata tokens + if((pClass->m_PropDList.COUNT())) + { + PropDescriptor* pPD; + int j; + + for(j=0,n=0; (pPD = pClass->m_PropDList.PEEK(j)); j++) + { + if(pPD->m_fNew) + { + if(!EmitProp(pPD)) + { + if(!OnErrGo) return FALSE; + ret = FALSE; + } + pPD->m_fNew = FALSE; + n++; + } + } + if(m_fReportProgress) printf("Props: %d;\t",n); + } + if(m_fReportProgress) printf("\n"); + return ret; +} + +HRESULT Assembler::CreateDeltaFiles(__in __nullterminated WCHAR *pwzOutputFilename) +{ + HRESULT hr; + DWORD mresourceSize = 0; + BYTE* mresourceData = NULL; + WCHAR* pEnd = NULL; + + if(m_fReportProgress) printf("Creating DMETA,DIL files\n"); + if (!m_pEmitter) + { + printf("Error: Cannot create a PE file with no metadata\n"); + return E_FAIL; + } +REPT_STEP + if(m_pManifest) + { + hr = S_OK; + if(m_pManifest->m_pAsmEmitter==NULL) + hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &(m_pManifest->m_pAsmEmitter)); + + if(SUCCEEDED(hr)) + { + m_pManifest->EmitAssemblyRefs(); + } + } + // Emit classes, class members and globals: + { + Class *pSearch; + int i; + BOOL bIsUndefClass = FALSE; + if(m_fReportProgress) printf("\nEmitting classes:\n"); + for (i=1; (pSearch = m_lstClass.PEEK(i)); i++) // 0 is <Module> + { + if(pSearch->m_fNew) + { + if(m_fReportProgress) + printf("Class %d:\t%s\n",i,pSearch->m_szFQN); + + if(pSearch->m_bIsMaster) + { + report->msg("Error: Reference to undefined class '%s'\n",pSearch->m_szFQN); + bIsUndefClass = TRUE; + } + if(!EmitClass(pSearch)) + { + if(!OnErrGo) return E_FAIL; + } + pSearch->m_fNew = FALSE; + } + } + if(bIsUndefClass && !OnErrGo) return E_FAIL; + + if(m_fReportProgress) printf("\nEmitting fields and methods:\n"); + for (i=0; (pSearch = m_lstClass.PEEK(i)) != NULL; i++) + { + if(pSearch->m_fNewMembers) + { + if(m_fReportProgress) + { + if(i == 0) printf("Global \t"); + else printf("Class %d\t",i); + } + if(!EmitFieldsMethodsENC(pSearch)) + { + if(!OnErrGo) return E_FAIL; + } + } + } + } +REPT_STEP + + // All ref'ed items def'ed in this file are emitted, resolve member refs to member defs: + hr = ResolveLocalMemberRefs(); + if(FAILED(hr) &&(!OnErrGo)) goto exit; + + // Local member refs resolved, emit events, props and method impls + { + Class *pSearch; + int i; + + if(m_fReportProgress) printf("\nEmitting events and properties:\n"); + for (i=0; (pSearch = m_lstClass.PEEK(i)); i++) + { + if(pSearch->m_fNewMembers) + { + if(m_fReportProgress) + { + if(i == 0) printf("Global \t"); + else printf("Class %d\t",i); + } + if(!EmitEventsPropsENC(pSearch)) + { + if(!OnErrGo) return E_FAIL; + } + pSearch->m_fNewMembers = FALSE; + } + } + } + if(m_MethodImplDList.COUNT()) + { + if(m_fReportProgress) report->msg("Method Implementations (total): %d\n",m_MethodImplDList.COUNT()); + if(!EmitMethodImpls()) + { + if(!OnErrGo) return E_FAIL; + } + } +REPT_STEP + // Emit the rest of the metadata + hr = S_OK; + if(m_pManifest) + { + if (FAILED(hr = m_pManifest->EmitManifest())) goto exit; + } + ResolveLocalMemberRefs(); // in case CAs added some + EmitUnresolvedCustomAttributes(); +REPT_STEP + + hr = DoLocalMemberRefFixups(); + if(FAILED(hr) &&(!OnErrGo)) goto exit; + + // Local member refs resolved and fixed up in BinStr method bodies. Emit the bodies to a separate file. + pEnd = &pwzOutputFilename[wcslen(pwzOutputFilename)]; + { + Class* pClass; + Method* pMethod; + FILE* pF = NULL; + wcscat_s(pwzOutputFilename,MAX_SCOPE_LENGTH,W(".dil")); + if(_wfopen_s(&pF,pwzOutputFilename,W("wb"))==0) + { + int i,j,L=0,M=0; + BinStr bsOut; + for (i=0; (pClass = m_lstClass.PEEK(i)); i++) + { + for(j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++) + { + if(pMethod->m_fNewBody) + { + L+= pMethod->m_pbsBody->length()+3; + M++; + } + } + } + bsOut.getBuff(L+sizeof(DWORD)); // to avoid reallocs + bsOut.remove(L); + for (i=0; (pClass = m_lstClass.PEEK(i)); i++) + { + for(j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++) + { + if(pMethod->m_fNewBody) + { + if(!EmitMethodBody(pMethod,&bsOut)) + { + report->msg("Error: failed to emit body of '%s'\n",pMethod->m_szName); + hr = E_FAIL; + if(!OnErrGo) + { + fclose(pF); + *pEnd = 0; + goto exit; + } + } + pMethod->m_fNewBody = FALSE; + } + } + } + *((DWORD*)(bsOut.ptr())) = bsOut.length() - sizeof(DWORD); + fwrite(bsOut.ptr(),bsOut.length(),1,pF); + fclose(pF); + } + else + report->msg("Error: failed to open file '%S'\n",pwzOutputFilename); + + *pEnd = 0; + } +REPT_STEP + + //if (DoGlobalFixups() == FALSE) + // return E_FAIL; + + //if (FAILED(hr=m_pCeeFileGen->SetOutputFileName(m_pCeeFile, pwzOutputFilename))) goto exit; + + // Emit the meta-data to a separate file + IMetaDataEmit2* pENCEmitter; + if(FAILED(hr = m_pEmitter->QueryInterface(IID_IMetaDataEmit2, (void**)&pENCEmitter))) + goto exit; + + DWORD metaDataSize; + if (FAILED(hr=pENCEmitter->GetDeltaSaveSize(cssAccurate, &metaDataSize))) goto exit; + + wcscat_s(pwzOutputFilename,MAX_SCOPE_LENGTH,W(".dmeta")); + pENCEmitter->SaveDelta(pwzOutputFilename,0); // second arg (dwFlags) is not used + *pEnd = 0; + pENCEmitter->Release(); + + // apply delta to create basis for the next ENC iteration + if(m_pbsMD) + { + IMetaDataEmit2* pBaseMDEmit = NULL; + if(FAILED(hr = m_pDisp->OpenScopeOnMemory(m_pbsMD->ptr(), + m_pbsMD->length(), + ofWrite, + IID_IMetaDataEmit2, + (IUnknown **)&pBaseMDEmit))) goto exit; + + if(FAILED(hr = pBaseMDEmit->ApplyEditAndContinue((IUnknown*)m_pImporter))) goto exit; + delete m_pbsMD; + if((m_pbsMD = new BinStr()) != NULL) + { + DWORD cb; + hr = pBaseMDEmit->GetSaveSize(cssAccurate,&cb); + BYTE* pb = m_pbsMD->getBuff(cb); + hr = pBaseMDEmit->SaveToMemory(pb,cb); + } + pBaseMDEmit->Release(); + } + + + // release all interfaces + if (m_pSymWriter != NULL) + { + m_pSymWriter->Close(); + m_pSymWriter->Release(); + m_pSymWriter = NULL; + } + if (m_pImporter != NULL) + { + m_pImporter->Release(); + m_pImporter = NULL; + } + if (m_pEmitter != NULL) + { + m_pEmitter->Release(); + m_pEmitter = NULL; + } + if (m_pPortablePdbWriter != NULL) + { + delete m_pPortablePdbWriter; + m_pPortablePdbWriter = NULL; + } + + return S_OK; + +REPT_STEP + + // set managed resource entry, if any + if(m_pManifest && m_pManifest->m_dwMResSizeTotal) + { + mresourceSize = m_pManifest->m_dwMResSizeTotal; + + if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, mresourceSize, + sizeof(DWORD), (void**) &mresourceData))) goto exit; + if (FAILED(hr=m_pCeeFileGen->SetManifestEntry(m_pCeeFile, mresourceSize, 0))) goto exit; + } +REPT_STEP + /* + if (m_fWindowsCE) + { + if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, 2, 10))) goto exit; + + if (FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, 0x10000))) goto exit; + } + else if(m_dwSubsystem != (DWORD)-1) + { + if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, m_dwSubsystem, 4, 0))) goto exit; + } + + if (FAILED(hr=m_pCeeFileGen->ClearComImageFlags(m_pCeeFile, COMIMAGE_FLAGS_ILONLY))) goto exit; + if (FAILED(hr=m_pCeeFileGen->SetComImageFlags(m_pCeeFile, m_dwComImageFlags & ~COMIMAGE_FLAGS_STRONGNAMESIGNED))) goto exit; + + if(m_dwFileAlignment) + { + if(FAILED(hr=m_pCeeFileGen->SetFileAlignment(m_pCeeFile, m_dwFileAlignment))) goto exit; + } + if(m_stBaseAddress) + { + if(FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, m_stBaseAddress))) goto exit; + } + */ +REPT_STEP + //Compute all the RVAs + if (FAILED(hr=m_pCeeFileGen->LinkCeeFile(m_pCeeFile))) goto exit; + +REPT_STEP + // Fix up any fields that have RVA associated with them +/* + if (m_fHaveFieldsWithRvas) { + hr = S_OK; + ULONG dataSectionRVA; + if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pGlobalDataSection, &dataSectionRVA))) goto exit; + + ULONG tlsSectionRVA; + if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pTLSSection, &tlsSectionRVA))) goto exit; + + FieldDescriptor* pListFD; + Class* pClass; + for(int i=0; (pClass = m_lstClass.PEEK(i)); i++) + { + for(int j=0; (pListFD = pClass->m_FieldDList.PEEK(j)); j++) + { + if (pListFD->m_rvaLabel != 0) + { + DWORD rva; + if(*(pListFD->m_rvaLabel)=='@') + { + rva = (DWORD)atoi(pListFD->m_rvaLabel + 1); + } + else + { + GlobalLabel *pLabel = FindGlobalLabel(pListFD->m_rvaLabel); + if (pLabel == 0) + { + report->msg("Error:Could not find label '%s' for the field '%s'\n", pListFD->m_rvaLabel, pListFD->m_szName); + hr = E_FAIL; + continue; + } + + rva = pLabel->m_GlobalOffset; + if (pLabel->m_Section == m_pTLSSection) + rva += tlsSectionRVA; + else { + _ASSERTE(pLabel->m_Section == m_pGlobalDataSection); + rva += dataSectionRVA; + } + } + if (FAILED(m_pEmitter->SetFieldRVA(pListFD->m_fdFieldTok, rva))) goto exit; + } + } + } + if (FAILED(hr)) goto exit; + } +REPT_STEP +*/ + +REPT_STEP + // actually output the resources + if(mresourceSize && mresourceData) + { + size_t i, N = m_pManifest->m_dwMResNum, sizeread, L; + BYTE *ptr = (BYTE*)mresourceData; + BOOL mrfail = FALSE; + FILE* pFile = NULL; + char sz[2048]; + for(i=0; i < N; i++) + { + if(!m_pManifest->m_fMResNew[i]) continue; + m_pManifest->m_fMResNew[i] = FALSE; + memset(sz,0,2048); + WszWideCharToMultiByte(CP_ACP,0,m_pManifest->m_wzMResName[i],-1,sz,2047,NULL,NULL); + L = m_pManifest->m_dwMResSize[i]; + sizeread = 0; + memcpy(ptr,&L,sizeof(DWORD)); + ptr += sizeof(DWORD); + pFile = NULL; + if(fopen_s(&pFile,sz,"rb")==0) + { + sizeread = fread((void *)ptr,1,L,pFile); + fclose(pFile); + ptr += sizeread; + } + else + { + report->msg("Error: failed to open mgd resource file '%ls'\n",m_pManifest->m_wzMResName[i]); + mrfail = TRUE; + } + if(sizeread < L) + { + report->msg("Error: failed to read expected %d bytes from mgd resource file '%ls'\n",L,m_pManifest->m_wzMResName[i]); + mrfail = TRUE; + L -= sizeread; + memset(ptr,0,L); + ptr += L; + } + } + if(mrfail) + { + hr = E_FAIL; + goto exit; + } + } +REPT_STEP + + // Generate the file -- moved to main + //if (FAILED(hr=m_pCeeFileGen->GenerateCeeFile(m_pCeeFile))) goto exit; + + + hr = S_OK; + +exit: + return hr; +} |