[PATCH] MIR Serialization: Connect the machine function analysis pass to MIR parser.

Alex L arphaman at gmail.com
Thu Jun 11 16:53:41 PDT 2015


2015-06-11 15:57 GMT-07:00 Justin Bogner <mail at justinbogner.com>:

> Alex Lorenz <arphaman at gmail.com> writes:
> > I've updated the patch based on Justin's comments:
> >
> > - renamed MIRMachineFunctionInitializer to MachineFunctionInitializer
> > - simplified the MIRParser library interface - now the functions only
> >   create the parser, they don't parse the LLVM module. The LLVM module
> >   can be parsed by calling the appropriate method from the MIRParser
> >   class.
>
> Thanks.
>
> > - reworked the error handling to use LLVM's diagnostic info.
>
> The particular mix of SMDiagnostic and DiagnosticInfo we've ended up
> with here is kind of confusing and awkward. We should probably take the
> SMDiagnostic out of the MachineFunctionInitializer::parse API entirely
> and use LLVMContext::diagnose consistently:
>

That's a good idea, but I still would like keep the SMDiagnostic inside of
DiagnosticInfo (I explain why below).


>
> >
> > I also added the 'anchor' method to the MachineFunctionInitializer
> interface.
> >
> >
> > REPOSITORY
> >   rL LLVM
> >
> > http://reviews.llvm.org/D9928
> >
> > Files:
> >   include/llvm/CodeGen/MIRParser/MIRParser.h
> >   include/llvm/CodeGen/MachineFunctionAnalysis.h
> >   include/llvm/CodeGen/MachineFunctionInitializer.h
> >   include/llvm/IR/DiagnosticInfo.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/Target/CppBackend/CPPBackend.cpp
> >   lib/Target/CppBackend/CPPTargetMachine.h
> >   test/CodeGen/MIR/function-missing-machine-function.mir
> >   test/CodeGen/MIR/llvmIR.mir
> >   tools/llc/llc.cpp
> >
> > EMAIL PREFERENCES
> >   http://reviews.llvm.org/settings/panel/emailpreferences/
> >
> > Index: include/llvm/CodeGen/MIRParser/MIRParser.h
> > ===================================================================
> > --- include/llvm/CodeGen/MIRParser/MIRParser.h
> > +++ include/llvm/CodeGen/MIRParser/MIRParser.h
> > @@ -19,33 +19,62 @@
> >  #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(SMDiagnostic &Error);
>
> Make this 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: include/llvm/CodeGen/MachineFunctionAnalysis.h
> > ===================================================================
> > --- include/llvm/CodeGen/MachineFunctionAnalysis.h
> > +++ include/llvm/CodeGen/MachineFunctionAnalysis.h
> > @@ -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 @@
> >    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; }
> > Index: include/llvm/CodeGen/MachineFunctionInitializer.h
> > ===================================================================
> > --- /dev/null
> > +++ include/llvm/CodeGen/MachineFunctionInitializer.h
> > @@ -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: include/llvm/IR/DiagnosticInfo.h
> > ===================================================================
> > --- include/llvm/IR/DiagnosticInfo.h
> > +++ include/llvm/IR/DiagnosticInfo.h
> > @@ -32,6 +32,7 @@
> >  class Twine;
> >  class Value;
> >  class DebugLoc;
> > +class SMDiagnostic;
> >
> >  /// \brief Defines the different supported severity of a diagnostic.
> >  enum DiagnosticSeverity {
> > @@ -56,6 +57,7 @@
> >    DK_OptimizationRemarkMissed,
> >    DK_OptimizationRemarkAnalysis,
> >    DK_OptimizationFailure,
> > +  DK_MIRParser,
> >    DK_FirstPluginKind
> >  };
> >
> > @@ -386,6 +388,24 @@
> >    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)
> {}
>
> We can probably do with just storing "std::string Message" here for now
> , instead of a reference to an SMDiagnostic. Maybe also the .mir
> filename if that's appropriate. We can add more structure later if we
> need it.
>

SMDiagnostics print colors, and they a nice and consistent look when
printed, which shows the line and
column number before the 'error: ' indicator. They also print the pointer
which shows you where the error is
and can print the appropriate source ranges as well. This is really
important for me, as a lot of the errors that
will come later rely on all of those features.

I can't just print out SMDiagnostics to a string and store the string in
the DiagnosticInfo - the color information
isn't preserved, and the default printer for the diagnostic infos prints
the 'error: ' indicator before the message
which would break the consistency if my message would contain the line and
column numbers.

This is the reason why it's important for me to store the SMDiagnostic and
to print it out from the custom diagnostic
info handler in llc directly to errs().


