MIR Serialization: Connect the machine function analysis pass to the MIR parser.
authorAlex Lorenz <arphaman@gmail.com>
Mon, 15 Jun 2015 20:30:22 +0000 (20:30 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Mon, 15 Jun 2015 20:30:22 +0000 (20:30 +0000)
This commit connects the machine function analysis pass (which creates machine
functions) to the MIR parser, which will initialize the machine functions
with the state from the MIR file and reconstruct the machine IR.

This commit introduces a new interface called 'MachineFunctionInitializer',
which can be used to provide custom initialization for the machine functions.

This commit also introduces a new diagnostic class called
'DiagnosticInfoMIRParser' which is used for MIR parsing errors.
This commit modifies the default diagnostic handling in LLVMContext - now the
the diagnostics are printed directly into llvm::errs() so that the MIR parsing
errors can be printed with colours.

Reviewers: Justin Bogner

Differential Revision: http://reviews.llvm.org/D9928

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239753 91177308-0d34-0410-b5e6-96231b3b80d8

22 files changed:
include/llvm/CodeGen/MIRParser/MIRParser.h
include/llvm/CodeGen/MachineFunctionAnalysis.h
include/llvm/CodeGen/MachineFunctionInitializer.h [new file with mode: 0644]
include/llvm/IR/DiagnosticInfo.h
include/llvm/IR/DiagnosticPrinter.h
include/llvm/Support/SourceMgr.h
include/llvm/Target/TargetMachine.h
lib/CodeGen/LLVMTargetMachine.cpp
lib/CodeGen/MIRParser/MIRParser.cpp
lib/CodeGen/MachineFunction.cpp
lib/CodeGen/MachineFunctionAnalysis.cpp
lib/IR/DiagnosticInfo.cpp
lib/IR/DiagnosticPrinter.cpp
lib/IR/LLVMContext.cpp
lib/Support/SourceMgr.cpp
lib/Target/CppBackend/CPPBackend.cpp
lib/Target/CppBackend/CPPTargetMachine.h
test/CodeGen/MIR/function-missing-machine-function.mir [new file with mode: 0644]
test/CodeGen/MIR/llvm-ir-error-reported.mir
test/CodeGen/MIR/llvmIR.mir
test/CodeGen/MIR/machine-function-missing-name.mir
tools/llc/llc.cpp

index 710b2d4bef8e0806c757ca110b6a83c24d23509a..67b756d5e886a6bc902e042105f3b2c8c3f9d22e 100644 (file)
 #define LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineFunctionInitializer.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <memory>
 
 namespace llvm {
 
+class MIRParserImpl;
 class SMDiagnostic;
 
+/// This class initializes machine functions by applying the state loaded from
+/// a MIR file.
+class MIRParser : public MachineFunctionInitializer {
+  std::unique_ptr<MIRParserImpl> Impl;
+
+public:
+  MIRParser(std::unique_ptr<MIRParserImpl> Impl);
+  MIRParser(const MIRParser &) = delete;
+  ~MIRParser();
+
+  /// Parse the optional LLVM IR module that's embedded in the MIR file.
+  ///
+  /// A new, empty module is created if the LLVM IR isn't present.
+  /// Returns null if a parsing error occurred.
+  std::unique_ptr<Module> parseLLVMModule();
+
+  /// Initialize the machine function to the state that's described in the MIR
+  /// file.
+  ///
+  /// Return true if error occurred.
+  bool initializeMachineFunction(MachineFunction &MF) override;
+};
+
 /// This function is the main interface to the MIR serialization format parser.
 ///
-/// It reads a YAML file that has an optional LLVM IR and returns an LLVM
-/// module.
+/// It reads in a MIR file and returns a MIR parser that can parse the embedded
+/// LLVM IR module and initialize the machine functions by parsing the machine
+/// function's state.
+///
 /// \param Filename - The name of the file to parse.
 /// \param Error - Error result info.
-/// \param Context - Context in which to allocate globals info.
-std::unique_ptr<Module> parseMIRFile(StringRef Filename, SMDiagnostic &Error,
-                                     LLVMContext &Context);
+/// \param Context - Context which will be used for the parsed LLVM IR module.
+std::unique_ptr<MIRParser> createMIRParserFromFile(StringRef Filename,
+                                                   SMDiagnostic &Error,
+                                                   LLVMContext &Context);
 
 /// This function is another interface to the MIR serialization format parser.
 ///
-/// It parses the optional LLVM IR in the given buffer, and returns an LLVM
-/// module.
+/// It returns a MIR parser that works with the given memory buffer and that can
+/// parse the embedded LLVM IR module and initialize the machine functions by
+/// parsing the machine function's state.
+///
 /// \param Contents - The MemoryBuffer containing the machine level IR.
-/// \param Error - Error result info.
-/// \param Context - Context in which to allocate globals info.
-std::unique_ptr<Module> parseMIR(std::unique_ptr<MemoryBuffer> Contents,
-                                 SMDiagnostic &Error, LLVMContext &Context);
+/// \param Context - Context which will be used for the parsed LLVM IR module.
+std::unique_ptr<MIRParser>
+createMIRParser(std::unique_ptr<MemoryBuffer> Contents, LLVMContext &Context);
 
 } // end namespace llvm
 
index 023eeb1b4d0ea49cbdc6ca37e3da6e09f9e40b97..4c0f5e63ea1d9c99629249282956851a2a62aca1 100644 (file)
@@ -19,6 +19,7 @@
 namespace llvm {
 
 class MachineFunction;
+class MachineFunctionInitializer;
 class TargetMachine;
 
 /// MachineFunctionAnalysis - This class is a Pass that manages a
@@ -28,9 +29,12 @@ private:
   const TargetMachine &TM;
   MachineFunction *MF;
   unsigned NextFnNum;
+  MachineFunctionInitializer *MFInitializer;
+
 public:
   static char ID;
-  explicit MachineFunctionAnalysis(const TargetMachine &tm);
+  explicit MachineFunctionAnalysis(const TargetMachine &tm,
+                                   MachineFunctionInitializer *MFInitializer);
   ~MachineFunctionAnalysis() override;
 
   MachineFunction &getMF() const { return *MF; }
diff --git a/include/llvm/CodeGen/MachineFunctionInitializer.h b/include/llvm/CodeGen/MachineFunctionInitializer.h
new file mode 100644 (file)
index 0000000..ff4c29c
--- /dev/null
@@ -0,0 +1,38 @@
+//===- MachineFunctionInitalizer.h - machine function initializer ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares an interface that allows custom machine function
+// initialization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINEFUNCTIONINITIALIZER_H
+#define LLVM_CODEGEN_MACHINEFUNCTIONINITIALIZER_H
+
+namespace llvm {
+
+class MachineFunction;
+
+/// This interface provides a way to initialize machine functions after they are
+/// created by the machine function analysis pass.
+class MachineFunctionInitializer {
+  virtual void anchor();
+
+public:
+  virtual ~MachineFunctionInitializer() {}
+
+  /// Initialize the machine function.
+  ///
+  /// Return true if error occurred.
+  virtual bool initializeMachineFunction(MachineFunction &MF) = 0;
+};
+
+} // end namespace llvm
+
+#endif
index 6db5a40c5772c052c94252b24cbf1b45924218b1..f38313f82ea72a0ef51ffd55e6797d6f05a1814c 100644 (file)
@@ -32,6 +32,7 @@ class LLVMContextImpl;
 class Twine;
 class Value;
 class DebugLoc;
+class SMDiagnostic;
 
 /// \brief Defines the different supported severity of a diagnostic.
 enum DiagnosticSeverity {
@@ -56,6 +57,7 @@ enum DiagnosticKind {
   DK_OptimizationRemarkMissed,
   DK_OptimizationRemarkAnalysis,
   DK_OptimizationFailure,
+  DK_MIRParser,
   DK_FirstPluginKind
 };
 
@@ -386,6 +388,24 @@ public:
   bool isEnabled() const override;
 };
 
+/// Diagnostic information for machine IR parser.
+class DiagnosticInfoMIRParser : public DiagnosticInfo {
+  const SMDiagnostic &Diagnostic;
+
+public:
+  DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
+                          const SMDiagnostic &Diagnostic)
+      : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
+
+  const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
+
+  void print(DiagnosticPrinter &DP) const override;
+
+  static bool classof(const DiagnosticInfo *DI) {
+    return DI->getKind() == DK_MIRParser;
+  }
+};
+
 // Create wrappers for C Binding types (see CBindingWrapping.h).
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
 
index db5779a8a8a5c9b8354a57cec2caab09633c3fdd..735e3ad7a8b015656bfd859a6f3d6c7e7a2e29bb 100644 (file)
@@ -22,6 +22,7 @@ namespace llvm {
 // Forward declarations.
 class Module;
 class raw_ostream;
+class SMDiagnostic;
 class StringRef;
 class Twine;
 class Value;
@@ -51,6 +52,9 @@ public:
   // IR related types.
   virtual DiagnosticPrinter &operator<<(const Value &V) = 0;
   virtual DiagnosticPrinter &operator<<(const Module &M) = 0;
+
+  // Other types.
+  virtual DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) = 0;
 };
 
 /// \brief Basic diagnostic printer that uses an underlying raw_ostream.
