summaryrefslogtreecommitdiff
path: root/ghc/includes/Assembler.h
blob: 105acf3cf18f2b6653ace29138f0c1db254a5e41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/* -*- mode: hugs-c; -*- */
/* -----------------------------------------------------------------------------
 * Bytecode assembler
 *
 * Copyright (c) 1994-1998.
 *
 * $RCSfile: Assembler.h,v $
 * $Revision: 1.3 $
 * $Date: 1999/01/18 15:23:30 $
 *
 * NB This is one of the few files shared between Hugs and the runtime system,
 * so it is very important that it not conflict with either and that it not
 * rely on either.  
 * (In fact, it might be fun to create a GreenCard interface to this file too.)
 * ---------------------------------------------------------------------------*/

/* ToDo: put this somewhere more sensible */
extern void DEBUG_LoadSymbols( char *name );

/* This file is supposed to be somewhat self-contained because it is one
 * of the major external interfaces to the runtime system.
 * Keeping it self-contained reduces the chance of conflict with Hugs
 * (or anything else that includes it).
 * The big disadvantage of being self-contained is that definitions
 * like AsmNat8, etc duplicate definitions in StgTypes.h.
 * I'm not sure what we can do about this but, if you try to fix it,
 * please remember why it was done this way in the first place.
 * -- ADR
 */

typedef unsigned char   AsmNat8;
typedef unsigned int    AsmNat;
typedef signed   int    AsmInt;
typedef signed long long int AsmInt64;  /* ToDo: not portable!  */
typedef unsigned int    AsmWord;
typedef void*           AsmAddr;
typedef unsigned char   AsmChar;
typedef float           AsmFloat;       /* ToDo: not on Alphas! */
typedef double          AsmDouble;
typedef char*           AsmString;

/* I want to #include this file into the file that defines the
 * functions but I don't want to expose the structures that
 * these types point to.
 * This hack is the best I could think of.  Surely there's a better way?
 */
#ifdef INSIDE_ASSEMBLER_C
typedef struct AsmObject_ *AsmObject;
typedef struct AsmBCO_    *AsmBCO;
typedef struct AsmCAF_    *AsmCAF;
typedef struct AsmCon_    *AsmCon;
typedef StgInfoTable      *AsmInfo;
typedef StgClosure        *AsmClosure;
typedef Instr              AsmInstr;
#else
/* the types we export are totally opaque */
typedef void              *AsmObject;
typedef void              *AsmBCO;
typedef void              *AsmCAF;
typedef void              *AsmCon;
typedef void              *AsmInfo;
typedef void              *AsmClosure;
typedef unsigned int       AsmInstr;
#endif

typedef int   AsmSp;   /* stack offset                  */
typedef int   AsmPc;   /* program counter		*/
typedef AsmSp AsmVar;  /* offset of a Var on the stack  */

/* --------------------------------------------------------------------------
 * "Types" used within the assembler
 *
 * Some of these types are synonyms for the same underlying representation
 * to let Hugs (or whoever) generate useful Haskell types from the type
 * of a primitive operation.
 *
 *  Extreme care should be taken if you change any of these - the
 *  same constants are hardwired into Hugs (ILLEGAL_REP) and into
 *  pieces of assembly language used to implement foreign import/export.
 *  And, of course, you'll have to change the primop table in Assembler.c
 * ------------------------------------------------------------------------*/