>
> > +
> > +  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: include/llvm/Target/TargetMachine.h
> > ===================================================================
> > --- include/llvm/Target/TargetMachine.h
> > +++ include/llvm/Target/TargetMachine.h
> > @@ -27,6 +27,7 @@
> >  class InstrItineraryData;
> >  class GlobalValue;
> >  class Mangler;
> > +class MachineFunctionInitializer;
> >  class MCAsmInfo;
> >  class MCCodeGenInfo;
> >  class MCContext;
> > @@ -208,11 +209,11 @@
> >    /// 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;
> >    }
> >
> > @@ -256,10 +257,11 @@
> >
> >    /// 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: lib/CodeGen/LLVMTargetMachine.cpp
> > ===================================================================
> > --- lib/CodeGen/LLVMTargetMachine.cpp
> > +++ lib/CodeGen/LLVMTargetMachine.cpp
> > @@ -87,11 +87,11 @@
> >  }
> >
> >  /// 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 @@
> >    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 @@
> >
> >  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: lib/CodeGen/MIRParser/MIRParser.cpp
> > ===================================================================
> > --- lib/CodeGen/MIRParser/MIRParser.cpp
> > +++ lib/CodeGen/MIRParser/MIRParser.cpp
> > @@ -14,9 +14,13 @@
> >
> >  #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,19 +31,27 @@
> >
> >  using namespace llvm;
> >
> > -namespace {
> > +namespace llvm {
> >
> >  /// This class implements the parsing of LLVM IR that's embedded inside
> a MIR
> >  /// file.
> >  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 at the given message.
> > +  ///
> > +  /// Always returns true.
> > +  bool error(const Twine &Message);
>
> Why return anything at all if it's always true?


To allow the parsing methods to have simple early exits on errors, like:

  if (/* error condition */)
    return error("error message");

vs

  if (/* error condition */) {
    error("error message);
    return true;
  }


>
> > +
> >    /// Try to parse the optional LLVM module and the machine functions
> in the MIR
> >    /// file.
> >    ///
> > @@ -51,27 +63,55 @@
> >    /// 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)
> >      : SM(), Filename(Filename), Context(Context) {
> >    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;
> > +  }
>
> Pull out the error message here and give that to diagnose.
>
> > +  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) {
> >    yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
> > -                 /*Ctxt=*/nullptr, handleYAMLDiag, &Error);
> > +                 /*Ctxt=*/nullptr, handleYAMLDiag, this);
>
> A couple of things in here will need to call diagnose instead of
> populating Error and returning nullptr.
>
> >
> >    if (!In.setCurrentDocument()) {
> >      if (!Error.getMessage().empty())
> > @@ -110,12 +150,21 @@
> >  }
> >
> >  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 +199,35 @@
> >                        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(SMDiagnostic &Error)
> {
> > +  return Impl->parse(Error);
> > +}
> > +
> > +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: lib/CodeGen/MachineFunction.cpp
> > ===================================================================
> > --- lib/CodeGen/MachineFunction.cpp
> > +++ lib/CodeGen/MachineFunction.cpp
> > @@ -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 @@
> >
> >  #define DEBUG_TYPE "codegen"
> >
> > +void MachineFunctionInitializer::anchor() {}
> > +
> >
> //===----------------------------------------------------------------------===//
> >  // MachineFunction implementation
> >
> //===----------------------------------------------------------------------===//
> > Index: lib/CodeGen/MachineFunctionAnalysis.cpp
> > ===================================================================
> > --- lib/CodeGen/MachineFunctionAnalysis.cpp
> > +++ lib/CodeGen/MachineFunctionAnalysis.cpp
> > @@ -15,12 +15,14 @@
> >  #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 @@
> >    assert(!MF && "MachineFunctionAnalysis already initialized!");
> >    MF = new MachineFunction(&F, TM, NextFnNum++,
> >                             getAnalysis<MachineModuleInfo>());
> > +  if (MFInitializer)
> > +    MFInitializer->initializeMachineFunction(*MF);
> >    return false;
> >  }
> >
> > Index: lib/IR/DiagnosticInfo.cpp
> > ===================================================================
> > --- lib/IR/DiagnosticInfo.cpp
> > +++ lib/IR/DiagnosticInfo.cpp
> > @@ -25,6 +25,7 @@
> >  #include "llvm/Support/Atomic.h"
> >  #include "llvm/Support/CommandLine.h"
> >  #include "llvm/Support/Regex.h"
> > +#include "llvm/Support/SourceMgr.h"
> >  #include <string>
> >
> >  using namespace llvm;
> > @@ -170,6 +171,13 @@
> >           PassRemarksAnalysisOptLoc.Pattern->match(getPassName());
> >  }
> >
> > +void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
> > +  std::string Str;
> > +  raw_string_ostream StrOS(Str);
> > +  Diagnostic.print("", StrOS);
> > +  DP << StrOS.str();
> > +}
> > +
> >  void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char
> *PassName,
> >                                    const Function &Fn, const DebugLoc
> &DLoc,
> >                                    const Twine &Msg) {
> > Index: lib/Target/CppBackend/CPPBackend.cpp
> > ===================================================================
> > --- lib/Target/CppBackend/CPPBackend.cpp
> > +++ lib/Target/CppBackend/CPPBackend.cpp
> > @@ -2148,7 +2148,8 @@
> >
> >  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: lib/Target/CppBackend/CPPTargetMachine.h
> > ===================================================================
> > --- lib/Target/CppBackend/CPPTargetMachine.h
> > +++ lib/Target/CppBackend/CPPTargetMachine.h
> > @@ -31,8 +31,8 @@
> >  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;
> > Index: test/CodeGen/MIR/function-missing-machine-function.mir
> > ===================================================================
> > --- /dev/null
> > +++ test/CodeGen/MIR/function-missing-machine-function.mir
> > @@ -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: test/CodeGen/MIR/llvmIR.mir
> > ===================================================================
> > --- test/CodeGen/MIR/llvmIR.mir
> > +++ test/CodeGen/MIR/llvmIR.mir
> > @@ -30,3 +30,6 @@
> >    }
> >
> >  ...
> > +---
> > +name: foo
> > +...
> > Index: tools/llc/llc.cpp
> > ===================================================================
> > --- tools/llc/llc.cpp
> > +++ tools/llc/llc.cpp
> > @@ -22,6 +22,7 @@
> >  #include "llvm/CodeGen/LinkAllCodegenComponents.h"
> >  #include "llvm/CodeGen/MIRParser/MIRParser.h"
> >  #include "llvm/IR/DataLayout.h"
> > +#include "llvm/IR/DiagnosticInfo.h"
> >  #include "llvm/IR/IRPrintingPasses.h"
> >  #include "llvm/IR/LLVMContext.h"
> >  #include "llvm/IR/LegacyPassManager.h"
> > @@ -166,6 +167,22 @@
> >    return FDOut;
> >  }
> >
> > +void handleLLVMDiagnostic(const DiagnosticInfo &DI, void *C) {
> > +  LLVMContext &Context = *reinterpret_cast<LLVMContext *>(C);
> > +
> > +  if (const auto *MIRDiagnostic = cast<DiagnosticInfoMIRParser>(&DI)) {
> > +    MIRDiagnostic->getDiagnostic().print("", errs());
> > +    if (MIRDiagnostic->getSeverity() != DS_Error)
> > +      return;
> > +    exit(1);
> > +  }
> > +
> > +  // Redirect the diagnostic back to the LLVM Context
> > +  Context.setDiagnosticHandler(nullptr);
> > +  Context.diagnose(DI);
> > +  Context.setDiagnosticHandler(handleLLVMDiagnostic, C);
> > +}
>
> This does nothing at all - you're reimplementing the behaviour you'd get
> if you didn't set a diagnostic handler, and falling back to the default
> by changing global state is error prone and ugly. Just remove this.