@@ -81,6 +85,9 @@ public:
   // IR related types.
   DiagnosticPrinter &operator<<(const Value &V) override;
   DiagnosticPrinter &operator<<(const Module &M) override;
+
+  // Other types.
+  DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) override;
 };
 } // End namespace llvm
 
index d492748e7781ece07cd8540e71d4b5df9d7b4056..1f8b1a01865f59091dc70c1c644d2b0e5203c0b9 100644 (file)
@@ -276,8 +276,8 @@ public:
     return FixIts;
   }
 
-  void print(const char *ProgName, raw_ostream &S,
-             bool ShowColors = true) const;
+  void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
+             bool ShowKindLabel = true) const;
 };
 
 }  // end llvm namespace
index a73a14de779ba53d278a8ae193ea1119ab4a8143..b69f94707423bdc059808f2a71a0c2edd21a223d 100644 (file)
@@ -28,6 +28,7 @@ namespace llvm {
 class InstrItineraryData;
 class GlobalValue;
 class Mangler;
+class MachineFunctionInitializer;
 class MCAsmInfo;
 class MCCodeGenInfo;
 class MCContext;
@@ -210,11 +211,11 @@ public:
   /// emitted.  Typically this will involve several steps of code generation.
   /// This method should return true if emission of this file type is not
   /// supported, or false on success.
-  virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &,
-                                   CodeGenFileType,
-                                   bool /*DisableVerify*/ = true,
-                                   AnalysisID /*StartAfter*/ = nullptr,
-                                   AnalysisID /*StopAfter*/ = nullptr) {
+  virtual bool addPassesToEmitFile(
+      PassManagerBase &, raw_pwrite_stream &, CodeGenFileType,
+      bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr,
+      AnalysisID /*StopAfter*/ = nullptr,
+      MachineFunctionInitializer * /*MFInitializer*/ = nullptr) {
     return true;
   }
 
@@ -258,10 +259,11 @@ public:
 
   /// Add passes to the specified pass manager to get the specified file
   /// emitted.  Typically this will involve several steps of code generation.
-  bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
-                           CodeGenFileType FileType, bool DisableVerify = true,
-                           AnalysisID StartAfter = nullptr,
-                           AnalysisID StopAfter = nullptr) override;
+  bool addPassesToEmitFile(
+      PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType,
+      bool DisableVerify = true, AnalysisID StartAfter = nullptr,
+      AnalysisID StopAfter = nullptr,
+      MachineFunctionInitializer *MFInitializer = nullptr) override;
 
   /// Add passes to the specified pass manager to get machine code emitted with
   /// the MCJIT. This method returns true if machine code is not supported. It
