PageRenderTime 72ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/cmm/CmmParse.y

https://github.com/crdueck/ghc
Happy | 1294 lines | 1100 code | 194 blank | 0 comment | 0 complexity | 8ab21bb5e8a8a8946252914ea53e6c30 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. -----------------------------------------------------------------------------
  2. --
  3. -- (c) The University of Glasgow, 2004-2012
  4. --
  5. -- Parser for concrete Cmm.
  6. --
  7. -----------------------------------------------------------------------------
  8. {- -----------------------------------------------------------------------------
  9. Note [Syntax of .cmm files]
  10. NOTE: You are very much on your own in .cmm. There is very little
  11. error checking at all:
  12. * Type errors are detected by the (optional) -dcmm-lint pass, if you
  13. don't turn this on then a type error will likely result in a panic
  14. from the native code generator.
  15. * Passing the wrong number of arguments or arguments of the wrong
  16. type is not detected.
  17. There are two ways to write .cmm code:
  18. (1) High-level Cmm code delegates the stack handling to GHC, and
  19. never explicitly mentions Sp or registers.
  20. (2) Low-level Cmm manages the stack itself, and must know about
  21. calling conventions.
  22. Whether you want high-level or low-level Cmm is indicated by the
  23. presence of an argument list on a procedure. For example:
  24. foo ( gcptr a, bits32 b )
  25. {
  26. // this is high-level cmm code
  27. if (b > 0) {
  28. // we can make tail calls passing arguments:
  29. jump stg_ap_0_fast(a);
  30. }
  31. push (stg_upd_frame_info, a) {
  32. // stack frames can be explicitly pushed
  33. (x,y) = call wibble(a,b,3,4);
  34. // calls pass arguments and return results using the native
  35. // Haskell calling convention. The code generator will automatically
  36. // construct a stack frame and an info table for the continuation.
  37. return (x,y);
  38. // we can return multiple values from the current proc
  39. }
  40. }
  41. bar
  42. {
  43. // this is low-level cmm code, indicated by the fact that we did not
  44. // put an argument list on bar.
  45. x = R1; // the calling convention is explicit: better be careful
  46. // that this works on all platforms!
  47. jump %ENTRY_CODE(Sp(0))
  48. }
  49. Here is a list of rules for high-level and low-level code. If you
  50. break the rules, you get a panic (for using a high-level construct in
  51. a low-level proc), or wrong code (when using low-level code in a
  52. high-level proc). This stuff isn't checked! (TODO!)
  53. High-level only:
  54. - tail-calls with arguments, e.g.
  55. jump stg_fun (arg1, arg2);
  56. - function calls:
  57. (ret1,ret2) = call stg_fun (arg1, arg2);
  58. This makes a call with the NativeNodeCall convention, and the
  59. values are returned to the following code using the NativeReturn
  60. convention.
  61. - returning:
  62. return (ret1, ret2)
  63. These use the NativeReturn convention to return zero or more
  64. results to the caller.
  65. - pushing stack frames:
  66. push (info_ptr, field1, ..., fieldN) { ... statements ... }
  67. Low-level only:
  68. - References to Sp, R1-R8, F1-F4 etc.
  69. NB. foreign calls may clobber the argument registers R1-R8, F1-F4
  70. etc., so ensure they are saved into variables around foreign
  71. calls.
  72. - SAVE_THREAD_STATE() and LOAD_THREAD_STATE(), which modify Sp
  73. directly.
  74. Both high-level and low-level code can use a raw tail-call:
  75. jump stg_fun [R1,R2]
  76. This always transfers control to a low-level Cmm function, but the
  77. call can be made from high-level code. Arguments must be passed
  78. explicitly in R/F/D/L registers.
  79. NB. you *must* specify the list of GlobalRegs that are passed via a
  80. jump, otherwise the register allocator will assume that all the
  81. GlobalRegs are dead at the jump.
  82. A stack frame is written like this:
  83. INFO_TABLE_RET ( label, FRAME_TYPE, info_ptr, field1, ..., fieldN )
  84. return ( arg1, ..., argM )
  85. {
  86. ... code ...
  87. }
  88. where field1 ... fieldN are the fields of the stack frame (with types)
  89. arg1...argN are the values returned to the stack frame (with types).
  90. The return values are assumed to be passed according to the
  91. NativeReturn convention.
  92. On entry to the code, the stack frame looks like:
  93. |----------|
  94. | fieldN |
  95. | ... |
  96. | field1 |
  97. |----------|
  98. | info_ptr |
  99. |----------|
  100. | argN |
  101. | ... | <- Sp
  102. and some of the args may be in registers.
  103. We prepend the code by a copyIn of the args, and assign all the stack
  104. frame fields to their formals. The initial "arg offset" for stack
  105. layout purposes consists of the whole stack frame plus any args that
  106. might be on the stack.
  107. A tail-call may pass a stack frame to the callee using the following
  108. syntax:
  109. jump f (info_ptr, field1,..,fieldN) (arg1,..,argN)
  110. where info_ptr and field1..fieldN describe the stack frame, and
  111. arg1..argN are the arguments passed to f using the NativeNodeCall
  112. convention.
  113. ----------------------------------------------------------------------------- -}
  114. {
  115. {-# LANGUAGE BangPatterns #-} -- required for versions of Happy before 1.18.6
  116. {-# OPTIONS -Wwarn -w #-}
  117. -- The above warning supression flag is a temporary kludge.
  118. -- While working on this module you are encouraged to remove it and fix
  119. -- any warnings in the module. See
  120. -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
  121. -- for details
  122. module CmmParse ( parseCmmFile ) where
  123. import StgCmmExtCode
  124. import CmmCallConv
  125. import StgCmmProf
  126. import StgCmmHeap
  127. import StgCmmMonad hiding ( getCode, getCodeR, emitLabel, emit, emitStore
  128. , emitAssign, emitOutOfLine, withUpdFrameOff
  129. , getUpdFrameOff )
  130. import qualified StgCmmMonad as F
  131. import StgCmmUtils
  132. import StgCmmForeign
  133. import StgCmmExpr
  134. import StgCmmClosure
  135. import StgCmmLayout hiding (ArgRep(..))
  136. import StgCmmTicky
  137. import StgCmmBind ( emitBlackHoleCode, emitUpdateFrame )
  138. import MkGraph
  139. import Cmm
  140. import CmmUtils
  141. import CmmInfo
  142. import BlockId
  143. import CmmLex
  144. import CLabel
  145. import SMRep
  146. import Lexer
  147. import CostCentre
  148. import ForeignCall
  149. import Module
  150. import Platform
  151. import Literal
  152. import Unique
  153. import UniqFM
  154. import SrcLoc
  155. import DynFlags
  156. import StaticFlags
  157. import ErrUtils
  158. import StringBuffer
  159. import FastString
  160. import Panic
  161. import Constants
  162. import Outputable
  163. import BasicTypes
  164. import Bag ( emptyBag, unitBag )
  165. import Var
  166. import Control.Monad
  167. import Data.Array
  168. import Data.Char ( ord )
  169. import System.Exit
  170. import Data.Maybe
  171. #include "HsVersions.h"
  172. }
  173. %expect 0
  174. %token
  175. ':' { L _ (CmmT_SpecChar ':') }
  176. ';' { L _ (CmmT_SpecChar ';') }
  177. '{' { L _ (CmmT_SpecChar '{') }
  178. '}' { L _ (CmmT_SpecChar '}') }
  179. '[' { L _ (CmmT_SpecChar '[') }
  180. ']' { L _ (CmmT_SpecChar ']') }
  181. '(' { L _ (CmmT_SpecChar '(') }
  182. ')' { L _ (CmmT_SpecChar ')') }
  183. '=' { L _ (CmmT_SpecChar '=') }
  184. '`' { L _ (CmmT_SpecChar '`') }
  185. '~' { L _ (CmmT_SpecChar '~') }
  186. '/' { L _ (CmmT_SpecChar '/') }
  187. '*' { L _ (CmmT_SpecChar '*') }
  188. '%' { L _ (CmmT_SpecChar '%') }
  189. '-' { L _ (CmmT_SpecChar '-') }
  190. '+' { L _ (CmmT_SpecChar '+') }
  191. '&' { L _ (CmmT_SpecChar '&') }
  192. '^' { L _ (CmmT_SpecChar '^') }
  193. '|' { L _ (CmmT_SpecChar '|') }
  194. '>' { L _ (CmmT_SpecChar '>') }
  195. '<' { L _ (CmmT_SpecChar '<') }
  196. ',' { L _ (CmmT_SpecChar ',') }
  197. '!' { L _ (CmmT_SpecChar '!') }
  198. '..' { L _ (CmmT_DotDot) }
  199. '::' { L _ (CmmT_DoubleColon) }
  200. '>>' { L _ (CmmT_Shr) }
  201. '<<' { L _ (CmmT_Shl) }
  202. '>=' { L _ (CmmT_Ge) }
  203. '<=' { L _ (CmmT_Le) }
  204. '==' { L _ (CmmT_Eq) }
  205. '!=' { L _ (CmmT_Ne) }
  206. '&&' { L _ (CmmT_BoolAnd) }
  207. '||' { L _ (CmmT_BoolOr) }
  208. 'CLOSURE' { L _ (CmmT_CLOSURE) }
  209. 'INFO_TABLE' { L _ (CmmT_INFO_TABLE) }
  210. 'INFO_TABLE_RET'{ L _ (CmmT_INFO_TABLE_RET) }
  211. 'INFO_TABLE_FUN'{ L _ (CmmT_INFO_TABLE_FUN) }
  212. 'INFO_TABLE_CONSTR'{ L _ (CmmT_INFO_TABLE_CONSTR) }
  213. 'INFO_TABLE_SELECTOR'{ L _ (CmmT_INFO_TABLE_SELECTOR) }
  214. 'else' { L _ (CmmT_else) }
  215. 'export' { L _ (CmmT_export) }
  216. 'section' { L _ (CmmT_section) }
  217. 'align' { L _ (CmmT_align) }
  218. 'goto' { L _ (CmmT_goto) }
  219. 'if' { L _ (CmmT_if) }
  220. 'call' { L _ (CmmT_call) }
  221. 'jump' { L _ (CmmT_jump) }
  222. 'foreign' { L _ (CmmT_foreign) }
  223. 'never' { L _ (CmmT_never) }
  224. 'prim' { L _ (CmmT_prim) }
  225. 'return' { L _ (CmmT_return) }
  226. 'returns' { L _ (CmmT_returns) }
  227. 'import' { L _ (CmmT_import) }
  228. 'switch' { L _ (CmmT_switch) }
  229. 'case' { L _ (CmmT_case) }
  230. 'default' { L _ (CmmT_default) }
  231. 'push' { L _ (CmmT_push) }
  232. 'bits8' { L _ (CmmT_bits8) }
  233. 'bits16' { L _ (CmmT_bits16) }
  234. 'bits32' { L _ (CmmT_bits32) }
  235. 'bits64' { L _ (CmmT_bits64) }
  236. 'bits128' { L _ (CmmT_bits128) }
  237. 'float32' { L _ (CmmT_float32) }
  238. 'float64' { L _ (CmmT_float64) }
  239. 'gcptr' { L _ (CmmT_gcptr) }
  240. GLOBALREG { L _ (CmmT_GlobalReg $$) }
  241. NAME { L _ (CmmT_Name $$) }
  242. STRING { L _ (CmmT_String $$) }
  243. INT { L _ (CmmT_Int $$) }
  244. FLOAT { L _ (CmmT_Float $$) }
  245. %monad { P } { >>= } { return }
  246. %lexer { cmmlex } { L _ CmmT_EOF }
  247. %name cmmParse cmm
  248. %tokentype { Located CmmToken }
  249. -- C-- operator precedences, taken from the C-- spec
  250. %right '||' -- non-std extension, called %disjoin in C--
  251. %right '&&' -- non-std extension, called %conjoin in C--
  252. %right '!'
  253. %nonassoc '>=' '>' '<=' '<' '!=' '=='
  254. %left '|'
  255. %left '^'
  256. %left '&'
  257. %left '>>' '<<'
  258. %left '-' '+'
  259. %left '/' '*' '%'
  260. %right '~'
  261. %%
  262. cmm :: { CmmParse () }
  263. : {- empty -} { return () }
  264. | cmmtop cmm { do $1; $2 }
  265. cmmtop :: { CmmParse () }
  266. : cmmproc { $1 }
  267. | cmmdata { $1 }
  268. | decl { $1 }
  269. | 'CLOSURE' '(' NAME ',' NAME lits ')' ';'
  270. {% withThisPackage $ \pkg ->
  271. do lits <- sequence $6;
  272. staticClosure pkg $3 $5 (map getLit lits) }
  273. -- The only static closures in the RTS are dummy closures like
  274. -- stg_END_TSO_QUEUE_closure and stg_dummy_ret. We don't need
  275. -- to provide the full generality of static closures here.
  276. -- In particular:
  277. -- * CCS can always be CCS_DONT_CARE
  278. -- * closure is always extern
  279. -- * payload is always empty
  280. -- * we can derive closure and info table labels from a single NAME
  281. cmmdata :: { CmmParse () }
  282. : 'section' STRING '{' data_label statics '}'
  283. { do lbl <- $4;
  284. ss <- sequence $5;
  285. code (emitDecl (CmmData (section $2) (Statics lbl $ concat ss))) }
  286. data_label :: { CmmParse CLabel }
  287. : NAME ':'
  288. {% withThisPackage $ \pkg ->
  289. return (mkCmmDataLabel pkg $1) }
  290. statics :: { [CmmParse [CmmStatic]] }
  291. : {- empty -} { [] }
  292. | static statics { $1 : $2 }
  293. -- Strings aren't used much in the RTS HC code, so it doesn't seem
  294. -- worth allowing inline strings. C-- doesn't allow them anyway.
  295. static :: { CmmParse [CmmStatic] }
  296. : type expr ';' { do e <- $2;
  297. return [CmmStaticLit (getLit e)] }
  298. | type ';' { return [CmmUninitialised
  299. (widthInBytes (typeWidth $1))] }
  300. | 'bits8' '[' ']' STRING ';' { return [mkString $4] }
  301. | 'bits8' '[' INT ']' ';' { return [CmmUninitialised
  302. (fromIntegral $3)] }
  303. | typenot8 '[' INT ']' ';' { return [CmmUninitialised
  304. (widthInBytes (typeWidth $1) *
  305. fromIntegral $3)] }
  306. | 'CLOSURE' '(' NAME lits ')'
  307. { do { lits <- sequence $4
  308. ; dflags <- getDynFlags
  309. ; return $ map CmmStaticLit $
  310. mkStaticClosure dflags (mkForeignLabel $3 Nothing ForeignLabelInExternalPackage IsData)
  311. -- mkForeignLabel because these are only used
  312. -- for CHARLIKE and INTLIKE closures in the RTS.
  313. dontCareCCS (map getLit lits) [] [] [] } }
  314. -- arrays of closures required for the CHARLIKE & INTLIKE arrays
  315. lits :: { [CmmParse CmmExpr] }
  316. : {- empty -} { [] }
  317. | ',' expr lits { $2 : $3 }
  318. cmmproc :: { CmmParse () }
  319. : info maybe_conv maybe_formals maybe_body
  320. { do ((entry_ret_label, info, stk_formals, formals), agraph) <-
  321. getCodeR $ loopDecls $ do {
  322. (entry_ret_label, info, stk_formals) <- $1;
  323. formals <- sequence (fromMaybe [] $3);
  324. $4;
  325. return (entry_ret_label, info, stk_formals, formals) }
  326. let do_layout = isJust $3
  327. code (emitProcWithStackFrame $2 info
  328. entry_ret_label stk_formals formals agraph
  329. do_layout ) }
  330. maybe_conv :: { Convention }
  331. : {- empty -} { NativeNodeCall }
  332. | 'return' { NativeReturn }
  333. maybe_body :: { CmmParse () }
  334. : ';' { return () }
  335. | '{' body '}' { $2 }
  336. info :: { CmmParse (CLabel, Maybe CmmInfoTable, [LocalReg]) }
  337. : NAME
  338. {% withThisPackage $ \pkg ->
  339. do newFunctionName $1 pkg
  340. return (mkCmmCodeLabel pkg $1, Nothing, []) }
  341. | 'INFO_TABLE' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ')'
  342. -- ptrs, nptrs, closure type, description, type
  343. {% withThisPackage $ \pkg ->
  344. do dflags <- getDynFlags
  345. let prof = profilingInfo dflags $11 $13
  346. rep = mkRTSRep (fromIntegral $9) $
  347. mkHeapRep dflags False (fromIntegral $5)
  348. (fromIntegral $7) Thunk
  349. -- not really Thunk, but that makes the info table
  350. -- we want.
  351. return (mkCmmEntryLabel pkg $3,
  352. Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
  353. , cit_rep = rep
  354. , cit_prof = prof, cit_srt = NoC_SRT },
  355. []) }
  356. | 'INFO_TABLE_FUN' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ',' INT ')'
  357. -- ptrs, nptrs, closure type, description, type, fun type
  358. {% withThisPackage $ \pkg ->
  359. do dflags <- getDynFlags
  360. let prof = profilingInfo dflags $11 $13
  361. ty = Fun 0 (ArgSpec (fromIntegral $15))
  362. -- Arity zero, arg_type $15
  363. rep = mkRTSRep (fromIntegral $9) $
  364. mkHeapRep dflags False (fromIntegral $5)
  365. (fromIntegral $7) ty
  366. return (mkCmmEntryLabel pkg $3,
  367. Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
  368. , cit_rep = rep
  369. , cit_prof = prof, cit_srt = NoC_SRT },
  370. []) }
  371. -- we leave most of the fields zero here. This is only used
  372. -- to generate the BCO info table in the RTS at the moment.
  373. | 'INFO_TABLE_CONSTR' '(' NAME ',' INT ',' INT ',' INT ',' INT ',' STRING ',' STRING ')'
  374. -- ptrs, nptrs, tag, closure type, description, type
  375. {% withThisPackage $ \pkg ->
  376. do dflags <- getDynFlags
  377. let prof = profilingInfo dflags $13 $15
  378. ty = Constr (fromIntegral $9) -- Tag
  379. (stringToWord8s $13)
  380. rep = mkRTSRep (fromIntegral $11) $
  381. mkHeapRep dflags False (fromIntegral $5)
  382. (fromIntegral $7) ty
  383. return (mkCmmEntryLabel pkg $3,
  384. Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
  385. , cit_rep = rep
  386. , cit_prof = prof, cit_srt = NoC_SRT },
  387. []) }
  388. -- If profiling is on, this string gets duplicated,
  389. -- but that's the way the old code did it we can fix it some other time.
  390. | 'INFO_TABLE_SELECTOR' '(' NAME ',' INT ',' INT ',' STRING ',' STRING ')'
  391. -- selector, closure type, description, type
  392. {% withThisPackage $ \pkg ->
  393. do dflags <- getDynFlags
  394. let prof = profilingInfo dflags $9 $11
  395. ty = ThunkSelector (fromIntegral $5)
  396. rep = mkRTSRep (fromIntegral $7) $
  397. mkHeapRep dflags False 0 0 ty
  398. return (mkCmmEntryLabel pkg $3,
  399. Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
  400. , cit_rep = rep
  401. , cit_prof = prof, cit_srt = NoC_SRT },
  402. []) }
  403. | 'INFO_TABLE_RET' '(' NAME ',' INT ')'
  404. -- closure type (no live regs)
  405. {% withThisPackage $ \pkg ->
  406. do let prof = NoProfilingInfo
  407. rep = mkRTSRep (fromIntegral $5) $ mkStackRep []
  408. return (mkCmmRetLabel pkg $3,
  409. Just $ CmmInfoTable { cit_lbl = mkCmmRetInfoLabel pkg $3
  410. , cit_rep = rep
  411. , cit_prof = prof, cit_srt = NoC_SRT },
  412. []) }
  413. | 'INFO_TABLE_RET' '(' NAME ',' INT ',' formals0 ')'
  414. -- closure type, live regs
  415. {% withThisPackage $ \pkg ->
  416. do dflags <- getDynFlags
  417. live <- sequence $7
  418. let prof = NoProfilingInfo
  419. -- drop one for the info pointer
  420. bitmap = mkLiveness dflags (map Just (drop 1 live))
  421. rep = mkRTSRep (fromIntegral $5) $ mkStackRep bitmap
  422. return (mkCmmRetLabel pkg $3,
  423. Just $ CmmInfoTable { cit_lbl = mkCmmRetInfoLabel pkg $3
  424. , cit_rep = rep
  425. , cit_prof = prof, cit_srt = NoC_SRT },
  426. live) }
  427. body :: { CmmParse () }
  428. : {- empty -} { return () }
  429. | decl body { do $1; $2 }
  430. | stmt body { do $1; $2 }
  431. decl :: { CmmParse () }
  432. : type names ';' { mapM_ (newLocal $1) $2 }
  433. | 'import' importNames ';' { mapM_ newImport $2 }
  434. | 'export' names ';' { return () } -- ignore exports
  435. -- an imported function name, with optional packageId
  436. importNames
  437. :: { [(FastString, CLabel)] }
  438. : importName { [$1] }
  439. | importName ',' importNames { $1 : $3 }
  440. importName
  441. :: { (FastString, CLabel) }
  442. -- A label imported without an explicit packageId.
  443. -- These are taken to come frome some foreign, unnamed package.
  444. : NAME
  445. { ($1, mkForeignLabel $1 Nothing ForeignLabelInExternalPackage IsFunction) }
  446. -- A label imported with an explicit packageId.
  447. | STRING NAME
  448. { ($2, mkCmmCodeLabel (fsToPackageId (mkFastString $1)) $2) }
  449. names :: { [FastString] }
  450. : NAME { [$1] }
  451. | NAME ',' names { $1 : $3 }
  452. stmt :: { CmmParse () }
  453. : ';' { return () }
  454. | NAME ':'
  455. { do l <- newLabel $1; emitLabel l }
  456. | lreg '=' expr ';'
  457. { do reg <- $1; e <- $3; emitAssign reg e }
  458. | type '[' expr ']' '=' expr ';'
  459. { doStore $1 $3 $6 }
  460. -- Gah! We really want to say "foreign_results" but that causes
  461. -- a shift/reduce conflict with assignment. We either
  462. -- we expand out the no-result and single result cases or
  463. -- we tweak the syntax to avoid the conflict. The later
  464. -- option is taken here because the other way would require
  465. -- multiple levels of expanding and get unwieldy.
  466. | foreign_results 'foreign' STRING foreignLabel '(' cmm_hint_exprs0 ')' safety opt_never_returns ';'
  467. {% foreignCall $3 $1 $4 $6 $8 $9 }
  468. | foreign_results 'prim' '%' NAME '(' exprs0 ')' ';'
  469. {% primCall $1 $4 $6 }
  470. -- stmt-level macros, stealing syntax from ordinary C-- function calls.
  471. -- Perhaps we ought to use the %%-form?
  472. | NAME '(' exprs0 ')' ';'
  473. {% stmtMacro $1 $3 }
  474. | 'switch' maybe_range expr '{' arms default '}'
  475. { do as <- sequence $5; doSwitch $2 $3 as $6 }
  476. | 'goto' NAME ';'
  477. { do l <- lookupLabel $2; emit (mkBranch l) }
  478. | 'return' '(' exprs0 ')' ';'
  479. { doReturn $3 }
  480. | 'jump' expr vols ';'
  481. { doRawJump $2 $3 }
  482. | 'jump' expr '(' exprs0 ')' ';'
  483. { doJumpWithStack $2 [] $4 }
  484. | 'jump' expr '(' exprs0 ')' '(' exprs0 ')' ';'
  485. { doJumpWithStack $2 $4 $7 }
  486. | 'call' expr '(' exprs0 ')' ';'
  487. { doCall $2 [] $4 }
  488. | '(' formals ')' '=' 'call' expr '(' exprs0 ')' ';'
  489. { doCall $6 $2 $8 }
  490. | 'if' bool_expr 'goto' NAME
  491. { do l <- lookupLabel $4; cmmRawIf $2 l }
  492. | 'if' bool_expr '{' body '}' else
  493. { cmmIfThenElse $2 $4 $6 }
  494. | 'push' '(' exprs0 ')' maybe_body
  495. { pushStackFrame $3 $5 }
  496. foreignLabel :: { CmmParse CmmExpr }
  497. : NAME { return (CmmLit (CmmLabel (mkForeignLabel $1 Nothing ForeignLabelInThisPackage IsFunction))) }
  498. opt_never_returns :: { CmmReturnInfo }
  499. : { CmmMayReturn }
  500. | 'never' 'returns' { CmmNeverReturns }
  501. bool_expr :: { CmmParse BoolExpr }
  502. : bool_op { $1 }
  503. | expr { do e <- $1; return (BoolTest e) }
  504. bool_op :: { CmmParse BoolExpr }
  505. : bool_expr '&&' bool_expr { do e1 <- $1; e2 <- $3;
  506. return (BoolAnd e1 e2) }
  507. | bool_expr '||' bool_expr { do e1 <- $1; e2 <- $3;
  508. return (BoolOr e1 e2) }
  509. | '!' bool_expr { do e <- $2; return (BoolNot e) }
  510. | '(' bool_op ')' { $2 }
  511. safety :: { Safety }
  512. : {- empty -} { PlayRisky }
  513. | STRING {% parseSafety $1 }
  514. vols :: { [GlobalReg] }
  515. : '[' ']' { [] }
  516. | '[' '*' ']' {% do df <- getDynFlags
  517. ; return (realArgRegsCover df) }
  518. -- All of them. See comment attached
  519. -- to realArgRegsCover
  520. | '[' globals ']' { $2 }
  521. globals :: { [GlobalReg] }
  522. : GLOBALREG { [$1] }
  523. | GLOBALREG ',' globals { $1 : $3 }
  524. maybe_range :: { Maybe (Int,Int) }
  525. : '[' INT '..' INT ']' { Just (fromIntegral $2, fromIntegral $4) }
  526. | {- empty -} { Nothing }
  527. arms :: { [CmmParse ([Int],Either BlockId (CmmParse ()))] }
  528. : {- empty -} { [] }
  529. | arm arms { $1 : $2 }
  530. arm :: { CmmParse ([Int],Either BlockId (CmmParse ())) }
  531. : 'case' ints ':' arm_body { do b <- $4; return ($2, b) }
  532. arm_body :: { CmmParse (Either BlockId (CmmParse ())) }
  533. : '{' body '}' { return (Right $2) }
  534. | 'goto' NAME ';' { do l <- lookupLabel $2; return (Left l) }
  535. ints :: { [Int] }
  536. : INT { [ fromIntegral $1 ] }
  537. | INT ',' ints { fromIntegral $1 : $3 }
  538. default :: { Maybe (CmmParse ()) }
  539. : 'default' ':' '{' body '}' { Just $4 }
  540. -- taking a few liberties with the C-- syntax here; C-- doesn't have
  541. -- 'default' branches
  542. | {- empty -} { Nothing }
  543. -- Note: OldCmm doesn't support a first class 'else' statement, though
  544. -- CmmNode does.
  545. else :: { CmmParse () }
  546. : {- empty -} { return () }
  547. | 'else' '{' body '}' { $3 }
  548. -- we have to write this out longhand so that Happy's precedence rules
  549. -- can kick in.
  550. expr :: { CmmParse CmmExpr }
  551. : expr '/' expr { mkMachOp MO_U_Quot [$1,$3] }
  552. | expr '*' expr { mkMachOp MO_Mul [$1,$3] }
  553. | expr '%' expr { mkMachOp MO_U_Rem [$1,$3] }
  554. | expr '-' expr { mkMachOp MO_Sub [$1,$3] }
  555. | expr '+' expr { mkMachOp MO_Add [$1,$3] }
  556. | expr '>>' expr { mkMachOp MO_U_Shr [$1,$3] }
  557. | expr '<<' expr { mkMachOp MO_Shl [$1,$3] }
  558. | expr '&' expr { mkMachOp MO_And [$1,$3] }
  559. | expr '^' expr { mkMachOp MO_Xor [$1,$3] }
  560. | expr '|' expr { mkMachOp MO_Or [$1,$3] }
  561. | expr '>=' expr { mkMachOp MO_U_Ge [$1,$3] }
  562. | expr '>' expr { mkMachOp MO_U_Gt [$1,$3] }
  563. | expr '<=' expr { mkMachOp MO_U_Le [$1,$3] }
  564. | expr '<' expr { mkMachOp MO_U_Lt [$1,$3] }
  565. | expr '!=' expr { mkMachOp MO_Ne [$1,$3] }
  566. | expr '==' expr { mkMachOp MO_Eq [$1,$3] }
  567. | '~' expr { mkMachOp MO_Not [$2] }
  568. | '-' expr { mkMachOp MO_S_Neg [$2] }
  569. | expr0 '`' NAME '`' expr0 {% do { mo <- nameToMachOp $3 ;
  570. return (mkMachOp mo [$1,$5]) } }
  571. | expr0 { $1 }
  572. expr0 :: { CmmParse CmmExpr }
  573. : INT maybe_ty { return (CmmLit (CmmInt $1 (typeWidth $2))) }
  574. | FLOAT maybe_ty { return (CmmLit (CmmFloat $1 (typeWidth $2))) }
  575. | STRING { do s <- code (newStringCLit $1);
  576. return (CmmLit s) }
  577. | reg { $1 }
  578. | type '[' expr ']' { do e <- $3; return (CmmLoad e $1) }
  579. | '%' NAME '(' exprs0 ')' {% exprOp $2 $4 }
  580. | '(' expr ')' { $2 }
  581. -- leaving out the type of a literal gives you the native word size in C--
  582. maybe_ty :: { CmmType }
  583. : {- empty -} {% do dflags <- getDynFlags; return $ bWord dflags }
  584. | '::' type { $2 }
  585. cmm_hint_exprs0 :: { [CmmParse (CmmExpr, ForeignHint)] }
  586. : {- empty -} { [] }
  587. | cmm_hint_exprs { $1 }
  588. cmm_hint_exprs :: { [CmmParse (CmmExpr, ForeignHint)] }
  589. : cmm_hint_expr { [$1] }
  590. | cmm_hint_expr ',' cmm_hint_exprs { $1 : $3 }
  591. cmm_hint_expr :: { CmmParse (CmmExpr, ForeignHint) }
  592. : expr { do e <- $1;
  593. return (e, inferCmmHint e) }
  594. | expr STRING {% do h <- parseCmmHint $2;
  595. return $ do
  596. e <- $1; return (e, h) }
  597. exprs0 :: { [CmmParse CmmExpr] }
  598. : {- empty -} { [] }
  599. | exprs { $1 }
  600. exprs :: { [CmmParse CmmExpr] }
  601. : expr { [ $1 ] }
  602. | expr ',' exprs { $1 : $3 }
  603. reg :: { CmmParse CmmExpr }
  604. : NAME { lookupName $1 }
  605. | GLOBALREG { return (CmmReg (CmmGlobal $1)) }
  606. foreign_results :: { [CmmParse (LocalReg, ForeignHint)] }
  607. : {- empty -} { [] }
  608. | '(' foreign_formals ')' '=' { $2 }
  609. foreign_formals :: { [CmmParse (LocalReg, ForeignHint)] }
  610. : foreign_formal { [$1] }
  611. | foreign_formal ',' { [$1] }
  612. | foreign_formal ',' foreign_formals { $1 : $3 }
  613. foreign_formal :: { CmmParse (LocalReg, ForeignHint) }
  614. : local_lreg { do e <- $1; return (e, (inferCmmHint (CmmReg (CmmLocal e)))) }
  615. | STRING local_lreg {% do h <- parseCmmHint $1;
  616. return $ do
  617. e <- $2; return (e,h) }
  618. local_lreg :: { CmmParse LocalReg }
  619. : NAME { do e <- lookupName $1;
  620. return $
  621. case e of
  622. CmmReg (CmmLocal r) -> r
  623. other -> pprPanic "CmmParse:" (ftext $1 <> text " not a local register") }
  624. lreg :: { CmmParse CmmReg }
  625. : NAME { do e <- lookupName $1;
  626. return $
  627. case e of
  628. CmmReg r -> r
  629. other -> pprPanic "CmmParse:" (ftext $1 <> text " not a register") }
  630. | GLOBALREG { return (CmmGlobal $1) }
  631. maybe_formals :: { Maybe [CmmParse LocalReg] }
  632. : {- empty -} { Nothing }
  633. | '(' formals0 ')' { Just $2 }
  634. formals0 :: { [CmmParse LocalReg] }
  635. : {- empty -} { [] }
  636. | formals { $1 }
  637. formals :: { [CmmParse LocalReg] }
  638. : formal ',' { [$1] }
  639. | formal { [$1] }
  640. | formal ',' formals { $1 : $3 }
  641. formal :: { CmmParse LocalReg }
  642. : type NAME { newLocal $1 $2 }
  643. type :: { CmmType }
  644. : 'bits8' { b8 }
  645. | typenot8 { $1 }
  646. typenot8 :: { CmmType }
  647. : 'bits16' { b16 }
  648. | 'bits32' { b32 }
  649. | 'bits64' { b64 }
  650. | 'bits128' { b128 }
  651. | 'float32' { f32 }
  652. | 'float64' { f64 }
  653. | 'gcptr' {% do dflags <- getDynFlags; return $ gcWord dflags }
  654. {
  655. section :: String -> Section
  656. section "text" = Text
  657. section "data" = Data
  658. section "rodata" = ReadOnlyData
  659. section "relrodata" = RelocatableReadOnlyData
  660. section "bss" = UninitialisedData
  661. section s = OtherSection s
  662. mkString :: String -> CmmStatic
  663. mkString s = CmmString (map (fromIntegral.ord) s)
  664. -- |
  665. -- Given an info table, decide what the entry convention for the proc
  666. -- is. That is, for an INFO_TABLE_RET we want the return convention,
  667. -- otherwise it is a NativeNodeCall.
  668. --
  669. infoConv :: Maybe CmmInfoTable -> Convention
  670. infoConv Nothing = NativeNodeCall
  671. infoConv (Just info)
  672. | isStackRep (cit_rep info) = NativeReturn
  673. | otherwise = NativeNodeCall
  674. -- mkMachOp infers the type of the MachOp from the type of its first
  675. -- argument. We assume that this is correct: for MachOps that don't have
  676. -- symmetrical args (e.g. shift ops), the first arg determines the type of
  677. -- the op.
  678. mkMachOp :: (Width -> MachOp) -> [CmmParse CmmExpr] -> CmmParse CmmExpr
  679. mkMachOp fn args = do
  680. dflags <- getDynFlags
  681. arg_exprs <- sequence args
  682. return (CmmMachOp (fn (typeWidth (cmmExprType dflags (head arg_exprs)))) arg_exprs)
  683. getLit :: CmmExpr -> CmmLit
  684. getLit (CmmLit l) = l
  685. getLit (CmmMachOp (MO_S_Neg _) [CmmLit (CmmInt i r)]) = CmmInt (negate i) r
  686. getLit _ = panic "invalid literal" -- TODO messy failure
  687. nameToMachOp :: FastString -> P (Width -> MachOp)
  688. nameToMachOp name =
  689. case lookupUFM machOps name of
  690. Nothing -> fail ("unknown primitive " ++ unpackFS name)
  691. Just m -> return m
  692. exprOp :: FastString -> [CmmParse CmmExpr] -> P (CmmParse CmmExpr)
  693. exprOp name args_code = do
  694. dflags <- getDynFlags
  695. case lookupUFM (exprMacros dflags) name of
  696. Just f -> return $ do
  697. args <- sequence args_code
  698. return (f args)
  699. Nothing -> do
  700. mo <- nameToMachOp name
  701. return $ mkMachOp mo args_code
  702. exprMacros :: DynFlags -> UniqFM ([CmmExpr] -> CmmExpr)
  703. exprMacros dflags = listToUFM [
  704. ( fsLit "ENTRY_CODE", \ [x] -> entryCode dflags x ),
  705. ( fsLit "INFO_PTR", \ [x] -> closureInfoPtr dflags x ),
  706. ( fsLit "STD_INFO", \ [x] -> infoTable dflags x ),
  707. ( fsLit "FUN_INFO", \ [x] -> funInfoTable dflags x ),
  708. ( fsLit "GET_ENTRY", \ [x] -> entryCode dflags (closureInfoPtr dflags x) ),
  709. ( fsLit "GET_STD_INFO", \ [x] -> infoTable dflags (closureInfoPtr dflags x) ),
  710. ( fsLit "GET_FUN_INFO", \ [x] -> funInfoTable dflags (closureInfoPtr dflags x) ),
  711. ( fsLit "INFO_TYPE", \ [x] -> infoTableClosureType dflags x ),
  712. ( fsLit "INFO_PTRS", \ [x] -> infoTablePtrs dflags x ),
  713. ( fsLit "INFO_NPTRS", \ [x] -> infoTableNonPtrs dflags x )
  714. ]
  715. -- we understand a subset of C-- primitives:
  716. machOps = listToUFM $
  717. map (\(x, y) -> (mkFastString x, y)) [
  718. ( "add", MO_Add ),
  719. ( "sub", MO_Sub ),
  720. ( "eq", MO_Eq ),
  721. ( "ne", MO_Ne ),
  722. ( "mul", MO_Mul ),
  723. ( "neg", MO_S_Neg ),
  724. ( "quot", MO_S_Quot ),
  725. ( "rem", MO_S_Rem ),
  726. ( "divu", MO_U_Quot ),
  727. ( "modu", MO_U_Rem ),
  728. ( "ge", MO_S_Ge ),
  729. ( "le", MO_S_Le ),
  730. ( "gt", MO_S_Gt ),
  731. ( "lt", MO_S_Lt ),
  732. ( "geu", MO_U_Ge ),
  733. ( "leu", MO_U_Le ),
  734. ( "gtu", MO_U_Gt ),
  735. ( "ltu", MO_U_Lt ),
  736. ( "and", MO_And ),
  737. ( "or", MO_Or ),
  738. ( "xor", MO_Xor ),
  739. ( "com", MO_Not ),
  740. ( "shl", MO_Shl ),
  741. ( "shrl", MO_U_Shr ),
  742. ( "shra", MO_S_Shr ),
  743. ( "fadd", MO_F_Add ),
  744. ( "fsub", MO_F_Sub ),
  745. ( "fneg", MO_F_Neg ),
  746. ( "fmul", MO_F_Mul ),
  747. ( "fquot", MO_F_Quot ),
  748. ( "feq", MO_F_Eq ),
  749. ( "fne", MO_F_Ne ),
  750. ( "fge", MO_F_Ge ),
  751. ( "fle", MO_F_Le ),
  752. ( "fgt", MO_F_Gt ),
  753. ( "flt", MO_F_Lt ),
  754. ( "lobits8", flip MO_UU_Conv W8 ),
  755. ( "lobits16", flip MO_UU_Conv W16 ),
  756. ( "lobits32", flip MO_UU_Conv W32 ),
  757. ( "lobits64", flip MO_UU_Conv W64 ),
  758. ( "zx16", flip MO_UU_Conv W16 ),
  759. ( "zx32", flip MO_UU_Conv W32 ),
  760. ( "zx64", flip MO_UU_Conv W64 ),
  761. ( "sx16", flip MO_SS_Conv W16 ),
  762. ( "sx32", flip MO_SS_Conv W32 ),
  763. ( "sx64", flip MO_SS_Conv W64 ),
  764. ( "f2f32", flip MO_FF_Conv W32 ), -- TODO; rounding mode
  765. ( "f2f64", flip MO_FF_Conv W64 ), -- TODO; rounding mode
  766. ( "f2i8", flip MO_FS_Conv W8 ),
  767. ( "f2i16", flip MO_FS_Conv W16 ),
  768. ( "f2i32", flip MO_FS_Conv W32 ),
  769. ( "f2i64", flip MO_FS_Conv W64 ),
  770. ( "i2f32", flip MO_SF_Conv W32 ),
  771. ( "i2f64", flip MO_SF_Conv W64 )
  772. ]
  773. callishMachOps = listToUFM $
  774. map (\(x, y) -> (mkFastString x, y)) [
  775. ( "write_barrier", MO_WriteBarrier ),
  776. ( "memcpy", MO_Memcpy ),
  777. ( "memset", MO_Memset ),
  778. ( "memmove", MO_Memmove )
  779. -- ToDo: the rest, maybe
  780. ]
  781. parseSafety :: String -> P Safety
  782. parseSafety "safe" = return PlaySafe
  783. parseSafety "unsafe" = return PlayRisky
  784. parseSafety "interruptible" = return PlayInterruptible
  785. parseSafety str = fail ("unrecognised safety: " ++ str)
  786. parseCmmHint :: String -> P ForeignHint
  787. parseCmmHint "ptr" = return AddrHint
  788. parseCmmHint "signed" = return SignedHint
  789. parseCmmHint str = fail ("unrecognised hint: " ++ str)
  790. -- labels are always pointers, so we might as well infer the hint
  791. inferCmmHint :: CmmExpr -> ForeignHint
  792. inferCmmHint (CmmLit (CmmLabel _)) = AddrHint
  793. inferCmmHint (CmmReg (CmmGlobal g)) | isPtrGlobalReg g = AddrHint
  794. inferCmmHint _ = NoHint
  795. isPtrGlobalReg Sp = True
  796. isPtrGlobalReg SpLim = True
  797. isPtrGlobalReg Hp = True
  798. isPtrGlobalReg HpLim = True
  799. isPtrGlobalReg CCCS = True
  800. isPtrGlobalReg CurrentTSO = True
  801. isPtrGlobalReg CurrentNursery = True
  802. isPtrGlobalReg (VanillaReg _ VGcPtr) = True
  803. isPtrGlobalReg _ = False
  804. happyError :: P a
  805. happyError = srcParseFail
  806. -- -----------------------------------------------------------------------------
  807. -- Statement-level macros
  808. stmtMacro :: FastString -> [CmmParse CmmExpr] -> P (CmmParse ())
  809. stmtMacro fun args_code = do
  810. case lookupUFM stmtMacros fun of
  811. Nothing -> fail ("unknown macro: " ++ unpackFS fun)
  812. Just fcode -> return $ do
  813. args <- sequence args_code
  814. code (fcode args)
  815. stmtMacros :: UniqFM ([CmmExpr] -> FCode ())
  816. stmtMacros = listToUFM [
  817. ( fsLit "CCS_ALLOC", \[words,ccs] -> profAlloc words ccs ),
  818. ( fsLit "ENTER_CCS_THUNK", \[e] -> enterCostCentreThunk e ),
  819. ( fsLit "CLOSE_NURSERY", \[] -> emitCloseNursery ),
  820. ( fsLit "OPEN_NURSERY", \[] -> emitOpenNursery ),
  821. -- completely generic heap and stack checks, for use in high-level cmm.
  822. ( fsLit "HP_CHK_GEN", \[bytes] ->
  823. heapStackCheckGen Nothing (Just bytes) ),
  824. ( fsLit "STK_CHK_GEN", \[] ->
  825. heapStackCheckGen (Just (CmmLit CmmHighStackMark)) Nothing ),
  826. -- A stack check for a fixed amount of stack. Sounds a bit strange, but
  827. -- we use the stack for a bit of temporary storage in a couple of primops
  828. ( fsLit "STK_CHK_GEN_N", \[bytes] ->
  829. heapStackCheckGen (Just bytes) Nothing ),
  830. -- A stack check on entry to a thunk, where the argument is the thunk pointer.
  831. ( fsLit "STK_CHK_NP" , \[node] -> entryHeapCheck' False node 0 [] (return ())),
  832. ( fsLit "LOAD_THREAD_STATE", \[] -> emitLoadThreadState ),
  833. ( fsLit "SAVE_THREAD_STATE", \[] -> emitSaveThreadState ),
  834. ( fsLit "LDV_ENTER", \[e] -> ldvEnter e ),
  835. ( fsLit "LDV_RECORD_CREATE", \[e] -> ldvRecordCreate e ),
  836. ( fsLit "PUSH_UPD_FRAME", \[sp,e] -> emitPushUpdateFrame sp e ),
  837. ( fsLit "SET_HDR", \[ptr,info,ccs] ->
  838. emitSetDynHdr ptr info ccs ),
  839. ( fsLit "TICK_ALLOC_PRIM", \[hdr,goods,slop] ->
  840. tickyAllocPrim hdr goods slop ),
  841. ( fsLit "TICK_ALLOC_PAP", \[goods,slop] ->
  842. tickyAllocPAP goods slop ),
  843. ( fsLit "TICK_ALLOC_UP_THK", \[goods,slop] ->
  844. tickyAllocThunk goods slop ),
  845. ( fsLit "UPD_BH_UPDATABLE", \[reg] -> emitBlackHoleCode reg )
  846. ]
  847. emitPushUpdateFrame :: CmmExpr -> CmmExpr -> FCode ()
  848. emitPushUpdateFrame sp e = do
  849. dflags <- getDynFlags
  850. emitUpdateFrame dflags sp mkUpdInfoLabel e
  851. pushStackFrame :: [CmmParse CmmExpr] -> CmmParse () -> CmmParse ()
  852. pushStackFrame fields body = do
  853. dflags <- getDynFlags
  854. exprs <- sequence fields
  855. updfr_off <- getUpdFrameOff
  856. let (new_updfr_off, _, g) = copyOutOflow dflags NativeReturn Ret Old
  857. [] updfr_off exprs
  858. emit g
  859. withUpdFrameOff new_updfr_off body
  860. profilingInfo dflags desc_str ty_str
  861. = if not (gopt Opt_SccProfilingOn dflags)
  862. then NoProfilingInfo
  863. else ProfilingInfo (stringToWord8s desc_str)
  864. (stringToWord8s ty_str)
  865. staticClosure :: PackageId -> FastString -> FastString -> [CmmLit] -> CmmParse ()
  866. staticClosure pkg cl_label info payload
  867. = do dflags <- getDynFlags
  868. let lits = mkStaticClosure dflags (mkCmmInfoLabel pkg info) dontCareCCS payload [] [] []
  869. code $ emitDataLits (mkCmmDataLabel pkg cl_label) lits
  870. foreignCall
  871. :: String
  872. -> [CmmParse (LocalReg, ForeignHint)]
  873. -> CmmParse CmmExpr
  874. -> [CmmParse (CmmExpr, ForeignHint)]
  875. -> Safety
  876. -> CmmReturnInfo
  877. -> P (CmmParse ())
  878. foreignCall conv_string results_code expr_code args_code safety ret
  879. = do conv <- case conv_string of
  880. "C" -> return CCallConv
  881. "stdcall" -> return StdCallConv
  882. _ -> fail ("unknown calling convention: " ++ conv_string)
  883. return $ do
  884. dflags <- getDynFlags
  885. results <- sequence results_code
  886. expr <- expr_code
  887. args <- sequence args_code
  888. let
  889. expr' = adjCallTarget dflags conv expr args
  890. (arg_exprs, arg_hints) = unzip args
  891. (res_regs, res_hints) = unzip results
  892. fc = ForeignConvention conv arg_hints res_hints ret
  893. target = ForeignTarget expr' fc
  894. _ <- code $ emitForeignCall safety res_regs target arg_exprs
  895. return ()
  896. doReturn :: [CmmParse CmmExpr] -> CmmParse ()
  897. doReturn exprs_code = do
  898. dflags <- getDynFlags
  899. exprs <- sequence exprs_code
  900. updfr_off <- getUpdFrameOff
  901. emit (mkReturnSimple dflags exprs updfr_off)
  902. mkReturnSimple :: DynFlags -> [CmmActual] -> UpdFrameOffset -> CmmAGraph
  903. mkReturnSimple dflags actuals updfr_off =
  904. mkReturn dflags e actuals updfr_off
  905. where e = entryCode dflags (CmmLoad (CmmStackSlot Old updfr_off)
  906. (gcWord dflags))
  907. doRawJump :: CmmParse CmmExpr -> [GlobalReg] -> CmmParse ()
  908. doRawJump expr_code vols = do
  909. dflags <- getDynFlags
  910. expr <- expr_code
  911. updfr_off <- getUpdFrameOff
  912. emit (mkRawJump dflags expr updfr_off vols)
  913. doJumpWithStack :: CmmParse CmmExpr -> [CmmParse CmmExpr]
  914. -> [CmmParse CmmExpr] -> CmmParse ()
  915. doJumpWithStack expr_code stk_code args_code = do
  916. dflags <- getDynFlags
  917. expr <- expr_code
  918. stk_args <- sequence stk_code
  919. args <- sequence args_code
  920. updfr_off <- getUpdFrameOff
  921. emit (mkJumpExtra dflags NativeNodeCall expr args updfr_off stk_args)
  922. doCall :: CmmParse CmmExpr -> [CmmParse LocalReg] -> [CmmParse CmmExpr]
  923. -> CmmParse ()
  924. doCall expr_code res_code args_code = do
  925. dflags <- getDynFlags
  926. expr <- expr_code
  927. args <- sequence args_code
  928. ress <- sequence res_code
  929. updfr_off <- getUpdFrameOff
  930. c <- code $ mkCall expr (NativeNodeCall,NativeReturn) ress args updfr_off []
  931. emit c
  932. adjCallTarget :: DynFlags -> CCallConv -> CmmExpr -> [(CmmExpr, ForeignHint) ]
  933. -> CmmExpr
  934. -- On Windows, we have to add the '@N' suffix to the label when making
  935. -- a call with the stdcall calling convention.
  936. adjCallTarget dflags StdCallConv (CmmLit (CmmLabel lbl)) args
  937. | platformOS (targetPlatform dflags) == OSMinGW32
  938. = CmmLit (CmmLabel (addLabelSize lbl (sum (map size args))))
  939. where size (e, _) = max (wORD_SIZE dflags) (widthInBytes (typeWidth (cmmExprType dflags e)))
  940. -- c.f. CgForeignCall.emitForeignCall
  941. adjCallTarget _ _ expr _
  942. = expr
  943. primCall
  944. :: [CmmParse (CmmFormal, ForeignHint)]
  945. -> FastString
  946. -> [CmmParse CmmExpr]
  947. -> P (CmmParse ())
  948. primCall results_code name args_code
  949. = case lookupUFM callishMachOps name of
  950. Nothing -> fail ("unknown primitive " ++ unpackFS name)
  951. Just p -> return $ do
  952. results <- sequence results_code
  953. args <- sequence args_code
  954. code (emitPrimCall (map fst results) p args)
  955. doStore :: CmmType -> CmmParse CmmExpr -> CmmParse CmmExpr -> CmmParse ()
  956. doStore rep addr_code val_code
  957. = do dflags <- getDynFlags
  958. addr <- addr_code
  959. val <- val_code
  960. -- if the specified store type does not match the type of the expr
  961. -- on the rhs, then we insert a coercion that will cause the type
  962. -- mismatch to be flagged by cmm-lint. If we don't do this, then
  963. -- the store will happen at the wrong type, and the error will not
  964. -- be noticed.
  965. let val_width = typeWidth (cmmExprType dflags val)
  966. rep_width = typeWidth rep
  967. let coerce_val
  968. | val_width /= rep_width = CmmMachOp (MO_UU_Conv val_width rep_width) [val]
  969. | otherwise = val
  970. emitStore addr coerce_val
  971. -- -----------------------------------------------------------------------------
  972. -- If-then-else and boolean expressions
  973. data BoolExpr
  974. = BoolExpr `BoolAnd` BoolExpr
  975. | BoolExpr `BoolOr` BoolExpr
  976. | BoolNot BoolExpr
  977. | BoolTest CmmExpr
  978. -- ToDo: smart constructors which simplify the boolean expression.
  979. cmmIfThenElse cond then_part else_part = do
  980. then_id <- newBlockId
  981. join_id <- newBlockId
  982. c <- cond
  983. emitCond c then_id
  984. else_part
  985. emit (mkBranch join_id)
  986. emitLabel then_id
  987. then_part
  988. -- fall through to join
  989. emitLabel join_id
  990. cmmRawIf cond then_id = do
  991. c <- cond
  992. emitCond c then_id
  993. -- 'emitCond cond true_id' emits code to test whether the cond is true,
  994. -- branching to true_id if so, and falling through otherwise.
  995. emitCond (BoolTest e) then_id = do
  996. else_id <- newBlockId
  997. emit (mkCbranch e then_id else_id)
  998. emitLabel else_id
  999. emitCond (BoolNot (BoolTest (CmmMachOp op args))) then_id
  1000. | Just op' <- maybeInvertComparison op
  1001. = emitCond (BoolTest (CmmMachOp op' args)) then_id
  1002. emitCond (BoolNot e) then_id = do
  1003. else_id <- newBlockId
  1004. emitCond e else_id
  1005. emit (mkBranch then_id)
  1006. emitLabel else_id
  1007. emitCond (e1 `BoolOr` e2) then_id = do
  1008. emitCond e1 then_id
  1009. emitCond e2 then_id
  1010. emitCond (e1 `BoolAnd` e2) then_id = do
  1011. -- we'd like to invert one of the conditionals here to avoid an
  1012. -- extra branch instruction, but we can't use maybeInvertComparison
  1013. -- here because we can't look too closely at the expression since
  1014. -- we're in a loop.
  1015. and_id <- newBlockId
  1016. else_id <- newBlockId
  1017. emitCond e1 and_id
  1018. emit (mkBranch else_id)
  1019. emitLabel and_id
  1020. emitCond e2 then_id
  1021. emitLabel else_id
  1022. -- -----------------------------------------------------------------------------
  1023. -- Table jumps
  1024. -- We use a simplified form of C-- switch statements for now. A
  1025. -- switch statement always compiles to a table jump. Each arm can
  1026. -- specify a list of values (not ranges), and there can be a single
  1027. -- default branch. The range of the table is given either by the
  1028. -- optional range on the switch (eg. switch [0..7] {...}), or by
  1029. -- the minimum/maximum values from the branches.
  1030. doSwitch :: Maybe (Int,Int) -> CmmParse CmmExpr -> [([Int],Either BlockId (CmmParse ()))]
  1031. -> Maybe (CmmParse ()) -> CmmParse ()
  1032. doSwitch mb_range scrut arms deflt
  1033. = do
  1034. -- Compile code for the default branch
  1035. dflt_entry <-
  1036. case deflt of
  1037. Nothing -> return Nothing
  1038. Just e -> do b <- forkLabelledCode e; return (Just b)
  1039. -- Compile each case branch
  1040. table_entries <- mapM emitArm arms
  1041. -- Construct the table
  1042. let
  1043. all_entries = concat table_entries
  1044. ixs = map fst all_entries
  1045. (min,max)
  1046. | Just (l,u) <- mb_range = (l,u)
  1047. | otherwise = (minimum ixs, maximum ixs)
  1048. entries = elems (accumArray (\_ a -> Just a) dflt_entry (min,max)
  1049. all_entries)
  1050. expr <- scrut
  1051. -- ToDo: check for out of range and jump to default if necessary
  1052. emit (mkSwitch expr entries)
  1053. where
  1054. emitArm :: ([Int],Either BlockId (CmmParse ())) -> CmmParse [(Int,BlockId)]
  1055. emitArm (ints,Left blockid) = return [ (i,blockid) | i <- ints ]
  1056. emitArm (ints,Right code) = do
  1057. blockid <- forkLabelledCode code
  1058. return [ (i,blockid) | i <- ints ]
  1059. forkLabelledCode :: CmmParse () -> CmmParse BlockId
  1060. forkLabelledCode p = do
  1061. ag <- getCode p
  1062. l <- newBlockId
  1063. emitOutOfLine l ag
  1064. return l
  1065. -- -----------------------------------------------------------------------------
  1066. -- Putting it all together
  1067. -- The initial environment: we define some constants that the compiler
  1068. -- knows about here.
  1069. initEnv :: DynFlags -> Env
  1070. initEnv dflags = listToUFM [
  1071. ( fsLit "SIZEOF_StgHeader",
  1072. VarN (CmmLit (CmmInt (fromIntegral (fixedHdrSize dflags * wORD_SIZE dflags)) (wordWidth dflags)) )),
  1073. ( fsLit "SIZEOF_StgInfoTable",
  1074. VarN (CmmLit (CmmInt (fromIntegral (stdInfoTableSizeB dflags)) (wordWidth dflags)) ))
  1075. ]
  1076. parseCmmFile :: DynFlags -> FilePath -> IO (Messages, Maybe CmmGroup)
  1077. parseCmmFile dflags filename = do
  1078. showPass dflags "ParseCmm"
  1079. buf <- hGetStringBuffer filename
  1080. let
  1081. init_loc = mkRealSrcLoc (mkFastString filename) 1 1
  1082. init_state = (mkPState dflags buf init_loc) { lex_state = [0] }
  1083. -- reset the lex_state: the Lexer monad leaves some stuff
  1084. -- in there

Large files files are truncated, but you can click here to view the full file