typedef enum {
  ILLEGAL_REP = 0,

  /* The following can be passed to C */
  CHAR_REP    = 'C',     
  INT_REP     = 'I',      
#ifdef PROVIDE_INT64
  INT64_REP   = 'z', 
#endif
#ifdef PROVIDE_INTEGER
  INTEGER_REP = 'Z',  
#endif
#ifdef PROVIDE_WORD
  WORD_REP    = 'W',     
#endif
#ifdef PROVIDE_ADDR
  ADDR_REP    = 'A',     
#endif
  FLOAT_REP   = 'F',    
  DOUBLE_REP  = 'D',   
#ifdef PROVIDE_STABLE
  STABLE_REP  = 's',   /* StablePtr a */
#endif
#ifdef PROVIDE_FOREIGN
  FOREIGN_REP = 'f',   /* ForeignObj  */
#endif
#ifdef PROVIDE_WEAK
  WEAK_REP    = 'w',   /* Weak a      */
#endif
#ifdef PROVIDE_ARRAY
  BARR_REP     = 'x',  /* PrimByteArray          a */
  MUTBARR_REP  = 'm',  /* PrimMutableByteArray s a */
#endif

  /* The following can't be passed to C */
  PTR_REP      = 'P',      
  ALPHA_REP    = 'a',  /* a                        */
  BETA_REP     = 'b',  /* b			   */
  GAMMA_REP    = 'c',  /* c                        */
  BOOL_REP     = 'B',  /* Bool			   */
  IO_REP       = 'i',  /* IO a	                   */
  HANDLER_REP  = 'H',  /* Exception -> IO a	   */
  ERROR_REP    = 'E',  /* Exception		   */
#ifdef PROVIDE_ARRAY		
  ARR_REP      = 'X',  /* PrimArray              a */
  REF_REP      = 'R',  /* Ref                  s a */
  MUTARR_REP   = 'M',  /* PrimMutableArray     s a */
#endif
#ifdef PROVIDE_CONCURRENT
  THREADID_REP = 'T',  /* ThreadId                 */
  MVAR_REP     = 'r',  /* MVar a                   */
#endif

  /* Allegedly used in the IO monad */
  VOID_REP     = 'v'      
} AsmRep;

/* --------------------------------------------------------------------------
 * Allocating (top level) heap objects
 * ------------------------------------------------------------------------*/

extern AsmBCO     asmBeginBCO        ( void );
extern void       asmEndBCO          ( AsmBCO bco );

extern AsmBCO     asmBeginContinuation ( AsmSp sp );
extern void       asmEndContinuation   ( AsmBCO bco );

extern AsmObject  asmMkObject        ( AsmClosure c );

extern AsmCAF     asmBeginCAF        ( void );
extern void       asmEndCAF          ( AsmCAF caf, AsmBCO body );

extern AsmInfo    asmMkInfo          ( AsmNat tag, AsmNat ptrs );
extern AsmCon     asmBeginCon        ( AsmInfo info );
extern void       asmEndCon          ( AsmCon con );

/* NB: we add ptrs to other objects in left-to-right order.
 * This is different from pushing arguments on the stack which is done
 * in right to left order.
 */
extern void       asmAddPtr          ( AsmObject obj, AsmObject arg );

extern int        asmObjectHasClosure( AsmObject obj );
extern AsmClosure asmClosureOfObject ( AsmObject obj );
extern void       asmMarkObject      ( AsmObject obj );

/* --------------------------------------------------------------------------
 * Generating instruction streams
 * ------------------------------------------------------------------------*/
                               
extern AsmSp  asmBeginArgCheck ( AsmBCO bco );
extern void   asmEndArgCheck   ( AsmBCO bco, AsmSp last_arg );
                               
extern AsmSp  asmBeginEnter    ( AsmBCO bco );
extern void   asmEndEnter      ( AsmBCO bco, AsmSp sp1, AsmSp sp2 );
                               
extern AsmVar asmBind          ( AsmBCO bco, AsmRep rep );
extern void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep );
                               
extern AsmSp  asmBeginCase     ( AsmBCO bco );
extern void   asmEndCase       ( AsmBCO bco );
extern AsmSp  asmContinuation  ( AsmBCO bco, AsmBCO ret_addr );
                               
extern AsmSp  asmBeginAlt      ( AsmBCO bco );
extern void   asmEndAlt        ( AsmBCO bco, AsmSp  sp );
extern AsmPc  asmTest          ( AsmBCO bco, AsmWord tag );
extern AsmPc  asmTestInt       ( AsmBCO bco, AsmVar v, AsmInt x );
extern void   asmFixBranch     ( AsmBCO bco, AsmPc pc );
extern void   asmPanic         ( AsmBCO bco );
                               
