... | ... | @@ -4,7 +4,7 @@ TODO This page is possibly outdated. Update to the latest information. |
|
|
|
|
|
>
|
|
|
>
|
|
|
> See also [Code Generator](commentary/compiler/code-gen) and [compiler/cmm/cmm-notes](/trac/ghc/browser/ghc/compiler/cmm/cmm-notes).
|
|
|
> See also [Code Generator](commentary/compiler/code-gen) and [compiler/cmm/cmm-notes](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/cmm-notes).
|
|
|
>
|
|
|
>
|
|
|
|
... | ... | @@ -14,7 +14,7 @@ TODO This page is possibly outdated. Update to the latest information. |
|
|
This page was written with more detail than usual since you may need to know how to work with Cmm as a programming language. Cmm is the basis for the future of GHC, Native Code Generation, and if you are interested in hacking Cmm at least this page might help reduce your learning curve. As a finer detail, if you read the [Compiler pipeline](commentary/compiler/hsc-main) wiki page or glanced at the diagram there you may have noticed that whether you are working backward from an `intermediate C` (Haskell-C "HC", `.hc`) file or an Assembler file you get to Cmm before you get to the STG language, the Simplifier or anything else. In other words, for really low-level debugging you may have an easier time if you know what Cmm is about. Cmm also has opportunities for implementing small and easy hacks, such as little optimisations and implementing new Cmm Primitive Operations.
|
|
|
|
|
|
|
|
|
A portion of the [RTS](commentary/rts) is written in Cmm: [rts/Apply.cmm](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/rts/Apply.cmm), [rts/Exception.cmm](/trac/ghc/browser/ghc/rts/Exception.cmm), [rts/HeapStackCheck.cmm](/trac/ghc/browser/ghc/rts/HeapStackCheck.cmm), [rts/PrimOps.cmm](/trac/ghc/browser/ghc/rts/PrimOps.cmm), [rts/StgMiscClosures.cmm](/trac/ghc/browser/ghc/rts/StgMiscClosures.cmm), [rts/StgStartup.cmm](/trac/ghc/browser/ghc/rts/StgStartup.cmm) and [rts/StgStdThunks.cmm](/trac/ghc/browser/ghc/rts/StgStdThunks.cmm). (For notes related to `PrimOps.cmm` see the [PrimOps](commentary/prim-ops) page; for much of the rest, see the [HaskellExecution](commentary/rts/haskell-execution) page.) Cmm is optimised before GHC outputs either HC or Assembler. The C compiler (from HC, pretty printed by [compiler/cmm/PprC.hs](/trac/ghc/browser/ghc/compiler/cmm/PprC.hs)) and the [Native Code Generator](commentary/compiler/backends/ncg) (NCG) [Backends](commentary/compiler/backends) are closely tied to data representations and transformations performed in Cmm. In GHC, Cmm roughly performs a function similar to the intermediate [Register Transfer Language (RTL)](http://gcc.gnu.org/onlinedocs/gccint/RTL.html) in GCC.
|
|
|
A portion of the [RTS](commentary/rts) is written in Cmm: [rts/Apply.cmm](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/rts/Apply.cmm), [rts/Exception.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/rts/Exception.cmm), [rts/HeapStackCheck.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/rts/HeapStackCheck.cmm), [rts/PrimOps.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/rts/PrimOps.cmm), [rts/StgMiscClosures.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/rts/StgMiscClosures.cmm), [rts/StgStartup.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/rts/StgStartup.cmm) and [rts/StgStdThunks.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/rts/StgStdThunks.cmm). (For notes related to `PrimOps.cmm` see the [PrimOps](commentary/prim-ops) page; for much of the rest, see the [HaskellExecution](commentary/rts/haskell-execution) page.) Cmm is optimised before GHC outputs either HC or Assembler. The C compiler (from HC, pretty printed by [compiler/cmm/PprC.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/PprC.hs)) and the [Native Code Generator](commentary/compiler/backends/ncg) (NCG) [Backends](commentary/compiler/backends) are closely tied to data representations and transformations performed in Cmm. In GHC, Cmm roughly performs a function similar to the intermediate [Register Transfer Language (RTL)](http://gcc.gnu.org/onlinedocs/gccint/RTL.html) in GCC.
|
|
|
|
|
|
# Table of Contents
|
|
|
|
... | ... | @@ -63,7 +63,7 @@ A portion of the [RTS](commentary/rts) is written in Cmm: [rts/Apply.cmm](https: |
|
|
- [compiler/cmm/CmmLint.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmLint.hs): a consistency checker.
|
|
|
- [compiler/cmm/CmmOpt.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmOpt.hs): an optimiser for `Cmm`.
|
|
|
|
|
|
- [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y), [compiler/cmm/CmmLex.x](/trac/ghc/browser/ghc/compiler/cmm/CmmLex.x): parser and lexer for [.cmm files](commentary/rts/cmm).
|
|
|
- [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y), [compiler/cmm/CmmLex.x](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmLex.x): parser and lexer for [.cmm files](commentary/rts/cmm).
|
|
|
|
|
|
- [compiler/cmm/PprC.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/PprC.hs): pretty-print `Cmm` in C syntax, when compiling via C.
|
|
|
|
... | ... | @@ -124,7 +124,7 @@ __stginit_Main_() { // parse error `(' |
|
|
```
|
|
|
|
|
|
|
|
|
The Cmm procedure names in [rts/PrimOps.cmm](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/rts/PrimOps.cmm) are not followed by a (possibly empty) parenthetical list of arguments; all their arguments are Global (STG) Registers, anyway, see [Variables, Registers and Types](commentary/compiler/cmm-type#variables,-registers-and-types), below. Don't be confused by the procedure definitions in other handwritten `.cmm` files in the RTS, such as [rts/Apply.cmm](/trac/ghc/browser/ghc/rts/Apply.cmm): all-uppercase procedure invocations are special reserved tokens in [compiler/cmm/CmmLex.x](/trac/ghc/browser/ghc/compiler/cmm/CmmLex.x) and [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y). For example, `INFO_TABLE` is parsed as one of the tokens in the Alex `info` predicate:
|
|
|
The Cmm procedure names in [rts/PrimOps.cmm](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/rts/PrimOps.cmm) are not followed by a (possibly empty) parenthetical list of arguments; all their arguments are Global (STG) Registers, anyway, see [Variables, Registers and Types](commentary/compiler/cmm-type#variables,-registers-and-types), below. Don't be confused by the procedure definitions in other handwritten `.cmm` files in the RTS, such as [rts/Apply.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/rts/Apply.cmm): all-uppercase procedure invocations are special reserved tokens in [compiler/cmm/CmmLex.x](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmLex.x) and [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y). For example, `INFO_TABLE` is parsed as one of the tokens in the Alex `info` predicate:
|
|
|
|
|
|
```wiki
|
|
|
info :: { ExtFCode (CLabel, [CmmLit],[CmmLit]) }
|
... | ... | @@ -187,7 +187,7 @@ Cmm is a high level assembler with a syntax style similar to C. This section de |
|
|
- [The C-- Language Specification Version 2.0 (CVS Revision 1.128, 23 February 2005)](http://cminusminus.org/extern/man2.pdf) (PDF)
|
|
|
|
|
|
|
|
|
Cmm is not a stand alone C-- compiler; it is an implementation of C-- embedded in the GHC compiler. One difference between Cmm and a C-- compiler like [Quick C--](http://cminusminus.org/code.html) is this: Cmm uses the C preprocessor (cpp). Cpp lets Cmm *integrate* with C code, especially the C header defines in [includes](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/includes), and among many other consequences it makes the C-- `import` and `export` statements irrelevant; in fact, according to [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y) they are ignored. The most significant action taken by the Cmm modules in the Compiler is to optimise Cmm, through [compiler/cmm/CmmOpt.hs](/trac/ghc/browser/ghc/compiler/cmm/CmmOpt.hs). The Cmm Optimiser generally runs a few simplification passes over primitive Cmm operations, inlines simple Cmm expressions that do not contain global registers (these would be left to one of the [Backends](commentary/compiler/backends), which currently cannot handle inlines with global registers) and performs a simple loop optimisation.
|
|
|
Cmm is not a stand alone C-- compiler; it is an implementation of C-- embedded in the GHC compiler. One difference between Cmm and a C-- compiler like [Quick C--](http://cminusminus.org/code.html) is this: Cmm uses the C preprocessor (cpp). Cpp lets Cmm *integrate* with C code, especially the C header defines in [includes](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/includes), and among many other consequences it makes the C-- `import` and `export` statements irrelevant; in fact, according to [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y) they are ignored. The most significant action taken by the Cmm modules in the Compiler is to optimise Cmm, through [compiler/cmm/CmmOpt.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmOpt.hs). The Cmm Optimiser generally runs a few simplification passes over primitive Cmm operations, inlines simple Cmm expressions that do not contain global registers (these would be left to one of the [Backends](commentary/compiler/backends), which currently cannot handle inlines with global registers) and performs a simple loop optimisation.
|
|
|
|
|
|
### Code Blocks in Cmm
|
|
|
|
... | ... | @@ -254,7 +254,7 @@ For a description of Cmm labels and the `CLabel` data type, see the subsection [ |
|
|
|
|
|
|
|
|
|
|
|
Cmm Basic Blocks are labeled blocks of Cmm code ending in an explicit jump. Sections (see [Sections and Directives](commentary/compiler/cmm-type#sections-and-directives)) have no jumps--in Cmm, Sections cannot contain nested Procedures (see, e.g., [Compiling Cmm with GHC](commentary/compiler/cmm-type#compiling-cmm-with-ghc)). Basic Blocks encapsulate parts of Procedures. The data type `GenBasicBlock` and the type synonym `CmmBasicBlock` encapsulate Basic Blocks; they are defined in [compiler/cmm/Cmm.hs](/trac/ghc/browser/ghc/compiler/cmm/Cmm.hs):
|
|
|
Cmm Basic Blocks are labeled blocks of Cmm code ending in an explicit jump. Sections (see [Sections and Directives](commentary/compiler/cmm-type#sections-and-directives)) have no jumps--in Cmm, Sections cannot contain nested Procedures (see, e.g., [Compiling Cmm with GHC](commentary/compiler/cmm-type#compiling-cmm-with-ghc)). Basic Blocks encapsulate parts of Procedures. The data type `GenBasicBlock` and the type synonym `CmmBasicBlock` encapsulate Basic Blocks; they are defined in [compiler/cmm/Cmm.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/Cmm.hs):
|
|
|
|
|
|
|
|
|
```
|
... | ... | @@ -314,7 +314,7 @@ For a list of references with information on `Unique`, see the [Basic Blocks and |
|
|
|
|
|
|
|
|
|
|
|
A `MachRep`, the type of a machine register, is defined in [compiler/cmm/CmmMachOp.hs](/trac/ghc/browser/ghc/compiler/cmm/CmmMachOp.hs):
|
|
|
A `MachRep`, the type of a machine register, is defined in [compiler/cmm/CmmMachOp.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmMachOp.hs):
|
|
|
|
|
|
|
|
|
```
|
... | ... | @@ -333,7 +333,7 @@ data MachRep |
|
|
|
|
|
|
|
|
|
|
|
There is currently no register for floating point vectors, such as `F128`. The types of Cmm variables are defined in the Happy parser file [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y) and the Alex lexer file [compiler/cmm/CmmLex.x](/trac/ghc/browser/ghc/compiler/cmm/CmmLex.x). (Happy and Alex will compile these into `CmmParse.hs` and `CmmLex.hs`, respectively.) Cmm recognises the following `C--` types as parseable tokens, listed next to their corresponding `define`s in [includes/Cmm.h](/trac/ghc/browser/ghc/includes/Cmm.h) and their STG types:
|
|
|
There is currently no register for floating point vectors, such as `F128`. The types of Cmm variables are defined in the Happy parser file [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y) and the Alex lexer file [compiler/cmm/CmmLex.x](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmLex.x). (Happy and Alex will compile these into `CmmParse.hs` and `CmmLex.hs`, respectively.) Cmm recognises the following `C--` types as parseable tokens, listed next to their corresponding `define`s in [includes/Cmm.h](https://gitlab.haskell.org/ghc/ghc/blob/master/includes/Cmm.h) and their STG types:
|
|
|
|
|
|
|
|
|
<table><tr><th> <b>Cmm Token</b> </th>
|
... | ... | @@ -378,7 +378,7 @@ There is currently no register for floating point vectors, such as `F128`. The |
|
|
|
|
|
|
|
|
|
|
|
These are universal both to a Cmm module and to the whole compiled program. Variables are global if they are declared at the top-level of a compilation unit (outside any procedure). Global Variables are marked as external symbols with the `.globl` assembler directive. In Cmm, global registers are used for special STG registers and specific registers for passing arguments and returning values. The Haskell representation of Global Variables (Registers) is the `GlobalReg` data type, defined in [compiler/cmm/Cmm.hs](/trac/ghc/browser/ghc/compiler/cmm/Cmm.hs):
|
|
|
These are universal both to a Cmm module and to the whole compiled program. Variables are global if they are declared at the top-level of a compilation unit (outside any procedure). Global Variables are marked as external symbols with the `.globl` assembler directive. In Cmm, global registers are used for special STG registers and specific registers for passing arguments and returning values. The Haskell representation of Global Variables (Registers) is the `GlobalReg` data type, defined in [compiler/cmm/Cmm.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/Cmm.hs):
|
|
|
|
|
|
|
|
|
```
|
... | ... | @@ -426,7 +426,7 @@ data GlobalReg |
|
|
|
|
|
|
|
|
|
|
|
For a description of the `Hp` and `Sp` *virtual registers*, see [The Haskell Execution Model](commentary/rts/haskell-execution) page. General `GlobalReg`s are clearly visible in Cmm code according to the following syntax defined in [compiler/cmm/CmmLex.x](/trac/ghc/browser/ghc/compiler/cmm/CmmLex.x):
|
|
|
For a description of the `Hp` and `Sp` *virtual registers*, see [The Haskell Execution Model](commentary/rts/haskell-execution) page. General `GlobalReg`s are clearly visible in Cmm code according to the following syntax defined in [compiler/cmm/CmmLex.x](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmLex.x):
|
|
|
|
|
|
|
|
|
<table><tr><th> <b><tt>GlobalReg</tt> Constructor</b> </th>
|
... | ... | @@ -493,12 +493,12 @@ data MachHint |
|
|
Although the C-- specification does not allow the C-- type system to statically distinguish between floats, signed ints, unsigned ints or pointers, Cmm does. Cmm `MachRep`s carry the float or int kind of a variable, either within a local block or in a global register. `GlobalReg` includes separate constructors for `Vanilla`, `Float`, `Double` and `Long`. Cmm still does not distinguish between signed ints, unsigned ints and pointers (addresses) at the register level, as these are given *hint* pseudo-types or their real type is determined as they run through primitive operations. `MachHint`s still follow the C-- specification and carry kind information as an aide to the backend optimisers.
|
|
|
|
|
|
|
|
|
Global Registers in Cmm currently have a problem with inlining: because neither [compiler/cmm/PprC.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/PprC.hs) nor the NCG are able to keep Global Registers from clashing with C argument passing registers, Cmm expressions that contain Global Registers cannot be inlined into an argument position of a foreign call. For more thorough notes on inlining, see the comments in [compiler/cmm/CmmOpt.hs](/trac/ghc/browser/ghc/compiler/cmm/CmmOpt.hs).
|
|
|
Global Registers in Cmm currently have a problem with inlining: because neither [compiler/cmm/PprC.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/PprC.hs) nor the NCG are able to keep Global Registers from clashing with C argument passing registers, Cmm expressions that contain Global Registers cannot be inlined into an argument position of a foreign call. For more thorough notes on inlining, see the comments in [compiler/cmm/CmmOpt.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmOpt.hs).
|
|
|
|
|
|
#### Declaration and Initialisation
|
|
|
|
|
|
|
|
|
Cmm variables hold the same values registers do in assembly languages but may be declared in a similar way to variables in C. As in C--, they may actually be declared anywhere in the scope for which they are visible (a block or file)--for Cmm, this is done by the `loopDecls` function in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y). In [compiler/rts/PrimOps.cmm](/trac/ghc/browser/ghc/compiler/rts/PrimOps.cmm), you will see Cmm variable declarations like this one:
|
|
|
Cmm variables hold the same values registers do in assembly languages but may be declared in a similar way to variables in C. As in C--, they may actually be declared anywhere in the scope for which they are visible (a block or file)--for Cmm, this is done by the `loopDecls` function in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y). In [compiler/rts/PrimOps.cmm](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/rts/PrimOps.cmm), you will see Cmm variable declarations like this one:
|
|
|
|
|
|
```wiki
|
|
|
W_ w, code, val; // W_ is a cpp #define for StgWord,
|
... | ... | @@ -506,7 +506,7 @@ W_ w, code, val; // W_ is a cpp #define for StgWord, |
|
|
```
|
|
|
|
|
|
|
|
|
Remember that Cmm code is run through the C preprocessor. `W_` will be transformed into `bits32`, `bits64` or whatever is the `bits`*size* of the machine word, as defined in [includes/Cmm.h](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/includes/Cmm.h). In Haskell code, you may use the [compiler/cmm/CmmMachOp.hs](/trac/ghc/browser/ghc/compiler/cmm/CmmMachOp.hs) functions `wordRep` and `halfWordRep` to dynamically determine the machine word size. For a description of word sizes in GHC, see the [Word](commentary/rts/word) page.
|
|
|
Remember that Cmm code is run through the C preprocessor. `W_` will be transformed into `bits32`, `bits64` or whatever is the `bits`*size* of the machine word, as defined in [includes/Cmm.h](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/includes/Cmm.h). In Haskell code, you may use the [compiler/cmm/CmmMachOp.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmMachOp.hs) functions `wordRep` and `halfWordRep` to dynamically determine the machine word size. For a description of word sizes in GHC, see the [Word](commentary/rts/word) page.
|
|
|
|
|
|
|
|
|
|
... | ... | @@ -583,7 +583,7 @@ is used in: |
|
|
```
|
|
|
|
|
|
|
|
|
The function `cmmMachOpFold` in [compiler/cmm/CmmOpt.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmOpt.hs) will reduce the resulting expression `Sp + (n * SIZEOF_W)` to `Sp + N`, where `N` is a constant. A very large number of macros for accessing STG struct fields and the like are produced by [utils/deriveConstants](/trac/ghc/browser/ghc/utils/deriveConstants) and output into the file `includes/DerivedConstants.h` when GHC is compiled.
|
|
|
The function `cmmMachOpFold` in [compiler/cmm/CmmOpt.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmOpt.hs) will reduce the resulting expression `Sp + (n * SIZEOF_W)` to `Sp + N`, where `N` is a constant. A very large number of macros for accessing STG struct fields and the like are produced by [utils/deriveConstants](https://gitlab.haskell.org/ghc/ghc/blob/master/utils/deriveConstants) and output into the file `includes/DerivedConstants.h` when GHC is compiled.
|
|
|
|
|
|
|
|
|
Of course, all this also holds true for the reverse (when an assignment is made to a memory address):
|
... | ... | @@ -620,7 +620,7 @@ I32[frame + SIZEOF_StgHeader + 0] = R1; |
|
|
|
|
|
|
|
|
|
|
|
Cmm literals are exactly like C-- literals, including the Haskell-style type syntax, for example: `0x00000001::bits32`. Cmm literals may be used for initialisation by assignment or in expressions. The `CmmLit` and `CmmStatic` data types, defined in [compiler/cmm/Cmm.hs](/trac/ghc/browser/ghc/compiler/cmm/Cmm.hs) together represent Cmm literals, static information and Cmm labels:
|
|
|
Cmm literals are exactly like C-- literals, including the Haskell-style type syntax, for example: `0x00000001::bits32`. Cmm literals may be used for initialisation by assignment or in expressions. The `CmmLit` and `CmmStatic` data types, defined in [compiler/cmm/Cmm.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/Cmm.hs) together represent Cmm literals, static information and Cmm labels:
|
|
|
|
|
|
|
|
|
```
|
... | ... | @@ -650,7 +650,7 @@ data CmmLit |
|
|
Note how the `CmmLit` constructor `CmmInt Integer MachRep` contains sign information in the `Integer`, the representation of the literal itself: this conforms to the C-- specification, where integral literals contain sign information. For an example of a function using `CmmInt` sign information, see `cmmMachOpFold` in [compiler/cmm/CmmOpt.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmOpt.hs), where sign-operations are performed on the `Integer`.
|
|
|
|
|
|
|
|
|
The `MachRep` of a literal, such as `CmmInt Integer MachRep` or `CmmFloat Rational MachRep` may not always require the size defined by `MachRep`. The NCG optimiser, [compiler/nativeGen/MachCodeGen.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/nativeGen/MachCodeGen.hs), will test a literal such as `1::bits32` (in Haskell, `CmmInt (1::Integer) I32`) for whether it would fit into the bit-size of Assembler instruction literals on that particular architecture with a function defined in [compiler/nativeGen/MachRegs.lhs](/trac/ghc/browser/ghc/compiler/nativeGen/MachRegs.lhs), such as `fits16Bits` on the PPC. If the Integer literal fits, the function `makeImmediate` will truncate it to the specified size if possible and store it in a NCG data type, `Imm`, specifically `Maybe Imm`. (These are also defined in [compiler/nativeGen/MachRegs.lhs](/trac/ghc/browser/ghc/compiler/nativeGen/MachRegs.lhs).)
|
|
|
The `MachRep` of a literal, such as `CmmInt Integer MachRep` or `CmmFloat Rational MachRep` may not always require the size defined by `MachRep`. The NCG optimiser, [compiler/nativeGen/MachCodeGen.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/nativeGen/MachCodeGen.hs), will test a literal such as `1::bits32` (in Haskell, `CmmInt (1::Integer) I32`) for whether it would fit into the bit-size of Assembler instruction literals on that particular architecture with a function defined in [compiler/nativeGen/MachRegs.lhs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/MachRegs.lhs), such as `fits16Bits` on the PPC. If the Integer literal fits, the function `makeImmediate` will truncate it to the specified size if possible and store it in a NCG data type, `Imm`, specifically `Maybe Imm`. (These are also defined in [compiler/nativeGen/MachRegs.lhs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/MachRegs.lhs).)
|
|
|
|
|
|
|
|
|
|
... | ... | @@ -768,7 +768,7 @@ data CLabel |
|
|
|
|
|
|
|
|
|
|
|
The Haskell representation of Cmm Section directives, in [compiler/cmm/Cmm.hs](/trac/ghc/browser/ghc/compiler/cmm/Cmm.hs) as the first part of the "Static Data" section, is:
|
|
|
The Haskell representation of Cmm Section directives, in [compiler/cmm/Cmm.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/Cmm.hs) as the first part of the "Static Data" section, is:
|
|
|
|
|
|
|
|
|
```
|
... | ... | @@ -785,7 +785,7 @@ data Section |
|
|
|
|
|
|
|
|
|
|
|
Cmm supports the following directives, corresponding to the assembler directives pretty-printed by the `pprSectionHeader` function in [compiler/nativeGen/PprMach.hs](/trac/ghc/browser/ghc/compiler/nativeGen/PprMach.hs):
|
|
|
Cmm supports the following directives, corresponding to the assembler directives pretty-printed by the `pprSectionHeader` function in [compiler/nativeGen/PprMach.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/PprMach.hs):
|
|
|
|
|
|
|
|
|
<table><tr><th> <b><tt>Section</tt> Constructor</b> </th>
|
... | ... | @@ -869,7 +869,7 @@ target |
|
|
This is essentially a custom-coded version of the GNU Assembler (`as`) `.machine` directive, which is essentially the same as passing the `-arch [cpu_type]` option to `as`.
|
|
|
|
|
|
|
|
|
Cmm does not support the `target` directive. This is partly due GHC generally lacking cross-compiler capabilities. Should GHC move toward adding cross-compilation capabilities, the `target` might not be a bad thing to add. Target architecture parameters are currently handled through the [Build System](attic/building/build-system), which partly sets such architectural parameters through [utils/deriveConstants](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/utils/deriveConstants) and [includes/ghcconfig.h](/trac/ghc/browser/ghc/includes/ghcconfig.h).
|
|
|
Cmm does not support the `target` directive. This is partly due GHC generally lacking cross-compiler capabilities. Should GHC move toward adding cross-compilation capabilities, the `target` might not be a bad thing to add. Target architecture parameters are currently handled through the [Build System](attic/building/build-system), which partly sets such architectural parameters through [utils/deriveConstants](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/utils/deriveConstants) and [includes/ghcconfig.h](https://gitlab.haskell.org/ghc/ghc/blob/master/includes/ghcconfig.h).
|
|
|
|
|
|
### Expressions
|
|
|
|
... | ... | @@ -922,11 +922,11 @@ CmmMachOp (MO_Add rep) [(CmmReg reg),(CmmLit (CmmInt i rep))] |
|
|
|
|
|
|
|
|
|
|
|
The function `cmmRegRep` is described below. Note: the original comment following `CmmExpr` in [compiler/cmm/Cmm.hs](/trac/ghc/browser/ghc/compiler/cmm/Cmm.hs) is erroneous (cf., `mangleIndexTree` in [compiler/nativeGen/MachCodeGen.hs](/trac/ghc/browser/ghc/compiler/nativeGen/MachCodeGen.hs)) but makes the same point described here. The offset, `(CmmLit (CmmInt i rep))`, is a literal (`CmmLit`), not a name (`CLabel`). A `CmmExpr` for an offset must be reducible to a `CmmInt` *in Haskell*; in other words, offsets in Cmm expressions may not be external symbols whose addresses are not resolvable in the current context.
|
|
|
The function `cmmRegRep` is described below. Note: the original comment following `CmmExpr` in [compiler/cmm/Cmm.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/Cmm.hs) is erroneous (cf., `mangleIndexTree` in [compiler/nativeGen/MachCodeGen.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/MachCodeGen.hs)) but makes the same point described here. The offset, `(CmmLit (CmmInt i rep))`, is a literal (`CmmLit`), not a name (`CLabel`). A `CmmExpr` for an offset must be reducible to a `CmmInt` *in Haskell*; in other words, offsets in Cmm expressions may not be external symbols whose addresses are not resolvable in the current context.
|
|
|
|
|
|
|
|
|
|
|
|
Boolean comparisons are not boolean conditions. Boolean comparisons involve relational operators, such as `>`, `<` and `==`, and map to `MachOp`s that are converted to comparison followed by branch instructions. For example, `<` would map to `MO_S_Lt` for signed operands, [compiler/nativeGen/MachCodeGen.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/nativeGen/MachCodeGen.hs) would transform `MO_S_Lt` into the `LTT` constructor of the `Cond` union data type defined in [compiler/nativeGen/MachInstrs.hs](/trac/ghc/browser/ghc/compiler/nativeGen/MachInstrs.hs) and [compiler/nativeGen/PprMach.hs](/trac/ghc/browser/ghc/compiler/nativeGen/PprMach.hs) would transform `LTT` to the distinguishing comparison type for an assembler comparison instruction. You already know that the result of a comparison instruction is actually a change in the state of the Condition Register (CR), so Cmm boolean expressions do have a kind of side-effect but that is to be expected. In fact, it is necessary since at the least a conditional expression becomes two assembler instructions, in PPC Assembler:
|
|
|
Boolean comparisons are not boolean conditions. Boolean comparisons involve relational operators, such as `>`, `<` and `==`, and map to `MachOp`s that are converted to comparison followed by branch instructions. For example, `<` would map to `MO_S_Lt` for signed operands, [compiler/nativeGen/MachCodeGen.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/nativeGen/MachCodeGen.hs) would transform `MO_S_Lt` into the `LTT` constructor of the `Cond` union data type defined in [compiler/nativeGen/MachInstrs.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/MachInstrs.hs) and [compiler/nativeGen/PprMach.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/PprMach.hs) would transform `LTT` to the distinguishing comparison type for an assembler comparison instruction. You already know that the result of a comparison instruction is actually a change in the state of the Condition Register (CR), so Cmm boolean expressions do have a kind of side-effect but that is to be expected. In fact, it is necessary since at the least a conditional expression becomes two assembler instructions, in PPC Assembler:
|
|
|
|
|
|
```wiki
|
|
|
cmplwi r3, 0 ; condition test
|
... | ... | @@ -938,7 +938,7 @@ This condition mapping does have an unfortunate consequence: conditional express |
|
|
|
|
|
|
|
|
|
|
|
Boolean conditions include: `&&`, `||`, `!` and parenthetical combinations of boolean conditions. The `if expr { }` and `if expr { } else { }` statements contain boolean conditions. The C-- type produced by conditional expressions is `bool`, in Cmm, type `BoolExpr` in [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y):
|
|
|
Boolean conditions include: `&&`, `||`, `!` and parenthetical combinations of boolean conditions. The `if expr { }` and `if expr { } else { }` statements contain boolean conditions. The C-- type produced by conditional expressions is `bool`, in Cmm, type `BoolExpr` in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y):
|
|
|
|
|
|
|
|
|
```
|
... | ... | @@ -996,7 +996,7 @@ CmmMachOp (MO_Add I32) [CmmReg (CmmLocal uniq I32), CmmReg (CmmLocal uniq I32)] |
|
|
|
|
|
|
|
|
|
|
|
The `expr` production rule in the Cmm Parser [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y) maps tokens to "values", such as `+` to an addition operation, `MO_Add`. The `mkMachOp` function in the Parser determines the `MachOp` type in `CmmMachOp MachOp [CmmExpr]` from the token value and the `MachRep` type of the `head` variable. Notice that the simple `+` operator did not contain sign information, only the `MachRep`. For `expr`, signed and other `MachOps`, see the `machOps` function in [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y). Here is a table of operators and the corresponding `MachOp`s recognised by Cmm (listed in order of precedence):
|
|
|
The `expr` production rule in the Cmm Parser [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y) maps tokens to "values", such as `+` to an addition operation, `MO_Add`. The `mkMachOp` function in the Parser determines the `MachOp` type in `CmmMachOp MachOp [CmmExpr]` from the token value and the `MachRep` type of the `head` variable. Notice that the simple `+` operator did not contain sign information, only the `MachRep`. For `expr`, signed and other `MachOps`, see the `machOps` function in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y). Here is a table of operators and the corresponding `MachOp`s recognised by Cmm (listed in order of precedence):
|
|
|
|
|
|
|
|
|
<table><tr><th> <b>Operator</b> </th>
|
... | ... | @@ -1062,7 +1062,7 @@ The `expr` production rule in the Cmm Parser [compiler/cmm/CmmParse.y](/trac/ghc |
|
|
|
|
|
|
|
|
|
|
|
If you read to the end of `expr` in [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y), in the next production rule, `expr0`, you will notice that Cmm expressions also recognise a set of name (not symbol) based operators that would probably be better understood as *quasi-operators*. The syntax for these quasi-operators is in some cases similar to syntax for Cmm statements and generally conform to the C-- specification, sections 3.3.2 (`expr`) and 7.4.1 (syntax of primitive operators), *except that* 3. *and, by the equivalence of the two,* 1. *may return* **multiple** * arguments*. In Cmm, quasi-operators may have side effects. The syntax for quasi-operators may be:
|
|
|
If you read to the end of `expr` in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y), in the next production rule, `expr0`, you will notice that Cmm expressions also recognise a set of name (not symbol) based operators that would probably be better understood as *quasi-operators*. The syntax for these quasi-operators is in some cases similar to syntax for Cmm statements and generally conform to the C-- specification, sections 3.3.2 (`expr`) and 7.4.1 (syntax of primitive operators), *except that* 3. *and, by the equivalence of the two,* 1. *may return* **multiple** * arguments*. In Cmm, quasi-operators may have side effects. The syntax for quasi-operators may be:
|
|
|
|
|
|
|
|
|
1. `expr0` ``name`` `expr0`
|
... | ... | @@ -1091,7 +1091,7 @@ res = %lt(one, two); |
|
|
```
|
|
|
|
|
|
|
|
|
The primitive operations allowed by Cmm are listed in the `machOps` production rule, in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y), and largely correspond to `MachOp` data type constructors, in [compiler/cmm/CmmMachOp.hs](/trac/ghc/browser/ghc/compiler/cmm/CmmMachOp.hs), with a few additions. The primitive operations distinguish between signed, unsigned and floating point types.
|
|
|
The primitive operations allowed by Cmm are listed in the `machOps` production rule, in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y), and largely correspond to `MachOp` data type constructors, in [compiler/cmm/CmmMachOp.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmMachOp.hs), with a few additions. The primitive operations distinguish between signed, unsigned and floating point types.
|
|
|
|
|
|
|
|
|
Cmm adds some expression macros that map to Haskell Cmm functions. They are listed under `exprMacros` in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y) and include:
|
... | ... | @@ -1128,7 +1128,7 @@ Cmm does not implement the C-- specification for Spans (sec. 6.1) or Continuatio |
|
|
|
|
|
Although Cmm supports primitive operations that may have side effects (see [Primitive Operations](commentary/compiler/cmm-type#primitive-operations), below), it does not parse the syntax `%%` form mentioned in section 6.3 of the C-- specification. Use the `%name(arg1,arg2)` expression-syntax instead.
|
|
|
|
|
|
Cmm does not implement the `return` statement (C-- spec, sec. 6.8.2) but provides a set of macros that return a list of tuples of a `CgRep` and a `CmmExpr`: `[(CgRep,CmmExpr)]`. For a description of `CgRep`, see comments in [compiler/codeGen/SMRep.lhs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/codeGen/SMRep.lhs). The return macros are defined at the end of the production rule `stmtMacros` in [compiler/cmm/CmmParse.y](/trac/ghc/browser/ghc/compiler/cmm/CmmParse.y):
|
|
|
Cmm does not implement the `return` statement (C-- spec, sec. 6.8.2) but provides a set of macros that return a list of tuples of a `CgRep` and a `CmmExpr`: `[(CgRep,CmmExpr)]`. For a description of `CgRep`, see comments in [compiler/codeGen/SMRep.lhs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/codeGen/SMRep.lhs). The return macros are defined at the end of the production rule `stmtMacros` in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmParse.y):
|
|
|
|
|
|
- `RET_P`
|
|
|
- `RET_N`
|
... | ... | @@ -1141,7 +1141,7 @@ Cmm does not implement the `return` statement (C-- spec, sec. 6.8.2) but provide |
|
|
- `RET_NPNP`
|
|
|
|
|
|
|
|
|
In the above macros, `P` stands for `PtrArg` and `N` stands for `NonPtrArg`; both are `CgRep` constructors. These return macros provide greater control for the [CodeGen](commentary/compiler/code-gen) and integrate with the RTS but limit the number and type of return arguments in Cmm: you may only return according to these macros! The returns are processed by the `emitRetUT` function in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y), which in turn calls several functions from [compiler/codeGen/CgMonad.lhs](/trac/ghc/browser/ghc/compiler/codeGen/CgMonad.lhs), notably `emitStmts`, which is the core Code Generator function for emitting `CmmStmt` data.
|
|
|
In the above macros, `P` stands for `PtrArg` and `N` stands for `NonPtrArg`; both are `CgRep` constructors. These return macros provide greater control for the [CodeGen](commentary/compiler/code-gen) and integrate with the RTS but limit the number and type of return arguments in Cmm: you may only return according to these macros! The returns are processed by the `emitRetUT` function in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y), which in turn calls several functions from [compiler/codeGen/CgMonad.lhs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/codeGen/CgMonad.lhs), notably `emitStmts`, which is the core Code Generator function for emitting `CmmStmt` data.
|
|
|
|
|
|
|
|
|
|
... | ... | @@ -1204,7 +1204,7 @@ The computed procedure address, in this case `(bits32[x+4])`, should always be t |
|
|
|
|
|
`CmmCondBranch CmmExpr BlockId` represents a conditional branch to another [Basic Block](commentary/compiler/cmm-type#basic-blocks-and-procedures) in the same procedure. This is the `if expr` statement where `expr` is a `CmmExpr`, used in both the unary `if` and `if-then-else` statements. `CmmCondBranch` maps to more complex Assembler instruction sets or HC code ([compiler/cmm/PprC.hs](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/PprC.hs)). For assembler, labels are created for each new Basic Block. During parsing, conditional statements map to the `BoolExpr` data type which guides the encoding of assembler instruction sets.
|
|
|
|
|
|
`CmmSwitch` represents the `switch` statement. It is parsed and created as with the `doSwitch` function in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y) or created from `case` expressions with the `emitSwitch` and `mk_switch` functions in [compiler/codeGen/CgUtils.hs](/trac/ghc/browser/ghc/compiler/codeGen/CgUtils.hs). In the NCG, a `CmmSwitch` is generated as a jump table using the `genSwitch` function in [compiler/nativeGen/MachCodeGen.hs](/trac/ghc/browser/ghc/compiler/nativeGen/MachCodeGen.hs). There is currently no implementation of any optimisations, such as a cascade of comparisons for switches with a wide deviation in values or binary search for very wide value ranges--for output to HC, earlier versions of GCC could not handle large if-trees, anyway.
|
|
|
`CmmSwitch` represents the `switch` statement. It is parsed and created as with the `doSwitch` function in [compiler/cmm/CmmParse.y](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/cmm/CmmParse.y) or created from `case` expressions with the `emitSwitch` and `mk_switch` functions in [compiler/codeGen/CgUtils.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/codeGen/CgUtils.hs). In the NCG, a `CmmSwitch` is generated as a jump table using the `genSwitch` function in [compiler/nativeGen/MachCodeGen.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/MachCodeGen.hs). There is currently no implementation of any optimisations, such as a cascade of comparisons for switches with a wide deviation in values or binary search for very wide value ranges--for output to HC, earlier versions of GCC could not handle large if-trees, anyway.
|
|
|
|
|
|
#### Cmm Calls
|
|
|
|
... | ... | @@ -1213,7 +1213,7 @@ Cmm calls include both calls to foreign functions and calls to Cmm quasi-operato |
|
|
|
|
|
|
|
|
|
|
|
The data type, `CmmCallTarget` is defined in [compiler/cmm/Cmm.hs](/trac/ghc/browser/ghc/compiler/cmm/Cmm.hs) as:
|
|
|
The data type, `CmmCallTarget` is defined in [compiler/cmm/Cmm.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/Cmm.hs) as:
|
|
|
|
|
|
|
|
|
```
|
... | ... | @@ -1231,11 +1231,11 @@ data CmmCallTarget |
|
|
|
|
|
|
|
|
|
|
|
`CCallConv` is defined in [compiler/prelude/ForeignCall.hs](/trac/ghc/browser/ghc/compiler/prelude/ForeignCall.hs); for information on register assignments, see comments in [compiler/codeGen/CgCallConv.hs](/trac/ghc/browser/ghc/compiler/codeGen/CgCallConv.hs).
|
|
|
`CCallConv` is defined in [compiler/prelude/ForeignCall.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/prelude/ForeignCall.hs); for information on register assignments, see comments in [compiler/codeGen/CgCallConv.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/codeGen/CgCallConv.hs).
|
|
|
|
|
|
|
|
|
|
|
|
`CallishMachOp` is defined in [compiler/cmm/CmmMachOp.hs](/trac/ghc/browser/ghc/compiler/cmm/CmmMachOp.hs); see, also, below [Primitive Operations](commentary/compiler/cmm-type#primitive-operations). `CallishMachOp`s are generally used for floating point computations (without implementing any floating point exceptions). Here is an example of using a `CallishMachOp` (not yet implemented):
|
|
|
`CallishMachOp` is defined in [compiler/cmm/CmmMachOp.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/cmm/CmmMachOp.hs); see, also, below [Primitive Operations](commentary/compiler/cmm-type#primitive-operations). `CallishMachOp`s are generally used for floating point computations (without implementing any floating point exceptions). Here is an example of using a `CallishMachOp` (not yet implemented):
|
|
|
|
|
|
|
|
|
```wiki
|
... | ... | @@ -1367,7 +1367,7 @@ data CallishMachOp |
|
|
```
|
|
|
|
|
|
|
|
|
For an example, the floating point sine function, `sinFloat#` in [compiler/prelude/primops.txt.pp](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/prelude/primops.txt.pp) is piped through the `callishOp` function in [compiler/codeGen/CgPrimOp.hs](/trac/ghc/browser/ghc/compiler/codeGen/CgPrimOp.hs) to become `Just MO_F32_Sin`. The `CallishMachOp` constructor `MO_F32_Sin` is piped through a platform specific function such as [compiler/nativeGen/X86/CodeGen.hs](/trac/ghc/browser/ghc/compiler/nativeGen/X86/CodeGen.hs) on X86, where the function `genCCall` will call `outOfLineFloatOp` to issue a call to a C function such as `sin`.
|
|
|
For an example, the floating point sine function, `sinFloat#` in [compiler/prelude/primops.txt.pp](https://gitlab.haskell.org/ghc/ghc/tree/master/ghc/compiler/prelude/primops.txt.pp) is piped through the `callishOp` function in [compiler/codeGen/CgPrimOp.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/codeGen/CgPrimOp.hs) to become `Just MO_F32_Sin`. The `CallishMachOp` constructor `MO_F32_Sin` is piped through a platform specific function such as [compiler/nativeGen/X86/CodeGen.hs](https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/nativeGen/X86/CodeGen.hs) on X86, where the function `genCCall` will call `outOfLineFloatOp` to issue a call to a C function such as `sin`.
|
|
|
|
|
|
## Cmm Design: Observations and Areas for Potential Improvement
|
|
|
|
... | ... | |