summaryrefslogtreecommitdiff
path: root/ghc/compiler/main/CodeOutput.lhs
blob: ec316beb8a47f4656aced82ec06dcf9f70478361 (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
%
% (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
%
\section{Code output phase}

\begin{code}
module CodeOutput( codeOutput ) where

#include "HsVersions.h"

#if ! OMIT_NATIVE_CODEGEN
import AsmCodeGen	( nativeCodeGen )
#endif

import AbsCSyn		( AbstractC, absCNop )
import PprAbsC		( dumpRealC, writeRealC )
import UniqSupply	( UniqSupply )
import Module		( Module, moduleString )
import CmdLineOpts
import Maybes		( maybeToBool )
import ErrUtils		( doIfSet, dumpIfSet )
import Outputable
import IO		( IOMode(..), hPutStr, hClose, openFile, stderr	)
\end{code}


\begin{code}
codeOutput :: Module
	   -> SDoc 		-- C stubs for foreign exported functions
	   -> SDoc		-- Header file prototype for foreign exported functions
	   -> AbstractC		-- Compiled abstract C
	   -> UniqSupply
	   -> IO ()
codeOutput mod_name c_code h_code flat_abstractC ncg_uniqs
  = -- You can have C (c_output) or assembly-language (ncg_output),
    -- but not both.  [Allowing for both gives a space leak on
    -- flat_abstractC.  WDP 94/10]

    dumpIfSet opt_D_dump_asm "Asm code" ncg_output_d 	>>
    doOutput opt_ProduceS ncg_output_w 			>>

    dumpIfSet opt_D_dump_foreign "Foreign export header file" stub_h_output_d >>
    outputHStub opt_ProduceExportHStubs stub_h_output_w	>>

    dumpIfSet opt_D_dump_foreign "Foreign export stubs" stub_c_output_d >>
    outputCStub mod_name opt_ProduceExportCStubs stub_c_output_w	>>

    dumpIfSet opt_D_dump_realC "Real C" c_output_d 	>>
    doOutput opt_ProduceC c_output_w

  where
    (flat_absC_c, flat_absC_ncg) =
	 case (maybeToBool opt_ProduceC || opt_D_dump_realC,
	       maybeToBool opt_ProduceS || opt_D_dump_asm) of
	     (True,  False) -> (flat_abstractC, absCNop)
	     (False, True)  -> (absCNop, flat_abstractC)
	     (False, False) -> (absCNop, absCNop)
	     (True,  True)  -> error "ERROR: Can't do both .hc and .s at the same time"

    -- C stubs for "foreign export"ed functions.
    stub_c_output_d = pprCode CStyle c_code
    stub_c_output_w = showSDoc stub_c_output_d

    -- Header file protos for "foreign export"ed functions.
    stub_h_output_d = pprCode CStyle h_code
    stub_h_output_w = showSDoc stub_h_output_d

    c_output_d = dumpRealC flat_absC_c
    c_output_w = (\ f -> writeRealC f flat_absC_c)

	-- Native code generation done here!
#if OMIT_NATIVE_CODEGEN
    ncg_output_d = error "*** GHC not built with a native-code generator ***"
    ncg_output_w = ncg_output_d
#else
    ncg_output_d = nativeCodeGen flat_absC_ncg ncg_uniqs
    ncg_output_w = (\ f -> printForAsm f ncg_output_d)
#endif


    -- don't use doOutput for dumping the f. export stubs
    -- since it is more than likely that the stubs file will
    -- turn out to be empty, in which case no file should be created.
outputCStub mod_name switch ""
  = return ()
outputCStub mod_name switch doc_str
  = case switch of
	  Nothing    -> return ()
	  Just fname -> writeFile fname ("#include \"Rts.h\"\n#include \"RtsAPI.h\"\n"++rest)
	    where
	     rest = "#include "++show (moduleString mod_name ++ "_stub.h") ++ '\n':doc_str
	      
outputHStub switch ""
  = return ()
outputHStub switch doc_str
  = case switch of
	  Nothing    -> return ()
	  Just fname -> writeFile fname ("#include \"Rts.h\"\n"++doc_str)

doOutput switch io_action
  = case switch of
	  Nothing    -> return ()
	  Just fname ->
	    openFile fname WriteMode	>>= \ handle ->
	    io_action handle		>>
	    hClose handle
\end{code}