Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h +++ include/llvm/CodeGen/Passes.h @@ -374,6 +374,10 @@ createMachineFunctionPrinterPass(raw_ostream &OS, const std::string &Banner =""); + /// MachineLevelIRPrinting pass - this pass prints out the machine level IR + /// to the given stream. + MachineFunctionPass *createMachineLevelIRPrintingPass(raw_ostream &OS); + /// createCodeGenPreparePass - Transform the code to expose more pattern /// matching during instruction selection. FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr); @@ -488,6 +492,9 @@ /// MachineFunctionPrinterPass - This pass prints out MachineInstr's. extern char &MachineFunctionPrinterPassID; + /// MachineLevelIRPrintingPass - This pass prints out machine level IR. + extern char &MachineLevelIRPrintingPassID; + /// TailDuplicate - Duplicate blocks with unconditional branches /// into tails of their predecessors. extern char &TailDuplicateID; Index: include/llvm/CodeGen/Serialization/Parser.h =================================================================== --- /dev/null +++ include/llvm/CodeGen/Serialization/Parser.h @@ -0,0 +1,76 @@ +//===- Parser.h - Machine level IR parser ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the functions that parse the machine level IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SERIALIZATION_PARSER_H +#define LLVM_CODEGEN_SERIALIZATION_PARSER_H + +#include "llvm/IR/Module.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ErrorOr.h" +#include +#include + +namespace llvm { + +class SMDiagnostic; +class MachineLevelIRParserImpl; + +/// \brief This class parses the machine level IR. +/// It allows the users to parse the machine level IR at a later stage, +/// for example, after they created the TargetMachine using the target triple +/// in the already parsed LLVM module. +class MachineLevelIRParser { + std::unique_ptr Impl; + +public: + MachineLevelIRParser(std::unique_ptr Impl); + MachineLevelIRParser(const MachineLevelIRParser &) = delete; + ~MachineLevelIRParser(); + + /// \brief Parse the machine level IR. + void parseMachineLevelIR(TargetMachine &TM, Module &M, + std::vector &Errs); +}; + +typedef std::pair, + std::unique_ptr> MIRParseResult; + +/// \brief This function is the main interface to the machine level IR parser. +/// It reads a YAML file that contains machine level IR and the optional +/// LLVM IR, parses the LLVM IR, and returns an LLVM module and an instance of a +/// MachineLevelIRParser that allows the user to parse the machine level IR +/// at a later stage. +/// \param Filename - The name of the file to parse. +/// \param Errs - The array into which the parsing errors are placed. +/// \param Context - Context in which to allocate globals info. +MIRParseResult beginParsingMachineLevelIRFile(StringRef Filename, + std::vector &Errs, + LLVMContext &Context); + +/// \brief This function is another interface to the machine level IR parser. +/// It parses the optional LLVM IR in the given buffer, and returns an LLVM +/// module and an instance of a MachineLevelIRParser that allows the user to +/// parse the machine level IR at a later stage. +/// \param Contents - The MemoryBuffer containing the machine level IR. +/// \param Errs - The array into which the parsing errors are placed. +/// \param Context - Context in which to allocate globals info. +MIRParseResult +beginParsingMachineLevelIR(std::unique_ptr Contents, + std::vector &Errs, + LLVMContext &Context); + +} // End llvm namespace + +#endif Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -289,6 +289,7 @@ void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); +void initializeMachineLevelIRPrintingPassPass(PassRegistry &); void initializeStackMapLivenessPass(PassRegistry&); void initializeMachineCombinerPass(PassRegistry &); void initializeLoadCombinePass(PassRegistry&); Index: include/llvm/Support/YAMLTraits.h =================================================================== --- include/llvm/Support/YAMLTraits.h +++ include/llvm/Support/YAMLTraits.h @@ -1089,6 +1089,9 @@ bool setCurrentDocument(); bool nextDocument(); + /// \brief Returns the current node that's being parsed by the YAML Parser. + const Node *getCurrentNode(); + private: llvm::SourceMgr SrcMgr; // must be before Strm std::unique_ptr Strm; Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -128,3 +128,4 @@ add_subdirectory(SelectionDAG) add_subdirectory(AsmPrinter) +add_subdirectory(Serialization) Index: lib/CodeGen/LLVMBuild.txt =================================================================== --- lib/CodeGen/LLVMBuild.txt +++ lib/CodeGen/LLVMBuild.txt @@ -16,10 +16,10 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = AsmPrinter SelectionDAG +subdirectories = AsmPrinter SelectionDAG Serialization [component_0] type = Library name = CodeGen parent = Libraries -required_libraries = Analysis Core MC Scalar Support Target TransformUtils +required_libraries = Analysis Core MC Scalar Support Target TransformUtils CodeGenSerialization Index: lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- lib/CodeGen/LLVMTargetMachine.cpp +++ lib/CodeGen/LLVMTargetMachine.cpp @@ -150,12 +150,7 @@ return true; if (StopAfter) { - // FIXME: The intent is that this should eventually write out a YAML file, - // containing the LLVM IR, the machine-level IR (when stopping after a - // machine-level pass), and whatever other information is needed to - // deserialize the code and resume compilation. For now, just write the - // LLVM IR. - PM.add(createPrintModulePass(Out)); + PM.add(createMachineLevelIRPrintingPass(outs())); return false; } Index: lib/CodeGen/Makefile =================================================================== --- lib/CodeGen/Makefile +++ lib/CodeGen/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMCodeGen -PARALLEL_DIRS = SelectionDAG AsmPrinter +PARALLEL_DIRS = SelectionDAG AsmPrinter Serialization BUILD_ARCHIVE = 1 include $(LEVEL)/Makefile.common Index: lib/CodeGen/Serialization/CMakeLists.txt =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/CMakeLists.txt @@ -0,0 +1,8 @@ +add_llvm_library(LLVMCodeGenSerialization + YAML.cpp + MIRPrintingPass.cpp + Parser.cpp + MIRParser.cpp + ) + +add_dependencies(LLVMCodeGenSerialization intrinsics_gen) Index: lib/CodeGen/Serialization/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./lib/CodeGen/Serialization/LLVMBuild.txt ----------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = CodeGenSerialization +parent = CodeGen +required_libraries = Core Support Target AsmParser Index: lib/CodeGen/Serialization/MIRParser.h =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/MIRParser.h @@ -0,0 +1,51 @@ +//===- MIRParser.h - Machine level IR parser ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the class that parses the machine level IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_SERIALIZATION_MIRPARSER_H +#define LLVM_LIB_CODEGEN_SERIALIZATION_MIRPARSER_H + +#include "llvm/IR/Module.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include + +namespace llvm { + +class SMDiagnostic; + +/// \brief This class implements machine level IR parsing. +class MachineLevelIRParserImpl { + SourceMgr SM; + StringRef Filename; + LLVMContext &Context; + bool HasLLVMModule; + +public: + MachineLevelIRParserImpl(std::unique_ptr Contents, + StringRef Filename, LLVMContext &Context); + + /// \brief Try to parse the optional LLVM module in the MIR file. Return null + /// if an error occurred while parsing the LLVM module. + std::unique_ptr parseLLVMModule(std::vector &Errs); + +private: + /// \brief Parse the LLVM module in the given string. + std::unique_ptr parseLLVMModule(StringRef Str, SMRange SourceRange, + std::vector &Errs); +}; + +} // End llvm namespace + +#endif Index: lib/CodeGen/Serialization/MIRParser.cpp =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/MIRParser.cpp @@ -0,0 +1,66 @@ +//===- MIRParser.cpp - Machine level IR parser implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the machine level IR parser class. +// +//===----------------------------------------------------------------------===// + +#include "MIRParser.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +MachineLevelIRParserImpl::MachineLevelIRParserImpl( + std::unique_ptr Contents, StringRef Filename, + LLVMContext &Context) + : SM(), Filename(Filename), Context(Context), HasLLVMModule(false) { + SM.AddNewSourceBuffer(std::move(Contents), SMLoc()); +} + +std::unique_ptr +MachineLevelIRParserImpl::parseLLVMModule(StringRef Str, SMRange SourceRange, + std::vector &Errs) { + SMDiagnostic LLErr; + auto Mod = parseAssembly(MemoryBufferRef(Str, Filename), LLErr, Context); + if (LLErr.getLineNo()) { + if (!SourceRange.isValid()) { + Errs.push_back(LLErr); + return Mod; + } + + // Translate the location of the error from the location in the llvm IR + // string to the corresponding location in the mir file. + auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start); + unsigned Line = LineAndColumn.first + LLErr.getLineNo() - 1; + unsigned Column = LLErr.getColumnNo(); + StringRef LineStr = LLErr.getLineContents(); + SMLoc Loc = LLErr.getLoc(); + + // Get the full line and adjust the column number by taking indentation + // of LLVM IR into account. + for (line_iterator Lines(*SM.getMemoryBuffer(SM.getMainFileID()), false); + !Lines.is_at_end(); ++Lines) { + if (Lines.line_number() == Line) { + LineStr = *Lines; + Loc = SMLoc::getFromPointer(LineStr.data()); + auto Indent = LineStr.find(LLErr.getLineContents()); + if (Indent != StringRef::npos) + Column += Indent; + } + } + + Errs.push_back(SMDiagnostic(SM, Loc, Filename, Line, Column, + LLErr.getKind(), LLErr.getMessage(), LineStr, + LLErr.getRanges(), LLErr.getFixIts())); + } + return Mod; +} Index: lib/CodeGen/Serialization/MIRPrintingPass.cpp =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/MIRPrintingPass.cpp @@ -0,0 +1,73 @@ +//===- IRPrintingPass.cpp - Pass that prints out the machine level IR -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a pass that prints out the machine level IR. +// +//===----------------------------------------------------------------------===// + +#include "YAML.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { + +/// MachineLevelIRPrintingPass - This pass prints out the machine level IR to +/// an output stream. +struct MachineLevelIRPrintingPass : public MachineFunctionPass { + static char ID; + raw_ostream &OS; + bool HaveToPrintModule; + + MachineLevelIRPrintingPass() + : MachineFunctionPass(ID), OS(dbgs()), HaveToPrintModule(true) {} + MachineLevelIRPrintingPass(raw_ostream &OS) + : MachineFunctionPass(ID), OS(OS), HaveToPrintModule(true) {} + + const char *getPassName() const override { + return "Machine Level IR Printing Pass"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + void printModule(const Module *Mod) { + MachineLevelIRPrinter Printer(OS); + Printer.printModule(Mod); + HaveToPrintModule = false; + } + + bool runOnMachineFunction(MachineFunction &MF) override { + if (HaveToPrintModule) + printModule(MF.getMMI().getModule()); + // TODO: Print out the machine function. + return false; + } +}; + +char MachineLevelIRPrintingPass::ID = 0; +} + +char &llvm::MachineLevelIRPrintingPassID = MachineLevelIRPrintingPass::ID; +INITIALIZE_PASS(MachineLevelIRPrintingPass, "machinelevelir-printer", + "Machine Level IR Printer", false, false) + +namespace llvm { + +MachineFunctionPass *createMachineLevelIRPrintingPass(raw_ostream &OS) { + return new MachineLevelIRPrintingPass(OS); +} +} Index: lib/CodeGen/Serialization/Makefile =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/Makefile @@ -0,0 +1,13 @@ +##===- lib/CodeGen/Serialization/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMCodeGenSerialization + +include $(LEVEL)/Makefile.common Index: lib/CodeGen/Serialization/Parser.cpp =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/Parser.cpp @@ -0,0 +1,56 @@ +//===- Parser.cpp - Machine level IR parser implementation ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the functions that parse the machine level IR. +// +//===----------------------------------------------------------------------===// + +#include "MIRParser.h" +#include "llvm/CodeGen/Serialization/Parser.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +MachineLevelIRParser::MachineLevelIRParser( + std::unique_ptr Impl) + : Impl(std::move(Impl)) {} + +MachineLevelIRParser::~MachineLevelIRParser() {} + +void MachineLevelIRParser::parseMachineLevelIR( + TargetMachine &TM, Module &M, std::vector &Errs) { + // TODO: Parse machine functions. +} + +MIRParseResult llvm::beginParsingMachineLevelIRFile( + StringRef Filename, std::vector &Errs, LLVMContext &Context) { + auto FileOrErr = MemoryBuffer::getFile(Filename); + if (auto EC = FileOrErr.getError()) { + Errs.push_back(SMDiagnostic(Filename, SourceMgr::DK_Error, + "Could not open input file: " + EC.message())); + return std::make_pair(std::unique_ptr(), + std::unique_ptr()); + } + return beginParsingMachineLevelIR(std::move(FileOrErr.get()), Errs, Context); +} + +MIRParseResult +llvm::beginParsingMachineLevelIR(std::unique_ptr Contents, + std::vector &Errs, + LLVMContext &Context) { + auto Parser = llvm::make_unique( + std::move(Contents), Contents->getBufferIdentifier(), Context); + return std::make_pair( + std::move(Parser->parseLLVMModule(Errs)), + llvm::make_unique(std::move(Parser))); +} Index: lib/CodeGen/Serialization/YAML.h =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/YAML.h @@ -0,0 +1,36 @@ +//===- YAML.h - YAML IO utilities for machine level IR --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares some of the utility classes for handling the YAML +// representation of machine level IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_SERIALIZATION_YAML_H +#define LLVM_LIB_CODEGEN_SERIALIZATION_YAML_H + +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { + +class Module; + +/// \brief This class prints out the machine level IR using YAML IO. +class MachineLevelIRPrinter { + raw_ostream &OS; + +public: + MachineLevelIRPrinter(raw_ostream &OS); + + void printModule(const Module *Mod); +}; + +} // End llvm namespace + +#endif Index: lib/CodeGen/Serialization/YAML.cpp =================================================================== --- /dev/null +++ lib/CodeGen/Serialization/YAML.cpp @@ -0,0 +1,66 @@ +//===- YAML.cpp - YAML IO utilities for machine level IR ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines utility classes for handling the YAML representation of +// machine level IR. +// +//===----------------------------------------------------------------------===// + +#include "YAML.h" +#include "MIRParser.h" +#include "llvm/IR/Module.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +typedef const Module *ModuleRef; + +namespace llvm { +namespace yaml { + +/// \brief This class serializes the LLVM IR module. +template <> struct BlockScalarTraits { + static void output(const ModuleRef &Mod, void *Ctxt, raw_ostream &OS) { + Mod->print(OS, nullptr); + } + static StringRef input(StringRef Str, void *Ctxt, ModuleRef &Mod) { + assert(false && "LLVM Module is supposed to be parsed separately"); + return StringRef(); + } +}; +} +} + +MachineLevelIRPrinter::MachineLevelIRPrinter(raw_ostream &OS) : OS(OS) {} + +void MachineLevelIRPrinter::printModule(const Module *Mod) { + yaml::Output Out(OS); + Out << Mod; +} + +std::unique_ptr +MachineLevelIRParserImpl::parseLLVMModule(std::vector &Errs) { + yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(), this); + + // We need access to the YAML nodes in order to get their source ranges so + // that it will be possible to use correct source locations in the diagnostic + // messages. + if (In.setCurrentDocument()) { + if (const auto *BSN = + dyn_cast_or_null(In.getCurrentNode())) { + HasLLVMModule = true; + return parseLLVMModule(BSN->getValue(), BSN->getSourceRange(), Errs); + } + } + + return llvm::make_unique(Filename, Context); +} Index: lib/Support/YAMLTraits.cpp =================================================================== --- lib/Support/YAMLTraits.cpp +++ lib/Support/YAMLTraits.cpp @@ -97,6 +97,10 @@ return ++DocIterator != Strm->end(); } +const Node *Input::getCurrentNode() { + return CurrentNode ? CurrentNode->_node : nullptr; +} + bool Input::mapTag(StringRef Tag, bool Default) { std::string foundTag = CurrentNode->_node->getVerbatimTag(); if (foundTag.empty()) { Index: test/CodeGen/Generic/stop-after.ll =================================================================== --- test/CodeGen/Generic/stop-after.ll +++ test/CodeGen/Generic/stop-after.ll @@ -1,9 +1,10 @@ ; RUN: llc < %s -debug-pass=Structure -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP ; RUN: llc < %s -debug-pass=Structure -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START -; STOP: -loop-reduce -print-module +; STOP: -loop-reduce ; STOP: Loop Strength Reduction ; STOP-NEXT: Machine Function Analysis +; STOP-NEXT: Machine Level IR Printing Pass ; START: -machine-branch-prob -gc-lowering ; START: FunctionPass Manager Index: test/CodeGen/Serialization/lit.local.cfg =================================================================== --- /dev/null +++ test/CodeGen/Serialization/lit.local.cfg @@ -0,0 +1,2 @@ +config.suffixes = ['.mir'] + Index: test/CodeGen/Serialization/llvmIR.mir =================================================================== --- /dev/null +++ test/CodeGen/Serialization/llvmIR.mir @@ -0,0 +1,35 @@ +# RUN: ~/build/llvm/bin/llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s +# This test ensures that the LLVM IR that's embedded with machine level IR is +# parsed correctly. + +--- | + target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-apple-darwin14.3.0" + + ; CHECK: define i32 @foo(i32 %x, i32 %y) + ; CHECK: %z = alloca i32, align 4 + ; CHECK: store i32 %x, i32* %z, align 4 + ; CHECK: br label %Test + ; CHECK: Test: + ; CHECK: %m = load i32, i32* %z, align 4 + ; CHECK: %cond = icmp eq i32 %y, %m + ; CHECK: br i1 %cond, label %IfEqual, label %IfUnequal + ; CHECK: IfEqual: + ; CHECK: ret i32 1 + ; CHECK: IfUnequal: + ; CHECK: ret i32 0 + define i32 @foo(i32 %x, i32 %y) { + %z = alloca i32, align 4 + store i32 %x, i32* %z, align 4 + br label %Test + Test: + %m = load i32, i32* %z, align 4 + %cond = icmp eq i32 %y, %m + br i1 %cond, label %IfEqual, label %IfUnequal + IfEqual: + ret i32 1 + IfUnequal: + ret i32 0 + } + +... Index: test/CodeGen/Serialization/llvmIRError.mir =================================================================== --- /dev/null +++ test/CodeGen/Serialization/llvmIRError.mir @@ -0,0 +1,24 @@ +# RUN: not ~/build/llvm/bin/llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# This test ensures an error is reported if the embedded LLVM IR contains an +# error. + +--- | + target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-apple-darwin14.3.0" + + ; CHECK: 12:15: error: use of undefined value '%a' + define i32 @foo(i32 %x, i32 %y) { + %z = alloca i32, align 4 + store i32 %a, i32* %z, align 4 + br label %Test + Test: + %m = load i32, i32* %z, align 4 + %cond = icmp eq i32 %y, %m + br i1 %cond, label %IfEqual, label %IfUnequal + IfEqual: + ret i32 1 + IfUnequal: + ret i32 0 + } + +... Index: test/CodeGen/Serialization/llvmIRMissing.mir =================================================================== --- /dev/null +++ test/CodeGen/Serialization/llvmIRMissing.mir @@ -0,0 +1,5 @@ +# RUN: ~/build/llvm/bin/llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s +# This test ensures that the MIR parser accepts files without the LLVM IR. + +--- +... Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" +#include "llvm/CodeGen/Serialization/Parser.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" @@ -109,6 +110,8 @@ StringRef IFN = InputFilename; if (IFN.endswith(".bc") || IFN.endswith(".ll")) OutputFilename = IFN.drop_back(3); + else if (IFN.endswith(".mir")) + OutputFilename = IFN.drop_back(4); else OutputFilename = IFN; @@ -206,7 +209,9 @@ static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; + std::vector Errs; std::unique_ptr M; + std::unique_ptr MIRParser; Triple TheTriple; bool SkipModule = MCPU == "help" || @@ -214,10 +219,22 @@ // If user just wants to list available options, skip module loading if (!SkipModule) { - M = parseIRFile(InputFilename, Err, Context); - if (!M) { - Err.print(argv[0], errs()); - return 1; + if (StringRef(InputFilename).endswith_lower(".mir")) { + auto ParseState = + beginParsingMachineLevelIRFile(InputFilename, Errs, Context); + M = std::move(ParseState.first); + MIRParser = std::move(ParseState.second); + if (!M) { + for (const auto &Err : Errs) + Err.print(argv[0], errs()); + return 1; + } + } else { + M = parseIRFile(InputFilename, Err, Context); + if (!M) { + Err.print(argv[0], errs()); + return 1; + } } // Verify module immediately to catch problems before doInitialization() is @@ -280,6 +297,17 @@ if (SkipModule) return 0; + // We have the target machine, so finish parsing the machine level IR if + // required. + if (MIRParser) { + MIRParser->parseMachineLevelIR(*Target, *M, Errs); + if (!Errs.empty()) { + for (const auto &Err : Errs) + Err.print(argv[0], errs()); + return 1; + } + } + assert(M && "Should have exited if we didn't have a module!"); if (GenerateSoftFloatCalls)