Missing import in C-- parser
[ghc-hetmet.git] / compiler / cmm / CmmParse.y
1 -----------------------------------------------------------------------------
2 --
3 -- (c) The University of Glasgow, 2004-2006
4 --
5 -- Parser for concrete Cmm.
6 --
7 -----------------------------------------------------------------------------
8
9 {
10 {-# OPTIONS -w #-}
11 -- The above warning supression flag is a temporary kludge.
12 -- While working on this module you are encouraged to remove it and fix
13 -- any warnings in the module. See
14 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
15 -- for details
16
17 module CmmParse ( parseCmmFile ) where
18
19 import CgMonad
20 import CgHeapery
21 import CgUtils
22 import CgProf
23 import CgTicky
24 import CgInfoTbls
25 import CgForeignCall
26 import CgTailCall
27 import CgStackery
28 import ClosureInfo
29 import CgCallConv
30 import CgClosure
31 import CostCentre
32
33 import BlockId
34 import Cmm
35 import PprCmm
36 import CmmUtils
37 import CmmLex
38 import CLabel
39 import MachOp
40 import SMRep
41 import Lexer
42
43 import ForeignCall
44 import Literal
45 import Unique
46 import UniqFM
47 import SrcLoc
48 import DynFlags
49 import StaticFlags
50 import ErrUtils
51 import StringBuffer
52 import FastString
53 import Panic
54 import Constants
55 import Outputable
56
57 import Control.Monad
58 import Data.Array
59 import Data.Char        ( ord )
60 import System.Exit
61
62 #include "HsVersions.h"
63 }
64
65 %token
66         ':'     { L _ (CmmT_SpecChar ':') }
67         ';'     { L _ (CmmT_SpecChar ';') }
68         '{'     { L _ (CmmT_SpecChar '{') }
69         '}'     { L _ (CmmT_SpecChar '}') }
70         '['     { L _ (CmmT_SpecChar '[') }
71         ']'     { L _ (CmmT_SpecChar ']') }
72         '('     { L _ (CmmT_SpecChar '(') }
73         ')'     { L _ (CmmT_SpecChar ')') }
74         '='     { L _ (CmmT_SpecChar '=') }
75         '`'     { L _ (CmmT_SpecChar '`') }
76         '~'     { L _ (CmmT_SpecChar '~') }
77         '/'     { L _ (CmmT_SpecChar '/') }
78         '*'     { L _ (CmmT_SpecChar '*') }
79         '%'     { L _ (CmmT_SpecChar '%') }
80         '-'     { L _ (CmmT_SpecChar '-') }
81         '+'     { L _ (CmmT_SpecChar '+') }
82         '&'     { L _ (CmmT_SpecChar '&') }
83         '^'     { L _ (CmmT_SpecChar '^') }
84         '|'     { L _ (CmmT_SpecChar '|') }
85         '>'     { L _ (CmmT_SpecChar '>') }
86         '<'     { L _ (CmmT_SpecChar '<') }
87         ','     { L _ (CmmT_SpecChar ',') }
88         '!'     { L _ (CmmT_SpecChar '!') }
89
90         '..'    { L _ (CmmT_DotDot) }
91         '::'    { L _ (CmmT_DoubleColon) }
92         '>>'    { L _ (CmmT_Shr) }
93         '<<'    { L _ (CmmT_Shl) }
94         '>='    { L _ (CmmT_Ge) }
95         '<='    { L _ (CmmT_Le) }
96         '=='    { L _ (CmmT_Eq) }
97         '!='    { L _ (CmmT_Ne) }
98         '&&'    { L _ (CmmT_BoolAnd) }
99         '||'    { L _ (CmmT_BoolOr) }
100
101         'CLOSURE'       { L _ (CmmT_CLOSURE) }
102         'INFO_TABLE'    { L _ (CmmT_INFO_TABLE) }
103         'INFO_TABLE_RET'{ L _ (CmmT_INFO_TABLE_RET) }
104         'INFO_TABLE_FUN'{ L _ (CmmT_INFO_TABLE_FUN) }
105         'INFO_TABLE_CONSTR'{ L _ (CmmT_INFO_TABLE_CONSTR) }
106         'INFO_TABLE_SELECTOR'{ L _ (CmmT_INFO_TABLE_SELECTOR) }
107         'else'          { L _ (CmmT_else) }
108         'export'        { L _ (CmmT_export) }
109         'section'       { L _ (CmmT_section) }
110         'align'         { L _ (CmmT_align) }
111         'goto'          { L _ (CmmT_goto) }
112         'if'            { L _ (CmmT_if) }
113         'jump'          { L _ (CmmT_jump) }
114         'foreign'       { L _ (CmmT_foreign) }
115         'never'         { L _ (CmmT_never) }
116         'prim'          { L _ (CmmT_prim) }
117         'return'        { L _ (CmmT_return) }
118         'returns'       { L _ (CmmT_returns) }
119         'import'        { L _ (CmmT_import) }
120         'switch'        { L _ (CmmT_switch) }
121         'case'          { L _ (CmmT_case) }
122         'default'       { L _ (CmmT_default) }
123         'bits8'         { L _ (CmmT_bits8) }
124         'bits16'        { L _ (CmmT_bits16) }
125         'bits32'        { L _ (CmmT_bits32) }
126         'bits64'        { L _ (CmmT_bits64) }
127         'float32'       { L _ (CmmT_float32) }
128         'float64'       { L _ (CmmT_float64) }
129
130         GLOBALREG       { L _ (CmmT_GlobalReg   $$) }
131         NAME            { L _ (CmmT_Name        $$) }
132         STRING          { L _ (CmmT_String      $$) }
133         INT             { L _ (CmmT_Int         $$) }
134         FLOAT           { L _ (CmmT_Float       $$) }
135
136 %monad { P } { >>= } { return }
137 %lexer { cmmlex } { L _ CmmT_EOF }
138 %name cmmParse cmm
139 %tokentype { Located CmmToken }
140
141 -- C-- operator precedences, taken from the C-- spec
142 %right '||'     -- non-std extension, called %disjoin in C--
143 %right '&&'     -- non-std extension, called %conjoin in C--
144 %right '!'
145 %nonassoc '>=' '>' '<=' '<' '!=' '=='
146 %left '|'
147 %left '^'
148 %left '&'
149 %left '>>' '<<'
150 %left '-' '+'
151 %left '/' '*' '%'
152 %right '~'
153
154 %%
155
156 cmm     :: { ExtCode }
157         : {- empty -}                   { return () }
158         | cmmtop cmm                    { do $1; $2 }
159
160 cmmtop  :: { ExtCode }
161         : cmmproc                       { $1 }
162         | cmmdata                       { $1 }
163         | decl                          { $1 } 
164         | 'CLOSURE' '(' NAME ',' NAME lits ')' ';'  
165                 { do lits <- sequence $6;
166                      staticClosure $3 $5 (map getLit lits) }
167
168 -- The only static closures in the RTS are dummy closures like
169 -- stg_END_TSO_QUEUE_closure and stg_dummy_ret.  We don't need
170 -- to provide the full generality of static closures here.
171 -- In particular:
172 --      * CCS can always be CCS_DONT_CARE
173 --      * closure is always extern
174 --      * payload is always empty
175 --      * we can derive closure and info table labels from a single NAME
176
177 cmmdata :: { ExtCode }
178         : 'section' STRING '{' statics '}' 
179                 { do ss <- sequence $4;
180                      code (emitData (section $2) (concat ss)) }
181
182 statics :: { [ExtFCode [CmmStatic]] }
183         : {- empty -}                   { [] }
184         | static statics                { $1 : $2 }
185
186 -- Strings aren't used much in the RTS HC code, so it doesn't seem
187 -- worth allowing inline strings.  C-- doesn't allow them anyway.
188 static  :: { ExtFCode [CmmStatic] }
189         : NAME ':'      { return [CmmDataLabel (mkRtsDataLabelFS $1)] }
190         | type expr ';' { do e <- $2;
191                              return [CmmStaticLit (getLit e)] }
192         | type ';'                      { return [CmmUninitialised
193                                                         (machRepByteWidth $1)] }
194         | 'bits8' '[' ']' STRING ';'    { return [mkString $4] }
195         | 'bits8' '[' INT ']' ';'       { return [CmmUninitialised 
196                                                         (fromIntegral $3)] }
197         | typenot8 '[' INT ']' ';'      { return [CmmUninitialised 
198                                                 (machRepByteWidth $1 * 
199                                                         fromIntegral $3)] }
200         | 'align' INT ';'               { return [CmmAlign (fromIntegral $2)] }
201         | 'CLOSURE' '(' NAME lits ')'
202                 { do lits <- sequence $4;
203                      return $ map CmmStaticLit $
204                        mkStaticClosure (mkForeignLabel $3 Nothing True)
205                          -- mkForeignLabel because these are only used
206                          -- for CHARLIKE and INTLIKE closures in the RTS.
207                          dontCareCCS (map getLit lits) [] [] [] }
208         -- arrays of closures required for the CHARLIKE & INTLIKE arrays
209
210 lits    :: { [ExtFCode CmmExpr] }
211         : {- empty -}           { [] }
212         | ',' expr lits         { $2 : $3 }
213
214 cmmproc :: { ExtCode }
215 -- TODO: add real SRT/info tables to parsed Cmm
216         : info maybe_formals_without_kinds maybe_gc_block maybe_frame '{' body '}'
217                 { do ((entry_ret_label, info, live, formals, gc_block, frame), stmts) <-
218                        getCgStmtsEC' $ loopDecls $ do {
219                          (entry_ret_label, info, live) <- $1;
220                          formals <- sequence $2;
221                          gc_block <- $3;
222                          frame <- $4;
223                          $6;
224                          return (entry_ret_label, info, live, formals, gc_block, frame) }
225                      blks <- code (cgStmtsToBlocks stmts)
226                      code (emitInfoTableAndCode entry_ret_label (CmmInfo gc_block frame info) formals blks) }
227
228         | info maybe_formals_without_kinds ';'
229                 { do (entry_ret_label, info, live) <- $1;
230                      formals <- sequence $2;
231                      code (emitInfoTableAndCode entry_ret_label (CmmInfo Nothing Nothing info) formals []) }
232
233         | NAME maybe_formals_without_kinds maybe_gc_block maybe_frame '{' body '}'
234                 { do ((formals, gc_block, frame), stmts) <-
235                         getCgStmtsEC' $ loopDecls $ do {
236                           formals <- sequence $2;
237                           gc_block <- $3;
238                           frame <- $4;
239                           $6;
240                           return (formals, gc_block, frame) }
241                      blks <- code (cgStmtsToBlocks stmts)
242                      code (emitProc (CmmInfo gc_block frame CmmNonInfoTable) (mkRtsCodeLabelFS $1) formals blks) }
243
244 info    :: { ExtFCode (CLabel, CmmInfoTable, [Maybe LocalReg]) }
245         : 'INFO_TABLE' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ')'
246                 -- ptrs, nptrs, closure type, description, type
247                 { do prof <- profilingInfo $11 $13
248                      return (mkRtsEntryLabelFS $3,
249                         CmmInfoTable prof (fromIntegral $9)
250                                      (ThunkInfo (fromIntegral $5, fromIntegral $7) NoC_SRT),
251                         []) }
252         
253         | 'INFO_TABLE_FUN' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ',' INT ')'
254                 -- ptrs, nptrs, closure type, description, type, fun type
255                 { do prof <- profilingInfo $11 $13
256                      return (mkRtsEntryLabelFS $3,
257                         CmmInfoTable prof (fromIntegral $9)
258                                      (FunInfo (fromIntegral $5, fromIntegral $7) NoC_SRT (fromIntegral $15) 0
259                                       (ArgSpec 0)
260                                       zeroCLit),
261                         []) }
262                 -- we leave most of the fields zero here.  This is only used
263                 -- to generate the BCO info table in the RTS at the moment.
264
265         -- A variant with a non-zero arity (needed to write Main_main in Cmm)
266         | 'INFO_TABLE_FUN' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ',' INT ',' INT ')'
267                 -- ptrs, nptrs, closure type, description, type, fun type, arity
268                 { do prof <- profilingInfo $11 $13
269                      return (mkRtsEntryLabelFS $3,
270                         CmmInfoTable prof (fromIntegral $9)
271                                      (FunInfo (fromIntegral $5, fromIntegral $7) NoC_SRT (fromIntegral $15) (fromIntegral $17)
272                                       (ArgSpec 0)
273                                       zeroCLit),
274                         []) }
275                 -- we leave most of the fields zero here.  This is only used
276                 -- to generate the BCO info table in the RTS at the moment.
277         
278         | 'INFO_TABLE_CONSTR' '(' NAME ',' INT ',' INT ',' INT ',' INT ',' STRING ',' STRING ')'
279                 -- ptrs, nptrs, tag, closure type, description, type
280                 { do prof <- profilingInfo $13 $15
281                      -- If profiling is on, this string gets duplicated,
282                      -- but that's the way the old code did it we can fix it some other time.
283                      desc_lit <- code $ mkStringCLit $13
284                      return (mkRtsEntryLabelFS $3,
285                         CmmInfoTable prof (fromIntegral $11)
286                                      (ConstrInfo (fromIntegral $5, fromIntegral $7) (fromIntegral $9) desc_lit),
287                         []) }
288         
289         | 'INFO_TABLE_SELECTOR' '(' NAME ',' INT ',' INT ',' STRING ',' STRING ')'
290                 -- selector, closure type, description, type
291                 { do prof <- profilingInfo $9 $11
292                      return (mkRtsEntryLabelFS $3,
293                         CmmInfoTable prof (fromIntegral $7)
294                                      (ThunkSelectorInfo (fromIntegral $5) NoC_SRT),
295                         []) }
296
297         | 'INFO_TABLE_RET' '(' NAME ',' INT ')'
298                 -- closure type (no live regs)
299                 { do let infoLabel = mkRtsInfoLabelFS $3
300                      return (mkRtsRetLabelFS $3,
301                         CmmInfoTable (ProfilingInfo zeroCLit zeroCLit) (fromIntegral $5)
302                                      (ContInfo [] NoC_SRT),
303                         []) }
304
305         | 'INFO_TABLE_RET' '(' NAME ',' INT ',' formals_without_kinds0 ')'
306                 -- closure type, live regs
307                 { do live <- sequence (map (liftM Just) $7)
308                      return (mkRtsRetLabelFS $3,
309                         CmmInfoTable (ProfilingInfo zeroCLit zeroCLit) (fromIntegral $5)
310                                      (ContInfo live NoC_SRT),
311                         live) }
312
313 body    :: { ExtCode }
314         : {- empty -}                   { return () }
315         | decl body                     { do $1; $2 }
316         | stmt body                     { do $1; $2 }
317
318 decl    :: { ExtCode }
319         : type names ';'                { mapM_ (newLocal defaultKind $1) $2 }
320         | STRING type names ';'         {% do k <- parseGCKind $1;
321                                               return $ mapM_ (newLocal k $2) $3 }
322
323         | 'import' names ';'            { mapM_ newImport $2 }
324         | 'export' names ';'            { return () }  -- ignore exports
325
326 names   :: { [FastString] }
327         : NAME                  { [$1] }
328         | NAME ',' names        { $1 : $3 }
329
330 stmt    :: { ExtCode }
331         : ';'                                   { nopEC }
332
333         | NAME ':'
334                 { do l <- newLabel $1; code (labelC l) }
335
336         | lreg '=' expr ';'
337                 { do reg <- $1; e <- $3; stmtEC (CmmAssign reg e) }
338         | type '[' expr ']' '=' expr ';'
339                 { doStore $1 $3 $6 }
340
341         -- Gah! We really want to say "maybe_results" but that causes
342         -- a shift/reduce conflict with assignment.  We either
343         -- we expand out the no-result and single result cases or
344         -- we tweak the syntax to avoid the conflict.  The later
345         -- option is taken here because the other way would require
346         -- multiple levels of expanding and get unwieldy.
347         | maybe_results 'foreign' STRING expr '(' cmm_kind_exprs0 ')' safety vols opt_never_returns ';'
348                 {% foreignCall $3 $1 $4 $6 $9 $8 $10 }
349         | maybe_results 'prim' '%' NAME '(' cmm_kind_exprs0 ')' safety vols ';'
350                 {% primCall $1 $4 $6 $9 $8 }
351         -- stmt-level macros, stealing syntax from ordinary C-- function calls.
352         -- Perhaps we ought to use the %%-form?
353         | NAME '(' exprs0 ')' ';'
354                 {% stmtMacro $1 $3  }
355         | 'switch' maybe_range expr '{' arms default '}'
356                 { doSwitch $2 $3 $5 $6 }
357         | 'goto' NAME ';'
358                 { do l <- lookupLabel $2; stmtEC (CmmBranch l) }
359         | 'jump' expr maybe_actuals ';'
360                 { do e1 <- $2; e2 <- sequence $3; stmtEC (CmmJump e1 e2) }
361         | 'return' maybe_actuals ';'
362                 { do e <- sequence $2; stmtEC (CmmReturn e) }
363         | 'if' bool_expr '{' body '}' else      
364                 { ifThenElse $2 $4 $6 }
365
366 opt_never_returns :: { CmmReturnInfo }
367         :                               { CmmMayReturn }
368         | 'never' 'returns'             { CmmNeverReturns }
369
370 bool_expr :: { ExtFCode BoolExpr }
371         : bool_op                       { $1 }
372         | expr                          { do e <- $1; return (BoolTest e) }
373
374 bool_op :: { ExtFCode BoolExpr }
375         : bool_expr '&&' bool_expr      { do e1 <- $1; e2 <- $3; 
376                                           return (BoolAnd e1 e2) }
377         | bool_expr '||' bool_expr      { do e1 <- $1; e2 <- $3; 
378                                           return (BoolOr e1 e2)  }
379         | '!' bool_expr                 { do e <- $2; return (BoolNot e) }
380         | '(' bool_op ')'               { $2 }
381
382 -- This is not C-- syntax.  What to do?
383 safety  :: { CmmSafety }
384         : {- empty -}                   { CmmUnsafe } -- Default may change soon
385         | STRING                        {% parseSafety $1 }
386
387 -- This is not C-- syntax.  What to do?
388 vols    :: { Maybe [GlobalReg] }
389         : {- empty -}                   { Nothing }
390         | '[' ']'                       { Just [] }
391         | '[' globals ']'               { Just $2 }
392
393 globals :: { [GlobalReg] }
394         : GLOBALREG                     { [$1] }
395         | GLOBALREG ',' globals         { $1 : $3 }
396
397 maybe_range :: { Maybe (Int,Int) }
398         : '[' INT '..' INT ']'  { Just (fromIntegral $2, fromIntegral $4) }
399         | {- empty -}           { Nothing }
400
401 arms    :: { [([Int],ExtCode)] }
402         : {- empty -}                   { [] }
403         | arm arms                      { $1 : $2 }
404
405 arm     :: { ([Int],ExtCode) }
406         : 'case' ints ':' '{' body '}'  { ($2, $5) }
407
408 ints    :: { [Int] }
409         : INT                           { [ fromIntegral $1 ] }
410         | INT ',' ints                  { fromIntegral $1 : $3 }
411
412 default :: { Maybe ExtCode }
413         : 'default' ':' '{' body '}'    { Just $4 }
414         -- taking a few liberties with the C-- syntax here; C-- doesn't have
415         -- 'default' branches
416         | {- empty -}                   { Nothing }
417
418 else    :: { ExtCode }
419         : {- empty -}                   { nopEC }
420         | 'else' '{' body '}'           { $3 }
421
422 -- we have to write this out longhand so that Happy's precedence rules
423 -- can kick in.
424 expr    :: { ExtFCode CmmExpr } 
425         : expr '/' expr                 { mkMachOp MO_U_Quot [$1,$3] }
426         | expr '*' expr                 { mkMachOp MO_Mul [$1,$3] }
427         | expr '%' expr                 { mkMachOp MO_U_Rem [$1,$3] }
428         | expr '-' expr                 { mkMachOp MO_Sub [$1,$3] }
429         | expr '+' expr                 { mkMachOp MO_Add [$1,$3] }
430         | expr '>>' expr                { mkMachOp MO_U_Shr [$1,$3] }
431         | expr '<<' expr                { mkMachOp MO_Shl [$1,$3] }
432         | expr '&' expr                 { mkMachOp MO_And [$1,$3] }
433         | expr '^' expr                 { mkMachOp MO_Xor [$1,$3] }
434         | expr '|' expr                 { mkMachOp MO_Or [$1,$3] }
435         | expr '>=' expr                { mkMachOp MO_U_Ge [$1,$3] }
436         | expr '>' expr                 { mkMachOp MO_U_Gt [$1,$3] }
437         | expr '<=' expr                { mkMachOp MO_U_Le [$1,$3] }
438         | expr '<' expr                 { mkMachOp MO_U_Lt [$1,$3] }
439         | expr '!=' expr                { mkMachOp MO_Ne [$1,$3] }
440         | expr '==' expr                { mkMachOp MO_Eq [$1,$3] }
441         | '~' expr                      { mkMachOp MO_Not [$2] }
442         | '-' expr                      { mkMachOp MO_S_Neg [$2] }
443         | expr0 '`' NAME '`' expr0      {% do { mo <- nameToMachOp $3 ;
444                                                 return (mkMachOp mo [$1,$5]) } }
445         | expr0                         { $1 }
446
447 expr0   :: { ExtFCode CmmExpr }
448         : INT   maybe_ty         { return (CmmLit (CmmInt $1 $2)) }
449         | FLOAT maybe_ty         { return (CmmLit (CmmFloat $1 $2)) }
450         | STRING                 { do s <- code (mkStringCLit $1); 
451                                       return (CmmLit s) }
452         | reg                    { $1 }
453         | type '[' expr ']'      { do e <- $3; return (CmmLoad e $1) }
454         | '%' NAME '(' exprs0 ')' {% exprOp $2 $4 }
455         | '(' expr ')'           { $2 }
456
457
458 -- leaving out the type of a literal gives you the native word size in C--
459 maybe_ty :: { MachRep }
460         : {- empty -}                   { wordRep }
461         | '::' type                     { $2 }
462
463 maybe_actuals :: { [ExtFCode CmmActual] }
464         : {- empty -}           { [] }
465         | '(' cmm_kind_exprs0 ')'       { $2 }
466
467 cmm_kind_exprs0 :: { [ExtFCode CmmActual] }
468         : {- empty -}                   { [] }
469         | cmm_kind_exprs                        { $1 }
470
471 cmm_kind_exprs :: { [ExtFCode CmmActual] }
472         : cmm_kind_expr                 { [$1] }
473         | cmm_kind_expr ',' cmm_kind_exprs      { $1 : $3 }
474
475 cmm_kind_expr :: { ExtFCode CmmActual }
476         : expr                          { do e <- $1; return (CmmKinded e (inferCmmKind e)) }
477         | expr STRING                   {% do h <- parseCmmKind $2;
478                                               return $ do
479                                                 e <- $1; return (CmmKinded e h) }
480
481 exprs0  :: { [ExtFCode CmmExpr] }
482         : {- empty -}                   { [] }
483         | exprs                         { $1 }
484
485 exprs   :: { [ExtFCode CmmExpr] }
486         : expr                          { [ $1 ] }
487         | expr ',' exprs                { $1 : $3 }
488
489 reg     :: { ExtFCode CmmExpr }
490         : NAME                  { lookupName $1 }
491         | GLOBALREG             { return (CmmReg (CmmGlobal $1)) }
492
493 maybe_results :: { [ExtFCode CmmFormal] }
494         : {- empty -}           { [] }
495         | '(' cmm_formals ')' '='       { $2 }
496
497 cmm_formals :: { [ExtFCode CmmFormal] }
498         : cmm_formal                    { [$1] }
499         | cmm_formal ','                        { [$1] }
500         | cmm_formal ',' cmm_formals    { $1 : $3 }
501
502 cmm_formal :: { ExtFCode CmmFormal }
503         : local_lreg                    { do e <- $1; return (CmmKinded e (inferCmmKind (CmmReg (CmmLocal e)))) }
504         | STRING local_lreg             {% do h <- parseCmmKind $1;
505                                               return $ do
506                                                 e <- $2; return (CmmKinded e h) }
507
508 local_lreg :: { ExtFCode LocalReg }
509         : NAME                  { do e <- lookupName $1;
510                                      return $
511                                        case e of 
512                                         CmmReg (CmmLocal r) -> r
513                                         other -> pprPanic "CmmParse:" (ftext $1 <> text " not a local register") }
514
515 lreg    :: { ExtFCode CmmReg }
516         : NAME                  { do e <- lookupName $1;
517                                      return $
518                                        case e of 
519                                         CmmReg r -> r
520                                         other -> pprPanic "CmmParse:" (ftext $1 <> text " not a register") }
521         | GLOBALREG             { return (CmmGlobal $1) }
522
523 maybe_formals_without_kinds :: { [ExtFCode LocalReg] }
524         : {- empty -}           { [] }
525         | '(' formals_without_kinds0 ')'        { $2 }
526
527 formals_without_kinds0 :: { [ExtFCode LocalReg] }
528         : {- empty -}           { [] }
529         | formals_without_kinds         { $1 }
530
531 formals_without_kinds :: { [ExtFCode LocalReg] }
532         : formal_without_kind ','               { [$1] }
533         | formal_without_kind           { [$1] }
534         | formal_without_kind ',' formals_without_kinds { $1 : $3 }
535
536 formal_without_kind :: { ExtFCode LocalReg }
537         : type NAME             { newLocal defaultKind $1 $2 }
538         | STRING type NAME      {% do k <- parseGCKind $1;
539                                      return $ newLocal k $2 $3 }
540
541 maybe_frame :: { ExtFCode (Maybe UpdateFrame) }
542         : {- empty -}                   { return Nothing }
543         | 'jump' expr '(' exprs0 ')'    { do { target <- $2;
544                                                args <- sequence $4;
545                                                return $ Just (UpdateFrame target args) } }
546
547 maybe_gc_block :: { ExtFCode (Maybe BlockId) }
548         : {- empty -}                   { return Nothing }
549         | 'goto' NAME
550                 { do l <- lookupLabel $2; return (Just l) }
551
552 type    :: { MachRep }
553         : 'bits8'               { I8 }
554         | typenot8              { $1 }
555
556 typenot8 :: { MachRep }
557         : 'bits16'              { I16 }
558         | 'bits32'              { I32 }
559         | 'bits64'              { I64 }
560         | 'float32'             { F32 }
561         | 'float64'             { F64 }
562 {
563 section :: String -> Section
564 section "text"   = Text
565 section "data"   = Data
566 section "rodata" = ReadOnlyData
567 section "relrodata" = RelocatableReadOnlyData
568 section "bss"    = UninitialisedData
569 section s        = OtherSection s
570
571 mkString :: String -> CmmStatic
572 mkString s = CmmString (map (fromIntegral.ord) s)
573
574 -- mkMachOp infers the type of the MachOp from the type of its first
575 -- argument.  We assume that this is correct: for MachOps that don't have
576 -- symmetrical args (e.g. shift ops), the first arg determines the type of
577 -- the op.
578 mkMachOp :: (MachRep -> MachOp) -> [ExtFCode CmmExpr] -> ExtFCode CmmExpr
579 mkMachOp fn args = do
580   arg_exprs <- sequence args
581   return (CmmMachOp (fn (cmmExprRep (head arg_exprs))) arg_exprs)
582
583 getLit :: CmmExpr -> CmmLit
584 getLit (CmmLit l) = l
585 getLit (CmmMachOp (MO_S_Neg _) [CmmLit (CmmInt i r)])  = CmmInt (negate i) r
586 getLit _ = panic "invalid literal" -- TODO messy failure
587
588 nameToMachOp :: FastString -> P (MachRep -> MachOp)
589 nameToMachOp name = 
590   case lookupUFM machOps name of
591         Nothing -> fail ("unknown primitive " ++ unpackFS name)
592         Just m  -> return m
593
594 exprOp :: FastString -> [ExtFCode CmmExpr] -> P (ExtFCode CmmExpr)
595 exprOp name args_code =
596   case lookupUFM exprMacros name of
597      Just f  -> return $ do
598         args <- sequence args_code
599         return (f args)
600      Nothing -> do
601         mo <- nameToMachOp name
602         return $ mkMachOp mo args_code
603
604 exprMacros :: UniqFM ([CmmExpr] -> CmmExpr)
605 exprMacros = listToUFM [
606   ( fsLit "ENTRY_CODE",   \ [x] -> entryCode x ),
607   ( fsLit "INFO_PTR",     \ [x] -> closureInfoPtr x ),
608   ( fsLit "STD_INFO",     \ [x] -> infoTable x ),
609   ( fsLit "FUN_INFO",     \ [x] -> funInfoTable x ),
610   ( fsLit "GET_ENTRY",    \ [x] -> entryCode (closureInfoPtr x) ),
611   ( fsLit "GET_STD_INFO", \ [x] -> infoTable (closureInfoPtr x) ),
612   ( fsLit "GET_FUN_INFO", \ [x] -> funInfoTable (closureInfoPtr x) ),
613   ( fsLit "INFO_TYPE",    \ [x] -> infoTableClosureType x ),
614   ( fsLit "INFO_PTRS",    \ [x] -> infoTablePtrs x ),
615   ( fsLit "INFO_NPTRS",   \ [x] -> infoTableNonPtrs x )
616   ]
617
618 -- we understand a subset of C-- primitives:
619 machOps = listToUFM $
620         map (\(x, y) -> (mkFastString x, y)) [
621         ( "add",        MO_Add ),
622         ( "sub",        MO_Sub ),
623         ( "eq",         MO_Eq ),
624         ( "ne",         MO_Ne ),
625         ( "mul",        MO_Mul ),
626         ( "neg",        MO_S_Neg ),
627         ( "quot",       MO_S_Quot ),
628         ( "rem",        MO_S_Rem ),
629         ( "divu",       MO_U_Quot ),
630         ( "modu",       MO_U_Rem ),
631
632         ( "ge",         MO_S_Ge ),
633         ( "le",         MO_S_Le ),
634         ( "gt",         MO_S_Gt ),
635         ( "lt",         MO_S_Lt ),
636
637         ( "geu",        MO_U_Ge ),
638         ( "leu",        MO_U_Le ),
639         ( "gtu",        MO_U_Gt ),
640         ( "ltu",        MO_U_Lt ),
641
642         ( "flt",        MO_S_Lt ),
643         ( "fle",        MO_S_Le ),
644         ( "feq",        MO_Eq ),
645         ( "fne",        MO_Ne ),
646         ( "fgt",        MO_S_Gt ),
647         ( "fge",        MO_S_Ge ),
648         ( "fneg",       MO_S_Neg ),
649
650         ( "and",        MO_And ),
651         ( "or",         MO_Or ),
652         ( "xor",        MO_Xor ),
653         ( "com",        MO_Not ),
654         ( "shl",        MO_Shl ),
655         ( "shrl",       MO_U_Shr ),
656         ( "shra",       MO_S_Shr ),
657
658         ( "lobits8",  flip MO_U_Conv I8  ),
659         ( "lobits16", flip MO_U_Conv I16 ),
660         ( "lobits32", flip MO_U_Conv I32 ),
661         ( "lobits64", flip MO_U_Conv I64 ),
662         ( "sx16",     flip MO_S_Conv I16 ),
663         ( "sx32",     flip MO_S_Conv I32 ),
664         ( "sx64",     flip MO_S_Conv I64 ),
665         ( "zx16",     flip MO_U_Conv I16 ),
666         ( "zx32",     flip MO_U_Conv I32 ),
667         ( "zx64",     flip MO_U_Conv I64 ),
668         ( "f2f32",    flip MO_S_Conv F32 ),  -- TODO; rounding mode
669         ( "f2f64",    flip MO_S_Conv F64 ),  -- TODO; rounding mode
670         ( "f2i8",     flip MO_S_Conv I8 ),
671         ( "f2i16",    flip MO_S_Conv I16 ),
672         ( "f2i32",    flip MO_S_Conv I32 ),
673         ( "f2i64",    flip MO_S_Conv I64 ),
674         ( "i2f32",    flip MO_S_Conv F32 ),
675         ( "i2f64",    flip MO_S_Conv F64 )
676         ]
677
678 callishMachOps = listToUFM $
679         map (\(x, y) -> (mkFastString x, y)) [
680         ( "write_barrier", MO_WriteBarrier )
681         -- ToDo: the rest, maybe
682     ]
683
684 parseSafety :: String -> P CmmSafety
685 parseSafety "safe"   = return (CmmSafe NoC_SRT)
686 parseSafety "unsafe" = return CmmUnsafe
687 parseSafety str      = fail ("unrecognised safety: " ++ str)
688
689 parseCmmKind :: String -> P CmmKind
690 parseCmmKind "ptr"    = return PtrHint
691 parseCmmKind "signed" = return SignedHint
692 parseCmmKind "float"  = return FloatHint
693 parseCmmKind str      = fail ("unrecognised hint: " ++ str)
694
695 parseGCKind :: String -> P GCKind
696 parseGCKind "ptr"    = return GCKindPtr
697 parseGCKind str      = fail ("unrecognized kin: " ++ str)
698
699 defaultKind :: GCKind
700 defaultKind = GCKindNonPtr
701
702 -- labels are always pointers, so we might as well infer the hint
703 inferCmmKind :: CmmExpr -> CmmKind
704 inferCmmKind (CmmLit (CmmLabel _)) = PtrHint
705 inferCmmKind (CmmReg (CmmGlobal g)) | isPtrGlobalReg g = PtrHint
706 inferCmmKind _ = NoHint
707
708 isPtrGlobalReg Sp               = True
709 isPtrGlobalReg SpLim            = True
710 isPtrGlobalReg Hp               = True
711 isPtrGlobalReg HpLim            = True
712 isPtrGlobalReg CurrentTSO       = True
713 isPtrGlobalReg CurrentNursery   = True
714 isPtrGlobalReg _                = False
715
716 happyError :: P a
717 happyError = srcParseFail
718
719 -- -----------------------------------------------------------------------------
720 -- Statement-level macros
721
722 stmtMacro :: FastString -> [ExtFCode CmmExpr] -> P ExtCode
723 stmtMacro fun args_code = do
724   case lookupUFM stmtMacros fun of
725     Nothing -> fail ("unknown macro: " ++ unpackFS fun)
726     Just fcode -> return $ do
727         args <- sequence args_code
728         code (fcode args)
729
730 stmtMacros :: UniqFM ([CmmExpr] -> Code)
731 stmtMacros = listToUFM [
732   ( fsLit "CCS_ALLOC",             \[words,ccs]  -> profAlloc words ccs ),
733   ( fsLit "CLOSE_NURSERY",         \[]  -> emitCloseNursery ),
734   ( fsLit "ENTER_CCS_PAP_CL",     \[e] -> enterCostCentrePAP e ),
735   ( fsLit "ENTER_CCS_THUNK",      \[e] -> enterCostCentreThunk e ),
736   ( fsLit "HP_CHK_GEN",           \[words,liveness,reentry] -> 
737                                       hpChkGen words liveness reentry ),
738   ( fsLit "HP_CHK_NP_ASSIGN_SP0", \[e,f] -> hpChkNodePointsAssignSp0 e f ),
739   ( fsLit "LOAD_THREAD_STATE",    \[] -> emitLoadThreadState ),
740   ( fsLit "LDV_ENTER",            \[e] -> ldvEnter e ),
741   ( fsLit "LDV_RECORD_CREATE",    \[e] -> ldvRecordCreate e ),
742   ( fsLit "OPEN_NURSERY",          \[]  -> emitOpenNursery ),
743   ( fsLit "PUSH_UPD_FRAME",        \[sp,e] -> emitPushUpdateFrame sp e ),
744   ( fsLit "SAVE_THREAD_STATE",    \[] -> emitSaveThreadState ),
745   ( fsLit "SET_HDR",               \[ptr,info,ccs] -> 
746                                         emitSetDynHdr ptr info ccs ),
747   ( fsLit "STK_CHK_GEN",          \[words,liveness,reentry] -> 
748                                       stkChkGen words liveness reentry ),
749   ( fsLit "STK_CHK_NP",    \[e] -> stkChkNodePoints e ),
750   ( fsLit "TICK_ALLOC_PRIM",       \[hdr,goods,slop] -> 
751                                         tickyAllocPrim hdr goods slop ),
752   ( fsLit "TICK_ALLOC_PAP",       \[goods,slop] -> 
753                                         tickyAllocPAP goods slop ),
754   ( fsLit "TICK_ALLOC_UP_THK",    \[goods,slop] -> 
755                                         tickyAllocThunk goods slop ),
756   ( fsLit "UPD_BH_UPDATABLE",       \[] -> emitBlackHoleCode False ),
757   ( fsLit "UPD_BH_SINGLE_ENTRY",    \[] -> emitBlackHoleCode True ),
758
759   ( fsLit "RET_P",      \[a] ->       emitRetUT [(PtrArg,a)]),
760   ( fsLit "RET_N",      \[a] ->       emitRetUT [(NonPtrArg,a)]),
761   ( fsLit "RET_PP",     \[a,b] ->     emitRetUT [(PtrArg,a),(PtrArg,b)]),
762   ( fsLit "RET_NN",     \[a,b] ->     emitRetUT [(NonPtrArg,a),(NonPtrArg,b)]),
763   ( fsLit "RET_NP",     \[a,b] ->     emitRetUT [(NonPtrArg,a),(PtrArg,b)]),
764   ( fsLit "RET_PPP",    \[a,b,c] ->   emitRetUT [(PtrArg,a),(PtrArg,b),(PtrArg,c)]),
765   ( fsLit "RET_NPP",    \[a,b,c] ->   emitRetUT [(NonPtrArg,a),(PtrArg,b),(PtrArg,c)]),
766   ( fsLit "RET_NNP",    \[a,b,c] ->   emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(PtrArg,c)]),
767   ( fsLit "RET_NNN",  \[a,b,c] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(NonPtrArg,c)]),
768   ( fsLit "RET_NNNP",   \[a,b,c,d] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(NonPtrArg,c),(PtrArg,d)]),
769   ( fsLit "RET_NPNP",   \[a,b,c,d] -> emitRetUT [(NonPtrArg,a),(PtrArg,b),(NonPtrArg,c),(PtrArg,d)])
770
771  ]
772
773 -- -----------------------------------------------------------------------------
774 -- Our extended FCode monad.
775
776 -- We add a mapping from names to CmmExpr, to support local variable names in
777 -- the concrete C-- code.  The unique supply of the underlying FCode monad
778 -- is used to grab a new unique for each local variable.
779
780 -- In C--, a local variable can be declared anywhere within a proc,
781 -- and it scopes from the beginning of the proc to the end.  Hence, we have
782 -- to collect declarations as we parse the proc, and feed the environment
783 -- back in circularly (to avoid a two-pass algorithm).
784
785 data Named = Var CmmExpr | Label BlockId
786 type Decls = [(FastString,Named)]
787 type Env   = UniqFM Named
788
789 newtype ExtFCode a = EC { unEC :: Env -> Decls -> FCode (Decls, a) }
790
791 type ExtCode = ExtFCode ()
792
793 returnExtFC a = EC $ \e s -> return (s, a)
794 thenExtFC (EC m) k = EC $ \e s -> do (s',r) <- m e s; unEC (k r) e s'
795
796 instance Monad ExtFCode where
797   (>>=) = thenExtFC
798   return = returnExtFC
799
800 -- This function takes the variable decarations and imports and makes 
801 -- an environment, which is looped back into the computation.  In this
802 -- way, we can have embedded declarations that scope over the whole
803 -- procedure, and imports that scope over the entire module.
804 -- Discards the local declaration contained within decl'
805 loopDecls :: ExtFCode a -> ExtFCode a
806 loopDecls (EC fcode) =
807       EC $ \e globalDecls -> do
808         (decls', a) <- fixC (\ ~(decls,a) -> fcode (addListToUFM e (decls ++ globalDecls)) globalDecls)
809         return (globalDecls, a)
810
811 getEnv :: ExtFCode Env
812 getEnv = EC $ \e s -> return (s, e)
813
814 addVarDecl :: FastString -> CmmExpr -> ExtCode
815 addVarDecl var expr = EC $ \e s -> return ((var, Var expr):s, ())
816
817 addLabel :: FastString -> BlockId -> ExtCode
818 addLabel name block_id = EC $ \e s -> return ((name, Label block_id):s, ())
819
820 newLocal :: GCKind -> MachRep -> FastString -> ExtFCode LocalReg
821 newLocal kind ty name = do
822    u <- code newUnique
823    let reg = LocalReg u ty kind
824    addVarDecl name (CmmReg (CmmLocal reg))
825    return reg
826
827 -- Creates a foreign label in the import. CLabel's labelDynamic
828 -- classifies these labels as dynamic, hence the code generator emits the
829 -- PIC code for them.
830 newImport :: FastString -> ExtFCode ()
831 newImport name
832    = addVarDecl name (CmmLit (CmmLabel (mkForeignLabel name Nothing True)))
833
834 newLabel :: FastString -> ExtFCode BlockId
835 newLabel name = do
836    u <- code newUnique
837    addLabel name (BlockId u)
838    return (BlockId u)
839
840 lookupLabel :: FastString -> ExtFCode BlockId
841 lookupLabel name = do
842   env <- getEnv
843   return $ 
844      case lookupUFM env name of
845         Just (Label l) -> l
846         _other -> BlockId (newTagUnique (getUnique name) 'L')
847
848 -- Unknown names are treated as if they had been 'import'ed.
849 -- This saves us a lot of bother in the RTS sources, at the expense of
850 -- deferring some errors to link time.
851 lookupName :: FastString -> ExtFCode CmmExpr
852 lookupName name = do
853   env <- getEnv
854   return $ 
855      case lookupUFM env name of
856         Just (Var e) -> e
857         _other -> CmmLit (CmmLabel (mkRtsCodeLabelFS name))
858
859 -- Lifting FCode computations into the ExtFCode monad:
860 code :: FCode a -> ExtFCode a
861 code fc = EC $ \e s -> do r <- fc; return (s, r)
862
863 code2 :: (FCode (Decls,b) -> FCode ((Decls,b),c))
864          -> ExtFCode b -> ExtFCode c
865 code2 f (EC ec) = EC $ \e s -> do ((s',b),c) <- f (ec e s); return (s',c)
866
867 nopEC = code nopC
868 stmtEC stmt = code (stmtC stmt)
869 stmtsEC stmts = code (stmtsC stmts)
870 getCgStmtsEC = code2 getCgStmts'
871 getCgStmtsEC' = code2 (\m -> getCgStmts' m >>= f)
872   where f ((decl, b), c) = return ((decl, b), (b, c))
873
874 forkLabelledCodeEC ec = do
875   stmts <- getCgStmtsEC ec
876   code (forkCgStmts stmts)
877
878
879 profilingInfo desc_str ty_str = do
880   lit1 <- if opt_SccProfilingOn 
881                    then code $ mkStringCLit desc_str
882                    else return (mkIntCLit 0)
883   lit2 <- if opt_SccProfilingOn 
884                    then code $ mkStringCLit ty_str
885                    else return (mkIntCLit 0)
886   return (ProfilingInfo lit1 lit2)
887
888
889 staticClosure :: FastString -> FastString -> [CmmLit] -> ExtCode
890 staticClosure cl_label info payload
891   = code $ emitDataLits (mkRtsDataLabelFS cl_label) lits
892   where  lits = mkStaticClosure (mkRtsInfoLabelFS info) dontCareCCS payload [] [] []
893
894 foreignCall
895         :: String
896         -> [ExtFCode CmmFormal]
897         -> ExtFCode CmmExpr
898         -> [ExtFCode CmmActual]
899         -> Maybe [GlobalReg]
900         -> CmmSafety
901         -> CmmReturnInfo
902         -> P ExtCode
903 foreignCall conv_string results_code expr_code args_code vols safety ret
904   = do  convention <- case conv_string of
905           "C" -> return CCallConv
906           "stdcall" -> return StdCallConv
907           "C--" -> return CmmCallConv
908           _ -> fail ("unknown calling convention: " ++ conv_string)
909         return $ do
910           results <- sequence results_code
911           expr <- expr_code
912           args <- sequence args_code
913           --code (stmtC (CmmCall (CmmCallee expr convention) results args safety))
914           case convention of
915             -- Temporary hack so at least some functions are CmmSafe
916             CmmCallConv -> code (stmtC (CmmCall (CmmCallee expr convention) results args safety ret))
917             _ ->
918               let expr' = adjCallTarget convention expr args in
919               case safety of
920               CmmUnsafe ->
921                 code (emitForeignCall' PlayRisky results 
922                    (CmmCallee expr' convention) args vols NoC_SRT ret)
923               CmmSafe srt ->
924                 code (emitForeignCall' (PlaySafe unused) results 
925                    (CmmCallee expr' convention) args vols NoC_SRT ret) where
926                 unused = panic "not used by emitForeignCall'"
927
928 adjCallTarget :: CCallConv -> CmmExpr -> [CmmKinded CmmExpr] -> CmmExpr
929 #ifdef mingw32_TARGET_OS
930 -- On Windows, we have to add the '@N' suffix to the label when making
931 -- a call with the stdcall calling convention.
932 adjCallTarget StdCallConv (CmmLit (CmmLabel lbl)) args
933   = CmmLit (CmmLabel (addLabelSize lbl (sum (map size args))))
934   where size (CmmKinded e _) = max wORD_SIZE (machRepByteWidth (cmmExprRep e))
935                  -- c.f. CgForeignCall.emitForeignCall
936 #endif
937 adjCallTarget _ expr _
938   = expr
939
940 primCall
941         :: [ExtFCode CmmFormal]
942         -> FastString
943         -> [ExtFCode CmmActual]
944         -> Maybe [GlobalReg]
945         -> CmmSafety
946         -> P ExtCode
947 primCall results_code name args_code vols safety
948   = case lookupUFM callishMachOps name of
949         Nothing -> fail ("unknown primitive " ++ unpackFS name)
950         Just p  -> return $ do
951                 results <- sequence results_code
952                 args <- sequence args_code
953                 case safety of
954                   CmmUnsafe ->
955                     code (emitForeignCall' PlayRisky results
956                       (CmmPrim p) args vols NoC_SRT CmmMayReturn)
957                   CmmSafe srt ->
958                     code (emitForeignCall' (PlaySafe unused) results 
959                       (CmmPrim p) args vols NoC_SRT CmmMayReturn) where
960                     unused = panic "not used by emitForeignCall'"
961
962 doStore :: MachRep -> ExtFCode CmmExpr  -> ExtFCode CmmExpr -> ExtCode
963 doStore rep addr_code val_code
964   = do addr <- addr_code
965        val <- val_code
966         -- if the specified store type does not match the type of the expr
967         -- on the rhs, then we insert a coercion that will cause the type
968         -- mismatch to be flagged by cmm-lint.  If we don't do this, then
969         -- the store will happen at the wrong type, and the error will not
970         -- be noticed.
971        let coerce_val 
972                 | cmmExprRep val /= rep = CmmMachOp (MO_U_Conv rep rep) [val]
973                 | otherwise             = val
974        stmtEC (CmmStore addr coerce_val)
975
976 -- Return an unboxed tuple.
977 emitRetUT :: [(CgRep,CmmExpr)] -> Code
978 emitRetUT args = do
979   tickyUnboxedTupleReturn (length args)  -- TICK
980   (sp, stmts) <- pushUnboxedTuple 0 args
981   emitStmts stmts
982   when (sp /= 0) $ stmtC (CmmAssign spReg (cmmRegOffW spReg (-sp)))
983   stmtC (CmmJump (entryCode (CmmLoad (cmmRegOffW spReg sp) wordRep)) [])
984   -- TODO (when using CPS): emitStmt (CmmReturn (map snd args))
985
986 -- -----------------------------------------------------------------------------
987 -- If-then-else and boolean expressions
988
989 data BoolExpr
990   = BoolExpr `BoolAnd` BoolExpr
991   | BoolExpr `BoolOr`  BoolExpr
992   | BoolNot BoolExpr
993   | BoolTest CmmExpr
994
995 -- ToDo: smart constructors which simplify the boolean expression.
996
997 ifThenElse cond then_part else_part = do
998      then_id <- code newLabelC
999      join_id <- code newLabelC
1000      c <- cond
1001      emitCond c then_id
1002      else_part
1003      stmtEC (CmmBranch join_id)
1004      code (labelC then_id)
1005      then_part
1006      -- fall through to join
1007      code (labelC join_id)
1008
1009 -- 'emitCond cond true_id'  emits code to test whether the cond is true,
1010 -- branching to true_id if so, and falling through otherwise.
1011 emitCond (BoolTest e) then_id = do
1012   stmtEC (CmmCondBranch e then_id)
1013 emitCond (BoolNot (BoolTest (CmmMachOp op args))) then_id
1014   | Just op' <- maybeInvertComparison op
1015   = emitCond (BoolTest (CmmMachOp op' args)) then_id
1016 emitCond (BoolNot e) then_id = do
1017   else_id <- code newLabelC
1018   emitCond e else_id
1019   stmtEC (CmmBranch then_id)
1020   code (labelC else_id)
1021 emitCond (e1 `BoolOr` e2) then_id = do
1022   emitCond e1 then_id
1023   emitCond e2 then_id
1024 emitCond (e1 `BoolAnd` e2) then_id = do
1025         -- we'd like to invert one of the conditionals here to avoid an
1026         -- extra branch instruction, but we can't use maybeInvertComparison
1027         -- here because we can't look too closely at the expression since
1028         -- we're in a loop.
1029   and_id <- code newLabelC
1030   else_id <- code newLabelC
1031   emitCond e1 and_id
1032   stmtEC (CmmBranch else_id)
1033   code (labelC and_id)
1034   emitCond e2 then_id
1035   code (labelC else_id)
1036
1037
1038 -- -----------------------------------------------------------------------------
1039 -- Table jumps
1040
1041 -- We use a simplified form of C-- switch statements for now.  A
1042 -- switch statement always compiles to a table jump.  Each arm can
1043 -- specify a list of values (not ranges), and there can be a single
1044 -- default branch.  The range of the table is given either by the
1045 -- optional range on the switch (eg. switch [0..7] {...}), or by
1046 -- the minimum/maximum values from the branches.
1047
1048 doSwitch :: Maybe (Int,Int) -> ExtFCode CmmExpr -> [([Int],ExtCode)]
1049          -> Maybe ExtCode -> ExtCode
1050 doSwitch mb_range scrut arms deflt
1051    = do 
1052         -- Compile code for the default branch
1053         dflt_entry <- 
1054                 case deflt of
1055                   Nothing -> return Nothing
1056                   Just e  -> do b <- forkLabelledCodeEC e; return (Just b)
1057
1058         -- Compile each case branch
1059         table_entries <- mapM emitArm arms
1060
1061         -- Construct the table
1062         let
1063             all_entries = concat table_entries
1064             ixs = map fst all_entries
1065             (min,max) 
1066                 | Just (l,u) <- mb_range = (l,u)
1067                 | otherwise              = (minimum ixs, maximum ixs)
1068
1069             entries = elems (accumArray (\_ a -> Just a) dflt_entry (min,max)
1070                                 all_entries)
1071         expr <- scrut
1072         -- ToDo: check for out of range and jump to default if necessary
1073         stmtEC (CmmSwitch expr entries)
1074    where
1075         emitArm :: ([Int],ExtCode) -> ExtFCode [(Int,BlockId)]
1076         emitArm (ints,code) = do
1077            blockid <- forkLabelledCodeEC code
1078            return [ (i,blockid) | i <- ints ]
1079
1080
1081 -- -----------------------------------------------------------------------------
1082 -- Putting it all together
1083
1084 -- The initial environment: we define some constants that the compiler
1085 -- knows about here.
1086 initEnv :: Env
1087 initEnv = listToUFM [
1088   ( fsLit "SIZEOF_StgHeader", 
1089     Var (CmmLit (CmmInt (fromIntegral (fixedHdrSize * wORD_SIZE)) wordRep) )),
1090   ( fsLit "SIZEOF_StgInfoTable",
1091     Var (CmmLit (CmmInt (fromIntegral stdInfoTableSizeB) wordRep) ))
1092   ]
1093
1094 parseCmmFile :: DynFlags -> FilePath -> IO (Maybe Cmm)
1095 parseCmmFile dflags filename = do
1096   showPass dflags "ParseCmm"
1097   buf <- hGetStringBuffer filename
1098   let
1099         init_loc = mkSrcLoc (mkFastString filename) 1 0
1100         init_state = (mkPState buf init_loc dflags) { lex_state = [0] }
1101                 -- reset the lex_state: the Lexer monad leaves some stuff
1102                 -- in there we don't want.
1103   case unP cmmParse init_state of
1104     PFailed span err -> do printError span err; return Nothing
1105     POk pst code -> do
1106         cmm <- initC dflags no_module (getCmm (unEC code initEnv [] >> return ()))
1107         let ms = getMessages pst
1108         printErrorsAndWarnings dflags ms
1109         when (errorsFound dflags ms) $ exitWith (ExitFailure 1)
1110         dumpIfSet_dyn dflags Opt_D_dump_cmm "Cmm" (ppr cmm)
1111         return (Just cmm)
1112   where
1113         no_module = panic "parseCmmFile: no module"
1114 }