summaryrefslogtreecommitdiff
path: root/compiler/GHC/Driver/Backend.hs
blob: a27a2e7b4a36f7d86ff29dda97ca6b5bd5e53a2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
{-# LANGUAGE MultiWayIf #-}

{-|
Module      : GHC.Driver.Backend
Description : Back ends for code generation

This module exports the `Backend` type and all the available values
of that type.  The type is abstract, and GHC assumes a "closed world":
all the back ends are known and are known here.  The compiler driver
chooses a `Backend` value based on how it is asked to generate code.

A `Backend` value encapsulates the knowledge needed to take Cmm, STG,
or Core and write assembly language to a file.  A back end also
provides a function that enables the compiler driver to run an
assembler on the code that is written, if any (the "post-backend
pipeline").  Finally, a back end has myriad /properties/.  Properties
mediate interactions between a back end and the rest of the compiler,
especially the driver.  Examples include the following:

 * Property `backendValidityOfCImport` says whether the back end can
   import foreign C functions.

 * Property `backendForcesOptimization0` says whether the back end can
   be used with optimization levels higher than `-O0`.

 * Property `backendCDefs` tells the compiler driver, "if you're using
   this back end, then these are the command-line flags you should add
   to any invocation of the C compiler."

These properties are use elsewhere in GHC, primarily in the driver, to
fine-tune operations according to the capabilities of the chosen back
end.  You might use a property to make GHC aware of a potential
limitation of certain back ends, or a special feature available only
in certain back ends.  If your client code needs to know a fact that
is not exposed in an existing property, you would define and export a
new property.  Conditioning client code on the /identity/ or /name/ of
a back end is Not Done.

For full details, see the documentation of each property.
-}

module GHC.Driver.Backend
   ( -- * The @Backend@ type
     Backend  -- note: type is abstract
   -- * Available back ends
   , ncgBackend
   , llvmBackend
   , viaCBackend
   , interpreterBackend
   , noBackend
   , allBackends

    -- * Types used to specify properties of back ends
   , PrimitiveImplementation(..)
     -- ** Properties that stand for functions
     -- *** Back-end function for code generation
   , DefunctionalizedCodeOutput(..)
     -- *** Back-end functions for assembly
   , DefunctionalizedPostHscPipeline(..)
   , DefunctionalizedAssemblerProg(..)
   , DefunctionalizedAssemblerInfoGetter(..)
     -- *** Other back-end functions
   , DefunctionalizedCDefs(..)
     -- ** Names of back ends (for API clients of version 9.4 or earlier)
   , BackendName



     -- * Properties of back ends
   , backendDescription
   , backendWritesFiles
   , backendPipelineOutput
   , backendCanReuseLoadedCode
   , backendGeneratesCode
   , backendSupportsInterfaceWriting
   , backendRespectsSpecialise
   , backendWantsGlobalBindings
   , backendHasNativeSwitch
   , backendPrimitiveImplementation
   , backendSimdValidity
   , backendSupportsEmbeddedBlobs
   , backendNeedsPlatformNcgSupport
   , backendSupportsUnsplitProcPoints
   , backendSwappableWithViaC
   , backendUnregisterisedAbiOnly
   , backendGeneratesHc
   , backendSptIsDynamic
   , backendWantsBreakpointTicks
   , backendForcesOptimization0
   , backendNeedsFullWays
   , backendSpecialModuleSource
   , backendSupportsHpc
   , backendSupportsCImport
   , backendSupportsCExport
   , backendAssemblerProg
   , backendAssemblerInfoGetter
   , backendCDefs
   , backendCodeOutput
   , backendPostHscPipeline
   , backendNormalSuccessorPhase
   , backendName
   , backendValidityOfCImport
   , backendValidityOfCExport

   -- * Other functions of back ends
   , platformDefaultBackend
   , platformNcgSupported
   )

where


import GHC.Prelude

import GHC.Driver.Backend.Internal (BackendName(..))
import GHC.Driver.Phases


import GHC.Utils.Error
import GHC.Utils.Panic

import GHC.Driver.Pipeline.Monad
import GHC.Platform


---------------------------------------------------------------------------------
--
--   DESIGN CONSIDERATIONS
--
--
--
-- The `Backend` type is made abstract in order to make it possible to
-- add new back ends without having to inspect or modify much code
-- elsewhere in GHC.  Adding a new back end would be /easiest/ if
-- `Backend` were represented as a record type, but in peer review,
-- the clear will of the majority was to use a sum type.  As a result,
-- when adding a new back end it is necessary to modify /every/
-- function in this module that expects `Backend` as its first argument.
-- **By design, these functions have no default/wildcard cases.** This
-- design forces the author of a new back end to consider the semantics
-- in every case, rather than relying on a default that may be wrong.
-- The names and documentation of the functions defined in the `Backend`
-- record are sufficiently descriptive that the author of a new back
-- end will be able to identify correct result values without having to go
-- spelunking throughout the compiler.
--
-- While the design localizes /most/ back-end logic in this module,
-- the author of a new back end will still have to make changes
-- elsewhere in the compiler:
--
--   * For reasons described in Note [Backend Defunctionalization],
--     code-generation and post-backend pipeline functions, among other
--     functions, cannot be placed in the `Backend` record itself.
--     Instead, the /names/ of those functions are placed.  Each name is
--     a value constructor in one of the algebraic data types defined in
--     this module.  The named function is then defined near its point
--     of use.
--
--     The author of a new back end will have to consider whether an
--     existing function will do or whether a new function needs to be
--     defined.  When a new function needs to be defined, the author
--     must take two steps:
--
--       - Add a value constructor to the relevant data type here
--         in the `Backend` module
--
--       - Add a case to the location in the compiler (there should be
--         exactly one) where the value constructors of the relevant
--         data type are used
--
--   * When a new back end is defined, it's quite possible that the
--     compiler driver will have to be changed in some way.  Just because
--     the driver supports five back ends doesn't mean it will support a sixth
--     without changes.
--
-- The collection of functions exported from this module hasn't
-- really been "designed"; it's what emerged from a refactoring of
-- older code.  The real design criterion was "make it crystal clear
-- what has to be done to add a new back end."
--
-- One issue remains unresolved: some of the error messages and
-- warning messages used in the driver assume a "closed world": they
-- think they know all the back ends that exist, and they are not shy
-- about enumerating them.  Just one set of error messages has been
-- ported to have an open-world assumption: these are the error
-- messages associated with type checking of foreign imports and
-- exports.  To allow other errors to be issued with an open-world
-- assumption, use functions `backendValidityOfCImport` and
-- `backendValidityOfCExport` as models, and have a look at how the
-- 'expected back ends' are used in modules "GHC.Tc.Gen.Foreign" and
-- "GHC.Tc.Errors.Ppr"
--
---------------------------------------------------------------------------------




platformDefaultBackend :: Platform -> Backend
platformDefaultBackend platform = if
      | platformUnregisterised platform -> viaCBackend
      | platformNcgSupported platform   -> ncgBackend
      | otherwise                       -> llvmBackend

-- | Is the platform supported by the Native Code Generator?
platformNcgSupported :: Platform -> Bool
platformNcgSupported platform = if
      | platformUnregisterised platform -> False -- NCG doesn't support unregisterised ABI
      | ncgValidArch                    -> True
      | otherwise                       -> False
   where
      ncgValidArch = case platformArch platform of
         ArchX86       -> True
         ArchX86_64    -> True
         ArchPPC       -> True
         ArchPPC_64 {} -> True
         ArchAArch64   -> True
         _             -> False



-- | A value of type @Backend@ represents one of GHC's back ends.
-- The set of back ends cannot be extended except by modifying the
-- definition of @Backend@ in this module.
--
-- The @Backend@ type is abstract; that is, its value constructors are
-- not exported.  It's crucial that they not be exported, because a
-- value of type @Backend@ carries only the back end's /name/, not its
-- behavior or properties.  If @Backend@ were not abstract, then code
-- elsewhere in the compiler could depend directly on the name, not on
-- the semantics, which would make it challenging to create a new back end.
-- Because @Backend@ /is/ abstract, all the obligations of a new back
-- end are enumerated in this module, in the form of functions that
-- take @Backend@ as an argument.
--
-- The issue of abstraction is discussed at great length in #20927 and !7442.


newtype Backend = Named BackendName
  -- Must be a newtype so that it has no `Eq` instance and
  -- a different `Show` instance.

-- | The Show instance is for messages /only/.  If code depends on
-- what's in the string, you deserve what happens to you.

instance Show Backend where
  show = backendDescription


ncgBackend, llvmBackend, viaCBackend, interpreterBackend, noBackend
    :: Backend

-- | The native code generator.
-- Compiles Cmm code into textual assembler, then relies on
-- an external assembler toolchain to produce machine code.
--
-- Only supports a few platforms (X86, PowerPC, SPARC).
--
-- See "GHC.CmmToAsm".
ncgBackend = Named NCG

-- | The LLVM backend.
--
-- Compiles Cmm code into LLVM textual IR, then relies on
-- LLVM toolchain to produce machine code.
--
-- It relies on LLVM support for the calling convention used
-- by the NCG backend to produce code objects ABI compatible
-- with it (see "cc 10" or "ghccc" calling convention in
-- https://llvm.org/docs/LangRef.html#calling-conventions).
--
-- Supports a few platforms (X86, AArch64, s390x, ARM).
--
-- See "GHC.CmmToLlvm"
llvmBackend = Named LLVM

-- | Via-C ("unregisterised") backend.
--
-- Compiles Cmm code into C code, then relies on a C compiler
-- to produce machine code.
--
-- It produces code objects that are /not/ ABI compatible
-- with those produced by NCG and LLVM backends.
--
-- Produced code is expected to be less efficient than the
-- one produced by NCG and LLVM backends because STG
-- registers are not pinned into real registers.  On the
-- other hand, it supports more target platforms (those
-- having a valid C toolchain).
--
-- See "GHC.CmmToC"
viaCBackend = Named ViaC

-- | The ByteCode interpreter.
--
-- Produce ByteCode objects (BCO, see "GHC.ByteCode") that
-- can be interpreted. It is used by GHCi.
--
-- Currently some extensions are not supported
-- (foreign primops).
--
-- See "GHC.StgToByteCode"
interpreterBackend = Named Interpreter

-- | A dummy back end that generates no code.
--
-- Use this back end to disable code generation. It is particularly
-- useful when GHC is used as a library for other purpose than
-- generating code (e.g. to generate documentation with Haddock) or
-- when the user requested it (via `-fno-code`) for some reason.
noBackend = Named NoBackend

---------------------------------------------------------------------------------




-- | This enumeration type specifies how the back end wishes GHC's
-- primitives to be implemented.  (Module "GHC.StgToCmm.Prim" provides
-- a generic implementation of every primitive, but some primitives,
-- like `IntQuotRemOp`, can be implemented more efficiently by
-- certain back ends on certain platforms.  For example, by using a
-- machine instruction that simultaneously computes quotient and remainder.)
--
-- For the meaning of each alternative, consult
-- "GHC.StgToCmm.Config".  (In a perfect world, type
-- `PrimitiveImplementation` would be defined there, in the module
-- that determines its meaning.  But I could not figure out how to do
-- it without mutual recursion across module boundaries.)

data PrimitiveImplementation
    = LlvmPrimitives -- ^ Primitives supported by LLVM
    | NcgPrimitives  -- ^ Primitives supported by the native code generator
    | GenericPrimitives -- ^ Primitives supported by all back ends
  deriving Show


-- | Names a function that runs the assembler, of this type:
--
-- > Logger -> DynFlags -> Platform -> [Option] -> IO ()
--
-- The functions so named are defined in "GHC.Driver.Pipeline.Execute".

data DefunctionalizedAssemblerProg
  = StandardAssemblerProg
       -- ^ Use the standard system assembler
  | DarwinClangAssemblerProg
       -- ^ If running on Darwin, use the assembler from the @clang@
       -- toolchain.  Otherwise use the standard system assembler.



-- | Names a function that discover from what toolchain the assembler
-- is coming, of this type:
--
-- > Logger -> DynFlags -> Platform -> IO CompilerInfo
--
-- The functions so named are defined in "GHC.Driver.Pipeline.Execute".

data DefunctionalizedAssemblerInfoGetter
  = StandardAssemblerInfoGetter
       -- ^ Interrogate the standard system assembler
  | DarwinClangAssemblerInfoGetter
       -- ^ If running on Darwin, return `Clang`; otherwise
       -- interrogate the standard system assembler.


-- | Names a function that generates code and writes the results to a
--  file, of this type:
--
--  >    Logger
--  > -> DynFlags
--  > -> Module -- ^ module being compiled
--  > -> ModLocation
--  > -> FilePath -- ^ Where to write output
--  > -> Set UnitId -- ^ dependencies
--  > -> Stream IO RawCmmGroup a -- results from `StgToCmm`
--  > -> IO a
--
-- The functions so named are defined in "GHC.Driver.CodeOutput".
--
-- We expect one function per back end—or more precisely, one function
-- for each back end that writes code to a file.  (The interpreter
-- does not write to files; its output lives only in memory.)

data DefunctionalizedCodeOutput
  = NcgCodeOutput
  | ViaCCodeOutput
  | LlvmCodeOutput


-- | Names a function that tells the driver what should happen after
-- assembly code is written.  This might include running a C compiler,
-- running LLVM, running an assembler, or various similar activities.
-- The function named normally has this type:
--
-- >    TPipelineClass TPhase m
-- > => PipeEnv
-- > -> HscEnv
-- > -> Maybe ModLocation
-- > -> FilePath
-- > -> m (Maybe FilePath)
--
-- The functions so named are defined in "GHC.Driver.Pipeline".

data DefunctionalizedPostHscPipeline
  = NcgPostHscPipeline
  | ViaCPostHscPipeline
  | LlvmPostHscPipeline
  | NoPostHscPipeline -- ^ After code generation, nothing else need happen.

-- | Names a function that tells the driver what command-line options
-- to include when invoking a C compiler.  It's meant for @-D@ options that
-- define symbols for the C preprocessor.  Because the exact symbols
-- defined might depend on versions of tools located in the file
-- system (/cough/ LLVM /cough/), the function requires an `IO` action.
-- The function named has this type:
--
-- > Logger -> DynFlags -> IO [String]

data DefunctionalizedCDefs
  = NoCDefs   -- ^ No additional command-line options are needed

  | LlvmCDefs -- ^ Return command-line options that tell GHC about the
              -- LLVM version.

---------------------------------------------------------------------------------



-- | An informal description of the back end, for use in
-- issuing warning messages /only/.  If code depends on
-- what's in the string, you deserve what happens to you.
backendDescription :: Backend -> String
backendDescription (Named NCG) = "native code generator"
backendDescription (Named LLVM) = "LLVM"
backendDescription (Named ViaC) = "compiling via C"
backendDescription (Named Interpreter) = "byte-code interpreter"
backendDescription (Named NoBackend) = "no code generated"

-- | This flag tells the compiler driver whether the back
-- end will write files: interface files and object files.
-- It is typically true for "real" back ends that generate
-- code into the filesystem.  (That means, not the interpreter.)
backendWritesFiles :: Backend -> Bool
backendWritesFiles (Named NCG) = True
backendWritesFiles (Named LLVM) = True
backendWritesFiles (Named ViaC) = True
backendWritesFiles (Named Interpreter) = False
backendWritesFiles (Named NoBackend) = False

-- | When the back end does write files, this value tells
-- the compiler in what manner of file the output should go:
-- temporary, persistent, or specific.
backendPipelineOutput :: Backend -> PipelineOutput
backendPipelineOutput (Named NCG) = Persistent
backendPipelineOutput (Named LLVM) = Persistent
backendPipelineOutput (Named ViaC) = Persistent
backendPipelineOutput (Named Interpreter) = NoOutputFile
backendPipelineOutput (Named NoBackend) = NoOutputFile

-- | This flag tells the driver whether the back end can
-- reuse code (bytecode or object code) that has been
-- loaded dynamically.  Likely true only of the interpreter.
backendCanReuseLoadedCode :: Backend -> Bool
backendCanReuseLoadedCode (Named NCG) = False
backendCanReuseLoadedCode (Named LLVM) = False
backendCanReuseLoadedCode (Named ViaC) = False
backendCanReuseLoadedCode (Named Interpreter) = True
backendCanReuseLoadedCode (Named NoBackend) = False

-- | It is is true of every back end except @-fno-code@
-- that it "generates code."  Surprisingly, this property
-- influences the driver in a ton of ways.  Some examples:
--
--   * If the back end does not generate code, then the
--     driver needs to turn on code generation for
--     Template Haskell (because that code needs to be
--     generated and run at compile time).
--
--   * If the back end does not generate code, then the
--     driver does not need to deal with an output file.
--
--   * If the back end /does/ generated code, then the
--     driver supports `HscRecomp`.  If not, recompilation
--     does not need a linkable (and is automatically up
--     to date).
--
backendGeneratesCode :: Backend -> Bool
backendGeneratesCode (Named NCG) = True
backendGeneratesCode (Named LLVM) = True
backendGeneratesCode (Named ViaC) = True
backendGeneratesCode (Named Interpreter) = True
backendGeneratesCode (Named NoBackend) = False

-- | When set, this flag turns on interface writing for
-- Backpack.  It should probably be the same as
-- `backendGeneratesCode`, but it is kept distinct for
-- reasons described in Note [-fno-code mode].
backendSupportsInterfaceWriting :: Backend -> Bool
backendSupportsInterfaceWriting (Named NCG) = True
backendSupportsInterfaceWriting (Named LLVM) = True
backendSupportsInterfaceWriting (Named ViaC) = True
backendSupportsInterfaceWriting (Named Interpreter) = True
backendSupportsInterfaceWriting (Named NoBackend) = False

-- | When preparing code for this back end, the type
-- checker should pay attention to SPECIALISE pragmas.  If
-- this flag is `False`, then the type checker ignores
-- SPECIALISE pragmas (for imported things?).
backendRespectsSpecialise :: Backend -> Bool
backendRespectsSpecialise (Named NCG) = True
backendRespectsSpecialise (Named LLVM) = True
backendRespectsSpecialise (Named ViaC) = True
backendRespectsSpecialise (Named Interpreter) = False
backendRespectsSpecialise (Named NoBackend) = False

-- | This back end wants the `mi_globals` field of a
-- `ModIface` to be populated (with the top-level bindings
-- of the original source).  True for the interpreter, and
-- also true for "no backend", which is used by Haddock.
-- (After typechecking a module, Haddock wants access to
-- the module's `GlobalRdrEnv`.)
backendWantsGlobalBindings :: Backend -> Bool
backendWantsGlobalBindings (Named NCG) = False
backendWantsGlobalBindings (Named LLVM) = False
backendWantsGlobalBindings (Named ViaC) = False
backendWantsGlobalBindings (Named Interpreter) = True
backendWantsGlobalBindings (Named NoBackend) = True

-- | The back end targets a technology that implements
-- `switch` natively.  (For example, LLVM or C.) Therefore
-- it is not necessary for GHC to ccompile a Cmm `Switch`
-- form into a decision tree with jump tables at the
-- leaves.
backendHasNativeSwitch :: Backend -> Bool
backendHasNativeSwitch (Named NCG) = False
backendHasNativeSwitch (Named LLVM) = True
backendHasNativeSwitch (Named ViaC) = True
backendHasNativeSwitch (Named Interpreter) = False
backendHasNativeSwitch (Named NoBackend) = False

-- | As noted in the documentation for
-- `PrimitiveImplementation`, certain primitives have
-- multiple implementations, depending on the capabilities
-- of the back end.  This field signals to module
-- "GHC.StgToCmm.Prim" what implementations to use with
-- this back end.
backendPrimitiveImplementation :: Backend -> PrimitiveImplementation
backendPrimitiveImplementation (Named NCG) = NcgPrimitives
backendPrimitiveImplementation (Named LLVM) = LlvmPrimitives
backendPrimitiveImplementation (Named ViaC) = GenericPrimitives
backendPrimitiveImplementation (Named Interpreter) = GenericPrimitives
backendPrimitiveImplementation (Named NoBackend) = GenericPrimitives

-- | When this value is `IsValid`, the back end is
-- compatible with vector instructions.  When it is
-- `NotValid`, it carries a message that is shown to
-- users.
backendSimdValidity :: Backend -> Validity' String
backendSimdValidity (Named NCG) = NotValid $ unlines ["SIMD vector instructions require the LLVM back-end.","Please use -fllvm."]
backendSimdValidity (Named LLVM) = IsValid
backendSimdValidity (Named ViaC) = NotValid $ unlines ["SIMD vector instructions require the LLVM back-end.","Please use -fllvm."]
backendSimdValidity (Named Interpreter) = NotValid $ unlines ["SIMD vector instructions require the LLVM back-end.","Please use -fllvm."]
backendSimdValidity (Named NoBackend) = NotValid $ unlines ["SIMD vector instructions require the LLVM back-end.","Please use -fllvm."]

-- | This flag says whether the back end supports large
-- binary blobs.  See Note [Embedding large binary blobs]
-- in "GHC.CmmToAsm.Ppr".
backendSupportsEmbeddedBlobs :: Backend -> Bool
backendSupportsEmbeddedBlobs (Named NCG) = True
backendSupportsEmbeddedBlobs (Named LLVM) = False
backendSupportsEmbeddedBlobs (Named ViaC) = False
backendSupportsEmbeddedBlobs (Named Interpreter) = False
backendSupportsEmbeddedBlobs (Named NoBackend) = False

-- | This flag tells the compiler driver that the back end
-- does not support every target platform; it supports
-- only platforms that claim NCG support.  (It's set only
-- for the native code generator.)  Crufty.  If the driver
-- tries to use the native code generator /without/
-- platform support, the driver fails over to the LLVM
-- back end.
backendNeedsPlatformNcgSupport :: Backend -> Bool
backendNeedsPlatformNcgSupport (Named NCG) = True
backendNeedsPlatformNcgSupport (Named LLVM) = False
backendNeedsPlatformNcgSupport (Named ViaC) = False
backendNeedsPlatformNcgSupport (Named Interpreter) = False
backendNeedsPlatformNcgSupport (Named NoBackend) = False

-- | This flag is set if the back end can generate code
-- for proc points.  If the flag is not set, then a Cmm
-- pass needs to split proc points (that is, turn each
-- proc point into a standalone procedure).
backendSupportsUnsplitProcPoints :: Backend -> Bool
backendSupportsUnsplitProcPoints (Named NCG) = True
backendSupportsUnsplitProcPoints (Named LLVM) = False
backendSupportsUnsplitProcPoints (Named ViaC) = False
backendSupportsUnsplitProcPoints (Named Interpreter) = False
backendSupportsUnsplitProcPoints (Named NoBackend) = False

-- | This flag guides the driver in resolving issues about
-- API support on the target platform. If the flag is set,
-- then these things are true:
--
--    * When the target platform supports /only/ an unregisterised API,
--      this backend can be replaced with compilation via C.
--
--    * When the target does /not/ support an unregisterised API,
--      this back end can replace compilation via C.
--
backendSwappableWithViaC :: Backend -> Bool
backendSwappableWithViaC (Named NCG) = True
backendSwappableWithViaC (Named LLVM) = True
backendSwappableWithViaC (Named ViaC) = False
backendSwappableWithViaC (Named Interpreter) = False
backendSwappableWithViaC (Named NoBackend) = False

-- | This flag is true if the back end works *only* with
-- the unregisterised ABI.
backendUnregisterisedAbiOnly :: Backend -> Bool
backendUnregisterisedAbiOnly (Named NCG) = False
backendUnregisterisedAbiOnly (Named LLVM) = False
backendUnregisterisedAbiOnly (Named ViaC) = True
backendUnregisterisedAbiOnly (Named Interpreter) = False
backendUnregisterisedAbiOnly (Named NoBackend) = False

-- | This flag is set if the back end generates C code in
-- a @.hc@ file.  The flag lets the compiler driver know
-- if the command-line flag @-C@ is meaningful.
backendGeneratesHc :: Backend -> Bool
backendGeneratesHc (Named NCG) = False
backendGeneratesHc (Named LLVM) = False
backendGeneratesHc (Named ViaC) = True
backendGeneratesHc (Named Interpreter) = False
backendGeneratesHc (Named NoBackend) = False

-- | This flag says whether SPT (static pointer table)
-- entries will be inserted dynamically if needed.  If
-- this flag is `False`, then "GHC.Iface.Tidy" should emit C
-- stubs that initialize the SPT entries.
backendSptIsDynamic :: Backend -> Bool
backendSptIsDynamic (Named NCG) = False
backendSptIsDynamic (Named LLVM) = False
backendSptIsDynamic (Named ViaC) = False
backendSptIsDynamic (Named Interpreter) = True
backendSptIsDynamic (Named NoBackend) = False

-- | If this flag is set, then "GHC.HsToCore.Coverage"
-- inserts `Breakpoint` ticks.  Used only for the
-- interpreter.
backendWantsBreakpointTicks :: Backend -> Bool
backendWantsBreakpointTicks (Named NCG) = False
backendWantsBreakpointTicks (Named LLVM) = False
backendWantsBreakpointTicks (Named ViaC) = False
backendWantsBreakpointTicks (Named Interpreter) = True
backendWantsBreakpointTicks (Named NoBackend) = False

-- | If this flag is set, then the driver forces the
-- optimization level to 0, issuing a warning message if
-- the command line requested a higher optimization level.
backendForcesOptimization0 :: Backend -> Bool
backendForcesOptimization0 (Named NCG) = False
backendForcesOptimization0 (Named LLVM) = False
backendForcesOptimization0 (Named ViaC) = False
backendForcesOptimization0 (Named Interpreter) = True
backendForcesOptimization0 (Named NoBackend) = False

-- | I don't understand exactly how this works.  But if
-- this flag is set *and* another condition is met, then
-- @ghc/Main.hs@ will alter the `DynFlags` so that all the
-- `hostFullWays` are asked for.  It is set only for the interpreter.
backendNeedsFullWays :: Backend -> Bool
backendNeedsFullWays (Named NCG) = False
backendNeedsFullWays (Named LLVM) = False
backendNeedsFullWays (Named ViaC) = False
backendNeedsFullWays (Named Interpreter) = True
backendNeedsFullWays (Named NoBackend) = False

-- | This flag is also special for the interpreter: if a
-- message about a module needs to be shown, do we know
-- anything special about where the module came from?  The
-- Boolean argument is a `recomp` flag.
backendSpecialModuleSource :: Backend -> Bool -> Maybe String
backendSpecialModuleSource (Named NCG) = const Nothing
backendSpecialModuleSource (Named LLVM) = const Nothing
backendSpecialModuleSource (Named ViaC) = const Nothing
backendSpecialModuleSource (Named Interpreter) = \b -> if b then Just "interpreted" else Nothing
backendSpecialModuleSource (Named NoBackend) = const (Just "nothing")

-- | This flag says whether the back end supports Haskell
-- Program Coverage (HPC). If not, the compiler driver
-- will ignore the `-fhpc` option (and will issue a
-- warning message if it is used).
backendSupportsHpc :: Backend -> Bool
backendSupportsHpc (Named NCG) = True
backendSupportsHpc (Named LLVM) = True
backendSupportsHpc (Named ViaC) = True
backendSupportsHpc (Named Interpreter) = False
backendSupportsHpc (Named NoBackend) = True

-- | This flag says whether the back end supports foreign
-- import of C functions.  ("Supports" means "does not
-- barf on," so @-fno-code@ supports foreign C imports.)
backendSupportsCImport :: Backend -> Bool
backendSupportsCImport (Named NCG) = True
backendSupportsCImport (Named LLVM) = True
backendSupportsCImport (Named ViaC) = True
backendSupportsCImport (Named Interpreter) = True
backendSupportsCImport (Named NoBackend) = True

-- | This flag says whether the back end supports foreign
-- export of Haskell functions to C.
backendSupportsCExport :: Backend -> Bool
backendSupportsCExport (Named NCG) = True
backendSupportsCExport (Named LLVM) = True
backendSupportsCExport (Named ViaC) = True
backendSupportsCExport (Named Interpreter) = False
backendSupportsCExport (Named NoBackend) = True

-- | This (defunctionalized) function runs the assembler
-- used on the code that is written by this back end.  A
-- program determined by a combination of back end,
-- `DynFlags`, and `Platform` is run with the given
-- `Option`s.
--
-- The function's type is
-- @
-- Logger -> DynFlags -> Platform -> [Option] -> IO ()
-- @
--
-- This field is usually defaulted.
backendAssemblerProg :: Backend -> DefunctionalizedAssemblerProg
backendAssemblerProg (Named NCG) = StandardAssemblerProg
backendAssemblerProg (Named LLVM) = DarwinClangAssemblerProg
backendAssemblerProg (Named ViaC) = StandardAssemblerProg
backendAssemblerProg (Named Interpreter) = StandardAssemblerProg
backendAssemblerProg (Named NoBackend) = StandardAssemblerProg

-- | This (defunctionalized) function is used to retrieve
-- an enumeration value that characterizes the C/assembler
-- part of a toolchain.  The function caches the info in a
-- mutable variable that is part of the `DynFlags`.
--
-- The function's type is
-- @
-- Logger -> DynFlags -> Platform -> IO CompilerInfo
-- @
--
-- This field is usually defaulted.
backendAssemblerInfoGetter :: Backend -> DefunctionalizedAssemblerInfoGetter
backendAssemblerInfoGetter (Named NCG) = StandardAssemblerInfoGetter
backendAssemblerInfoGetter (Named LLVM) = DarwinClangAssemblerInfoGetter
backendAssemblerInfoGetter (Named ViaC) = StandardAssemblerInfoGetter
backendAssemblerInfoGetter (Named Interpreter) = StandardAssemblerInfoGetter
backendAssemblerInfoGetter (Named NoBackend) = StandardAssemblerInfoGetter

-- | When using this back end, it may be necessary or
-- advisable to pass some `-D` options to a C compiler.
-- This (defunctionalized) function produces those
-- options, if any.  An IO action may be necessary in
-- order to interrogate external tools about what version
-- they are, for example.
--
-- The function's type is
-- @
-- Logger -> DynFlags -> IO [String]
-- @
--
-- This field is usually defaulted.
backendCDefs :: Backend -> DefunctionalizedCDefs
backendCDefs (Named NCG) = NoCDefs
backendCDefs (Named LLVM) = LlvmCDefs
backendCDefs (Named ViaC) = NoCDefs
backendCDefs (Named Interpreter) = NoCDefs
backendCDefs (Named NoBackend) = NoCDefs

-- | This (defunctionalized) function generates code and
-- writes it to a file.  The type of the function is
--
-- >    Logger
-- > -> DynFlags
-- > -> Module -- ^ module being compiled
-- > -> ModLocation
-- > -> FilePath -- ^ Where to write output
-- > -> Set UnitId -- ^ dependencies
-- > -> Stream IO RawCmmGroup a -- results from `StgToCmm`
-- > -> IO a
backendCodeOutput :: Backend -> DefunctionalizedCodeOutput
backendCodeOutput (Named NCG) = NcgCodeOutput
backendCodeOutput (Named LLVM) = LlvmCodeOutput
backendCodeOutput (Named ViaC) = ViaCCodeOutput
backendCodeOutput (Named Interpreter) = panic "backendCodeOutput: interpreterBackend"
backendCodeOutput (Named NoBackend) = panic "backendCodeOutput: noBackend"

-- | This (defunctionalized) function tells the compiler
-- driver what else has to be run after code output.
-- The type of the function is
--
-- >
-- >    TPipelineClass TPhase m
-- > => PipeEnv
-- > -> HscEnv
-- > -> Maybe ModLocation
-- > -> FilePath
-- > -> m (Maybe FilePath)
backendPostHscPipeline :: Backend -> DefunctionalizedPostHscPipeline
backendPostHscPipeline (Named NCG) = NcgPostHscPipeline
backendPostHscPipeline (Named LLVM) = LlvmPostHscPipeline
backendPostHscPipeline (Named ViaC) = ViaCPostHscPipeline
backendPostHscPipeline (Named Interpreter) = NoPostHscPipeline
backendPostHscPipeline (Named NoBackend) = NoPostHscPipeline

-- | Somewhere in the compiler driver, when compiling
-- Haskell source (as opposed to a boot file or a sig
-- file), it needs to know what to do with the code that
-- the `backendCodeOutput` writes to a file.  This `Phase`
-- value gives instructions like "run the C compiler",
-- "run the assembler," or "run the LLVM Optimizer."
backendNormalSuccessorPhase :: Backend -> Phase
backendNormalSuccessorPhase (Named NCG) = As False
backendNormalSuccessorPhase (Named LLVM) = LlvmOpt
backendNormalSuccessorPhase (Named ViaC) = HCc
backendNormalSuccessorPhase (Named Interpreter) = StopLn
backendNormalSuccessorPhase (Named NoBackend) = StopLn

-- | Name of the back end, if any.  Used to migrate legacy
-- clients of the GHC API.  Code within the GHC source
-- tree should not refer to a back end's name.
backendName :: Backend -> BackendName
backendName (Named NCG) = NCG
backendName (Named LLVM) = LLVM
backendName (Named ViaC) = ViaC
backendName (Named Interpreter) = Interpreter
backendName (Named NoBackend) = NoBackend



-- | A list of all back ends.  They are ordered as we wish them to
-- appear when they are enumerated in error messages.

allBackends :: [Backend]
allBackends = [ ncgBackend
              , llvmBackend
              , viaCBackend
              , interpreterBackend
              , noBackend
              ]

-- | When foreign C import or export is invalid, the carried value
-- enumerates the /valid/ back ends.

backendValidityOfCImport, backendValidityOfCExport :: Backend -> Validity' [Backend]

backendValidityOfCImport backend =
    if backendSupportsCImport backend then
        IsValid
    else
        NotValid $ filter backendSupportsCImport allBackends

backendValidityOfCExport backend =
    if backendSupportsCExport backend then
        IsValid
    else
        NotValid $ filter backendSupportsCExport allBackends




{-
Note [Backend Defunctionalization]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I had hoped to include code-output and post-hsc-pipeline functions
directly in the `Backend` record itself.  But this agenda was derailed
by mutual recursion in the types:

  - A `DynFlags` record contains a back end of type `Backend`.
  - A `Backend` contains a code-output function.
  - A code-output function takes Cmm as input.
  - Cmm can include a `CLabel`.
  - A `CLabel` can have elements that are defined in
    `GHC.Driver.Session`, where `DynFlags` is defined.

There is also a nasty issue in the values: a typical post-backend
pipeline function both depends on and is depended upon by functions in
"GHC.Driver.Pipeline".

I'm cut the Gordian not by removing the function types from the
`Backend` record.  Instead, a function is represented by its /name/.
This representation is an example of an old trick called
/defunctionalization/, which has been used in both compilers and
interpreters for languages with first-class, nested functions.  Here,
a function's name is a value of an algebraic data type.  For example,
a code-output function is represented by a value of this type:

    data DefunctionalizedCodeOutput
      = NcgCodeOutput
      | ViaCCodeOutput
      | LlvmCodeOutput

Such a function may be applied in one of two ways:

  - In this particular example, a `case` expression in module
    "GHC.Driver.CodeOutput" discriminates on the value and calls the
    designated function.

  - In another example, a function of type `DefunctionalizedCDefs` is
    applied by calling function `applyCDefs`, which has this type:

    @
    applyCDefs :: DefunctionalizedCDefs -> Logger -> DynFlags -> IO [String]
    @

    Function `applyCDefs` is defined in module "GHC.Driver.Pipeline.Execute".

I don't love this solution, but defunctionalization is a standard
thing, and it makes the meanings of the enumeration values clear.

Anyone defining a new back end will need to extend both the
`DefunctionalizedCodeOutput` type and the corresponding apply
function.
-}