1 //===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
28 using namespace clang
;
32 class BackendConsumer
: public ASTConsumer
{
35 const CodeGenOptions
&CodeGenOpts
;
36 const TargetOptions
&TargetOpts
;
37 llvm::raw_ostream
*AsmOutStream
;
40 Timer LLVMIRGeneration
;
42 llvm::OwningPtr
<CodeGenerator
> Gen
;
44 llvm::OwningPtr
<llvm::Module
> TheModule
;
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
,
54 CodeGenOpts(compopts
),
55 TargetOpts(targetopts
),
57 LLVMIRGeneration("LLVM IR Generation Time"),
58 Gen(CreateLLVMCodeGen(Diags
, infile
, compopts
, C
)) {
59 llvm::TimePassesIsEnabled
= TimePasses
;
62 llvm::Module
*takeModule() { return TheModule
.take(); }
64 virtual void Initialize(ASTContext
&Ctx
) {
67 if (llvm::TimePassesIsEnabled
)
68 LLVMIRGeneration
.startTimer();
72 TheModule
.reset(Gen
->GetModule());
74 if (llvm::TimePassesIsEnabled
)
75 LLVMIRGeneration
.stopTimer();
78 virtual void HandleTopLevelDecl(DeclGroupRef D
) {
79 PrettyStackTraceDecl
CrashInfo(*D
.begin(), SourceLocation(),
80 Context
->getSourceManager(),
81 "LLVM IR generation of declaration");
83 if (llvm::TimePassesIsEnabled
)
84 LLVMIRGeneration
.startTimer();
86 Gen
->HandleTopLevelDecl(D
);
88 if (llvm::TimePassesIsEnabled
)
89 LLVMIRGeneration
.stopTimer();
92 virtual void HandleTranslationUnit(ASTContext
&C
) {
94 PrettyStackTraceString
CrashInfo("Per-file LLVM IR generation");
95 if (llvm::TimePassesIsEnabled
)
96 LLVMIRGeneration
.startTimer();
98 Gen
->HandleTranslationUnit(C
);
100 if (llvm::TimePassesIsEnabled
)
101 LLVMIRGeneration
.stopTimer();
104 // Silently ignore if we weren't initialized for some reason.
108 // Make sure IR generation is happy with the module. This is released by
109 // the module provider.
110 Module
*M
= Gen
->ReleaseModule();
112 // The module has been released by IR gen on failures, do not double
118 assert(TheModule
.get() == M
&&
119 "Unexpected module change during IR generation");
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);
129 EmitBackendOutput(Diags
, CodeGenOpts
, TargetOpts
,
130 TheModule
.get(), Action
, AsmOutStream
);
132 Ctx
.setInlineAsmDiagnosticHandler(OldHandler
, OldContext
);
135 virtual void HandleTagDeclDefinition(TagDecl
*D
) {
136 PrettyStackTraceDecl
CrashInfo(D
, SourceLocation(),
137 Context
->getSourceManager(),
138 "LLVM IR generation of declaration");
139 Gen
->HandleTagDeclDefinition(D
);
142 virtual void CompleteTentativeDefinition(VarDecl
*D
) {
143 Gen
->CompleteTentativeDefinition(D
);
146 virtual void HandleVTable(CXXRecordDecl
*RD
, bool DefinitionRequired
) {
147 Gen
->HandleVTable(RD
, DefinitionRequired
);
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
);
156 void InlineAsmDiagHandler2(const llvm::SMDiagnostic
&,
157 SourceLocation LocCookie
);
161 /// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr
162 /// buffer to be a valid FullSourceLoc.
163 static 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();
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()));
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
);
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
);
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.
192 void 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.
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);
202 // If the SMDiagnostic has an inline asm source location, translate it.
204 if (D
.getLoc() != SMLoc())
205 Loc
= ConvertBackendLocation(D
, Context
->getSourceManager());
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
211 if (LocCookie
.isValid()) {
212 Diags
.Report(LocCookie
, diag::err_fe_inline_asm
).AddString(Message
);
214 if (D
.getLoc().isValid())
215 Diags
.Report(Loc
, diag::note_fe_inline_asm_here
);
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
222 Diags
.Report(Loc
, diag::err_fe_inline_asm
).AddString(Message
);
227 CodeGenAction::CodeGenAction(unsigned _Act
, LLVMContext
*_VMContext
)
228 : Act(_Act
), VMContext(_VMContext
? _VMContext
: new LLVMContext
),
229 OwnsVMContext(!_VMContext
) {}
231 CodeGenAction::~CodeGenAction() {
237 bool CodeGenAction::hasIRSupport() const { return true; }
239 void CodeGenAction::EndSourceFileAction() {
240 // If the consumer creation failed, do nothing.
241 if (!getCompilerInstance().hasASTConsumer())
244 // Steal the module from the consumer.
245 TheModule
.reset(BEConsumer
->takeModule());
248 llvm::Module
*CodeGenAction::takeModule() {
249 return TheModule
.take();
252 llvm::LLVMContext
*CodeGenAction::takeLLVMContext() {
253 OwnsVMContext
= false;
257 static raw_ostream
*GetOutputStream(CompilerInstance
&CI
,
258 llvm::StringRef InFile
,
259 BackendAction Action
) {
261 case Backend_EmitAssembly
:
262 return CI
.createDefaultOutputFile(false, InFile
, "s");
264 return CI
.createDefaultOutputFile(false, InFile
, "ll");
266 return CI
.createDefaultOutputFile(true, InFile
, "bc");
267 case Backend_EmitNothing
:
269 case Backend_EmitMCNull
:
270 case Backend_EmitObj
:
271 return CI
.createDefaultOutputFile(true, InFile
, "o");
274 assert(0 && "Invalid action!");
278 ASTConsumer
*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
)
286 new BackendConsumer(BA
, CI
.getDiagnostics(),
287 CI
.getCodeGenOpts(), CI
.getTargetOpts(),
288 CI
.getFrontendOpts().ShowTimers
, InFile
, OS
.take(),
293 void 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
)
303 SourceManager
&SM
= CI
.getSourceManager();
304 const llvm::MemoryBuffer
*MainFile
= SM
.getBuffer(SM
.getMainFileID(),
309 // FIXME: This is stupid, IRReader shouldn't take ownership.
310 llvm::MemoryBuffer
*MainFileCopy
=
311 llvm::MemoryBuffer::getMemBufferCopy(MainFile
->getBuffer(),
312 getCurrentFile().c_str());
314 llvm::SMDiagnostic Err
;
315 TheModule
.reset(ParseIR(MainFileCopy
, Err
, *VMContext
));
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);
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: "))
327 unsigned DiagID
= CI
.getDiagnostics().getCustomDiagID(Diagnostic::Error
,
330 CI
.getDiagnostics().Report(Loc
, DiagID
);
334 EmitBackendOutput(CI
.getDiagnostics(), CI
.getCodeGenOpts(),
335 CI
.getTargetOpts(), TheModule
.get(),
340 // Otherwise follow the normal AST path.
341 this->ASTFrontendAction::ExecuteAction();
346 EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext
*_VMContext
)
347 : CodeGenAction(Backend_EmitAssembly
, _VMContext
) {}
349 EmitBCAction::EmitBCAction(llvm::LLVMContext
*_VMContext
)
350 : CodeGenAction(Backend_EmitBC
, _VMContext
) {}
352 EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext
*_VMContext
)
353 : CodeGenAction(Backend_EmitLL
, _VMContext
) {}
355 EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext
*_VMContext
)
356 : CodeGenAction(Backend_EmitNothing
, _VMContext
) {}
358 EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext
*_VMContext
)
359 : CodeGenAction(Backend_EmitMCNull
, _VMContext
) {}
361 EmitObjAction::EmitObjAction(llvm::LLVMContext
*_VMContext
)
362 : CodeGenAction(Backend_EmitObj
, _VMContext
) {}