Open sourcing ILASM
authordotnet-bot <dotnet-bot@microsoft.com>
Tue, 8 Dec 2015 17:17:49 +0000 (09:17 -0800)
committerdotnet-bot <dotnet-bot@microsoft.com>
Tue, 8 Dec 2015 17:17:49 +0000 (09:17 -0800)
[tfs-changeset: 1555681]

45 files changed:
src/dlls/mscorpe/.gitmirrorall [new file with mode: 0644]
src/dlls/mscorpe/Native.rc [new file with mode: 0644]
src/dlls/mscorpe/ceefilegenwriter.cpp [new file with mode: 0644]
src/dlls/mscorpe/ceefilegenwritertokens.cpp [new file with mode: 0644]
src/dlls/mscorpe/dirs.proj [new file with mode: 0644]
src/dlls/mscorpe/iceefilegen.cpp [new file with mode: 0644]
src/dlls/mscorpe/mscorpe/mscorpe.def [new file with mode: 0644]
src/dlls/mscorpe/mscorpe/mscorpe.nativeproj [new file with mode: 0644]
src/dlls/mscorpe/mscorpe/wrapper.cpp [new file with mode: 0644]
src/dlls/mscorpe/mscorpehost/mscorpehost.def [new file with mode: 0644]
src/dlls/mscorpe/mscorpehost/mscorpehost.nativeproj [new file with mode: 0644]
src/dlls/mscorpe/pewriter.cpp [new file with mode: 0644]
src/dlls/mscorpe/pewriter.h [new file with mode: 0644]
src/dlls/mscorpe/stdafx.cpp [new file with mode: 0644]
src/dlls/mscorpe/stdafx.h [new file with mode: 0644]
src/dlls/mscorpe/stubs.h [new file with mode: 0644]
src/dlls/mscorpe/utilcodeinit.cpp [new file with mode: 0644]
src/ilasm/.gitmirrorall [new file with mode: 0644]
src/ilasm/Assembler.h [new file with mode: 0644]
src/ilasm/MscorpeSxS.cpp [new file with mode: 0644]
src/ilasm/MscorpeSxS.h [new file with mode: 0644]
src/ilasm/Native.rc [new file with mode: 0644]
src/ilasm/asmenum.h [new file with mode: 0644]
src/ilasm/asmman.cpp [new file with mode: 0644]
src/ilasm/asmman.hpp [new file with mode: 0644]
src/ilasm/asmparse.h [new file with mode: 0644]
src/ilasm/asmparse.y [new file with mode: 0644]
src/ilasm/asmtemplates.h [new file with mode: 0644]
src/ilasm/assem.cpp [new file with mode: 0644]
src/ilasm/assembler.cpp [new file with mode: 0644]
src/ilasm/binstr.h [new file with mode: 0644]
src/ilasm/class.hpp [new file with mode: 0644]
src/ilasm/extractGrammar.pl [new file with mode: 0644]
src/ilasm/grammar_after.cpp [new file with mode: 0644]
src/ilasm/grammar_before.cpp [new file with mode: 0644]
src/ilasm/ilasm.nativeproj [new file with mode: 0644]
src/ilasm/ilasmpch.cpp [new file with mode: 0644]
src/ilasm/ilasmpch.h [new file with mode: 0644]
src/ilasm/main.cpp [new file with mode: 0644]
src/ilasm/method.cpp [new file with mode: 0644]
src/ilasm/method.hpp [new file with mode: 0644]
src/ilasm/nvpair.h [new file with mode: 0644]
src/ilasm/typar.hpp [new file with mode: 0644]
src/ilasm/writer.cpp [new file with mode: 0644]
src/ilasm/writer_enc.cpp [new file with mode: 0644]

