blob: 57ecacf7dce16c2d0b1be3356205d03a22e3644c [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"
Alex Lorenz8e0a1b42015-06-22 17:02:30 +000016#include "MIParser.h"
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000017#include "llvm/ADT/StringRef.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000018#include "llvm/ADT/StringMap.h"
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000019#include "llvm/ADT/STLExtras.h"
20#include "llvm/AsmParser/Parser.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000021#include "llvm/CodeGen/MachineFunction.h"
Alex Lorenz78d78312015-05-28 22:41:12 +000022#include "llvm/CodeGen/MIRYamlMapping.h"
Alex Lorenz4f093bf2015-06-19 17:43:07 +000023#include "llvm/IR/BasicBlock.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000024#include "llvm/IR/DiagnosticInfo.h"
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000025#include "llvm/IR/Instructions.h"
Alex Lorenz735c47e2015-06-15 20:30:22 +000026#include "llvm/IR/LLVMContext.h"
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000027#include "llvm/IR/Module.h"
Alex Lorenz4f093bf2015-06-19 17:43:07 +000028#include "llvm/IR/ValueSymbolTable.h"
Alex Lorenz09b832c2015-05-29 17:05:41 +000029#include "llvm/Support/LineIterator.h"
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000030#include "llvm/Support/SMLoc.h"
31#include "llvm/Support/SourceMgr.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/YAMLTraits.h"
34#include <memory>
35
36using namespace llvm;
37
Alex Lorenz735c47e2015-06-15 20:30:22 +000038namespace llvm {
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000039
40/// This class implements the parsing of LLVM IR that's embedded inside a MIR
41/// file.
42class MIRParserImpl {
43 SourceMgr SM;
44 StringRef Filename;
45 LLVMContext &Context;
Alex Lorenz735c47e2015-06-15 20:30:22 +000046 StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000047
48public:
49 MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
50 LLVMContext &Context);
51
Alex Lorenz735c47e2015-06-15 20:30:22 +000052 void reportDiagnostic(const SMDiagnostic &Diag);
53
54 /// Report an error with the given message at unknown location.
55 ///
56 /// Always returns true.
57 bool error(const Twine &Message);
58
Alex Lorenz78d78312015-05-28 22:41:12 +000059 /// Try to parse the optional LLVM module and the machine functions in the MIR
60 /// file.
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000061 ///
Alex Lorenz78d78312015-05-28 22:41:12 +000062 /// Return null if an error occurred.
Alex Lorenz735c47e2015-06-15 20:30:22 +000063 std::unique_ptr<Module> parse();
Alex Lorenz78d78312015-05-28 22:41:12 +000064
65 /// Parse the machine function in the current YAML document.
66 ///
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000067 /// \param NoLLVMIR - set to true when the MIR file doesn't have LLVM IR.
68 /// A dummy IR function is created and inserted into the given module when
69 /// this parameter is true.
70 ///
Alex Lorenz78d78312015-05-28 22:41:12 +000071 /// Return true if an error occurred.
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000072 bool parseMachineFunction(yaml::Input &In, Module &M, bool NoLLVMIR);
Alex Lorenz09b832c2015-05-29 17:05:41 +000073
Alex Lorenz735c47e2015-06-15 20:30:22 +000074 /// Initialize the machine function to the state that's described in the MIR
75 /// file.
76 ///
77 /// Return true if error occurred.
78 bool initializeMachineFunction(MachineFunction &MF);
79
Alex Lorenz4f093bf2015-06-19 17:43:07 +000080 /// Initialize the machine basic block using it's YAML representation.
81 ///
82 /// Return true if an error occurred.
Alex Lorenz8e0a1b42015-06-22 17:02:30 +000083 bool initializeMachineBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB,
Alex Lorenz4f093bf2015-06-19 17:43:07 +000084 const yaml::MachineBasicBlock &YamlMBB);
85
Alex Lorenz09b832c2015-05-29 17:05:41 +000086private:
Alex Lorenz51af1602015-06-23 22:39:23 +000087 /// Return a MIR diagnostic converted from an MI string diagnostic.
88 SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
89 SMRange SourceRange);
90
Alex Lorenz09b832c2015-05-29 17:05:41 +000091 /// Return a MIR diagnostic converted from an LLVM assembly diagnostic.
92 SMDiagnostic diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
93 SMRange SourceRange);
Alex Lorenz8e7a58d72015-06-15 23:07:38 +000094
95 /// Create an empty function with the given name.
96 void createDummyFunction(StringRef Name, Module &M);
Alex Lorenz2bdb4e12015-05-27 18:02:19 +000097};
98
Alex Lorenz735c47e2015-06-15 20:30:22 +000099} // end namespace llvm
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000100
101MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
102 StringRef Filename, LLVMContext &Context)
103 : SM(), Filename(Filename), Context(Context) {
104 SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
105}
106
Alex Lorenz735c47e2015-06-15 20:30:22 +0000107bool MIRParserImpl::error(const Twine &Message) {
108 Context.diagnose(DiagnosticInfoMIRParser(
109 DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
110 return true;
Alex Lorenz78d78312015-05-28 22:41:12 +0000111}
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000112
Alex Lorenz735c47e2015-06-15 20:30:22 +0000113void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
114 DiagnosticSeverity Kind;
115 switch (Diag.getKind()) {
116 case SourceMgr::DK_Error:
117 Kind = DS_Error;
118 break;
119 case SourceMgr::DK_Warning:
120 Kind = DS_Warning;
121 break;
122 case SourceMgr::DK_Note:
123 Kind = DS_Note;
124 break;
125 }
126 Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
127}
128
129static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
130 reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
131}
132
133std::unique_ptr<Module> MIRParserImpl::parse() {
Alex Lorenz78d78312015-05-28 22:41:12 +0000134 yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
Alex Lorenz735c47e2015-06-15 20:30:22 +0000135 /*Ctxt=*/nullptr, handleYAMLDiag, this);
Alex Lorenz51af1602015-06-23 22:39:23 +0000136 In.setContext(&In);
Alex Lorenz78d78312015-05-28 22:41:12 +0000137
138 if (!In.setCurrentDocument()) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000139 if (In.error())
Alex Lorenz78d78312015-05-28 22:41:12 +0000140 return nullptr;
141 // Create an empty module when the MIR file is empty.
142 return llvm::make_unique<Module>(Filename, Context);
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000143 }
144
Alex Lorenz78d78312015-05-28 22:41:12 +0000145 std::unique_ptr<Module> M;
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000146 bool NoLLVMIR = false;
Alex Lorenz78d78312015-05-28 22:41:12 +0000147 // Parse the block scalar manually so that we can return unique pointer
148 // without having to go trough YAML traits.
149 if (const auto *BSN =
150 dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000151 SMDiagnostic Error;
Alex Lorenz78d78312015-05-28 22:41:12 +0000152 M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
153 Context);
Alex Lorenz09b832c2015-05-29 17:05:41 +0000154 if (!M) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000155 reportDiagnostic(diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange()));
Alex Lorenz78d78312015-05-28 22:41:12 +0000156 return M;
Alex Lorenz09b832c2015-05-29 17:05:41 +0000157 }
Alex Lorenz78d78312015-05-28 22:41:12 +0000158 In.nextDocument();
159 if (!In.setCurrentDocument())
160 return M;
161 } else {
162 // Create an new, empty module.
163 M = llvm::make_unique<Module>(Filename, Context);
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000164 NoLLVMIR = true;
Alex Lorenz78d78312015-05-28 22:41:12 +0000165 }
166
167 // Parse the machine functions.
168 do {
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000169 if (parseMachineFunction(In, *M, NoLLVMIR))
Alex Lorenz78d78312015-05-28 22:41:12 +0000170 return nullptr;
171 In.nextDocument();
172 } while (In.setCurrentDocument());
173
174 return M;
175}
176
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000177bool MIRParserImpl::parseMachineFunction(yaml::Input &In, Module &M,
178 bool NoLLVMIR) {
Alex Lorenz735c47e2015-06-15 20:30:22 +0000179 auto MF = llvm::make_unique<yaml::MachineFunction>();
180 yaml::yamlize(In, *MF, false);
Alex Lorenz78d78312015-05-28 22:41:12 +0000181 if (In.error())
182 return true;
Alex Lorenz735c47e2015-06-15 20:30:22 +0000183 auto FunctionName = MF->Name;
Alex Lorenzfe2aa972015-06-15 22:23:23 +0000184 if (Functions.find(FunctionName) != Functions.end())
185 return error(Twine("redefinition of machine function '") + FunctionName +
186 "'");
Alex Lorenz735c47e2015-06-15 20:30:22 +0000187 Functions.insert(std::make_pair(FunctionName, std::move(MF)));
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000188 if (NoLLVMIR)
189 createDummyFunction(FunctionName, M);
Alex Lorenz5ef16b82015-06-16 17:06:29 +0000190 else if (!M.getFunction(FunctionName))
191 return error(Twine("function '") + FunctionName +
192 "' isn't defined in the provided LLVM IR");
Alex Lorenz735c47e2015-06-15 20:30:22 +0000193 return false;
194}
195
Alex Lorenz8e7a58d72015-06-15 23:07:38 +0000196void MIRParserImpl::createDummyFunction(StringRef Name, Module &M) {
197 auto &Context = M.getContext();
198 Function *F = cast<Function>(M.getOrInsertFunction(
199 Name, FunctionType::get(Type::getVoidTy(Context), false)));
200 BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
201 new UnreachableInst(Context, BB);
202}
203
Alex Lorenz735c47e2015-06-15 20:30:22 +0000204bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
205 auto It = Functions.find(MF.getName());
206 if (It == Functions.end())
207 return error(Twine("no machine function information for function '") +
208 MF.getName() + "' in the MIR file");
209 // TODO: Recreate the machine function.
Alex Lorenz5b5f9752015-06-16 00:10:47 +0000210 const yaml::MachineFunction &YamlMF = *It->getValue();
211 if (YamlMF.Alignment)
212 MF.setAlignment(YamlMF.Alignment);
213 MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
214 MF.setHasInlineAsm(YamlMF.HasInlineAsm);
Alex Lorenz4f093bf2015-06-19 17:43:07 +0000215 const auto &F = *MF.getFunction();
216 for (const auto &YamlMBB : YamlMF.BasicBlocks) {
217 const BasicBlock *BB = nullptr;
218 if (!YamlMBB.Name.empty()) {
219 BB = dyn_cast_or_null<BasicBlock>(
220 F.getValueSymbolTable().lookup(YamlMBB.Name));
Alex Lorenz00302df2015-06-19 20:12:03 +0000221 if (!BB)
222 return error(Twine("basic block '") + YamlMBB.Name +
223 "' is not defined in the function '" + MF.getName() + "'");
Alex Lorenz4f093bf2015-06-19 17:43:07 +0000224 }
225 auto *MBB = MF.CreateMachineBasicBlock(BB);
226 MF.insert(MF.end(), MBB);
Alex Lorenz8e0a1b42015-06-22 17:02:30 +0000227 if (initializeMachineBasicBlock(MF, *MBB, YamlMBB))
Alex Lorenz4f093bf2015-06-19 17:43:07 +0000228 return true;
229 }
230 return false;
231}
232
233bool MIRParserImpl::initializeMachineBasicBlock(
Alex Lorenz8e0a1b42015-06-22 17:02:30 +0000234 MachineFunction &MF, MachineBasicBlock &MBB,
235 const yaml::MachineBasicBlock &YamlMBB) {
Alex Lorenz4f093bf2015-06-19 17:43:07 +0000236 MBB.setAlignment(YamlMBB.Alignment);
237 if (YamlMBB.AddressTaken)
238 MBB.setHasAddressTaken();
239 MBB.setIsLandingPad(YamlMBB.IsLandingPad);
Alex Lorenz8e0a1b42015-06-22 17:02:30 +0000240 // Parse the instructions.
241 for (const auto &MISource : YamlMBB.Instructions) {
242 SMDiagnostic Error;
Alex Lorenz51af1602015-06-23 22:39:23 +0000243 if (auto *MI = parseMachineInstr(SM, MF, MISource.Value, Error)) {
Alex Lorenz8e0a1b42015-06-22 17:02:30 +0000244 MBB.insert(MBB.end(), MI);
245 continue;
246 }
Alex Lorenz51af1602015-06-23 22:39:23 +0000247 reportDiagnostic(diagFromMIStringDiag(Error, MISource.SourceRange));
Alex Lorenz8e0a1b42015-06-22 17:02:30 +0000248 return true;
249 }
Alex Lorenz78d78312015-05-28 22:41:12 +0000250 return false;
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000251}
252
Alex Lorenz51af1602015-06-23 22:39:23 +0000253SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
254 SMRange SourceRange) {
255 assert(SourceRange.isValid() && "Invalid source range");
256 SMLoc Loc = SourceRange.Start;
257 bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() &&
258 *Loc.getPointer() == '\'';
259 // Translate the location of the error from the location in the MI string to
260 // the corresponding location in the MIR file.
261 Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() +
262 (HasQuote ? 1 : 0));
263
264 // TODO: Translate any source ranges as well.
265 return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), None,
266 Error.getFixIts());
267}
268
Alex Lorenz09b832c2015-05-29 17:05:41 +0000269SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
270 SMRange SourceRange) {
271 assert(SourceRange.isValid());
272
273 // Translate the location of the error from the location in the llvm IR string
274 // to the corresponding location in the MIR file.
275 auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start);
276 unsigned Line = LineAndColumn.first + Error.getLineNo() - 1;
277 unsigned Column = Error.getColumnNo();
278 StringRef LineStr = Error.getLineContents();
279 SMLoc Loc = Error.getLoc();
280
281 // Get the full line and adjust the column number by taking the indentation of
282 // LLVM IR into account.
283 for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E;
284 L != E; ++L) {
285 if (L.line_number() == Line) {
286 LineStr = *L;
287 Loc = SMLoc::getFromPointer(LineStr.data());
288 auto Indent = LineStr.find(Error.getLineContents());
289 if (Indent != StringRef::npos)
290 Column += Indent;
291 break;
292 }
293 }
294
295 return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(),
296 Error.getMessage(), LineStr, Error.getRanges(),
297 Error.getFixIts());
298}
299
Alex Lorenz735c47e2015-06-15 20:30:22 +0000300MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
301 : Impl(std::move(Impl)) {}
302
303MIRParser::~MIRParser() {}
304
305std::unique_ptr<Module> MIRParser::parseLLVMModule() { return Impl->parse(); }
306
307bool MIRParser::initializeMachineFunction(MachineFunction &MF) {
308 return Impl->initializeMachineFunction(MF);
309}
310
311std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(StringRef Filename,
312 SMDiagnostic &Error,
313 LLVMContext &Context) {
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000314 auto FileOrErr = MemoryBuffer::getFile(Filename);
315 if (std::error_code EC = FileOrErr.getError()) {
316 Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
317 "Could not open input file: " + EC.message());
Alex Lorenz735c47e2015-06-15 20:30:22 +0000318 return nullptr;
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000319 }
Alex Lorenz735c47e2015-06-15 20:30:22 +0000320 return createMIRParser(std::move(FileOrErr.get()), Context);
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000321}
322
Alex Lorenz735c47e2015-06-15 20:30:22 +0000323std::unique_ptr<MIRParser>
324llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
325 LLVMContext &Context) {
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000326 auto Filename = Contents->getBufferIdentifier();
Alex Lorenz735c47e2015-06-15 20:30:22 +0000327 return llvm::make_unique<MIRParser>(
328 llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context));
Alex Lorenz2bdb4e12015-05-27 18:02:19 +0000329}