extern AsmVar asmBox           ( AsmBCO bco, AsmRep rep );
extern AsmVar asmUnbox         ( AsmBCO bco, AsmRep rep );
extern void   asmReturnUnboxed ( AsmBCO bco, AsmRep rep );             

/* push unboxed Ints, Floats, etc */
extern void   asmConstInt      ( AsmBCO bco, AsmInt     x );
#ifdef PROVIDE_ADDR
extern void   asmConstAddr     ( AsmBCO bco, AsmAddr    x );
#endif
#ifdef PROVIDE_WORD
extern void   asmConstWord     ( AsmBCO bco, AsmWord    x );
#endif
extern void   asmConstChar     ( AsmBCO bco, AsmChar    x );
extern void   asmConstFloat    ( AsmBCO bco, AsmFloat   x );
extern void   asmConstDouble   ( AsmBCO bco, AsmDouble  x );
#ifdef PROVIDE_INT64
extern void   asmConstInt64    ( AsmBCO bco, AsmInt64   x );
#endif
#ifdef PROVIDE_INTEGER
extern void   asmConstInteger  ( AsmBCO bco, AsmString  x );
#endif
             
/* Which monad (if any) does the primop live in? */
typedef enum {
    MONAD_Id,  /* no monad (aka the identity monad) */
    MONAD_ST,
    MONAD_IO
} AsmMonad;

typedef struct {
    char*    name;
    char*    args;
    char*    results;
    AsmMonad monad;
    AsmNat8  prefix; /* should be StgInstr           */
    AsmNat8  opcode; /* should be Primop1 or Primop2 */
} AsmPrim;

extern const AsmPrim asmPrimOps[]; /* null terminated list */

extern const AsmPrim* asmFindPrim    ( char* s );
extern const AsmPrim* asmFindPrimop  ( AsmInstr prefix, AsmInstr op );
extern AsmSp          asmBeginPrim   ( AsmBCO bco );
extern void           asmEndPrim     ( AsmBCO bco, const AsmPrim* prim, AsmSp base );

/* --------------------------------------------------------------------------
 * Heap manipulation
 * ------------------------------------------------------------------------*/

extern AsmVar asmClosure       ( AsmBCO bco, AsmObject p );

extern AsmVar asmAllocCONSTR   ( AsmBCO bco, AsmInfo info );

extern AsmSp  asmBeginPack     ( AsmBCO bco );
extern void   asmEndPack       ( AsmBCO bco, AsmVar v, AsmSp start, AsmInfo info );

extern void   asmBeginUnpack   ( AsmBCO bco );
extern void   asmEndUnpack     ( AsmBCO bco );

extern AsmVar asmAllocAP       ( AsmBCO bco, AsmNat size );
extern AsmSp  asmBeginMkAP     ( AsmBCO bco );
extern void   asmEndMkAP       ( AsmBCO bco, AsmVar v, AsmSp start );

extern AsmVar asmAllocPAP      ( AsmBCO bco, AsmNat size );
extern AsmSp  asmBeginMkPAP    ( AsmBCO bco );
extern void   asmEndMkPAP      ( AsmBCO bco, AsmVar v, AsmSp start );

/* --------------------------------------------------------------------------
 * C-call and H-call
 * ------------------------------------------------------------------------*/

extern const AsmPrim ccall_Id;
extern const AsmPrim ccall_IO;

typedef struct {
  char *        arg_tys;
  int           arg_size;
  char *        result_tys;
  int           result_size;
} CFunDescriptor;

typedef struct {
  char *        arg_tys;
  char *        result_tys;
} HFunDescriptor;

CFunDescriptor* mkDescriptor( char* as, char* rs );

/*-------------------------------------------------------------------------*/