diff --git a/src/dlls/mscorpe/.gitmirrorall b/src/dlls/mscorpe/.gitmirrorall
new file mode 100644 (file)
index 0000000..9ee5c57
--- /dev/null
@@ -0,0 +1 @@
+This folder will be mirrored by the Git-TFS Mirror recursively.
\ No newline at end of file
diff --git a/src/dlls/mscorpe/Native.rc b/src/dlls/mscorpe/Native.rc
new file mode 100644 (file)
index 0000000..1711906
--- /dev/null
@@ -0,0 +1,9 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#define FX_VER_FILEDESCRIPTION_STR "Microsoft .NET Runtime PE File Generator\0"
+
+#include <fxver.h>
+#include <fxver.rc>
diff --git a/src/dlls/mscorpe/ceefilegenwriter.cpp b/src/dlls/mscorpe/ceefilegenwriter.cpp
new file mode 100644 (file)
index 0000000..867512d
--- /dev/null
@@ -0,0 +1,2022 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+// Derived class from CCeeGen which handles writing out
+// the exe. All references to PEWriter pulled out of CCeeGen,
+// and moved here
+//
+//
+
+#include "stdafx.h"
+
+#include <string.h>
+#include <limits.h>
+
+#include "corerror.h"
+#include "stubs.h"
+#include <posterror.h>
+#include <shlwapi.h>
+
+// Globals.
+HINSTANCE       g_hThisInst;            // This library.
+
+
+#ifdef EMIT_FIXUPS
+
+// Emitted PEFIXUP structure looks like this
+struct PEFIXUP
+{
+   WORD  wType;
+   WORD  wSpare;
+   DWORD rva;
+   DWORD rvaTarget;
+};
+
+// Following structure is used to store the reloc information which
+// will be used at UpdateFixups time to get the final data from the section
+// bytes to update the fixup information.
+//
+struct DBG_FIXUP
+{
+   WORD  wType;
+   WORD  wSpare;
+
+   union
+   {
+      DWORD rva;
+      unsigned offset;
+   };
+
+   union
+   {
+      DWORD rvaTarget;
+      CeeSection * sectionSource;
+   };
+};
+
+enum
+{
+   IMAGE_REL_I386_DIR24NB          = 0x0081,   // 24-bit base relative
+   IMAGE_REL_I386_FILEPOS          = 0x0082,   // 32-bit file relative
+                                               // all other relocation types are
+                                               // in winnt.h, for some reason
+                                               // this one is missing
+   IMAGE_REL_I386_DIR30NB          = 0x0083,   // 30-bit base relative
+};
+
+#endif // EMIT_FIXUPS
+
+// Get the Symbol entry given the head and a 0-based index
+inline IMAGE_SYMBOL* GetSymbolEntry(IMAGE_SYMBOL* pHead, SIZE_T idx)
+{
+    return (IMAGE_SYMBOL*) (((BYTE*) pHead) + IMAGE_SIZEOF_SYMBOL * idx);
+}
+
+#ifdef EnC_SUPPORTED
+#define ENC_DELTA_HACK
+#endif
+
+#ifdef ENC_DELTA_HACK
+    BOOL g_EnCMode = FALSE;
+#endif
+
+//*****************************************************************************
+// To get a new instance, call CreateNewInstance() or CreateNewInstanceEx() instead of new
+//*****************************************************************************
+
+HRESULT CeeFileGenWriter::CreateNewInstance(CCeeGen *pCeeFileGenFrom,
+                                            CeeFileGenWriter* & pGenWriter,
+                                            DWORD createFlags)
+{
+    return CreateNewInstanceEx(pCeeFileGenFrom, pGenWriter, createFlags);
+}
+
+//
+// Seed file is used as the base file. The new file data will be "appended" to the seed file
+//
+
+HRESULT CeeFileGenWriter::CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom,
+                                              CeeFileGenWriter* & pGenWriter,
+                                              DWORD createFlags,
+                                              LPCWSTR seedFileName)
+{
+    HRESULT hr = S_OK;
+    ULONG preallocatedOffset = 0;
+    NewHolder<PEWriter> pPEWriter(NULL);
+    NewHolder<CeeFileGenWriter> pPrivateGenWriter;
+    CeeSection *corHeaderSection = NULL;
+
+    pPrivateGenWriter = new (nothrow) CeeFileGenWriter;
+    if (pPrivateGenWriter == NULL)
+        IfFailGo(E_OUTOFMEMORY);
+
+    pPEWriter = new (nothrow) PEWriter;
+    if (pPEWriter == NULL)
+        IfFailGo(E_OUTOFMEMORY);
+
+    //workaround
+    //What's really the correct thing to be doing here?
+    //HRESULT hr = pPEWriter->Init(pCeeFileGenFrom ? pCeeFileGenFrom->getPESectionMan() : NULL);
+    hr = pPEWriter->Init(NULL, createFlags, seedFileName);
+    IfFailGo(hr);
+
+    //Create the general PEWriter.
+    pPrivateGenWriter->m_peSectionMan = pPEWriter;
+    hr = pPrivateGenWriter->Init(); // base class member to finish init
+    IfFailGo(hr);
+
+    if (!seedFileName) // Use base file's preferred base (if present)
+    {
+        if (pPEWriter->isPE32())
+        {
+            pPrivateGenWriter->setImageBase((DWORD) CEE_IMAGE_BASE_32);   // use same default as linker
+        }
+        else
+        {
+            pPrivateGenWriter->setImageBase64((ULONGLONG) CEE_IMAGE_BASE_64); // use same default as linker
+        }
+    }
+
+    pPrivateGenWriter->setSubsystem(IMAGE_SUBSYSTEM_WINDOWS_CUI, CEE_IMAGE_SUBSYSTEM_MAJOR_VERSION, CEE_IMAGE_SUBSYSTEM_MINOR_VERSION);
+
+    if (pPEWriter->createCorMainStub())
+    {
+        hr = pPrivateGenWriter->allocateIAT(); // so the IAT goes out first
+        IfFailGo(hr);
+    }
+
+    hr = pPrivateGenWriter->allocateCorHeader();   // get COR header near front
+    IfFailGo(hr);
+
+#if 0 // Need to add this if we want to propagate the old COM+ header
+    if (seedFileName)
+    {
+        memcpy(m_corHeader, baseFileDecoder->ntHeaders32()->corHeader, sizeof(IMAGE_COR20_HEADER));
+    }
+#endif
+
+    //If we were passed a CCeeGen at the beginning, copy it's data now.
+    if (pCeeFileGenFrom) {
+        pCeeFileGenFrom->cloneInstance((CCeeGen*)pPrivateGenWriter);
+    }
+   
+    hr = pPrivateGenWriter->getSectionCreate(".text0", sdExecute, &corHeaderSection);
+    IfFailGo(hr);
+    preallocatedOffset = corHeaderSection->dataLen();
+    
+
+    // set il RVA to be after the preallocated sections
+    pPEWriter->setIlRva(preallocatedOffset);
+
+#ifdef EMIT_FIXUPS
+    if (createFlags & ICEE_CREATE_FILE_EMIT_FIXUPS)
+    {
+        pPrivateGenWriter->setEmitFixups();
+    }
+#endif
+
+    pPEWriter.SuppressRelease();
+    pPrivateGenWriter.SuppressRelease();
+    pGenWriter = pPrivateGenWriter;
+
+ErrExit:
+    return hr;
+} // HRESULT CeeFileGenWriter::CreateNewInstance()
+
+CeeFileGenWriter::CeeFileGenWriter() // ctor is protected
+{
+    m_outputFileName = NULL;
+    m_resourceFileName = NULL;
+    m_dllSwitch = false;
+    m_objSwitch = false;
+    m_libraryName = NULL;
+    m_libraryGuid = GUID_NULL;
+
+    m_entryPoint = 0;
+    m_comImageFlags = COMIMAGE_FLAGS_ILONLY;    // ceegen PEs don't have native code
+    m_iatOffset = 0;
+    m_dllCount = 0;
+
+    m_dwMacroDefinitionSize = 0;
+    m_dwMacroDefinitionRVA = NULL;
+
+    m_dwManifestSize = 0;
+    m_dwManifestRVA = NULL;
+
+    m_dwStrongNameSize = 0;
+    m_dwStrongNameRVA = NULL;
+
+    m_dwVTableSize = 0;
+    m_dwVTableRVA = NULL;
+
+    m_iDataDlls = NULL;
+
+    m_linked = false;
+    m_fixed = false;
+
+#ifdef EMIT_FIXUPS
+
+    m_fEmitFixups = false;
+    m_fFixupsUpdated = false;
+    m_sectionFixups = NULL;
+    m_pDebugDir = NULL;
+
+#endif
+
+#ifdef ENC_DELTA_HACK
+    // for EnC we want the RVA to be right at the front of the IL stream
+    WCHAR szFileName[256];
+    DWORD len = WszGetEnvironmentVariable(L"COMP_ENC_EMIT", szFileName, NumItems(szFileName));
+    if (len > 0)
+        g_EnCMode = TRUE;
+#endif
+
+} // CeeFileGenWriter::CeeFileGenWriter()
+
+//*****************************************************************************
+// Cleanup
+//*****************************************************************************
+HRESULT CeeFileGenWriter::Cleanup() // virtual
+{
+    ((PEWriter *)m_peSectionMan)->Cleanup();  // call derived cleanup
+    delete m_peSectionMan;
+    m_peSectionMan = NULL; // so base class won't delete
+
+    delete[] m_outputFileName;
+    delete[] m_resourceFileName;
+
+    if (m_iDataDlls) {
+        for (int i=0; i < m_dllCount; i++) {
+            if (m_iDataDlls[i].m_methodName)
+                delete[] m_iDataDlls[i].m_methodName;
+        }
+        delete[] m_iDataDlls;
+    }
+
+    return CCeeGen::Cleanup();
+} // HRESULT CeeFileGenWriter::Cleanup()
+
+HRESULT CeeFileGenWriter::EmitMacroDefinitions(void *pData, DWORD cData)
+{
+    // OBSOLETE
+    m_dwMacroDefinitionSize = 0;
+
+    return S_OK;
+} // HRESULT CeeFileGenWriter::EmitMacroDefinitions()
+
+HRESULT CeeFileGenWriter::link()
+{
+    HRESULT hr = checkForErrors();
+    if (! SUCCEEDED(hr))
+        return hr;
+
+#ifdef EMIT_FIXUPS
+
+    // The fixups describe each relocation.  Each fixup contains the relocation's
+    // type, source RVA, and target RVA.  Since the reloc target can be filled
+    // in after the relocation creation, the fixup target RVA discovery needs to
+    // be deferred.
+    // At this point all bytes should be filled in, ensuring that the final
+    // target information is available.
+    // UpdateFixups is called at this point to discover the final relocation target info.
+    //
+    hr = UpdateFixups();
+    if (! SUCCEEDED(hr))
+        return hr;
+
+#endif
+
+    // Don't set this if SetManifestEntry was not called - zapper sets the
+    // resource directory explicitly
+    if (m_dwManifestSize != 0)
+    {
+        m_corHeader->Resources.VirtualAddress = VAL32(m_dwManifestRVA);
+        m_corHeader->Resources.Size = VAL32(m_dwManifestSize);
+    }
+
+    if (m_dwStrongNameSize != 0)
+    {
+        m_corHeader->StrongNameSignature.VirtualAddress = VAL32(m_dwStrongNameRVA);
+        m_corHeader->StrongNameSignature.Size = VAL32(m_dwStrongNameSize);
+    }
+
+    if (m_dwVTableSize != 0)
+    {
+        m_corHeader->VTableFixups.VirtualAddress = VAL32(m_dwVTableRVA);
+        m_corHeader->VTableFixups.Size = VAL32(m_dwVTableSize);
+    }
+
+    unsigned characteristicsMask = IMAGE_FILE_EXECUTABLE_IMAGE;
+
+    if (getPEWriter().isPE32())
+        characteristicsMask |= IMAGE_FILE_32BIT_MACHINE;
+    if (!getPEWriter().isPE32())
+        characteristicsMask |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
+
+    getPEWriter().setCharacteristics(characteristicsMask);
+
+    m_corHeader->cb = VAL32(sizeof(IMAGE_COR20_HEADER));
+    m_corHeader->MajorRuntimeVersion = VAL16(COR_VERSION_MAJOR);
+    m_corHeader->MinorRuntimeVersion = VAL16(COR_VERSION_MINOR);
+    if (m_dllSwitch)
+        getPEWriter().setCharacteristics(IMAGE_FILE_DLL);
+    if (m_objSwitch)
+        getPEWriter().clearCharacteristics(IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE);
+    m_corHeader->Flags = VAL32(m_comImageFlags);
+    IMAGE_COR20_HEADER_FIELD(*m_corHeader, EntryPointToken) = VAL32(m_entryPoint);
+    _ASSERTE(TypeFromToken(m_entryPoint) == mdtMethodDef || m_entryPoint == mdTokenNil ||
+             TypeFromToken(m_entryPoint) == mdtFile);
+    setDirectoryEntry(getCorHeaderSection(), IMAGE_DIRECTORY_ENTRY_COMHEADER, sizeof(IMAGE_COR20_HEADER), m_corHeaderOffset);
+
+    if ((m_comImageFlags & COMIMAGE_FLAGS_IL_LIBRARY) == 0
+        && !m_linked && !m_objSwitch)
+    {
+        hr = emitExeMain();
+        if (FAILED(hr))
+            return hr;
+
+        hr = emitResourceSection();
+        if (FAILED(hr))
+            return hr;
+    }
+
+    m_linked = true;
+
+    IfFailRet(getPEWriter().link());
+
+    return S_OK;
+} // HRESULT CeeFileGenWriter::link()
+
+
+HRESULT CeeFileGenWriter::fixup()
+{
+    HRESULT hr;
+
+    m_fixed = true;
+
+    if (!m_linked)
+        IfFailRet(link());
+
+    CeeGenTokenMapper *pMapper = getTokenMapper();
+
+    // Apply token remaps if there are any.
+    if (! m_fTokenMapSupported && pMapper != NULL) {
+        IMetaDataImport *pImport;
+        hr = pMapper->GetMetaData(&pImport);
+        _ASSERTE(SUCCEEDED(hr));
+        hr = MapTokens(pMapper, pImport);
+        pImport->Release();
+
+    }
+
+    // remap the entry point if entry point token has been moved
+    if (pMapper != NULL && !m_objSwitch)
+    {
+        mdToken tk = m_entryPoint;
+        pMapper->HasTokenMoved(tk, tk);
+        IMAGE_COR20_HEADER_FIELD(*m_corHeader, EntryPointToken) = VAL32(tk);
+    }
+
+    IfFailRet(getPEWriter().fixup(pMapper));
+
+    return S_OK;
+} // HRESULT CeeFileGenWriter::fixup()
+
+HRESULT CeeFileGenWriter::generateImage(void **ppImage)
+{
+    HRESULT hr = S_OK;
+    LPWSTR outputFileName = NULL;
+
+    HANDLE hThreadToken = NULL;
+    // Impersonation is only supported on Win2k and above. 
+    if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ | TOKEN_IMPERSONATE, TRUE, &hThreadToken)) 
+    {
+        if (GetLastError() != ERROR_NO_TOKEN) 
+        {
+            _ASSERTE(!"Failed to get thread token!");
+            return HRESULT_FROM_GetLastError();
+        }
+    }
+    
+    if (hThreadToken != NULL) 
+    {
+        if (!RevertToSelf()) 
+        {
+            _ASSERTE(!"Failed to revert impersonation!");
+            CloseHandle(hThreadToken);
+            return HRESULT_FROM_GetLastError();
+        }                
+    }
+
+#ifdef ENC_DELTA_HACK
+    // fixups break because we've set the base RVA to 0 for the delta stream
+    if (! g_EnCMode)
+#endif
+        if (!m_fixed)
+            IfFailGo(fixup());
+
+    outputFileName = m_outputFileName;
+
+    if (! outputFileName && ppImage == NULL) {
+        if (m_comImageFlags & COMIMAGE_FLAGS_IL_LIBRARY)
+            outputFileName = L"output.ill";
+        else if (m_dllSwitch)
+            outputFileName = L"output.dll";
+        else if (m_objSwitch)
+            outputFileName = L"output.obj";
+        else
+            outputFileName = L"output.exe";
+    }
+
+    // output file name and ppImage are mutually exclusive
+    _ASSERTE((NULL == outputFileName && ppImage != NULL) || (outputFileName != NULL && NULL == ppImage));
+
+    if (outputFileName != NULL)
+        IfFailGo(getPEWriter().write(outputFileName));
+    else
+        IfFailGo(getPEWriter().write(ppImage));
+
+ErrExit:
+    if (hThreadToken != NULL) 
+    {
+        BOOL success = SetThreadToken(NULL, hThreadToken);
+        CloseHandle(hThreadToken);
+    
+        if (!success) 
+        {
+            _ASSERTE(!"Failed to reimpersonate!");
+            hr = HRESULT_FROM_GetLastError();
+        }
+    }
+    return hr;
+} // HRESULT CeeFileGenWriter::generateImage()
+
+HRESULT CeeFileGenWriter::setOutputFileName(__in LPWSTR fileName)
+{
+    if (m_outputFileName)
+        delete[] m_outputFileName;
+    int len = lstrlenW(fileName) + 1;
+    m_outputFileName = (LPWSTR)new (nothrow) WCHAR[len];
+    TESTANDRETURN(m_outputFileName!=NULL, E_OUTOFMEMORY);
+    wcscpy_s(m_outputFileName, len, fileName);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setOutputFileName()
+
+HRESULT CeeFileGenWriter::setResourceFileName(__in LPWSTR fileName)
+{
+    if (m_resourceFileName)
+        delete[] m_resourceFileName;
+    int len = lstrlenW(fileName) + 1;
+    m_resourceFileName = (LPWSTR)new (nothrow) WCHAR[len];
+    TESTANDRETURN(m_resourceFileName!=NULL, E_OUTOFMEMORY);
+    wcscpy_s(m_resourceFileName, len, fileName);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setResourceFileName()
+
+HRESULT CeeFileGenWriter::setLibraryName(__in LPWSTR libraryName)
+{
+    if (m_libraryName)
+        delete[] m_libraryName;
+    int len = lstrlenW(libraryName) + 1;
+    m_libraryName = (LPWSTR)new (nothrow) WCHAR[len];
+    TESTANDRETURN(m_libraryName != NULL, E_OUTOFMEMORY);
+    wcscpy_s(m_libraryName, len, libraryName);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setLibraryName()
+
+HRESULT CeeFileGenWriter::setLibraryGuid(__in LPWSTR libraryGuid)
+{
+    return IIDFromString(libraryGuid, &m_libraryGuid);
+} // HRESULT CeeFileGenWriter::setLibraryGuid()
+
+HRESULT CeeFileGenWriter::emitLibraryName(IMetaDataEmit *emitter)
+{
+    HRESULT hr;
+    IfFailRet(emitter->SetModuleProps(m_libraryName));
+
+    // Set the GUID as a custom attribute, if it is not NULL_GUID.
+    if (m_libraryGuid != GUID_NULL)
+    {
+        static COR_SIGNATURE _SIG[] = INTEROP_GUID_SIG;
+        mdTypeRef tr;
+        mdMemberRef mr;
+        WCHAR wzGuid[40];
+        BYTE  rgCA[50];
+        IfFailRet(emitter->DefineTypeRefByName(mdTypeRefNil, INTEROP_GUID_TYPE_W, &tr));
+        IfFailRet(emitter->DefineMemberRef(tr, L".ctor", _SIG, sizeof(_SIG), &mr));
+        StringFromGUID2(m_libraryGuid, wzGuid, lengthof(wzGuid));
+        memset(rgCA, 0, sizeof(rgCA));
+        // Tag is 0x0001
+        rgCA[0] = 1;
+        // Length of GUID string is 36 characters.
+        rgCA[2] = 0x24;
+        // Convert 36 characters, skipping opening {, into 3rd byte of buffer.
+        WszWideCharToMultiByte(CP_ACP,0, wzGuid+1,36, reinterpret_cast<char*>(&rgCA[3]),36, 0,0);
+        hr = emitter->DefineCustomAttribute(1,mr,rgCA,41,0);
+    }
+    return (hr);
+} // HRESULT CeeFileGenWriter::emitLibraryName()
+
+HRESULT CeeFileGenWriter::setImageBase(size_t imageBase)
+{
+    _ASSERTE(getPEWriter().isPE32());
+        getPEWriter().setImageBase32((DWORD)imageBase);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setImageBase()
+
+HRESULT CeeFileGenWriter::setImageBase64(ULONGLONG imageBase)
+{
+    _ASSERTE(!getPEWriter().isPE32());
+    getPEWriter().setImageBase64(imageBase);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setImageBase64()
+
+HRESULT CeeFileGenWriter::setFileAlignment(ULONG fileAlignment)
+{
+    getPEWriter().setFileAlignment(fileAlignment);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setFileAlignment()
+
+HRESULT CeeFileGenWriter::setSubsystem(DWORD subsystem, DWORD major, DWORD minor)
+{
+    getPEWriter().setSubsystem(subsystem, major, minor);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setSubsystem()
+
+HRESULT CeeFileGenWriter::checkForErrors()
+{
+    if (TypeFromToken(m_entryPoint) == mdtMethodDef) {
+        if (m_dllSwitch) {
+            //current spec would need to check the binary sig of the entry point method
+        }
+        return S_OK;
+    }
+    return S_OK;
+} // HRESULT CeeFileGenWriter::checkForErrors()
+
+HRESULT CeeFileGenWriter::getMethodRVA(ULONG codeOffset, ULONG *codeRVA)
+{
+    _ASSERTE(codeRVA);
+#ifdef ENC_DELTA_HACK
+    // for EnC we want the RVA to be right be relative to the front of the delta IL stream rather
+    // than take into account the .text section and the cor header as we would for a real PE file
+    if (g_EnCMode)
+        *codeRVA = codeOffset;
+    else
+#endif
+        *codeRVA = getPEWriter().getIlRva() + codeOffset;
+    return S_OK;
+} // HRESULT CeeFileGenWriter::getMethodRVA()
+
+HRESULT CeeFileGenWriter::setDirectoryEntry(CeeSection &section, ULONG entry, ULONG size, ULONG offset)
+{
+    return getPEWriter().setDirectoryEntry((PEWriterSection*)(&section.getImpl()), entry, size, offset);
+} // HRESULT CeeFileGenWriter::setDirectoryEntry()
+
+HRESULT CeeFileGenWriter::getFileTimeStamp(DWORD *pTimeStamp)
+{
+    return getPEWriter().getFileTimeStamp(pTimeStamp);
+} // HRESULT CeeFileGenWriter::getFileTimeStamp()
+
+HRESULT CeeFileGenWriter::setAddrReloc(UCHAR *instrAddr, DWORD value)
+{
+    *(DWORD *)instrAddr = VAL32(value);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setAddrReloc()
+
+HRESULT CeeFileGenWriter::addAddrReloc(CeeSection &thisSection, UCHAR *instrAddr, DWORD offset, CeeSection *targetSection)
+{
+    if (!targetSection) {
+        thisSection.addBaseReloc(offset, srRelocHighLow);
+    } else {
+        thisSection.addSectReloc(offset, *targetSection, srRelocHighLow);
+    }
+    return S_OK;
+} // HRESULT CeeFileGenWriter::addAddrReloc()
+
+// create CorExeMain and import directory into .text and the .iat into .data
+//
+// The structure of the import directory information is as follows, but it is not contiguous in
+// section. All the r/o data goes into the .text section and the iat array (which the loader
+// updates with the imported addresses) goes into the .data section because WINCE needs it to be writable.
+//
+//    struct IData {
+//      // one for each DLL, terminating in NULL
+//      IMAGE_IMPORT_DESCRIPTOR iid[];
+//      // import lookup table: a set of entries for the methods of each DLL,
+//      // terminating each set with NULL
+//      IMAGE_THUNK_DATA32/64 ilt[];
+//      // hint/name table: an set of entries for each method of each DLL wiht
+//      // no terminating entry
+//      struct {
+//          WORD Hint;
+//          // null terminated string
+//          BYTE Name[];
+//      } ibn;      // Hint/name table
+//      // import address table: a set of entries for the methods of each DLL,
+//      // terminating each set with NULL
+//      IMAGE_THUNK_DATA32/64 iat[];
+//      // one for each DLL, null terminated strings
+//      BYTE DllName[];
+//  };
+//
+
+// IAT must be first in its section, so have code here to allocate it up front
+// prior to knowing other info such as if dll or not. This won't work if have > 1
+// function imported, but we'll burn that bridge when we get to it.
+HRESULT CeeFileGenWriter::allocateIAT()
+{
+    m_dllCount = 1;
+    m_iDataDlls = new (nothrow) IDataDllInfo[m_dllCount];
+    if (m_iDataDlls == NULL) {
+        return E_OUTOFMEMORY;
+    }
+    memset(m_iDataDlls, '\0', m_dllCount * sizeof(IDataDllInfo));
+    m_iDataDlls[0].m_name = "mscoree.dll";
+    m_iDataDlls[0].m_numMethods = 1;
+    m_iDataDlls[0].m_methodName = new (nothrow) const char*[m_iDataDlls[0].m_numMethods];
+    if (! m_iDataDlls[0].m_methodName) {
+        return E_OUTOFMEMORY;
+    }
+    m_iDataDlls[0].m_methodName[0] = NULL;
+
+    int iDataSizeIAT = 0;
+
+    for (int i=0; i < m_dllCount; i++) {
+        m_iDataDlls[i].m_iatOffset = iDataSizeIAT;
+        iDataSizeIAT += (m_iDataDlls[i].m_numMethods + 1)
+                      * (getPEWriter().isPE32() ? sizeof(IMAGE_THUNK_DATA32)
+                                                : sizeof(IMAGE_THUNK_DATA64));
+    }
+
+    HRESULT hr = getSectionCreate(".text0", sdExecute, &m_iDataSectionIAT);
+    TESTANDRETURNHR(hr);
+    m_iDataOffsetIAT = m_iDataSectionIAT->dataLen();
+    _ASSERTE(m_iDataOffsetIAT == 0);
+    m_iDataIAT = m_iDataSectionIAT->getBlock(iDataSizeIAT);
+    if (! m_iDataIAT) {
+        return E_OUTOFMEMORY;
+    }
+    memset(m_iDataIAT, '\0', iDataSizeIAT);
+
+    // Don't set the IAT directory entry yet, since we may not actually end up doing
+    // an emitExeMain.
+
+    return S_OK;
+} // HRESULT CeeFileGenWriter::allocateIAT()
+
+HRESULT CeeFileGenWriter::emitExeMain()
+{
+    if (m_dllCount == 0)
+        return S_OK;
+
+    // Note: code later on in this method assumes that mscoree.dll is at
+    // index m_iDataDlls[0], with CorDllMain or CorExeMain at method[0]
+
+    _ASSERTE(getPEWriter().createCorMainStub());
+
+    if (m_dllSwitch) {
+        m_iDataDlls[0].m_methodName[0] = "_CorDllMain";
+    } else {
+        m_iDataDlls[0].m_methodName[0] = "_CorExeMain";
+    }
+
+    // IMAGE_IMPORT_DESCRIPTOR on PE/PE+ must be 4-byte or 8-byte aligned
+    int align     = (getPEWriter().isPE32()) ? 4 : 8;
+    int curOffset = getTextSection().dataLen();
+
+    int diff = ((curOffset + align -1) & ~(align-1)) - curOffset;
+    if (diff)
+    {
+        char* pDiff = getTextSection().getBlock(diff);
+        if (NULL==pDiff) return E_OUTOFMEMORY;
+        memset(pDiff,0,diff);
+    }
+
+    int iDataSizeRO = (m_dllCount + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
+    CeeSection &iDataSectionRO = getTextSection();
+    int iDataOffsetRO = iDataSectionRO.dataLen();
+    int iDataSizeIAT = 0;
+    int i;
+    for (i=0; i < m_dllCount; i++) {
+        m_iDataDlls[i].m_iltOffset = iDataSizeRO + iDataSizeIAT;
+        iDataSizeIAT += (m_iDataDlls[i].m_numMethods + 1)
+                      * (getPEWriter().isPE32() ? sizeof(IMAGE_THUNK_DATA32)
+                                                : sizeof(IMAGE_THUNK_DATA64));
+    }
+
+    iDataSizeRO += iDataSizeIAT;
+
+    for (i=0; i < m_dllCount; i++) {
+        int delta = (iDataSizeRO + iDataOffsetRO) % 16;
+        // make sure is on a 16-byte offset
+        if (delta != 0)
+            iDataSizeRO += (16 - delta);
+        _ASSERTE((iDataSizeRO + iDataOffsetRO) % 16 == 0);
+        m_iDataDlls[i].m_ibnOffset = iDataSizeRO;
+        for (int j=0; j < m_iDataDlls[i].m_numMethods; j++) {
+            int nameLen = (int)(strlen(m_iDataDlls[i].m_methodName[j]) + 1);
+            iDataSizeRO += sizeof(WORD) + nameLen + nameLen%2;
+        }
+    }
+    for (i=0; i < m_dllCount; i++) {
+        m_iDataDlls[i].m_nameOffset = iDataSizeRO;
+        iDataSizeRO += (int)(strlen(m_iDataDlls[i].m_name) + 2);
+    }
+
+    char *iDataRO = iDataSectionRO.getBlock(iDataSizeRO);
+
+    if (!iDataRO) return E_OUTOFMEMORY;
+
+    memset(iDataRO, '\0', iDataSizeRO);
+
+    setDirectoryEntry(iDataSectionRO, IMAGE_DIRECTORY_ENTRY_IMPORT, iDataSizeRO, iDataOffsetRO);
+
+    IMAGE_IMPORT_DESCRIPTOR *iid = (IMAGE_IMPORT_DESCRIPTOR *)iDataRO;
+    for (i=0; i < m_dllCount; i++) {
+
+        // fill in the import descriptors for each DLL
+        IMAGE_IMPORT_DESC_FIELD(iid[i], OriginalFirstThunk) = VAL32((ULONG)(m_iDataDlls[i].m_iltOffset + iDataOffsetRO));
+        iid[i].Name = VAL32(m_iDataDlls[i].m_nameOffset + iDataOffsetRO);
+        iid[i].FirstThunk = VAL32((ULONG)(m_iDataDlls[i].m_iatOffset + m_iDataOffsetIAT));
+
+        iDataSectionRO.addSectReloc(
+            (unsigned)(iDataOffsetRO + (char *)(&IMAGE_IMPORT_DESC_FIELD(iid[i], OriginalFirstThunk)) - iDataRO), iDataSectionRO, srRelocAbsolute);
+        iDataSectionRO.addSectReloc(
+            (unsigned)(iDataOffsetRO + (char *)(&iid[i].Name) - iDataRO), iDataSectionRO, srRelocAbsolute);
+        iDataSectionRO.addSectReloc(
+            (unsigned)(iDataOffsetRO + (char *)(&iid[i].FirstThunk) - iDataRO), *m_iDataSectionIAT, srRelocAbsolute);
+
+        if (getPEWriter().isPE32())
+        {
+        // now fill in the import lookup table for each DLL
+            IMAGE_THUNK_DATA32 *ilt = (IMAGE_THUNK_DATA32*) (iDataRO + m_iDataDlls[i].m_iltOffset);
+            IMAGE_THUNK_DATA32 *iat = (IMAGE_THUNK_DATA32*) (m_iDataIAT + m_iDataDlls[i].m_iatOffset);
+
+            int ibnOffset = m_iDataDlls[i].m_ibnOffset;
+            for (int j=0; j < m_iDataDlls[i].m_numMethods; j++)
+            {
+                ilt[j].u1.AddressOfData = VAL32((ULONG)(ibnOffset + iDataOffsetRO));
+                iat[j].u1.AddressOfData = VAL32((ULONG)(ibnOffset + iDataOffsetRO));
+    
+                iDataSectionRO.addSectReloc( (unsigned)(iDataOffsetRO + (char *)(&ilt[j].u1.AddressOfData) - iDataRO),
+                                                iDataSectionRO, srRelocAbsolute);
+                m_iDataSectionIAT->addSectReloc( (unsigned)(m_iDataOffsetIAT + (char *)(&iat[j].u1.AddressOfData) - m_iDataIAT),
+                                                    iDataSectionRO, srRelocAbsolute);
+                int nameLen = (int)(strlen(m_iDataDlls[i].m_methodName[j]) + 1);
+                memcpy(iDataRO + ibnOffset + offsetof(IMAGE_IMPORT_BY_NAME, Name),
+                                        m_iDataDlls[i].m_methodName[j], nameLen);
+                ibnOffset += sizeof(WORD) + nameLen + nameLen%2;
+            }
+        }
+        else
+        {
+            // now fill in the import lookup table for each DLL
+            IMAGE_THUNK_DATA64 *ilt = (IMAGE_THUNK_DATA64*) (iDataRO + m_iDataDlls[i].m_iltOffset);
+            IMAGE_THUNK_DATA64 *iat = (IMAGE_THUNK_DATA64*) (m_iDataIAT + m_iDataDlls[i].m_iatOffset);
+
+            int ibnOffset = m_iDataDlls[i].m_ibnOffset;
+            for (int j=0; j < m_iDataDlls[i].m_numMethods; j++)
+            {
+                ilt[j].u1.AddressOfData = VAL64((ULONG)(ibnOffset + iDataOffsetRO));
+                iat[j].u1.AddressOfData = VAL64((ULONG)(ibnOffset + iDataOffsetRO));
+
+                iDataSectionRO.addSectReloc( (unsigned)(iDataOffsetRO + (char *)(&ilt[j].u1.AddressOfData) - iDataRO),
+                                             iDataSectionRO, srRelocAbsolute);
+                m_iDataSectionIAT->addSectReloc( (unsigned)(m_iDataOffsetIAT + (char *)(&iat[j].u1.AddressOfData) - m_iDataIAT),
+                                                 iDataSectionRO, srRelocAbsolute);
+                int nameLen = (int)(strlen(m_iDataDlls[i].m_methodName[j]) + 1);
+                memcpy(iDataRO + ibnOffset + offsetof(IMAGE_IMPORT_BY_NAME, Name),
+                       m_iDataDlls[i].m_methodName[j], nameLen);
+                ibnOffset += sizeof(WORD) + nameLen + nameLen%2;
+            }
+        }
+
+        // now fill in the import lookup table for each DLL
+        strcpy_s(iDataRO + m_iDataDlls[i].m_nameOffset, 
+                 iDataSizeRO - m_iDataDlls[i].m_nameOffset,
+                 m_iDataDlls[i].m_name);
+
+    } // end of for loop i < m_dllCount
+
+
+    if (getPEWriter().isI386())
+    {
+        // Put the entry point code into the PE file
+        unsigned entryPointOffset = getTextSection().dataLen();
+        int iatOffset = (int) (entryPointOffset + (m_dllSwitch ? CorDllMainX86IATOffset : CorExeMainX86IATOffset));
+        align = 4;    // x86 fixups must be 4-byte aligned
+
+        // The IAT offset must be aligned because fixup is applied to it.
+        diff = ((iatOffset + align -1) & ~(align-1)) - iatOffset;
+        if (diff)
+        {
+            char* pDiff = getTextSection().getBlock(diff);
+            if(NULL==pDiff) return E_OUTOFMEMORY;
+            memset(pDiff,0,diff);
+            entryPointOffset += diff;
+        }
+        _ASSERTE((getTextSection().dataLen() + (m_dllSwitch ? CorDllMainX86IATOffset : CorExeMainX86IATOffset)) % align == 0);
+
+        getPEWriter().setEntryPointTextOffset(entryPointOffset);
+        if (m_dllSwitch)
+        {
+            UCHAR *dllMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(DllMainX86Template));
+            if(dllMainBuf==NULL) return E_OUTOFMEMORY;
+            memcpy(dllMainBuf, DllMainX86Template, sizeof(DllMainX86Template));
+            //mscoree.dll
+            setAddrReloc(dllMainBuf+CorDllMainX86IATOffset, m_iDataDlls[0].m_iatOffset + m_iDataOffsetIAT);
+            addAddrReloc(getTextSection(), dllMainBuf, entryPointOffset+CorDllMainX86IATOffset, m_iDataSectionIAT);
+        }
+        else
+        {
+            UCHAR *exeMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(ExeMainX86Template));
+            if(exeMainBuf==NULL) return E_OUTOFMEMORY;
+            memcpy(exeMainBuf, ExeMainX86Template, sizeof(ExeMainX86Template));
+            //mscoree.dll
+            setAddrReloc(exeMainBuf+CorExeMainX86IATOffset, m_iDataDlls[0].m_iatOffset + m_iDataOffsetIAT);
+            addAddrReloc(getTextSection(), exeMainBuf, entryPointOffset+CorExeMainX86IATOffset, m_iDataSectionIAT);
+        }
+    }
+    else if (getPEWriter().isAMD64())
+    {
+        // Put the entry point code into the PE file
+        unsigned entryPointOffset = getTextSection().dataLen();
+        int iatOffset = (int) (entryPointOffset + (m_dllSwitch ? CorDllMainAMD64IATOffset : CorExeMainAMD64IATOffset));
+        align = 16;    // AMD64 fixups must be 8-byte aligned
+
+        // The IAT offset must be aligned because fixup is applied to it.
+        diff = ((iatOffset + align -1) & ~(align-1)) - iatOffset;
+        if (diff)
+        {
+            char* pDiff = getTextSection().getBlock(diff);
+            if(NULL==pDiff) return E_OUTOFMEMORY;
+            memset(pDiff,0,diff);
+            entryPointOffset += diff;
+        }
+        _ASSERTE((getTextSection().dataLen() + (m_dllSwitch ? CorDllMainAMD64IATOffset : CorExeMainAMD64IATOffset)) % align == 0);
+        
+        getPEWriter().setEntryPointTextOffset(entryPointOffset);
+        if (m_dllSwitch)
+        {
+            UCHAR *dllMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(DllMainAMD64Template));
+            if(dllMainBuf==NULL) return E_OUTOFMEMORY;
+            memcpy(dllMainBuf, DllMainAMD64Template, sizeof(DllMainAMD64Template));
+            //mscoree.dll
+            setAddrReloc(dllMainBuf+CorDllMainAMD64IATOffset, m_iDataDlls[0].m_iatOffset + m_iDataOffsetIAT);
+            addAddrReloc(getTextSection(), dllMainBuf, entryPointOffset+CorDllMainAMD64IATOffset, m_iDataSectionIAT);
+        }
+        else
+        {
+            UCHAR *exeMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(ExeMainAMD64Template));
+            if(exeMainBuf==NULL) return E_OUTOFMEMORY;
+            memcpy(exeMainBuf, ExeMainAMD64Template, sizeof(ExeMainAMD64Template));
+            //mscoree.dll
+            setAddrReloc(exeMainBuf+CorExeMainAMD64IATOffset, m_iDataDlls[0].m_iatOffset + m_iDataOffsetIAT);
+            addAddrReloc(getTextSection(), exeMainBuf, entryPointOffset+CorExeMainAMD64IATOffset, m_iDataSectionIAT);
+        }
+    }
+    else if (getPEWriter().isIA64())
+    {
+        // Must have a PE+ PE64 file
+        //_ASSERTE(!getPEWriter().isPE32());
+
+        // Put the entry point code into the PE+ file
+        curOffset = getTextSection().dataLen();
+        align = 16;       // instructions on ia64 must be 16-byte aligned
+
+        // The entry point address be aligned
+        diff = ((curOffset + align -1) & ~(align-1)) - curOffset;
+        if (diff)
+        {
+            char* pDiff = getTextSection().getBlock(diff);
+            if(NULL==pDiff) return E_OUTOFMEMORY;
+            memset(pDiff,0,diff);
+        }
+
+        unsigned entryPointOffset = getTextSection().dataLen();
+
+        if (m_dllSwitch)
+        {
+            UCHAR *dllMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(DllMainIA64Template));
+            if (dllMainBuf==NULL) return E_OUTOFMEMORY;
+            memcpy(dllMainBuf, DllMainIA64Template, sizeof(DllMainIA64Template));
+        }
+        else
+        {
+            UCHAR *exeMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(ExeMainIA64Template));
+            if (exeMainBuf==NULL) return E_OUTOFMEMORY;
+            memcpy(exeMainBuf, ExeMainIA64Template, sizeof(ExeMainIA64Template));
+        }
+
+        // Put the entry point function pointer into the PE file
+        unsigned entryPlabelOffset = getTextSection().dataLen();
+        getPEWriter().setEntryPointTextOffset(entryPlabelOffset);
+
+        UCHAR * entryPtr = (UCHAR*)getTextSection().getBlock(sizeof(ULONGLONG));
+        UCHAR * gpPtr    = (UCHAR*)getTextSection().getBlock(sizeof(ULONGLONG));
+
+        memset(entryPtr,0,sizeof(ULONGLONG));
+        memset(gpPtr,0,sizeof(ULONGLONG));
+
+        setAddrReloc(entryPtr, entryPointOffset);
+        addAddrReloc(getTextSection(), entryPtr, entryPlabelOffset, &getTextSection());
+
+        setAddrReloc(gpPtr, m_iDataDlls[0].m_iatOffset + m_iDataOffsetIAT);
+        addAddrReloc(getTextSection(), gpPtr, entryPlabelOffset+8, m_iDataSectionIAT);
+    }
+    else
+    {
+        _ASSERTE(!"Unknown target machine");
+    }
+
+    // Now set our IAT entry since we're using the IAT
+    setDirectoryEntry(*m_iDataSectionIAT, IMAGE_DIRECTORY_ENTRY_IAT, iDataSizeIAT, m_iDataOffsetIAT);
+
+    return S_OK;
+} // HRESULT CeeFileGenWriter::emitExeMain()
+
+// Like CreateProcess(), but waits for execution to finish
+// Returns true if successful, false on failure.
+// dwExitCode set to process' exitcode
+
+HRESULT CopySystemDirectory(__in WCHAR* pPath,
+                            __out_ecount_part(cchBuffer, *pdwLength) LPWSTR pbuffer, 
+                            DWORD  cchBuffer,
+                            __out DWORD* pdwLength)
+{
+    if (pdwLength == NULL)
+        return E_POINTER;
+
+    HRESULT hr = S_OK;
+    if(pPath == NULL) 
+        return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+
+    SIZE_T dwPath = wcslen(pPath);
+    LPWSTR pSep = wcsrchr(pPath, L'\\');
+    if(pSep) {
+        dwPath = (DWORD)(pSep-pPath+1);
+        pPath[dwPath] = L'\0';
+    }
+
+    dwPath++; // Add back in the null
+    *pdwLength = (DWORD)dwPath;
+    if(dwPath > cchBuffer || pbuffer == NULL)
+        hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+    else {
+        CopyMemory(pbuffer, 
+                   pPath,
+                   dwPath*sizeof(WCHAR));
+    }
+    return hr;
+}
+
+HRESULT GetClrSystemDirectory(__out_ecount_part(cchBuffer, *pdwLength) LPWSTR pbuffer, 
+                             DWORD  cchBuffer,
+                             __out DWORD* pdwLength)
+{
+    HRESULT hr = S_OK;
+
+    if(pdwLength == NULL)
+        return E_POINTER;
+
+    WCHAR pPath[MAX_PATH];
+    DWORD dwPath = MAX_PATH;
+    
+
+    _ASSERTE (g_hThisInst);
+
+    dwPath = WszGetModuleFileName(g_hThisInst, pPath, dwPath);
+    if(dwPath == 0)
+    {
+        hr = HRESULT_FROM_GetLastErrorNA();
+        return (hr);
+    }
+    else 
+        return CopySystemDirectory(pPath, pbuffer, cchBuffer, pdwLength);
+}
+
+
+BOOL RunProcess(LPCWSTR tempResObj, LPCWSTR pszFilename, DWORD* pdwExitCode, PEWriter &pewriter)
+{
+    BOOL fSuccess = FALSE;
+
+    PROCESS_INFORMATION pi;
+
+    DWORD cchSystemDir = MAX_PATH + 1;
+    DWORD dwLen;
+    WCHAR wszSystemDir[MAX_PATH + 1];
+    if (FAILED(GetClrSystemDirectory(wszSystemDir, cchSystemDir, &dwLen)))
+        return FALSE;
+
+    WCHAR* wzMachine;
+    if(pewriter.isIA64())
+        wzMachine = L"IA64";
+    else if(pewriter.isAMD64())
+        wzMachine = L"AMD64";
+    else if(pewriter.isARM())
+        wzMachine = L"ARM";
+    else
+        wzMachine = L"IX86";
+
+    // Res file, so convert it
+    StackSString ssCmdLine;
+
+    LPWSTR ext = PathFindExtension(pszFilename);
+    if(*ext == NULL)
+    {
+        ssCmdLine.Printf(L"%scvtres.exe /NOLOGO /READONLY /MACHINE:%s \"/OUT:%s\" \"%s.\"",
+                    wszSystemDir,
+                    wzMachine,
+                    tempResObj,
+                    pszFilename);
+    }
+    else
+    {
+        ssCmdLine.Printf(L"%scvtres.exe /NOLOGO /READONLY /MACHINE:%s \"/OUT:%s\" \"%s\"",
+                    wszSystemDir,
+                    wzMachine,
+                    tempResObj,
+                    pszFilename);
+    }
+
+    STARTUPINFOW start;
+    ZeroMemory(&start, sizeof(start));
+    start.cb = sizeof(start);
+    start.dwFlags = STARTF_USESHOWWINDOW;
+    start.wShowWindow = SW_HIDE;
+
+    fSuccess = WszCreateProcess(
+                                NULL,
+                                ssCmdLine.GetUnicode(),
+                                NULL,
+                                NULL,
+                                true,
+                                0,
+                                0,
+                                NULL,
+                                &start,
+                                &pi);
+
+    // If process runs, wait for it to finish
+    if (fSuccess) {
+        WaitForSingleObject(pi.hProcess, INFINITE);
+
+        GetExitCodeProcess(pi.hProcess, pdwExitCode);
+
+        CloseHandle(pi.hProcess);
+
+        CloseHandle(pi.hThread);
+    }
+    return fSuccess;
+} // BOOL RunProcess()
+
+// Ensure that pszFilename is an object file (not just a binary resource)
+// If we convert, then return obj filename in pszTempFilename
+HRESULT ConvertResource(const WCHAR * pszFilename, __in_ecount(cchTempFilename) WCHAR *pszTempFilename, size_t cchTempFilename, PEWriter &pewriter)
+{
+    HANDLE hFile = WszCreateFile(pszFilename, GENERIC_READ,
+        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+// failure
+    if (!hFile || (hFile == INVALID_HANDLE_VALUE))
+    {
+        //dbprintf("Can't find resource files:%S\n", pszFilename);
+        return HRESULT_FROM_GetLastError();
+    }
+
+// Read first 4 bytes. If they're all 0, we have a win32 .res file which must be
+// converted. (So call CvtRes.exe). Else it's an obj file.
+
+    DWORD dwCount = -1;
+    DWORD dwData  = -1;
+
+    BOOL fRet = ReadFile(hFile,
+                    &dwData,
+                    4,
+                    &dwCount,
+                    NULL
+    );
+
+    CloseHandle(hFile);
+
+    if (!fRet) {
+        //dbprintf("Invalid resource file:%S\n", pszFilename);
+        return HRESULT_FROM_GetLastError();
+    }
+
+    if (dwData != 0)
+    {
+        return S_OK;
+    }
+
+    WCHAR tempResObj[MAX_PATH+1];
+    WCHAR tempResPath[MAX_PATH+1];
+
+    // Create the temp file where the temp path is at rather than where the application is at.
+    if (!WszGetTempPath(MAX_PATH, tempResPath))
+    {
+        return HRESULT_FROM_GetLastError();
+    }
+
+    if (!WszGetTempFileName(tempResPath, L"RES", 0, tempResObj))
+    {
+        //dbprintf("GetTempFileName failed\n");
+        return HRESULT_FROM_GetLastError();
+    }
+
+    DWORD dwExitCode;
+    fRet = RunProcess(tempResObj, pszFilename, &dwExitCode, pewriter);
+
+    if (!fRet)
+    {   // Couldn't run cvtres.exe
+        return PostError(CEE_E_CVTRES_NOT_FOUND);
+    }
+    else if (dwExitCode != 0)
+    {   // CvtRes.exe ran, but failed
+        return HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+    }
+    else
+    {   // Conversion succesful, so return filename.
+        wcscpy_s(pszTempFilename, cchTempFilename, tempResObj);
+    }
+    return S_OK;
+} // HRESULT ConvertResource()
+
+
+
+// This function reads a resource file and emits it into the generated PE file.
+// 1. We can only link resources in obj format. Must convert from .res to .obj
+// with CvtRes.exe.
+// 2. Must touch up all COFF relocs from .rsrc$01 (resource header) to .rsrc$02
+// (resource raw data)
+HRESULT CeeFileGenWriter::emitResourceSection()
+{
+    if (m_resourceFileName == NULL)
+        return S_OK;
+
+    // Make sure szResFileName is an obj, not just a .res; change name if we convert
+    WCHAR szTempFileName[MAX_PATH+1];
+    szTempFileName[0] = L'\0';
+    HRESULT hr = ConvertResource(m_resourceFileName, szTempFileName,
+                                 MAX_PATH+1, getPEWriter());
+    if (FAILED(hr)) return hr;
+
+    // Filename may change (if we convert .res to .obj), so have floating pointer
+    const WCHAR* szResFileName;
+    if (*szTempFileName)
+        szResFileName = szTempFileName;
+    else
+        szResFileName = m_resourceFileName;
+
+    _ASSERTE(szResFileName);
+
+    // read the resource file and spit it out in the .rsrc section
+
+    HANDLE hFile = INVALID_HANDLE_VALUE;
+    HANDLE hMap = NULL;
+    IMAGE_FILE_HEADER *hMod = NULL;
+    SIZE_T cbFileSize;
+    const BYTE *pbStartOfMappedMem;
+    IMAGE_SECTION_HEADER *rsrc[2] = { NULL, NULL };
+
+    S_SIZE_T cbTotalSizeOfRawData;
+
+    hr = S_OK;
+
+    WIN_PAL_TRY
+    {
+        // create a mapped view of the .res file
+        hFile = WszCreateFile(szResFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (hFile == INVALID_HANDLE_VALUE)
+        {
+            //dbprintf("Resource file %S not found\n", szResFileName);
+            hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+            goto lDone;
+        }
+
+        // Grab the file size for verification checks.
+        {
+            DWORD dwFileSizeHigh;
+            DWORD dwFileSize = SafeGetFileSize(hFile, &dwFileSizeHigh);
+            if (dwFileSize == (DWORD)(-1))
+            {
+                hr = HRESULT_FROM_GetLastError();
+                goto lDone;
+            }
+
+            // Since we intend to memory map this file, the size of the file can not need 64 bits to represent!
+            if (dwFileSizeHigh != 0)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                goto lDone;
+            }
+
+            cbFileSize = static_cast<SIZE_T>(dwFileSize);
+        }
+
+        hMap = WszCreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, NULL);
+
+        if (hMap == NULL)
+        {
+            //dbprintf("Invalid .res file: %S\n", szResFileName);
+            hr = HRESULT_FROM_GetLastError();
+            goto lDone;
+        }
+
+        pbStartOfMappedMem = reinterpret_cast<const BYTE *>(MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0));
+
+        // test failure conditions
+        if (pbStartOfMappedMem == NULL)
+        {
+            //dbprintf("Invalid .res file: %S:Can't get header\n", szResFileName);
+            hr = HRESULT_FROM_GetLastError();
+            goto lDone;
+        }
+
+        // Check that the file contains an IMAGE_FILE_HEADER structure.
+        if (IMAGE_SIZEOF_FILE_HEADER > cbFileSize)
+        {
+            hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+            goto lDone;
+        }
+
+        hMod = (IMAGE_FILE_HEADER*) pbStartOfMappedMem;
+
+        if (VAL16(hMod->SizeOfOptionalHeader) != 0)
+        {
+            //dbprintf("Invalid .res file: %S:Illegal optional header\n", szResFileName);
+            hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND); // GetLastError() = 0 since API worked.
+            goto lDone;
+        }
+
+        // Scan all section headers and grab .rsrc$01 and .rsrc$02
+        {
+            // First section is directly after header
+            SIZE_T cSections = static_cast<SIZE_T>(VAL16(hMod->NumberOfSections));
+            SIZE_T cbStartOfSections = IMAGE_SIZEOF_FILE_HEADER;
+            S_SIZE_T cbEndOfSections(S_SIZE_T(cbStartOfSections) +
+                                     (S_SIZE_T(cSections) * S_SIZE_T(IMAGE_SIZEOF_SECTION_HEADER)));
+
+            // Check that all sections are within the bounds of the mapped file.
+            if (cbEndOfSections.IsOverflow() ||
+                cbEndOfSections.Value() > cbFileSize)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                goto lDone;
+            }
+
+            {
+                IMAGE_SECTION_HEADER *pSection =
+                    (IMAGE_SECTION_HEADER *)(pbStartOfMappedMem + cbStartOfSections);
+                IMAGE_SECTION_HEADER *pSectionEnd = pSection + cSections;
+
+                for (; pSection < pSectionEnd; pSection++)
+                {
+                    if (strcmp(".rsrc$01", (char *)pSection->Name) == 0)
+                    {
+                        rsrc[0] = pSection;
+                    }
+                    else if (strcmp(".rsrc$02", (char *)pSection->Name) == 0)
+                    {
+                        rsrc[1] = pSection;
+                    }
+                }
+            }
+        }
+
+        // If we don't have both resources, fail.
+        if (!rsrc[0] || !rsrc[1])
+        {
+            //dbprintf("Invalid .res file: %S: Missing sections .rsrc$01 or .rsrc$02\n", szResFileName);
+            hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+            goto lDone;
+        }
+
+        // Verify the resource data starts and sizes
+        {
+            cbTotalSizeOfRawData = S_SIZE_T(0);
+
+            for (int i = 0; i < 2; i++)
+            {
+                S_SIZE_T cbStartOfResourceData(static_cast<SIZE_T>(VAL32(rsrc[i]->PointerToRawData)));
+                S_SIZE_T cbSizeOfResourceData(static_cast<SIZE_T>(VAL32(rsrc[i]->SizeOfRawData)));
+                S_SIZE_T cbEndOfResourceData(cbStartOfResourceData + cbSizeOfResourceData);
+
+                if (cbEndOfResourceData.IsOverflow() ||
+                    cbEndOfResourceData.Value() > cbFileSize)
+                {
+                    hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                    goto lDone;
+                }
+
+                cbTotalSizeOfRawData += cbSizeOfResourceData;
+            }
+
+            // Check that the total raw data doesn't overflow.
+            if (cbTotalSizeOfRawData.IsOverflow() ||
+                cbTotalSizeOfRawData.Value() > cbFileSize)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                goto lDone;
+            }
+        }
+
+        PESection *rsrcSection;
+        hr = getPEWriter().getSectionCreate(".rsrc", sdReadOnly, &rsrcSection);
+        if (FAILED(hr)) goto lDone;
+
+        rsrcSection->directoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE);
+        char *data = rsrcSection->getBlock(static_cast<unsigned>(cbTotalSizeOfRawData.Value()), 8);
+        if(data == NULL)
+        {
+            hr = E_OUTOFMEMORY;
+            goto lDone;
+        }
+
+        // Copy resource header
+        memcpy(data, (char *)hMod + VAL32(rsrc[0]->PointerToRawData), VAL32(rsrc[0]->SizeOfRawData));
+
+        // Map all the relocs in .rsrc$01 using the reloc and symbol tables in the COFF object.,
+        SIZE_T            cReloc        = 0;         // Total number of relocs
+        IMAGE_RELOCATION *pReloc        = NULL;      // Reloc table start
+
+        SIZE_T            cSymbol       = 0;         // Total number of symbols
+        IMAGE_SYMBOL     *pSymbolTable  = NULL;      // Symbol table start
+
+        {
+            // Check that the relocations and symbols lie within the resource
+            cReloc = VAL16(rsrc[0]->NumberOfRelocations);
+            SIZE_T cbStartOfRelocations = static_cast<SIZE_T>(VAL32(rsrc[0]->PointerToRelocations));
+            S_SIZE_T cbEndOfRelocations(S_SIZE_T(cbStartOfRelocations) +
+                                        (S_SIZE_T(cReloc) * S_SIZE_T(sizeof(IMAGE_RELOCATION))));
+
+
+            // Verify the number of symbols fit into the resource.
+            cSymbol = static_cast<SIZE_T>(VAL32(hMod->NumberOfSymbols));
+            SIZE_T cbStartOfSymbolTable = static_cast<SIZE_T>(VAL32(hMod->PointerToSymbolTable));
+            S_SIZE_T cbEndOfSymbolTable(S_SIZE_T(cbStartOfSymbolTable) +
+                                        (S_SIZE_T(cSymbol) * S_SIZE_T(IMAGE_SIZEOF_SYMBOL)));
+
+            if (cbEndOfRelocations.IsOverflow() ||
+                cbEndOfRelocations.Value() > cbFileSize ||
+                cbEndOfSymbolTable.IsOverflow() ||
+                cbEndOfSymbolTable.Value() > cbFileSize)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                goto lDone;
+            }
+
+            pReloc = (IMAGE_RELOCATION *)(pbStartOfMappedMem + cbStartOfRelocations);
+            pSymbolTable = (IMAGE_SYMBOL *)(pbStartOfMappedMem + cbStartOfSymbolTable);
+        }
+
+        _ASSERTE(pReloc != NULL && pSymbolTable != NULL);
+
+        for(SIZE_T iReloc = 0; iReloc < cReloc; iReloc++, pReloc++)
+        {
+            // Ensure this is a valid reloc
+            {
+                S_SIZE_T cbRelocEnd = S_SIZE_T(VAL32(pReloc->VirtualAddress)) + S_SIZE_T(sizeof(DWORD));
+                if (cbRelocEnd.IsOverflow() || 
+                    cbRelocEnd.Value() > static_cast<SIZE_T>(VAL32(rsrc[0]->SizeOfRawData)))
+                {
+                    hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                    goto lDone;
+                }
+            }
+
+            // index into symbol table, provides address into $02
+            DWORD iSymbol = VAL32(pReloc->SymbolTableIndex);
+
+            // Make sure the index is in range
+            if (iSymbol >= cSymbol)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                goto lDone;
+            }
+
+            IMAGE_SYMBOL* pSymbolEntry = GetSymbolEntry(pSymbolTable, iSymbol);
+
+            // Ensure the symbol entry is valid for a resource.
+            if ((pSymbolEntry->StorageClass != IMAGE_SYM_CLASS_STATIC) ||
+                (VAL16(pSymbolEntry->Type) != IMAGE_SYM_TYPE_NULL) ||
+                (VAL16(pSymbolEntry->SectionNumber) != 3)) // 3rd section is .rsrc$02
+            {
+                //dbprintf("Invalid .res file: %S:Illegal symbol entry\n", szResFileName);
+                hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                goto lDone;
+            }
+
+            // Ensure that RVA is valid address (inside rsrc[1])
+            if (VAL32(pSymbolEntry->Value) >= VAL32(rsrc[1]->SizeOfRawData))
+            {
+                //dbprintf("Invalid .res file: %S:Illegal rva into .rsrc$02\n", szResFileName);
+                hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+                goto lDone;
+            }
+
+            DWORD dwOffsetInRsrc2 = VAL32(pSymbolEntry->Value) + VAL32(rsrc[0]->SizeOfRawData);
+
+            // Create reloc
+            *(DWORD*)(data + VAL32(pReloc->VirtualAddress)) = VAL32(dwOffsetInRsrc2);
+            rsrcSection->addSectReloc(pReloc->VirtualAddress, rsrcSection, srRelocAbsolute);
+        }
+
+        // Copy $02 (resource raw) data
+        memcpy(data+VAL32(rsrc[0]->SizeOfRawData), 
+            (char *)hMod + VAL32(rsrc[1]->PointerToRawData), 
+            VAL32(rsrc[1]->SizeOfRawData));
+
+lDone: ;
+    }
+    WIN_PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        //dbprintf("Exception occured manipulating .res file %S\n", szResFileName);
+        hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
+    }
+    WIN_PAL_ENDTRY
+
+    if (hMod != NULL)
+        UnmapViewOfFile(hMod);
+    if (hMap != NULL)
+        CloseHandle(hMap);
+    if (hFile != INVALID_HANDLE_VALUE)
+        CloseHandle(hFile);
+    if (szResFileName == szTempFileName)
+        // delete temporary file if we created one
+        WszDeleteFile(szResFileName);
+
+    return hr;
+} // HRESULT CeeFileGenWriter::emitResourceSection()
+
+HRESULT CeeFileGenWriter::setManifestEntry(ULONG size, ULONG offset)
+{
+    if (offset)
+        m_dwManifestRVA = offset;
+    else {
+        CeeSection TextSection = getTextSection();
+        getMethodRVA(TextSection.dataLen() - size, &m_dwManifestRVA);
+    }
+
+    m_dwManifestSize = size;
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setManifestEntry()
+
+HRESULT CeeFileGenWriter::setStrongNameEntry(ULONG size, ULONG offset)
+{
+    m_dwStrongNameRVA = offset;
+    m_dwStrongNameSize = size;
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setStrongNameEntry()
+
+HRESULT CeeFileGenWriter::setVTableEntry64(ULONG size, void* ptr)
+{
+    if (ptr && size)
+    {
+        void * pv;
+        CeeSection TextSection = getTextSection();
+        // make it DWORD-aligned
+        ULONG L = TextSection.dataLen();
+        if((L &= ((ULONG)sizeof(DWORD)-1)))
+        {
+            L = (ULONG)sizeof(DWORD) - L;
+            if((pv = TextSection.getBlock(L)))
+                memset(pv,0,L);
+            else
+                return E_OUTOFMEMORY;
+        }
+        getMethodRVA(TextSection.dataLen(), &m_dwVTableRVA);
+        if((pv = TextSection.getBlock(size)))
+        {
+            memcpy(pv,ptr,size);
+        }
+        else
+            return E_OUTOFMEMORY;
+        m_dwVTableSize = size;
+    }
+
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setVTableEntry()
+
+HRESULT CeeFileGenWriter::setVTableEntry(ULONG size, ULONG offset)
+{
+    return setVTableEntry64(size,(void*)(ULONG_PTR)offset);
+} // HRESULT CeeFileGenWriter::setVTableEntry()
+
+HRESULT CeeFileGenWriter::setEnCRvaBase(ULONG dataBase, ULONG rdataBase)
+{
+    setEnCMode();
+    getPEWriter().setEnCRvaBase(dataBase, rdataBase);
+    return S_OK;
+} // HRESULT CeeFileGenWriter::setEnCRvaBase()
+
+HRESULT CeeFileGenWriter::computeSectionOffset(CeeSection &section, __in char *ptr,
+                                               unsigned *offset)
+{
+    *offset = section.computeOffset(ptr);
+
+    return S_OK;
+} // HRESULT CeeFileGenWriter::computeSectionOffset()
+
+HRESULT CeeFileGenWriter::computeOffset(__in char *ptr,
+                                        CeeSection **pSection, unsigned *offset)
+{
+    TESTANDRETURNPOINTER(pSection);
+
+    CeeSection **s = m_sections;
+    CeeSection **sEnd = s + m_numSections;
+    while (s < sEnd)
+    {
+        if ((*s)->containsPointer(ptr))
+        {
+            *pSection = *s;
+            *offset = (*s)->computeOffset(ptr);
+
+            return S_OK;
+        }
+        s++;
+    }
+
+    return E_FAIL;
+} // HRESULT CeeFileGenWriter::computeOffset()
+
+HRESULT CeeFileGenWriter::getCorHeader(IMAGE_COR20_HEADER **ppHeader)
+{
+    *ppHeader = m_corHeader;
+    return S_OK;
+} // HRESULT CeeFileGenWriter::getCorHeader()
+
+
+#ifdef EMIT_FIXUPS
+
+HRESULT CeeFileGenWriter::InitFixupSection()
+{
+    if (!m_fEmitFixups)
+    {
+       return(E_UNEXPECTED);
+    }
+
+    HRESULT hr;
+
+    hr = getSectionCreate(".fixups",
+                           IMAGE_SCN_CNT_INITIALIZED_DATA  | IMAGE_SCN_MEM_READ,
+                           &m_sectionFixups);
+    if (SUCCEEDED(hr))
+    {
+       size_t cbDebugDir = sizeof(IMAGE_DEBUG_DIRECTORY);
+       hr = GetSectionBlock(m_sectionFixups, (ULONG) cbDebugDir, 32, (void **) &m_pDebugDir);
+       if (SUCCEEDED(hr))
+       {
+          memset(m_pDebugDir, 0, cbDebugDir);
+          m_pDebugDir->Type = IMAGE_DEBUG_TYPE_FIXUP;
+          m_fFixupsUpdated = false;
+
+          return(S_OK);
+       }
+    }
+
+    m_pDebugDir = NULL;
+    m_sectionFixups = NULL;
+    m_fEmitFixups = false;
+
+    return(E_FAIL);
+
+} // HRESULT CeeFileGenWriter::InitFixupSection()
+
+HRESULT CeeFileGenWriter::addFixup(CeeSection& sectionSource, unsigned offset, CeeSectionRelocType relocType, CeeSection * psectionTarget, CeeSectionRelocExtra *extra)
+{
+   if (!m_fEmitFixups)
+   {
+      return(S_OK);
+   }
+
+   _ASSERTE(sizeof(DBG_FIXUP) == sizeof(PEFIXUP));
+   _ASSERTE(m_fFixupsUpdated == false);
+
+   DBG_FIXUP * pfixup;
+
+   if (m_sectionFixups == NULL)
+   {
+      HRESULT hr = InitFixupSection();
+      if (FAILED(hr))
+      {
+         return(hr);
+      }
+
+      // The fixup section begins with a IMAGE_DEBUG_DIRECTORY containing a
+      // IMAGE_DEBUG_TYPE_FIXUP directory entry, which describes the array
+      // of fixups which follows it.
+
+      // The very first item of this array is aligned on a 32 bit boundary.
+      // All other fixup entries follow unaligned.
+      pfixup = (DBG_FIXUP *) m_sectionFixups->getBlock(sizeof(DBG_FIXUP), 32);
+      TESTANDRETURN(pfixup != NULL, E_OUTOFMEMORY);
+
+      // Initialize the IMAGE_DEBUG_TYPE_FIXUP entry relocations
+#ifdef _WIN64
+      _ASSERTE(!"Base relocs are not yet implemented for 64-bit");
+      m_pDebugDir->AddressOfRawData = 0; // @ToDo: srRelocAbsolutePtr can't take a 64-bit address
+#else
+      m_pDebugDir->AddressOfRawData = (size_t) pfixup;
+      m_sectionFixups->addSectReloc(offsetof(IMAGE_DEBUG_DIRECTORY, AddressOfRawData), *m_sectionFixups, srRelocAbsolutePtr);
+#endif
+
+      m_pDebugDir->PointerToRawData = m_sectionFixups->computeOffset((char *) pfixup);
+
+      m_sectionFixups->addSectReloc(offsetof(IMAGE_DEBUG_DIRECTORY, PointerToRawData), *m_sectionFixups, srRelocFilePos);
+
+      unsigned offsetDir = m_sectionFixups->computeOffset((char *) m_pDebugDir);
+      setDirectoryEntry(*m_sectionFixups, IMAGE_DIRECTORY_ENTRY_DEBUG, sizeof(IMAGE_DEBUG_DIRECTORY), offsetDir);
+
+#ifdef TEST_EMIT_FIXUPS
+      TestEmitFixups();
+#endif
+   }
+   else
+   {
+      pfixup = (DBG_FIXUP *) m_sectionFixups->getBlock(sizeof(DBG_FIXUP), 1);
+      TESTANDRETURN(pfixup != NULL, E_OUTOFMEMORY);
+   }
+
+   // Save off the relocation information for use later.  The relocation's
+   // target information can be filled in later.
+   // The relocation target info is not always immediately available, so it needs
+   // to be extracted later, during the link phase.  For now the relocation info
+   // is stored so the target can be extracted at link time in the UpdateFixups
+   // function.
+   //
+   unsigned offsetFixup = m_sectionFixups->computeOffset((char *) pfixup);
+   pfixup->wSpare = 0;
+   pfixup->wType = relocType;
+   _ASSERTE(pfixup->wType == relocType);
+   pfixup->offset = offset;
+   pfixup->sectionSource = &sectionSource;
+
+   m_pDebugDir->SizeOfData += sizeof(DBG_FIXUP);
+
+   // Add a relocation for the fixup's source RVA field, (no fixup on this reloc)
+   m_sectionFixups->addSectReloc(offsetFixup + offsetof(DBG_FIXUP, rva), sectionSource, srRelocAbsolutePtr);
+
+   // Add a relocation for the fixup's target RVA field.  Correct target extracted
+   // later in UpdateFixups, (no fixup on this reloc)
+   CeeSectionRelocType tgtRelocType;
+
+   switch (relocType)
+   {
+      case srRelocMapToken:
+         // not an RVA
+         tgtRelocType = srRelocMapToken;
+         break;
+
+      case srRelocFilePos:
+         tgtRelocType = srRelocFilePos;
+         break;
+
+      case srRelocHighAdj:
+         tgtRelocType = srRelocHighAdj;
+         break;
+
+      default:
+         tgtRelocType = (relocType & srRelocPtr) ? srRelocAbsolutePtr : srRelocAbsolute;
+         break;
+   }
+
+   if (psectionTarget != NULL)
+   {
+      m_sectionFixups->addSectReloc(offsetFixup + offsetof(DBG_FIXUP, rvaTarget), *psectionTarget, tgtRelocType, extra);
+   }
+   else
+   {
+      m_sectionFixups->addBaseReloc(offsetFixup + offsetof(DBG_FIXUP, rvaTarget), tgtRelocType, extra);
+   }
+
+   return(S_OK);
+} // HRESULT CeeFileGenWriter::addFixup()
+
+HRESULT CeeFileGenWriter::UpdateFixups()
+{
+   // This method extracts the correct relocation target.  See addFixup method.
+
+   if (!m_fEmitFixups || m_fFixupsUpdated)
+   {
+      return(S_OK);
+   }
+   m_fFixupsUpdated = true; // prevent UpdateFixups from being called again.
+
+   size_t cfixups = m_pDebugDir->SizeOfData / sizeof(DBG_FIXUP);
+   _ASSERT(m_pDebugDir->SizeOfData % sizeof(DBG_FIXUP) == 0);
+   unsigned ibFixup = m_pDebugDir->PointerToRawData;
+
+   for (size_t idx = 0; idx < cfixups; idx++, ibFixup += sizeof(DBG_FIXUP))
+   {
+      DBG_FIXUP * pfixup = (DBG_FIXUP *) m_sectionFixups->computePointer(ibFixup);
+      CeeSection * sectionSource = pfixup->sectionSource;
+      CeeSectionRelocType relocType = (CeeSectionRelocType) pfixup->wType;
+      unsigned offset = pfixup->offset;
+
+      // Get current data for replacing fixup contents
+      const DWORD * pdw = (DWORD *) sectionSource->computePointer(offset);
+      pfixup->rva = (DWORD) (UINT_PTR) pdw;
+      pfixup->rvaTarget = *pdw;
+
+      switch (relocType)
+      {
+#ifdef _X86_
+      case srRelocAbsolute:
+          // Emitted bytes: RVA, offset relative to image base
+          // reloc src contains target offset relative to target section
+          if ((*pdw & 0xFF000000) == 0)
+          {
+              pfixup->wType = IMAGE_REL_I386_DIR32NB;
+          }
+          else
+          {
+              // MethodDesc::Fixup function creates a 24 bit RVA, where the
+              // high byte of the DWORD stores the flag value: METHOD_NEEDS_PRESTUB_RUN_FLAG.
+              // work around it by converting the type to 24 bits here
+              pfixup->wType = IMAGE_REL_I386_DIR24NB;
+              pfixup->rvaTarget = *pdw & 0x00FFFFFF;
+          }
+          break;
+
+      case srRelocAbsolutePtr:
+          // Emitted bytes: RVA, offset relative to image base
+          // reloc src contains target pointer
+          pfixup->wType = IMAGE_REL_I386_DIR32NB;
+          break;
+          
+      case srRelocHighLow:
+          // Emitted bytes: full address of target
+          // reloc src contains target offset relative to target section
+          pfixup->wType = IMAGE_REL_I386_DIR32;
+          break;
+          
+      case srRelocHighLowPtr:
+          // Emitted bytes: full address of target
+          // reloc src contains target pointer
+          pfixup->wType = IMAGE_REL_I386_DIR32;
+          break;
+          
+      case srRelocRelative:
+          // Emitted bytes: value of reloc tgt - (reloc source + sizeof(DWORD))
+          // reloc src contains offset relative to target section, minus sizeof(DWORD)
+          // the reloc type for pFixup->rvaTarget is srRelocAbsolute
+          // so contents of pFixup->rvaTarget need to be offset Target + sizeof(DWORD)
+          // which is offset Target == Source contents + sizeof(DWORD) == *pdw + sizeof(DWORD)
+          pfixup->wType = IMAGE_REL_I386_REL32;
+          pfixup->rvaTarget = *pdw + sizeof(DWORD);
+          break;
+          
+      case srRelocRelativePtr:
+          // Emitted bytes: value of reloc tgt - (reloc source + sizeof(DWORD))
+          // reloc src contains disp, disp = pTarget - (pSource + sizeof(DWORD))
+          // the reloc type for pFixup->rvaTarget is srRelocAbsolutePtr
+          // so contents of pFixup->rvaTarget need to be pTarget
+          // which is pTarget == pSource + sizeof(DWORD) + disp == pdw + 4 + *pdw
+          pfixup->wType = IMAGE_REL_I386_REL32;
+          pfixup->rvaTarget = (int) (INT_PTR) pdw + sizeof(DWORD) + (int) *pdw;
+          break;
+          
+      case srRelocMapToken:
+          // Emitted bytes: contents of reloc source unchanged.
+          // reloc src contains token value
+          pfixup->wType = IMAGE_REL_I386_TOKEN;
+          break;
+
+#elif defined(_AMD64_)
+          /*
+          //
+          // X86-64 relocations
+          //
+          IMAGE_REL_AMD64_ABSOLUTE        0x0000  // Reference is absolute, no relocation is necessary
+          IMAGE_REL_AMD64_ADDR64          0x0001  // 64-bit address (VA).
+          IMAGE_REL_AMD64_ADDR32          0x0002  // 32-bit address (VA).
+          IMAGE_REL_AMD64_ADDR32NB        0x0003  // 32-bit address w/o image base (RVA).
+          IMAGE_REL_AMD64_REL32           0x0004  // 32-bit relative address from byte following reloc
+          IMAGE_REL_AMD64_REL32_1         0x0005  // 32-bit relative address from byte distance 1 from reloc
+          IMAGE_REL_AMD64_REL32_2         0x0006  // 32-bit relative address from byte distance 2 from reloc
+          IMAGE_REL_AMD64_REL32_3         0x0007  // 32-bit relative address from byte distance 3 from reloc
+          IMAGE_REL_AMD64_REL32_4         0x0008  // 32-bit relative address from byte distance 4 from reloc
+          IMAGE_REL_AMD64_REL32_5         0x0009  // 32-bit relative address from byte distance 5 from reloc
+          IMAGE_REL_AMD64_SECTION         0x000A  // Section index
+          IMAGE_REL_AMD64_SECREL          0x000B  // 32 bit offset from base of section containing target
+          IMAGE_REL_AMD64_SECREL7         0x000C  // 7 bit unsigned offset from base of section containing target
+          IMAGE_REL_AMD64_TOKEN           0x000D  // 32 bit metadata token
+          IMAGE_REL_AMD64_SREL32          0x000E  // 32 bit signed span-dependent value emitted into object
+          IMAGE_REL_AMD64_PAIR            0x000F
+          IMAGE_REL_AMD64_SSPAN32         0x0010  // 32 bit signed span-dependent value applied at link time
+          */
+      case srRelocAbsolute:
+          // Emitted bytes: RVA, offset relative to image base
+          pfixup->wType = IMAGE_REL_AMD64_ADDR32NB;
+          break;
+          
+      case srRelocAbsolutePtr:
+          // Emitted bytes: RVA, offset relative to image base
+          // reloc src contains target pointer
+          pfixup->wType = IMAGE_REL_AMD64_ADDR32NB;
+          break;
+          
+      case srRelocDir64Ptr:
+          // Emitted bytes: full address of target
+          // reloc src contains target pointer
+          pfixup->wType = IMAGE_REL_IA64_DIR64;
+          break;
+          
+      case srRelocMapToken:
+          // Emitted bytes: contents of reloc source unchanged.
+          // reloc src contains token value
+          pfixup->wType = IMAGE_REL_AMD64_TOKEN;
+          break;
+#endif
+      case srRelocFilePos:
+          // Emitted bytes: offset relative to start of file, differs from RVA.
+          pfixup->wType = IMAGE_REL_I386_FILEPOS;
+          break;
+
+      case srRelocAbsoluteTagged:
+            pfixup->wType = IMAGE_REL_I386_DIR30NB;
+            pfixup->rvaTarget = (*pdw & ~0x80000001) >> 1;
+          break;
+
+      case srRelocHighAdj:
+          // Emitted bytes: 2 part relocation, with high part adjusted by constant.
+          pfixup->wType = IMAGE_REL_BASED_HIGHADJ;
+          break;
+
+      default:
+          _ASSERTE(!"Unknown relocation type");
+          return(E_UNEXPECTED);
+          break;
+      }
+   }
+
+   return(S_OK);
+
+} // HRESULT CeeFileGenWriter::UpdateFixups()
+
+
+HRESULT CeeFileGenWriter::setEmitFixups()
+{
+   m_fEmitFixups = true;
+   return(S_OK);
+
+} // HRESULT CeeFileGenWriter::setEmitFixups()
+
+#ifdef TEST_EMIT_FIXUPS
+
+HRESULT CeeFileGenWriter::TestEmitFixups()
+{
+   HRESULT hr;
+   // Test fixups
+
+   CeeSection * testSection;
+   hr = getSectionCreate(".test",
+                          IMAGE_SCN_CNT_INITIALIZED_DATA  | IMAGE_SCN_MEM_READ,
+                          &testSection);
+   if (SUCCEEDED(hr))
+   {
+      struct FixupEntry
+      {
+         char sz[18];
+         DWORD wTargets[8];
+      };
+
+      struct FixupTypes
+      {
+         char *               pszType;
+         CeeSectionRelocType  relocType;
+      };
+
+      FixupTypes rgTypes[] =
+      {
+         { "srRelocAbsolute   ", srRelocAbsolute      },
+         { "srRelocAbsolutePtr", srRelocAbsolutePtr   },
+         { "srRelocHighLow    ", srRelocHighLow       },
+         { "srRelocHighLowPtr ", srRelocHighLowPtr    },
+      // { "srRelocRelative   ", srRelocRelative      },
+      // { "srRelocRelativePtr", srRelocRelativePtr   },
+         { "srRelocMapToken   ", srRelocMapToken      },
+      // { "srRelocFilePos    ", srRelocFilePos       },
+      // { "srRelocHighAdj    ", srRelocHighAdj       },
+      };
+
+      const size_t cFixups = sizeof(rgTypes) / sizeof(rgTypes[0]);
+
+      DWORD * pdwTargets[20];
+
+      // Target Blocks:
+
+      for (size_t idx = 0; idx < cFixups; idx++)
+      {
+         hr = GetSectionBlock(testSection, sizeof(DWORD), 1, (void **) &pdwTargets[idx]);
+         _ASSERTE(SUCCEEDED(hr));
+
+         DWORD * pdw = pdwTargets[idx];
+         *pdw = idx;
+      }
+
+      for (size_t idxType = 0; idxType < cFixups; idxType++)
+      {
+         // Fixup Entries
+         FixupEntry * pEntry;
+         hr = GetSectionBlock(testSection, sizeof(FixupEntry), 1, (void **) &pEntry);
+         _ASSERTE(SUCCEEDED(hr));
+
+         memset(pEntry, 0, sizeof(FixupEntry));
+         strcpy_s(pEntry->sz, sizeof(pEntry->sz), rgTypes[idxType].pszType);
+
+         size_t ibBlock = testSection->computeOffset((char *) pEntry);
+
+         for (size_t idx = 0; idx < cFixups; idx++)
+         {
+            size_t ibFixup = ((size_t) &pEntry->wTargets[idx]) - (size_t) pEntry;
+
+            switch (rgTypes[idxType].relocType)
+            {
+               case srRelocAbsolute:
+                 pEntry->wTargets[idx] = idx * sizeof(DWORD);
+                 break;
+
+               case srRelocAbsolutePtr:
+                 pEntry->wTargets[idx] = (DWORD) pdwTargets[idx];
+                 break;
+
+               case srRelocHighLow:
+                 pEntry->wTargets[idx] = idx * sizeof(DWORD);
+                 break;
+
+               case srRelocHighLowPtr:
+                 pEntry->wTargets[idx] = (DWORD) pdwTargets[idx];
+                 break;
+
+               case srRelocRelative:
+                 pEntry->wTargets[idx] = idx;
+                 break;
+
+               case srRelocRelativePtr:
+               {
+                 size_t ibTgt = (size_t) pdwTargets[idx];
+                 size_t ibSrc = ((size_t) &pEntry->wTargets[idx]) + sizeof(DWORD);
+                 pEntry->wTargets[idx] = (DWORD)( ibTgt - ibSrc );
+                 ibFixup += sizeof(DWORD); // offset needs to point at end of DWORD
+                 break;
+               }
+
+               case srRelocHighAdj:
+                 pEntry->wTargets[idx] = idx * sizeof(DWORD);
+                 break;
+
+               case srRelocMapToken:
+                 pEntry->wTargets[idx] = idx * sizeof(DWORD);
+                 break;
+
+               case srRelocFilePos:
+                 pEntry->wTargets[idx] = idx * sizeof(DWORD);
+                 break;
+            }
+
+            addFixup(*testSection, ibBlock + ibFixup, rgTypes[idxType].relocType, testSection);
+            testSection->addSectReloc(ibBlock + ibFixup, *testSection, rgTypes[idxType].relocType);
+         }
+      }
+   }
+
+   return(S_OK);
+}
+#endif // TEST_EMIT_FIXUPS
+#endif // EMIT_FIXUPS
+
+#ifndef FEATURE_MERGE_JIT_AND_ENGINE
+
+//*****************************************************************************
+// Handle lifetime of loaded library.
+//*****************************************************************************
+extern "C"
+BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+    switch (dwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+        {   // Save the module handle.
+            g_hThisInst = (HINSTANCE)hInstance;
+            DisableThreadLibraryCalls((HMODULE)hInstance);
+        }
+        break;
+    case DLL_PROCESS_DETACH:
+        break;
+    }
+
+    return (true);
+} // BOOL WINAPI DllMain()
+
+
+HINSTANCE GetModuleInst()
+{
+    return (g_hThisInst);
+} // HINSTANCE GetModuleInst()
+
+#endif //FEATURE_MERGE_JIT_AND_ENGINE
diff --git a/src/dlls/mscorpe/ceefilegenwritertokens.cpp b/src/dlls/mscorpe/ceefilegenwritertokens.cpp
new file mode 100644 (file)
index 0000000..b8d5ac0
--- /dev/null
@@ -0,0 +1,265 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//*****************************************************************************
+// CeeFileGenWriterTokens.cpp
+//
+// This code will walk the byte codes for all methods before they are saved
+// to disk and apply the token fix-ups if they have moved.
+//
+//*****************************************************************************
+#include "stdafx.h"
+#include "ceegen.h"
+#define DECLARE_DATA
+#include "../../ildasm/dasmenum.hpp"
+#define MAX_CLASSNAME_LENGTH    1024
+
+//********** Locals. **********************************************************
+OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen);
+
+
+
+//********** Code. ************************************************************
+
+
+//*****************************************************************************
+// Method bodies are kept in the text section.  The meta data contains the
+// RVA of each method body in the image.  The TextSection object contains the
+// actual raw bytes where the method bodies are located.  This code will
+// determine the raw offset of each method based on the RVA kept in the meta
+// data.
+//*****************************************************************************
+
+HRESULT CeeFileGenWriter::MapTokens(
+    CeeGenTokenMapper *pMapper,
+    IMetaDataImport *pImport)
+{
+    mdTypeDef   td;
+    mdMethodDef md;
+    ULONG       count;
+    ULONG       MethodRVA;
+    ULONG       codeOffset;
+    ULONG       BaseRVA;
+    DWORD       dwFlags;
+    DWORD       iFlags;
+    HCORENUM    hTypeDefs = 0, hEnum = 0;
+    WCHAR       rcwName[MAX_CLASSNAME_LENGTH];
+    HRESULT     hr;
+    CeeSection  TextSection = getTextSection();
+
+    // Ask for the base RVA of the first method in the stream.  All other
+    // method RVA's are >= that value, and will give us the raw offset required.
+
+    hr = getMethodRVA(0, &BaseRVA);
+    _ASSERTE(SUCCEEDED(hr));
+    // do globals first
+    while ((hr = pImport->EnumMethods(&hEnum, mdTokenNil, &md, 1, &count)) == S_OK)
+    {
+        hr = pImport->GetMethodProps(md, NULL,
+                    rcwName, lengthof(rcwName), NULL,
+                    &dwFlags, NULL, NULL,
+                    &MethodRVA, &iFlags);
+        _ASSERTE(SUCCEEDED(hr));
+
+        if (MethodRVA == 0 || ((IsMdAbstract(dwFlags) || IsMiInternalCall(iFlags)) ||
+                                   (! IsMiIL(iFlags) && ! IsMiOPTIL(iFlags))))
+            continue;
+
+        // The raw offset of the method is the RVA in the image minus
+        // the first method in the text section.
+        codeOffset = MethodRVA - BaseRVA;
+        hr = MapTokensForMethod(pMapper,
+                    (BYTE *) TextSection.computePointer(codeOffset),
+                    rcwName);
+        if (FAILED(hr))
+            goto ErrExit;
+    }
+    if (hEnum) pImport->CloseEnum(hEnum);
+    hEnum = 0;
+
+    while ((hr = pImport->EnumTypeDefs(&hTypeDefs, &td, 1, &count)) == S_OK)
+    {
+        while ((hr = pImport->EnumMethods(&hEnum, td, &md, 1, &count)) == S_OK)
+        {
+            hr = pImport->GetMethodProps(md, NULL,
+                        rcwName, lengthof(rcwName), NULL,
+                        &dwFlags, NULL, NULL,
+                        &MethodRVA, &iFlags);
+            _ASSERTE(SUCCEEDED(hr));
+
+            if (MethodRVA == 0 || ((IsMdAbstract(dwFlags) || IsMiInternalCall(iFlags)) ||
+                                   (! IsMiIL(iFlags) && ! IsMiOPTIL(iFlags))))
+                continue;
+
+
+            // The raw offset of the method is the RVA in the image minus
+            // the first method in the text section.
+            codeOffset = MethodRVA - BaseRVA;
+            hr = MapTokensForMethod(pMapper,
+                        (BYTE *) TextSection.computePointer(codeOffset),
+                        rcwName);
+            if (FAILED(hr))
+                goto ErrExit;
+        }
+
+        if (hEnum) pImport->CloseEnum(hEnum);
+        hEnum = 0;
+    }
+
+ErrExit:
+    if (hTypeDefs) pImport->CloseEnum(hTypeDefs);
+    if (hEnum) pImport->CloseEnum(hEnum);
+    return (hr);
+}
+
+
+//*****************************************************************************
+// This method will walk the byte codes of an IL method looking for tokens.
+// For each token found, it will check to see if it has been moved, and if
+// so, apply the new token value in its place.
+//*****************************************************************************
+HRESULT CeeFileGenWriter::MapTokensForMethod(
+    CeeGenTokenMapper *pMapper,
+    BYTE        *pCode,
+    LPCWSTR     szMethodName)
+{
+    mdToken     tkTo;
+    DWORD       PC;
+
+    COR_ILMETHOD_DECODER method((COR_ILMETHOD*) pCode);
+
+    // If compressed IL is being emitted, this routine will have no idea how to walk the tokens,
+    // so don't do it
+    if (m_dwMacroDefinitionSize != 0)
+        return S_OK;
+
+    pCode = const_cast<BYTE*>(method.Code);
+
+    PC = 0;
+    while (PC < method.GetCodeSize())
+    {
+        DWORD   Len;
+        DWORD   i;
+        OPCODE  instr;
+
+        instr = DecodeOpcode(&pCode[PC], &Len);
+
+        if (instr == CEE_COUNT)
+        {
+            _ASSERTE(0 && "Instruction decoding error\n");
+            return E_FAIL;
+        }
+
+
+        PC += Len;
+
+        switch (OpcodeInfo[instr].Type)
+        {
+            DWORD tk;
+
+            default:
+            {
+                _ASSERTE(0 && "Unknown instruction\n");
+                return E_FAIL;
+            }
+
+            case InlineNone:
+            break;
+
+            case ShortInlineI:
+            case ShortInlineVar:
+            case ShortInlineBrTarget:
+            PC++;
+            break;
+
+            case InlineVar:
+            PC += 2;
+            break;
+
+            case InlineI:
+            case ShortInlineR:
+            case InlineBrTarget:
+            case InlineRVA:
+            PC += 4;
+            break;
+
+            case InlineI8:
+            case InlineR:
+            PC += 8;
+            break;
+
+            case InlinePhi:
+                {
+                    DWORD cases = pCode[PC];
+                    PC += 2 * cases + 1;
+                    break;
+                }
+
+            case InlineSwitch:
+            {
+                DWORD cases = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+
+                PC += 4;
+                for (i = 0; i < cases; i++)
+                {
+                    PC += 4;
+                }
+
+                // skip bottom of loop which prints szString
+                continue;
+            }
+
+            case InlineTok:
+            case InlineSig:
+            case InlineMethod:
+            case InlineField:
+            case InlineType:
+            case InlineString:
+            {
+                tk = GET_UNALIGNED_VAL32(&pCode[PC]);
+
+                if (pMapper->HasTokenMoved(tk, tkTo))
+                {
+                    SET_UNALIGNED_VAL32(&pCode[PC], tkTo);
+                }
+
+                PC += 4;
+                break;
+            }
+        }
+    }
+
+    return S_OK;
+}
+
+
+
+
+OPCODE 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)
+                opcode = 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:
+            *pdwLen = 3;
+            return CEE_COUNT;
+        default:
+            break;
+        }
+    return opcode;
+}
diff --git a/src/dlls/mscorpe/dirs.proj b/src/dlls/mscorpe/dirs.proj
new file mode 100644 (file)
index 0000000..46bb0ce
--- /dev/null
@@ -0,0 +1,15 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+
+    <!--The following projects will build during PHASE 1-->
+  <PropertyGroup>
+    <BuildInPhaseDefault>false</BuildInPhaseDefault>
+    <BuildInPhase1>true</BuildInPhase1>
+  </PropertyGroup>
+    <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+        <ProjectFile Include="mscorpe\mscorpe.nativeproj" />
+        <ProjectFile Include="mscorpehost\mscorpehost.nativeproj" />
+    </ItemGroup>
+
+    <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/dlls/mscorpe/iceefilegen.cpp b/src/dlls/mscorpe/iceefilegen.cpp
new file mode 100644 (file)
index 0000000..d41dcfd
--- /dev/null
@@ -0,0 +1,733 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+// ===========================================================================
+//  File: CEEGEN.CPP
+// ===========================================================================
+#include "stdafx.h"
+#include "iceefilegen.h"
+#include "ceefilegenwriter.h"
+
+#ifdef EnC_SUPPORTED
+#define ENC_DELTA_HACK
+#endif
+
+#ifdef ENC_DELTA_HACK
+extern BOOL g_EnCMode;
+#endif
+
+// Deprecated
+//****************************************************************************
+    HRESULT ICeeFileGen::EmitMethod ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::EmitSignature ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::SetEntryClassToken ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::GetEntryClassToken ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::SetEntryPointDescr ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::GetEntryPointDescr ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::SetEntryPointFlags ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::GetEntryPointFlags ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::CreateSig ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::AddSigArg ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::SetSigReturnType ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::SetSigCallingConvention ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+    HRESULT ICeeFileGen::DeleteSig ()
+    {
+        _ASSERTE("Deprecated" && 0);
+        return (E_FAIL);
+    }
+//****************************************************************************
+
+EXTERN_C HRESULT __stdcall CreateICeeFileGen(ICeeFileGen** pCeeFileGen)
+{
+    if (!pCeeFileGen)
+        return E_POINTER;
+    
+    ICeeFileGen *gen = new (nothrow) ICeeFileGen();
+    IfNullRet(gen);
+   
+    *pCeeFileGen = gen;
+    return S_OK;
+}
+
+EXTERN_C HRESULT __stdcall DestroyICeeFileGen(ICeeFileGen** pCeeFileGen)
+{
+    if (!pCeeFileGen)
+        return E_POINTER;
+    delete *pCeeFileGen;
+    *pCeeFileGen = NULL;
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::CreateCeeFile (HCEEFILE *ceeFile)
+{
+    return CreateCeeFileEx(ceeFile, ICEE_CREATE_FILE_PURE_IL);
+}
+
+HRESULT ICeeFileGen::CreateCeeFileEx (HCEEFILE *ceeFile, DWORD createFlags)
+{
+    return CreateCeeFileEx2(ceeFile, createFlags, NULL);
+}
+
+//
+// Seed file is used as the base file. The new file data will be "appended" to the seed file
+//
+
+HRESULT ICeeFileGen::CreateCeeFileEx2 (HCEEFILE *ceeFile, DWORD createFlags, LPCWSTR seedFileName)
+{
+    if (!ceeFile)
+        return E_POINTER;
+    
+    CeeFileGenWriter *gen = NULL;
+    HRESULT hr;
+    IfFailRet(CeeFileGenWriter::CreateNewInstanceEx(NULL, gen, createFlags, seedFileName));
+    TESTANDRETURN(gen != NULL, E_OUTOFMEMORY);
+    *ceeFile = gen;
+
+#ifdef ENC_DELTA_HACK
+    // for EnC we want the RVA to be right be relative to the front of the delta IL stream rather
+    // than take into account the .text section and the cor header as we would for a real PE file
+    // However, the RVA must be non-zero, so just stick a dword on the front to push it out.
+    if (g_EnCMode)
+    {
+        CeeSection *sec = &gen->getIlSection();
+        sec->getBlock(sizeof(DWORD), sizeof(DWORD));
+    } 
+#endif
+
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::CreateCeeFileFromICeeGen(ICeeGen *pICeeGen, HCEEFILE *ceeFile, DWORD createFlags)
+{
+    if (!ceeFile)
+        return E_POINTER;
+    CCeeGen *genFrom = reinterpret_cast<CCeeGen*>(pICeeGen);
+    CeeFileGenWriter *gen = NULL;
+    if (FAILED(CeeFileGenWriter::CreateNewInstance(genFrom, gen, createFlags))) return FALSE;
+    TESTANDRETURN(gen != NULL, E_OUTOFMEMORY);
+    *ceeFile = gen;
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::DestroyCeeFile(HCEEFILE *ceeFile)
+{
+    if (!ceeFile)
+        return E_POINTER;
+    if (!*ceeFile)
+        return E_POINTER;
+
+    CeeFileGenWriter **gen = reinterpret_cast<CeeFileGenWriter**>(ceeFile);
+    (*gen)->Cleanup();
+    delete *gen;
+    *ceeFile = NULL;
+    return S_OK;
+}
+
+// 
+
+HRESULT ICeeFileGen::GetRdataSection (HCEEFILE ceeFile, HCEESECTION *section)
+{
+    TESTANDRETURNPOINTER(section);
+    TESTANDRETURNARG(ceeFile != 0);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    *section = &gen->getStringSection();
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::GetIlSection (HCEEFILE ceeFile, HCEESECTION *section)
+{
+    TESTANDRETURNPOINTER(section);
+    TESTANDRETURNARG(ceeFile != 0);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    *section = &gen->getIlSection();
+    return S_OK;
+}
+
+
+HRESULT ICeeFileGen::GetSectionCreate (HCEEFILE ceeFile, const char *name, DWORD flags,
+                                                        HCEESECTION *section)
+{
+    TESTANDRETURNPOINTER(section);
+    TESTANDRETURNARG(ceeFile != 0);
+    TESTANDRETURNPOINTER(name);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    CeeSection **ceeSection = reinterpret_cast<CeeSection**>(section);
+
+    HRESULT hr = gen->getSectionCreate(name, flags, ceeSection);
+
+    return hr;
+}
+
+HRESULT ICeeFileGen::SetDirectoryEntry(HCEEFILE ceeFile, HCEESECTION section, ULONG num, ULONG size, ULONG offset)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(section);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    CeeSection &sec = *(reinterpret_cast<CeeSection*>(section));
+    return(gen->setDirectoryEntry(sec, num, size, offset));
+}
+
+HRESULT ICeeFileGen::GetSectionDataLen (HCEESECTION section, ULONG *dataLen)
+{
+    TESTANDRETURNPOINTER(section);
+    TESTANDRETURNPOINTER(dataLen);
+
+    CeeSection *sec = reinterpret_cast<CeeSection*>(section);
+    *dataLen = sec->dataLen();
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::GetSectionRVA (HCEESECTION section, ULONG *rva)
+{
+    TESTANDRETURNPOINTER(section);
+    TESTANDRETURNPOINTER(rva);
+
+    CeeSection *sec = reinterpret_cast<CeeSection*>(section);
+    *rva = sec->getBaseRVA();
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::GetSectionBlock (HCEESECTION section, ULONG len,
+                            ULONG align, void **ppBytes)
+{
+    TESTANDRETURNPOINTER(section);
+    TESTANDRETURNPOINTER(ppBytes);
+
+    CeeSection *sec = reinterpret_cast<CeeSection*>(section);
+    void *bytes = sec->getBlock(len, align);
+    TESTANDRETURN(bytes != NULL, E_OUTOFMEMORY);
+    *ppBytes = bytes;
+
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::TruncateSection (HCEESECTION section, ULONG len)
+{
+    _ASSERTE(!"This is an obsolete function!");
+    return E_NOTIMPL;
+}
+
+HRESULT ICeeFileGen::AddSectionReloc (HCEESECTION section, ULONG offset, HCEESECTION relativeTo, CeeSectionRelocType relocType)
+{
+    TESTANDRETURNPOINTER(section);
+
+    CeeSection *sec = reinterpret_cast<CeeSection*>(section);
+    CeeSection *relSec = reinterpret_cast<CeeSection*>(relativeTo);
+
+    if (relSec)
+    {
+#ifdef EMIT_FIXUPS
+        CeeFileGenWriter * gen = reinterpret_cast<CeeFileGenWriter*>(&sec->ceeFile());
+        HRESULT hr = gen->addFixup(*sec, offset, relocType, relSec);
+        if (FAILED(hr))
+        {
+           return(hr);
+        }
+#endif
+        return(sec->addSectReloc(offset, *relSec, relocType));
+    }
+    else
+    {
+#ifdef EMIT_FIXUPS
+        CeeFileGenWriter * gen = reinterpret_cast<CeeFileGenWriter*>(&sec->ceeFile());
+        HRESULT hr = gen->addFixup(*sec, offset, relocType);
+        if (FAILED(hr))
+        {
+           return(hr);
+        }
+#endif
+        return(sec->addBaseReloc(offset, relocType));
+    }
+}
+
+HRESULT ICeeFileGen::SetSectionDirectoryEntry(HCEESECTION section, ULONG num)
+{
+    TESTANDRETURNPOINTER(section);
+
+    printf("Warning: deprecated method. Use SetDirectoryEntry instead\n");
+    CeeSection *sec = reinterpret_cast<CeeSection*>(section);
+    return(sec->directoryEntry(num));
+}
+
+HRESULT ICeeFileGen::SetOutputFileName (HCEEFILE ceeFile, __in LPWSTR outputFileName)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(outputFileName);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->setOutputFileName(outputFileName));
+}
+
+__success(return == S_OK) HRESULT ICeeFileGen::GetOutputFileName (HCEEFILE ceeFile, __out LPWSTR *outputFileName)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(outputFileName);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    TESTANDRETURNPOINTER(outputFileName);
+    *outputFileName = gen->getOutputFileName();
+    return S_OK;
+}
+
+
+HRESULT ICeeFileGen::SetResourceFileName (HCEEFILE ceeFile, __in LPWSTR resourceFileName)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(resourceFileName);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->setResourceFileName(resourceFileName));
+}
+
+__success(return == S_OK)
+HRESULT ICeeFileGen::GetResourceFileName (HCEEFILE ceeFile, __out LPWSTR *resourceFileName)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(resourceFileName);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    TESTANDRETURNPOINTER(resourceFileName);
+    *resourceFileName = gen->getResourceFileName();
+    return S_OK;
+}
+
+
+HRESULT ICeeFileGen::SetImageBase(HCEEFILE ceeFile, size_t imageBase)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    gen->setImageBase(imageBase);
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::SetImageBase64(HCEEFILE ceeFile, ULONGLONG imageBase)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    gen->setImageBase64(imageBase);
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::SetFileAlignment(HCEEFILE ceeFile, ULONG fileAlignment)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    gen->setFileAlignment(fileAlignment);
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::SetSubsystem(HCEEFILE ceeFile, DWORD subsystem, DWORD major, DWORD minor)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    gen->setSubsystem(subsystem, major, minor);
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::GetIMapTokenIface(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken)
+{
+    _ASSERTE(!"This is an obsolete function!");
+    return E_NOTIMPL;
+}
+
+HRESULT ICeeFileGen::EmitMetaData (HCEEFILE ceeFile, IMetaDataEmit *emitter,
+                                                                mdScope scopeE)
+{
+    _ASSERTE(!"This is an obsolete function!");
+    return E_NOTIMPL;
+}
+
+HRESULT ICeeFileGen::EmitLibraryName (HCEEFILE ceeFile, IMetaDataEmit *emitter,
+                                                                mdScope scopeE)
+{
+    _ASSERTE(!"This is an obsolete function!");
+    return E_NOTIMPL;
+}
+
+HRESULT ICeeFileGen::GetMethodRVA(HCEEFILE ceeFile, ULONG codeOffset, ULONG *codeRVA)
+{
+    TESTANDRETURNARG(ceeFile != 0);
+    TESTANDRETURNPOINTER(codeRVA);
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    gen->getMethodRVA(codeOffset, codeRVA);
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::EmitString(HCEEFILE ceeFile, __in LPWSTR strValue, ULONG *strRef)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->getStringSection().getEmittedStringRef(strValue, strRef));
+}
+
+HRESULT ICeeFileGen::LinkCeeFile (HCEEFILE ceeFile)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->link();
+}
+
+HRESULT ICeeFileGen::FixupCeeFile (HCEEFILE ceeFile)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->fixup();
+}
+
+HRESULT ICeeFileGen::GetHeaderInfo (HCEEFILE ceeFile, PIMAGE_NT_HEADERS *ppNtHeaders, PIMAGE_SECTION_HEADER *ppSections, ULONG *pNumSections)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    gen->getPEWriter().getHeaderInfo(ppNtHeaders, ppSections, pNumSections);
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::GenerateCeeFile (HCEEFILE ceeFile)
+{
+    SO_NOT_MAINLINE_FUNCTION;
+
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->generateImage(NULL);     // NULL means don't write in-memory buffer, uses outputFileName
+}
+
+// GenerateCeeMemoryImage - returns in ppImage an in-memory PE image allocated by CoTaskMemAlloc()
+// the caller is responsible for calling CoTaskMemFree on this memory image
+HRESULT ICeeFileGen::GenerateCeeMemoryImage (HCEEFILE ceeFile, void **ppImage)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(ppImage);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->generateImage(ppImage);
+}
+
+HRESULT ICeeFileGen::SetEntryPoint(HCEEFILE ceeFile, mdMethodDef method)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->setEntryPoint(method);
+}
+
+HRESULT ICeeFileGen::GetEntryPoint(HCEEFILE ceeFile, mdMethodDef *method)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    TESTANDRETURNPOINTER(method);
+    *method = gen->getEntryPoint();
+    return S_OK;
+}
+
+
+HRESULT ICeeFileGen::SetComImageFlags (HCEEFILE ceeFile, DWORD mask)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->setComImageFlags(mask);
+}
+
+HRESULT ICeeFileGen::ClearComImageFlags (HCEEFILE ceeFile, DWORD mask)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->clearComImageFlags(mask);
+}
+
+HRESULT ICeeFileGen::GetComImageFlags (HCEEFILE ceeFile, DWORD *mask)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    TESTANDRETURNPOINTER(mask);
+    *mask = gen->getComImageFlags();
+    return S_OK;
+}
+
+
+HRESULT ICeeFileGen::SetDllSwitch (HCEEFILE ceeFile, BOOL dllSwitch)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->setDllSwitch(dllSwitch==TRUE));
+}
+
+HRESULT ICeeFileGen::GetDllSwitch (HCEEFILE ceeFile, BOOL *dllSwitch)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    TESTANDRETURNPOINTER(dllSwitch);
+    *dllSwitch = gen->getDllSwitch();
+    return S_OK;
+}
+
+HRESULT ICeeFileGen::SetObjSwitch (HCEEFILE ceeFile, BOOL objSwitch)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->setObjSwitch(objSwitch==TRUE));
+}
+
+HRESULT ICeeFileGen::GetObjSwitch (HCEEFILE ceeFile, BOOL *objSwitch)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    TESTANDRETURNPOINTER(objSwitch);
+    *objSwitch = gen->getObjSwitch();
+    return S_OK;
+}
+
+
+HRESULT ICeeFileGen::SetLibraryName (HCEEFILE ceeFile, __in LPWSTR LibraryName)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(LibraryName);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->setLibraryName(LibraryName));
+}
+
+HRESULT ICeeFileGen::SetLibraryGuid (HCEEFILE ceeFile, __in LPWSTR LibraryGuid)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(LibraryGuid);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->setLibraryGuid(LibraryGuid));
+}
+
+__success(return == S_OK) HRESULT ICeeFileGen::GetLibraryName (HCEEFILE ceeFile, __out LPWSTR *LibraryName)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(LibraryName);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    *LibraryName = gen->getLibraryName();
+    return S_OK;
+}
+
+
+
+HRESULT ICeeFileGen::EmitMetaDataEx (HCEEFILE ceeFile, IMetaDataEmit *emitter)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(emitter);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->emitMetaData(emitter));
+}
+
+HRESULT ICeeFileGen::EmitMetaDataAt (HCEEFILE ceeFile, IMetaDataEmit *emitter, HCEESECTION section, DWORD offset, BYTE* buffer, unsigned buffLen)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(emitter);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    CeeSection* sec = reinterpret_cast<CeeSection*>(section);
+
+    return(gen->emitMetaData(emitter, sec, offset, buffer, buffLen));
+}
+
+HRESULT ICeeFileGen::EmitLibraryNameEx (HCEEFILE ceeFile, IMetaDataEmit *emitter)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(emitter);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->emitLibraryName(emitter));
+}
+
+HRESULT ICeeFileGen::GetIMapTokenIfaceEx(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(pIMapToken);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->getMapTokenIface(pIMapToken);
+}
+
+HRESULT ICeeFileGen::AddNotificationHandler(HCEEFILE ceeFile,
+                                            IUnknown *pHandler)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(pHandler);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->addNotificationHandler(pHandler);
+}
+
+HRESULT ICeeFileGen::EmitMacroDefinitions(HCEEFILE ceeFile, void *pData, DWORD cData)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->EmitMacroDefinitions(pData, cData);
+}
+
+HRESULT ICeeFileGen::SetManifestEntry(HCEEFILE ceeFile, ULONG size, ULONG offset)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->setManifestEntry(size, offset);
+}
+
+HRESULT ICeeFileGen::SetStrongNameEntry(HCEEFILE ceeFile, ULONG size, ULONG offset)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->setStrongNameEntry(size, offset);
+}
+
+HRESULT ICeeFileGen::ComputeSectionOffset(HCEESECTION section, __in char *ptr,
+                                                                                 unsigned *offset)
+{
+    TESTANDRETURNPOINTER(section);
+
+    CeeSection &sec = *(reinterpret_cast<CeeSection*>(section));
+
+       *offset = sec.computeOffset(ptr);
+
+       return S_OK;
+}
+
+__success(return == S_OK)
+HRESULT ICeeFileGen::ComputeSectionPointer(HCEESECTION section, ULONG offset,
+                                                                                 __out char **ptr)
+{
+    TESTANDRETURNPOINTER(section);
+
+    CeeSection &sec = *(reinterpret_cast<CeeSection*>(section));
+
+       *ptr = sec.computePointer(offset);
+
+       return S_OK;
+}
+
+HRESULT ICeeFileGen::ComputeOffset(HCEEFILE ceeFile, __in char *ptr,
+                                                                  HCEESECTION *pSection, unsigned *offset)
+{
+    TESTANDRETURNPOINTER(pSection);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+
+       CeeSection *section;
+
+       HRESULT hr = gen->computeOffset(ptr, &section, offset);
+
+       if (SUCCEEDED(hr))
+               *pSection = reinterpret_cast<HCEESECTION>(section);
+
+       return hr;
+}
+
+HRESULT ICeeFileGen::SetEnCRVABase(HCEEFILE ceeFile, ULONG dataBase, ULONG rdataBase)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->setEnCRvaBase(dataBase, rdataBase);
+}
+
+HRESULT ICeeFileGen::GetCorHeader(HCEEFILE ceeFile,
+                                                                 IMAGE_COR20_HEADER **header)
+{
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+       return gen->getCorHeader(header);
+}
+
+HRESULT ICeeFileGen::SetVTableEntry(HCEEFILE ceeFile, ULONG size, ULONG offset)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->setVTableEntry(size, offset);
+}
+
+HRESULT ICeeFileGen::SetVTableEntry64(HCEEFILE ceeFile, ULONG size, void* ptr)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return gen->setVTableEntry64(size, ptr);
+}
+
+HRESULT ICeeFileGen::GetFileTimeStamp (HCEEFILE ceeFile, DWORD *pTimeStamp)
+{
+    TESTANDRETURNPOINTER(ceeFile);
+    TESTANDRETURNPOINTER(pTimeStamp);
+
+    CeeFileGenWriter *gen = reinterpret_cast<CeeFileGenWriter*>(ceeFile);
+    return(gen->getFileTimeStamp(pTimeStamp));
+}
+
diff --git a/src/dlls/mscorpe/mscorpe/mscorpe.def b/src/dlls/mscorpe/mscorpe/mscorpe.def
new file mode 100644 (file)
index 0000000..61cb903
--- /dev/null
@@ -0,0 +1,11 @@
+;
+; Copyright (c) Microsoft. All rights reserved.
+; Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+;
+; mscorpe.def for mscorpe.dll (a simple wrapper around real implementation mscorpehost.dll - see 
+; file:wrapper.cpp for more details)
+; PE file generator in EE
+
+EXPORTS
+     CreateICeeFileGen
+     DestroyICeeFileGen
diff --git a/src/dlls/mscorpe/mscorpe/mscorpe.nativeproj b/src/dlls/mscorpe/mscorpe/mscorpe.nativeproj
new file mode 100644 (file)
index 0000000..526cf60
--- /dev/null
@@ -0,0 +1,46 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+
+    <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+
+    <PropertyGroup>
+        <NoCrt>true</NoCrt>
+        <LinkUseCMT>true</LinkUseCMT>
+        <UserIncludes>
+            $(UserIncludes);
+            .
+        </UserIncludes>
+        <CDefines>$(CDefines);__TODO_PORT_TO_WRAPPERS__;UNICODE</CDefines>
+        <OutputName>mscorpe</OutputName>
+        <FileToMarkForSigning>$(BinariesDirectory)\$(OutputName).dll</FileToMarkForSigning>
+        <OutputLibPath>$(IntermediateOutputDirectory)</OutputLibPath>
+        <DllDef>$(OutputName).def</DllDef>
+        <TargetType>DYNLINK</TargetType>
+        <LinkSubsystem>windows</LinkSubsystem>
+        <PogoOptimized>true</PogoOptimized>
+        <DllEntryPoint>_DllMainCRTStartup</DllEntryPoint>
+        <Win32DllLibs>$(ClrLibPath)\utilcodestaticnohost.lib</Win32DllLibs>
+        <UseMsvcrt>false</UseMsvcrt>
+        <NoLinkGdi32>true</NoLinkGdi32>
+    </PropertyGroup>
+
+    <ItemGroup>
+        <TargetLib Include="$(SdkLibPath)\mscoree.lib" />
+        <TargetLib Include="$(SdkLibPath)\oleaut32.lib" />
+        <TargetLib Include="$(SdkLibPath)\uuid.lib" />
+        <TargetLib Include="$(SdkLibPath)\kernel32.lib" />
+        <TargetLib Include="$(SdkLibPath)\advapi32.lib" />
+        <TargetLib Include="$(SdkLibPath)\user32.lib" />
+        <TargetLib Include="$(SdkLibPath)\shlwapi.lib" />
+        <ProjectReference Include="$(ClrSrcDirectory)utilcode\staticnohost\staticnohost.nativeproj"/>
+    </ItemGroup>
+    
+    <ItemGroup>
+        <RCResourceFile Include="..\Native.rc" />
+    </ItemGroup>
+    
+    <ItemGroup>
+        <CppCompile Include="wrapper.cpp" />
+    </ItemGroup>
+
+    <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/dlls/mscorpe/mscorpe/wrapper.cpp b/src/dlls/mscorpe/mscorpe/wrapper.cpp
new file mode 100644 (file)
index 0000000..c5822cd
--- /dev/null
@@ -0,0 +1,150 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+// 
+// File: wrapper.cpp
+// 
+
+// 
+// This file implements a simple wrapper DLL (mscorpe.dll) which calls properly into mscorpehost.dll.
+// It exists because of compatibility with 1.x/2.0 apps running on CLR 4.0+. Such older apps could pass 
+// full path to LoadLibrary() Windows API and get this DLL.
+// 
+// Noone in CLR should ever try to load this DLL directly (using LoadLibrary API). Note that hosting APIs 
+// and PInvoke redirect mscorpe.dll to mscorpehost.dll automatically.
+// 
+
+#include <MscorpeSxSWrapper.h>
+
+#include <mscoree.h>
+#include <metahost.h>
+
+// Globals
+HINSTANCE g_hThisInst;  // This library.
+
+//*****************************************************************************
+// Handle lifetime of loaded library.
+//*****************************************************************************
+extern "C"
+BOOL WINAPI 
+DllMain(
+    HINSTANCE hInstance, 
+    DWORD     dwReason, 
+    LPVOID    lpReserved)
+{
+    switch (dwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+        {   // Save the module handle.
+            g_hThisInst = hInstance;
+            DisableThreadLibraryCalls((HMODULE)hInstance);
+        }
+        break;
+    case DLL_PROCESS_DETACH:
+        break;
+    }
+
+    return TRUE;
+} // DllMain
+
+// Implementation for utilcode
+HINSTANCE 
+GetModuleInst()
+{
+    return g_hThisInst;
+} // GetModuleInst
+
+// Load correct SxS version of mscorpe.dll and initialize it (uses shim).
+HRESULT 
+LoadMscorpe(HMODULE * phModule)
+{
+    HRESULT hr = S_OK;
+    ICLRMetaHost *    pMetaHost = NULL;
+    ICLRRuntimeInfo * pCLRRuntimeInfo = NULL;
+    
+    // Get full DLL path
+    WCHAR wszPath[_MAX_PATH];
+    DWORD dwLength = GetModuleFileName((HMODULE)g_hThisInst, wszPath, NumItems(wszPath));
+    
+    if ((dwLength == 0) || 
+        ((dwLength == NumItems(wszPath)) && 
+         (GetLastError() == ERROR_INSUFFICIENT_BUFFER)))
+    {
+        IfFailGo(CLR_E_SHIM_RUNTIMELOAD);
+    }
+    
+    // Find start of '\mscorpe.dll'
+    LPWSTR wszSeparator = wcsrchr(wszPath, L'\\');
+    if (wszSeparator == NULL)
+    {
+        IfFailGo(CLR_E_SHIM_RUNTIMELOAD);
+    }
+    // Check the name of this DLL
+    _ASSERTE(_wcsicmp(wszSeparator, L"\\mscorpe.dll") == 0);
+    // Remove the DLL name
+    *wszSeparator = 0;
+
+    // Find start of last directory name (\<version>),
+    // C:\Windows\Microsoft.NET\Framework\[[v4.0.12345]]\mscorpe.dll
+    LPWSTR wszLastDirectoryName = wcsrchr(wszPath, L'\\');
+    if (wszLastDirectoryName == NULL)
+    {
+        IfFailGo(CLR_E_SHIM_RUNTIMELOAD);
+    }
+    LPWSTR wszVersion = wszLastDirectoryName + 1;
+    
+    IfFailGo(CLRCreateInstance(
+        CLSID_CLRMetaHost, 
+        IID_ICLRMetaHost, 
+        reinterpret_cast<LPVOID *>(&pMetaHost)));
+    
+    IfFailGo(pMetaHost->GetRuntime(
+        wszVersion, 
+        IID_ICLRRuntimeInfo, 
+        reinterpret_cast<LPVOID *>(&pCLRRuntimeInfo)));
+    
+    // Shim will load correct SxS version of mscorpe.dll and will initialize it
+    IfFailGo(pCLRRuntimeInfo->LoadLibrary(
+        L"mscorpe.dll", 
+        phModule));
+    
+ErrExit:
+    if (pMetaHost != NULL)
+    {
+        pMetaHost->Release();
+        pMetaHost = NULL;
+    }
+    if (pCLRRuntimeInfo != NULL)
+    {
+        pCLRRuntimeInfo->Release();
+        pCLRRuntimeInfo = NULL;
+    }
+    
+    if (FAILED(hr))
+    {
+        *phModule = NULL;
+    }
+    
+    return hr;
+} // LoadMscorpe
+
+// SxS wrapper of mscorpe.dll entrypoints
+typedef MscorpeSxSWrapper<LoadMscorpe> MscorpeSxS;
+
+// Export of 'original' 1.x/2.0 mscorpe.dll
+EXTERN_C 
+HRESULT __stdcall 
+CreateICeeFileGen(
+    ICeeFileGen ** ppCeeFileGen)
+{
+    return MscorpeSxS::CreateICeeFileGen(ppCeeFileGen);
+}
+
+// Export of 'original' 1.x/2.0 mscorpe.dll
+EXTERN_C 
+HRESULT __stdcall 
+DestroyICeeFileGen(ICeeFileGen ** ppCeeFileGen)
+{
+    return MscorpeSxS::DestroyICeeFileGen(ppCeeFileGen);
+}
diff --git a/src/dlls/mscorpe/mscorpehost/mscorpehost.def b/src/dlls/mscorpe/mscorpehost/mscorpehost.def
new file mode 100644 (file)
index 0000000..e10fc1b
--- /dev/null
@@ -0,0 +1,12 @@
+;
+; Copyright (c) Microsoft. All rights reserved.
+; Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+;
+; PeWriter.def for PeWriter.dll
+; PE file generator in EE
+
+EXPORTS
+     CreateICeeFileGen
+     DestroyICeeFileGen
+     InitializeSxS
+
diff --git a/src/dlls/mscorpe/mscorpehost/mscorpehost.nativeproj b/src/dlls/mscorpe/mscorpehost/mscorpehost.nativeproj
new file mode 100644 (file)
index 0000000..45af39f
--- /dev/null
@@ -0,0 +1,68 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+    <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+
+    <PropertyGroup>
+        <LibCLib>$(ClrCrtLib)</LibCLib>
+        <OutputName>mscorpehost</OutputName>
+        <FileToMarkForSigning>$(BinariesDirectory)\$(OutputName).dll</FileToMarkForSigning>
+        <OutputLibPath>$(IntermediateOutputDirectory)</OutputLibPath>
+        <DllDef>$(OutputName).def</DllDef>
+        <TargetType>DYNLINK</TargetType>
+        <PCHHeader>stdafx.h</PCHHeader>
+        <EnableCxxPCHHeaders>true</EnableCxxPCHHeaders>
+        <PCHCompile>..\stdafx.cpp</PCHCompile>   
+        <UserIncludes>
+            $(UserIncludes);
+            .;
+            ../../vm
+        </UserIncludes>
+        <CDefines>$(CDefines);__TODO_PORT_TO_WRAPPERS__;UNICODE</CDefines>
+        <LinkSubsystem>windows</LinkSubsystem>
+        <PogoOptimized>true</PogoOptimized>
+        <DllEntryPoint>_DllMainCRTStartup</DllEntryPoint>  
+        <ExtDelayImpLib>false</ExtDelayImpLib>
+    </PropertyGroup>
+
+    <PropertyGroup>
+        <LinkDelayLoad Condition="'$(LinkDelayLoad)'!=''">$(LinkDelayLoad);</LinkDelayLoad>
+        <LinkDelayLoad>$(LinkDelayLoad)ole32.dll</LinkDelayLoad>
+    </PropertyGroup>
+    
+    <ItemGroup>
+        <CppCompile Include="..\utilcodeinit.cpp" />
+    </ItemGroup>
+
+    <ItemGroup>
+        <LinkPreCrtLibs Include="$(ClrLibPath)\utilcode.lib">
+            <ProjectReference>$(ClrSrcDirectory)utilcode\dyncrt\dyncrt.nativeproj</ProjectReference>
+        </LinkPreCrtLibs>
+
+        <TargetLib Include="$(SdkLibPath)\mscoree.lib" />
+        <TargetLib Include="$(ClrLibPath)\ceefgen.lib">
+            <ProjectReference>$(ClrSrcDirectory)md\ceefilegen\ceefgen.nativeproj</ProjectReference>
+        </TargetLib>
+        <TargetLib Include="$(ClrLibPath)\delayimp.lib">
+            <ProjectReference>$(ClrSrcDirectory)delayimp\delayimp.nativeproj</ProjectReference>
+        </TargetLib>
+        <TargetLib Include="$(SdkLibPath)\ole32.lib" />
+        <TargetLib Include="$(SdkLibPath)\oleaut32.lib" />
+        <TargetLib Include="$(SdkLibPath)\uuid.lib" />
+        <TargetLib Include="$(SdkLibPath)\kernel32.lib" />
+        <TargetLib Include="$(SdkLibPath)\advapi32.lib" />
+        <TargetLib Include="$(SdkLibPath)\user32.lib" />
+        <TargetLib Include="$(SdkLibPath)\shlwapi.lib" />
+    </ItemGroup>
+    
+    <ItemGroup>
+        <RCResourceFile Include="..\Native.rc" />
+    </ItemGroup>
+    
+    <ItemGroup>
+        <CppCompile Include="..\ICeeFileGen.cpp" />
+        <CppCompile Include="..\CeeFileGenWriter.cpp" />
+        <CppCompile Include="..\PEWriter.cpp" />
+        <CppCompile Include="..\CeeFileGenWriterTokens.cpp" />
+    </ItemGroup>
+    
+    <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/dlls/mscorpe/pewriter.cpp b/src/dlls/mscorpe/pewriter.cpp
new file mode 100644 (file)
index 0000000..7494ad9
--- /dev/null
@@ -0,0 +1,2401 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+#include "stdafx.h"
+
+#include "blobfetcher.h"
+#include "pedecoder.h"
+
+#ifdef _DEBUG
+#define LOGGING
+#endif
+
+#ifdef LOGGING
+#include "log.h"
+
+static const char* const RelocName[] = {
+    "Absolute", "Unk1",    "Unk2",    "HighLow", "Unk4", "MapToken",
+    "Relative", "FilePos", "CodeRel", "Movl64",  "Dir64", "PcRel25", "PcRel64",
+    "AbsTag" };
+static const char RelocSpaces[] = "        ";
+
+static INT64 s_minPcRel25;
+static INT64 s_maxPcRel25;
+#endif
+
+#ifdef EnC_SUPPORTED
+#define ENC_DELTA_HACK
+#endif
+
+    /* This is the stub program that says it can't be run in DOS mode */
+    /* it is x86 specific, but so is dos so I suppose that is OK */
+static const unsigned char x86StubPgm[] = {
+    0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
+    0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
+    0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
+    0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+    /* number of pad bytes to make 'len' bytes align to 'align' */
+inline static unsigned roundUp(unsigned len, unsigned align) {
+    return((len + align-1) & ~(align-1));
+}
+
+inline static unsigned padLen(unsigned len, unsigned align) {
+    return(roundUp(len, align) - len);
+}
+
+inline static bool isExeOrDll(IMAGE_NT_HEADERS* ntHeaders) {
+    return ((ntHeaders->FileHeader.Characteristics & VAL16(IMAGE_FILE_EXECUTABLE_IMAGE)) != 0);
+}
+
+#ifndef IMAGE_DLLCHARACTERISTICS_NO_SEH
+#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x400
+#endif
+
+#ifndef IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
+#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE   0x0040
+#endif
+
+#ifndef IMAGE_DLLCHARACTERISTICS_NX_COMPAT
+#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT      0x0100
+#endif
+
+#define COPY_AND_ADVANCE(target, src, size) { \
+                            ::memcpy((void *) (target), (const void *) (src), (size)); \
+                            (char *&) (target) += (size); }
+
+/******************************************************************/
+int __cdecl relocCmp(const void* a_, const void* b_) {
+
+    const PESectionReloc* a = (const PESectionReloc*) a_;
+    const PESectionReloc* b = (const PESectionReloc*) b_;
+    return (a->offset > b->offset ? 1 : (a->offset == b->offset ? 0 : -1));
+}
+
+PERelocSection::PERelocSection(PEWriterSection *pBaseReloc)
+{
+   section = pBaseReloc;
+   relocPage = (unsigned) -1;
+   relocSize = 0;
+   relocSizeAddr = NULL;
+   pages = 0;
+
+#ifdef _DEBUG
+   lastRVA = 0;
+#endif
+}
+
+void PERelocSection::AddBaseReloc(unsigned rva, int type, unsigned short highAdj)
+{
+#ifdef _DEBUG
+    // Guarantee that we're adding relocs in strict increasing order.
+    _ASSERTE(rva > lastRVA);
+    lastRVA = rva;
+#endif
+
+    if (relocPage != (rva & ~0xFFF)) {
+        if (relocSizeAddr) {
+            if ((relocSize & 1) == 1) {     // pad to an even number
+                short *ps = (short*) section->getBlock(2);
+                if(ps) {
+                    *ps = 0;
+                    relocSize++;
+                }
+            }
+            *relocSizeAddr = VAL32(relocSize*2 + sizeof(IMAGE_BASE_RELOCATION));
+        }
+        IMAGE_BASE_RELOCATION* base = (IMAGE_BASE_RELOCATION*) section->getBlock(sizeof(IMAGE_BASE_RELOCATION));
+        if(base) {
+            relocPage = (rva & ~0xFFF);
+            relocSize = 0;
+            base->VirtualAddress = VAL32(relocPage);
+            // Size needs to be fixed up when we know it - save address here
+            relocSizeAddr = &base->SizeOfBlock;
+            pages++;
+        }
+    }
+
+    relocSize++;
+    unsigned short* offset = (unsigned short*) section->getBlock(2);
+    if(offset) {
+        *offset = VAL16((rva & 0xFFF) | (type << 12));
+    }
+}
+
+void PERelocSection::Finish(bool isPE32)
+{
+    // fixup the last reloc block (if there was one)
+    if (relocSizeAddr) {
+        if ((relocSize & 1) == 1) {     // pad to an even number
+            short* psh = (short*) section->getBlock(2);
+            if(psh)
+            {
+                *psh = 0;
+                relocSize++;
+            }
+        }
+        *relocSizeAddr = VAL32(relocSize*2 + sizeof(IMAGE_BASE_RELOCATION));
+    }
+}
+
+#define GET_UNALIGNED_INT32(_ptr)     ((INT32) GET_UNALIGNED_VAL32(_ptr))
+
+static inline HRESULT SignedFitsIn31Bits(INT64 immediate)
+{
+    INT64 hiBits = immediate >> 31;
+    if ((hiBits == 0) || (hiBits == -1))
+    {
+        return S_OK;
+    }
+    else
+    {
+        return E_FAIL;
+    }
+}
+
+static inline HRESULT UnsignedFitsIn32Bits(UINT64 immediate)
+{
+    UINT64 hiBits = immediate >> 32;
+    if (hiBits == 0)
+    {
+        return S_OK;
+    }
+    else
+    {
+        return E_FAIL;
+    }
+}
+
+static inline HRESULT AddOvf_RVA(DWORD& a, DWORD b)
+{
+    DWORD r = a + b; 
+    if (r < a)  // Check for overflow
+        return E_FAIL;
+    a = r;
+    return S_OK;
+}
+
+static inline HRESULT AddOvf_S_U32(INT64 & a, unsigned int b)
+{
+    INT64 r = a + b;
+    if (r < a)  // Check for overflow
+        return E_FAIL;
+    a = r;
+    return S_OK;
+}
+
+static inline HRESULT AddOvf_S_S32(INT64 & a, int b)
+{
+    INT64 r = a + b;
+    if ( ((r >= a) && (b >= 0)) ||
+         ((r <  a) && (b <  0))    )
+    {
+        a = r;
+        return S_OK;
+    }
+    return E_FAIL;
+}
+
+static inline HRESULT AddOvf_U_U32(UINT64 & a, unsigned int b)
+{
+    UINT64 r = a + b;
+    if (r < a)  // Check for overflow
+        return E_FAIL;
+    a = r;
+    return S_OK;
+}
+
+static inline HRESULT AddOvf_U_U(UINT64 & a, UINT64 b)
+{
+    UINT64 r = a + b;
+    if (r < a)  // Check for overflow
+        return E_FAIL;
+    a = r;
+    return S_OK;
+}
+
+static inline HRESULT SubOvf_S_U32(INT64 & a, unsigned int b)
+{
+    INT64 r = a - b;
+    if (r > a)  // Check for overflow
+        return E_FAIL;
+    a = r;
+    return S_OK;
+}
+
+static inline HRESULT SubOvf_S_U(INT64 & a, UINT64 b)
+{
+    INT64 r = a - b;
+    if (r > a)  // Check for overflow
+        return E_FAIL;
+    a = r;
+    return S_OK;
+}
+
+static inline HRESULT SubOvf_U_U32(UINT64 & a, unsigned int b)
+{
+    UINT64 r = a - b;
+    if (r > a)  // Check for overflow
+        return E_FAIL;
+    a = r;
+    return S_OK;
+}
+
+/* subtract two unsigned pointers yeilding a signed pointer sized int */
+static inline HRESULT SubOvf_U_U(INT64 & r, UINT64 a, UINT64 b)
+{
+    r = a - b;
+    if ( ((a >= b) && (r >= 0))  ||
+         ((a <  b) && (r <  0)))
+    {
+        return S_OK;
+    }
+    return E_FAIL;
+}
+
+
+/******************************************************************/
+/* apply the relocs for this section.
+*/
+
+HRESULT PEWriterSection::applyRelocs(IMAGE_NT_HEADERS  *  pNtHeaders,
+                                     PERelocSection    *  pBaseRelocSection,
+                                     CeeGenTokenMapper *  pTokenMapper,
+                                     DWORD                dataRvaBase,
+                                     DWORD                rdataRvaBase,
+                                     DWORD                codeRvaBase)
+{
+    HRESULT hr;
+
+    _ASSERTE(pBaseRelocSection); // need section to write relocs
+
+#ifdef LOGGING
+    // Ensure that if someone adds a value to CeeSectionRelocType in cor.h,
+    // that they also add an entry to RelocName.
+    static_assert_no_msg(NumItems(RelocName) == srRelocSentinel);
+#ifdef _DEBUG
+    for (unsigned int i = 0; i < srRelocSentinel; i++)
+    {
+        _ASSERTE(strlen(RelocName[i]) <= strlen(RelocSpaces));
+    }
+#endif // _DEBUG
+#endif // LOGGING
+
+    if (m_relocCur == m_relocStart)
+        return S_OK;
+
+    bool isPE32 = (pNtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC));
+
+#ifdef LOGGING
+    LOG((LF_ZAP, LL_INFO100000,
+         "APPLYING section relocs for section %s start RVA = 0x%x\n",
+         m_name, m_baseRVA));
+#endif
+
+    UINT64 imageBase = isPE32 ? VAL32(((IMAGE_NT_HEADERS32 *) pNtHeaders)->OptionalHeader.ImageBase)
+                              : VAL64(((IMAGE_NT_HEADERS64 *) pNtHeaders)->OptionalHeader.ImageBase);
+
+    // sort them to make the baseRelocs pretty
+    qsort(m_relocStart, (m_relocCur - m_relocStart), sizeof(PESectionReloc), relocCmp);
+
+    for (PESectionReloc * cur = m_relocStart; cur < m_relocCur; cur++)
+    {
+        _ASSERTE((cur->offset + 4) <= m_blobFetcher.GetDataLen());
+
+        int    curType      = cur->type;
+        DWORD  curOffset    = cur->offset;
+        bool   isRelocPtr   = ((curType & srRelocPtr) != 0);
+        bool   noBaseBaseReloc = ((curType & srNoBaseReloc) != 0);
+        UINT64 targetOffset = 0;
+        int    slotNum      = 0;
+        INT64  oldStarPos;
+
+        // If cur->section is NULL then this is a pointer outside the module. 
+        bool externalAddress = (cur->section == NULL);
+
+        curType &= ~(srRelocPtr | srNoBaseReloc);
+
+        /* If we see any srRelocHighLow's in a PE64 file we convert them into DIR64 relocs */
+        if (!isPE32 && (curType == srRelocHighLow))
+            curType = srRelocDir64;
+
+        /* If we have an IA64 instruction fixup then extract the slot number and adjust curOffset */
+        if ((curType == srRelocIA64PcRel25) || (curType == srRelocIA64Imm64) || (curType == srRelocIA64PcRel64))
+        {
+            _ASSERTE((curOffset & 0x3) == 0);
+            slotNum = (curOffset & 0xf) >> 2;
+            curOffset &= ~0xf;
+        }
+
+        DWORD curRVA = m_baseRVA;    // RVA in the PE image of the reloc site
+        IfFailRet(AddOvf_RVA(curRVA, curOffset));
+        DWORD UNALIGNED * pos = (DWORD *) m_blobFetcher.ComputePointer(curOffset);
+
+        PREFIX_ASSUME(pos != NULL);
+
+#ifdef LOGGING
+        LOG((LF_ZAP, LL_INFO1000000,
+             "   Reloc %s%s%s at %-7s+%04x (RVA=%08x) at" FMT_ADDR,
+             RelocName[curType], (isRelocPtr) ? "Ptr" : "   ",
+             &RelocSpaces[strlen(RelocName[curType])],
+             m_name, curOffset, curRVA, DBG_ADDR(pos)));
+#endif
+        //
+        // 'pos' is the site of the reloc
+        // Compute 'targetOffset' from pointer if necessary
+        //
+
+        if (isRelocPtr)
+        {
+            // Calculate the value of ptr to pass to computeOffset
+            char * ptr = (char *) pos;
+            
+            if (curType == srRelocRelative) {
+                // 
+                // Here we add sizeof(int) because we need to calculate 
+                // ptr as the true call target address (x86 pc-rel)
+                // We need to true call target address since pass it
+                // to computeOffset and this function would fall if
+                // the address we pass is before the start of a section
+                // 
+                oldStarPos   = (SSIZE_T) ptr;
+                IfFailRet(AddOvf_S_S32(oldStarPos, GET_UNALIGNED_INT32(pos)));
+                IfFailRet(AddOvf_S_U32(oldStarPos, sizeof(int)));
+                ptr          = (char *) oldStarPos;
+                targetOffset = externalAddress ? (size_t) ptr
+                                               : cur->section->computeOffset(ptr);
+                // We subtract off the four bytes that we added previous
+                // since the code below depends upon this
+                IfFailRet(SubOvf_U_U32(targetOffset, sizeof(int)));
+                IfFailRet(UnsignedFitsIn32Bits(targetOffset));  // Check for overflow
+                SET_UNALIGNED_VAL32(pos, targetOffset);
+            }
+            else if (curType == srRelocIA64Imm64) {
+                _ASSERTE(slotNum == 1);
+                ptr = (char *) ((intptr_t) GetIA64Imm64((UINT64 *) ptr));
+                oldStarPos   = (SSIZE_T) ptr;
+                targetOffset = externalAddress ? (size_t) ptr
+                                               : cur->section->computeOffset(ptr);
+                _ASSERTE(!isPE32);
+                PutIA64Imm64((UINT64 *)pos, targetOffset);
+            }
+            else if (curType == srRelocIA64PcRel64) {
+                _ASSERTE(slotNum == 1);
+                ptr = (char *) ((intptr_t) GetIA64Rel64((UINT64 *) ptr));
+                oldStarPos   = (SSIZE_T) ptr;
+                targetOffset = externalAddress ? (size_t) ptr
+                                               : cur->section->computeOffset(ptr);
+                _ASSERTE(!isPE32);
+                PutIA64Rel64((UINT64 *)pos, targetOffset);
+            }
+            else {
+                _ASSERTE(curType != srRelocIA64PcRel25);
+                ptr = (char *) GET_UNALIGNED_VALPTR(ptr);
+                oldStarPos   = (SSIZE_T) ptr;
+                targetOffset = externalAddress ? (size_t) ptr
+                                               : cur->section->computeOffset(ptr);
+                IfFailRet(UnsignedFitsIn32Bits(targetOffset));  // Check for overflow
+                SET_UNALIGNED_VAL32(pos, targetOffset);
+                /* Zero the upper 32-bits for a machine with 64-bit pointers */
+                if (!isPE32)
+                    SET_UNALIGNED_VAL32(pos+1, 0);
+            }
+        }
+#ifdef LOGGING
+        else
+        {
+            if (curType == srRelocIA64PcRel25)
+            {
+                oldStarPos = GetIA64Rel25((UINT64 *) pos, slotNum);
+            }
+            else
+            {
+                if (curType == srRelocIA64PcRel64)
+                {
+                    _ASSERTE(slotNum == 1);
+                    oldStarPos = GetIA64Rel64((UINT64 *) pos);
+                }
+                else if (curType == srRelocIA64Imm64)
+                {
+                    oldStarPos = GetIA64Imm64((UINT64 *)pos);
+                }
+                else
+                {
+                    oldStarPos = GET_UNALIGNED_VAL32(pos);
+                }
+            }
+        }
+#endif
+
+        //
+        // 'targetOffset' has now been computed. Write out the appropriate value.
+        // Record base relocs as necessary.
+        //
+
+        bool  fBaseReloc = false;
+        bool  fNeedBrl   = false;
+        INT64 newStarPos = 0; // oldStarPos gets updated to newStarPos
+
+        if (curType == srRelocAbsolute || curType == srRelocAbsoluteTagged) {
+            _ASSERTE(!externalAddress);
+
+            newStarPos = GET_UNALIGNED_INT32(pos);
+
+            if (curType == srRelocAbsoluteTagged)
+                newStarPos = (newStarPos & ~0x80000001) >> 1;
+
+            if (rdataRvaBase > 0 && ! strcmp((const char *)(cur->section->m_name), ".rdata"))
+                IfFailRet(AddOvf_S_U32(newStarPos, rdataRvaBase));
+            else if (dataRvaBase > 0 && ! strcmp((const char *)(cur->section->m_name), ".data"))
+                IfFailRet(AddOvf_S_U32(newStarPos, dataRvaBase));
+            else
+                IfFailRet(AddOvf_S_U32(newStarPos, cur->section->m_baseRVA));
+
+            if (curType == srRelocAbsoluteTagged)
+                newStarPos = (newStarPos << 1) | 0x80000001;
+
+            SET_UNALIGNED_VAL32(pos, newStarPos);
+        }
+        else if (curType == srRelocMapToken)
+        {
+            mdToken newToken;
+            if (pTokenMapper != NULL && pTokenMapper->HasTokenMoved((mdToken)GET_UNALIGNED_VAL32(pos), newToken)) {
+                // we have a mapped token
+                SET_UNALIGNED_VAL32(pos, newToken);
+            }
+            newStarPos = GET_UNALIGNED_VAL32(pos);
+        }
+        else if (curType == srRelocFilePos)
+        {
+            _ASSERTE(!externalAddress);
+            newStarPos = GET_UNALIGNED_VAL32(pos);
+            IfFailRet(AddOvf_S_U32(newStarPos, cur->section->m_filePos));
+            SET_UNALIGNED_VAL32(pos, newStarPos);
+        }
+        else if (curType == srRelocRelative)
+        {
+            if (externalAddress) {
+#if defined(_AMD64_)
+                newStarPos = GET_UNALIGNED_INT32(pos);
+#else  // x86
+                UINT64 targetAddr = GET_UNALIGNED_VAL32(pos);
+                IfFailRet(SubOvf_U_U(newStarPos, targetAddr, imageBase));
+#endif
+            }
+            else {
+                newStarPos = GET_UNALIGNED_INT32(pos);
+                IfFailRet(AddOvf_S_U32(newStarPos, cur->section->m_baseRVA));
+            }
+            IfFailRet(SubOvf_S_U32(newStarPos, curRVA));
+            IfFailRet(SignedFitsIn31Bits(newStarPos));  // Check for overflow
+            SET_UNALIGNED_VAL32(pos, newStarPos);
+        }
+        else if (curType == srRelocCodeRelative)
+        {
+            newStarPos = GET_UNALIGNED_INT32(pos);
+            IfFailRet(SubOvf_S_U32(newStarPos, codeRvaBase));
+            if (externalAddress)
+                IfFailRet(SubOvf_S_U(newStarPos, imageBase));
+            else
+                IfFailRet(AddOvf_S_U32(newStarPos, cur->section->m_baseRVA));
+            IfFailRet(SignedFitsIn31Bits(newStarPos));  // Check for overflow
+            SET_UNALIGNED_VAL32(pos, newStarPos);
+            
+        }
+        else if (curType == srRelocIA64PcRel25)
+        {
+            _ASSERTE((m_baseRVA & 15) == 0);
+            _ASSERTE((cur->section->m_baseRVA & 15) == 0);
+
+            newStarPos = GetIA64Rel25((UINT64 *) pos, slotNum);
+            IfFailRet(SubOvf_S_U32(newStarPos, curRVA));
+            if (externalAddress)
+                IfFailRet(SubOvf_S_U(newStarPos, imageBase));
+            else
+                IfFailRet(AddOvf_S_U32(newStarPos, cur->section->m_baseRVA));
+
+            INT64 hiBits = newStarPos >> 24;
+            
+            _ASSERTE((hiBits==0) || (hiBits==-1));
+            
+            IfFailRet(AddOvf_S_U32(newStarPos, GetIA64Rel25((UINT64 *) pos, slotNum)));
+
+            hiBits = newStarPos >> 24;
+            
+            _ASSERTE((hiBits==0) || (hiBits==-1));
+            
+            INT32 delta32 = (INT32) newStarPos;
+
+            PutIA64Rel25((UINT64 *) pos, slotNum, delta32);
+
+            _ASSERTE(GetIA64Rel25((UINT64 *) pos, slotNum) == delta32);
+
+#ifdef LOGGING
+            if (newStarPos < s_minPcRel25)
+                s_minPcRel25 = newStarPos;
+            if (newStarPos > s_maxPcRel25)
+                s_maxPcRel25 = newStarPos;
+#endif
+        }
+        else if (curType == srRelocIA64PcRel64)
+        {
+            _ASSERTE((m_baseRVA & 15) == 0);
+            _ASSERTE(slotNum == 1);
+
+            newStarPos = GetIA64Rel64((UINT64 *) pos);
+            IfFailRet(SubOvf_S_U32(newStarPos, m_baseRVA));
+            
+            if (externalAddress)
+                IfFailRet(SubOvf_S_U(newStarPos, imageBase));
+            else
+            {
+                _ASSERTE((cur->section->m_baseRVA & 15) == 0);
+                IfFailRet(AddOvf_S_U32(newStarPos, cur->section->m_baseRVA));
+            }
+
+            INT64 hiBits = newStarPos >> 24;
+
+            fNeedBrl = (hiBits != 0) && (hiBits != -1);
+
+            /* Can we convert the brl.call into a br.call? */
+            if (!fNeedBrl)
+            {
+                INT32 delta32 = (INT32) newStarPos;
+
+                UINT64  temp0 = ((UINT64 *) pos)[0];
+                UINT64  temp1 = ((UINT64 *) pos)[1];
+#ifdef _DEBUG
+                //
+                // make certain we're decoding a brl opcode, with template 4 or 5
+                //
+                UINT64  templa = (temp0 >>  0) & 0x1f;
+                UINT64  opcode = (temp1 >> 60) & 0xf;
+
+                _ASSERTE(((opcode == 0xC) || (opcode == 0xD)) &&
+                         ((templa == 0x4) || (templa == 0x5)));
+#endif
+                const UINT64 mask0 = UI64(0x00003FFFFFFFFFE1);
+                const UINT64 mask1 = UI64(0x7700000FFF800000);
+
+                /* Clear all bits used as part of the slot1 and slot2 */
+                temp0 &= mask0;   // opcode becomes 4 or 5
+                temp1 &= mask1;
+
+                temp0 |= 0x10;    // template becomes 0x10 or 0x11
+                temp1 |= 0x200;   // slot 1 becomes nop.i
+
+                ((UINT64 *) pos)[0] = temp0;
+                ((UINT64 *) pos)[1] = temp1;
+
+                PutIA64Rel25((UINT64 *) pos, 2, delta32);
+                _ASSERTE(GetIA64Rel25((UINT64 *) pos, 2) == delta32);
+            }
+            else
+            {
+                PutIA64Rel64((UINT64 *) pos, newStarPos);
+                _ASSERTE(GetIA64Rel64((UINT64 *) pos) == newStarPos);
+            }
+        }
+        else if (curType == srRelocHighLow)
+        {
+            _ASSERTE(isPE32);
+
+            // we have a 32-bit value at pos
+            UINT64 value = GET_UNALIGNED_VAL32(pos);
+
+            if (!externalAddress)
+            {
+                IfFailRet(AddOvf_U_U32(value, cur->section->m_baseRVA));
+                IfFailRet(AddOvf_U_U(value, imageBase));
+            }
+
+            IfFailRet(UnsignedFitsIn32Bits(value));  // Check for overflow
+            SET_UNALIGNED_VAL32(pos, value);
+
+            newStarPos = value;
+
+            fBaseReloc = true;
+        }
+        else if (curType == srRelocDir64)
+        {
+            _ASSERTE(!isPE32);
+
+            // we have a 64-bit value at pos
+            UINT64 UNALIGNED * p_value = (UINT64 *) pos;
+            targetOffset = *p_value;
+
+            if (!externalAddress)
+            {
+                // The upper bits of targetOffset must be zero
+                IfFailRet(UnsignedFitsIn32Bits(targetOffset));            
+
+                IfFailRet(AddOvf_U_U32(targetOffset, cur->section->m_baseRVA));
+                IfFailRet(AddOvf_U_U(targetOffset, imageBase));
+            }
+
+            *p_value   = targetOffset;
+            newStarPos = targetOffset;
+            fBaseReloc = true;
+        }
+        else if (curType == srRelocIA64Imm64)
+        {
+            _ASSERTE(!isPE32);
+            _ASSERTE((curRVA & 15) == 0);       // This reloc should be 16-byte aligned
+
+            // we have a 64-bit value encoded in the instruction at pos
+            targetOffset = GetIA64Imm64((UINT64 *)pos);
+
+            if (!externalAddress)
+            {
+                // The upper bits of targetOffset must be zero
+                IfFailRet(UnsignedFitsIn32Bits(targetOffset));            
+            
+                IfFailRet(AddOvf_U_U32(targetOffset, cur->section->m_baseRVA));
+                IfFailRet(AddOvf_U_U(targetOffset, imageBase));
+            }
+
+            PutIA64Imm64((UINT64 *)pos, targetOffset);
+            newStarPos = targetOffset;
+            fBaseReloc = true;
+        }
+        else
+        {
+            _ASSERTE(!"Unknown Relocation type");
+        }
+
+        if (fBaseReloc && !noBaseBaseReloc)
+        {
+            pBaseRelocSection->AddBaseReloc(curRVA, curType);
+        }
+
+#ifdef LOGGING
+        const char* sectionName;
+
+        if (externalAddress)
+        {
+            sectionName = "external";
+        }
+        else
+        {
+            sectionName = cur->section->m_name;
+        }
+
+        LOG((LF_ZAP, LL_INFO1000000,
+             "to %-7s+%04x, old =" FMT_ADDR "new =" FMT_ADDR "%s%s\n",
+             sectionName, targetOffset,
+             DBG_ADDR(oldStarPos), DBG_ADDR(newStarPos),
+             fBaseReloc ? "(BASE RELOC)" : "",
+             fNeedBrl   ? "(BRL)"        : ""  ));
+#endif
+
+    }
+    return S_OK;
+}
+
+/******************************************************************/
+
+PESeedSection::PESeedSection(PEDecoder * peDecoder,
+                             IMAGE_SECTION_HEADER * seedSection)
+  : PEWriterSection((const char *)seedSection->Name,
+              VAL32(seedSection->Characteristics),
+              VAL32(seedSection->SizeOfRawData),
+              0),
+    m_pSeedFileDecoder(peDecoder),
+    m_pSeedSectionHeader(seedSection)
+{
+    m_baseRVA = VAL32(seedSection->VirtualAddress);
+}
+
+HRESULT  PESeedSection::write(HANDLE file) {
+    ULONG sizeOfSection = VAL32(m_pSeedSectionHeader->SizeOfRawData);
+    LPCVOID sectionData = PBYTE(m_pSeedFileDecoder->GetBase()) + m_pSeedSectionHeader->PointerToRawData;
+
+    DWORD dwWritten = 0;
+    if (!WriteFile(file, sectionData, sizeOfSection, &dwWritten, NULL)) {
+        return HRESULT_FROM_GetLastError();
+    }
+    _ASSERTE(dwWritten == sizeOfSection);
+    return S_OK;
+}
+
+unsigned PESeedSection::writeMem(void ** pMem) {
+    ULONG sizeOfSection = VAL32(m_pSeedSectionHeader->SizeOfRawData);
+    LPCVOID sectionData = PBYTE(m_pSeedFileDecoder->GetBase()) + m_pSeedSectionHeader->PointerToRawData;
+
+    COPY_AND_ADVANCE(*pMem, sectionData, sizeOfSection);
+    return sizeOfSection;
+}
+
+/******************************************************************/
+HRESULT PEWriter::Init(PESectionMan *pFrom, DWORD createFlags, LPCWSTR seedFileName)
+{
+    if (pFrom)
+        *(PESectionMan*)this = *pFrom;
+    else {
+        HRESULT hr = PESectionMan::Init();
+        if (FAILED(hr))
+            return hr;
+    }
+    time_t now;
+    time(&now);
+
+#ifdef LOGGING
+    InitializeLogging();
+#endif
+
+    // Save the timestamp so that we can give it out if someone needs
+    // it.
+    m_peFileTimeStamp = (DWORD) now;
+
+    // We must be creating either a PE32 or a PE64 file
+    if (createFlags & ICEE_CREATE_FILE_PE64)
+    {
+        m_ntHeaders     = (IMAGE_NT_HEADERS *) new (nothrow) IMAGE_NT_HEADERS64;
+        m_ntHeadersSize = sizeof(IMAGE_NT_HEADERS64);
+
+        if (!m_ntHeaders) return E_OUTOFMEMORY;
+        memset(m_ntHeaders, 0, m_ntHeadersSize);
+
+        m_ntHeaders->OptionalHeader.Magic = VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC);
+        m_ntHeaders->FileHeader.SizeOfOptionalHeader = VAL16(sizeof(IMAGE_OPTIONAL_HEADER64));
+    }
+    else
+    {
+        _ASSERTE(createFlags & ICEE_CREATE_FILE_PE32);
+        m_ntHeaders     = (IMAGE_NT_HEADERS *) new (nothrow) IMAGE_NT_HEADERS32;
+        m_ntHeadersSize = sizeof(IMAGE_NT_HEADERS32);
+
+        if (!m_ntHeaders) return E_OUTOFMEMORY;
+        memset(m_ntHeaders, 0, m_ntHeadersSize);
+
+        m_ntHeaders->OptionalHeader.Magic = VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC);
+        m_ntHeaders->FileHeader.SizeOfOptionalHeader = VAL16(sizeof(IMAGE_OPTIONAL_HEADER32));
+    }
+
+    // Record whether we should create the CorExeMain and CorDllMain stubs
+    m_createCorMainStub = ((createFlags & ICEE_CREATE_FILE_CORMAIN_STUB) != 0);
+
+    // We must have a valid target machine selected
+    if ((createFlags & ICEE_CREATE_MACHINE_MASK) == ICEE_CREATE_MACHINE_I386)
+    {
+        m_ntHeaders->FileHeader.Machine = VAL16(IMAGE_FILE_MACHINE_I386);
+    }
+    else if ((createFlags & ICEE_CREATE_MACHINE_MASK) == ICEE_CREATE_MACHINE_IA64)
+    {
+        m_ntHeaders->FileHeader.Machine = VAL16(IMAGE_FILE_MACHINE_IA64);
+    }
+    else if ((createFlags & ICEE_CREATE_MACHINE_MASK) == ICEE_CREATE_MACHINE_AMD64)
+    {
+        m_ntHeaders->FileHeader.Machine = VAL16(IMAGE_FILE_MACHINE_AMD64);
+    }
+    else if ((createFlags & ICEE_CREATE_MACHINE_MASK) == ICEE_CREATE_MACHINE_ARM)
+    {
+        m_ntHeaders->FileHeader.Machine = VAL16(IMAGE_FILE_MACHINE_ARMNT);
+
+        // The OS loader already knows how to initialize pure managed assemblies and we have no legacy OS
+        // support to worry about on ARM so don't ever create the stub for ARM binaries.
+        m_createCorMainStub = false;
+    }
+    else
+    {
+        _ASSERTE(!"Invalid target machine");
+    }
+
+    cEntries = IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR + 1;
+    pEntries = new (nothrow) directoryEntry[cEntries];
+    if (pEntries == NULL) return E_OUTOFMEMORY;
+    memset(pEntries, 0, sizeof(*pEntries) * cEntries);
+
+    m_ntHeaders->Signature                       = VAL32(IMAGE_NT_SIGNATURE);
+    m_ntHeaders->FileHeader.TimeDateStamp        = VAL32((ULONG) now);
+    m_ntHeaders->FileHeader.Characteristics      = VAL16(0);
+
+    if (createFlags & ICEE_CREATE_FILE_STRIP_RELOCS)
+    {
+        m_ntHeaders->FileHeader.Characteristics |= VAL16(IMAGE_FILE_RELOCS_STRIPPED);
+    }
+    
+    // Linker version should be consistent with current VC level
+    m_ntHeaders->OptionalHeader.MajorLinkerVersion  = 11;
+    m_ntHeaders->OptionalHeader.MinorLinkerVersion  = 0;
+
+    m_ntHeaders->OptionalHeader.SectionAlignment    = VAL32(IMAGE_NT_OPTIONAL_HDR_SECTION_ALIGNMENT);
+    m_ntHeaders->OptionalHeader.FileAlignment       = VAL32(0);
+    m_ntHeaders->OptionalHeader.AddressOfEntryPoint = VAL32(0);
+
+    m_ntHeaders->OptionalHeader.MajorOperatingSystemVersion = VAL16(4);
+    m_ntHeaders->OptionalHeader.MinorOperatingSystemVersion = VAL16(0);
+
+    m_ntHeaders->OptionalHeader.MajorImageVersion     = VAL16(0);
+    m_ntHeaders->OptionalHeader.MinorImageVersion     = VAL16(0);
+    m_ntHeaders->OptionalHeader.MajorSubsystemVersion = VAL16(4);
+    m_ntHeaders->OptionalHeader.MinorSubsystemVersion = VAL16(0);
+    m_ntHeaders->OptionalHeader.Win32VersionValue     = VAL32(0);
+    m_ntHeaders->OptionalHeader.Subsystem             = VAL16(0);
+    m_ntHeaders->OptionalHeader.DllCharacteristics    = VAL16(0);
+    m_ntHeaders->OptionalHeader.CheckSum              = VAL32(0);
+    setDllCharacteristics(IMAGE_DLLCHARACTERISTICS_NO_SEH |
+                          IMAGE_DLLCHARACTERISTICS_NX_COMPAT |
+                          IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
+                          IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE);
+
+    if (isPE32())
+    {
+        IMAGE_NT_HEADERS32*  p_ntHeaders32 = ntHeaders32();
+        p_ntHeaders32->OptionalHeader.ImageBase             = VAL32(CEE_IMAGE_BASE_32);
+        p_ntHeaders32->OptionalHeader.SizeOfStackReserve    = VAL32(0x100000);
+        p_ntHeaders32->OptionalHeader.SizeOfStackCommit     = VAL32(0x1000);
+        p_ntHeaders32->OptionalHeader.SizeOfHeapReserve     = VAL32(0x100000);
+        p_ntHeaders32->OptionalHeader.SizeOfHeapCommit      = VAL32(0x1000);
+        p_ntHeaders32->OptionalHeader.LoaderFlags           = VAL32(0);
+        p_ntHeaders32->OptionalHeader.NumberOfRvaAndSizes   = VAL32(16);
+    }
+    else
+    {
+        IMAGE_NT_HEADERS64*  p_ntHeaders64 = ntHeaders64();
+        // FIX what are the correct values for PE+ (64-bit) ?
+        p_ntHeaders64->OptionalHeader.ImageBase             = VAL64(CEE_IMAGE_BASE_64);
+        p_ntHeaders64->OptionalHeader.SizeOfStackReserve    = VAL64(0x400000);
+        p_ntHeaders64->OptionalHeader.SizeOfStackCommit     = VAL64(0x4000);
+        p_ntHeaders64->OptionalHeader.SizeOfHeapReserve     = VAL64(0x100000);
+        p_ntHeaders64->OptionalHeader.SizeOfHeapCommit      = VAL64(0x2000);
+        p_ntHeaders64->OptionalHeader.LoaderFlags           = VAL32(0);
+        p_ntHeaders64->OptionalHeader.NumberOfRvaAndSizes   = VAL32(16);
+    }
+
+    m_ilRVA = (DWORD) -1;
+    m_dataRvaBase = 0;
+    m_rdataRvaBase = 0;
+    m_codeRvaBase = 0;
+    m_encMode = FALSE;
+
+    virtualPos = 0;
+    filePos = 0;
+    reloc = NULL;
+    strtab = NULL;
+    headers = NULL;
+    headersEnd = NULL;
+
+    m_file = INVALID_HANDLE_VALUE;
+
+    //
+    // Seed file
+    //
+
+    m_hSeedFile = INVALID_HANDLE_VALUE;
+    m_hSeedFileMap = INVALID_HANDLE_VALUE;
+    m_pSeedFileDecoder = NULL;
+    m_iSeedSections = 0;
+    m_pSeedSectionToAdd = NULL;
+
+    if (seedFileName)
+    {
+        HandleHolder hFile (WszCreateFile(seedFileName,
+                                     GENERIC_READ,
+                                     FILE_SHARE_READ,
+                                     NULL,
+                                     OPEN_EXISTING,
+                                     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                                     NULL));
+
+        if (hFile == INVALID_HANDLE_VALUE)
+            return HRESULT_FROM_GetLastError();
+
+        MapViewHolder hMapFile (WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL));
+        DWORD dwFileLen = SafeGetFileSize(hFile, 0);
+        if (dwFileLen == 0xffffffff)
+            return HRESULT_FROM_GetLastError();
+
+        if (hMapFile == NULL)
+            return HRESULT_FROM_GetLastError();
+
+        BYTE * baseFileView = (BYTE*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
+
+        PEDecoder * pPEDecoder = new (nothrow) PEDecoder(baseFileView, (COUNT_T)dwFileLen);
+        if (pPEDecoder == NULL) return E_OUTOFMEMORY;
+        
+        if (pPEDecoder->Has32BitNTHeaders())
+        {
+            if ((createFlags & ICEE_CREATE_FILE_PE32) == 0)
+                return E_FAIL;
+
+            setImageBase32(DWORD(size_t(pPEDecoder->GetPreferredBase())));
+        }
+        else
+        {
+            if ((createFlags & ICEE_CREATE_FILE_PE64) == 0)
+                return E_FAIL;
+
+            setImageBase64(UINT64((intptr_t) pPEDecoder->GetPreferredBase()));
+        }
+
+        setFileAlignment   (VAL32(pPEDecoder->GetFileAlignment()));
+        setSectionAlignment(VAL32(pPEDecoder->GetSectionAlignment()));
+
+        hFile.SuppressRelease();
+        hMapFile.SuppressRelease();
+        
+        m_hSeedFile = hFile;
+        m_hSeedFileMap = hMapFile;
+        m_pSeedFileDecoder = pPEDecoder;
+
+#ifdef  _WIN64       
+        m_pSeedFileNTHeaders = pPEDecoder->GetNTHeaders64();
+#else
+        m_pSeedFileNTHeaders = pPEDecoder->GetNTHeaders32();
+#endif
+
+        // Add the seed sections
+
+        m_pSeedSections = m_pSeedFileDecoder->FindFirstSection();
+
+        m_pSeedSectionToAdd = m_pSeedSections;
+        m_iSeedSections = m_pSeedFileDecoder->GetNumberOfSections();
+
+        for (unsigned i = 0; i < m_iSeedSections; m_pSeedSectionToAdd++, i++) {
+            PESection * dummy;
+            getSectionCreate((const char *)(m_pSeedSectionToAdd->Name),
+                VAL32(m_pSeedSectionToAdd->Characteristics),
+                &dummy);
+        }
+
+        m_pSeedSectionToAdd = NULL;
+    }
+
+    return S_OK;
+}
+
+/******************************************************************/
+HRESULT PEWriter::Cleanup() {
+
+    if (m_hSeedFile != INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(m_hSeedFile);
+        CloseHandle(m_hSeedFileMap);
+        delete m_pSeedFileDecoder;
+    }
+
+    if (isPE32())
+    {
+        delete ntHeaders32();
+    }
+    else
+    {
+        delete ntHeaders64();
+    }
+
+    if (headers != NULL)
+        delete [] headers;
+
+    if (pEntries != NULL)
+        delete [] pEntries;
+
+    return PESectionMan::Cleanup();
+}
+
+PESection* PEWriter::getSection(const char* name)
+{
+    int     len = (int)strlen(name);
+
+    // the section name can be at most 8 characters including the null.
+    if (len < 8)
+        len++;
+    else
+        len = 8;
+
+    // dbPrintf(("looking for section %s\n", name));
+    // Skip over the seed sections
+
+    for(PESection** cur = sectStart+m_iSeedSections; cur < sectCur; cur++) {
+        // dbPrintf(("searching section %s\n", (*cur)->m_ame));
+        if (strncmp((*cur)->m_name, name, len) == 0) {
+            // dbPrintf(("found section %s\n", (*cur)->m_name));
+            return(*cur);
+        }
+    }
+    return(0);
+}
+
+HRESULT PEWriter::newSection(const char* name, PESection **section,
+                            unsigned flags, unsigned estSize,
+                            unsigned estRelocs)
+{
+    if (m_pSeedSectionToAdd) {
+        _ASSERTE(strcmp((const char *)(m_pSeedSectionToAdd->Name), name) == 0 &&
+            VAL32(m_pSeedSectionToAdd->Characteristics) == flags);
+
+        PESeedSection * ret = new (nothrow) PESeedSection(m_pSeedFileDecoder, m_pSeedSectionToAdd);
+        *section = ret;
+        TESTANDRETURNMEMORY(ret);
+        return S_OK;
+    }
+
+    PEWriterSection * ret = new (nothrow) PEWriterSection(name, flags, estSize, estRelocs);
+    *section = ret;
+    TESTANDRETURNMEMORY(ret);
+    return S_OK;
+}
+
+ULONG PEWriter::getIlRva()
+{
+    // assume that pe optional header is less than size of section alignment. So this
+    // gives out the rva for the .text section, which is merged after the .text0 section
+    // This is verified in debug build when actually write out the file
+    _ASSERTE(m_ilRVA > 0);
+    return m_ilRVA;
+}
+
+void PEWriter::setIlRva(ULONG offset)
+{
+    // assume that pe optional header is less than size of section alignment. So this
+    // gives out the rva for the .text section, which is merged after the .text0 section
+    // This is verified in debug build when actually write out the file
+    m_ilRVA = roundUp(VAL32(m_ntHeaders->OptionalHeader.SectionAlignment) + offset, SUBSECTION_ALIGN);
+}
+
+HRESULT PEWriter::setDirectoryEntry(PEWriterSection *section, ULONG entry, ULONG size, ULONG offset)
+{
+    if (entry >= cEntries)
+    {
+        USHORT cNewEntries = (USHORT)max((ULONG)cEntries * 2, entry + 1);
+
+        if (cNewEntries <= cEntries) return E_OUTOFMEMORY;  // Integer overflow
+        if (cNewEntries <= entry) return E_OUTOFMEMORY;  // Integer overflow
+
+        directoryEntry *pNewEntries = new (nothrow) directoryEntry [ cNewEntries ];
+        if (pNewEntries == NULL) return E_OUTOFMEMORY;
+
+        CopyMemory(pNewEntries, pEntries, cEntries * sizeof(*pNewEntries));
+        ZeroMemory(pNewEntries + cEntries, (cNewEntries - cEntries) * sizeof(*pNewEntries));
+
+        delete [] pEntries;
+        pEntries = pNewEntries;
+        cEntries = cNewEntries;
+    }
+
+    pEntries[entry].section = section;
+    pEntries[entry].offset = offset;
+    pEntries[entry].size = size;
+    return S_OK;
+}
+
+void PEWriter::setEnCRvaBase(ULONG dataBase, ULONG rdataBase)
+{
+    m_dataRvaBase = dataBase;
+    m_rdataRvaBase = rdataBase;
+    m_encMode = TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// These 2 write functions must be implemented here so that they're in the same
+// .obj file as whoever creates the FILE struct. We can't pass a FILE struct
+// across a dll boundary and use it.
+//-----------------------------------------------------------------------------
+
+HRESULT PEWriterSection::write(HANDLE file)
+{
+    return m_blobFetcher.Write(file);
+}
+
+//-----------------------------------------------------------------------------
+// Write out the section to the stream
+//-----------------------------------------------------------------------------
+HRESULT CBlobFetcher::Write(HANDLE file)
+{
+// Must write out each pillar (including idx = m_nIndexUsed), one after the other
+    unsigned idx;
+    for(idx = 0; idx <= m_nIndexUsed; idx ++) {
+        if (m_pIndex[idx].GetDataLen() > 0)
+        {
+            ULONG length = m_pIndex[idx].GetDataLen();
+            DWORD dwWritten = 0;
+            if (!WriteFile(file, m_pIndex[idx].GetRawDataStart(), length, &dwWritten, NULL))
+            {
+                return HRESULT_FROM_GetLastError();
+            }
+            _ASSERTE(dwWritten == length);
+        }
+    }
+
+    return S_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// These 2 write functions must be implemented here so that they're in the same
+// .obj file as whoever creates the FILE struct. We can't pass a FILE struct
+// across a dll boundary  and use it.
+//-----------------------------------------------------------------------------
+
+unsigned PEWriterSection::writeMem(void **ppMem)
+{
+    HRESULT hr;
+    hr = m_blobFetcher.WriteMem(ppMem);
+    _ASSERTE(SUCCEEDED(hr));
+
+    return m_blobFetcher.GetDataLen();
+}
+
+//-----------------------------------------------------------------------------
+// Write out the section to memory
+//-----------------------------------------------------------------------------
+HRESULT CBlobFetcher::WriteMem(void **ppMem)
+{
+    char **ppDest = (char **)ppMem;
+    // Must write out each pillar (including idx = m_nIndexUsed), one after the other
+    unsigned idx;
+    for(idx = 0; idx <= m_nIndexUsed; idx ++) {
+        if (m_pIndex[idx].GetDataLen() > 0)
+        {
+            // WARNING: macro - must enclose in curly braces
+            COPY_AND_ADVANCE(*ppDest, m_pIndex[idx].GetRawDataStart(), m_pIndex[idx].GetDataLen());
+        }
+    }
+
+    return S_OK;
+}
+
+/******************************************************************/
+
+//
+// Intermediate table to sort to help determine section order
+//
+struct entry {
+    const char *    name;       // full name of the section
+    unsigned char   nameLength; // length of the text part of the name
+    signed char     index;      // numeral value at the end of the name; -1 if none
+    unsigned short  arrayIndex; // index of section within sectStart[]
+};
+
+class SectionNameSorter : protected CQuickSort<entry>
+{
+    entry *             m_entries;
+    PEWriterSection **  m_sections;
+    unsigned            m_count;
+    unsigned            m_seedCount;
+
+  public:
+    SectionNameSorter(entry *entries, PEWriterSection ** sections, int count, unsigned seedSections)
+      : CQuickSort<entry>(entries, count),
+        m_entries(entries),
+        m_sections(sections),
+        m_count(unsigned(count)),
+        m_seedCount(seedSections)
+    {}
+
+    // Sorts the entries according to alphabetical + numerical order
+
+    int Compare(entry *first, entry *second)
+    {
+        PEWriterSection * firstSection = m_sections[first->arrayIndex];
+        PEWriterSection * secondSection = m_sections[second->arrayIndex];
+
+        // Seed sections are always at the start, in the order they were
+        // added to the PEWriter
+
+        if (firstSection->isSeedSection() || secondSection->isSeedSection()) {
+            if (firstSection->isSeedSection() && secondSection->isSeedSection())
+                return first->arrayIndex - second->arrayIndex;
+
+            return firstSection->isSeedSection() ? -1 : 1;
+        }
+
+        // Sort the names
+
+        int lenDiff = first->nameLength - second->nameLength;
+        int smallerLen;
+        if (lenDiff < 0)
+            smallerLen = first->nameLength;
+        else
+            smallerLen = second->nameLength;
+
+        int result = strncmp(first->name, second->name, smallerLen);
+
+        if (result != 0)
+            return result;
+        else
+        {
+            if (lenDiff != 0)
+                return lenDiff;
+            else
+                return (int)(first->index - second->index);
+        }
+    }
+
+    int SortSections()
+    {
+        Sort();
+
+        entry * ePrev = m_entries;
+        entry * e = ePrev + 1;
+        int iSections = 1; // First section is obviously unique
+
+        for (unsigned i = 1; i < m_count; i++, ePrev = e, e++) {
+
+            // Seed sections should stay at the front
+            _ASSERTE(i >= m_seedCount || i == e->arrayIndex);
+
+            if (!m_sections[ePrev->arrayIndex]->isSeedSection() &&
+                (ePrev->nameLength == e->nameLength) &&
+                strncmp(ePrev->name, e->name, e->nameLength) == 0)
+            {
+                continue;
+            }
+
+            iSections++;
+        }
+
+        return iSections;
+    }
+};
+
+#define SectionIndex    IMAGE_SECTION_HEADER::VirtualAddress
+#define FirstEntryIndex IMAGE_SECTION_HEADER::SizeOfRawData
+
+HRESULT PEWriter::linkSortSections(entry * entries,
+                                   unsigned * piEntries,
+                                   unsigned * piUniqueSections)
+{
+    //
+    // Preserve current section order as much as possible, but apply the following
+    // rules:
+    //  - sections named "xxx#" are collated into a single PE section "xxx".
+    //      The contents of the CeeGen sections are sorted according to numerical
+    //      order & made contiguous in the PE section
+    //  - "text" always comes first in the file
+    //  - empty sections receive no PE section
+    //
+
+    bool ExeOrDll = isExeOrDll(m_ntHeaders);
+
+    entry *e = entries;
+    for (PEWriterSection **cur = getSectStart(); cur < getSectCur(); cur++) {
+
+        //
+        // Throw away any old headers we've used.
+        //
+
+        (*cur)->m_header = NULL;
+
+        //
+        // Don't allocate PE data for 0 length sections
+        //
+
+        if ((*cur)->dataLen() == 0)
+            continue;
+
+        //
+        // Special case: omit "text0" from obj's
+        //
+
+        if (!ExeOrDll && strcmp((*cur)->m_name, ".text0") == 0)
+            continue;
+
+        e->name = (*cur)->m_name;
+
+        //
+        // Now find the end of the text part of the section name, and
+        // calculate the numeral (if any) at the end
+        //
+
+        _ASSERTE(strlen(e->name) < UCHAR_MAX);
+        const char *p = e->name + strlen(e->name);
+        int index = 0; // numeral at the end of the section name
+        int placeValue = 1;
+        if (isdigit(p[-1]))
+        {
+            while (--p > e->name)
+            {
+                if (!isdigit(*p))
+                    break;
+                index += ((*p - '0') * placeValue);
+                placeValue *= 10;
+            }
+            p++;
+
+            //
+            // Special case: put "xxx" after "xxx0" and before "xxx1"
+            //
+
+            if (index == 0)
+                index = -1;
+        }
+
+        _ASSERTE(index == -1 || index == atoi(p));
+
+        e->nameLength = (unsigned char)(p - e->name);
+        e->index = index;
+        e->arrayIndex = (unsigned short)(cur - getSectStart());
+        e++;
+    }
+
+    //
+    // Sort the entries according to alphabetical + numerical order
+    //
+
+    SectionNameSorter sorter(entries, getSectStart(), int(e - entries), m_iSeedSections);
+    *piUniqueSections = sorter.SortSections();
+
+    *piEntries = unsigned(e - entries);
+
+    return S_OK;
+}
+
+class HeaderSorter : public CQuickSort<IMAGE_SECTION_HEADER>
+{
+  public:
+    HeaderSorter(IMAGE_SECTION_HEADER *headers, int count)
+      : CQuickSort<IMAGE_SECTION_HEADER>(headers, count) {}
+
+    int Compare(IMAGE_SECTION_HEADER *first, IMAGE_SECTION_HEADER *second)
+    {
+        // IMAGE_SECTION_HEADER::VirtualAddress/SectionIndex contains the
+        // index of the section
+        return VAL32(first->SectionIndex) - VAL32(second->SectionIndex);
+    }
+};
+
+HRESULT PEWriter::linkSortHeaders(entry * entries, unsigned iEntries, unsigned iUniqueSections)
+{
+    if (headers != NULL)
+        delete [] headers;
+    
+    // 1 extra for .reloc
+    S_UINT32 cUniqueSectionsAllocated = S_UINT32(iUniqueSections) + S_UINT32(1);
+    if (cUniqueSectionsAllocated.IsOverflow())
+    {
+        return COR_E_OVERFLOW;
+    }
+    headers = new (nothrow) IMAGE_SECTION_HEADER[cUniqueSectionsAllocated.Value()];
+    TESTANDRETURNMEMORY(headers);
+    
+    memset(headers, 0, sizeof(*headers) * cUniqueSectionsAllocated.Value());
+    
+    entry *ePrev = NULL;
+    IMAGE_SECTION_HEADER *h = headers - 1;
+    
+    //
+    // Store the sorting index
+    //
+
+    entry * entriesEnd = entries + iEntries;
+
+    for (entry * e = entries ; e < entriesEnd; e++)
+    {
+        if (ePrev != NULL
+            && !getSectStart()[ePrev->arrayIndex]->isSeedSection()
+            && e->nameLength == ePrev->nameLength
+            && strncmp(e->name, ePrev->name, e->nameLength) == 0)
+        {
+            //
+            // This section has the same name as the previous section, and
+            // will be collapsed with the previous section.
+            // Just update the (common) header information
+            //
+
+            if (e->arrayIndex < ePrev->arrayIndex)
+            {
+                //
+                // Use the smaller of the indices of e and ePrev
+                //
+                h->SectionIndex = VAL32(VAL32(h->SectionIndex) - (e->arrayIndex - ePrev->arrayIndex));
+            }
+
+            // Store an approximation of the size of the section temporarily
+            h->Misc.VirtualSize =  VAL32(VAL32(h->Misc.VirtualSize) + getSectStart()[e->arrayIndex]->dataLen());
+        }
+        else
+        {
+            // Grab a new header
+
+            h++;
+
+            strncpy_s((char *) h->Name, sizeof(h->Name), e->name, e->nameLength);
+
+            setSectionIndex(h, e->arrayIndex);
+
+            // Store the entry index in this field temporarily
+            h->FirstEntryIndex = VAL32((DWORD)(e - entries));
+
+            // Store an approximation of the size of the section temporarily
+            h->Misc.VirtualSize = VAL32(getSectStart()[e->arrayIndex]->dataLen());
+        }
+        ePrev = e;
+    }
+
+    headersEnd = ++h;
+
+    _ASSERTE(headers + iUniqueSections == headersEnd);
+
+    //
+    // Sort the entries according to alphabetical + numerical order
+    //
+
+    HeaderSorter headerSorter(headers, int(iUniqueSections));
+
+    headerSorter.Sort();
+
+    return S_OK;
+} // PEWriter::linkSortHeaders
+
+HRESULT PEWriter::linkPlaceSections(entry * entries, unsigned iEntries)
+{
+    entry * entriesEnd = entries + iEntries;
+
+    for (IMAGE_SECTION_HEADER * h = headers; h < headersEnd; h++)
+    {
+        // Get to the first entry corresponding to this section header
+
+        entry * e = entries + VAL32(h->FirstEntryIndex);
+        PEWriterSection *s = getSectStart()[e->arrayIndex];
+
+        if (s->isSeedSection()) {
+            virtualPos = s->getBaseRVA();
+        }
+
+        h->VirtualAddress = VAL32(virtualPos);
+        h->PointerToRawData = VAL32(filePos);
+
+        s->m_baseRVA = virtualPos;
+        s->m_filePos = filePos;
+        s->m_header = h;
+        h->Characteristics = VAL32(s->m_flags);
+
+#ifdef LOGGING
+        LOG((LF_ZAP, LL_INFO10,
+             "   Section %-7s RVA=%08x, Length=%08x, FilePos=%08x\n",
+             s->m_name, s->m_baseRVA, s->dataLen(), s->m_filePos));
+#endif
+
+        unsigned dataSize = s->dataLen();
+
+        // Find all the other entries corresponding to this section header
+
+        PEWriterSection *sPrev = s;
+        entry * ePrev = e;
+        while (++e < entriesEnd)
+        {
+           if (e->nameLength != ePrev->nameLength
+               || strncmp(e->name, ePrev->name, e->nameLength) != 0)
+               break;
+
+           s = getSectStart()[e->arrayIndex];
+           _ASSERTE(s->m_flags == VAL32(h->Characteristics));
+
+           sPrev->m_filePad = padLen(dataSize, SUBSECTION_ALIGN);
+           dataSize = roundUp(dataSize, SUBSECTION_ALIGN);
+
+           s->m_baseRVA = virtualPos + dataSize;
+           s->m_filePos = filePos + dataSize;
+           s->m_header = h;
+           sPrev = s;
+
+           dataSize += s->dataLen();
+
+#ifdef LOGGING
+           LOG((LF_ZAP, LL_INFO10,
+                "   Section %-7s RVA=%08x, Length=%08x, FilePos=%08x\n",
+                s->m_name, s->m_baseRVA, s->dataLen(), s->m_filePos));
+#endif
+
+           ePrev = e;
+        }
+
+        h->Misc.VirtualSize = VAL32(dataSize);
+
+        sPrev->m_filePad = padLen(dataSize, VAL32(m_ntHeaders->OptionalHeader.FileAlignment));
+        dataSize = roundUp(dataSize, VAL32(m_ntHeaders->OptionalHeader.FileAlignment));
+        h->SizeOfRawData = VAL32(dataSize);
+        filePos += dataSize;
+
+        dataSize = roundUp(dataSize, VAL32(m_ntHeaders->OptionalHeader.SectionAlignment));
+        virtualPos += dataSize;
+    }
+
+    return S_OK;
+}
+
+void PEWriter::setSectionIndex(IMAGE_SECTION_HEADER * h, unsigned sectionIndex) {
+
+    if (getSectStart()[sectionIndex]->isSeedSection()) {
+        h->SectionIndex = VAL32(sectionIndex);
+        return;
+    }
+
+    //
+    // Reserve some dummy "array index" values for special sections
+    // at the start of the image (after the seed sections)
+    //
+
+    static const char * const SpecialNames[] = { ".text", ".cormeta", NULL };
+    enum { SPECIAL_NAMES_COUNT = NumItems(SpecialNames) };
+
+    for (const char * const * s = SpecialNames; /**/; s++)
+    {
+        if (*s == 0)
+        {
+            h->SectionIndex = VAL32(sectionIndex + SPECIAL_NAMES_COUNT);
+            break;
+        }
+        else if (strcmp((char *) h->Name, *s) == 0)
+        {
+            h->SectionIndex = VAL32(m_iSeedSections + DWORD(s - SpecialNames));
+            break;
+        }
+        s++;
+    }
+
+}
+
+
+HRESULT PEWriter::link() {
+
+    //
+    // NOTE:
+    // link() can be called more than once!  This is because at least one compiler
+    // (the prejitter) needs to know the base addresses of some segments before it
+    // builds others. It's up to the caller to insure the layout remains the same
+    // after changes are made, though.
+    //
+
+    //
+    // Assign base addresses to all sections, and layout & merge PE sections
+    //
+
+    bool ExeOrDll = isExeOrDll(m_ntHeaders);
+
+    //
+    // Collate by name & sort by index
+    //
+
+    // First collect all information into entries[]
+
+    int sectCount = getSectCount();
+    entry *entries = (entry *) _alloca(sizeof(entry) * sectCount);
+
+    unsigned iUniqueSections, iEntries;
+    HRESULT hr;
+    IfFailRet(linkSortSections(entries, &iEntries, &iUniqueSections));
+
+    //
+    // Now, allocate a header for each unique section name.
+    // Also record the minimum section index for each section
+    // so we can preserve order as much as possible.
+    //
+
+    IfFailRet(linkSortHeaders(entries, iEntries, iUniqueSections));
+
+    //
+    // If file alignment is not zero, it must have been set through
+    //  setFileAlignment(), in which case we leave it untouched
+    //
+
+    if( VAL32(0) == m_ntHeaders->OptionalHeader.FileAlignment )
+    {
+        //
+        // Figure out what file alignment to use.
+        //
+
+        unsigned RoundUpVal;
+
+        if (ExeOrDll)
+        {
+            RoundUpVal = 0x0200;
+        }
+        else
+        {
+            // Don't bother padding for objs
+            RoundUpVal = 4;
+        }
+
+        m_ntHeaders->OptionalHeader.FileAlignment = VAL32(RoundUpVal);
+    }
+
+    //
+    // Now, assign a section header & location to each section
+    //
+
+    if (ExeOrDll)
+    {
+        iUniqueSections++; // One more for .reloc
+        filePos = sizeof(IMAGE_DOS_HEADER)+sizeof(x86StubPgm) + m_ntHeadersSize;
+    }
+    else
+    {
+        filePos = sizeof(IMAGE_FILE_HEADER);
+    }
+
+    m_ntHeaders->FileHeader.NumberOfSections = VAL16(iUniqueSections);
+
+    filePos += iUniqueSections * sizeof(IMAGE_SECTION_HEADER);
+    filePos  = roundUp(filePos, VAL32(m_ntHeaders->OptionalHeader.FileAlignment));
+
+    m_ntHeaders->OptionalHeader.SizeOfHeaders = VAL32(filePos);
+
+    virtualPos = roundUp(filePos, VAL32(m_ntHeaders->OptionalHeader.SectionAlignment));
+
+    if (m_hSeedFile != INVALID_HANDLE_VALUE) {
+        // We do not support relocating/sliding down the seed sections
+        if (filePos > VAL32(m_pSeedSections->VirtualAddress) ||
+            virtualPos > VAL32(m_pSeedSections->VirtualAddress))
+           return E_FAIL;
+
+        if (virtualPos < VAL32(m_pSeedSections->VirtualAddress)) {
+            virtualPos = VAL32(m_pSeedSections->VirtualAddress);
+        }
+    }
+
+    // Now finally assign RVAs to the sections
+
+    IfFailRet(linkPlaceSections(entries, iEntries));
+
+    return S_OK;
+}
+
+#undef SectionIndex
+#undef FirstEntryIndex
+
+
+class SectionRVASorter : public CQuickSort<PEWriterSection*>
+{
+    public:
+        SectionRVASorter(PEWriterSection **elts, SSIZE_T count)
+          : CQuickSort<PEWriterSection*>(elts, count) {}
+
+        int Compare(PEWriterSection **e1, PEWriterSection **e2)
+        {
+            return (*e1)->getBaseRVA() - (*e2)->getBaseRVA();
+        }
+};
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+HRESULT PEWriter::fixup(CeeGenTokenMapper *pMapper)
+{
+    HRESULT hr;
+
+    bool ExeOrDll = isExeOrDll(m_ntHeaders);
+    const unsigned RoundUpVal = VAL32(m_ntHeaders->OptionalHeader.FileAlignment);
+
+    if(ExeOrDll)
+    {
+        //
+        // Apply manual relocation for entry point field
+        //
+
+        PESection *textSection;
+        IfFailRet(getSectionCreate(".text", 0, &textSection));
+
+        if (m_ntHeaders->OptionalHeader.AddressOfEntryPoint != VAL32(0))
+            m_ntHeaders->OptionalHeader.AddressOfEntryPoint = VAL32(VAL32(m_ntHeaders->OptionalHeader.AddressOfEntryPoint) + textSection->m_baseRVA);
+
+        //
+        // Apply normal relocs
+        //
+
+        IfFailRet(getSectionCreate(".reloc", sdReadOnly | IMAGE_SCN_MEM_DISCARDABLE,
+                                   (PESection **) &reloc));
+        reloc->m_baseRVA = virtualPos;
+        reloc->m_filePos = filePos;
+        reloc->m_header = headersEnd++;
+        strcpy_s((char *)reloc->m_header->Name, sizeof(reloc->m_header->Name),
+                 ".reloc");
+        reloc->m_header->Characteristics = VAL32(reloc->m_flags);
+        reloc->m_header->VirtualAddress = VAL32(virtualPos);
+        reloc->m_header->PointerToRawData = VAL32(filePos);
+
+#ifdef _DEBUG
+        if (m_encMode)
+            printf("Applying relocs for .rdata section with RVA %x\n", m_rdataRvaBase);
+#endif
+
+        //
+        // Sort the sections by RVA
+        //
+
+        CQuickArray<PEWriterSection *> sections;
+
+        SIZE_T count = getSectCur() - getSectStart();
+        IfFailRet(sections.ReSizeNoThrow(count));
+        UINT i = 0;
+        PEWriterSection **cur;
+        for(cur = getSectStart(); cur < getSectCur(); cur++, i++)
+            sections[i] = *cur;
+
+        SectionRVASorter sorter(sections.Ptr(), sections.Size());
+
+        sorter.Sort();
+
+        PERelocSection relocSection(reloc);
+
+        cur = sections.Ptr();
+        PEWriterSection **curEnd = cur + sections.Size();
+        while (cur < curEnd)
+        {
+            IfFailRet((*cur)->applyRelocs(m_ntHeaders, 
+                                          &relocSection, 
+                                          pMapper, 
+                                          m_dataRvaBase, 
+                                          m_rdataRvaBase, 
+                                          m_codeRvaBase));
+            cur++;
+        }
+
+        relocSection.Finish(isPE32());
+        reloc->m_header->Misc.VirtualSize = VAL32(reloc->dataLen());
+
+        // Strip the reloc section if the flag is set
+        if (m_ntHeaders->FileHeader.Characteristics & VAL16(IMAGE_FILE_RELOCS_STRIPPED))
+        {
+            reloc->m_header->Misc.VirtualSize = VAL32(0);
+        }
+
+        reloc->m_header->SizeOfRawData = VAL32(roundUp(VAL32(reloc->m_header->Misc.VirtualSize), RoundUpVal));
+        reloc->m_filePad = padLen(VAL32(reloc->m_header->Misc.VirtualSize), RoundUpVal);
+        filePos += VAL32(reloc->m_header->SizeOfRawData);
+        virtualPos += roundUp(VAL32(reloc->m_header->Misc.VirtualSize),
+                              VAL32(m_ntHeaders->OptionalHeader.SectionAlignment));
+
+        if (reloc->m_header->Misc.VirtualSize == VAL32(0))
+        {
+            //
+            // Omit reloc section from section list.  (It will
+            // still be there but the loader won't see it - this
+            // only works because we've allocated it as the last
+            // section.)
+            //
+            m_ntHeaders->FileHeader.NumberOfSections = VAL16(VAL16(m_ntHeaders->FileHeader.NumberOfSections) - 1);
+        }
+        else
+        {
+            IMAGE_DATA_DIRECTORY * pRelocDataDirectory;
+            //
+            // Put reloc address in header
+            //
+            if (isPE32())
+            {
+                pRelocDataDirectory = &(ntHeaders32()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
+            }
+            else
+            {
+                pRelocDataDirectory = &(ntHeaders64()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
+            }
+
+            pRelocDataDirectory->VirtualAddress = reloc->m_header->VirtualAddress;
+            pRelocDataDirectory->Size           = reloc->m_header->Misc.VirtualSize;
+        }
+
+        // compute ntHeader fields that depend on the sizes of other things
+        for(IMAGE_SECTION_HEADER *h = headersEnd-1; h >= headers; h--) {    // go backwards, so first entry takes precedence
+            if (h->Characteristics & VAL32(IMAGE_SCN_CNT_CODE)) {
+                m_ntHeaders->OptionalHeader.BaseOfCode = h->VirtualAddress;
+                m_ntHeaders->OptionalHeader.SizeOfCode =
+                    VAL32(VAL32(m_ntHeaders->OptionalHeader.SizeOfCode) + VAL32(h->SizeOfRawData));
+            }
+            if (h->Characteristics & VAL32(IMAGE_SCN_CNT_INITIALIZED_DATA)) {
+                if (isPE32())
+                {
+                    ntHeaders32()->OptionalHeader.BaseOfData = h->VirtualAddress;
+                }
+                m_ntHeaders->OptionalHeader.SizeOfInitializedData =
+                    VAL32(VAL32(m_ntHeaders->OptionalHeader.SizeOfInitializedData) + VAL32(h->SizeOfRawData));
+            }
+            if (h->Characteristics & VAL32(IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
+                m_ntHeaders->OptionalHeader.SizeOfUninitializedData =
+                    VAL32(VAL32(m_ntHeaders->OptionalHeader.SizeOfUninitializedData) + VAL32(h->SizeOfRawData));
+            }
+        }
+
+        int index;
+        IMAGE_DATA_DIRECTORY * pCurDataDirectory;
+
+        // go backwards, so first entry takes precedence
+        for(cur = getSectCur()-1; getSectStart() <= cur; --cur)
+        {
+            index = (*cur)->getDirEntry();
+
+            // Is this a valid directory entry
+            if (index > 0)
+            {
+                if (isPE32())
+                {
+                    _ASSERTE((unsigned)(index) < VAL32(ntHeaders32()->OptionalHeader.NumberOfRvaAndSizes));
+
+                    pCurDataDirectory = &(ntHeaders32()->OptionalHeader.DataDirectory[index]);
+                }
+                else
+                {
+                    _ASSERTE((unsigned)(index) < VAL32(ntHeaders64()->OptionalHeader.NumberOfRvaAndSizes));
+
+                    pCurDataDirectory = &(ntHeaders64()->OptionalHeader.DataDirectory[index]);
+                }
+
+                pCurDataDirectory->VirtualAddress = VAL32((*cur)->m_baseRVA);
+                pCurDataDirectory->Size           = VAL32((*cur)->dataLen());
+            }
+        }
+
+        // handle the directory entries specified using the file.
+        for (index=0; index < cEntries; index++)
+        {
+            if (pEntries[index].section)
+            {
+                PEWriterSection *section = pEntries[index].section;
+                _ASSERTE(pEntries[index].offset < section->dataLen());
+
+                if (isPE32())
+                    pCurDataDirectory = &(ntHeaders32()->OptionalHeader.DataDirectory[index]);
+                else
+                    pCurDataDirectory = &(ntHeaders64()->OptionalHeader.DataDirectory[index]);
+
+                pCurDataDirectory->VirtualAddress = VAL32(section->m_baseRVA + pEntries[index].offset);
+                pCurDataDirectory->Size           = VAL32(pEntries[index].size);
+            }
+        }
+
+        m_ntHeaders->OptionalHeader.SizeOfImage = VAL32(virtualPos);
+    } // end if(ExeOrDll)
+    else //i.e., if OBJ
+    {
+        //
+        // Clean up note:
+        // I've cleaned up the executable linking path, but the .obj linking
+        // is still a bit strange, what with a "extra" reloc & strtab sections
+        // which are created after the linking step and get treated specially.
+        //
+        reloc = new (nothrow) PEWriterSection(".reloc",
+                                    sdReadOnly | IMAGE_SCN_MEM_DISCARDABLE, 0x4000, 0);
+        if(reloc == NULL) return E_OUTOFMEMORY;
+        strtab = new (nothrow)  PEWriterSection(".strtab",
+                                     sdReadOnly | IMAGE_SCN_MEM_DISCARDABLE, 0x4000, 0); //string table (if any)
+        if(strtab == NULL) return E_OUTOFMEMORY;
+
+        DWORD* TokInSymbolTable = new (nothrow) DWORD[16386];
+        if (TokInSymbolTable == NULL) return E_OUTOFMEMORY;
+
+        m_ntHeaders->FileHeader.SizeOfOptionalHeader = 0;
+        //For each section set VirtualAddress to 0
+        PEWriterSection **cur;
+        for(cur = getSectStart(); cur < getSectCur(); cur++)
+        {
+            IMAGE_SECTION_HEADER* header = (*cur)->m_header;
+            header->VirtualAddress = VAL32(0);
+        }
+        // Go over section relocations and build the Symbol Table, use .reloc section as buffer:
+        DWORD tk=0, rva=0, NumberOfSymbols=0;
+        BOOL  ToRelocTable = FALSE;
+        IMAGE_SYMBOL is;
+        IMAGE_RELOCATION ir;
+        ULONG StrTableLen = 4; //size itself only
+        char* szSymbolName = NULL;
+        char* pch;
+
+        PESection *textSection;
+        getSectionCreate(".text", 0, &textSection);
+
+        for(PESectionReloc* rcur = textSection->m_relocStart; rcur < textSection->m_relocCur; rcur++)
+        {
+            switch(rcur->type)
+            {
+                case 0x7FFA: // Ptr to symbol name
+#ifdef _WIN64
+                    _ASSERTE(!"this is probably broken!!");
+#endif // _WIN64
+                    szSymbolName = (char*)(UINT_PTR)(rcur->offset);
+                    break;
+
+                case 0x7FFC: // Ptr to file name
+                    TokInSymbolTable[NumberOfSymbols++] = 0;
+                    memset(&is,0,sizeof(IMAGE_SYMBOL));
+                    memcpy(is.N.ShortName,".file\0\0\0",8);
+                    is.Value = 0;
+                    is.SectionNumber = VAL16(IMAGE_SYM_DEBUG);
+                    is.Type = VAL16(IMAGE_SYM_DTYPE_NULL);
+                    is.StorageClass = IMAGE_SYM_CLASS_FILE;
+                    is.NumberOfAuxSymbols = 1;
+                    if((pch = reloc->getBlock(sizeof(IMAGE_SYMBOL))))
+                        memcpy(pch,&is,sizeof(IMAGE_SYMBOL));
+                    else return E_OUTOFMEMORY;
+                    TokInSymbolTable[NumberOfSymbols++] = 0;
+                    memset(&is,0,sizeof(IMAGE_SYMBOL));
+#ifdef _WIN64
+                    _ASSERTE(!"this is probably broken!!");
+#endif // _WIN64
+                    strcpy_s((char*)&is,sizeof(is),(char*)(UINT_PTR)(rcur->offset));
+                    if((pch = reloc->getBlock(sizeof(IMAGE_SYMBOL))))
+                        memcpy(pch,&is,sizeof(IMAGE_SYMBOL));
+                    else return E_OUTOFMEMORY;
+#ifdef _WIN64
+                    _ASSERTE(!"this is probably broken!!");
+#endif // _WIN64
+                    delete (char*)(UINT_PTR)(rcur->offset);
+                    ToRelocTable = FALSE;
+                    tk = 0;
+                    szSymbolName = NULL;
+                    break;
+
+                case 0x7FFB: // compid value
+                    TokInSymbolTable[NumberOfSymbols++] = 0;
+                    memset(&is,0,sizeof(IMAGE_SYMBOL));
+                    memcpy(is.N.ShortName,"@comp.id",8);
+                    is.Value = VAL32(rcur->offset);
+                    is.SectionNumber = VAL16(IMAGE_SYM_ABSOLUTE);
+                    is.Type = VAL16(IMAGE_SYM_DTYPE_NULL);
+                    is.StorageClass = IMAGE_SYM_CLASS_STATIC;
+                    is.NumberOfAuxSymbols = 0;
+                    if((pch = reloc->getBlock(sizeof(IMAGE_SYMBOL))))
+                        memcpy(pch,&is,sizeof(IMAGE_SYMBOL));
+                    else return E_OUTOFMEMORY;
+                    ToRelocTable = FALSE;
+                    tk = 0;
+                    szSymbolName = NULL;
+                    break;
+
+                case 0x7FFF: // Token value, def
+                    tk = rcur->offset;
+                    ToRelocTable = FALSE;
+                    break;
+
+                case 0x7FFE: //Token value, ref
+                    tk = rcur->offset;
+                    ToRelocTable = TRUE;
+                    break;
+
+                case 0x7FFD: //RVA value
+                    rva = rcur->offset;
+                    if(tk)
+                    {
+                        // Add to SymbolTable
+                        DWORD i;
+                        for(i = 0; (i < NumberOfSymbols)&&(tk != TokInSymbolTable[i]); i++);
+                        if(i == NumberOfSymbols)
+                        {
+                            if(szSymbolName && *szSymbolName) // Add "extern" symbol and string table entry
+                            {
+                                TokInSymbolTable[NumberOfSymbols++] = 0;
+                                memset(&is,0,sizeof(IMAGE_SYMBOL));
+                                i++; // so reloc record (if generated) points to COM token symbol
+                                is.N.Name.Long = VAL32(StrTableLen);
+                                is.SectionNumber = VAL16(1); //textSection is the first one
+                                is.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
+                                is.NumberOfAuxSymbols = 0;
+                                is.Value = VAL32(rva);
+                                if(TypeFromToken(tk) == mdtMethodDef)
+                                {
+                                    is.Type = VAL16(0x20); //IMAGE_SYM_DTYPE_FUNCTION;
+                                }
+                                if((pch = reloc->getBlock(sizeof(IMAGE_SYMBOL))))
+                                    memcpy(pch,&is,sizeof(IMAGE_SYMBOL));
+                                else return E_OUTOFMEMORY;
+                                DWORD l = (DWORD)(strlen(szSymbolName)+1); // don't forget zero terminator!
+                                if((pch = reloc->getBlock(1)))
+                                    memcpy(pch,szSymbolName,1);
+                                else return E_OUTOFMEMORY;
+                                delete szSymbolName;
+                                StrTableLen += l;
+                            }
+                            TokInSymbolTable[NumberOfSymbols++] = tk;
+                            memset(&is,0,sizeof(IMAGE_SYMBOL));
+                            sprintf_s((char*)is.N.ShortName,sizeof(is.N.ShortName),"%08X",tk);
+                            is.SectionNumber = VAL16(1); //textSection is the first one
+                            is.StorageClass = 0x6B; //IMAGE_SYM_CLASS_COM_TOKEN;
+                            is.Value = VAL32(rva);
+                            if(TypeFromToken(tk) == mdtMethodDef)
+                            {
+                                is.Type = VAL16(0x20); //IMAGE_SYM_DTYPE_FUNCTION;
+                                //is.NumberOfAuxSymbols = 1;
+                            }
+                            if((pch = reloc->getBlock(sizeof(IMAGE_SYMBOL))))
+                                memcpy(pch,&is,sizeof(IMAGE_SYMBOL));
+                            else return E_OUTOFMEMORY;
+                            if(is.NumberOfAuxSymbols == 1)
+                            {
+                                BYTE dummy[sizeof(IMAGE_SYMBOL)];
+                                memset(dummy,0,sizeof(IMAGE_SYMBOL));
+                                dummy[0] = dummy[2] = 1;
+                                if((pch = reloc->getBlock(sizeof(IMAGE_SYMBOL))))
+                                    memcpy(pch,dummy,sizeof(IMAGE_SYMBOL));
+                                else return E_OUTOFMEMORY;
+                                TokInSymbolTable[NumberOfSymbols++] = 0;
+                            }
+                        }
+                        if(ToRelocTable)
+                        {
+                            IMAGE_SECTION_HEADER* phdr = textSection->m_header;
+                            // Add to reloc table
+                            IMAGE_RELOC_FIELD(ir, VirtualAddress) = VAL32(rva);
+                            ir.SymbolTableIndex = VAL32(i);
+                            ir.Type = VAL16(IMAGE_REL_I386_SECREL);
+                            if(phdr->PointerToRelocations == 0)
+                                phdr->PointerToRelocations = VAL32(VAL32(phdr->PointerToRawData) + VAL32(phdr->SizeOfRawData));
+                            phdr->NumberOfRelocations = VAL32(VAL32(phdr->NumberOfRelocations) + 1);
+                            if((pch = reloc->getBlock(sizeof(IMAGE_RELOCATION))))
+                                memcpy(pch,&is,sizeof(IMAGE_RELOCATION));
+                            else return E_OUTOFMEMORY;
+                        }
+                    }
+                    ToRelocTable = FALSE;
+                    tk = 0;
+                    szSymbolName = NULL;
+                    break;
+
+                default:
+                    break;
+            } //end switch(cur->type)
+        } // end for all relocs
+        // Add string table counter:
+        if((pch = reloc->getBlock(sizeof(ULONG))))
+            memcpy(pch,&StrTableLen,sizeof(ULONG));
+        else return E_OUTOFMEMORY;
+        reloc->m_header->Misc.VirtualSize = VAL32(reloc->dataLen());
+        if(NumberOfSymbols)
+        {
+            // recompute the actual sizes and positions of all the sections
+            filePos = roundUp(VAL16(m_ntHeaders->FileHeader.NumberOfSections) * sizeof(IMAGE_SECTION_HEADER)+
+                              sizeof(IMAGE_FILE_HEADER), RoundUpVal);
+            for(cur = getSectStart(); cur < getSectCur(); cur++)
+            {
+                IMAGE_SECTION_HEADER* header = (*cur)->m_header;
+                header->Misc.VirtualSize = VAL32((*cur)->dataLen());
+                header->VirtualAddress = VAL32(0);
+                header->SizeOfRawData = VAL32(roundUp(VAL32(header->Misc.VirtualSize), RoundUpVal));
+                header->PointerToRawData = VAL32(filePos);
+
+                filePos += VAL32(header->SizeOfRawData);
+            }
+            m_ntHeaders->FileHeader.Machine = VAL16(0xC0EE); //COM+ EE
+            m_ntHeaders->FileHeader.PointerToSymbolTable = VAL32(filePos);
+            m_ntHeaders->FileHeader.NumberOfSymbols = VAL32(NumberOfSymbols);
+            filePos += roundUp(VAL32(reloc->m_header->Misc.VirtualSize)+strtab->dataLen(),RoundUpVal);
+        }
+        delete[] TokInSymbolTable;
+    } //end if OBJ
+
+    const unsigned headerOffset = (unsigned) (ExeOrDll ? sizeof(IMAGE_DOS_HEADER) + sizeof(x86StubPgm) : 0);
+
+    memset(&m_dosHeader, 0, sizeof(IMAGE_DOS_HEADER));
+    m_dosHeader.e_magic = VAL16(IMAGE_DOS_SIGNATURE);
+    m_dosHeader.e_cblp =  VAL16(0x90);              // bytes in last page
+    m_dosHeader.e_cp =  VAL16(3);                   // pages in file
+    m_dosHeader.e_cparhdr =  VAL16(4);              // size of header in paragraphs
+    m_dosHeader.e_maxalloc =   VAL16(0xFFFF);       // maximum extra mem needed
+    m_dosHeader.e_sp =  VAL16(0xB8);                // initial SP value
+    m_dosHeader.e_lfarlc =  VAL16(0x40);            // file offset of relocations
+    m_dosHeader.e_lfanew =  VAL32(headerOffset);    // file offset of NT header!
+
+    return(S_OK);   // SUCCESS
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+HRESULT PEWriter::Open(__in LPCWSTR fileName)
+{
+    _ASSERTE(m_file == INVALID_HANDLE_VALUE);
+    HRESULT hr = NOERROR;
+
+    m_file = WszCreateFile(fileName,
+                           GENERIC_WRITE,
+                           0, // No sharing.  Was: FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL,
+                           CREATE_ALWAYS,
+                           FILE_ATTRIBUTE_NORMAL,
+                           NULL );
+    if (m_file == INVALID_HANDLE_VALUE)
+        hr = HRESULT_FROM_GetLastErrorNA();
+
+    return hr;
+}
+
+HRESULT PEWriter::Seek(int offset)
+{
+    _ASSERTE(m_file != INVALID_HANDLE_VALUE);
+    if (SetFilePointer(m_file, offset, 0, FILE_BEGIN))
+        return S_OK;
+    else
+        return HRESULT_FROM_GetLastError();
+}
+
+HRESULT PEWriter::Write(const void *data, int size)
+{
+    _ASSERTE(m_file != INVALID_HANDLE_VALUE);
+
+    HRESULT hr = S_OK;
+    DWORD dwWritten = 0;
+    if (size)
+    {
+        CQuickBytes zero;
+        if (data == NULL)
+        {
+            hr = zero.ReSizeNoThrow(size);
+            if (SUCCEEDED(hr))
+            {
+                ZeroMemory(zero.Ptr(), size);
+                data = zero.Ptr();
+            }
+        }
+
+        if (WriteFile(m_file, data, size, &dwWritten, NULL))
+        {
+            _ASSERTE(dwWritten == (DWORD)size);
+        }
+        else
+            hr = HRESULT_FROM_GetLastError();
+    }
+
+    return hr;
+}
+
+HRESULT PEWriter::Pad(int align)
+{
+    DWORD offset = SetFilePointer(m_file, 0, NULL, FILE_CURRENT);
+    int pad = padLen(offset, align);
+    if (pad > 0)
+        return Write(NULL, pad);
+    else
+        return S_FALSE;
+}
+
+HRESULT PEWriter::Close()
+{
+    if (m_file == INVALID_HANDLE_VALUE)
+        return S_OK;
+
+    HRESULT hr;
+    if (CloseHandle(m_file))
+        hr = S_OK;
+    else
+        hr = HRESULT_FROM_GetLastError();
+
+    m_file = INVALID_HANDLE_VALUE;
+
+    return hr;
+}
+
+/******************************************************************/
+HRESULT PEWriter::write(__in const LPWSTR fileName) {
+
+    HRESULT hr;
+
+#ifdef ENC_DELTA_HACK
+    WCHAR szFileName[256];
+    DWORD len = WszGetEnvironmentVariable(L"COMP_ENC_EMIT", szFileName, NumItems(szFileName));
+    _ASSERTE(len < sizeof(szFileName));
+    if (len > 0)
+    {
+        _ASSERTE(!m_pSeedFileDecoder);
+
+        wcscat_s(szFileName, sizeof(szFileName)/sizeof(szFileName[0]), L".dil");
+        HANDLE pDelta = WszCreateFile(szFileName,
+                           GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL,
+                           CREATE_ALWAYS,
+                           FILE_ATTRIBUTE_NORMAL,
+                           NULL );
+        if (pDelta == INVALID_HANDLE_VALUE) {
+            hr = HRESULT_FROM_GetLastError();
+            _ASSERTE(!"failure so open .dil file");
+            goto ErrExit;
+        }
+
+        // write the actual data
+        for (PEWriterSection **cur = getSectStart(); cur < getSectCur(); cur++) {
+            if (strcmp((*cur)->m_name, ".text") == 0)
+            {
+                hr = (*cur)->write(pDelta);
+                CloseHandle(pDelta);
+                pDelta = NULL;
+                if (FAILED(hr))
+                {
+                    _ASSERT(!"failure to write to .dil file");
+                    goto ErrExit;
+                }
+                break;
+            }
+        }
+        PREFIX_ASSUME(!pDelta);
+        return S_OK;
+    }
+#endif
+
+    bool ExeOrDll;
+    unsigned RoundUpVal;
+    ExeOrDll = isExeOrDll(m_ntHeaders);
+    RoundUpVal = VAL32(m_ntHeaders->OptionalHeader.FileAlignment);
+
+    IfFailGo(Open(fileName));
+
+    if(ExeOrDll)
+    {
+        // write the PE headers
+        IfFailGo(Write(&m_dosHeader, sizeof(IMAGE_DOS_HEADER)));
+        IfFailGo(Write(x86StubPgm, sizeof(x86StubPgm)));
+        IfFailGo(Write(m_ntHeaders, m_ntHeadersSize));
+    }
+    else
+    {
+        // write the object file header
+        IfFailGo(Write(&(m_ntHeaders->FileHeader),sizeof(IMAGE_FILE_HEADER)));
+    }
+
+    IfFailGo(Write(headers, (int)(sizeof(IMAGE_SECTION_HEADER)*(headersEnd-headers))));
+
+    IfFailGo(Pad(RoundUpVal));
+
+    // write the actual data
+    for (PEWriterSection **cur = getSectStart(); cur < getSectCur(); cur++) {
+        if ((*cur)->m_header != NULL) {
+            IfFailGo(Seek((*cur)->m_filePos));
+            IfFailGo((*cur)->write(m_file));
+            IfFailGo(Write(NULL, (*cur)->m_filePad));
+        }
+    }
+
+    // writes for an object file
+    if (!ExeOrDll)
+    {
+        // write the relocs section (Does nothing if relocs section is empty)
+        IfFailGo(reloc->write(m_file));
+        //write string table (obj only, empty for exe or dll)
+        IfFailGo(strtab->write(m_file));
+        int lena = padLen(VAL32(reloc->m_header->Misc.VirtualSize)+strtab->dataLen(), RoundUpVal);
+        if (lena > 0)
+            IfFailGo(Write(NULL, lena));
+    }
+
+    return Close();
+
+ ErrExit:
+    Close();
+
+    return hr;
+}
+
+HRESULT PEWriter::write(void ** ppImage)
+{
+    bool ExeOrDll = isExeOrDll(m_ntHeaders);
+    const unsigned RoundUpVal = VAL32(m_ntHeaders->OptionalHeader.FileAlignment);
+    char *pad = (char *) _alloca(RoundUpVal);
+    memset(pad, 0, RoundUpVal);
+
+    size_t lSize = filePos;
+    if (!ExeOrDll)
+    {
+        lSize += reloc->dataLen();
+        lSize += strtab->dataLen();
+        lSize += padLen(VAL32(reloc->m_header->Misc.VirtualSize)+strtab->dataLen(),
+                        RoundUpVal);
+    }
+
+    // allocate the block we are handing back to the caller
+    void * pImage = (void *) ::CoTaskMemAlloc(lSize);
+    if (NULL == pImage)
+    {
+        return E_OUTOFMEMORY;
+    }
+
+    // zero the memory
+    ::memset(pImage, 0, lSize);
+
+    char *pCur = (char *)pImage;
+
+    if(ExeOrDll)
+    {
+        // PE Header
+        COPY_AND_ADVANCE(pCur, &m_dosHeader, sizeof(IMAGE_DOS_HEADER));
+        COPY_AND_ADVANCE(pCur, x86StubPgm, sizeof(x86StubPgm));
+        COPY_AND_ADVANCE(pCur, m_ntHeaders, m_ntHeadersSize);
+    }
+    else
+    {
+        COPY_AND_ADVANCE(pCur, &(m_ntHeaders->FileHeader), sizeof(IMAGE_FILE_HEADER));
+    }
+
+    COPY_AND_ADVANCE(pCur, headers, sizeof(*headers)*(headersEnd - headers));
+
+    // now the sections
+    // write the actual data
+    for (PEWriterSection **cur = getSectStart(); cur < getSectCur(); cur++) {
+        if ((*cur)->m_header != NULL) {
+            unsigned len;
+            pCur = (char*)pImage + (*cur)->m_filePos;
+            len = (*cur)->writeMem((void**)&pCur);
+            _ASSERTE(len == (*cur)->dataLen());
+            COPY_AND_ADVANCE(pCur, pad, (*cur)->m_filePad);
+        }
+    }
+
+    // !!! Need to jump to the right place...
+
+    if (!ExeOrDll)
+    {
+        // now the relocs (exe, dll) or symbol table (obj) (if any)
+        // write the relocs section (Does nothing if relocs section is empty)
+        reloc->writeMem((void **)&pCur);
+
+        //write string table (obj only, empty for exe or dll)
+        strtab->writeMem((void **)&pCur);
+
+        // final pad
+        size_t len = padLen(VAL32(reloc->m_header->Misc.VirtualSize)+strtab->dataLen(), RoundUpVal);
+        if (len > 0)
+        {
+            // WARNING: macro - must enclose in curly braces
+            COPY_AND_ADVANCE(pCur, pad, len);
+        }
+    }
+
+    // make sure we wrote the exact numbmer of bytes expected
+    _ASSERTE(lSize == (size_t) (pCur - (char *)pImage));
+
+    // give pointer to memory image back to caller (who must free with ::CoTaskMemFree())
+    *ppImage = pImage;
+
+    // all done
+    return S_OK;
+}
+
+HRESULT PEWriter::getFileTimeStamp(DWORD *pTimeStamp)
+{
+    if (pTimeStamp)
+        *pTimeStamp = m_peFileTimeStamp;
+
+    return S_OK;
+}
+
+DWORD PEWriter::getImageBase32()
+{
+    _ASSERTE(isPE32());
+    return VAL32(ntHeaders32()->OptionalHeader.ImageBase);
+}
+
+UINT64 PEWriter::getImageBase64()
+{
+    _ASSERTE(!isPE32());
+    return VAL64(ntHeaders64()->OptionalHeader.ImageBase);
+}
+
+void PEWriter::setImageBase32(DWORD imageBase)
+{
+    _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE);
+
+    _ASSERTE(isPE32());
+    ntHeaders32()->OptionalHeader.ImageBase = VAL32(imageBase);
+}
+
+void PEWriter::setImageBase64(UINT64 imageBase)
+{
+    _ASSERTE(!isPE32());
+    ntHeaders64()->OptionalHeader.ImageBase = VAL64(imageBase);
+}
+
+void PEWriter::getHeaderInfo(PIMAGE_NT_HEADERS *ppNtHeaders, PIMAGE_SECTION_HEADER *ppSections, ULONG *pNumSections)
+{
+    *ppNtHeaders = m_ntHeaders;
+    *ppSections = headers;
+    *pNumSections = (ULONG)(headersEnd - headers);
+}
diff --git a/src/dlls/mscorpe/pewriter.h b/src/dlls/mscorpe/pewriter.h
new file mode 100644 (file)
index 0000000..67441ee
--- /dev/null
@@ -0,0 +1,338 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+#ifndef PEWriter_H
+#define PEWriter_H
+
+#include <crtwrap.h>
+
+#include <windows.h>
+
+#include "ceegen.h"
+
+#include "pesectionman.h"
+
+class PEWriter;
+class PEWriterSection;
+class PEDecoder;
+struct entry;
+struct _IMAGE_SECTION_HEADER;
+
+#define SUBSECTION_ALIGN 16
+
+/***************************************************************/
+// PEWriter is derived from PESectionManager. While the base class just
+// manages the sections, PEWriter can actually write them out.
+
+class PEWriter : public PESectionMan
+{
+public:
+
+    // See ICeeFileGen.h for definition of createFlags
+    HRESULT Init(PESectionMan *pFrom, DWORD createFlags, LPCWSTR seedFileName = NULL);
+    HRESULT Cleanup();
+
+    // Finds section with given name.  returns 0 if not found
+    virtual PESection* getSection(const char* name);
+
+    // Create a new section
+    virtual HRESULT newSection(const char* name, PESection **section,
+                        unsigned flags=sdNone, unsigned estSize=0x10000,
+                        unsigned estRelocs=0x100);
+
+    HRESULT link();
+    HRESULT fixup(CeeGenTokenMapper *pMapper);
+    HRESULT write(__in const LPWSTR fileName);
+    HRESULT write(void **ppImage);
+
+    // calling these functions is optional
+    DWORD      getSectionAlignment();
+    void       setSectionAlignment(DWORD);
+    DWORD      getFileAlignment();
+    void       setFileAlignment(DWORD);
+    DWORD      getImageBase32();
+    void       setImageBase32(DWORD);
+    UINT64     getImageBase64();
+    void       setImageBase64(UINT64);
+    void       stripRelocations(bool val);        // default = false
+
+    void getHeaderInfo(PIMAGE_NT_HEADERS *ppNtHeaders, PIMAGE_SECTION_HEADER *ppSections, ULONG *pNumSections);
+
+    // these affect the charactertics in the NT file header
+    void setCharacteristics(unsigned mask);
+    void clearCharacteristics(unsigned mask);
+
+    // these affect the charactertics in the NT optional header
+    void setDllCharacteristics(unsigned mask);
+    void clearDllCharacteristics(unsigned mask);
+
+    // sets the SubSystem field in the optional header
+    void setSubsystem(unsigned subsystem, unsigned major, unsigned minor);
+
+    // specify the entry point as an offset into the text section. The
+    // method will convert into an RVA from the base
+    void setEntryPointTextOffset(unsigned entryPoint);
+
+    HRESULT setDirectoryEntry(PEWriterSection *section, ULONG entry, ULONG size, ULONG offset=0);
+
+
+    // get the RVA for the IL section
+    ULONG getIlRva();
+
+    // set the RVA for the IL section by supplying offset to the IL section
+    void setIlRva(DWORD offset);
+
+    unsigned getSubsystem();
+
+    size_t getImageBase();
+
+    void setEnCRvaBase(ULONG dataBase, ULONG rdataBase);
+
+    HRESULT getFileTimeStamp(DWORD *pTimeStamp);
+
+    IMAGE_NT_HEADERS32* ntHeaders32()    { return (IMAGE_NT_HEADERS32*) m_ntHeaders; }
+    IMAGE_NT_HEADERS64* ntHeaders64()    { return (IMAGE_NT_HEADERS64*) m_ntHeaders; }
+
+    bool isPE32()  // true  -> created a PE  32-bit PE file
+                   // false -> created a PE+ 64-bit PE file
+    { return (m_ntHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)); }
+
+    bool isI386()  // true  -> target machine is i386
+    { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_I386)); }
+
+    bool isIA64()  // true  -> target machine is ia64
+    { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_IA64)); }
+    
+    bool isAMD64()  // true  -> target machine is ia64
+    { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_AMD64)); }
+
+    bool isARM()  // true  -> target machine is ARM
+    { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_ARMNT)); }
+
+    bool createCorMainStub() // do we need the CorExeMain/CorDllMain stubs?
+    { return m_createCorMainStub; }
+
+private:
+    DWORD  m_ilRVA;
+    BOOL   m_encMode;
+    ULONG  m_dataRvaBase;
+    ULONG  m_rdataRvaBase;
+    ULONG  m_codeRvaBase;
+    DWORD  m_peFileTimeStamp;
+
+    HANDLE   m_file;
+
+    // "Seed" file information. The new file data will be "appended" to the seed file
+    // These are valid only if m_hSeedFile is valid
+
+    HANDLE              m_hSeedFile;
+    HANDLE              m_hSeedFileMap;
+    PEDecoder *         m_pSeedFileDecoder;
+    IMAGE_NT_HEADERS *  m_pSeedFileNTHeaders;
+    unsigned            m_iSeedSections;
+    IMAGE_SECTION_HEADER*m_pSeedSections;
+    IMAGE_SECTION_HEADER*m_pSeedSectionToAdd; // used only by newSection()
+
+    PEWriterSection **getSectStart() {
+        return (PEWriterSection**)sectStart;
+    }
+
+    PEWriterSection **getSectCur() {
+        return (PEWriterSection**)sectCur;
+    }
+
+    COUNT_T getSectCount() {
+        return COUNT_T(sectCur - sectStart);
+    }
+
+
+    IMAGE_DOS_HEADER    m_dosHeader;
+    IMAGE_NT_HEADERS *  m_ntHeaders;
+    DWORD               m_ntHeadersSize; // Size of IMAGE_NT_HEADERS (not including section headers)
+
+    unsigned            virtualPos;
+    unsigned            filePos;
+
+    PEWriterSection *   reloc;
+    PEWriterSection *   strtab;
+
+    IMAGE_SECTION_HEADER *headers, *headersEnd;
+
+    struct directoryEntry {
+        PEWriterSection *section;
+        ULONG offset;
+        ULONG size;
+    };
+
+    // Directory entries in the file header
+    directoryEntry  *   pEntries;
+    USHORT              cEntries;
+
+    bool   m_createCorMainStub;
+
+    // Helpers for link()
+    HRESULT linkSortSections(entry * entries,
+                             unsigned * piEntries, // OUT
+                             unsigned * piUniqueSections); // OUT
+    HRESULT linkSortHeaders(entry * entries, unsigned iEntries, unsigned iUniqueSections);
+    HRESULT linkPlaceSections(entry * entries, unsigned iEntries);
+    void setSectionIndex(IMAGE_SECTION_HEADER * h, unsigned sectionIndex);
+
+    HRESULT Open(__in LPCWSTR fileName);
+    HRESULT Write(const void *data, int size);
+    HRESULT Seek(int offset);
+    HRESULT Pad(int align);
+    HRESULT Close();
+};
+
+// This class encapsulates emitting the base relocs into the
+// .reloc section of the PE file, for the case where the image
+// does not get loaded at its preferred base address.
+
+class PERelocSection
+{
+ private:
+    PEWriterSection *   section;
+    unsigned            relocPage;
+    unsigned            relocSize;
+    DWORD *             relocSizeAddr;
+    unsigned            pages;
+
+#ifdef _DEBUG
+    unsigned            lastRVA;
+#endif
+
+ public:
+    PERelocSection(PEWriterSection *pBaseReloc);
+    void AddBaseReloc(unsigned rva, int type, unsigned short highAdj=0);
+    void Finish(bool isPE32);
+};
+
+class PEWriterSection : public PESection {
+
+public:
+
+    PEWriterSection(const char* name, unsigned flags,
+                    unsigned estSize, unsigned estRelocs)
+        : PESection(name, flags, estSize, estRelocs)  {}
+
+    virtual HRESULT  applyRelocs(IMAGE_NT_HEADERS *  pNtHeaders,
+                         PERelocSection *    relocSection,
+                         CeeGenTokenMapper * pTokenMapper,
+                         DWORD               rdataRvaBase,
+                         DWORD               dataRvaBase,
+                         DWORD               textRvaBase);
+
+    virtual HRESULT  write      (HANDLE file);
+    virtual unsigned writeMem   (void ** pMem);
+    virtual bool     isSeedSection() { return false; }
+
+};
+
+// This is for sections from the seed file. Their order needs to be maintained and
+// they need to be written to the output file.
+
+class PESeedSection : public PEWriterSection {
+
+public:
+
+    PESeedSection(PEDecoder * peDecoder, IMAGE_SECTION_HEADER * seedSection);
+
+    // PESection methods
+
+    unsigned dataLen() { return m_pSeedSectionHeader->SizeOfRawData; }
+    HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper) { return S_OK; }
+    char* getBlock(unsigned len, unsigned align) { _ASSERTE(!"PESeedSection"); return NULL; }
+    HRESULT truncate(unsigned newLen) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+    void writeSectReloc(unsigned val, CeeSection& relativeTo,
+                CeeSectionRelocType reloc,
+                CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return; }
+    HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo,
+                            CeeSectionRelocType reloc,
+                            CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+    HRESULT addSectReloc(unsigned offset, PESection *relativeTo,
+                            CeeSectionRelocType reloc,
+                            CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+    HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc,
+                            CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+//  unsigned char *name();
+//  unsigned flags();
+//  unsigned getBaseRVA();
+    int getDirEntry() { _ASSERTE(!"PESeedSection"); return 0; }
+    HRESULT directoryEntry(unsigned num) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+    char * computePointer(unsigned offset) const { _ASSERTE(!"PESeedSection"); return NULL; }
+    BOOL containsPointer(__in char *ptr) const { _ASSERTE(!"PESeedSection"); return FALSE; }
+    unsigned computeOffset(__in char *ptr) const { _ASSERTE(!"PESeedSection"); return 0; }
+    HRESULT cloneInstance(PESection *destination) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+
+    // PEWriterSection
+
+    HRESULT applyRelocs(IMAGE_NT_HEADERS *  pNtHeaders,
+                        PERelocSection *    relocSection,
+                        CeeGenTokenMapper * pTokenMapper,
+                        DWORD               rdataRvaBase,
+                        DWORD               dataRvaBase,
+                        DWORD               textRvaBase) { return S_OK; }
+
+    HRESULT  write(HANDLE file);
+    unsigned writeMem(void ** pMem);
+    bool isSeedSection() { return true; }
+
+protected:
+
+    PEDecoder *             m_pSeedFileDecoder;
+    IMAGE_SECTION_HEADER *  m_pSeedSectionHeader;
+
+};
+
+inline DWORD PEWriter::getSectionAlignment() {
+    return VAL32(m_ntHeaders->OptionalHeader.FileAlignment);
+}
+
+inline void PEWriter::setSectionAlignment(DWORD SectionAlignment) {
+
+    _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE);
+    m_ntHeaders->OptionalHeader.SectionAlignment = VAL32(SectionAlignment);
+}
+
+inline DWORD PEWriter::getFileAlignment() {
+    return m_ntHeaders->OptionalHeader.FileAlignment;
+}
+
+inline void PEWriter::setFileAlignment(DWORD fileAlignment) {
+    _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE);
+    m_ntHeaders->OptionalHeader.FileAlignment = VAL32(fileAlignment);
+}
+
+inline unsigned PEWriter::getSubsystem() {
+    return VAL16(m_ntHeaders->OptionalHeader.Subsystem);
+}
+
+inline void PEWriter::setSubsystem(unsigned subsystem, unsigned major, unsigned minor) {
+    m_ntHeaders->OptionalHeader.Subsystem = VAL16(subsystem);
+    m_ntHeaders->OptionalHeader.MajorSubsystemVersion = VAL16(major);
+    m_ntHeaders->OptionalHeader.MinorSubsystemVersion = VAL16(minor);
+}
+
+inline void PEWriter::setCharacteristics(unsigned mask) {
+    m_ntHeaders->FileHeader.Characteristics |= VAL16(mask);
+}
+
+inline void PEWriter::clearCharacteristics(unsigned mask) {
+    m_ntHeaders->FileHeader.Characteristics &= VAL16(~mask);
+}
+
+inline void PEWriter::setDllCharacteristics(unsigned mask) {
+    m_ntHeaders->OptionalHeader.DllCharacteristics |= VAL16(mask);
+}
+
+inline void PEWriter::clearDllCharacteristics(unsigned mask) {
+    m_ntHeaders->OptionalHeader.DllCharacteristics &= VAL16(~mask);
+}
+
+inline void PEWriter::setEntryPointTextOffset(unsigned offset) {
+    m_ntHeaders->OptionalHeader.AddressOfEntryPoint = VAL32(offset);
+}
+
+#endif
diff --git a/src/dlls/mscorpe/stdafx.cpp b/src/dlls/mscorpe/stdafx.cpp
new file mode 100644 (file)
index 0000000..9d644a3
--- /dev/null
@@ -0,0 +1,11 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//*****************************************************************************
+//     stdafx.cpp
+//
+//     Host for precompiled header.
+//
+//*****************************************************************************
+#include "stdafx.h"                                            // Precompiled header key.
diff --git a/src/dlls/mscorpe/stdafx.h b/src/dlls/mscorpe/stdafx.h
new file mode 100644 (file)
index 0000000..2d34ce2
--- /dev/null
@@ -0,0 +1,25 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//*****************************************************************************
+// stdafx.h
+//
+// Common include file for utility code.
+//*****************************************************************************
+#include <stdlib.h>            // for qsort
+#include <windows.h>
+#include <time.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#define FEATURE_NO_HOST     // Do not use host interface
+#include <utilcode.h>
+
+#include <corpriv.h>
+
+#include "pewriter.h"
+#include "ceegen.h"
+#include "ceefilegenwriter.h"
+#include "ceesectionstring.h"
diff --git a/src/dlls/mscorpe/stubs.h b/src/dlls/mscorpe/stubs.h
new file mode 100644 (file)
index 0000000..e232591
--- /dev/null
@@ -0,0 +1,170 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//*****************************************************************************
+// Stubs.h
+//
+// This file contains a template for the default entry point stubs of a COM+
+// IL only program.  One can emit these stubs (with some fix-ups) and make
+// the code supplied the entry point value for the image.  The fix-ups will
+// in turn cause mscoree.dll to be loaded and the correct entry point to be
+// called.
+//
+// Note: Although these stubs contain x86 specific code, they are used
+// for all platforms
+//
+//*****************************************************************************
+#ifndef __STUBS_H__
+#define __STUBS_H__
+
+//*****************************************************************************
+// This stub is designed for a x86 Windows application.  It will call the
+// _CorExeMain function in mscoree.dll.  This entry point will in turn load
+// and run the IL program.
+//
+//    jump _CorExeMain();
+//
+// The code jumps to the imported function _CorExeMain using the iat.
+// The address in the template is address of the iat entry which is 
+// fixed up by the loader when the image is paged in.
+//*****************************************************************************
+
+SELECTANY const BYTE ExeMainX86Template[] =
+{
+       // Jump through IAT to _CorExeMain
+       0xFF, 0x25,                             // jmp [iat:_CorDllMain entry]
+               0x00, 0x00, 0x00, 0x00,         //   address to replace
+
+};
+
+#define ExeMainX86TemplateSize         sizeof(ExeMainX86Template)
+#define CorExeMainX86IATOffset         2
+
+//*****************************************************************************
+// This stub is designed for a x86 Windows application.  It will call the 
+// _CorDllMain function in mscoree.dll with with the base entry point for
+// the loaded DLL.  This entry point will in turn load and run the IL program.
+//
+//    jump _CorDllMain
+//
+// The code jumps to the imported function _CorExeMain using the iat.
+// The address in the template is address of the iat entry which is 
+// fixed up by the loader when the image is paged in.
+//*****************************************************************************
+
+SELECTANY const BYTE DllMainX86Template[] = 
+{
+       // Jump through IAT to CorDllMain 
+       0xFF, 0x25,                             // jmp [iat:_CorDllMain entry]
+               0x00, 0x00, 0x00, 0x00,         //   address to replace
+};
+
+#define DllMainX86TemplateSize         sizeof(DllMainX86Template)
+#define CorDllMainX86IATOffset         2
+
+//*****************************************************************************
+// This stub is designed for a AMD64 Windows application.  It will call the
+// _CorExeMain function in mscoree.dll.  This entry point will in turn load
+// and run the IL program.
+//
+//    mov rax, _CorExeMain();
+//    jmp [rax]
+//
+// The code jumps to the imported function _CorExeMain using the iat.
+// The address in the template is address of the iat entry which is 
+// fixed up by the loader when the image is paged in.
+//*****************************************************************************
+
+SELECTANY const BYTE ExeMainAMD64Template[] =
+{
+       // Jump through IAT to _CorExeMain
+       0x48, 0xA1,                             // rex.w rex.b mov rax,[following address]
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//address of iat:_CorExeMain entry
+    0xFF, 0xE0              // jmp [rax]
+};
+
+#define ExeMainAMD64TemplateSize               sizeof(ExeMainAMD64Template)
+#define CorExeMainAMD64IATOffset               2
+
+//*****************************************************************************
+// This stub is designed for a AMD64 Windows application.  It will call the 
+// _CorDllMain function in mscoree.dll with with the base entry point for
+// the loaded DLL.  This entry point will in turn load and run the IL program.
+//
+//    mov rax, _CorDllMain();
+//    jmp [rax]
+//
+// The code jumps to the imported function _CorDllMain using the iat.
+// The address in the template is address of the iat entry which is 
+// fixed up by the loader when the image is paged in.
+//*****************************************************************************
+
+SELECTANY const BYTE DllMainAMD64Template[] = 
+{
+       // Jump through IAT to CorDllMain 
+       0x48, 0xA1,                             // rex.w rex.b mov rax,[following address]
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//address of iat:_CorDllMain entry
+    0xFF, 0xE0              // jmp [rax]
+};
+
+#define DllMainAMD64TemplateSize               sizeof(DllMainAMD64Template)
+#define CorDllMainAMD64IATOffset               2
+
+//*****************************************************************************
+// This stub is designed for an ia64 Windows application.  It will call the
+// _CorExeMain function in mscoree.dll.  This entry point will in turn load
+// and run the IL program.
+//
+//    jump _CorExeMain();
+//
+// The code jumps to the imported function _CorExeMain using the iat.
+// We set the value of gp to point at the iat table entry for _CorExeMain
+//*****************************************************************************
+
+SELECTANY const BYTE ExeMainIA64Template[] =
+{
+    // ld8    r9  = [gp]    ;;
+    // ld8    r10 = [r9],8
+    // nop.i                ;;
+    // ld8    gp  = [r9]
+    // mov    b6  = r10
+    // br.cond.sptk.few  b6
+    //
+    0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 
+    0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 
+    0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 
+    0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00
+};
+
+#define ExeMainIA64TemplateSize                sizeof(ExeMainIA64Template)
+
+//*****************************************************************************
+// This stub is designed for an ia64 Windows application.  It will call the 
+// _CorDllMain function in mscoree.dll with with the base entry point for
+// the loaded DLL.  This entry point will in turn load and run the IL program.
+//
+//    jump _CorDllMain
+//
+// The code jumps to the imported function _CorExeMain using the iat.
+// We set the value of gp to point at the iat table entry for _CorExeMain
+//*****************************************************************************
+
+SELECTANY const BYTE DllMainIA64Template[] = 
+{
+    // ld8    r9  = [gp]    ;;
+    // ld8    r10 = [r9],8
+    // nop.i                ;;
+    // ld8    gp  = [r9]
+    // mov    b6  = r10
+    // br.cond.sptk.few  b6
+    //
+    0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 
+    0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 
+    0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 
+    0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00
+};
+
+#define DllMainIA64TemplateSize                sizeof(DllMainIA64Template)
+
+#endif  // __STUBS_H__
diff --git a/src/dlls/mscorpe/utilcodeinit.cpp b/src/dlls/mscorpe/utilcodeinit.cpp
new file mode 100644 (file)
index 0000000..3c50bb3
--- /dev/null
@@ -0,0 +1,12 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#include "stdafx.h"
+#include <utilcode.h>
+
+EXTERN_C void __stdcall InitializeSxS(CoreClrCallbacks const & callbacks)
+{
+    InitUtilcode(callbacks);
+}
diff --git a/src/ilasm/.gitmirrorall b/src/ilasm/.gitmirrorall
new file mode 100644 (file)
index 0000000..9ee5c57
--- /dev/null
@@ -0,0 +1 @@
+This folder will be mirrored by the Git-TFS Mirror recursively.
\ No newline at end of file
diff --git a/src/ilasm/Assembler.h b/src/ilasm/Assembler.h
new file mode 100644 (file)
index 0000000..f3e4914
--- /dev/null
@@ -0,0 +1,1186 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+/************************************************************************/
+/*                           Assembler.h                                */
+/************************************************************************/
+
+#ifndef Assember_h
+#define Assember_h
+
+#define NEW_INLINE_NAMES
+
+#include "binstr.h"
+
+#include "specstrings.h"
+
+#include "asmenum.h"
+#include "asmtemplates.h"
+
+// Disable the "initialization of static local vars is no thread safe" error
+#ifdef _MSC_VER
+#pragma warning(disable : 4640)
+#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
+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;
+/**************************************************************************/
+#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;
+};
+#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;
+    }
+};
+
+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;
+
+    IMetaDataDispenserEx *m_pDisp;
+    IMetaDataEmit2      *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();
+    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 char *pszFQN);
+    BOOL EmitFieldRef(__in_z __in char *pszArg, int opcode);
+    BOOL EmitSwitchData(__in_z __in char *pszArg);
+    mdToken ResolveClassRef(mdToken tkResScope, __in __nullterminated char *pszClassName, Class** ppClass);
+    mdToken ResolveTypeSpec(BinStr* typeSpec);
+    mdToken GetBaseAsmRef();
+    mdToken GetAsmRef(__in __nullterminated 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;
+
+    // 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);
+    
+    HRESULT AllocateStrongNameSignature();
+    HRESULT StrongNameSign();
+    BinStr* EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps);
+
+    // 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 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);
+    HRESULT GetSignatureKey();
+};
+
+#endif  // Assember_h
+
+#ifdef _MSC_VER
+#pragma warning(default : 4640)
+#endif
+
+
diff --git a/src/ilasm/MscorpeSxS.cpp b/src/ilasm/MscorpeSxS.cpp
new file mode 100644 (file)
index 0000000..c10d772
--- /dev/null
@@ -0,0 +1,24 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+// 
+// File: MscorpeSxS.cpp
+// 
+
+// 
+// This file defines a wrapper for SxS version of mscorpe.dll (dynamically loaded via shim).
+// 
+#include "ilasmpch.h"
+
+#include "MscorpeSxS.h"
+
+#include <LegacyActivationShim.h>
+
+// Loads mscorpe.dll (uses shim)
+HRESULT 
+LoadMscorpeDll(HMODULE * phModule)
+{
+    // Load SxS version of mscorpe.dll (i.e. mscorpehost.dll) and initialize it
+    return LegacyActivationShim::LoadLibraryShim(L"mscorpe.dll", NULL, NULL, phModule);
+}
diff --git a/src/ilasm/MscorpeSxS.h b/src/ilasm/MscorpeSxS.h
new file mode 100644 (file)
index 0000000..92b15b7
--- /dev/null
@@ -0,0 +1,21 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+// 
+// File: MscorpeSxS.h
+// 
+
+// 
+// This file defines a wrapper for SxS version of mscorpe.dll (dynamically loaded via shim).
+// 
+
+#pragma once
+
+#include <MscorpeSxSWrapper.h>
+
+// Loads mscorpe.dll (uses shim)
+HRESULT LoadMscorpeDll(HMODULE * phModule);
+
+// Wrapper for mscorpe.dll calls
+typedef MscorpeSxSWrapper<LoadMscorpeDll> MscorpeSxS;
diff --git a/src/ilasm/Native.rc b/src/ilasm/Native.rc
new file mode 100644 (file)
index 0000000..41216be
--- /dev/null
@@ -0,0 +1,9 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#define FX_VER_FILEDESCRIPTION_STR "Microsoft .NET Framework IL assembler\0"
+
+#include <fxver.h>
+#include <fxver.rc>
diff --git a/src/ilasm/asmenum.h b/src/ilasm/asmenum.h
new file mode 100644 (file)
index 0000000..b8bd499
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+#ifndef __asmenum_h__
+#define __asmenum_h__
+
+#include "openum.h"
+
+typedef struct
+{
+    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/ilasm/asmman.cpp b/src/ilasm/asmman.cpp
new file mode 100644 (file)
index 0000000..c4aa0e5
--- /dev/null
@@ -0,0 +1,1264 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// asmman.cpp - manifest info handling (implementation of class AsmMan, see asmman.hpp)
+//
+
+//
+#include "ilasmpch.h"
+
+#include "assembler.h"
+#include "strongname.h"
+#include "LegacyActivationShim.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 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 char* szAsmRefName)
+{
+    AsmManAssembly* tmp = GetAsmRefByName(szAsmRefName);
+    return(tmp ? tmp->tkTok : mdAssemblyRefNil);
+}
+//==============================================================================================================
+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);
+        }
+    }
+}
+//==============================================================================================================
+// Borrowed from VM\assembly.cpp
+
+HRESULT GetHash(__in LPWSTR moduleName,
+                          ALG_ID iHashAlg,
+                          BYTE** pbCurrentValue,  // should be NULL
+                          DWORD *cbCurrentValue)
+{
+    HRESULT     hr = E_FAIL;
+    HCRYPTPROV  hProv = 0;
+    HCRYPTHASH  hHash = 0;
+    DWORD       dwCount = sizeof(DWORD);
+    PBYTE       pbBuffer = NULL;
+    DWORD       dwBufferLen;
+    HANDLE      hFile = INVALID_HANDLE_VALUE;
+    HANDLE      hMapFile = NULL;
+    
+    hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ,
+                         0, OPEN_EXISTING, 0, 0);
+    if (hFile == INVALID_HANDLE_VALUE) return E_FAIL;
+
+    dwBufferLen = SafeGetFileSize(hFile,NULL);
+    if (dwBufferLen == 0xffffffff)
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        goto exit;
+    }
+    hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+    if (hMapFile == NULL) goto exit;
+
+    pbBuffer = (PBYTE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
+    if (pbBuffer == NULL) goto exit;
+
+    // No need to late bind this stuff, all these crypto API entry points happen
+    // to live in ADVAPI32.
+
+    if ((!WszCryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) ||
+        (!CryptCreateHash(hProv, iHashAlg, 0, 0, &hHash)) ||
+        (!CryptHashData(hHash, pbBuffer, dwBufferLen, 0)) ||
+        (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *) cbCurrentValue, 
+                            &dwCount, 0))) {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        goto exit;
+    }
+
+    *pbCurrentValue = new BYTE[*cbCurrentValue];
+    if (!(*pbCurrentValue)) {
+        hr = E_OUTOFMEMORY;
+        goto exit;
+    }
+
+    if(!CryptGetHashParam(hHash, HP_HASHVAL, *pbCurrentValue, cbCurrentValue, 0)) {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        delete[] *pbCurrentValue;
+        *pbCurrentValue = 0;
+        goto exit;
+    }
+
+    hr = S_OK;
+
+ exit:
+    if (pbBuffer) UnmapViewOfFile(pbBuffer);
+    if (hMapFile) CloseHandle(hMapFile); 
+    CloseHandle(hFile);
+    if (hHash)
+        CryptDestroyHash(hHash);
+    if (hProv)
+        CryptReleaseContext(hProv, 0);
+
+    return hr;
+}
+//==============================================================================================================
+
+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
+                if(FAILED(GetHash(wzUniBuf,(ALG_ID)(m_pAssembly->ulHashAlgorithm),&pHash,&cbHash)))
+                {
+                    pHash = NULL;
+                    cbHash = 0;
+                }
+                else
+                {
+                    tmp->pHash = new BinStr(pHash,cbHash);
+                }
+            }
+        }
+        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");
+        _ASSERTE(pAssembly != NULL);
+        PREFIX_ASSUME(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;
+            }
+            if(m_pCurAsmRef->isAutodetect)
+            {
+                IAssemblyName* pIAsmName;
+                HRESULT hr;
+                // Convert name to Unicode
+                WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf);
+                hr = CreateAssemblyNameObject(&pIAsmName,wzUniBuf,CANOF_PARSE_DISPLAY_NAME,NULL);
+                if(SUCCEEDED(hr))
+                {
+                    // set enumeration criteria: what is known about AsmRef (besides name)
+                    if(m_pCurAsmRef->usVerMajor != (USHORT)0xFFFF)
+                        pIAsmName->SetProperty(ASM_NAME_MAJOR_VERSION,&(m_pCurAsmRef->usVerMajor),2);
+                    if(m_pCurAsmRef->usVerMinor != (USHORT)0xFFFF)
+                        pIAsmName->SetProperty(ASM_NAME_MINOR_VERSION,&(m_pCurAsmRef->usVerMinor),2);
+                    if(m_pCurAsmRef->usBuild != (USHORT)0xFFFF)
+                        pIAsmName->SetProperty(ASM_NAME_BUILD_NUMBER,&(m_pCurAsmRef->usBuild),2);
+                    if(m_pCurAsmRef->usRevision != (USHORT)0xFFFF)
+                        pIAsmName->SetProperty(ASM_NAME_REVISION_NUMBER,&(m_pCurAsmRef->usRevision),2);
+                    if(m_pCurAsmRef->pPublicKeyToken)
+                        pIAsmName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN,
+                                               m_pCurAsmRef->pPublicKeyToken->ptr(),
+                                               m_pCurAsmRef->pPublicKeyToken->length());
+                    if(m_pCurAsmRef->pLocale)
+                        pIAsmName->SetProperty(ASM_NAME_CULTURE,
+                                               m_pCurAsmRef->pLocale->ptr(),
+                                               m_pCurAsmRef->pLocale->length());
+
+                    // enumerate assemblies
+                    IAssemblyEnum* pIAsmEnum = NULL;
+                    hr = CreateAssemblyEnum(&pIAsmEnum, NULL, pIAsmName, ASM_CACHE_GAC, NULL);
+                    if(SUCCEEDED(hr))
+                    {
+                        IAssemblyName* pIAsmNameFound;
+                        IAssemblyName* pIAsmNameLatestVer = NULL;
+                        ULONGLONG   ullVer=0, ullVerLatest=0;
+                        DWORD  dwVerHi, dwVerLo;
+    
+                        // find the latest and greatest, if any
+                        for(;;)
+                        {
+                            pIAsmNameFound = NULL;
+                            hr = pIAsmEnum->GetNextAssembly(NULL,&pIAsmNameFound,0); 
+                            if(SUCCEEDED(hr) && pIAsmNameFound)
+                            {
+    
+                                pIAsmNameFound->GetVersion(&dwVerHi,&dwVerLo);
+                                ullVer = (ULONGLONG)dwVerHi;
+                                ullVer <<= sizeof(DWORD);
+                                ullVer |= dwVerLo;
+                                if(ullVer > ullVerLatest)
+                                {
+                                    if(pIAsmNameLatestVer)
+                                       pIAsmNameLatestVer->Release(); 
+                                    ullVerLatest = ullVer;
+                                    pIAsmNameLatestVer = pIAsmNameFound;
+                                }
+                                else
+                                    pIAsmNameFound->Release();
+                            }
+                            else break;
+                        }
+                        // if found, fill the gaps
+                        if(pIAsmNameLatestVer)
+                        {
+                            DWORD cbSize=0;
+                            USHORT usDummy=0;
+
+                            if(m_pCurAsmRef->pPublicKeyToken == NULL)
+                            {
+                                cbSize = 1024;
+                                pIAsmNameLatestVer->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN,
+                                                wzUniBuf, &cbSize);
+                                if(cbSize)
+                                {
+                                    if((m_pCurAsmRef->pPublicKeyToken = new BinStr()))
+                                        memcpy(m_pCurAsmRef->pPublicKeyToken->getBuff(cbSize),
+                                            wzUniBuf, cbSize);
+                                }
+                            }
+    
+                            if(m_pCurAsmRef->usVerMajor == (USHORT)0xFFFF)
+                            {
+                                cbSize = (DWORD)sizeof(WORD);
+                                pIAsmNameLatestVer->GetProperty(ASM_NAME_MAJOR_VERSION,
+                                                &usDummy, &cbSize);
+                                m_pCurAsmRef->usVerMajor = usDummy;
+                            }
+                            if(m_pCurAsmRef->usVerMinor == (USHORT)0xFFFF)
+                            {
+                                cbSize = (DWORD)sizeof(WORD);
+                                pIAsmNameLatestVer->GetProperty(ASM_NAME_MINOR_VERSION,
+                                                &usDummy, &cbSize);
+                                m_pCurAsmRef->usVerMinor = usDummy;
+                            }
+                            if(m_pCurAsmRef->usBuild == (USHORT)0xFFFF)
+                            {
+                                cbSize = (DWORD)sizeof(WORD);
+                                pIAsmNameLatestVer->GetProperty(ASM_NAME_BUILD_NUMBER,
+                                                &usDummy, &cbSize);
+                                m_pCurAsmRef->usBuild = usDummy;
+                            }
+                            if(m_pCurAsmRef->usRevision == (USHORT)0xFFFF)
+                            {
+                                cbSize = (DWORD)sizeof(WORD);
+                                pIAsmNameLatestVer->GetProperty(ASM_NAME_REVISION_NUMBER,
+                                                &usDummy, &cbSize);
+                                m_pCurAsmRef->usRevision = usDummy;
+                            }
+                            
+                            if(m_pCurAsmRef->pLocale == NULL)
+                            {
+                                cbSize = 1024;
+                                pIAsmNameLatestVer->GetProperty(ASM_NAME_CULTURE,
+                                                wzUniBuf, &cbSize);
+
+                                if(cbSize > (DWORD)sizeof(WCHAR))
+                                {
+                                    if((m_pCurAsmRef->pLocale = new BinStr()))
+                                        memcpy(m_pCurAsmRef->pLocale->getBuff(cbSize),
+                                            wzUniBuf, cbSize);
+                                }
+                            }
+                            pIAsmNameLatestVer->Release(); 
+                        }
+                        else
+                            report->warn("Failed to autodetect assembly '%s'\n",m_pCurAsmRef->szName);
+                        // if no assembly found, leave it as is, it might be not a GAC assembly
+    
+                        pIAsmEnum->Release();
+                    }
+                    else
+                        report->error("Failed to enum assemblies %S, hr=0x%08X\n",wzUniBuf,hr);
+                    pIAsmName->Release();
+                }
+                else
+                    report->error("Failed to create assembly name object for %S, hr=0x%08X\n",wzUniBuf,hr);
+            } // end if isAutodetect
+            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'@')
+                {
+                    // Extract public key from container (works whether
+                    // container has just a public key or an entire key
+                    // pair).
+                    m_sStrongName.m_wzKeyContainer = &((Assembler*)m_pAssembler)->m_wzKeySourceName[1];
+                    if (FAILED(hr = LegacyActivationShim::StrongNameGetPublicKey_HRESULT(
+                        m_sStrongName.m_wzKeyContainer, 
+                        NULL, 
+                        0, 
+                        &m_sStrongName.m_pbPublicKey, 
+                        &m_sStrongName.m_cbPublicKey)))
+                    {
+                        report->error("Failed to extract public key from '%S': 0x%08X\n",m_sStrongName.m_wzKeyContainer,hr);
+                        m_pCurAsmRef = NULL;
+                        return;
+                    }
+                    m_sStrongName.m_fFullSign = TRUE;
+                    m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedBySNApi;
+                }
+                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)
+                    {
+                        m_sStrongName.m_pbPrivateKey = m_sStrongName.m_pbPublicKey;
+                        m_sStrongName.m_cbPrivateKey = m_sStrongName.m_cbPublicKey;
+
+                        m_sStrongName.m_pbPublicKey = NULL;
+                        m_sStrongName.m_cbPublicKey = NULL;
+                        m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated;
+
+                        // Retrieve the public key portion as a byte blob.
+                        if (FAILED(hr = LegacyActivationShim::StrongNameGetPublicKey_HRESULT(
+                            NULL, 
+                            m_sStrongName.m_pbPrivateKey, 
+                            m_sStrongName.m_cbPrivateKey, 
+                            &m_sStrongName.m_pbPublicKey, 
+                            &m_sStrongName.m_cbPublicKey)))
+                        {
+                            report->error("Failed to extract public key: 0x%08X\n",hr);
+                            m_pCurAsmRef = NULL;
+                            return;
+                        }
+    
+                        m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedBySNApi;
+                    }
+                }
+            }
+            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,'\\');
+                    if(pwz == NULL) pwz = wcsrchr(wzFileName,':');
+                    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/ilasm/asmman.hpp b/src/ilasm/asmman.hpp
new file mode 100644 (file)
index 0000000..3db7ae2
--- /dev/null
@@ -0,0 +1,301 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// asmman.hpp - header file for manifest-related ILASM functions
+//
+
+#ifndef ASMMAN_HPP
+#define ASMMAN_HPP
+
+#include "strongname.h"
+#include "LegacyActivationShim.h"
+#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 == AllocatedBySNApi)
+        {
+            LegacyActivationShim::StrongNameFreeBuffer(m_pbPublicKey);
+        }
+        else 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 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);
+
+    mdToken             GetFileTokByName(__in __nullterminated char* szFileName);
+    mdToken             GetAsmRefTokByName(__in __nullterminated char* szAsmRefName);
+    mdToken             GetAsmTokByName(__in __nullterminated 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/ilasm/asmparse.h b/src/ilasm/asmparse.h
new file mode 100644 (file)
index 0000000..9c1ced2
--- /dev/null
@@ -0,0 +1,327 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+/**************************************************************************/
+/* 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 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 L"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* nextcharA(__in __nullterminated char* pos);
+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);
+    ~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
+    DWORD IsItUnicode(CONST LPVOID pBuff, int cb, LPINT lpi);
+       HANDLE  hstdout;
+       HANDLE  hstderr;
+
+private:
+       friend void yyerror(__in __nullterminated 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/ilasm/asmparse.y b/src/ilasm/asmparse.y
new file mode 100644 (file)
index 0000000..6619cfb
--- /dev/null
@@ -0,0 +1,2053 @@
+%{
+
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// 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_ 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_ IA64_ AMD64_ ARM_
+        /* 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 attributes */
+%token IN_ OUT_ OPT_ 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
+
+        /* 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);
+                                                            }
+                        | _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; }
+                        ;
+
+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 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_ '[' 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 IA64_                       { SET_PA($$,$1,afPA_IA64); }
+                        | asmAttr AMD64_                      { SET_PA($$,$1,afPA_AMD64); }
+                        | asmAttr ARM_                        { SET_PA($$,$1,afPA_ARM); }
+                        ;
+
+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/ilasm/asmtemplates.h b/src/ilasm/asmtemplates.h
new file mode 100644 (file)
index 0000000..7ec206e
--- /dev/null
@@ -0,0 +1,846 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#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;
+};
+
+
+#if (0)
+template <class T>
+class FIFO
+{
+public:
+    inline FIFO() { m_pHead = m_pTail = NULL; m_ulCount = 0;};
+    inline ~FIFO() {T *val; while(val = POP()) delete val; };
+    void PUSH(T *item) 
+    {
+        m_pTemp = new LIST_EL <T>(item); 
+        if(m_pTail) m_pTail->m_Next = m_pTemp;
+        m_pTail = m_pTemp;
+        if(m_pHead == NULL) m_pHead = m_pTemp;
+        m_ulCount++;
+    };
+    T* POP() 
+    {
+        T* ret = NULL;
+        if(m_pTemp = m_pHead)
+        {
+            m_pHead = m_pHead->m_Next;
+            ret = m_pTemp->m_Ptr;
+            delete m_pTemp;
+            if(m_pHead == NULL) m_pTail = NULL;
+            m_ulCount--;
+        }
+        return ret;
+    };
+    ULONG COUNT() { return m_ulCount; };
+    T* PEEK(ULONG idx)
+    {
+        T* ret = NULL;
+        ULONG   i;
+        if(idx < m_ulCount)
+        {
+            if(idx == m_ulCount-1) m_pTemp = m_pTail;
+            else for(m_pTemp = m_pHead, i = 0; i < idx; m_pTemp = m_pTemp->m_Next, i++);
+            ret = m_pTemp->m_Ptr;
+        }
+        return ret;
+    };
+private:
+    LIST_EL <T> *m_pHead;
+    LIST_EL <T> *m_pTail;
+    LIST_EL <T> *m_pTemp;
+    ULONG       m_ulCount;
+};
+#else
+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;
+};
+#endif
+
+
+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/ilasm/assem.cpp b/src/ilasm/assem.cpp
new file mode 100644 (file)
index 0000000..8f30613
--- /dev/null
@@ -0,0 +1,1613 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// File: assem.cpp
+//
+
+//
+// COM+ IL assembler
+//
+#include "ilasmpch.h"
+
+#define INITGUID
+
+#define DECLARE_DATA
+
+#include "assembler.h"
+#include "MscorpeSxS.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);
+}
+
+
+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);
+        MscorpeSxS::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_pDisp != NULL)
+    {
+        m_pDisp->Release();
+        m_pDisp = NULL;
+    }
+
+    if (m_fDidCoInitialise)
+        CoUninitialize();
+
+}
+
+
+BOOL Assembler::Init()
+{
+    if(!m_fDidCoInitialise)
+    {
+        if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
+            return FALSE;
+        m_fDidCoInitialise = TRUE;
+    }
+    if (m_pCeeFileGen != NULL) {
+        if (m_pCeeFile)
+            m_pCeeFileGen->DestroyCeeFile(&m_pCeeFile);
+        MscorpeSxS::DestroyICeeFileGen(&m_pCeeFileGen);
+        m_pCeeFileGen = NULL;
+    }
+    if (FAILED(MscorpeSxS::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;
+
+    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(fIsInterface  && (!IsMdStatic(pMethod->m_Attr))) strcat_s(sz,1024," non-static declared in interface");
+        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)
+{
+    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;
+                HRESULT hr;
+                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 && (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();
+            } // 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,L"$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, L".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* ptk;
+        mdToken tk;
+        for(i = 0; i < pMethod->m_NumTyPars; i++)
+        {
+            //ptk = (pMethod->m_TyParBounds[i] == NULL)? NULL :  (mdToken*)(pMethod->m_TyParBounds[i]->ptr());
+            //if(FAILED(m_pEmitter->DefineGenericParam(MethodToken,i,0,pMethod->m_TyParNames[i],0,ptk,&tk)))
+            ptk = (pMethod->m_TyPars[i].Bounds() == NULL)? NULL :  (mdToken*)(pMethod->m_TyPars[i].Bounds()->ptr());
+            if(FAILED(m_pEmitter->DefineGenericParam(MethodToken,i,pMethod->m_TyPars[i].Attrs(),pMethod->m_TyPars[i].Name(),0,ptk,&tk)))
+                report->error("Unable to define generic param'\n");
+            else
+                EmitCustomAttributes(tk, pMethod->m_TyPars[i].CAList());
+        }
+    }
+    //--------------------------------------------------------------------------------
+    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 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,L"$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* ptk;
+        mdToken tk;
+        for(i = 0; i < pClass->m_NumTyPars; i++)
+        {
+            //ptk = (pClass->m_TyParBounds[i] == NULL)? NULL :  (mdToken*)(pClass->m_TyParBounds[i]->ptr());
+            //if(FAILED(m_pEmitter->DefineGenericParam(pClass->m_cl,i,pClass->m_TyParAttrs[i],pClass->m_TyParNames[i],0,ptk,&tk)))
+            ptk = (pClass->m_TyPars[i].Bounds() == NULL)? NULL :  (mdToken*)(pClass->m_TyPars[i].Bounds()->ptr());
+            if(FAILED(m_pEmitter->DefineGenericParam(pClass->m_cl,i,pClass->m_TyPars[i].Attrs(),pClass->m_TyPars[i].Name(),0,ptk,&tk)))
+                report->error("Unable to define generic param'\n");
+            else
+                EmitCustomAttributes(tk, pClass->m_TyPars[i].CAList());
+        }
+    }
+    
+    
+    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);
+       case 10: c+=((unsigned)k[9] << 16);
+       case 9 : c+=((unsigned)k[8] << 8);
+          /* the first byte of c is reserved for the length */
+       case 8 : b+=((unsigned)k[7] << 24);
+       case 7 : b+=((unsigned)k[6] << 16);
+       case 6 : b+=((unsigned)k[5] << 8);
+       case 5 : b+=k[4];
+       case 4 : a+=((unsigned)k[3] << 24);
+       case 3 : a+=((unsigned)k[2] << 16);
+       case 2 : a+=((unsigned)k[1] << 8);
+       case 1 : a+=k[0];
+     /* case 0: nothing left to add */
+   }
+   mix(a,b,c);
+   /*-------------------------------------------- report the result */
+   return c;
+}
+
diff --git a/src/ilasm/assembler.cpp b/src/ilasm/assembler.cpp
new file mode 100644 (file)
index 0000000..d83bf7c
--- /dev/null
@@ -0,0 +1,2466 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// 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 char *pszFullClassName, Class** ppClass)
+{
+    Class *pClass = NULL;
+    mdToken tkRet = mdTokenNil;
+    mdToken *ptkSpecial = NULL;
+
+    if(pszFullClassName == NULL) return mdTokenNil;
+#if (0)
+    if (m_fInitialisedMetaData == FALSE)
+    {
+        if (FAILED(InitMetaData())) // impl. see WRITER.CPP
+        {
+            _ASSERTE(0);
+            if(ppClass) *ppClass = NULL;
+            return mdTokenNil;
+        }
+    }
+#endif
+
+    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) : 
+        len_(typeSpec->length()), 
+        hash_(typeSpec->length()), 
+        token_(mdTokenNil), 
+        ptr_(typeSpec->ptr())
+    {        
+        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) : 
+        len_(t.len_), 
+        hash_(t.hash_),
+        token_(tk), 
+        ptr_(new unsigned __int8[t.len_])
+    {
+        _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
+    const 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 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()
+{
+    if(RidFromToken(m_pManifest->GetAsmRefTokByName("System.Runtime")) != 0)
+    {
+        return GetAsmRef("System.Runtime");
+    }
+
+    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_TyParBounds, &m_pCurClass->m_TyParNames, &m_pCurClass->m_TyParAttrs);
+            m_pCurClass->m_NumTyPars = m_TyParList->ToArray(&(m_pCurClass->m_TyPars));
+            delete m_TyParList;
+            m_TyParList = NULL;
+        }
+        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");
+
+            }
+            if(!IsMdStatic(flags))
+            {
+                if(IsTdInterface(m_pCurClass->m_Attr))
+                {
+                    if(!IsMdPublic(flags)) report->error("Non-public instance method in interface\n");
+                    if((!(IsMdVirtual(flags) && IsMdAbstract(flags))))
+                    {
+                        if(OnErrGo) report->error("Non-virtual, non-abstract instance method in interface\n");
+                        else
+                        {
+                            report->warn("Non-virtual, non-abstract instance method in interface, set to such\n");
+                            flags = (CorMethodAttr)(flags |mdVirtual | mdAbstract);
+                        }
+                    }
+    
+                }
+            }
+            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_TyParBounds,
+                //&m_pCurMethod->m_TyParNames, NULL);
+                m_pCurMethod->m_NumTyPars = typars->ToArray(&(m_pCurMethod->m_TyPars));
+                delete typars;
+                m_TyParList = NULL;
+            }
+            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,L"$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;
+                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++;
+        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)
+        {
+            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);
+            delete instr;
+            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);
+        delete instr;
+    }
+    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");
+        delete instr;
+    }
+    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;
+    long    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 = (long)(UINT_PTR)pLbls->Label;
+            if (m_fDisplayTraceOutput) report->msg("%d\n", offset);
+        }
+        EmitBytes((BYTE *)&offset, sizeof(long));
+    }
+    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;
+#if (0)
+    // Emit MemberRef for .ctor
+    mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetAsmRef("mscorlib");
+    char buffer[64];
+    BinStr  *pbsSig = new BinStr();
+
+    strcpy(buffer,"System.Security.Permissions.SecurityAction");
+    mdToken tkSecAction = ResolveClassRef(tkMscorlib,buffer, NULL);
+
+    pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS);
+    pbsSig->appendInt8(1); //corEmitInt(pbsSig,1);
+    pbsSig->appendInt8(ELEMENT_TYPE_VOID);
+    pbsSig->appendInt8(ELEMENT_TYPE_VALUETYPE);
+    cnt = CorSigCompressToken(tkSecAction, pbsSig->getBuff(5));
+    pbsSig->remove(5 - cnt);
+    
+    char* szName = new char[16];
+    strcpy(szName,".ctor");
+    MakeMemberRef(tkSecAttr,szName,pbsSig);
+#endif
+
+    // 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;
+
+    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)))
+            {
+                if (dwErrorIndex == uCount)
+                {
+                    report->error("Failed to define security attribute set for 0x%08X\n", token);
+                }
+                else
+                {
+                    _ASSERT(uCount > dwErrorIndex);
+                    if (uCount > dwErrorIndex)
+                    {
+                        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;
+        pMID->m_fNew = TRUE;
+        if(pMID == NULL)
+        {
+            report->error("Failed to allocate MethodImpl Descriptor\n");
+            return;
+        }
+        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)
+            {
+                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;
+    }
+}
diff --git a/src/ilasm/binstr.h b/src/ilasm/binstr.h
new file mode 100644 (file)
index 0000000..0b8ee17
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+/**************************************************************************/
+/* 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/ilasm/class.hpp b/src/ilasm/class.hpp
new file mode 100644 (file)
index 0000000..027021d
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// 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;
+    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/ilasm/extractGrammar.pl b/src/ilasm/extractGrammar.pl
new file mode 100644 (file)
index 0000000..b5a99b1
--- /dev/null
@@ -0,0 +1,60 @@
+#
+# Copyright (c) Microsoft. All rights reserved.
+# Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+#
+# 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/ilasm/grammar_after.cpp b/src/ilasm/grammar_after.cpp
new file mode 100644 (file)
index 0000000..8fe93da
--- /dev/null
@@ -0,0 +1,1726 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+/********************************************************************************/
+/* Code goes here */
+
+/********************************************************************************/
+
+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* nextcharA(__in __nullterminated char* pos)
+{
+    return (*pos > 0) ? ++pos : (char *)_mbsinc((const unsigned char *)pos);
+}
+
+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_t*)dbuff, (wchar_t**)&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 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)
+        {
+            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;
+                pVal->column_end = 0;
+                pVal->pc = PASM->m_CurPC;
+            }
+        }
+    }
+    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 */
+   
+#if (0)   
+
+#define IsAlpha(x) ((('A' <= (x))&&((x) <= 'Z'))||(('a' <= (x))&&((x) <= 'z')))
+#define IsDigit(x) (('0' <= (x))&&((x) <= '9'))
+#define IsAlNum(x) (IsAlpha(x) || IsDigit(x))
+#define IsValidStartingSymbol(x) (IsAlpha(x)||((x)=='#')||((x)=='_')||((x)=='@')||((x)=='$'))
+#define IsValidContinuingSymbol(x) (IsAlNum(x)||((x)=='_')||((x)=='@')||((x)=='$')||((x)=='?'))
+void SetSymbolTables() { ; }
+
+#else
+
+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]; } 
+
+#endif
+
+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,'\\')==NULL)&&(wcschr(wzFile,':')==NULL))
+                                {
+                                    WCHAR* wzFullName =  new WCHAR[MAX_FILENAME_LENGTH+1];
+                                    if(wzFullName != NULL)
+                                    {
+                                        WCHAR* pwz;
+                                        DWORD dw = WszSearchPath(parser->wzIncludePath,wzFile,NULL,
+                                                   MAX_FILENAME_LENGTH+1,wzFullName,&pwz);
+                                        if(dw != 0)
+                                        {
+                                            wzFullName[dw] = 0;
+                                            delete [] wzFile;
+                                            wzFile = wzFullName;
+                                        }
+                                        else
+                                        {
+                                            delete [] wzFullName;
+                                        }
+                                    }
+                                }
+                                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)
+                                    {
+                                        // if not ANSI, then string is in UTF-8,
+                                        // insert prefix
+                                        if(nextchar != nextcharA)
+                                        {
+                                            yylval.binstr->insertInt8(0xEF);
+                                            yylval.binstr->insertInt8(0xBB);
+                                            yylval.binstr->insertInt8(0xBF);
+                                        }
+                                        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 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 depedant 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());
+}
+
+/**************************************************************************/
+DWORD AsmParse::IsItUnicode(CONST LPVOID pBuff, int cb, LPINT lpi)
+{
+    return IsTextUnicode(pBuff,cb,lpi);
+}
+
+/**************************************************************************/
+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;
+    int iOptions = IS_TEXT_UNICODE_UNICODE_MASK;
+    g_uCodePage = CP_ACP;
+    iPutToBuffer = (int)penv->in->getAll(&(penv->curPos));
+    
+    penv->endPos = penv->curPos + iPutToBuffer;
+    if(iPutToBuffer > 128) iPutToBuffer = 128;
+    if(IsItUnicode(penv->curPos,iPutToBuffer,&iOptions))
+    {
+        g_uCodePage = CP_UTF8;
+        if(iOptions & IS_TEXT_UNICODE_SIGNATURE)
+        {
+            penv->curPos += 2;
+        }
+        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))
+        {
+            g_uCodePage = CP_UTF8;
+            penv->curPos += 3;
+            if(assem->m_fReportProgress) printf("Source file is UTF-8\n\n");
+            penv->pfn_nextchar = nextcharU;
+        }
+        else
+        {
+            if(assem->m_fReportProgress) printf("Source file is ANSI\n\n");
+            penv->pfn_nextchar = nextcharA;
+        }    
+        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/ilasm/grammar_before.cpp b/src/ilasm/grammar_before.cpp
new file mode 100644 (file)
index 0000000..60d6b57
--- /dev/null
@@ -0,0 +1,150 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+#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 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)
+
+#if (0)
+
+#define nextchar                parser->penv->pfn_nextchar
+#define Sym                     parser->penv->pfn_Sym
+#define NewStrFromToken         parser->penv->pfn_NewStrFromToken
+#define NewStaticStrFromToken   parser->penv->pfn_NewStaticStrFromToken
+#define GetDouble               parser->penv->pfn_GetDouble
+
+void SetFunctionPtrs() {;}
+
+#else
+
+
+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;
+}    
+    
+#endif    
+
+static char* newStringWDel(__in __nullterminated char* str1, char delimiter, __in __nullterminated char* str3 = 0);
+static char* newString(__in __nullterminated 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/ilasm/ilasm.nativeproj b/src/ilasm/ilasm.nativeproj
new file mode 100644 (file)
index 0000000..318f3e9
--- /dev/null
@@ -0,0 +1,87 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+  <!--*****************************************************-->
+  <!--This MSBuild project file was automatically generated-->
+  <!--from the original SOURCES/DIRS file by the KBC tool.-->
+  <!--*****************************************************-->
+  <!--Import the settings-->
+  <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+  <!--Leaf project Properties-->
+  <PropertyGroup>
+    <LibCLib>$(ClrCrtLib)</LibCLib>
+    <CDefines>$(CDefines);UNICODE;_UNICODE;FEATURE_NO_HOST;SELF_NO_HOST;NO_HOST_CPP_EH_ONLY</CDefines>
+    <CDefines>$(CDefines);__TODO_PORT_TO_WRAPPERS__</CDefines>
+    <OutputName>ilasm</OutputName>
+    <FileToMarkForSigning>$(BinariesDirectory)\$(OutputName).exe</FileToMarkForSigning>
+    <TargetType>PROGRAM</TargetType>
+    <LinkSubsystem>console</LinkSubsystem>
+    <EntryPoint>wmain</EntryPoint>
+    <LinkLibIgnore>$(LinkLibIgnore),4078</LinkLibIgnore>
+    <LinkGenerateManifest>true</LinkGenerateManifest>
+    <LinkAdditionalOptions>$(LinkAdditionalOptions) /MANIFEST -HEAP:4194304 </LinkAdditionalOptions>
+    <LinkStackReserve>4194304</LinkStackReserve>
+    
+    <!-- PCH baloney -->
+    <EnableCxxPCHHeaders>true</EnableCxxPCHHeaders>
+    <PCHCompile>ilasmpch.cpp</PCHCompile>
+    <PCHHeader>ilasmpch.h</PCHHeader>
+
+  </PropertyGroup>
+  <!--Leaf Project Items-->
+  <ItemGroup>
+    <ProjectReference Include="$(ClrSrcDirectory)utilcode\dyncrtnohost\dyncrtnohost.nativeproj" />
+    <LinkPreCrtLibs Include="$(ClrLibPath)\utilcodenohost.lib" />
+    <ProjectReference Include="$(ClrSrcDirectory)md\hotdata\full\mdhotdata.nativeproj" />
+    <LinkPreCrtLibs Include="$(ClrLibPath)\MDHotData.lib" />
+  </ItemGroup>
+  <ItemGroup>
+    <TargetLib Include="$(ClrLibPath)\corguids.lib">
+      <ProjectReference>$(ClrSrcDirectory)inc\corguids.nativeproj</ProjectReference>
+    </TargetLib>
+    <TargetLib Include="$(ClrLibPath)\fusion.lib">
+      <ProjectReference>$(ClrSrcDirectory)dlls\fusion\fusion.nativeproj</ProjectReference>
+    </TargetLib>
+    <TargetLib Include="$(SdkLibPath)\mscoree.lib" />
+    <TargetLib Include="$(SdkLibPath)\ole32.lib" />
+    <TargetLib Include="$(SdkLibPath)\oleaut32.lib" />
+    <TargetLib Include="$(SdkLibPath)\user32.lib" />
+    <TargetLib Include="$(SdkLibPath)\uuid.lib" />
+  </ItemGroup>
+  <ItemGroup>
+    <RCResourceFile Include="native.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <CppCompile Include="assem.cpp" />
+    <CppCompile Include="writer.cpp" />
+    <CppCompile Include="writer_enc.cpp" />
+    <CppCompile Include="method.cpp" />
+    <CppCompile Include="asmman.cpp" />
+    <CppCompile Include="main.cpp" />
+    <CppCompile Include="assembler.cpp" />
+    <CppCompile Include="MscorpeSxS.cpp" />
+    <CppCompile Include="$(IntermediateOutputDirectory)\asmparse.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <DataFile Include="$(IntermediateOutputDirectory)\asmparse.grammar" />
+  </ItemGroup>
+  <!--Import the targets-->
+  <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+  
+  <PropertyGroup>
+    <BuildGeneratedDependsOn>
+      $(BuildGeneratedDependsOn);
+      GenerateAsmParseC
+    </BuildGeneratedDependsOn>
+  </PropertyGroup>
+  
+  <ItemGroup>
+    <Clean Include="$O\asmparse.c" />
+    <Clean Include="$O\asmparse.grammar" />
+  </ItemGroup>
+  <Target Name="GenerateAsmParseC"
+          Inputs="asmparse.y;asmparse.h;$(ClrSrcDirectory)inc\openum.h"
+          Outputs="$(IntermediateOutputDirectory)\asmparse.c;$(IntermediateOutputDirectory)\asmparse.grammar">
+    <Delete Files="$(IntermediateOutputDirectory)\asmparse.c;$(IntermediateOutputDirectory)\asmparse.grammar" />
+    <Exec Command="$(DevDivToolsBinPath)\yacc_ms.exe -o $(IntermediateOutputDirectory)\asmparse -i asmparse.y" StandardOutputImportance="Normal" />
+    <Exec Command="$(PerlCommand) extractGrammar.pl asmparse.y &gt; $(IntermediateOutputDirectory)\asmparse.grammar" StandardOutputImportance="Normal" />
+  </Target>
+</Project>
diff --git a/src/ilasm/ilasmpch.cpp b/src/ilasm/ilasmpch.cpp
new file mode 100644 (file)
index 0000000..c4e6eb7
--- /dev/null
@@ -0,0 +1,6 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#include "ilasmpch.h"
diff --git a/src/ilasm/ilasmpch.h b/src/ilasm/ilasmpch.h
new file mode 100644 (file)
index 0000000..16d1cad
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#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 <mbstring.h>           // for _mbsinc    
+#include <ctype.h>                      // for isspace    
+#include "openum.h"             // for CEE_*
+#include <stdarg.h>         // for vararg macros 
+
+#endif
diff --git a/src/ilasm/main.cpp b/src/ilasm/main.cpp
new file mode 100644 (file)
index 0000000..2bb0661
--- /dev/null
@@ -0,0 +1,904 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+// File:  main.cpp
+//
+
+//
+
+#include "ilasmpch.h"
+
+#include "asmparse.h"
+#include "ndpversion.h"
+#include "shimload.h"
+
+#include "strsafe.h"
+
+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;
+
+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] == '\\')||(j == 0))
+        {
+            wcscat_s(wzProperName,MAX_FILENAME_LENGTH,L".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       wzIncludePathBuffer[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;
+    char        szOpt[128];
+    Assembler   *pAsm;
+    MappedFileStream *pIn;
+    AsmParse    *pParser;
+    int         exitval=1;
+    bool        bLogo = TRUE;
+    bool        bReportProgress = TRUE;
+    BOOL        bNoDebug = TRUE;
+    WCHAR*      wzIncludePath = NULL;
+    int exitcode = 0;
+    unsigned    uCodePage;
+
+    bool bClock = false;
+    Clockwork   cw;
+
+    // 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);
+
+    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));
+
+#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], L"/?") || ! wcscmp(argv[1],L"-?"))
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif    
+    {
+        printf("\nMicrosoft (R) .NET Framework IL Assembler version " VER_FILEVERSION_STR);
+        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/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/RESOURCE=<res_file>    Link the specified resource file (*.res) \n\t\t\tinto resulting .exe or .dll");
+      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/ITANIUM        Target processor: Intel Itanium");
+      printf("\n/X64            Target processor: 64bit AMD processor");
+      printf("\n/ARM            Target processor: ARM 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\nDefault source file extension is .il\n");
+
+      printf("\nTarget defaults:");
+      printf("\n/PE64      => /PE64 /ITANIUM");
+      printf("\n/ITANIUM   => /PE64 /ITANIUM");
+      printf("\n/X64       => /PE64 /X64");
+
+      printf("\n\n");
+      exit(exitcode);
+    }
+
+    uCodePage = CP_UTF8;
+    WszSetEnvironmentVariable(L"COMP_ENC_OPENSCOPE", L"");
+    WszSetEnvironmentVariable(L"COMP_ENC_EMIT", L"");
+    if((pAsm = new Assembler()))
+    {
+        pAsm->SetCodePage(uCodePage);
+        //if(pAsm->Init())
+        {
+            pAsm->SetStdMapping(1);
+            //-------------------------------------------------
+            for (i = 1; i < argc; i++)
+            {
+                if((argv[i][0] == L'/') || (argv[i][0] == L'-'))
+                {
+                    memset(szOpt,0,sizeof(szOpt));
+                    WszWideCharToMultiByte(uCodePage,0,&argv[i][1],-1,szOpt,sizeof(szOpt),NULL,NULL);
+                    szOpt[3] = 0;
+                    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"))
+                    {
+                      pAsm->m_dwIncludeDebugInfo = 0x101;
+                      pAsm->m_fGeneratePDB = TRUE;
+                      bNoDebug = FALSE;
+
+                      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,L"OPT"))
+                                pAsm->m_dwIncludeDebugInfo = 0x3;
+                              else if(0 == _wcsicmp(wzSubOpt,L"IMP"))
+                                pAsm->m_dwIncludeDebugInfo = 0x103;
+                              else 
+                              {
+                                WCHAR *pFmt =((*pStr == '0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%ld";
+                                if(swscanf_s(pStr,pFmt,&(pAsm->m_dwIncludeDebugInfo))!=1)
+                                goto InvalidOption; // bad subooption
+                              }
+                          }
+                      }
+                    }
+                    else if (!_stricmp(szOpt, "PDB"))
+                    {
+                      pAsm->m_fGeneratePDB = TRUE;
+                      bNoDebug = FALSE;
+                    }
+                    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, "ITA"))
+                    {
+                      pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;
+                      pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_IA64;
+                    }
+                    else if (!_stricmp(szOpt, "X64"))
+                    {
+                      pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;        
+                      pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_AMD64;
+                    }
+                    else if (!_stricmp(szOpt, "ARM"))
+                    {
+                      pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;        
+                      pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_ARM;
+                    }
+                    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,L"%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++;
+                        WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%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,L"%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++;
+                        WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%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++;
+                        WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%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++;
+                        WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%I64x" : L"%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++;
+                        WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%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 /ITANIUM 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_IA64;
+                        printf(" Type set to ITANIUM.");
+                    }
+                    printf("\n");
+                }
+            }
+            else
+            {
+                if((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_IA64)
+                  ||(pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_AMD64))
+                {
+                    printf("\n64 bit target must be specified for machine type /ITANIUM 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_MACHINE_IA64))
+            {
+                pAsm->m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
+            }
+            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(!pAsm->Init())
+            {
+                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 ? L".dll" : (IsOBJ ? L".obj" : L".exe")));
+            }
+            if(wzIncludePath == NULL)
+            {
+                if(0!=WszGetEnvironmentVariable(L"ILASM_INCLUDE",wzIncludePathBuffer,MAX_FILENAME_LENGTH))
+                    wzIncludePath = wzIncludePathBuffer;
+            }
+            //------------ 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 Framework IL Assembler.  Version " VER_FILEVERSION_STR);
+                    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
+                        {
+                            DWORD dwBinType;
+                            if(GetBinaryTypeA(szInputFilename,&dwBinType))
+                            {
+                                pParser->msg("%s is not a text file\n",szInputFilename);
+                                fAllFilesPresent = FALSE;
+                            }
+                            else
+                            {
+                                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);
+                                }
+                                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);
+                                    }
+                                }
+                                if(bClock) cw.cEnd = GetTickCount();
+#define ENC_ENABLED
+#ifdef 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 = (int)StringCchPrintfW(&wzNewOutputFilename[wcslen(wzNewOutputFilename)], 32,
+                                                 L".%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
+                                        {
+                                            DWORD dwBinType;
+                                            if(GetBinaryTypeA(szInputFilename,&dwBinType))
+                                            {
+                                                pParser->msg("%s is not a text file\n",szInputFilename);
+                                                fAllFilesPresent = FALSE;
+                                            }
+                                            else
+                                            if (SUCCEEDED(pAsm->InitMetaDataForENC(wzNewOutputFilename)))
+                                            {
+                                                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)
+#endif
+                            }
+
+                        }
+                    }
+                }
+                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(L"COMP_ENC_OPENSCOPE", L"");
+    WszSetEnvironmentVariable(L"COMP_ENC_EMIT", L"");
+
+    if(exitval || bNoDebug)
+    {
+        // 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,L"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
+
+
+HINSTANCE GetModuleInst()
+{
+    return (NULL);
+}
+
+
+
diff --git a/src/ilasm/method.cpp b/src/ilasm/method.cpp
new file mode 100644 (file)
index 0000000..1e3eec5
--- /dev/null
@@ -0,0 +1,158 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// 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[0]=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;
+#if(0)
+        LinePC *pLPC = new LinePC;
+        if(pLPC)
+        {
+            pLPC->Line = m_pAssembler->m_ulCurLine;
+            pLPC->Column = m_pAssembler->m_ulCurColumn;
+            pLPC->PC = m_pAssembler->m_CurPC;
+            m_LinePCList.PUSH(pLPC);
+        }
+#endif
+        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;
+#if(0)
+    LinePC *pLPC = new LinePC;
+    if(pLPC)
+    {
+        pLPC->Line = m_pAssembler->m_ulCurLine;
+        pLPC->Column = m_pAssembler->m_ulCurColumn;
+        pLPC->PC = m_pAssembler->m_CurPC;
+        m_LinePCList.PUSH(pLPC);
+    }
+#endif
+    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;
+}
+
diff --git a/src/ilasm/method.hpp b/src/ilasm/method.hpp
new file mode 100644 (file)
index 0000000..8601920
--- /dev/null
@@ -0,0 +1,381 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// 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;
+};
+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;
+    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;
+    };
+};
+
+#endif /* _METHOD_HPP */
+
diff --git a/src/ilasm/nvpair.h b/src/ilasm/nvpair.h
new file mode 100644 (file)
index 0000000..9f67b98
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+/***************************************************************************/
+/* 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/ilasm/typar.hpp b/src/ilasm/typar.hpp
new file mode 100644 (file)
index 0000000..ad5cb0e
--- /dev/null
@@ -0,0 +1,167 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+/**************************************************************************/
+/* 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; };
+    CustomDescrList* CAList() { return &m_lstCA; };
+private:
+    BinStr* m_pbsBounds;
+    LPCWSTR m_wzName;
+    DWORD   m_dwAttrs;
+    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;
+               if (next) delete next; 
+       };
+    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/ilasm/writer.cpp b/src/ilasm/writer.cpp
new file mode 100644 (file)
index 0000000..c2b81ff
--- /dev/null
@@ -0,0 +1,1798 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// writer.cpp
+//
+
+#include "ilasmpch.h"
+
+#include "assembler.h"
+
+#include "ceefilegenwriter.h"
+#include "strongname.h"
+#include "LegacyActivationShim.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 = LegacyActivationShim::ClrCoCreateInstance(
+        CLSID_CorMetaDataDispenser, 
+        NULL, 
+        CLSCTX_INPROC_SERVER, 
+        IID_IMetaDataDispenserEx, 
+        (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_IMetaDataEmit2,
+                        (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;
+
+    hr = CoCreateInstance(CLSID_CorSymWriter_SxS,
+                           NULL,
+                           CLSCTX_INPROC_SERVER,
+                           IID_ISymUnmanagedWriter,
+                           (void **)&m_pSymWriter);
+    if(SUCCEEDED(hr))
+    {
+        if(m_pSymWriter) m_pSymWriter->Initialize((IUnknown*)m_pEmitter,
+                                                  m_wzOutputFileName,
+                                                  NULL,
+                                                  TRUE);
+    }
+    else
+    {
+        fprintf(stderr, "Error: QueryInterface(IID_ISymUnmanagedWriter) returns %X\n",hr);
+        m_pSymWriter = NULL;
+    }
+
+    //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 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_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;
+
+    // Only emit this if we're also emitting debug info.
+    if (!(m_fGeneratePDB && m_pSymWriter))
+        return S_OK;
+
+    IMAGE_DEBUG_DIRECTORY  debugDirIDD;
+    struct Param
+    {
+    DWORD                  debugDirDataSize;
+        BYTE              *debugDirData;
+    } param;
+    param.debugDirData = NULL;
+
+    // Get the debug info from the symbol writer.
+    if (FAILED(hr=m_pSymWriter->GetDebugInfo(NULL, 0, &param.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, &param) {
+        pParam->debugDirData = new BYTE[pParam->debugDirDataSize];
+    } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+        hr = E_FAIL;
+    } WIN_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);
+
+    // 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).
+    HCEESECTION sec = m_pILSection;//m_pGlobalDataSection;
+    BYTE *de;
+
+    if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(sec,
+                                                   sizeof(debugDirIDD) +
+                                                   param.debugDirDataSize,
+                                                   4,
+                                                   (void**) &de)))
+        goto ErrExit;
+
+    // Where did we get that memory?
+    ULONG deOffset;
+    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,'\\');
+    if(pszDllName == NULL) pszDllName = strrchr(szOutputFileName,':');
+    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
+};
+
+static const BYTE ExportStubIA64Template[] =
+{
+    // ld8    r9  = [gp]    ;;
+    // ld8    r10 = [r9],8
+    // nop.i                ;;
+    // ld8    gp  = [r9]
+    // mov    b6  = r10
+    // br.cond.sptk.few  b6
+    //
+    0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 
+    0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 
+    0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 
+    0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//address of the template
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //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_IA64)
+    {
+        STUB_TEMPLATE = (BYTE*)&ExportStubIA64Template[0];
+        EXPORT_STUB_SIZE = sizeof(ExportStubIA64Template);
+        OFFSET_OF_ADDR = 40;
+        if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, EXPORT_STUB_SIZE, STUB_ALIGNMENT, (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;
+        *((DWORD*)(&outBuff[OFFSET_OF_ADDR - 8])) = PEFileOffset; // set PLabel
+        m_pCeeFileGen->AddSectionReloc(m_pILSection, PEFileOffset+OFFSET_OF_ADDR-8,m_pILSection, srRelocHighLow);
+        m_pCeeFileGen->AddSectionReloc(m_pILSection, PEFileOffset+OFFSET_OF_ADDR,m_pGlobalDataSection, srRelocHighLow);
+        PEFileOffset += OFFSET_OF_ADDR - 8; // entry point is PLabel, which points at the template
+    }
+    else
+    {
+        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 GetBytesFromHex (LPCSTR szPublicKeyHexString, ULONG cchPublicKeyHexString, BYTE** buffer, ULONG *cbBufferSize)
+{
+    ULONG cchHex = cchPublicKeyHexString;
+    if (cchHex % 2 != 0)
+        return false;
+    *cbBufferSize = cchHex / 2;
+
+    *buffer = new BYTE[*cbBufferSize];
+    if (!*buffer)
+        return false;
+
+    for (ULONG i = 0; i < *cbBufferSize; i++)
+    {
+        BYTE msn = HexToByte(*szPublicKeyHexString);
+        BYTE lsn = HexToByte(*(szPublicKeyHexString + 1));
+        if (msn == 0xFF || lsn == 0xFF)
+        {
+            delete[] *buffer;
+            return false;
+        }
+
+        (*buffer)[i] = (BYTE) ( (msn << 4) | lsn );
+        szPublicKeyHexString += 2;
+    }
+
+    return true;
+}
+
+HRESULT Assembler::GetSignatureKey()
+{
+    HRESULT     hr = S_OK;
+    ULONG        cbSize = 0;
+    void *            pvData = NULL;
+    LPWSTR      pName = NULL;
+    
+    CustomDescrList* pCDList = &m_pManifest->m_pAssembly->m_CustomDescrList;
+    
+    for (ULONG i = 0;i < pCDList->COUNT(); i++)
+    {
+        CustomDescr* pCD = pCDList->PEEK(i);
+
+        if(pCD->pBlob)
+        {
+            pvData = (void *)(pCD->pBlob->ptr());
+            cbSize = pCD->pBlob->length();
+            pCD->tkOwner = m_pManifest->m_pAssembly->tkTok;
+            mdToken tkOwnerType, tkTypeType = TypeFromToken(pCD->tkType);
+            
+            if (GetCAName(pCD->tkType, &pName) != S_OK)
+                continue;
+
+            if (wcscmp(pName, L"System.Reflection.AssemblySignatureKeyAttribute") == 0)
+            {
+                    if (cbSize < sizeof(WORD) || GET_UNALIGNED_VAL16(pvData) != 1)
+                    {
+                        hr = E_FAIL;
+                        break;;
+                    }
+                    pvData = (unsigned char *)pvData  + sizeof(WORD);
+                    cbSize -= sizeof(WORD);
+                    
+                    // String is stored as compressed length, UTF8.
+                    if (*(const BYTE*)pvData != 0xFF)
+                    {
+                        PCCOR_SIGNATURE sig = (PCCOR_SIGNATURE)pvData;
+                        cbSize -= CorSigUncompressedDataSize(sig);
+                        DWORD len = CorSigUncompressData(sig);
+                        pvData = (void *)sig;
+                        if (cbSize < len)
+                        {
+                            hr = E_FAIL;
+                            break;
+                        }
+
+                        AsmManStrongName   *pSN = &m_pManifest->m_sStrongName;
+                        GetBytesFromHex((LPCSTR)pvData, len, &pSN->m_pbSignatureKey, &pSN->m_cbSignatureKey);
+                    }
+                    
+                    break;
+            }
+            
+            if (pName)
+            {
+                delete pName;
+                pName = NULL;
+            }
+        }
+    }
+
+    if (pName)
+        delete pName;
+    return hr;
+}
+
+HRESULT Assembler::AllocateStrongNameSignature()
+{
+    HRESULT             hr = S_OK;
+    HCEESECTION         hSection;
+    DWORD               dwDataLength;
+    DWORD               dwDataOffset;
+    DWORD               dwDataRVA;
+    VOID               *pvBuffer;
+    AsmManStrongName   *pSN = &m_pManifest->m_sStrongName;
+
+    // Pulls  the AssemblySignatureKey attribute from m_CustomDescrList
+    // If present, populate the pSN->m_pbSignatureKey from the AssemblySignatureKeyAttribute blob
+    if (FAILED(hr = GetSignatureKey()))
+    {
+        return hr;
+    }
+
+   // Determine size of signature blob.
+    if (pSN->m_pbSignatureKey != NULL)
+    {
+        // If m_pbSignatureKey present use it, else fall back to using identity key.
+        if (FAILED(hr = LegacyActivationShim::StrongNameSignatureSize_HRESULT(
+            pSN->m_pbSignatureKey, 
+            pSN->m_cbSignatureKey, 
+            &dwDataLength)))
+         {
+            return hr;
+        }
+    }
+    else if (FAILED(hr = LegacyActivationShim::StrongNameSignatureSize_HRESULT(
+            pSN->m_pbPublicKey, 
+            pSN->m_cbPublicKey, 
+            &dwDataLength)))
+    {
+        return hr;
+    }
+
+    // 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;
+}
+
+HRESULT Assembler::StrongNameSign()
+{
+    LPWSTR              wszOutputFile;
+    HRESULT             hr = S_OK;
+    AsmManStrongName   *pSN = &m_pManifest->m_sStrongName;
+
+    // Determine what the ouput PE was called.
+    if (FAILED(hr = m_pCeeFileGen->GetOutputFileName(m_pCeeFile,
+                                                     &wszOutputFile)))
+        return hr;
+
+    // Update the output PE image with a strong name signature.
+    if (FAILED(hr = LegacyActivationShim::StrongNameSignatureGeneration_HRESULT(
+        wszOutputFile, 
+        pSN->m_wzKeyContainer, 
+        pSN->m_pbPrivateKey, 
+        pSN->m_cbPrivateKey, 
+        NULL, 
+        NULL)))
+    {
+        return hr;
+    }
+
+    return S_OK;
+}
+
+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,L"$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;
+}
+
+#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, '\\')) != NULL) pwc++;
+        else if ((pwc = wcsrchr(m_wzOutputFileName, ':')) != NULL) pwc++;
+        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)
+    {
+        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);
+        }
+    }
+
+    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/ilasm/writer_enc.cpp b/src/ilasm/writer_enc.cpp
new file mode 100644 (file)
index 0000000..79f5245
--- /dev/null
@@ -0,0 +1,661 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+//
+// writer_ENC.cpp
+//
+
+//
+#include "ilasmpch.h"
+
+#include "assembler.h"
+
+//#include "ceefilegenwriter.h"
+#include "strongname.h"
+
+int ist=0;
+#define REPT_STEP   //printf("Step %d\n",++ist);
+
+HRESULT Assembler::InitMetaDataForENC(__in __nullterminated WCHAR* wzOrigFileName)
+{
+    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;
+    }
+    //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()) goto exit; // close and re-open CeeFileGen and CeeFile
+    hr = S_OK;
+
+    hr = CoCreateInstance(CLSID_CorSymWriter_SxS,
+                           NULL,
+                           CLSCTX_INPROC_SERVER,
+                           IID_ISymUnmanagedWriter,
+                           (void **)&m_pSymWriter);
+    if(SUCCEEDED(hr))
+    {
+        WCHAR* pwc = &wzOrigFileName[wcslen(wzOrigFileName)];
+        wcscat_s(wzOrigFileName,MAX_SCOPE_LENGTH,L".pdb");
+        if(m_pSymWriter) m_pSymWriter->Initialize((IUnknown*)m_pEmitter,
+                                                  wzOrigFileName,
+                                                  NULL,
+                                                  TRUE);
+        *pwc = 0;
+    }
+    else 
+    {
+        fprintf(stderr, "Error: CoCreateInstance(IID_ISymUnmanagedWriter) returns %X\n",hr);
+        m_pSymWriter = NULL;
+    }
+
+
+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,L".dil");
+        if(_wfopen_s(&pF,pwzOutputFilename,L"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,L".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();
+    }
+
+#if(0)
+//===================================================================================
+    // release SymWriter interfaces
+    if (m_pSymWriter != NULL)
+    {
+        m_pSymWriter->Close();
+        m_pSymWriter->Release();
+        m_pSymWriter = NULL;
+    }
+
+    hr = CoCreateInstance(CLSID_CorSymWriter_SxS,
+                           NULL,
+                           CLSCTX_INPROC_SERVER,
+                           IID_ISymUnmanagedWriter,
+                           (void **)&m_pSymWriter);
+    if(SUCCEEDED(hr))
+    {
+        WCHAR* pwc = &pwzOutputFilename[wcslen(pwzOutputFilename)];
+        wcscat(pwzOutputFilename,L".pdb");
+        if(m_pSymWriter) m_pSymWriter->Initialize((IUnknown*)m_pEmitter,
+                                                  pwzOutputFilename,
+                                                  NULL,
+                                                  TRUE);
+        *pwc = 0;
+    }
+    else 
+    {
+        fprintf(stderr, "Error: CoCreateInstance(IID_ISymUnmanagedWriter) returns %X\n",hr);
+        m_pSymWriter = NULL;
+    }
+    
+    m_fENCMode = FALSE;
+    if(FAILED(hr=CreatePEFile(pwzOutputFilename))) 
+        report->msg("Could not create output file, error code=0x%08X\n",hr);
+    m_fENCMode = TRUE;
+//=====================================================================================    
+#endif
+
+    // 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;
+    }
+
+    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;
+}