index ef44fda3390de21c5efb80d66fe498caafa94417..b7cac3ba381057b029d71965a1cc4a63e6ac5799 100644 (file)
@@ -87,11 +87,11 @@ TargetIRAnalysis LLVMTargetMachine::getTargetIRAnalysis() {
 }
 
 /// addPassesToX helper drives creation and initialization of TargetPassConfig.
-static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM,
-                                          PassManagerBase &PM,
-                                          bool DisableVerify,
-                                          AnalysisID StartAfter,
-                                          AnalysisID StopAfter) {
+static MCContext *
+addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM,
+                        bool DisableVerify, AnalysisID StartAfter,
+                        AnalysisID StopAfter,
+                        MachineFunctionInitializer *MFInitializer = nullptr) {
 
   // Add internal analysis passes from the target machine.
   PM.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
@@ -121,7 +121,7 @@ static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM,
   PM.add(MMI);
 
   // Set up a MachineFunction for the rest of CodeGen to work on.
-  PM.add(new MachineFunctionAnalysis(*TM));
+  PM.add(new MachineFunctionAnalysis(*TM, MFInitializer));
 
   // Enable FastISel with -fast, but allow that to be overridden.
   if (EnableFastISelOption == cl::BOU_TRUE ||
@@ -142,10 +142,11 @@ static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM,
 
 bool LLVMTargetMachine::addPassesToEmitFile(
     PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType,
-    bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) {
+    bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter,
+    MachineFunctionInitializer *MFInitializer) {
   // Add common CodeGen passes.
-  MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,
-                                               StartAfter, StopAfter);
+  MCContext *Context = addPassesToGenerateCode(
+      this, PM, DisableVerify, StartAfter, StopAfter, MFInitializer);
   if (!Context)
     return true;
 
index 7a51b3881afc68afaa572643459b7c155903fb51..69ecb923ed7bac24b5fd54baf8f503154f393953 100644 (file)
 
 #include "llvm/CodeGen/MIRParser/MIRParser.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/AsmParser/Parser.h"
+#include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MIRYamlMapping.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/SMLoc.h"
@@ -27,7 +31,7 @@
 
 using namespace llvm;
 
-namespace {
+namespace llvm {
 
 /// This class implements the parsing of LLVM IR that's embedded inside a MIR
 /// file.
@@ -35,29 +39,43 @@ class MIRParserImpl {
   SourceMgr SM;
   StringRef Filename;
   LLVMContext &Context;
+  StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
 
 public:
   MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
                 LLVMContext &Context);
 
+  void reportDiagnostic(const SMDiagnostic &Diag);
+
+  /// Report an error with the given message at unknown location.
+  ///
+  /// Always returns true.
+  bool error(const Twine &Message);
+
   /// Try to parse the optional LLVM module and the machine functions in the MIR
   /// file.
   ///
   /// Return null if an error occurred.
-  std::unique_ptr<Module> parse(SMDiagnostic &Error);
+  std::unique_ptr<Module> parse();
 
   /// Parse the machine function in the current YAML document.
   ///
   /// Return true if an error occurred.
   bool parseMachineFunction(yaml::Input &In);
 
+  /// Initialize the machine function to the state that's described in the MIR
+  /// file.
+  ///
+  /// Return true if error occurred.
+  bool initializeMachineFunction(MachineFunction &MF);
+
 private:
   /// Return a MIR diagnostic converted from an LLVM assembly diagnostic.
   SMDiagnostic diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
                                         SMRange SourceRange);
 };
 
-} // end anonymous namespace
+} // end namespace llvm
 
 MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
                              StringRef Filename, LLVMContext &Context)
