1210008Srdivacky//===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// 2210008Srdivacky// 3210008Srdivacky// The LLVM Compiler Infrastructure 4210008Srdivacky// 5210008Srdivacky// This file is distributed under the University of Illinois Open Source 6210008Srdivacky// License. See LICENSE.TXT for details. 7210008Srdivacky// 8210008Srdivacky//===----------------------------------------------------------------------===// 9210008Srdivacky 10210008Srdivacky#include "clang/CodeGen/CodeGenAction.h" 11249423Sdim#include "clang/AST/ASTConsumer.h" 12249423Sdim#include "clang/AST/ASTContext.h" 13249423Sdim#include "clang/AST/DeclGroup.h" 14234353Sdim#include "clang/Basic/FileManager.h" 15210008Srdivacky#include "clang/Basic/SourceManager.h" 16210008Srdivacky#include "clang/Basic/TargetInfo.h" 17210008Srdivacky#include "clang/CodeGen/BackendUtil.h" 18210008Srdivacky#include "clang/CodeGen/ModuleBuilder.h" 19210008Srdivacky#include "clang/Frontend/CompilerInstance.h" 20210008Srdivacky#include "clang/Frontend/FrontendDiagnostic.h" 21210008Srdivacky#include "llvm/ADT/OwningPtr.h" 22234353Sdim#include "llvm/ADT/SmallString.h" 23234353Sdim#include "llvm/Bitcode/ReaderWriter.h" 24249423Sdim#include "llvm/IR/LLVMContext.h" 25249423Sdim#include "llvm/IR/Module.h" 26249423Sdim#include "llvm/IRReader/IRReader.h" 27249423Sdim#include "llvm/Linker.h" 28249423Sdim#include "llvm/Pass.h" 29210008Srdivacky#include "llvm/Support/MemoryBuffer.h" 30210008Srdivacky#include "llvm/Support/SourceMgr.h" 31210008Srdivacky#include "llvm/Support/Timer.h" 32210008Srdivackyusing namespace clang; 33210008Srdivackyusing namespace llvm; 34210008Srdivacky 35218893Sdimnamespace clang { 36210008Srdivacky class BackendConsumer : public ASTConsumer { 37234353Sdim virtual void anchor(); 38226633Sdim DiagnosticsEngine &Diags; 39210008Srdivacky BackendAction Action; 40210008Srdivacky const CodeGenOptions &CodeGenOpts; 41210008Srdivacky const TargetOptions &TargetOpts; 42224145Sdim const LangOptions &LangOpts; 43226633Sdim raw_ostream *AsmOutStream; 44210008Srdivacky ASTContext *Context; 45210008Srdivacky 46210008Srdivacky Timer LLVMIRGeneration; 47210008Srdivacky 48234353Sdim OwningPtr<CodeGenerator> Gen; 49210008Srdivacky 50234353Sdim OwningPtr<llvm::Module> TheModule, LinkModule; 51210008Srdivacky 52210008Srdivacky public: 53226633Sdim BackendConsumer(BackendAction action, DiagnosticsEngine &_Diags, 54210008Srdivacky const CodeGenOptions &compopts, 55224145Sdim const TargetOptions &targetopts, 56224145Sdim const LangOptions &langopts, 57224145Sdim bool TimePasses, 58234353Sdim const std::string &infile, 59234353Sdim llvm::Module *LinkModule, 60234353Sdim raw_ostream *OS, 61210008Srdivacky LLVMContext &C) : 62210008Srdivacky Diags(_Diags), 63210008Srdivacky Action(action), 64210008Srdivacky CodeGenOpts(compopts), 65210008Srdivacky TargetOpts(targetopts), 66224145Sdim LangOpts(langopts), 67210008Srdivacky AsmOutStream(OS), 68243830Sdim Context(), 69210008Srdivacky LLVMIRGeneration("LLVM IR Generation Time"), 70249423Sdim Gen(CreateLLVMCodeGen(Diags, infile, compopts, targetopts, C)), 71243830Sdim LinkModule(LinkModule) 72243830Sdim { 73210008Srdivacky llvm::TimePassesIsEnabled = TimePasses; 74210008Srdivacky } 75210008Srdivacky 76210008Srdivacky llvm::Module *takeModule() { return TheModule.take(); } 77234353Sdim llvm::Module *takeLinkModule() { return LinkModule.take(); } 78210008Srdivacky 79234353Sdim virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { 80234353Sdim Gen->HandleCXXStaticMemberVarInstantiation(VD); 81234353Sdim } 82234353Sdim 83210008Srdivacky virtual void Initialize(ASTContext &Ctx) { 84210008Srdivacky Context = &Ctx; 85210008Srdivacky 86210008Srdivacky if (llvm::TimePassesIsEnabled) 87210008Srdivacky LLVMIRGeneration.startTimer(); 88210008Srdivacky 89210008Srdivacky Gen->Initialize(Ctx); 90210008Srdivacky 91210008Srdivacky TheModule.reset(Gen->GetModule()); 92210008Srdivacky 93210008Srdivacky if (llvm::TimePassesIsEnabled) 94210008Srdivacky LLVMIRGeneration.stopTimer(); 95210008Srdivacky } 96210008Srdivacky 97234353Sdim virtual bool HandleTopLevelDecl(DeclGroupRef D) { 98210008Srdivacky PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), 99210008Srdivacky Context->getSourceManager(), 100210008Srdivacky "LLVM IR generation of declaration"); 101210008Srdivacky 102210008Srdivacky if (llvm::TimePassesIsEnabled) 103210008Srdivacky LLVMIRGeneration.startTimer(); 104210008Srdivacky 105210008Srdivacky Gen->HandleTopLevelDecl(D); 106210008Srdivacky 107210008Srdivacky if (llvm::TimePassesIsEnabled) 108210008Srdivacky LLVMIRGeneration.stopTimer(); 109234353Sdim 110234353Sdim return true; 111210008Srdivacky } 112210008Srdivacky 113210008Srdivacky virtual void HandleTranslationUnit(ASTContext &C) { 114210008Srdivacky { 115210008Srdivacky PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); 116210008Srdivacky if (llvm::TimePassesIsEnabled) 117210008Srdivacky LLVMIRGeneration.startTimer(); 118210008Srdivacky 119210008Srdivacky Gen->HandleTranslationUnit(C); 120210008Srdivacky 121210008Srdivacky if (llvm::TimePassesIsEnabled) 122210008Srdivacky LLVMIRGeneration.stopTimer(); 123210008Srdivacky } 124210008Srdivacky 125210008Srdivacky // Silently ignore if we weren't initialized for some reason. 126210008Srdivacky if (!TheModule) 127210008Srdivacky return; 128210008Srdivacky 129210008Srdivacky // Make sure IR generation is happy with the module. This is released by 130210008Srdivacky // the module provider. 131234353Sdim llvm::Module *M = Gen->ReleaseModule(); 132210008Srdivacky if (!M) { 133210008Srdivacky // The module has been released by IR gen on failures, do not double 134210008Srdivacky // free. 135210008Srdivacky TheModule.take(); 136210008Srdivacky return; 137210008Srdivacky } 138210008Srdivacky 139210008Srdivacky assert(TheModule.get() == M && 140210008Srdivacky "Unexpected module change during IR generation"); 141210008Srdivacky 142234353Sdim // Link LinkModule into this module if present, preserving its validity. 143234353Sdim if (LinkModule) { 144234353Sdim std::string ErrorMsg; 145234353Sdim if (Linker::LinkModules(M, LinkModule.get(), Linker::PreserveSource, 146234353Sdim &ErrorMsg)) { 147234353Sdim Diags.Report(diag::err_fe_cannot_link_module) 148234353Sdim << LinkModule->getModuleIdentifier() << ErrorMsg; 149234353Sdim return; 150234353Sdim } 151234353Sdim } 152234353Sdim 153210008Srdivacky // Install an inline asm handler so that diagnostics get printed through 154210008Srdivacky // our diagnostics hooks. 155210008Srdivacky LLVMContext &Ctx = TheModule->getContext(); 156218893Sdim LLVMContext::InlineAsmDiagHandlerTy OldHandler = 157218893Sdim Ctx.getInlineAsmDiagnosticHandler(); 158210008Srdivacky void *OldContext = Ctx.getInlineAsmDiagnosticContext(); 159218893Sdim Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); 160210008Srdivacky 161224145Sdim EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, 162210008Srdivacky TheModule.get(), Action, AsmOutStream); 163210008Srdivacky 164210008Srdivacky Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); 165210008Srdivacky } 166210008Srdivacky 167210008Srdivacky virtual void HandleTagDeclDefinition(TagDecl *D) { 168210008Srdivacky PrettyStackTraceDecl CrashInfo(D, SourceLocation(), 169210008Srdivacky Context->getSourceManager(), 170210008Srdivacky "LLVM IR generation of declaration"); 171210008Srdivacky Gen->HandleTagDeclDefinition(D); 172210008Srdivacky } 173210008Srdivacky 174210008Srdivacky virtual void CompleteTentativeDefinition(VarDecl *D) { 175210008Srdivacky Gen->CompleteTentativeDefinition(D); 176210008Srdivacky } 177210008Srdivacky 178210008Srdivacky virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { 179210008Srdivacky Gen->HandleVTable(RD, DefinitionRequired); 180210008Srdivacky } 181210008Srdivacky 182210008Srdivacky static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, 183210008Srdivacky unsigned LocCookie) { 184210008Srdivacky SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); 185210008Srdivacky ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); 186210008Srdivacky } 187210008Srdivacky 188210008Srdivacky void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, 189210008Srdivacky SourceLocation LocCookie); 190210008Srdivacky }; 191234353Sdim 192234353Sdim void BackendConsumer::anchor() {} 193210008Srdivacky} 194210008Srdivacky 195210008Srdivacky/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr 196210008Srdivacky/// buffer to be a valid FullSourceLoc. 197210008Srdivackystatic FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, 198210008Srdivacky SourceManager &CSM) { 199210008Srdivacky // Get both the clang and llvm source managers. The location is relative to 200210008Srdivacky // a memory buffer that the LLVM Source Manager is handling, we need to add 201210008Srdivacky // a copy to the Clang source manager. 202210008Srdivacky const llvm::SourceMgr &LSM = *D.getSourceMgr(); 203210008Srdivacky 204210008Srdivacky // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr 205210008Srdivacky // already owns its one and clang::SourceManager wants to own its one. 206210008Srdivacky const MemoryBuffer *LBuf = 207210008Srdivacky LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); 208210008Srdivacky 209210008Srdivacky // Create the copy and transfer ownership to clang::SourceManager. 210210008Srdivacky llvm::MemoryBuffer *CBuf = 211210008Srdivacky llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), 212210008Srdivacky LBuf->getBufferIdentifier()); 213210008Srdivacky FileID FID = CSM.createFileIDForMemBuffer(CBuf); 214210008Srdivacky 215210008Srdivacky // Translate the offset into the file. 216210008Srdivacky unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); 217210008Srdivacky SourceLocation NewLoc = 218226633Sdim CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); 219210008Srdivacky return FullSourceLoc(NewLoc, CSM); 220210008Srdivacky} 221210008Srdivacky 222210008Srdivacky 223210008Srdivacky/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an 224210008Srdivacky/// error parsing inline asm. The SMDiagnostic indicates the error relative to 225210008Srdivacky/// the temporary memory buffer that the inline asm parser has set up. 226210008Srdivackyvoid BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, 227210008Srdivacky SourceLocation LocCookie) { 228210008Srdivacky // There are a couple of different kinds of errors we could get here. First, 229210008Srdivacky // we re-format the SMDiagnostic in terms of a clang diagnostic. 230210008Srdivacky 231210008Srdivacky // Strip "error: " off the start of the message string. 232226633Sdim StringRef Message = D.getMessage(); 233210008Srdivacky if (Message.startswith("error: ")) 234210008Srdivacky Message = Message.substr(7); 235210008Srdivacky 236210008Srdivacky // If the SMDiagnostic has an inline asm source location, translate it. 237210008Srdivacky FullSourceLoc Loc; 238210008Srdivacky if (D.getLoc() != SMLoc()) 239210008Srdivacky Loc = ConvertBackendLocation(D, Context->getSourceManager()); 240210008Srdivacky 241210008Srdivacky 242210008Srdivacky // If this problem has clang-level source location information, report the 243210008Srdivacky // issue as being an error in the source with a note showing the instantiated 244210008Srdivacky // code. 245210008Srdivacky if (LocCookie.isValid()) { 246218893Sdim Diags.Report(LocCookie, diag::err_fe_inline_asm).AddString(Message); 247210008Srdivacky 248234353Sdim if (D.getLoc().isValid()) { 249234353Sdim DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); 250234353Sdim // Convert the SMDiagnostic ranges into SourceRange and attach them 251234353Sdim // to the diagnostic. 252234353Sdim for (unsigned i = 0, e = D.getRanges().size(); i != e; ++i) { 253234353Sdim std::pair<unsigned, unsigned> Range = D.getRanges()[i]; 254234353Sdim unsigned Column = D.getColumnNo(); 255234353Sdim B << SourceRange(Loc.getLocWithOffset(Range.first - Column), 256234353Sdim Loc.getLocWithOffset(Range.second - Column)); 257234353Sdim } 258234353Sdim } 259210008Srdivacky return; 260210008Srdivacky } 261210008Srdivacky 262221345Sdim // Otherwise, report the backend error as occurring in the generated .s file. 263210008Srdivacky // If Loc is invalid, we still need to report the error, it just gets no 264210008Srdivacky // location info. 265210008Srdivacky Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message); 266210008Srdivacky} 267210008Srdivacky 268210008Srdivacky// 269210008Srdivacky 270218893SdimCodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) 271234353Sdim : Act(_Act), LinkModule(0), 272234353Sdim VMContext(_VMContext ? _VMContext : new LLVMContext), 273218893Sdim OwnsVMContext(!_VMContext) {} 274210008Srdivacky 275218893SdimCodeGenAction::~CodeGenAction() { 276218893Sdim TheModule.reset(); 277218893Sdim if (OwnsVMContext) 278218893Sdim delete VMContext; 279218893Sdim} 280210008Srdivacky 281210008Srdivackybool CodeGenAction::hasIRSupport() const { return true; } 282210008Srdivacky 283210008Srdivackyvoid CodeGenAction::EndSourceFileAction() { 284210008Srdivacky // If the consumer creation failed, do nothing. 285210008Srdivacky if (!getCompilerInstance().hasASTConsumer()) 286210008Srdivacky return; 287210008Srdivacky 288234353Sdim // If we were given a link module, release consumer's ownership of it. 289234353Sdim if (LinkModule) 290234353Sdim BEConsumer->takeLinkModule(); 291234353Sdim 292210008Srdivacky // Steal the module from the consumer. 293218893Sdim TheModule.reset(BEConsumer->takeModule()); 294210008Srdivacky} 295210008Srdivacky 296210008Srdivackyllvm::Module *CodeGenAction::takeModule() { 297210008Srdivacky return TheModule.take(); 298210008Srdivacky} 299210008Srdivacky 300218893Sdimllvm::LLVMContext *CodeGenAction::takeLLVMContext() { 301218893Sdim OwnsVMContext = false; 302218893Sdim return VMContext; 303218893Sdim} 304218893Sdim 305210008Srdivackystatic raw_ostream *GetOutputStream(CompilerInstance &CI, 306226633Sdim StringRef InFile, 307210008Srdivacky BackendAction Action) { 308210008Srdivacky switch (Action) { 309210008Srdivacky case Backend_EmitAssembly: 310210008Srdivacky return CI.createDefaultOutputFile(false, InFile, "s"); 311210008Srdivacky case Backend_EmitLL: 312210008Srdivacky return CI.createDefaultOutputFile(false, InFile, "ll"); 313210008Srdivacky case Backend_EmitBC: 314210008Srdivacky return CI.createDefaultOutputFile(true, InFile, "bc"); 315210008Srdivacky case Backend_EmitNothing: 316210008Srdivacky return 0; 317210008Srdivacky case Backend_EmitMCNull: 318210008Srdivacky case Backend_EmitObj: 319210008Srdivacky return CI.createDefaultOutputFile(true, InFile, "o"); 320210008Srdivacky } 321210008Srdivacky 322226633Sdim llvm_unreachable("Invalid action!"); 323210008Srdivacky} 324210008Srdivacky 325210008SrdivackyASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, 326226633Sdim StringRef InFile) { 327210008Srdivacky BackendAction BA = static_cast<BackendAction>(Act); 328234353Sdim OwningPtr<raw_ostream> OS(GetOutputStream(CI, InFile, BA)); 329210008Srdivacky if (BA != Backend_EmitNothing && !OS) 330210008Srdivacky return 0; 331210008Srdivacky 332234353Sdim llvm::Module *LinkModuleToUse = LinkModule; 333234353Sdim 334234353Sdim // If we were not given a link module, and the user requested that one be 335234353Sdim // loaded from bitcode, do so now. 336234353Sdim const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile; 337234353Sdim if (!LinkModuleToUse && !LinkBCFile.empty()) { 338234353Sdim std::string ErrorStr; 339234353Sdim 340234353Sdim llvm::MemoryBuffer *BCBuf = 341234353Sdim CI.getFileManager().getBufferForFile(LinkBCFile, &ErrorStr); 342234353Sdim if (!BCBuf) { 343234353Sdim CI.getDiagnostics().Report(diag::err_cannot_open_file) 344234353Sdim << LinkBCFile << ErrorStr; 345234353Sdim return 0; 346234353Sdim } 347234353Sdim 348234353Sdim LinkModuleToUse = getLazyBitcodeModule(BCBuf, *VMContext, &ErrorStr); 349234353Sdim if (!LinkModuleToUse) { 350234353Sdim CI.getDiagnostics().Report(diag::err_cannot_open_file) 351234353Sdim << LinkBCFile << ErrorStr; 352234353Sdim return 0; 353234353Sdim } 354234353Sdim } 355234353Sdim 356218893Sdim BEConsumer = 357218893Sdim new BackendConsumer(BA, CI.getDiagnostics(), 358218893Sdim CI.getCodeGenOpts(), CI.getTargetOpts(), 359224145Sdim CI.getLangOpts(), 360234353Sdim CI.getFrontendOpts().ShowTimers, InFile, 361234353Sdim LinkModuleToUse, OS.take(), *VMContext); 362218893Sdim return BEConsumer; 363210008Srdivacky} 364210008Srdivacky 365210008Srdivackyvoid CodeGenAction::ExecuteAction() { 366210008Srdivacky // If this is an IR file, we have to treat it specially. 367210008Srdivacky if (getCurrentFileKind() == IK_LLVM_IR) { 368210008Srdivacky BackendAction BA = static_cast<BackendAction>(Act); 369210008Srdivacky CompilerInstance &CI = getCompilerInstance(); 370210008Srdivacky raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA); 371210008Srdivacky if (BA != Backend_EmitNothing && !OS) 372210008Srdivacky return; 373210008Srdivacky 374210008Srdivacky bool Invalid; 375210008Srdivacky SourceManager &SM = CI.getSourceManager(); 376210008Srdivacky const llvm::MemoryBuffer *MainFile = SM.getBuffer(SM.getMainFileID(), 377210008Srdivacky &Invalid); 378210008Srdivacky if (Invalid) 379210008Srdivacky return; 380210008Srdivacky 381210008Srdivacky // FIXME: This is stupid, IRReader shouldn't take ownership. 382210008Srdivacky llvm::MemoryBuffer *MainFileCopy = 383210008Srdivacky llvm::MemoryBuffer::getMemBufferCopy(MainFile->getBuffer(), 384243830Sdim getCurrentFile()); 385210008Srdivacky 386210008Srdivacky llvm::SMDiagnostic Err; 387218893Sdim TheModule.reset(ParseIR(MainFileCopy, Err, *VMContext)); 388210008Srdivacky if (!TheModule) { 389210008Srdivacky // Translate from the diagnostic info to the SourceManager location. 390226633Sdim SourceLocation Loc = SM.translateFileLineCol( 391210008Srdivacky SM.getFileEntryForID(SM.getMainFileID()), Err.getLineNo(), 392210008Srdivacky Err.getColumnNo() + 1); 393210008Srdivacky 394210008Srdivacky // Get a custom diagnostic for the error. We strip off a leading 395210008Srdivacky // diagnostic code if there is one. 396226633Sdim StringRef Msg = Err.getMessage(); 397210008Srdivacky if (Msg.startswith("error: ")) 398210008Srdivacky Msg = Msg.substr(7); 399234353Sdim 400234353Sdim // Escape '%', which is interpreted as a format character. 401249423Sdim SmallString<128> EscapedMessage; 402234353Sdim for (unsigned i = 0, e = Msg.size(); i != e; ++i) { 403234353Sdim if (Msg[i] == '%') 404234353Sdim EscapedMessage += '%'; 405234353Sdim EscapedMessage += Msg[i]; 406234353Sdim } 407234353Sdim 408226633Sdim unsigned DiagID = CI.getDiagnostics().getCustomDiagID( 409234353Sdim DiagnosticsEngine::Error, EscapedMessage); 410210008Srdivacky 411218893Sdim CI.getDiagnostics().Report(Loc, DiagID); 412210008Srdivacky return; 413210008Srdivacky } 414210008Srdivacky 415210008Srdivacky EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), 416224145Sdim CI.getTargetOpts(), CI.getLangOpts(), 417224145Sdim TheModule.get(), 418210008Srdivacky BA, OS); 419210008Srdivacky return; 420210008Srdivacky } 421210008Srdivacky 422210008Srdivacky // Otherwise follow the normal AST path. 423210008Srdivacky this->ASTFrontendAction::ExecuteAction(); 424210008Srdivacky} 425210008Srdivacky 426210008Srdivacky// 427210008Srdivacky 428234353Sdimvoid EmitAssemblyAction::anchor() { } 429218893SdimEmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) 430218893Sdim : CodeGenAction(Backend_EmitAssembly, _VMContext) {} 431210008Srdivacky 432234353Sdimvoid EmitBCAction::anchor() { } 433218893SdimEmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) 434218893Sdim : CodeGenAction(Backend_EmitBC, _VMContext) {} 435210008Srdivacky 436234353Sdimvoid EmitLLVMAction::anchor() { } 437218893SdimEmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) 438218893Sdim : CodeGenAction(Backend_EmitLL, _VMContext) {} 439210008Srdivacky 440234353Sdimvoid EmitLLVMOnlyAction::anchor() { } 441218893SdimEmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) 442218893Sdim : CodeGenAction(Backend_EmitNothing, _VMContext) {} 443210008Srdivacky 444234353Sdimvoid EmitCodeGenOnlyAction::anchor() { } 445218893SdimEmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) 446218893Sdim : CodeGenAction(Backend_EmitMCNull, _VMContext) {} 447210008Srdivacky 448234353Sdimvoid EmitObjAction::anchor() { } 449218893SdimEmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) 450218893Sdim : CodeGenAction(Backend_EmitObj, _VMContext) {} 451