summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/MIRParser/MIRParser.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/MIRParser/MIRParser.cpp175
1 files changed, 150 insertions, 25 deletions
diff --git a/contrib/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/contrib/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 7a51b38..1fef3f6 100644
--- a/contrib/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/contrib/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -14,10 +14,17 @@
#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/BasicBlock.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
@@ -27,7 +34,7 @@
using namespace llvm;
-namespace {
+namespace llvm {
/// This class implements the parsing of LLVM IR that's embedded inside a MIR
/// file.
@@ -35,29 +42,56 @@ class MIRParserImpl {
SourceMgr SM;
StringRef Filename;
LLVMContext &Context;
+ StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
public:
MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
LLVMContext &Context);
+ void reportDiagnostic(const SMDiagnostic &Diag);
+
+ /// Report an error with the given message at unknown location.
+ ///
+ /// Always returns true.
+ bool error(const Twine &Message);
+
/// Try to parse the optional LLVM module and the machine functions in the MIR
/// file.
///
/// Return null if an error occurred.
- std::unique_ptr<Module> parse(SMDiagnostic &Error);
+ std::unique_ptr<Module> parse();
/// Parse the machine function in the current YAML document.
///
+ /// \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);
+
+ /// Initialize the machine function to the state that's described in the MIR
+ /// file.
+ ///
+ /// Return true if error occurred.
+ bool initializeMachineFunction(MachineFunction &MF);
+
+ /// Initialize the machine basic block using it's YAML representation.
+ ///
/// Return true if an error occurred.
- bool parseMachineFunction(yaml::Input &In);
+ bool initializeMachineBasicBlock(MachineBasicBlock &MBB,
+ const yaml::MachineBasicBlock &YamlMBB);
private:
/// Return a MIR diagnostic converted from an LLVM assembly diagnostic.
SMDiagnostic diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
SMRange SourceRange);
+
+ /// Create an empty function with the given name.
+ void createDummyFunction(StringRef Name, Module &M);
};
-} // end anonymous namespace
+} // end namespace llvm
MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
StringRef Filename, LLVMContext &Context)
@@ -65,30 +99,54 @@ MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
}
+bool MIRParserImpl::error(const Twine &Message) {
+ Context.diagnose(DiagnosticInfoMIRParser(
+ DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
+ return true;
+}
+
+void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
+ DiagnosticSeverity Kind;
+ switch (Diag.getKind()) {
+ case SourceMgr::DK_Error:
+ Kind = DS_Error;
+ break;
+ case SourceMgr::DK_Warning:
+ Kind = DS_Warning;
+ break;
+ case SourceMgr::DK_Note:
+ Kind = DS_Note;
+ break;
+ }
+ Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
+}
+
static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
- *reinterpret_cast<SMDiagnostic *>(Context) = Diag;
+ reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
}
-std::unique_ptr<Module> MIRParserImpl::parse(SMDiagnostic &Error) {
+std::unique_ptr<Module> MIRParserImpl::parse() {
yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
- /*Ctxt=*/nullptr, handleYAMLDiag, &Error);
+ /*Ctxt=*/nullptr, handleYAMLDiag, this);
if (!In.setCurrentDocument()) {
- if (!Error.getMessage().empty())
+ if (In.error())
return nullptr;
// Create an empty module when the MIR file is empty.
return llvm::make_unique<Module>(Filename, Context);
}
std::unique_ptr<Module> 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 =
dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
+ SMDiagnostic Error;
M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
Context);
if (!M) {
- Error = diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange());
+ reportDiagnostic(diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange()));
return M;
}
In.nextDocument();
@@ -97,11 +155,12 @@ std::unique_ptr<Module> MIRParserImpl::parse(SMDiagnostic &Error) {
} else {
// Create an new, empty module.
M = llvm::make_unique<Module>(Filename, Context);
+ NoLLVMIR = true;
}
// Parse the machine functions.
do {
- if (parseMachineFunction(In))
+ if (parseMachineFunction(In, *M, NoLLVMIR))
return nullptr;
In.nextDocument();
} while (In.setCurrentDocument());
@@ -109,13 +168,68 @@ std::unique_ptr<Module> MIRParserImpl::parse(SMDiagnostic &Error) {
return M;
}
-bool MIRParserImpl::parseMachineFunction(yaml::Input &In) {
- yaml::MachineFunction MF;
- yaml::yamlize(In, MF, false);
+bool MIRParserImpl::parseMachineFunction(yaml::Input &In, Module &M,
+ bool NoLLVMIR) {
+ 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;
+ 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) {
+ auto &Context = M.getContext();
+ Function *F = cast<Function>(M.getOrInsertFunction(
+ Name, FunctionType::get(Type::getVoidTy(Context), false)));
+ BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
+ new UnreachableInst(Context, BB);
+}
+
+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.
+ const yaml::MachineFunction &YamlMF = *It->getValue();
+ if (YamlMF.Alignment)
+ MF.setAlignment(YamlMF.Alignment);
+ MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
+ MF.setHasInlineAsm(YamlMF.HasInlineAsm);
+ const auto &F = *MF.getFunction();
+ for (const auto &YamlMBB : YamlMF.BasicBlocks) {
+ const BasicBlock *BB = nullptr;
+ if (!YamlMBB.Name.empty()) {
+ BB = dyn_cast_or_null<BasicBlock>(
+ F.getValueSymbolTable().lookup(YamlMBB.Name));
+ if (!BB)
+ return error(Twine("basic block '") + YamlMBB.Name +
+ "' is not defined in the function '" + MF.getName() + "'");
+ }
+ auto *MBB = MF.CreateMachineBasicBlock(BB);
+ MF.insert(MF.end(), MBB);
+ if (initializeMachineBasicBlock(*MBB, YamlMBB))
+ return true;
+ }
+ return false;
+}
+
+bool MIRParserImpl::initializeMachineBasicBlock(
+ MachineBasicBlock &MBB, const yaml::MachineBasicBlock &YamlMBB) {
+ MBB.setAlignment(YamlMBB.Alignment);
+ if (YamlMBB.AddressTaken)
+ MBB.setHasAddressTaken();
+ MBB.setIsLandingPad(YamlMBB.IsLandingPad);
return false;
}
@@ -150,22 +264,33 @@ SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
Error.getFixIts());
}
-std::unique_ptr<Module> llvm::parseMIRFile(StringRef Filename,
- SMDiagnostic &Error,
- LLVMContext &Context) {
+MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
+ : Impl(std::move(Impl)) {}
+
+MIRParser::~MIRParser() {}
+
+std::unique_ptr<Module> MIRParser::parseLLVMModule() { return Impl->parse(); }
+
+bool MIRParser::initializeMachineFunction(MachineFunction &MF) {
+ return Impl->initializeMachineFunction(MF);
+}
+
+std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(StringRef Filename,
+ SMDiagnostic &Error,
+ LLVMContext &Context) {
auto FileOrErr = MemoryBuffer::getFile(Filename);
if (std::error_code EC = FileOrErr.getError()) {
Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
"Could not open input file: " + EC.message());
- return std::unique_ptr<Module>();
+ return nullptr;
}
- return parseMIR(std::move(FileOrErr.get()), Error, Context);
+ return createMIRParser(std::move(FileOrErr.get()), Context);
}
-std::unique_ptr<Module> llvm::parseMIR(std::unique_ptr<MemoryBuffer> Contents,
- SMDiagnostic &Error,
- LLVMContext &Context) {
+std::unique_ptr<MIRParser>
+llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
+ LLVMContext &Context) {
auto Filename = Contents->getBufferIdentifier();
- MIRParserImpl Parser(std::move(Contents), Filename, Context);
- return Parser.parse(Error);
+ return llvm::make_unique<MIRParser>(
+ llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context));
}
OpenPOWER on IntegriCloud