Misc enhancements to LTO:
[oota-llvm.git] / tools / lto / LTOPostIPODriver.cpp
1 //===---------- LTOPostIPODriver.h - PostIPO Driver -----------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 //  This file defines the PostIPODriver class which is the driver for Post-IPO
9 // compilation.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Analysis/AliasAnalysis.h"
14 #include "llvm/IR/DataLayout.h"
15 #include "llvm/PassManager.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/FormattedStream.h"
18 #include "llvm/Support/Program.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/Target/TargetMachine.h"
21 #include "llvm/Transforms/ObjCARC.h"
22 #include "LTOPartition.h"
23 #include "LTOPostIPODriver.h"
24
25 using namespace llvm;
26 using namespace lto;
27
28 // /////////////////////////////////////////////////////////////////////////////
29 //
30 //      Declare all variants of Post-IPO drivers
31 //
32 // /////////////////////////////////////////////////////////////////////////////
33 //
34 namespace {
35   /// \breif Base class for all driver variants.
36   ///
37   class PostIPODrvBaseImpl {
38   public:
39     PostIPODrvBaseImpl(TargetMachine *Targ, IPOPartMgr &IPM, IPOFileMgr &IFM,
40                        bool ToMergeObjs):
41       PartMgr(IPM), FileMgr(IFM), MergedObjFile(0), Target(Targ),
42       MergeObjs(ToMergeObjs) {}
43   
44     virtual ~PostIPODrvBaseImpl() {};
45   
46     IPOPartMgr &getPartitionMgr() { return PartMgr; }
47     IPOFileMgr &getFileMgr() { return FileMgr; }
48
49     // Implement the PostIPODriver::getSingleObjFile()
50     virtual IPOFile *getSingleObjFile() const = 0;
51
52     bool IsToMergeObj() const { return MergeObjs; }
53   
54     virtual bool Compile(std::string &ErrMsg) = 0;
55   
56   protected:
57     // Populate post-IPO scalar optimization pass manager
58     bool PopulatePostIPOOptPM(PassManager &PM);
59
60     // Populate post-IPO machine-specific CodeGen pass manager
61     bool PopulateCodeGenPM(PassManager &PM, formatted_raw_ostream &OutFile,
62                            std::string &Err);
63
64   protected:
65     IPOPartMgr &PartMgr;
66     IPOFileMgr &FileMgr;
67     IPOFile *MergedObjFile;
68     TargetMachine *Target;
69     bool MergeObjs;
70   };
71   
72   /// \breif PostIPO driver for the compiling the entire program without
73   ///    partition.
74   class PostIPODrvSerial : public PostIPODrvBaseImpl {
75   public:
76     PostIPODrvSerial(TargetMachine *T, IPOPartMgr &IPM, IPOFileMgr &IFM,
77                         bool ToMergeObjs) :
78       PostIPODrvBaseImpl(T, IPM, IFM, ToMergeObjs) {}
79
80     virtual bool Compile(std::string &ErrMsg);
81     virtual IPOFile *getSingleObjFile() const;
82
83   private:
84     Module *getModule() const { return (*PartMgr.begin())->getModule(); }
85   };
86 }
87
88 // ////////////////////////////////////////////////////////////////////////////
89 //
90 //              Implemetation of PostIPODriver
91 //
92 // ////////////////////////////////////////////////////////////////////////////
93 //
94 PostIPODriver::PostIPODriver(VariantTy V, TargetMachine *TM, IPOPartMgr &IPM,
95                              IPOFileMgr &IFM, bool ToMergeObjs) {
96   if (V == PIDV_SERIAL) 
97     DrvImpl = new PostIPODrvSerial(TM, IPM, IFM, ToMergeObjs);
98   else 
99     assert(false && "TBD");
100 }
101
102 bool PostIPODriver::Compile(std::string &ErrMsg) {
103   PostIPODrvBaseImpl *P = static_cast<PostIPODrvBaseImpl *>(DrvImpl);
104   return P->Compile(ErrMsg);
105 }
106
107 IPOFile *PostIPODriver::getSingleObjFile() const {
108   PostIPODrvBaseImpl *P = static_cast<PostIPODrvBaseImpl *>(DrvImpl);
109   return P->getSingleObjFile();
110 }
111
112 // ////////////////////////////////////////////////////////////////////////////
113 //
114 //              Implemetation of PostIPODrvBaseImpl
115 //
116 // ////////////////////////////////////////////////////////////////////////////
117 //
118 bool PostIPODrvBaseImpl::PopulatePostIPOOptPM(PassManager &PM) {
119   (void)PM;
120   return true;
121 }
122
123 bool PostIPODrvBaseImpl::PopulateCodeGenPM(PassManager &PM,
124                                            formatted_raw_ostream &OutFile,
125                                            std::string &Err) {
126   PM.add(new DataLayout(*Target->getDataLayout()));
127   Target->addAnalysisPasses(PM);
128
129   // If the bitcode files contain ARC code and were compiled with optimization,
130   // the ObjCARCContractPass must be run, so do it unconditionally here.
131   PM.add(createObjCARCContractPass());
132
133   if (Target->addPassesToEmitFile(PM, OutFile,
134                                   TargetMachine::CGFT_ObjectFile)) {
135     Err = "target file type not supported";
136     return false;
137   }
138   return true;
139 }
140
141 // ////////////////////////////////////////////////////////////////////////////
142 //
143 //              Implemetation of PostIPODrvSerial
144 //
145 // ////////////////////////////////////////////////////////////////////////////
146 //
147 bool PostIPODrvSerial::Compile(std::string &ErrMsg) {
148   Module *M = getModule();
149
150   // Step 1: Run the post-IPO scalar optimizations
151   {
152     PassManager SoptPM;
153     PopulatePostIPOOptPM(SoptPM);
154     SoptPM.run(*M);
155   }
156
157   // Step 2: Run the post-IPO machine-specific code-generation passes
158   {
159     IPOFile &Obj = (*PartMgr.begin())->getObjFile();
160     raw_fd_ostream ros(Obj.getPath().c_str(), Obj.getLastErrStr(),
161                        sys::fs::F_Binary);
162     formatted_raw_ostream OutFile(ros);
163     
164     PassManager CodGenPM;
165     if (!PopulateCodeGenPM(CodGenPM, OutFile, ErrMsg)) {
166       ErrMsg += Obj.getLastErrStr();
167       return false;
168     }
169
170     CodGenPM.run(*M);
171   }
172
173   return true;
174 }
175
176 IPOFile *PostIPODrvSerial::getSingleObjFile() const {
177   assert(!MergedObjFile && "No need to *merge* a single object file");
178   IPOPartition *P = *PartMgr.begin();
179   return &P->getObjFile();
180 }