@@ -65,16 +83,38 @@ MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
   SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
 }
 
+bool MIRParserImpl::error(const Twine &Message) {
+  Context.diagnose(DiagnosticInfoMIRParser(
+      DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
+  return true;
+}
+
+void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
+  DiagnosticSeverity Kind;
+  switch (Diag.getKind()) {
+  case SourceMgr::DK_Error:
+    Kind = DS_Error;
+    break;
+  case SourceMgr::DK_Warning:
+    Kind = DS_Warning;
+    break;
+  case SourceMgr::DK_Note:
+    Kind = DS_Note;
+    break;
+  }
+  Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
+}
+
 static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
-  *reinterpret_cast<SMDiagnostic *>(Context) = Diag;
+  reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
 }
 
-std::unique_ptr<Module> MIRParserImpl::parse(SMDiagnostic &Error) {
+std::unique_ptr<Module> MIRParserImpl::parse() {
   yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
-                 /*Ctxt=*/nullptr, handleYAMLDiag, &Error);
+                 /*Ctxt=*/nullptr, handleYAMLDiag, this);
 
   if (!In.setCurrentDocument()) {
-    if (!Error.getMessage().empty())
+    if (In.error())
       return nullptr;
     // Create an empty module when the MIR file is empty.
     return llvm::make_unique<Module>(Filename, Context);
@@ -85,10 +125,11 @@ std::unique_ptr<Module> MIRParserImpl::parse(SMDiagnostic &Error) {
   // without having to go trough YAML traits.
   if (const auto *BSN =
           dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
+    SMDiagnostic Error;
     M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
                       Context);
     if (!M) {
-      Error = diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange());
+      reportDiagnostic(diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange()));
       return M;
     }
     In.nextDocument();
