/* Chordata - .NET File Format Parser
 * Copyright (C) 2001-2002  Jay Freeman (saurik)
*/

/*
 *        Redistribution and use in source and binary
 * forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation
 *    and/or other materials provided with the
 *    distribution.
 * 3. The name of the author may not be used to endorse
 *    or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef CHORDATA_ILMETHOD_H
#define CHORDATA_ILMETHOD_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Tokens.h"

namespace Chordata {
namespace ILMethod {

namespace Flags {
	enum CorILMethodFlags {
		InitLocals      = 0x0010,
		MoreSects       = 0x0008,
		CompressedIL    = 0x0040,

		FormatShift     = 3,
		FormatMask      = (1 << FormatShift) - 1,
		TinyFormat      = 0x0002,
		SmallFormat     = 0x0000,
		FatFormat       = 0x0003,
		TinyFormat1     = 0x0006
	};
}

struct Fat {
	uint32_t			Flags : 12;
    uint32_t			Size : 4;
    uint32_t			MaxStack : 16;
    uint32_t			CodeSize;
	Tokens::mdSignature	LocalVarSigTok;
};

struct Tiny { // Fscking Bogus Pretend Headers...
	uint8_t : 2;
	uint8_t size : 6;
}; // Microsoft: Was that SOO damned difficult?!?

namespace Section {
	namespace Flags {
		enum CorILMethodSect {
		    Reserved	= 0,
		    EHTable		= 1,
		    OptILTable	= 2,

		    KindMask	= 0x3F,
		    FatFormat	= 0x40,
		    MoreSects	= 0x80
		};
	}

	struct Fat {
		uint32_t Kind : 8;
		uint32_t DataSize : 24;
	};

	struct Small {
		uint8_t Kind;
		uint8_t DataSize;
	};

	namespace Exception {
		namespace Flags {
			enum CorExceptionFlag {
			    None,
			    OffsetLen	= 0x0,
			    Deprecated	= 0x0,
			    Filter		= 0x1,
			    Finally		= 0x2,
			    Fault		= 0x4
			};
		}

		struct FatHandlerClause {
			Flags::CorExceptionFlag	Flags;
		    uint32_t				TryOffset;
		    uint32_t				TryLength;
		    uint32_t				HandlerOffset;
		    uint32_t				HandlerLength;

		    union {
		        uint32_t			ClassToken;
		        uint32_t			FilterOffset;
		    };
		};
		
		struct FatHandler {
		    Fat					SectFat;
		    FatHandlerClause	Clauses[1];
		};

		struct SmallHandlerClause {
			Flags::CorExceptionFlag	Flags			: 16; // Win64!
		    uint32_t				TryOffset		: 16; 
		    uint32_t				TryLength		: 8;
		    uint32_t				HandlerOffset	: 16;
		    uint32_t				HandlerLength	: 8;

		    union {
		        uint32_t			ClassToken;
		        uint32_t			FilterOffset; 
		    };
		};
		
		struct SmallHandler {
			Small				SectSmall;
			uint16_t			Reserved;
			SmallHandlerClause	Clauses[1];
		};
	}
}

} }

#endif//CHORDATA_ILMETHOD_H