blob: 20d7f815655f77200a7b6eb461e5db2f117a0d70 [file] [log] [blame]
Alex Lorenz2bdb4e12015-05-27 18:02:19 +00001//===- MIRParser.cpp - MIR serialization format parser implementation -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the class that parses the optional LLVM IR and machine
11// functions that are stored in MIR files.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/CodeGen/MIRParser/MIRParser.h"
16#include "llvm/ADT/StringRef.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000017#include "llvm/ADT/StringMap.h"
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000018#include "llvm/ADT/STLExtras.h"
19#include "llvm/AsmParser/Parser.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000020#include "llvm/CodeGen/MachineFunction.h"
Alex Lorenz78d78312015-05-28 22:41:12 +000021#include "llvm/CodeGen/MIRYamlMapping.h"
Alex Lorenz4f093bf2015-06-19 17:43:07 +000022#include "llvm/IR/BasicBlock.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000023#include "llvm/IR/DiagnosticInfo.h"
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000024#include "llvm/IR/Instructions.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000025#include "llvm/IR/LLVMContext.h"
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000026#include "llvm/IR/Module.h"
Alex Lorenz4f093bf2015-06-19 17:43:07 +000027#include "llvm/IR/ValueSymbolTable.h"
Alex Lorenz09b832c2015-05-29 17:05:41 +000028#include "llvm/Support/LineIterator.h"
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000029#include "llvm/Support/SMLoc.h"
30#include "llvm/Support/SourceMgr.h"
31#include "llvm/Support/MemoryBuffer.h"
32#include "llvm/Support/YAMLTraits.h"
33#include <memory>
34
35using namespace llvm;
36
Alex Lorenz735c47e2015-06-15 20:30:22 +000037namespace llvm {
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000038
39/// This class implements the parsing of LLVM IR that's embedded inside a MIR
40/// file.
41class MIRParserImpl {
42 SourceMgr SM;
43 StringRef Filename;
44 LLVMContext &Context;
Alex Lorenz735c47e2015-06-15 20:30:22 +000045 StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000046
47public:
48 MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
49 LLVMContext &Context);
50
Alex Lorenz735c47e2015-06-15 20:30:22 +000051 void reportDiagnostic(const SMDiagnostic &Diag);
52
53 /// Report an error with the given message at unknown location.
54 ///
55 /// Always returns true.
56 bool error(const Twine &Message);
57
Alex Lorenz78d78312015-05-28 22:41:12 +000058 /// Try to parse the optional LLVM module and the machine functions in the MIR
59 /// file.
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000060 ///
Alex Lorenz78d78312015-05-28 22:41:12 +000061 /// Return null if an error occurred.
Alex Lorenz735c47e2015-06-15 20:30:22 +000062 std::unique_ptr<Module> parse();
Alex Lorenz78d78312015-05-28 22:41:12 +000063
64 /// Parse the machine function in the current YAML document.
65 ///
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000066 /// \param NoLLVMIR - set to true when the MIR file doesn't have LLVM IR.
67 /// A dummy IR function is created and inserted into the given module when
68 /// this parameter is true.
69 ///
Alex Lorenz78d78312015-05-28 22:41:12 +000070 /// Return true if an error occurred.
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000071 bool parseMachineFunction(yaml::Input &In, Module &M, bool NoLLVMIR);
Alex Lorenz09b832c2015-05-29 17:05:41 +000072
Alex Lorenz735c47e2015-06-15 20:30:22 +000073 /// Initialize the machine function to the state that's described in the MIR
74 /// file.
75 ///
76 /// Return true if error occurred.
77 bool initializeMachineFunction(MachineFunction &MF);
78
Alex Lorenz4f093bf2015-06-19 17:43:07 +000079 /// Initialize the machine basic block using it's YAML representation.
80 ///
81 /// Return true if an error occurred.
82 bool initializeMachineBasicBlock(MachineBasicBlock &MBB,
83 const yaml::MachineBasicBlock &YamlMBB);
84
Alex Lorenz09b832c2015-05-29 17:05:41 +000085private:
86 /// Return a MIR diagnostic converted from an LLVM assembly diagnostic.
87 SMDiagnostic diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
88 SMRange SourceRange);
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000089
90 /// Create an empty function with the given name.
91 void createDummyFunction(StringRef Name, Module &M);
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000092};
93
Alex Lorenz735c47e2015-06-15 20:30:22 +000094} // end namespace llvm
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000095
96MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
97 StringRef Filename, LLVMContext &Context)
98 : SM(), Filename(Filename), Context(Context) {
99 SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
100}
101
Alex Lorenz735c47e2015-06-15 20:30:22 +0000102bool MIRParserImpl::error(const Twine &Message) {
103 Context.diagnose(DiagnosticInfoMIRParser(
104 DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
105 return true;
Alex Lorenz78d78312015-05-28 22:41:12 +0000106}
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000107
Alex Lorenz735c47e2015-06-15 20:30:22 +0000108void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
109 DiagnosticSeverity Kind;
110 switch (Diag.getKind()) {
111 case SourceMgr::DK_Error:
112 Kind = DS_Error;
113 break;
114 case SourceMgr::DK_Warning:
115 Kind = DS_Warning;
116 break;
117 case SourceMgr::DK_Note:
118 Kind = DS_Note;
119 break;
120 }
121 Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
122}
123
124static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
125 reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
126}
127
128std::unique_ptr<Module> MIRParserImpl::parse() {
Alex Lorenz78d78312015-05-28 22:41:12 +0000129 yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
Alex Lorenz735c47e2015-06-15 20:30:22 +0000130 /*Ctxt=*/nullptr, handleYAMLDiag, this);
Alex Lorenz78d78312015-05-28 22:41:12 +0000131
132 if (!In.setCurrentDocument()) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000133 if (In.error())
Alex Lorenz78d78312015-05-28 22:41:12 +0000134 return nullptr;
135 // Create an empty module when the MIR file is empty.
136 return llvm::make_unique<Module>(Filename, Context);
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000137 }
138
Alex Lorenz78d78312015-05-28 22:41:12 +0000139 std::unique_ptr<Module> M;
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000140 bool NoLLVMIR = false;
Alex Lorenz78d78312015-05-28 22:41:12 +0000141 // Parse the block scalar manually so that we can return unique pointer
142 // without having to go trough YAML traits.
143 if (const auto *BSN =
144 dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000145 SMDiagnostic Error;
Alex Lorenz78d78312015-05-28 22:41:12 +0000146 M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
147 Context);
Alex Lorenz09b832c2015-05-29 17:05:41 +0000148 if (!M) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000149 reportDiagnostic(diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange()));
Alex Lorenz78d78312015-05-28 22:41:12 +0000150 return M;
Alex Lorenz09b832c2015-05-29 17:05:41 +0000151 }
Alex Lorenz78d78312015-05-28 22:41:12 +0000152 In.nextDocument();
153 if (!In.setCurrentDocument())
154 return M;
155 } else {
156 // Create an new, empty module.
157 M = llvm::make_unique<Module>(Filename, Context);
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000158 NoLLVMIR = true;
Alex Lorenz78d78312015-05-28 22:41:12 +0000159 }
160
161 // Parse the machine functions.
162 do {
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000163 if (parseMachineFunction(In, *M, NoLLVMIR))
Alex Lorenz78d78312015-05-28 22:41:12 +0000164 return nullptr;
165 In.nextDocument();
166 } while (In.setCurrentDocument());
167
168 return M;
169}
170
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000171bool MIRParserImpl::parseMachineFunction(yaml::Input &In, Module &M,
172 bool NoLLVMIR) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000173 auto MF = llvm::make_unique<yaml::MachineFunction>();
174 yaml::yamlize(In, *MF, false);
Alex Lorenz78d78312015-05-28 22:41:12 +0000175 if (In.error())
176 return true;
Alex Lorenz735c47e2015-06-15 20:30:22 +0000177 auto FunctionName = MF->Name;
Alex Lorenzfe2aa972015-06-15 22:23:23 +0000178 if (Functions.find(FunctionName) != Functions.end())
179 return error(Twine("redefinition of machine function '") + FunctionName +
180 "'");
Alex Lorenz735c47e2015-06-15 20:30:22 +0000181 Functions.insert(std::make_pair(FunctionName, std::move(MF)));
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000182 if (NoLLVMIR)
183 createDummyFunction(FunctionName, M);
Alex Lorenz5ef16b82015-06-16 17:06:29 +0000184 else if (!M.getFunction(FunctionName))
185 return error(Twine("function '") + FunctionName +
186 "' isn't defined in the provided LLVM IR");
Alex Lorenz735c47e2015-06-15 20:30:22 +0000187 return false;
188}
189
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000190void MIRParserImpl::createDummyFunction(StringRef Name, Module &M) {
191 auto &Context = M.getContext();
192 Function *F = cast<Function>(M.getOrInsertFunction(
193 Name, FunctionType::get(Type::getVoidTy(Context), false)));
194 BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
195 new UnreachableInst(Context, BB);
196}
197
Alex Lorenz735c47e2015-06-15 20:30:22 +0000198bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
199 auto It = Functions.find(MF.getName());
200 if (It == Functions.end())
201 return error(Twine("no machine function information for function '") +
202 MF.getName() + "' in the MIR file");
203 // TODO: Recreate the machine function.
Alex Lorenz5b5f9752015-06-16 00:10:47 +0000204 const yaml::MachineFunction &YamlMF = *It->getValue();
205 if (YamlMF.Alignment)
206 MF.setAlignment(YamlMF.Alignment);
207 MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
208 MF.setHasInlineAsm(YamlMF.HasInlineAsm);
Alex Lorenz4f093bf2015-06-19 17:43:07 +0000209 const auto &F = *MF.getFunction();
210 for (const auto &YamlMBB : YamlMF.BasicBlocks) {
211 const BasicBlock *BB = nullptr;
212 if (!YamlMBB.Name.empty()) {
213 BB = dyn_cast_or_null<BasicBlock>(
214 F.getValueSymbolTable().lookup(YamlMBB.Name));
215 // TODO: Report an error if a basic block isn't found.
216 }
217 auto *MBB = MF.CreateMachineBasicBlock(BB);
218 MF.insert(MF.end(), MBB);
219 if (initializeMachineBasicBlock(*MBB, YamlMBB))
220 return true;
221 }
222 return false;
223}
224
225bool MIRParserImpl::initializeMachineBasicBlock(
226 MachineBasicBlock &MBB, const yaml::MachineBasicBlock &YamlMBB) {
227 MBB.setAlignment(YamlMBB.Alignment);
228 if (YamlMBB.AddressTaken)
229 MBB.setHasAddressTaken();
230 MBB.setIsLandingPad(YamlMBB.IsLandingPad);
Alex Lorenz78d78312015-05-28 22:41:12 +0000231 return false;
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000232}
233
Alex Lorenz09b832c2015-05-29 17:05:41 +0000234SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
235 SMRange SourceRange) {
236 assert(SourceRange.isValid());
237
238 // Translate the location of the error from the location in the llvm IR string
239 // to the corresponding location in the MIR file.
240 auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start);
241 unsigned Line = LineAndColumn.first + Error.getLineNo() - 1;
242 unsigned Column = Error.getColumnNo();
243 StringRef LineStr = Error.getLineContents();
244 SMLoc Loc = Error.getLoc();
245
246 // Get the full line and adjust the column number by taking the indentation of
247 // LLVM IR into account.
248 for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E;
249 L != E; ++L) {
250 if (L.line_number() == Line) {
251 LineStr = *L;
252 Loc = SMLoc::getFromPointer(LineStr.data());
253 auto Indent = LineStr.find(Error.getLineContents());
254 if (Indent != StringRef::npos)
255 Column += Indent;
256 break;
257 }
258 }
259
260 return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(),
261 Error.getMessage(), LineStr, Error.getRanges(),
262 Error.getFixIts());
263}
264
Alex Lorenz735c47e2015-06-15 20:30:22 +0000265MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
266 : Impl(std::move(Impl)) {}
267
268MIRParser::~MIRParser() {}
269
270std::unique_ptr<Module> MIRParser::parseLLVMModule() { return Impl->parse(); }
271
272bool MIRParser::initializeMachineFunction(MachineFunction &MF) {
273 return Impl->initializeMachineFunction(MF);
274}
275
276std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(StringRef Filename,
277 SMDiagnostic &Error,
278 LLVMContext &Context) {
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000279 auto FileOrErr = MemoryBuffer::getFile(Filename);
280 if (std::error_code EC = FileOrErr.getError()) {
281 Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
282 "Could not open input file: " + EC.message());
Alex Lorenz735c47e2015-06-15 20:30:22 +0000283 return nullptr;
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000284 }
Alex Lorenz735c47e2015-06-15 20:30:22 +0000285 return createMIRParser(std::move(FileOrErr.get()), Context);
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000286}
287
Alex Lorenz735c47e2015-06-15 20:30:22 +0000288std::unique_ptr<MIRParser>
289llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
290 LLVMContext &Context) {
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000291 auto Filename = Contents->getBufferIdentifier();
Alex Lorenz735c47e2015-06-15 20:30:22 +0000292 return llvm::make_unique<MIRParser>(
293 llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context));
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000294}