/******************************** -*- C -*- ****************************
 *
 *	Declarations for the byte code compiler.
 *
 *	$Revision: 1.7.5$
 *	$Date: 2000/05/28 16:56:52$
 *	$Author: pb$
 *
 ***********************************************************************/

/***********************************************************************
 *
 * Copyright 1988-92, 1994-95, 1999, 2000 Free Software Foundation, Inc.
 * Written by Steve Byrne.
 *
 * This file is part of GNU Smalltalk.
 *
 * GNU Smalltalk is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2, or (at your option) any later 
 * version.
 * 
 * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
 *
 ***********************************************************************/


#ifndef __GSTCOMP__
#define __GSTCOMP__

/* These next three defines are the number of bits in a method header for
   the number of stack bits, the number of temporaries, and the number of
   arguments that the method takes.  If the representation is changed, these
   definitions need to be altered too */
#define DEPTH_SCALE		2
#define MAX_DEPTH		(((1 << MTH_DEPTH_BITS) - 1) << DEPTH_SCALE)
#define MAX_NUM_TEMPS		((1 << MTH_TEMPS_BITS) - 1)
#define MAX_NUM_ARGS		((1 << MTH_ARGS_BITS) - 1)

/*
 * This is the organization of a method header.  The 1 bit in the high end of
 * the word indicates that this is an integer, so that the GC won't be tempted
 * to try to scan the contents of this field, and so we can do bitwise operations
 * on this value to extract component pieces.
 * 
 *    3                   2                   1 
 *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |.|flags| prim index        | #temps    |   depth   | #args   |1|
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * 
 * flags (30-28)
 *   flags 0 -- nothing
 *   flags 1 -- return self
 *   flags 2 -- return instance variable (# in primitive index)
 *   flags 3 -- return literal
 *   flags 4 -- primitive index
 */

#define MTH_DEPTH_BITS		6
#define MTH_TEMPS_BITS		6
#define MTH_ARGS_BITS		5
#define MTH_PRIM_BITS		10
#define MTH_FLAG_BITS		3

typedef struct MethodHeaderStruct {
#ifdef WORDS_BIGENDIAN
#if SIZEOF_LONG == 8
  unsigned	dummy		: 32; /* unused */
#endif
  unsigned			: 1; /* sign - must be 0 */
  unsigned	headerFlag	: MTH_FLAG_BITS; /* prim self, etc. */
  unsigned	primitiveIndex	: MTH_PRIM_BITS; /* index of primitve, or 0 */
  unsigned	numTemps	: MTH_TEMPS_BITS;
  unsigned	stackDepth	: MTH_DEPTH_BITS;
  unsigned	numArgs		: MTH_ARGS_BITS;
  unsigned	intMark		: 1; /* flag this as an Int */
#else
  unsigned	intMark		: 1; /* flag this as an Int */
  unsigned	numArgs		: MTH_ARGS_BITS;
  unsigned	stackDepth	: MTH_DEPTH_BITS;
  unsigned	numTemps	: MTH_TEMPS_BITS;
  unsigned	primitiveIndex	: MTH_PRIM_BITS; /* index of primitve, or 0 */
  unsigned	headerFlag	: MTH_FLAG_BITS; /* prim self, etc. */
  unsigned			: 1; /* sign - must be 0 */
#if SIZEOF_LONG == 8
  unsigned	dummy		: 32; /* unused */
#endif
#endif /* WORDS_BIGENDIAN */
} MethodHeader;

typedef struct CompiledMethodStruct {
  OBJ_HEADER;
  OOP		literals;
  MethodHeader	header;
  OOP		descriptor;
  Byte		bytecodes[1];
} *Method;

typedef struct MethodInfoStruct {
  OBJ_HEADER;
  OOP		sourceCode;
  OOP		category;
  OOP		class;
  OOP		selector;
} *MethodInfo;


/*
 * These definition parallel the above ones, but they are for blocks. Here is
 * the organization of a block header.
 * 
 *    3                   2                   1 
 *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |.|  #args  | #temps  |   depth   |      unused     | clean   |1|
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * 
 * flags (30-28)
 *   flags 0 -- nothing
 *   flags 1 -- return self
 *   flags 2 -- return instance variable (# in primitive index)
 *   flags 3 -- return literal
 *   flags 4 -- primitive index
 */

#define BLK_DEPTH_BITS		6
#define BLK_TEMPS_BITS		5
#define BLK_ARGS_BITS		5
#define BLK_CLEAN_BITS		5
#define BLK_UNUSED_BITS		9

typedef struct BlockHeaderStruct {
#ifdef WORDS_BIGENDIAN
#if SIZEOF_LONG == 8
  unsigned	dummy	 : 32;		    /* unused */
#endif
  unsigned		 : 1;		    /* sign - must be 0 */
  unsigned	numArgs	 : BLK_ARGS_BITS;   /* number of arguments we have */
  unsigned	numTemps : BLK_TEMPS_BITS;  /* number of temporaries we have */
  unsigned	depth	 : BLK_DEPTH_BITS;  /* number of stack slots needed */
  unsigned	unused	 : BLK_UNUSED_BITS;
  unsigned	clean	 : BLK_CLEAN_BITS;  /* behavior of block */
  unsigned	intMark	 : 1;		    /* flag this as an Int */
#else
  unsigned	intMark	 : 1;		    /* flag this as an Int */
  unsigned	clean	 : BLK_CLEAN_BITS;  /* behavior of block */
  unsigned	unused	 : BLK_UNUSED_BITS;
  unsigned	depth	 : BLK_DEPTH_BITS;  /* number of stack slots needed */
  unsigned	numTemps : BLK_TEMPS_BITS;  /* number of temporaries we have */
  unsigned	numArgs	 : BLK_ARGS_BITS;   /* number of arguments we have */
  unsigned		 : 1;		    /* sign - must be 0 */
#if SIZEOF_LONG == 8
  unsigned	dummy	 : 32;		    /* unused */
#endif
#endif
} BlockHeader;

typedef struct CompiledBlockStruct {
  OBJ_HEADER;
  OOP		literals;
  BlockHeader	header;
  OOP		method;
  Byte		bytecodes[1];
} *Block;

typedef struct BlockClosureStruct {
  OBJ_HEADER;
  OOP           outerContext;   /* the parent BlockContext or MethodContext */
  OOP           block;		/* the CompiledBlock */
  OOP           receiver;	/* the receiver in which the closure lives */
} *BlockClosure;


extern OOP		thisClass, latestCompiledMethod, lastReturnedValue;
extern mst_Boolean	declareTracing;
extern mst_Boolean	emacsProcess;
extern mst_Boolean	skipCompilation;

extern void		executeStatements(), displayCompilationTrace(),
			installInitialMethods(), setCompilationClass(),
			invokeInitBlocks(), compiledMethodAtPut(),
			setMethodDescriptor(), /* copyCompileContext(), */
			setCompilationCategory(), markCompileContext();
extern OOP		compileMethod(), compiledMethodAt(),
			getMethodDescriptor(), makeNewMethod(),
			getTerminationMethod(), blockNew();
extern int		addForcedObject();
extern mst_Boolean	validMethodIndex(), isIdentityLiteral();

#define getMethodHeader(methodOOP) \
  (((Method)oopToObj(methodOOP))->header)


#endif /* __GSTCOMP__ */
