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