@@ -110,12 +151,21 @@ std::unique_ptr<Module> MIRParserImpl::parse(SMDiagnostic &Error) {
 }
 
 bool MIRParserImpl::parseMachineFunction(yaml::Input &In) {
-  yaml::MachineFunction MF;
-  yaml::yamlize(In, MF, false);
+  auto MF = llvm::make_unique<yaml::MachineFunction>();
+  yaml::yamlize(In, *MF, false);
   if (In.error())
     return true;
-  // TODO: Initialize the real machine function with the state in the yaml
-  // machine function later on.
+  auto FunctionName = MF->Name;
+  Functions.insert(std::make_pair(FunctionName, std::move(MF)));
+  return false;
+}
+
+bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
+  auto It = Functions.find(MF.getName());
+  if (It == Functions.end())
+    return error(Twine("no machine function information for function '") +
+                 MF.getName() + "' in the MIR file");
+  // TODO: Recreate the machine function.
   return false;
 }
 
@@ -150,22 +200,33 @@ SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
                       Error.getFixIts());
 }
 
-std::unique_ptr<Module> llvm::parseMIRFile(StringRef Filename,
-                                           SMDiagnostic &Error,
-                                           LLVMContext &Context) {
+MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
+    : Impl(std::move(Impl)) {}
+
+MIRParser::~MIRParser() {}
+
+std::unique_ptr<Module> MIRParser::parseLLVMModule() { return Impl->parse(); }
+
+bool MIRParser::initializeMachineFunction(MachineFunction &MF) {
+  return Impl->initializeMachineFunction(MF);
+}
+
+std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(StringRef Filename,
+                                                         SMDiagnostic &Error,
+                                                         LLVMContext &Context) {
   auto FileOrErr = MemoryBuffer::getFile(Filename);
   if (std::error_code EC = FileOrErr.getError()) {
     Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
                          "Could not open input file: " + EC.message());
-    return std::unique_ptr<Module>();
+    return nullptr;
   }
-  return parseMIR(std::move(FileOrErr.get()), Error, Context);
+  return createMIRParser(std::move(FileOrErr.get()), Context);
 }
 