> > +
> >  // main - Entry point for the llc compiler.
> >  //
> >  int main(int argc, char **argv) {
> > @@ -176,6 +193,7 @@
> >    EnableDebugBuffering = true;
> >
> >    LLVMContext &Context = getGlobalContext();
> > +  Context.setDiagnosticHandler(handleLLVMDiagnostic, &Context);
> >    llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
> >
> >    // Initialize targets first, so that --version shows registered
> targets.
> > @@ -210,16 +228,19 @@
> >    // Load the module to be compiled...
> >    SMDiagnostic Err;
> >    std::unique_ptr<Module> M;
> > +  std::unique_ptr<MIRParser> MIR;
> >    Triple TheTriple;
> >
> >    bool SkipModule = MCPU == "help" ||
> >                      (!MAttrs.empty() && MAttrs.front() == "help");
> >
> >    // 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(Err);
> > +    } else
> >        M = parseIRFile(InputFilename, Err, Context);
> >      if (!M) {
> >        Err.print(argv[0], errs());
>
> You'll have to restructure this a little to deal with the fact that
> parseLLVMModule doesn't fill Err anymore, or maybe just assert(M &&
> "parseLLVMModule exits on failure") after parseLLVMModule for now to
> document the implicit control flow.
>
> > @@ -350,7 +371,7 @@
> >
> >      // 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;
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150611/b3470dfd/attachment.html>


More information about the llvm-commits mailing list