summaryrefslogtreecommitdiff
path: root/tools/lto/LTOPostIPODriver.cpp
blob: 2bb833a5cafd6c2bc44ee165ab8f58afc6a871e7 (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
//===---------- LTOPostIPODriver.h - PostIPO Driver -----------------------===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the PostIPODriver class which is the driver for Post-IPO
// compilation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/PassManager.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/ObjCARC.h"
#include "LTOPartition.h"
#include "LTOPostIPODriver.h"

using namespace llvm;
using namespace lto;

// /////////////////////////////////////////////////////////////////////////////
//
//      Declare all variants of Post-IPO drivers
//
// /////////////////////////////////////////////////////////////////////////////
//
namespace {
  /// \breif Base class for all driver variants.
  ///
  class PostIPODrvBaseImpl {
  public:
    PostIPODrvBaseImpl(TargetMachine *Targ, IPOPartMgr &IPM, IPOFileMgr &IFM,
                       bool ToMergeObjs):
      PartMgr(IPM), FileMgr(IFM), MergedObjFile(0), Target(Targ),
      MergeObjs(ToMergeObjs) {}
  
    virtual ~PostIPODrvBaseImpl() {};
  
    IPOPartMgr &getPartitionMgr() { return PartMgr; }
    IPOFileMgr &getFileMgr() { return FileMgr; }

    // Implement the PostIPODriver::getSingleObjFile()
    virtual IPOFile *getSingleObjFile() const = 0;

    bool IsToMergeObj() const { return MergeObjs; }
  
    virtual bool Compile(std::string &ErrMsg) = 0;
  
  protected:
    // Populate post-IPO scalar optimization pass manager
    bool PopulatePostIPOOptPM(PassManager &PM);

    // Populate post-IPO machine-specific CodeGen pass manager
    bool PopulateCodeGenPM(PassManager &PM, formatted_raw_ostream &OutFile,
                           std::string &Err);

  protected:
    IPOPartMgr &PartMgr;
    IPOFileMgr &FileMgr;
    IPOFile *MergedObjFile;
    TargetMachine *Target;
    bool MergeObjs;
  };
  
  /// \breif PostIPO driver for the compiling the entire program without
  ///    partition.
  class PostIPODrvSerial : public PostIPODrvBaseImpl {
  public:
    PostIPODrvSerial(TargetMachine *T, IPOPartMgr &IPM, IPOFileMgr &IFM,
                        bool ToMergeObjs) :
      PostIPODrvBaseImpl(T, IPM, IFM, ToMergeObjs) {}

    virtual bool Compile(std::string &ErrMsg);
    virtual IPOFile *getSingleObjFile() const;

  private:
    Module *getModule() const { return (*PartMgr.begin())->getModule(); }
  };
}

// ////////////////////////////////////////////////////////////////////////////
//
//              Implemetation of PostIPODriver
//
// ////////////////////////////////////////////////////////////////////////////
//
PostIPODriver::PostIPODriver(VariantTy V, TargetMachine *TM, IPOPartMgr &IPM,
                             IPOFileMgr &IFM, bool ToMergeObjs) {
  if (V == PIDV_SERIAL) 
    DrvImpl = new PostIPODrvSerial(TM, IPM, IFM, ToMergeObjs);
  else 
    assert(false && "TBD");
}

bool PostIPODriver::Compile(std::string &ErrMsg) {
  PostIPODrvBaseImpl *P = static_cast<PostIPODrvBaseImpl *>(DrvImpl);
  return P->Compile(ErrMsg);
}

IPOFile *PostIPODriver::getSingleObjFile() const {
  PostIPODrvBaseImpl *P = static_cast<PostIPODrvBaseImpl *>(DrvImpl);
  return P->getSingleObjFile();
}

// ////////////////////////////////////////////////////////////////////////////
//
//              Implemetation of PostIPODrvBaseImpl
//
// ////////////////////////////////////////////////////////////////////////////
//
bool PostIPODrvBaseImpl::PopulatePostIPOOptPM(PassManager &PM) {
  (void)PM;
  return true;
}

bool PostIPODrvBaseImpl::PopulateCodeGenPM(PassManager &PM,
                                           formatted_raw_ostream &OutFile,
                                           std::string &Err) {
  PM.add(new DataLayout(*Target->getDataLayout()));
  Target->addAnalysisPasses(PM);

  // If the bitcode files contain ARC code and were compiled with optimization,
  // the ObjCARCContractPass must be run, so do it unconditionally here.
  PM.add(createObjCARCContractPass());

  if (Target->addPassesToEmitFile(PM, OutFile,
                                  TargetMachine::CGFT_ObjectFile)) {
    Err = "target file type not supported";
    return false;
  }
  return true;
}

// ////////////////////////////////////////////////////////////////////////////
//
//              Implemetation of PostIPODrvSerial
//
// ////////////////////////////////////////////////////////////////////////////
//
bool PostIPODrvSerial::Compile(std::string &ErrMsg) {
  Module *M = getModule();

  // Step 1: Run the post-IPO scalar optimizations
  {
    PassManager SoptPM;
    PopulatePostIPOOptPM(SoptPM);
    SoptPM.run(*M);
  }

  // Step 2: Run the post-IPO machine-specific code-generation passes
  {
    IPOFile &Obj = (*PartMgr.begin())->getObjFile();
    raw_fd_ostream ros(Obj.getPath().c_str(), Obj.getLastErrStr(),
                       sys::fs::F_Binary);
    formatted_raw_ostream OutFile(ros);
    
    PassManager CodGenPM;
    if (!PopulateCodeGenPM(CodGenPM, OutFile, ErrMsg)) {
      ErrMsg += Obj.getLastErrStr();
      return false;
    }

    CodGenPM.run(*M);
  }

  return true;
}

IPOFile *PostIPODrvSerial::getSingleObjFile() const {
  assert(!MergedObjFile && "No need to *merge* a single object file");
  IPOPartition *P = *PartMgr.begin();
  return &P->getObjFile();
}