CodeGenAction.cpp revision ff8f9ec8336c62b5e3504e2a394f4b25c0cb1963
1//===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/CodeGen/CodeGenAction.h"
11#include "clang/Basic/FileManager.h"
12#include "clang/Basic/SourceManager.h"
13#include "clang/Basic/TargetInfo.h"
14#include "clang/AST/ASTConsumer.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/DeclGroup.h"
17#include "clang/CodeGen/BackendUtil.h"
18#include "clang/CodeGen/ModuleBuilder.h"
19#include "clang/Frontend/CompilerInstance.h"
20#include "clang/Frontend/FrontendDiagnostic.h"
21#include "llvm/LLVMContext.h"
22#include "llvm/Linker.h"
23#include "llvm/Module.h"
24#include "llvm/Pass.h"
25#include "llvm/ADT/OwningPtr.h"
26#include "llvm/Bitcode/ReaderWriter.h"
27#include "llvm/Support/IRReader.h"
28#include "llvm/Support/MemoryBuffer.h"
29#include "llvm/Support/SourceMgr.h"
30#include "llvm/Support/Timer.h"
31using namespace clang;
32using namespace llvm;
33
34namespace clang {
35  class BackendConsumer : public ASTConsumer {
36    virtual void anchor();
37    DiagnosticsEngine &Diags;
38    BackendAction Action;
39    const CodeGenOptions &CodeGenOpts;
40    const TargetOptions &TargetOpts;
41    const LangOptions &LangOpts;
42    raw_ostream *AsmOutStream;
43    ASTContext *Context;
44
45    Timer LLVMIRGeneration;
46
47    llvm::OwningPtr<CodeGenerator> Gen;
48
49    llvm::OwningPtr<llvm::Module> TheModule, LinkModule;
50
51  public:
52    BackendConsumer(BackendAction action, DiagnosticsEngine &_Diags,
53                    const CodeGenOptions &compopts,
54                    const TargetOptions &targetopts,
55                    const LangOptions &langopts,
56                    bool TimePasses,
57                    const std::string &infile,
58                    llvm::Module *LinkModule,
59                    raw_ostream *OS,
60                    LLVMContext &C) :
61      Diags(_Diags),
62      Action(action),
63      CodeGenOpts(compopts),
64      TargetOpts(targetopts),
65      LangOpts(langopts),
66      AsmOutStream(OS),
67      LLVMIRGeneration("LLVM IR Generation Time"),
68      Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)),
69      LinkModule(LinkModule) {
70      llvm::TimePassesIsEnabled = TimePasses;
71    }
72
73    llvm::Module *takeModule() { return TheModule.take(); }
74    llvm::Module *takeLinkModule() { return LinkModule.take(); }
75
76    virtual void Initialize(ASTContext &Ctx) {
77      Context = &Ctx;
78
79      if (llvm::TimePassesIsEnabled)
80        LLVMIRGeneration.startTimer();
81
82      Gen->Initialize(Ctx);
83
84      TheModule.reset(Gen->GetModule());
85
86      if (llvm::TimePassesIsEnabled)
87        LLVMIRGeneration.stopTimer();
88    }
89
90    virtual bool HandleTopLevelDecl(DeclGroupRef D) {
91      PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
92                                     Context->getSourceManager(),
93                                     "LLVM IR generation of declaration");
94
95      if (llvm::TimePassesIsEnabled)
96        LLVMIRGeneration.startTimer();
97
98      Gen->HandleTopLevelDecl(D);
99
100      if (llvm::TimePassesIsEnabled)
101        LLVMIRGeneration.stopTimer();
102
103      return true;
104    }
105
106    virtual void HandleTranslationUnit(ASTContext &C) {
107      {
108        PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
109        if (llvm::TimePassesIsEnabled)
110          LLVMIRGeneration.startTimer();
111
112        Gen->HandleTranslationUnit(C);
113
114        if (llvm::TimePassesIsEnabled)
115          LLVMIRGeneration.stopTimer();
116      }
117
118      // Silently ignore if we weren't initialized for some reason.
119      if (!TheModule)
120        return;
121
122      // Make sure IR generation is happy with the module. This is released by
123      // the module provider.
124      llvm::Module *M = Gen->ReleaseModule();
125      if (!M) {
126        // The module has been released by IR gen on failures, do not double
127        // free.
128        TheModule.take();
129        return;
130      }
131
132      assert(TheModule.get() == M &&
133             "Unexpected module change during IR generation");
134
135      // Link LinkModule into this module if present, preserving its validity.
136      if (LinkModule) {
137        std::string ErrorMsg;
138        if (Linker::LinkModules(M, LinkModule.get(), Linker::PreserveSource,
139                                &ErrorMsg)) {
140          Diags.Report(diag::err_fe_cannot_link_module)
141            << LinkModule->getModuleIdentifier() << ErrorMsg;
142          return;
143        }
144      }
145
146      // Install an inline asm handler so that diagnostics get printed through
147      // our diagnostics hooks.
148      LLVMContext &Ctx = TheModule->getContext();
149      LLVMContext::InlineAsmDiagHandlerTy OldHandler =
150        Ctx.getInlineAsmDiagnosticHandler();
151      void *OldContext = Ctx.getInlineAsmDiagnosticContext();
152      Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
153
154      EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
155                        TheModule.get(), Action, AsmOutStream);
156
157      Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
158    }
159
160    virtual void HandleTagDeclDefinition(TagDecl *D) {
161      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
162                                     Context->getSourceManager(),
163                                     "LLVM IR generation of declaration");
164      Gen->HandleTagDeclDefinition(D);
165    }
166
167    virtual void CompleteTentativeDefinition(VarDecl *D) {
168      Gen->CompleteTentativeDefinition(D);
169    }
170
171    virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {
172      Gen->HandleVTable(RD, DefinitionRequired);
173    }
174
175    static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
176                                     unsigned LocCookie) {
177      SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
178      ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
179    }
180
181    void InlineAsmDiagHandler2(const llvm::SMDiagnostic &,
182                               SourceLocation LocCookie);
183  };
184
185  void BackendConsumer::anchor() {}
186}
187
188/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr
189/// buffer to be a valid FullSourceLoc.
190static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D,
191                                            SourceManager &CSM) {
192  // Get both the clang and llvm source managers.  The location is relative to
193  // a memory buffer that the LLVM Source Manager is handling, we need to add
194  // a copy to the Clang source manager.
195  const llvm::SourceMgr &LSM = *D.getSourceMgr();
196
197  // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr
198  // already owns its one and clang::SourceManager wants to own its one.
199  const MemoryBuffer *LBuf =
200  LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
201
202  // Create the copy and transfer ownership to clang::SourceManager.
203  llvm::MemoryBuffer *CBuf =
204  llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
205                                       LBuf->getBufferIdentifier());
206  FileID FID = CSM.createFileIDForMemBuffer(CBuf);
207
208  // Translate the offset into the file.
209  unsigned Offset = D.getLoc().getPointer()  - LBuf->getBufferStart();
210  SourceLocation NewLoc =
211  CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset);
212  return FullSourceLoc(NewLoc, CSM);
213}
214
215
216/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an
217/// error parsing inline asm.  The SMDiagnostic indicates the error relative to
218/// the temporary memory buffer that the inline asm parser has set up.
219void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
220                                            SourceLocation LocCookie) {
221  // There are a couple of different kinds of errors we could get here.  First,
222  // we re-format the SMDiagnostic in terms of a clang diagnostic.
223  StringRef Message = D.getMessage();
224
225  // If the SMDiagnostic has an inline asm source location, translate it.
226  FullSourceLoc Loc;
227  if (D.getLoc() != SMLoc())
228    Loc = ConvertBackendLocation(D, Context->getSourceManager());
229
230  // FIXME: Propagate ranges up as well.
231
232  // If this problem has clang-level source location information, report the
233  // issue as being an error in the source with a note showing the instantiated
234  // code.
235  if (LocCookie.isValid()) {
236    Diags.Report(LocCookie, diag::err_fe_inline_asm).AddString(Message);
237
238    if (D.getLoc().isValid()) {
239      DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
240      // Convert the SMDiagnostic ranges into SourceRange and attach them
241      // to the diagnostic.
242      for (unsigned i = 0, e = D.getRanges().size(); i != e; ++i) {
243        std::pair<unsigned, unsigned> Range = D.getRanges()[i];
244        unsigned Column = D.getColumnNo();
245        B << SourceRange(Loc.getLocWithOffset(Range.first - Column),
246                         Loc.getLocWithOffset(Range.second - Column));
247      }
248    }
249    return;
250  }
251
252  // Otherwise, report the backend error as occurring in the generated .s file.
253  // If Loc is invalid, we still need to report the error, it just gets no
254  // location info.
255  Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message);
256}
257
258//
259
260CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
261  : Act(_Act), LinkModule(0),
262    VMContext(_VMContext ? _VMContext : new LLVMContext),
263    OwnsVMContext(!_VMContext) {}
264
265CodeGenAction::~CodeGenAction() {
266  TheModule.reset();
267  if (OwnsVMContext)
268    delete VMContext;
269}
270
271bool CodeGenAction::hasIRSupport() const { return true; }
272
273void CodeGenAction::EndSourceFileAction() {
274  // If the consumer creation failed, do nothing.
275  if (!getCompilerInstance().hasASTConsumer())
276    return;
277
278  // If we were given a link module, release consumer's ownership of it.
279  if (LinkModule)
280    BEConsumer->takeLinkModule();
281
282  // Steal the module from the consumer.
283  TheModule.reset(BEConsumer->takeModule());
284}
285
286llvm::Module *CodeGenAction::takeModule() {
287  return TheModule.take();
288}
289
290llvm::LLVMContext *CodeGenAction::takeLLVMContext() {
291  OwnsVMContext = false;
292  return VMContext;
293}
294
295static raw_ostream *GetOutputStream(CompilerInstance &CI,
296                                    StringRef InFile,
297                                    BackendAction Action) {
298  switch (Action) {
299  case Backend_EmitAssembly:
300    return CI.createDefaultOutputFile(false, InFile, "s");
301  case Backend_EmitLL:
302    return CI.createDefaultOutputFile(false, InFile, "ll");
303  case Backend_EmitBC:
304    return CI.createDefaultOutputFile(true, InFile, "bc");
305  case Backend_EmitNothing:
306    return 0;
307  case Backend_EmitMCNull:
308  case Backend_EmitObj:
309    return CI.createDefaultOutputFile(true, InFile, "o");
310  }
311
312  llvm_unreachable("Invalid action!");
313}
314
315ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
316                                              StringRef InFile) {
317  BackendAction BA = static_cast<BackendAction>(Act);
318  llvm::OwningPtr<raw_ostream> OS(GetOutputStream(CI, InFile, BA));
319  if (BA != Backend_EmitNothing && !OS)
320    return 0;
321
322  llvm::Module *LinkModuleToUse = LinkModule;
323
324  // If we were not given a link module, and the user requested that one be
325  // loaded from bitcode, do so now.
326  const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile;
327  if (!LinkModuleToUse && !LinkBCFile.empty()) {
328    std::string ErrorStr;
329
330    llvm::MemoryBuffer *BCBuf =
331      CI.getFileManager().getBufferForFile(LinkBCFile, &ErrorStr);
332    if (!BCBuf) {
333      CI.getDiagnostics().Report(diag::err_cannot_open_file)
334        << LinkBCFile << ErrorStr;
335      return 0;
336    }
337
338    LinkModuleToUse = getLazyBitcodeModule(BCBuf, *VMContext, &ErrorStr);
339    if (!LinkModuleToUse) {
340      CI.getDiagnostics().Report(diag::err_cannot_open_file)
341        << LinkBCFile << ErrorStr;
342      return 0;
343    }
344  }
345
346  BEConsumer =
347      new BackendConsumer(BA, CI.getDiagnostics(),
348                          CI.getCodeGenOpts(), CI.getTargetOpts(),
349                          CI.getLangOpts(),
350                          CI.getFrontendOpts().ShowTimers, InFile,
351                          LinkModuleToUse, OS.take(), *VMContext);
352  return BEConsumer;
353}
354
355void CodeGenAction::ExecuteAction() {
356  // If this is an IR file, we have to treat it specially.
357  if (getCurrentFileKind() == IK_LLVM_IR) {
358    BackendAction BA = static_cast<BackendAction>(Act);
359    CompilerInstance &CI = getCompilerInstance();
360    raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA);
361    if (BA != Backend_EmitNothing && !OS)
362      return;
363
364    bool Invalid;
365    SourceManager &SM = CI.getSourceManager();
366    const llvm::MemoryBuffer *MainFile = SM.getBuffer(SM.getMainFileID(),
367                                                      &Invalid);
368    if (Invalid)
369      return;
370
371    // FIXME: This is stupid, IRReader shouldn't take ownership.
372    llvm::MemoryBuffer *MainFileCopy =
373      llvm::MemoryBuffer::getMemBufferCopy(MainFile->getBuffer(),
374                                           getCurrentFile().c_str());
375
376    llvm::SMDiagnostic Err;
377    TheModule.reset(ParseIR(MainFileCopy, Err, *VMContext));
378    if (!TheModule) {
379      // Translate from the diagnostic info to the SourceManager location.
380      SourceLocation Loc = SM.translateFileLineCol(
381        SM.getFileEntryForID(SM.getMainFileID()), Err.getLineNo(),
382        Err.getColumnNo() + 1);
383
384      // Get a custom diagnostic for the error. We strip off a leading
385      // diagnostic code if there is one.
386      StringRef Msg = Err.getMessage();
387      if (Msg.startswith("error: "))
388        Msg = Msg.substr(7);
389      unsigned DiagID = CI.getDiagnostics().getCustomDiagID(
390          DiagnosticsEngine::Error, Msg);
391
392      CI.getDiagnostics().Report(Loc, DiagID);
393      return;
394    }
395
396    EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(),
397                      CI.getTargetOpts(), CI.getLangOpts(),
398                      TheModule.get(),
399                      BA, OS);
400    return;
401  }
402
403  // Otherwise follow the normal AST path.
404  this->ASTFrontendAction::ExecuteAction();
405}
406
407//
408
409void EmitAssemblyAction::anchor() { }
410EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext)
411  : CodeGenAction(Backend_EmitAssembly, _VMContext) {}
412
413void EmitBCAction::anchor() { }
414EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext)
415  : CodeGenAction(Backend_EmitBC, _VMContext) {}
416
417void EmitLLVMAction::anchor() { }
418EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext)
419  : CodeGenAction(Backend_EmitLL, _VMContext) {}
420
421void EmitLLVMOnlyAction::anchor() { }
422EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext)
423  : CodeGenAction(Backend_EmitNothing, _VMContext) {}
424
425void EmitCodeGenOnlyAction::anchor() { }
426EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext)
427  : CodeGenAction(Backend_EmitMCNull, _VMContext) {}
428
429void EmitObjAction::anchor() { }
430EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext)
431  : CodeGenAction(Backend_EmitObj, _VMContext) {}
432