-std::unique_ptr<Module> llvm::parseMIR(std::unique_ptr<MemoryBuffer> Contents,
-                                       SMDiagnostic &Error,
-                                       LLVMContext &Context) {
+std::unique_ptr<MIRParser>
+llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
+                      LLVMContext &Context) {
   auto Filename = Contents->getBufferIdentifier();
-  MIRParserImpl Parser(std::move(Contents), Filename, Context);
-  return Parser.parse(Error);
+  return llvm::make_unique<MIRParser>(
+      llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context));
 }
index addb9e81d4a827918846353c0ffdcb6e24fcdf68..960e06af2e3f0a4714c0cc6e1a0941af271b9acc 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunctionInitializer.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
@@ -41,6 +42,8 @@ using namespace llvm;
 
 #define DEBUG_TYPE "codegen"
 
+void MachineFunctionInitializer::anchor() {}
+
 //===----------------------------------------------------------------------===//
 // MachineFunction implementation
 //===----------------------------------------------------------------------===//
index f6f34ba9d9275afddd3497e5361679531a4b60b6..338cd1e2203274df44b13c1bce77bd145288fc2b 100644 (file)
 #include "llvm/CodeGen/GCMetadata.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineFunctionInitializer.h"
 using namespace llvm;
 
 char MachineFunctionAnalysis::ID = 0;
 
-MachineFunctionAnalysis::MachineFunctionAnalysis(const TargetMachine &tm) :
-  FunctionPass(ID), TM(tm), MF(nullptr) {
+MachineFunctionAnalysis::MachineFunctionAnalysis(
+    const TargetMachine &tm, MachineFunctionInitializer *MFInitializer)
+    : FunctionPass(ID), TM(tm), MF(nullptr), MFInitializer(MFInitializer) {
   initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry());
 }
 
@@ -47,6 +49,8 @@ bool MachineFunctionAnalysis::runOnFunction(Function &F) {
   assert(!MF && "MachineFunctionAnalysis already initialized!");
   MF = new MachineFunction(&F, TM, NextFnNum++,
                            getAnalysis<MachineModuleInfo>());
+  if (MFInitializer)
+    MFInitializer->initializeMachineFunction(*MF);
   return false;
 }
 
index 50e1ccf834f7e88f8f6faa52e57083ea729b8c37..b8f77eda15a6dc3039793fbf4b103dcf525e5eb8 100644 (file)
@@ -170,6 +170,10 @@ bool DiagnosticInfoOptimizationRemarkAnalysis::isEnabled() const {
          PassRemarksAnalysisOptLoc.Pattern->match(getPassName());
 }
 
+void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
+  DP << Diagnostic;
+}
+
 void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
                                   const Function &Fn, const DebugLoc &DLoc,
                                   const Twine &Msg) {
index f25fc20a197bf7ca618699838b4c105e4c3a013e..659ff49d623f8fe7dc7c5fe698f34ccbe95e2853 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SourceMgr.h"
 
 using namespace llvm;
 
@@ -105,3 +106,12 @@ DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Module &M) {
   Stream << M.getModuleIdentifier();
   return *this;
 }
+
+// Other types.
+DiagnosticPrinter &DiagnosticPrinterRawOStream::
+operator<<(const SMDiagnostic &Diag) {
+  // We don't have to print the SMDiagnostic kind, as the diagnostic severity
+  // is printed by the diagnostic handler.
+  Diag.print("", Stream, /*ShowColors=*/true, /*ShowKindLabel=*/false);
+  return *this;
+}
index 7bcd829f9f5e0cd0897d6b88556ec793df8dc15f..0cd2a34eb16868484e0742963c930b0900419600 100644 (file)
@@ -199,6 +199,19 @@ static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {
   return true;
 }
 
