text: //
  // Copyright (c) Microsoft. All rights reserved.
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  //
  
  /*****************************************************************************
   **                                                                         **
   ** Corhlpr.h -                                                                 **
   **                                                                         **
   *****************************************************************************/
  
  
  #ifndef __CORHLPR_H__
  #define __CORHLPR_H__
  
  #if defined(_MSC_VER) && defined(_X86_) && !defined(FPO_ON)
  #pragma optimize("y", on)		// Small critical routines, don't put in EBP frame 
  #define FPO_ON 1
  #define CORHLPR_TURNED_FPO_ON 1
  #endif
  
  #include "cor.h"
  #include "corhdr.h"
  #include "corerror.h"
  
  // This header is consumed both within the runtime and externally. In the former
  // case we need to wrap memory allocations, in the latter there is no
  // infrastructure to support this. Detect which way we're building and provide a
  // very simple abstraction layer (handles allocating bytes only).
  #ifdef _BLD_CLR
  #include "new.hpp"
  
  
  #define NEW_NOTHROW(_bytes) new (nothrow) BYTE[_bytes]
  #define NEW_THROWS(_bytes) new BYTE[_bytes]
  void DECLSPEC_NORETURN ThrowOutOfMemory();
  inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY()
  {
      ThrowOutOfMemory();
  }
  #else
  #define NEW_NOTHROW(_bytes) new BYTE[_bytes]
  #define NEW_THROWS(_bytes) __CorHlprNewThrows(_bytes)
  static inline void DECLSPEC_NORETURN __CorHlprThrowOOM()
  {
      RaiseException(STATUS_NO_MEMORY, 0, 0, NULL);
  }
  static inline BYTE *__CorHlprNewThrows(size_t bytes)
  {
      BYTE *pbMemory = new BYTE[bytes];
      if (pbMemory == NULL)
          __CorHlprThrowOOM();
      return pbMemory;
  }
  inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY()
  {
      __CorHlprThrowOOM();
  }
  #endif
  
  
  //*****************************************************************************
  // There are a set of macros commonly used in the helpers which you will want
  // to override to get richer behavior.  The following defines what is needed
  // if you chose not to do the extra work.
  //*****************************************************************************
  #ifndef IfFailGoto
  #define IfFailGoto(EXPR, LABEL) \
  do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0)
  #endif
  
  #ifndef IfFailGo
  #define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit)
  #endif
  
  #ifndef IfFailRet
  #define IfFailRet(EXPR) do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0)
  #endif
  
  #ifndef IfNullRet
  #define IfNullRet(EXPR) do { if ((EXPR) == NULL){ return (E_OUTOFMEMORY); } } while (0)
  #endif
  
  
  #ifndef _ASSERTE
  #define _ASSERTE(expr)
  #endif
  
  #ifndef COUNTOF
  #define COUNTOF(a) (sizeof(a) / sizeof(*a))
  #endif
  
  #if !BIGENDIAN
  #define VAL16(x) x
  #define VAL32(x) x
  #endif
  
  
  //*****************************************************************************
  //
  //***** Macro to assist with cleaning up local static variables
  //
  //*****************************************************************************
  
  #define CHECK_LOCAL_STATIC_VAR(x)   \
      x                                \
  
  //*****************************************************************************
  //
  //***** Utility helpers
  //
  //*****************************************************************************
  
  
  #define MAX_CLASSNAME_LENGTH 1024
  
  //*****************************************************************************
  //
  //***** Signature helpers
  //
  //*****************************************************************************
  
  inline bool isCallConv(unsigned sigByte, CorCallingConvention conv)
  {
      return ((sigByte & IMAGE_CEE_CS_CALLCONV_MASK) == (unsigned) conv);
  }
  
  //*****************************************************************************
  //
  //***** File format helper classes
  //
  //*****************************************************************************
  
  
  
  //*****************************************************************************
  typedef struct tagCOR_ILMETHOD_SECT_SMALL : IMAGE_COR_ILMETHOD_SECT_SMALL {
          //Data follows
      const BYTE* Data() const 
      { 
          return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_SMALL)); 
      }
  
      bool IsSmall() const
      { 
          return (Kind & CorILMethod_Sect_FatFormat) == 0;
      }
  
      bool More() const
      {
          return (Kind & CorILMethod_Sect_MoreSects) != 0;
      }
  } COR_ILMETHOD_SECT_SMALL;
  
  
  /************************************/
  /* NOTE this structure must be DWORD aligned!! */
  typedef struct tagCOR_ILMETHOD_SECT_FAT : IMAGE_COR_ILMETHOD_SECT_FAT {
          //Data follows
      const BYTE* Data() const 
      { 
          return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_FAT)); 
      }
  
          //Endian-safe wrappers
      unsigned GetKind() const {
          /* return Kind; */
          return *(BYTE*)this;
      }
      void SetKind(unsigned kind) {
          /* Kind = kind; */
          *(BYTE*)this = (BYTE)kind;
      }
  
      unsigned GetDataSize() const {
          /* return DataSize; */
          BYTE* p = (BYTE*)this;
          return ((unsigned)*(p+1)) |
              (((unsigned)*(p+2)) << 8) |
              (((unsigned)*(p+3)) << 16);
      }
      void SetDataSize(unsigned datasize) {
          /* DataSize = dataSize; */
          BYTE* p = (BYTE*)this;
          *(p+1) = (BYTE)(datasize);
          *(p+2) = (BYTE)(datasize >> 8);
          *(p+3) = (BYTE)(datasize >> 16);
      }
  } COR_ILMETHOD_SECT_FAT;
  
  typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_FAT : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT {
      //Endian-safe wrappers
      CorExceptionFlag GetFlags() const {
          return (CorExceptionFlag)VAL32((unsigned)Flags);
      }
      void SetFlags(CorExceptionFlag flags) {
          Flags = (CorExceptionFlag)VAL32((unsigned)flags);
      }
  
      DWORD GetTryOffset() const {
          return VAL32(TryOffset);
      }
      void SetTryOffset(DWORD Offset) {
          TryOffset = VAL32(Offset);
      }
  
      DWORD GetTryLength() const {
          return VAL32(TryLength);
      }
      void SetTryLength(DWORD Length) {
          TryLength = VAL32(Length);
      }
  
      DWORD GetHandlerOffset() const {
          return VAL32(HandlerOffset);
      }
      void SetHandlerOffset(DWORD Offset) {
          HandlerOffset = VAL32(Offset);
      }
  
      DWORD GetHandlerLength() const {
          return VAL32(HandlerLength);
      }
      void SetHandlerLength(DWORD Length) {
          HandlerLength = VAL32(Length);
      }
  
      DWORD GetClassToken() const {
          return VAL32(ClassToken);
      }
      void SetClassToken(DWORD tok) {
          ClassToken = VAL32(tok);
      }
  
      DWORD GetFilterOffset() const {
          return VAL32(FilterOffset);
      }
      void SetFilterOffset(DWORD offset) {
          FilterOffset = VAL32(offset);
      }
  
  } COR_ILMETHOD_SECT_EH_CLAUSE_FAT;
  
  //*****************************************************************************
  struct COR_ILMETHOD_SECT_EH_FAT : public COR_ILMETHOD_SECT_FAT {
      static unsigned Size(unsigned ehCount) {
          return (sizeof(COR_ILMETHOD_SECT_EH_FAT) +
                  sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT) * (ehCount-1));
          }
  
      IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1];     // actually variable size
  };
  
  typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_SMALL : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL {
      //Endian-safe wrappers
      CorExceptionFlag GetFlags() const {
          return (CorExceptionFlag)VAL16((SHORT)Flags);
      }
      void SetFlags(CorExceptionFlag flags) {
          Flags = (CorExceptionFlag)VAL16((SHORT)flags);
      }
  
      DWORD GetTryOffset() const {
          return VAL16(TryOffset);
      }
      void SetTryOffset(DWORD Offset) {
          _ASSERTE((Offset & ~0xffff) == 0);
          TryOffset = VAL16(Offset);
      }
  
      DWORD GetTryLength() const {
          return TryLength;
      }
      void SetTryLength(DWORD Length) {
          _ASSERTE((Length & ~0xff) == 0);
          TryLength = Length;
      }
  
      DWORD GetHandlerOffset() const {
          return VAL16(HandlerOffset);
      }
      void SetHandlerOffset(DWORD Offset) {
          _ASSERTE((Offset & ~0xffff) == 0);
          HandlerOffset = VAL16(Offset);
      }
  
      DWORD GetHandlerLength() const {
          return HandlerLength;
      }
      void SetHandlerLength(DWORD Length) {
          _ASSERTE((Length & ~0xff) == 0);
          HandlerLength = Length;
      }
  
      DWORD GetClassToken() const {
          return VAL32(ClassToken);
      }
      void SetClassToken(DWORD tok) {
          ClassToken = VAL32(tok);
      }
  
      DWORD GetFilterOffset() const {
          return VAL32(FilterOffset);
      }
      void SetFilterOffset(DWORD offset) {
          FilterOffset = VAL32(offset);
      }
  } COR_ILMETHOD_SECT_EH_CLAUSE_SMALL;
  
  //*****************************************************************************
  struct COR_ILMETHOD_SECT_EH_SMALL : public COR_ILMETHOD_SECT_SMALL {
      static unsigned Size(unsigned ehCount) {
          return (sizeof(COR_ILMETHOD_SECT_EH_SMALL) +
                  sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL) * (ehCount-1));
          }
  
      WORD Reserved;                                  // alignment padding
      IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1];   // actually variable size
  };
  
  
  /************************************/
  /* NOTE this structure must be DWORD aligned!! */
  struct COR_ILMETHOD_SECT
  {
      bool More() const           
      { 
          return((AsSmall()->Kind & CorILMethod_Sect_MoreSects) != 0); 
      }
  
      CorILMethodSect Kind() const
      { 
          return((CorILMethodSect) (AsSmall()->Kind & CorILMethod_Sect_KindMask)); 
      }
  
      const COR_ILMETHOD_SECT* Next() const   
      {
          if (!More()) return(0);
          return ((COR_ILMETHOD_SECT*)(((BYTE *)this) + DataSize()))->Align();
      }
  
      const BYTE* Data() const 
      {
          if (IsFat()) return(AsFat()->Data());
          return(AsSmall()->Data());
      }
  
      unsigned DataSize() const
      {
          if (Kind() == CorILMethod_Sect_EHTable) 
          {
              // VB and MC++ shipped with bug where they have not accounted for size of COR_ILMETHOD_SECT_EH_XXX
              // in DataSize. To avoid breaking these images, we will align the size of EH sections up. This works
              // because IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_XXX is bigger than COR_ILMETHOD_SECT_EH_XXX 
              // (see VSWhidbey #99031 and related bugs for details).
  
              if (IsFat())
                  return Fat.Size(Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
              else
                  return Small.Size(Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL));
          }
          else
      {
          if (IsFat()) return(AsFat()->GetDataSize());
          return(AsSmall()->DataSize);
      }
      }
  
      friend struct COR_ILMETHOD;
      friend struct tagCOR_ILMETHOD_FAT;
      friend struct tagCOR_ILMETHOD_TINY;
      bool IsFat() const                            
      { 
          return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0); 
      }
  
      const COR_ILMETHOD_SECT* Align() const        
      { 
          return((COR_ILMETHOD_SECT*) ((((UINT_PTR) this) + 3) & ~3));  
      }
  
  protected:
      const COR_ILMETHOD_SECT_FAT*   AsFat() const  
      { 
          return((COR_ILMETHOD_SECT_FAT*) this); 
      }
  
      const COR_ILMETHOD_SECT_SMALL* AsSmall() const
      { 
          return((COR_ILMETHOD_SECT_SMALL*) this); 
      }
  
  public:
      // The body is either a COR_ILMETHOD_SECT_SMALL or COR_ILMETHOD_SECT_FAT
      // (as indicated by the CorILMethod_Sect_FatFormat bit
      union {
          COR_ILMETHOD_SECT_EH_SMALL Small;
          COR_ILMETHOD_SECT_EH_FAT Fat;
          };
  };
  
  
  /***********************************/
  // exported functions (implementation in Format\Format.cpp:
  extern "C" {
  IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff);
          // compute the size of the section (best format)
          // codeSize is the size of the method
      // deprecated
  unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize);
  
      // will return worse-case size and then Emit will return actual size
  unsigned __stdcall SectEH_SizeWorst(unsigned ehCount);
  
      // will return exact size which will match the size returned by Emit
  unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses);
  
          // emit the section (best format);
  unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount,
                    IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
                    BOOL moreSections, BYTE* outBuff,
                    ULONG* ehTypeOffsets = 0);
  } // extern "C"
  
  
  struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT
  {
      unsigned EHCount() const 
      {
          return (unsigned)(IsFat() ? (Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)) :
                          (Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL)));
      }
  
          // return one clause in its fat form.  Use 'buff' if needed
      const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* EHClause(unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) const
      { 
          return SectEH_EHClause((void *)this, idx, buff); 
      };
          // compute the size of the section (best format)
          // codeSize is the size of the method
      // deprecated
      unsigned static Size(unsigned ehCount, unsigned codeSize)
      { 
          return SectEH_SizeWithCode(ehCount, codeSize); 
      };
  
      // will return worse-case size and then Emit will return actual size
      unsigned static Size(unsigned ehCount)
      { 
          return SectEH_SizeWorst(ehCount); 
      };
  
      // will return exact size which will match the size returned by Emit
      unsigned static Size(unsigned ehCount, const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses)
      { 
          return SectEH_SizeExact(ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses);  
      };
  
          // emit the section (best format);
      unsigned static Emit(unsigned size, unsigned ehCount,
                    const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
                    bool moreSections, BYTE* outBuff,
                    ULONG* ehTypeOffsets = 0)
      { 
          return SectEH_Emit(size, ehCount,
                             (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses,
                             moreSections, outBuff, ehTypeOffsets); 
      };
  };
  
  
  /***************************************************************************/
  /* Used when the method is tiny (< 64 bytes), and there are no local vars */
  typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY
  {
      bool     IsTiny() const         
      { 
          return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat); 
      }
  
      unsigned GetCodeSize() const    
      { 
          return(((unsigned) Flags_CodeSize) >> (CorILMethod_FormatShift-1)); 
      }
  
      unsigned GetMaxStack() const    
      { 
          return(8); 
      }
  
      BYTE*    GetCode() const        
      { 
          return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY)); 
      }
  
      DWORD    GetLocalVarSigTok() const  
      { 
          return(0); 
      }
  
      COR_ILMETHOD_SECT* GetSect() const 
      { 
          return(0); 
      }
  } COR_ILMETHOD_TINY;
  
  
  /************************************/
  // This strucuture is the 'fat' layout, where no compression is attempted.
  // Note that this structure can be added on at the end, thus making it extensible
  typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT
  {
          //Endian-safe wrappers
      unsigned GetSize() const {
          /* return Size; */
          BYTE* p = (BYTE*)this;
          return *(p+1) >> 4;
      }
      void SetSize(unsigned size) {
          /* Size = size; */
          BYTE* p = (BYTE*)this;
          *(p+1) = (BYTE)((*(p+1) & 0x0F) | (size << 4));
      }
  
      unsigned GetFlags() const {
          /* return Flags; */
          BYTE* p = (BYTE*)this;
          return ((unsigned)*(p+0)) | (( ((unsigned)*(p+1)) & 0x0F) << 8);
      }
      void SetFlags(unsigned flags) {
          /* flags = Flags; */
          BYTE* p = (BYTE*)this;
          *p = (BYTE)flags;
          *(p+1) = (BYTE)((*(p+1) & 0xF0) | ((flags >> 8) & 0x0F));
      }
  
      bool IsFat() const {
          /* return((IMAGE_COR_ILMETHOD_FAT::GetFlags() & CorILMethod_FormatMask) == CorILMethod_FatFormat); */
          return (*(BYTE*)this & CorILMethod_FormatMask) == CorILMethod_FatFormat;
      }
  
      unsigned GetMaxStack() const {
          /* return MaxStack; */
          return VAL16(*(USHORT*)((BYTE*)this+2));
      }
      void SetMaxStack(unsigned maxStack) {
          /* MaxStack = maxStack; */
          *(USHORT*)((BYTE*)this+2) = VAL16((USHORT)maxStack);
      }
  
      unsigned GetCodeSize() const        
      { 
          return VAL32(CodeSize); 
      }
  
      void SetCodeSize(DWORD Size)        
      { 
          CodeSize = VAL32(Size); 
      }
  
      mdToken  GetLocalVarSigTok() const      
      { 
          return VAL32(LocalVarSigTok); 
      }
  
      void SetLocalVarSigTok(mdSignature tok) 
      { 
          LocalVarSigTok = VAL32(tok); 
      }
  
      BYTE* GetCode() const {
          return(((BYTE*) this) + 4*GetSize());
      }
  
      bool More() const {
          // return (GetFlags() & CorILMethod_MoreSects) != 0;
          return (*(BYTE*)this & CorILMethod_MoreSects) != 0;
      }
  
      const COR_ILMETHOD_SECT* GetSect() const {
          if (!More()) return (0);
          return(((COR_ILMETHOD_SECT*) (GetCode() + GetCodeSize()))->Align());
      }
  } COR_ILMETHOD_FAT;
  
  
  extern "C" {
  /************************************/
  // exported functions (impl. Format\Format.cpp)
  unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL MoreSections);
          // emit the header (bestFormat) return amount emitted
  unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header,
                    BOOL moreSections, BYTE* outBuff);
  }
  
  struct COR_ILMETHOD
  {
          // a COR_ILMETHOD header should not be decoded by hand.  Instead us
          // COR_ILMETHOD_DECODER to decode it.
      friend class COR_ILMETHOD_DECODER;
  
          // compute the size of the header (best format)
      unsigned static Size(const COR_ILMETHOD_FAT* header, bool MoreSections)
      { 
          return IlmethodSize((COR_ILMETHOD_FAT*)header,MoreSections); 
      };
          // emit the header (bestFormat) return amount emitted
      unsigned static Emit(unsigned size, const COR_ILMETHOD_FAT* header,
                    bool moreSections, BYTE* outBuff)
      { 
          return IlmethodEmit(size, (COR_ILMETHOD_FAT*)header, moreSections, outBuff); 
      };
  
  //private:
      union
      {
          COR_ILMETHOD_TINY       Tiny;
          COR_ILMETHOD_FAT        Fat;
      };
          // Code follows the Header, then immedately after the code comes
          // any sections (COR_ILMETHOD_SECT).
  };
  
  extern "C" {
  /***************************************************************************/
  /* COR_ILMETHOD_DECODER is the only way functions internal to the EE should
     fetch data from a COR_ILMETHOD.  This way any dependancy on the file format
     (and the multiple ways of encoding the header) is centralized to the
     COR_ILMETHOD_DECODER constructor) */
      void __stdcall DecoderInit(void * pThis, COR_ILMETHOD* header);
      int  __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header);
  } // extern "C"
  
  class COR_ILMETHOD_DECODER : public COR_ILMETHOD_FAT
  {
  public:
      // Typically the ONLY way you should access COR_ILMETHOD is through
      // this constructor so format changes are easier.
      COR_ILMETHOD_DECODER(const COR_ILMETHOD* header) 
      { 
          DecoderInit(this,(COR_ILMETHOD*)header); 
      };
  
      // The above variant of the constructor can not do a 'complete' job, because
      // it can not look up the local variable signature meta-data token.
      // This method should be used when you have access to the Meta data API
      // If the construction fails, the 'Code' field is set to 0
  
      enum DecoderStatus {SUCCESS, FORMAT_ERROR, VERIFICATION_ERROR};
  
      // If we want the decoder to verify the that local signature is OK we
      // will pass a non-NULL value for wbStatus
      //
      // When using LazyInit we want ask that the local signature be verified
      // But if we fail verification we still need access to the 'Code' field
      // Because we may be able to demand SkipVerification and thus it was OK
      // to have had a verification error.
  
      COR_ILMETHOD_DECODER(COR_ILMETHOD* header, 
                           void *pInternalImport,
                           DecoderStatus* wbStatus);
  
      unsigned EHCount() const 
      {
          return (EH != 0) ? EH->EHCount() : 0;
      }
  
      unsigned GetHeaderSize() const
      {
          return GetCodeSize() + ((EH != 0) ? EH->DataSize() : 0);
      }
  
      // returns total size of method for use in copying
      int GetOnDiskSize(const COR_ILMETHOD* header) 
      { 
          return DecoderGetOnDiskSize(this,(COR_ILMETHOD*)header); 
      }
  
      // Flags        these are available because we inherit COR_ILMETHOD_FAT
      // MaxStack
      // CodeSize
      const BYTE *    Code;
      PCCOR_SIGNATURE LocalVarSig;        // pointer to signature blob, or 0 if none
      DWORD           cbLocalVarSig;      // size of dignature blob, or 0 if none
      const COR_ILMETHOD_SECT_EH * EH;    // eh table if any  0 if none
      const COR_ILMETHOD_SECT *    Sect;  // additional sections  0 if none
  };  // class COR_ILMETHOD_DECODER
  
  #if defined(CORHLPR_TURNED_FPO_ON)
  #pragma optimize("", on)		// Go back to command line default optimizations
  #undef CORHLPR_TURNED_FPO_ON
  #undef FPO_ON
  #endif
  
  #endif // __CORHLPR_H__
  