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