+static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
+  switch (Severity) {
+  case DS_Error:
+    return "error";
+  case DS_Warning:
+    return "warning";
+  case DS_Remark:
+    return "remark";
+  case DS_Note:
+    return "note";
+  }
+}
+
 void LLVMContext::diagnose(const DiagnosticInfo &DI) {
   // If there is a report handler, use it.
   if (pImpl->DiagnosticHandler) {
@@ -211,25 +224,12 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) {
     return;
 
   // Otherwise, print the message with a prefix based on the severity.
-  std::string MsgStorage;
-  raw_string_ostream Stream(MsgStorage);
-  DiagnosticPrinterRawOStream DP(Stream);
+  DiagnosticPrinterRawOStream DP(errs());
+  errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
   DI.print(DP);
-  Stream.flush();
-  switch (DI.getSeverity()) {
-  case DS_Error:
-    errs() << "error: " << MsgStorage << "\n";
+  errs() << "\n";
+  if (DI.getSeverity() == DS_Error)
     exit(1);
-  case DS_Warning:
-    errs() << "warning: " << MsgStorage << "\n";
-    break;
-  case DS_Remark:
-    errs() << "remark: " << MsgStorage << "\n";
-    break;
-  case DS_Note:
-    errs() << "note: " << MsgStorage << "\n";
-    break;
-  }
 }
 
 void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
index d5e3157b064e898e1ad4e8d66647b1e028c66472..6d44a4d51f600e98a58caf5b256225c9fff732a7 100644 (file)
@@ -332,8 +332,8 @@ static bool isNonASCII(char c) {
   return c & 0x80;
 }
 
-void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
-                         bool ShowColors) const {
+void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors,
+                         bool ShowKindLabel) const {
   // Display colors only if OS supports colors.
   ShowColors &= S.has_colors();
 
@@ -357,27 +357,29 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
     S << ": ";
   }
 
-  switch (Kind) {
-  case SourceMgr::DK_Error:
-    if (ShowColors)
-      S.changeColor(raw_ostream::RED, true);
-    S << "error: ";
-    break;
-  case SourceMgr::DK_Warning:
-    if (ShowColors)
-      S.changeColor(raw_ostream::MAGENTA, true);
-    S << "warning: ";
-    break;
-  case SourceMgr::DK_Note:
-    if (ShowColors)
-      S.changeColor(raw_ostream::BLACK, true);
-    S << "note: ";
-    break;
-  }
+  if (ShowKindLabel) {
+    switch (Kind) {
+    case SourceMgr::DK_Error:
+      if (ShowColors)
+        S.changeColor(raw_ostream::RED, true);
+      S << "error: ";
+      break;
+    case SourceMgr::DK_Warning:
+      if (ShowColors)
+        S.changeColor(raw_ostream::MAGENTA, true);
+      S << "warning: ";
+      break;
+    case SourceMgr::DK_Note:
+      if (ShowColors)
+        S.changeColor(raw_ostream::BLACK, true);
+      S << "note: ";
+      break;
+    }
 
-  if (ShowColors) {
-    S.resetColor();
-    S.changeColor(raw_ostream::SAVEDCOLOR, true);
+    if (ShowColors) {
+      S.resetColor();
+      S.changeColor(raw_ostream::SAVEDCOLOR, true);
+    }
   }
 
   S << Message << '\n';
index b8377986ecc054f3377dd0f18fcc1767b0114423..36c421e2b14b997eccd4f1f2f5902f43a4caf9ec 100644 (file)
@@ -2148,7 +2148,8 @@ char CppWriter::ID = 0;
 
 bool CPPTargetMachine::addPassesToEmitFile(
     PassManagerBase &PM, raw_pwrite_stream &o, CodeGenFileType FileType,
-    bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) {
+    bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter,
+    MachineFunctionInitializer *MFInitializer) {
   if (FileType != TargetMachine::CGFT_AssemblyFile)
     return true;
   auto FOut = llvm::make_unique<formatted_raw_ostream>(o);
index f7d0e18a0c4dcd8908dc19ba64be646420b0834b..ebf0635b12e47fdc69a7dc42f9d934ab78d37605 100644 (file)
@@ -31,8 +31,8 @@ struct CPPTargetMachine : public TargetMachine {
 public:
   bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
                            CodeGenFileType FileType, bool DisableVerify,
-                           AnalysisID StartAfter,
-                           AnalysisID StopAfter) override;
+                           AnalysisID StartAfter, AnalysisID StopAfter,
+                           MachineFunctionInitializer *MFInitializer) override;
 };
 
 extern Target TheCppBackendTarget;
