Index: include/llvm/CodeGen/MIRParser/MIRParser.h =================================================================== --- include/llvm/CodeGen/MIRParser/MIRParser.h +++ include/llvm/CodeGen/MIRParser/MIRParser.h @@ -18,7 +18,6 @@ #ifndef LLVM_CODEGEN_MIRPARSER_MIRPARSER_H #define LLVM_CODEGEN_MIRPARSER_MIRPARSER_H -#include "llvm/CodeGen/MachineFunctionInitializer.h" #include "llvm/IR/Module.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -27,29 +26,30 @@ class StringRef; class MIRParserImpl; +class MachineModuleInfo; class SMDiagnostic; /// This class initializes machine functions by applying the state loaded from /// a MIR file. -class MIRParser : public MachineFunctionInitializer { +class MIRParser { std::unique_ptr Impl; public: MIRParser(std::unique_ptr Impl); MIRParser(const MIRParser &) = delete; - ~MIRParser() override; + ~MIRParser(); - /// Parse the optional LLVM IR module that's embedded in the MIR file. + /// Parses the optional LLVM IR module 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(); + /// \returns nullptr if a parsing error occurred. + std::unique_ptr parseIRModule(); - /// Initialize the machine function to the state that's described in the MIR - /// file. + /// \brief Parses MachineFunctions in the MIR file and add them to the given + /// MachineModuleInfo \p MMI. /// - /// Return true if error occurred. - bool initializeMachineFunction(MachineFunction &MF) override; + /// \returns true if an error occurred. + bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI); }; /// This function is the main interface to the MIR serialization format parser. Index: include/llvm/CodeGen/MachineFunctionInitializer.h =================================================================== --- include/llvm/CodeGen/MachineFunctionInitializer.h +++ /dev/null @@ -1,38 +0,0 @@ -//=- MachineFunctionInitializer.h - machine function initializer --*- C++ -*-=// -// -// 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() = default; - - /// Initialize the machine function. - /// - /// Return true if error occurred. - virtual bool initializeMachineFunction(MachineFunction &MF) = 0; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINEFUNCTIONINITIALIZER_H Index: include/llvm/CodeGen/MachineModuleInfo.h =================================================================== --- include/llvm/CodeGen/MachineModuleInfo.h +++ include/llvm/CodeGen/MachineModuleInfo.h @@ -47,7 +47,6 @@ class CallInst; class Function; class MachineFunction; -class MachineFunctionInitializer; class MMIAddrLabelMap; class Module; class TargetMachine; @@ -126,7 +125,6 @@ /// comments in lib/Target/X86/X86FrameLowering.cpp for more details. bool UsesMorestackAddr; - MachineFunctionInitializer *MFInitializer; /// Maps IR Functions to their corresponding MachineFunctions. DenseMap> MachineFunctions; /// Next unique number available for a MachineFunction. @@ -150,15 +148,14 @@ void setModule(const Module *M) { TheModule = M; } const Module *getModule() const { return TheModule; } - void setMachineFunctionInitializer(MachineFunctionInitializer *MFInit) { - MFInitializer = MFInit; - } - /// Returns the MachineFunction constructed for the IR function \p F. - /// Creates a new MachineFunction and runs the MachineFunctionInitializer - /// if none exists yet. + /// Creates a new MachineFunction if none exists yet. MachineFunction &getMachineFunction(const Function &F); + /// \bried Returns the MachineFunction associated to IR function \p F if there + /// is one, otherwise nullptr. + MachineFunction *queryMachineFunction(const Function &F) const; + /// Delete the MachineFunction \p MF and reset the link in the IR Function to /// Machine Function map. void deleteMachineFunctionFor(Function &F); Index: include/llvm/Target/TargetMachine.h =================================================================== --- include/llvm/Target/TargetMachine.h +++ include/llvm/Target/TargetMachine.h @@ -25,7 +25,6 @@ namespace llvm { class GlobalValue; -class MachineFunctionInitializer; class Mangler; class MCAsmInfo; class MCContext; @@ -227,8 +226,7 @@ PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, bool /*DisableVerify*/ = true, AnalysisID /*StartBefore*/ = nullptr, AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopBefore*/ = nullptr, - AnalysisID /*StopAfter*/ = nullptr, - MachineFunctionInitializer * /*MFInitializer*/ = nullptr) { + AnalysisID /*StopAfter*/ = nullptr) { return true; } @@ -289,8 +287,7 @@ PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify = true, AnalysisID StartBefore = nullptr, AnalysisID StartAfter = nullptr, AnalysisID StopBefore = nullptr, - AnalysisID StopAfter = nullptr, - MachineFunctionInitializer *MFInitializer = nullptr) override; + AnalysisID StopAfter = 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 @@ -106,9 +106,7 @@ addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM, bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter, AnalysisID StopBefore, - AnalysisID StopAfter, - MachineFunctionInitializer *MFInitializer = nullptr) { - + AnalysisID StopAfter) { // Targets may override createPassConfig to provide a target-specific // subclass. TargetPassConfig *PassConfig = TM->createPassConfig(PM); @@ -136,7 +134,6 @@ PassConfig->addISelPrepare(); MachineModuleInfo *MMI = new MachineModuleInfo(TM); - MMI->setMachineFunctionInitializer(MFInitializer); PM.add(MMI); // Enable FastISel with -fast, but allow that to be overridden. @@ -194,12 +191,11 @@ bool LLVMTargetMachine::addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter, - AnalysisID StopBefore, AnalysisID StopAfter, - MachineFunctionInitializer *MFInitializer) { + AnalysisID StopBefore, AnalysisID StopAfter) { // Add common CodeGen passes. MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, StartBefore, StartAfter, - StopBefore, StopAfter, MFInitializer); + StopBefore, StopAfter); if (!Context) return true; Index: lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIRParser.cpp +++ lib/CodeGen/MIRParser/MIRParser.cpp @@ -50,18 +50,22 @@ /// file. class MIRParserImpl { SourceMgr SM; + yaml::Input In; StringRef Filename; LLVMContext &Context; - StringMap> Functions; SlotMapping IRSlots; /// Maps from register class names to register classes. Name2RegClassMap Names2RegClasses; /// Maps from register bank names to register banks. Name2RegBankMap Names2RegBanks; + /// True when the MIR file doesn't have LLVM IR. Dummy IR functions are + /// created and inserted into the given module when this is true. + bool NoLLVMIR = false; + bool NoMIRDocuments = false; public: - MIRParserImpl(std::unique_ptr Contents, StringRef Filename, - LLVMContext &Context); + MIRParserImpl(std::unique_ptr Contents, + StringRef Filename, LLVMContext &Context); void reportDiagnostic(const SMDiagnostic &Diag); @@ -85,22 +89,22 @@ /// file. /// /// Return null if an error occurred. - std::unique_ptr parse(); + std::unique_ptr parseIRModule(); + + bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI); /// Parse the machine function in the current YAML document. /// - /// \param NoLLVMIR - set to true when the MIR file doesn't have LLVM IR. - /// A dummy IR function is created and inserted into the given module when - /// this parameter is true. /// /// Return true if an error occurred. - bool parseMachineFunction(yaml::Input &In, Module &M, bool NoLLVMIR); + bool parseMachineFunction(Module &M, MachineModuleInfo &MMI); /// Initialize the machine function to the state that's described in the MIR /// file. /// /// Return true if error occurred. - bool initializeMachineFunction(MachineFunction &MF); + bool initializeMachineFunction(const yaml::MachineFunction &YamlMF, + MachineFunction &MF); bool parseRegisterInfo(PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF); @@ -144,9 +148,6 @@ SMDiagnostic diagFromBlockStringDiag(const SMDiagnostic &Error, SMRange SourceRange); - /// Create an empty function with the given name. - void createDummyFunction(StringRef Name, Module &M); - void initNames2RegClasses(const MachineFunction &MF); void initNames2RegBanks(const MachineFunction &MF); @@ -166,10 +167,19 @@ } // end namespace llvm +static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) { + reinterpret_cast(Context)->reportDiagnostic(Diag); +} + MIRParserImpl::MIRParserImpl(std::unique_ptr Contents, StringRef Filename, LLVMContext &Context) - : SM(), Filename(Filename), Context(Context) { - SM.AddNewSourceBuffer(std::move(Contents), SMLoc()); + : SM(), + In(SM.getMemoryBuffer( + SM.AddNewSourceBuffer(std::move(Contents), SMLoc()))->getBuffer(), + nullptr, handleYAMLDiag, this), + Filename(Filename), + Context(Context) { + In.setContext(&In); } bool MIRParserImpl::error(const Twine &Message) { @@ -206,24 +216,16 @@ Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag)); } -static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) { - reinterpret_cast(Context)->reportDiagnostic(Diag); -} - -std::unique_ptr MIRParserImpl::parse() { - yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(), - /*Ctxt=*/nullptr, handleYAMLDiag, this); - In.setContext(&In); - +std::unique_ptr MIRParserImpl::parseIRModule() { if (!In.setCurrentDocument()) { if (In.error()) return nullptr; // Create an empty module when the MIR file is empty. + NoMIRDocuments = true; return llvm::make_unique(Filename, Context); } std::unique_ptr M; - bool NoLLVMIR = false; // Parse the block scalar manually so that we can return unique pointer // without having to go trough YAML traits. if (const auto *BSN = @@ -237,49 +239,68 @@ } In.nextDocument(); if (!In.setCurrentDocument()) - return M; + NoMIRDocuments = true; } else { // Create an new, empty module. M = llvm::make_unique(Filename, Context); NoLLVMIR = true; } + return M; +} + +bool MIRParserImpl::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) { + if (NoMIRDocuments) + return false; // Parse the machine functions. do { - if (parseMachineFunction(In, *M, NoLLVMIR)) - return nullptr; + if (parseMachineFunction(M, MMI)) + return true; In.nextDocument(); } while (In.setCurrentDocument()); - return M; -} - -bool MIRParserImpl::parseMachineFunction(yaml::Input &In, Module &M, - bool NoLLVMIR) { - auto MF = llvm::make_unique(); - yaml::EmptyContext Ctx; - yaml::yamlize(In, *MF, false, Ctx); - if (In.error()) - return true; - auto FunctionName = MF->Name; - if (Functions.find(FunctionName) != Functions.end()) - return error(Twine("redefinition of machine function '") + FunctionName + - "'"); - Functions.insert(std::make_pair(FunctionName, std::move(MF))); - if (NoLLVMIR) - createDummyFunction(FunctionName, M); - else if (!M.getFunction(FunctionName)) - return error(Twine("function '") + FunctionName + - "' isn't defined in the provided LLVM IR"); return false; } -void MIRParserImpl::createDummyFunction(StringRef Name, Module &M) { +/// Create an empty function with the given name. +static Function *createDummyFunction(StringRef Name, Module &M) { auto &Context = M.getContext(); Function *F = cast(M.getOrInsertFunction( Name, FunctionType::get(Type::getVoidTy(Context), false))); BasicBlock *BB = BasicBlock::Create(Context, "entry", F); new UnreachableInst(Context, BB); + return F; +} + +bool MIRParserImpl::parseMachineFunction(Module &M, MachineModuleInfo &MMI) { + // Parse the yaml. + yaml::MachineFunction YamlMF; + yaml::EmptyContext Ctx; + yaml::yamlize(In, YamlMF, false, Ctx); + if (In.error()) + return true; + + // Search for the corresponding IR function. + StringRef FunctionName = YamlMF.Name; + Function *F = M.getFunction(FunctionName); + if (!F) { + if (NoLLVMIR) { + F = createDummyFunction(FunctionName, M); + } else { + return error(Twine("function '") + FunctionName + + "' isn't defined in the provided LLVM IR"); + } + } + if (MMI.queryMachineFunction(*F) != nullptr) + return error(Twine("redefinition of machine function '") + FunctionName + + "'"); + + // Create the MachineFunction. + MachineFunction &MF = MMI.getMachineFunction(*F); + if (initializeMachineFunction(YamlMF, MF)) + return true; + + return false; } static bool isSSA(const MachineFunction &MF) { @@ -319,15 +340,12 @@ Properties.set(MachineFunctionProperties::Property::NoVRegs); } -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"); +bool +MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF, + MachineFunction &MF) { // TODO: Recreate the machine function. initNames2RegClasses(MF); initNames2RegBanks(MF); - const yaml::MachineFunction &YamlMF = *It->getValue(); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); @@ -838,10 +856,12 @@ MIRParser::~MIRParser() {} -std::unique_ptr MIRParser::parseLLVMModule() { return Impl->parse(); } +std::unique_ptr MIRParser::parseIRModule() { + return Impl->parseIRModule(); +} -bool MIRParser::initializeMachineFunction(MachineFunction &MF) { - return Impl->initializeMachineFunction(MF); +bool MIRParser::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) { + return Impl->parseMachineFunctions(M, MMI); } std::unique_ptr llvm::createMIRParserFromFile(StringRef Filename, Index: lib/CodeGen/MachineFunction.cpp =================================================================== --- lib/CodeGen/MachineFunction.cpp +++ lib/CodeGen/MachineFunction.cpp @@ -20,7 +20,6 @@ #include "llvm/Analysis/EHPersonalities.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" @@ -52,8 +51,6 @@ cl::desc("Force the alignment of all functions."), cl::init(0), cl::Hidden); -void MachineFunctionInitializer::anchor() {} - static const char *getPropertyName(MachineFunctionProperties::Property Prop) { typedef MachineFunctionProperties::Property P; switch(Prop) { Index: lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- lib/CodeGen/MachineModuleInfo.cpp +++ lib/CodeGen/MachineModuleInfo.cpp @@ -13,7 +13,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionInitializer.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/BasicBlock.h" @@ -259,6 +258,12 @@ /// \} +MachineFunction * +MachineModuleInfo::queryMachineFunction(const Function &F) const { + auto I = MachineFunctions.find(&F); + return I != MachineFunctions.end() ? I->second.get() : nullptr; +} + MachineFunction &MachineModuleInfo::getMachineFunction(const Function &F) { // Shortcut for the common case where a sequence of MachineFunctionPasses // all query for the same Function. @@ -273,10 +278,6 @@ MF = new MachineFunction(&F, TM, NextFnNum++, *this); // Update the set entry. I.first->second.reset(MF); - - if (MFInitializer) - if (MFInitializer->initializeMachineFunction(*MF)) - report_fatal_error("Unable to initialize machine function"); } else { MF = I.first->second.get(); } Index: test/CodeGen/MIR/AArch64/generic-virtual-registers-error.mir =================================================================== --- test/CodeGen/MIR/AArch64/generic-virtual-registers-error.mir +++ test/CodeGen/MIR/AArch64/generic-virtual-registers-error.mir @@ -17,6 +17,5 @@ liveins: %w0 ; ERR: generic virtual registers must have a type ; ERR-NEXT: %0 - ; ERR: Unable to initialize machine function %0 = G_ADD i32 %w0, %w0 ... Index: test/CodeGen/MIR/AArch64/generic-virtual-registers-with-regbank-error.mir =================================================================== --- test/CodeGen/MIR/AArch64/generic-virtual-registers-with-regbank-error.mir +++ test/CodeGen/MIR/AArch64/generic-virtual-registers-with-regbank-error.mir @@ -18,6 +18,5 @@ liveins: %w0 ; ERR: generic virtual registers must have a type ; ERR-NEXT: %0 - ; ERR: Unable to initialize machine function %0 = G_ADD i32 %w0, %w0 ... Index: test/CodeGen/MIR/Generic/function-missing-machine-function.mir =================================================================== --- test/CodeGen/MIR/Generic/function-missing-machine-function.mir +++ /dev/null @@ -1,13 +0,0 @@ -# RUN: not llc -run-pass none -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/X86/empty0.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/X86/empty0.mir @@ -0,0 +1,6 @@ +# RUN: llc -run-pass none -o - %s | FileCheck %s +# Make sure empty files don't crash us +# CHECK: --- | +# ... moduleid, sourcefilename stuff here .. +# CHECK: target datalayout = +# CHECK: ... Index: test/CodeGen/MIR/X86/empty1.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/X86/empty1.mir @@ -0,0 +1,8 @@ +# RUN: llc -run-pass none -o - %s | FileCheck %s +# Make sure empty files don't crash us +--- | +... +# CHECK: --- | +# ... moduleid, sourcefilename stuff here .. +# CHECK: target datalayout = +# CHECK: ... Index: test/CodeGen/MIR/X86/empty2.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/X86/empty2.mir @@ -0,0 +1,8 @@ +# RUN: llc -run-pass none -o - %s | FileCheck %s +# Make sure empty files don't crash us +--- +... +# CHECK: --- | +# ... moduleid, sourcefilename stuff here .. +# CHECK: target datalayout = +# CHECK: ... Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -398,7 +398,7 @@ if (StringRef(InputFilename).endswith_lower(".mir")) { MIR = createMIRParserFromFile(InputFilename, Err, Context); if (MIR) - M = MIR->parseLLVMModule(); + M = MIR->parseIRModule(); } else M = parseIRFile(InputFilename, Err, Context); if (!M) { @@ -530,7 +530,8 @@ TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM); PM.add(&TPC); MachineModuleInfo *MMI = new MachineModuleInfo(&LLVMTM); - MMI->setMachineFunctionInitializer(MIR.get()); + if (MIR->parseMachineFunctions(*M, *MMI)) + return 1; PM.add(MMI); TPC.printAndVerify(""); @@ -558,7 +559,7 @@ // Ask the target to add backend passes as necessary. if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartBeforeID, StartAfterID, StopBeforeID, - StopAfterID, MIR.get())) { + StopAfterID)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1;