From a15d888abf962a3b10d74a2a3a2cc73d83018da6 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 15 Jun 2015 20:30:22 +0000 Subject: [PATCH] MIR Serialization: Connect the machine function analysis pass to the MIR parser. 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 --- include/llvm/CodeGen/MIRParser/MIRParser.h | 51 +++++++-- .../llvm/CodeGen/MachineFunctionAnalysis.h | 6 +- .../llvm/CodeGen/MachineFunctionInitializer.h | 38 +++++++ include/llvm/IR/DiagnosticInfo.h | 20 ++++ include/llvm/IR/DiagnosticPrinter.h | 7 ++ include/llvm/Support/SourceMgr.h | 4 +- include/llvm/Target/TargetMachine.h | 20 ++-- lib/CodeGen/LLVMTargetMachine.cpp | 19 ++-- lib/CodeGen/MIRParser/MIRParser.cpp | 105 ++++++++++++++---- lib/CodeGen/MachineFunction.cpp | 3 + lib/CodeGen/MachineFunctionAnalysis.cpp | 8 +- lib/IR/DiagnosticInfo.cpp | 4 + lib/IR/DiagnosticPrinter.cpp | 10 ++ lib/IR/LLVMContext.cpp | 34 +++--- lib/Support/SourceMgr.cpp | 46 ++++---- lib/Target/CppBackend/CPPBackend.cpp | 3 +- lib/Target/CppBackend/CPPTargetMachine.h | 4 +- .../MIR/function-missing-machine-function.mir | 13 +++ test/CodeGen/MIR/llvm-ir-error-reported.mir | 2 +- test/CodeGen/MIR/llvmIR.mir | 3 + .../MIR/machine-function-missing-name.mir | 2 +- tools/llc/llc.cpp | 13 ++- 22 files changed, 311 insertions(+), 104 deletions(-) create mode 100644 include/llvm/CodeGen/MachineFunctionInitializer.h create mode 100644 test/CodeGen/MIR/function-missing-machine-function.mir diff --git a/include/llvm/CodeGen/MIRParser/MIRParser.h b/include/llvm/CodeGen/MIRParser/MIRParser.h index 710b2d4bef8..67b756d5e88 100644 --- a/include/llvm/CodeGen/MIRParser/MIRParser.h +++ b/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 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 Impl; + +public: + MIRParser(std::unique_ptr 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 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 parseMIRFile(StringRef Filename, SMDiagnostic &Error, - LLVMContext &Context); +/// \param Context - Context which will be used for the parsed LLVM IR module. +std::unique_ptr 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 parseMIR(std::unique_ptr Contents, - SMDiagnostic &Error, LLVMContext &Context); +/// \param Context - Context which will be used for the parsed LLVM IR module. +std::unique_ptr +createMIRParser(std::unique_ptr Contents, LLVMContext &Context); } // end namespace llvm diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index 023eeb1b4d0..4c0f5e63ea1 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/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 @@ 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 index 00000000000..ff4c29cc014 --- /dev/null +++ b/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 diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 6db5a40c577..f38313f82ea 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -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) diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h index db5779a8a8a..735e3ad7a8b 100644 --- a/include/llvm/IR/DiagnosticPrinter.h +++ b/include/llvm/IR/DiagnosticPrinter.h @@ -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 diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index d492748e778..1f8b1a01865 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -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 diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index a73a14de779..b69f9470742 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -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 diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index ef44fda3390..b7cac3ba381 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -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; diff --git a/lib/CodeGen/MIRParser/MIRParser.cpp b/lib/CodeGen/MIRParser/MIRParser.cpp index 7a51b3881af..69ecb923ed7 100644 --- a/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/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,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> Functions; public: MIRParserImpl(std::unique_ptr 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 parse(SMDiagnostic &Error); + std::unique_ptr 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 Contents, StringRef Filename, LLVMContext &Context) @@ -65,16 +83,38 @@ MIRParserImpl::MIRParserImpl(std::unique_ptr 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(Context) = Diag; + reinterpret_cast(Context)->reportDiagnostic(Diag); } -std::unique_ptr MIRParserImpl::parse(SMDiagnostic &Error) { +std::unique_ptr 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(Filename, Context); @@ -85,10 +125,11 @@ std::unique_ptr MIRParserImpl::parse(SMDiagnostic &Error) { // without having to go trough YAML traits. if (const auto *BSN = dyn_cast_or_null(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 MIRParserImpl::parse(SMDiagnostic &Error) { } bool MIRParserImpl::parseMachineFunction(yaml::Input &In) { - yaml::MachineFunction MF; - yaml::yamlize(In, MF, false); + auto MF = llvm::make_unique(); + 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 llvm::parseMIRFile(StringRef Filename, - SMDiagnostic &Error, - LLVMContext &Context) { +MIRParser::MIRParser(std::unique_ptr Impl) + : Impl(std::move(Impl)) {} + +MIRParser::~MIRParser() {} + +std::unique_ptr MIRParser::parseLLVMModule() { return Impl->parse(); } + +bool MIRParser::initializeMachineFunction(MachineFunction &MF) { + return Impl->initializeMachineFunction(MF); +} + +std::unique_ptr 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(); + return nullptr; } - return parseMIR(std::move(FileOrErr.get()), Error, Context); + return createMIRParser(std::move(FileOrErr.get()), Context); } -std::unique_ptr llvm::parseMIR(std::unique_ptr Contents, - SMDiagnostic &Error, - LLVMContext &Context) { +std::unique_ptr +llvm::createMIRParser(std::unique_ptr Contents, + LLVMContext &Context) { auto Filename = Contents->getBufferIdentifier(); - MIRParserImpl Parser(std::move(Contents), Filename, Context); - return Parser.parse(Error); + return llvm::make_unique( + llvm::make_unique(std::move(Contents), Filename, Context)); } diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index addb9e81d4a..960e06af2e3 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/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 @@ using namespace llvm; #define DEBUG_TYPE "codegen" +void MachineFunctionInitializer::anchor() {} + //===----------------------------------------------------------------------===// // MachineFunction implementation //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/MachineFunctionAnalysis.cpp b/lib/CodeGen/MachineFunctionAnalysis.cpp index f6f34ba9d92..338cd1e2203 100644 --- a/lib/CodeGen/MachineFunctionAnalysis.cpp +++ b/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 @@ bool MachineFunctionAnalysis::runOnFunction(Function &F) { assert(!MF && "MachineFunctionAnalysis already initialized!"); MF = new MachineFunction(&F, TM, NextFnNum++, getAnalysis()); + if (MFInitializer) + MFInitializer->initializeMachineFunction(*MF); return false; } diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index 50e1ccf834f..b8f77eda15a 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -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) { diff --git a/lib/IR/DiagnosticPrinter.cpp b/lib/IR/DiagnosticPrinter.cpp index f25fc20a197..659ff49d623 100644 --- a/lib/IR/DiagnosticPrinter.cpp +++ b/lib/IR/DiagnosticPrinter.cpp @@ -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; +} diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp index 7bcd829f9f5..0cd2a34eb16 100644 --- a/lib/IR/LLVMContext.cpp +++ b/lib/IR/LLVMContext.cpp @@ -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) { diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index d5e3157b064..6d44a4d51f6 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -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'; diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index b8377986ecc..36c421e2b14 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -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(o); diff --git a/lib/Target/CppBackend/CPPTargetMachine.h b/lib/Target/CppBackend/CPPTargetMachine.h index f7d0e18a0c4..ebf0635b12e 100644 --- a/lib/Target/CppBackend/CPPTargetMachine.h +++ b/lib/Target/CppBackend/CPPTargetMachine.h @@ -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 index 00000000000..71b5b284534 --- /dev/null +++ b/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 + } + +... diff --git a/test/CodeGen/MIR/llvm-ir-error-reported.mir b/test/CodeGen/MIR/llvm-ir-error-reported.mir index 013b28cd789..3508c341c44 100644 --- a/test/CodeGen/MIR/llvm-ir-error-reported.mir +++ b/test/CodeGen/MIR/llvm-ir-error-reported.mir @@ -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 diff --git a/test/CodeGen/MIR/llvmIR.mir b/test/CodeGen/MIR/llvmIR.mir index 7a7b46b6263..4d7fde240c5 100644 --- a/test/CodeGen/MIR/llvmIR.mir +++ b/test/CodeGen/MIR/llvmIR.mir @@ -30,3 +30,6 @@ } ... +--- +name: foo +... diff --git a/test/CodeGen/MIR/machine-function-missing-name.mir b/test/CodeGen/MIR/machine-function-missing-name.mir index 54668f1a5ef..b16156e54bd 100644 --- a/test/CodeGen/MIR/machine-function-missing-name.mir +++ b/test/CodeGen/MIR/machine-function-missing-name.mir @@ -14,7 +14,7 @@ ... --- -# CHECK: [[@LINE+1]]:1: error: missing required key 'name' +# CHECK: [[@LINE+1]]:1: missing required key 'name' nme: foo ... --- diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index fadcfa90235..88e73716099 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -210,6 +210,7 @@ static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; std::unique_ptr M; + std::unique_ptr 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; -- 2.34.1