diff --git a/test/CodeGen/MIR/function-missing-machine-function.mir b/test/CodeGen/MIR/function-missing-machine-function.mir
new file mode 100644 (file)
index 0000000..71b5b28
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+# This test verifies that an error is reported when a MIR file has some
+# function but is missing a corresponding machine function.
+
+# CHECK: no machine function information for function 'foo' in the MIR file
+
+--- |
+
+  define i32 @foo() {
+    ret i32 0
+  }
+
+...
index 013b28cd7890097bbedfe9432951e16cb8862a26..3508c341c44d8926654e85615001b13917acbd5d 100644 (file)
@@ -4,7 +4,7 @@
 
 --- |
   
-  ; CHECK: [[@LINE+3]]:15: error: use of undefined value '%a'
+  ; CHECK: [[@LINE+3]]:15: use of undefined value '%a'
   define i32 @foo(i32 %x, i32 %y) {
     %z = alloca i32, align 4
     store i32 %a, i32* %z, align 4
index 7a7b46b626386150d634cedbb621a9bd2621f720..4d7fde240c5b23c8af65e6507ec75b5b299fb849 100644 (file)
@@ -30,3 +30,6 @@
   }
   
 ...
+---
+name: foo
+...
index 54668f1a5efe3794746577af03fdd58695cb7b80..b16156e54bd1b2d74848fa03ea9aeb34932224a4 100644 (file)
@@ -14,7 +14,7 @@
 
 ...
 ---
-# CHECK: [[@LINE+1]]:1: error: missing required key 'name'
+# CHECK: [[@LINE+1]]:1: missing required key 'name'
 nme:             foo
 ...
 ---
index fadcfa90235c361402560b23f6aca2ea1ce293ea..88e7371609927c5a8cf63c82ba95c64fd5f81954 100644 (file)
@@ -210,6 +210,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
   // Load the module to be compiled...
   SMDiagnostic Err;
   std::unique_ptr<Module> M;
+  std::unique_ptr<MIRParser> MIR;
   Triple TheTriple;
 
   bool SkipModule = MCPU == "help" ||
@@ -217,9 +218,13 @@ static int compileModule(char **argv, LLVMContext &Context) {
 
   // If user just wants to list available options, skip module loading
   if (!SkipModule) {
-    if (StringRef(InputFilename).endswith_lower(".mir"))
-      M = parseMIRFile(InputFilename, Err, Context);
-    else
+    if (StringRef(InputFilename).endswith_lower(".mir")) {
+      MIR = createMIRParserFromFile(InputFilename, Err, Context);
+      if (MIR) {
+        M = MIR->parseLLVMModule();
+        assert(M && "parseLLVMModule should exit on failure");
+      }
+    } else
       M = parseIRFile(InputFilename, Err, Context);
     if (!M) {
       Err.print(argv[0], errs());
@@ -350,7 +355,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
 
     // Ask the target to add backend passes as necessary.
     if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartAfterID,
-                                    StopAfterID)) {
+                                    StopAfterID, MIR.get())) {
       errs() << argv[0] << ": target does not support generation of this"
              << " file type!\n";
       return 1;