1 //===- 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 "MIParser.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/AsmParser/Parser.h"
22 #include "llvm/AsmParser/SlotMapping.h"
23 #include "llvm/CodeGen/MachineConstantPool.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineFrameInfo.h"
26 #include "llvm/CodeGen/MachineModuleInfo.h"
27 #include "llvm/CodeGen/MachineRegisterInfo.h"
28 #include "llvm/CodeGen/MIRYamlMapping.h"
29 #include "llvm/IR/BasicBlock.h"
30 #include "llvm/IR/DiagnosticInfo.h"
31 #include "llvm/IR/Instructions.h"
32 #include "llvm/IR/LLVMContext.h"
33 #include "llvm/IR/Module.h"
34 #include "llvm/IR/ValueSymbolTable.h"
35 #include "llvm/Support/LineIterator.h"
36 #include "llvm/Support/SMLoc.h"
37 #include "llvm/Support/SourceMgr.h"
38 #include "llvm/Support/MemoryBuffer.h"
39 #include "llvm/Support/YAMLTraits.h"
40 #include <memory>
41
42 using namespace llvm;
43
44 namespace llvm {
45
46 /// This class implements the parsing of LLVM IR that's embedded inside a MIR
47 /// file.
48 class MIRParserImpl {
49 SourceMgr SM;
50 StringRef Filename;
51 LLVMContext &Context;
52 StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
53 SlotMapping IRSlots;
54 /// Maps from register class names to register classes.
55 StringMap<const TargetRegisterClass *> Names2RegClasses;
56
57 public:
58 MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
59 LLVMContext &Context);
60
61 void reportDiagnostic(const SMDiagnostic &Diag);
62
63 /// Report an error with the given message at unknown location.
64 ///
65 /// Always returns true.
66 bool error(const Twine &Message);
67
68 /// Report an error with the given message at the given location.
69 ///
70 /// Always returns true.
71 bool error(SMLoc Loc, const Twine &Message);
72
73 /// Report a given error with the location translated from the location in an
74 /// embedded string literal to a location in the MIR file.
75 ///
76 /// Always returns true.
77 bool error(const SMDiagnostic &Error, SMRange SourceRange);
78
79 /// Try to parse the optional LLVM module and the machine functions in the MIR
80 /// file.
81 ///
82 /// Return null if an error occurred.
83 std::unique_ptr<Module> parse();
84
85 /// Parse the machine function in the current YAML document.
86 ///
87 /// \param NoLLVMIR - set to true when the MIR file doesn't have LLVM IR.
88 /// A dummy IR function is created and inserted into the given module when
89 /// this parameter is true.
90 ///
91 /// Return true if an error occurred.
92 bool parseMachineFunction(yaml::Input &In, Module &M, bool NoLLVMIR);
93
94 /// Initialize the machine function to the state that's described in the MIR
95 /// file.
96 ///
97 /// Return true if error occurred.
98 bool initializeMachineFunction(MachineFunction &MF);
99
100 bool initializeRegisterInfo(MachineFunction &MF,
101 const yaml::MachineFunction &YamlMF,
102 PerFunctionMIParsingState &PFS);
103
104 void inferRegisterInfo(MachineFunction &MF,
105 const yaml::MachineFunction &YamlMF);
106
107 bool initializeFrameInfo(MachineFunction &MF,
108 const yaml::MachineFunction &YamlMF,
109 PerFunctionMIParsingState &PFS);
110
111 bool parseCalleeSavedRegister(MachineFunction &MF,
112 PerFunctionMIParsingState &PFS,
113 std::vector<CalleeSavedInfo> &CSIInfo,
114 const yaml::StringValue &RegisterSource,
115 int FrameIdx);
116
117 bool parseStackObjectsDebugInfo(MachineFunction &MF,
118 PerFunctionMIParsingState &PFS,
119 const yaml::MachineStackObject &Object,
120 int FrameIdx);
121
122 bool initializeConstantPool(MachineConstantPool &ConstantPool,
123 const yaml::MachineFunction &YamlMF,
124 const MachineFunction &MF,
125 DenseMap<unsigned, unsigned> &ConstantPoolSlots);
126
127 bool initializeJumpTableInfo(MachineFunction &MF,
128 const yaml::MachineJumpTable &YamlJTI,
129 PerFunctionMIParsingState &PFS);
130
131 private:
132 bool parseMDNode(MDNode *&Node, const yaml::StringValue &Source,
133 MachineFunction &MF, const PerFunctionMIParsingState &PFS);
134
135 bool parseMBBReference(MachineBasicBlock *&MBB,
136 const yaml::StringValue &Source, MachineFunction &MF,
137 const PerFunctionMIParsingState &PFS);
138
139 /// Return a MIR diagnostic converted from an MI string diagnostic.
140 SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
141 SMRange SourceRange);
142
143 /// Return a MIR diagnostic converted from a diagnostic located in a YAML
144 /// block scalar string.
145 SMDiagnostic diagFromBlockStringDiag(const SMDiagnostic &Error,
146 SMRange SourceRange);
147
148 /// Create an empty function with the given name.
149 void createDummyFunction(StringRef Name, Module &M);
150
151 void initNames2RegClasses(const MachineFunction &MF);
152
153 /// Check if the given identifier is a name of a register class.
154 ///
155 /// Return null if the name isn't a register class.
156 const TargetRegisterClass *getRegClass(const MachineFunction &MF,
157 StringRef Name);
158 };
159
160 } // end namespace llvm
161
MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,StringRef Filename,LLVMContext & Context)162 MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
163 StringRef Filename, LLVMContext &Context)
164 : SM(), Filename(Filename), Context(Context) {
165 SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
166 }
167
error(const Twine & Message)168 bool MIRParserImpl::error(const Twine &Message) {
169 Context.diagnose(DiagnosticInfoMIRParser(
170 DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
171 return true;
172 }
173
error(SMLoc Loc,const Twine & Message)174 bool MIRParserImpl::error(SMLoc Loc, const Twine &Message) {
175 Context.diagnose(DiagnosticInfoMIRParser(
176 DS_Error, SM.GetMessage(Loc, SourceMgr::DK_Error, Message)));
177 return true;
178 }
179
error(const SMDiagnostic & Error,SMRange SourceRange)180 bool MIRParserImpl::error(const SMDiagnostic &Error, SMRange SourceRange) {
181 assert(Error.getKind() == SourceMgr::DK_Error && "Expected an error");
182 reportDiagnostic(diagFromMIStringDiag(Error, SourceRange));
183 return true;
184 }
185
reportDiagnostic(const SMDiagnostic & Diag)186 void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
187 DiagnosticSeverity Kind;
188 switch (Diag.getKind()) {
189 case SourceMgr::DK_Error:
190 Kind = DS_Error;
191 break;
192 case SourceMgr::DK_Warning:
193 Kind = DS_Warning;
194 break;
195 case SourceMgr::DK_Note:
196 Kind = DS_Note;
197 break;
198 }
199 Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
200 }
201
handleYAMLDiag(const SMDiagnostic & Diag,void * Context)202 static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
203 reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
204 }
205
parse()206 std::unique_ptr<Module> MIRParserImpl::parse() {
207 yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
208 /*Ctxt=*/nullptr, handleYAMLDiag, this);
209 In.setContext(&In);
210
211 if (!In.setCurrentDocument()) {
212 if (In.error())
213 return nullptr;
214 // Create an empty module when the MIR file is empty.
215 return llvm::make_unique<Module>(Filename, Context);
216 }
217
218 std::unique_ptr<Module> M;
219 bool NoLLVMIR = false;
220 // Parse the block scalar manually so that we can return unique pointer
221 // without having to go trough YAML traits.
222 if (const auto *BSN =
223 dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
224 SMDiagnostic Error;
225 M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
226 Context, &IRSlots);
227 if (!M) {
228 reportDiagnostic(diagFromBlockStringDiag(Error, BSN->getSourceRange()));
229 return M;
230 }
231 In.nextDocument();
232 if (!In.setCurrentDocument())
233 return M;
234 } else {
235 // Create an new, empty module.
236 M = llvm::make_unique<Module>(Filename, Context);
237 NoLLVMIR = true;
238 }
239
240 // Parse the machine functions.
241 do {
242 if (parseMachineFunction(In, *M, NoLLVMIR))
243 return nullptr;
244 In.nextDocument();
245 } while (In.setCurrentDocument());
246
247 return M;
248 }
249
parseMachineFunction(yaml::Input & In,Module & M,bool NoLLVMIR)250 bool MIRParserImpl::parseMachineFunction(yaml::Input &In, Module &M,
251 bool NoLLVMIR) {
252 auto MF = llvm::make_unique<yaml::MachineFunction>();
253 yaml::yamlize(In, *MF, false);
254 if (In.error())
255 return true;
256 auto FunctionName = MF->Name;
257 if (Functions.find(FunctionName) != Functions.end())
258 return error(Twine("redefinition of machine function '") + FunctionName +
259 "'");
260 Functions.insert(std::make_pair(FunctionName, std::move(MF)));
261 if (NoLLVMIR)
262 createDummyFunction(FunctionName, M);
263 else if (!M.getFunction(FunctionName))
264 return error(Twine("function '") + FunctionName +
265 "' isn't defined in the provided LLVM IR");
266 return false;
267 }
268
createDummyFunction(StringRef Name,Module & M)269 void MIRParserImpl::createDummyFunction(StringRef Name, Module &M) {
270 auto &Context = M.getContext();
271 Function *F = cast<Function>(M.getOrInsertFunction(
272 Name, FunctionType::get(Type::getVoidTy(Context), false)));
273 BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
274 new UnreachableInst(Context, BB);
275 }
276
initializeMachineFunction(MachineFunction & MF)277 bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
278 auto It = Functions.find(MF.getName());
279 if (It == Functions.end())
280 return error(Twine("no machine function information for function '") +
281 MF.getName() + "' in the MIR file");
282 // TODO: Recreate the machine function.
283 const yaml::MachineFunction &YamlMF = *It->getValue();
284 if (YamlMF.Alignment)
285 MF.setAlignment(YamlMF.Alignment);
286 MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
287 MF.setHasInlineAsm(YamlMF.HasInlineAsm);
288 PerFunctionMIParsingState PFS;
289 if (initializeRegisterInfo(MF, YamlMF, PFS))
290 return true;
291 if (!YamlMF.Constants.empty()) {
292 auto *ConstantPool = MF.getConstantPool();
293 assert(ConstantPool && "Constant pool must be created");
294 if (initializeConstantPool(*ConstantPool, YamlMF, MF,
295 PFS.ConstantPoolSlots))
296 return true;
297 }
298
299 SMDiagnostic Error;
300 if (parseMachineBasicBlockDefinitions(MF, YamlMF.Body.Value.Value, PFS,
301 IRSlots, Error)) {
302 reportDiagnostic(
303 diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
304 return true;
305 }
306
307 if (MF.empty())
308 return error(Twine("machine function '") + Twine(MF.getName()) +
309 "' requires at least one machine basic block in its body");
310 // Initialize the frame information after creating all the MBBs so that the
311 // MBB references in the frame information can be resolved.
312 if (initializeFrameInfo(MF, YamlMF, PFS))
313 return true;
314 // Initialize the jump table after creating all the MBBs so that the MBB
315 // references can be resolved.
316 if (!YamlMF.JumpTableInfo.Entries.empty() &&
317 initializeJumpTableInfo(MF, YamlMF.JumpTableInfo, PFS))
318 return true;
319 // Parse the machine instructions after creating all of the MBBs so that the
320 // parser can resolve the MBB references.
321 if (parseMachineInstructions(MF, YamlMF.Body.Value.Value, PFS, IRSlots,
322 Error)) {
323 reportDiagnostic(
324 diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
325 return true;
326 }
327 inferRegisterInfo(MF, YamlMF);
328 // FIXME: This is a temporary workaround until the reserved registers can be
329 // serialized.
330 MF.getRegInfo().freezeReservedRegs(MF);
331 MF.verify();
332 return false;
333 }
334
initializeRegisterInfo(MachineFunction & MF,const yaml::MachineFunction & YamlMF,PerFunctionMIParsingState & PFS)335 bool MIRParserImpl::initializeRegisterInfo(MachineFunction &MF,
336 const yaml::MachineFunction &YamlMF,
337 PerFunctionMIParsingState &PFS) {
338 MachineRegisterInfo &RegInfo = MF.getRegInfo();
339 assert(RegInfo.isSSA());
340 if (!YamlMF.IsSSA)
341 RegInfo.leaveSSA();
342 assert(RegInfo.tracksLiveness());
343 if (!YamlMF.TracksRegLiveness)
344 RegInfo.invalidateLiveness();
345 RegInfo.enableSubRegLiveness(YamlMF.TracksSubRegLiveness);
346
347 SMDiagnostic Error;
348 // Parse the virtual register information.
349 for (const auto &VReg : YamlMF.VirtualRegisters) {
350 const auto *RC = getRegClass(MF, VReg.Class.Value);
351 if (!RC)
352 return error(VReg.Class.SourceRange.Start,
353 Twine("use of undefined register class '") +
354 VReg.Class.Value + "'");
355 unsigned Reg = RegInfo.createVirtualRegister(RC);
356 if (!PFS.VirtualRegisterSlots.insert(std::make_pair(VReg.ID.Value, Reg))
357 .second)
358 return error(VReg.ID.SourceRange.Start,
359 Twine("redefinition of virtual register '%") +
360 Twine(VReg.ID.Value) + "'");
361 if (!VReg.PreferredRegister.Value.empty()) {
362 unsigned PreferredReg = 0;
363 if (parseNamedRegisterReference(PreferredReg, SM, MF,
364 VReg.PreferredRegister.Value, PFS,
365 IRSlots, Error))
366 return error(Error, VReg.PreferredRegister.SourceRange);
367 RegInfo.setSimpleHint(Reg, PreferredReg);
368 }
369 }
370
371 // Parse the liveins.
372 for (const auto &LiveIn : YamlMF.LiveIns) {
373 unsigned Reg = 0;
374 if (parseNamedRegisterReference(Reg, SM, MF, LiveIn.Register.Value, PFS,
375 IRSlots, Error))
376 return error(Error, LiveIn.Register.SourceRange);
377 unsigned VReg = 0;
378 if (!LiveIn.VirtualRegister.Value.empty()) {
379 if (parseVirtualRegisterReference(
380 VReg, SM, MF, LiveIn.VirtualRegister.Value, PFS, IRSlots, Error))
381 return error(Error, LiveIn.VirtualRegister.SourceRange);
382 }
383 RegInfo.addLiveIn(Reg, VReg);
384 }
385
386 // Parse the callee saved register mask.
387 BitVector CalleeSavedRegisterMask(RegInfo.getUsedPhysRegsMask().size());
388 if (!YamlMF.CalleeSavedRegisters)
389 return false;
390 for (const auto &RegSource : YamlMF.CalleeSavedRegisters.getValue()) {
391 unsigned Reg = 0;
392 if (parseNamedRegisterReference(Reg, SM, MF, RegSource.Value, PFS, IRSlots,
393 Error))
394 return error(Error, RegSource.SourceRange);
395 CalleeSavedRegisterMask[Reg] = true;
396 }
397 RegInfo.setUsedPhysRegMask(CalleeSavedRegisterMask.flip());
398 return false;
399 }
400
inferRegisterInfo(MachineFunction & MF,const yaml::MachineFunction & YamlMF)401 void MIRParserImpl::inferRegisterInfo(MachineFunction &MF,
402 const yaml::MachineFunction &YamlMF) {
403 if (YamlMF.CalleeSavedRegisters)
404 return;
405 for (const MachineBasicBlock &MBB : MF) {
406 for (const MachineInstr &MI : MBB) {
407 for (const MachineOperand &MO : MI.operands()) {
408 if (!MO.isRegMask())
409 continue;
410 MF.getRegInfo().addPhysRegsUsedFromRegMask(MO.getRegMask());
411 }
412 }
413 }
414 }
415
initializeFrameInfo(MachineFunction & MF,const yaml::MachineFunction & YamlMF,PerFunctionMIParsingState & PFS)416 bool MIRParserImpl::initializeFrameInfo(MachineFunction &MF,
417 const yaml::MachineFunction &YamlMF,
418 PerFunctionMIParsingState &PFS) {
419 MachineFrameInfo &MFI = *MF.getFrameInfo();
420 const Function &F = *MF.getFunction();
421 const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
422 MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
423 MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken);
424 MFI.setHasStackMap(YamlMFI.HasStackMap);
425 MFI.setHasPatchPoint(YamlMFI.HasPatchPoint);
426 MFI.setStackSize(YamlMFI.StackSize);
427 MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment);
428 if (YamlMFI.MaxAlignment)
429 MFI.ensureMaxAlignment(YamlMFI.MaxAlignment);
430 MFI.setAdjustsStack(YamlMFI.AdjustsStack);
431 MFI.setHasCalls(YamlMFI.HasCalls);
432 MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize);
433 MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment);
434 MFI.setHasVAStart(YamlMFI.HasVAStart);
435 MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc);
436 if (!YamlMFI.SavePoint.Value.empty()) {
437 MachineBasicBlock *MBB = nullptr;
438 if (parseMBBReference(MBB, YamlMFI.SavePoint, MF, PFS))
439 return true;
440 MFI.setSavePoint(MBB);
441 }
442 if (!YamlMFI.RestorePoint.Value.empty()) {
443 MachineBasicBlock *MBB = nullptr;
444 if (parseMBBReference(MBB, YamlMFI.RestorePoint, MF, PFS))
445 return true;
446 MFI.setRestorePoint(MBB);
447 }
448
449 std::vector<CalleeSavedInfo> CSIInfo;
450 // Initialize the fixed frame objects.
451 for (const auto &Object : YamlMF.FixedStackObjects) {
452 int ObjectIdx;
453 if (Object.Type != yaml::FixedMachineStackObject::SpillSlot)
454 ObjectIdx = MFI.CreateFixedObject(Object.Size, Object.Offset,
455 Object.IsImmutable, Object.IsAliased);
456 else
457 ObjectIdx = MFI.CreateFixedSpillStackObject(Object.Size, Object.Offset);
458 MFI.setObjectAlignment(ObjectIdx, Object.Alignment);
459 if (!PFS.FixedStackObjectSlots.insert(std::make_pair(Object.ID.Value,
460 ObjectIdx))
461 .second)
462 return error(Object.ID.SourceRange.Start,
463 Twine("redefinition of fixed stack object '%fixed-stack.") +
464 Twine(Object.ID.Value) + "'");
465 if (parseCalleeSavedRegister(MF, PFS, CSIInfo, Object.CalleeSavedRegister,
466 ObjectIdx))
467 return true;
468 }
469
470 // Initialize the ordinary frame objects.
471 for (const auto &Object : YamlMF.StackObjects) {
472 int ObjectIdx;
473 const AllocaInst *Alloca = nullptr;
474 const yaml::StringValue &Name = Object.Name;
475 if (!Name.Value.empty()) {
476 Alloca = dyn_cast_or_null<AllocaInst>(
477 F.getValueSymbolTable().lookup(Name.Value));
478 if (!Alloca)
479 return error(Name.SourceRange.Start,
480 "alloca instruction named '" + Name.Value +
481 "' isn't defined in the function '" + F.getName() +
482 "'");
483 }
484 if (Object.Type == yaml::MachineStackObject::VariableSized)
485 ObjectIdx = MFI.CreateVariableSizedObject(Object.Alignment, Alloca);
486 else
487 ObjectIdx = MFI.CreateStackObject(
488 Object.Size, Object.Alignment,
489 Object.Type == yaml::MachineStackObject::SpillSlot, Alloca);
490 MFI.setObjectOffset(ObjectIdx, Object.Offset);
491 if (!PFS.StackObjectSlots.insert(std::make_pair(Object.ID.Value, ObjectIdx))
492 .second)
493 return error(Object.ID.SourceRange.Start,
494 Twine("redefinition of stack object '%stack.") +
495 Twine(Object.ID.Value) + "'");
496 if (parseCalleeSavedRegister(MF, PFS, CSIInfo, Object.CalleeSavedRegister,
497 ObjectIdx))
498 return true;
499 if (Object.LocalOffset)
500 MFI.mapLocalFrameObject(ObjectIdx, Object.LocalOffset.getValue());
501 if (parseStackObjectsDebugInfo(MF, PFS, Object, ObjectIdx))
502 return true;
503 }
504 MFI.setCalleeSavedInfo(CSIInfo);
505 if (!CSIInfo.empty())
506 MFI.setCalleeSavedInfoValid(true);
507
508 // Initialize the various stack object references after initializing the
509 // stack objects.
510 if (!YamlMFI.StackProtector.Value.empty()) {
511 SMDiagnostic Error;
512 int FI;
513 if (parseStackObjectReference(FI, SM, MF, YamlMFI.StackProtector.Value, PFS,
514 IRSlots, Error))
515 return error(Error, YamlMFI.StackProtector.SourceRange);
516 MFI.setStackProtectorIndex(FI);
517 }
518 return false;
519 }
520
parseCalleeSavedRegister(MachineFunction & MF,PerFunctionMIParsingState & PFS,std::vector<CalleeSavedInfo> & CSIInfo,const yaml::StringValue & RegisterSource,int FrameIdx)521 bool MIRParserImpl::parseCalleeSavedRegister(
522 MachineFunction &MF, PerFunctionMIParsingState &PFS,
523 std::vector<CalleeSavedInfo> &CSIInfo,
524 const yaml::StringValue &RegisterSource, int FrameIdx) {
525 if (RegisterSource.Value.empty())
526 return false;
527 unsigned Reg = 0;
528 SMDiagnostic Error;
529 if (parseNamedRegisterReference(Reg, SM, MF, RegisterSource.Value, PFS,
530 IRSlots, Error))
531 return error(Error, RegisterSource.SourceRange);
532 CSIInfo.push_back(CalleeSavedInfo(Reg, FrameIdx));
533 return false;
534 }
535
536 /// Verify that given node is of a certain type. Return true on error.
537 template <typename T>
typecheckMDNode(T * & Result,MDNode * Node,const yaml::StringValue & Source,StringRef TypeString,MIRParserImpl & Parser)538 static bool typecheckMDNode(T *&Result, MDNode *Node,
539 const yaml::StringValue &Source,
540 StringRef TypeString, MIRParserImpl &Parser) {
541 if (!Node)
542 return false;
543 Result = dyn_cast<T>(Node);
544 if (!Result)
545 return Parser.error(Source.SourceRange.Start,
546 "expected a reference to a '" + TypeString +
547 "' metadata node");
548 return false;
549 }
550
parseStackObjectsDebugInfo(MachineFunction & MF,PerFunctionMIParsingState & PFS,const yaml::MachineStackObject & Object,int FrameIdx)551 bool MIRParserImpl::parseStackObjectsDebugInfo(
552 MachineFunction &MF, PerFunctionMIParsingState &PFS,
553 const yaml::MachineStackObject &Object, int FrameIdx) {
554 // Debug information can only be attached to stack objects; Fixed stack
555 // objects aren't supported.
556 assert(FrameIdx >= 0 && "Expected a stack object frame index");
557 MDNode *Var = nullptr, *Expr = nullptr, *Loc = nullptr;
558 if (parseMDNode(Var, Object.DebugVar, MF, PFS) ||
559 parseMDNode(Expr, Object.DebugExpr, MF, PFS) ||
560 parseMDNode(Loc, Object.DebugLoc, MF, PFS))
561 return true;
562 if (!Var && !Expr && !Loc)
563 return false;
564 DILocalVariable *DIVar = nullptr;
565 DIExpression *DIExpr = nullptr;
566 DILocation *DILoc = nullptr;
567 if (typecheckMDNode(DIVar, Var, Object.DebugVar, "DILocalVariable", *this) ||
568 typecheckMDNode(DIExpr, Expr, Object.DebugExpr, "DIExpression", *this) ||
569 typecheckMDNode(DILoc, Loc, Object.DebugLoc, "DILocation", *this))
570 return true;
571 MF.getMMI().setVariableDbgInfo(DIVar, DIExpr, unsigned(FrameIdx), DILoc);
572 return false;
573 }
574
parseMDNode(MDNode * & Node,const yaml::StringValue & Source,MachineFunction & MF,const PerFunctionMIParsingState & PFS)575 bool MIRParserImpl::parseMDNode(MDNode *&Node, const yaml::StringValue &Source,
576 MachineFunction &MF,
577 const PerFunctionMIParsingState &PFS) {
578 if (Source.Value.empty())
579 return false;
580 SMDiagnostic Error;
581 if (llvm::parseMDNode(Node, SM, MF, Source.Value, PFS, IRSlots, Error))
582 return error(Error, Source.SourceRange);
583 return false;
584 }
585
initializeConstantPool(MachineConstantPool & ConstantPool,const yaml::MachineFunction & YamlMF,const MachineFunction & MF,DenseMap<unsigned,unsigned> & ConstantPoolSlots)586 bool MIRParserImpl::initializeConstantPool(
587 MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF,
588 const MachineFunction &MF,
589 DenseMap<unsigned, unsigned> &ConstantPoolSlots) {
590 const auto &M = *MF.getFunction()->getParent();
591 SMDiagnostic Error;
592 for (const auto &YamlConstant : YamlMF.Constants) {
593 const Constant *Value = dyn_cast_or_null<Constant>(
594 parseConstantValue(YamlConstant.Value.Value, Error, M));
595 if (!Value)
596 return error(Error, YamlConstant.Value.SourceRange);
597 unsigned Alignment =
598 YamlConstant.Alignment
599 ? YamlConstant.Alignment
600 : M.getDataLayout().getPrefTypeAlignment(Value->getType());
601 unsigned Index = ConstantPool.getConstantPoolIndex(Value, Alignment);
602 if (!ConstantPoolSlots.insert(std::make_pair(YamlConstant.ID.Value, Index))
603 .second)
604 return error(YamlConstant.ID.SourceRange.Start,
605 Twine("redefinition of constant pool item '%const.") +
606 Twine(YamlConstant.ID.Value) + "'");
607 }
608 return false;
609 }
610
initializeJumpTableInfo(MachineFunction & MF,const yaml::MachineJumpTable & YamlJTI,PerFunctionMIParsingState & PFS)611 bool MIRParserImpl::initializeJumpTableInfo(
612 MachineFunction &MF, const yaml::MachineJumpTable &YamlJTI,
613 PerFunctionMIParsingState &PFS) {
614 MachineJumpTableInfo *JTI = MF.getOrCreateJumpTableInfo(YamlJTI.Kind);
615 for (const auto &Entry : YamlJTI.Entries) {
616 std::vector<MachineBasicBlock *> Blocks;
617 for (const auto &MBBSource : Entry.Blocks) {
618 MachineBasicBlock *MBB = nullptr;
619 if (parseMBBReference(MBB, MBBSource.Value, MF, PFS))
620 return true;
621 Blocks.push_back(MBB);
622 }
623 unsigned Index = JTI->createJumpTableIndex(Blocks);
624 if (!PFS.JumpTableSlots.insert(std::make_pair(Entry.ID.Value, Index))
625 .second)
626 return error(Entry.ID.SourceRange.Start,
627 Twine("redefinition of jump table entry '%jump-table.") +
628 Twine(Entry.ID.Value) + "'");
629 }
630 return false;
631 }
632
parseMBBReference(MachineBasicBlock * & MBB,const yaml::StringValue & Source,MachineFunction & MF,const PerFunctionMIParsingState & PFS)633 bool MIRParserImpl::parseMBBReference(MachineBasicBlock *&MBB,
634 const yaml::StringValue &Source,
635 MachineFunction &MF,
636 const PerFunctionMIParsingState &PFS) {
637 SMDiagnostic Error;
638 if (llvm::parseMBBReference(MBB, SM, MF, Source.Value, PFS, IRSlots, Error))
639 return error(Error, Source.SourceRange);
640 return false;
641 }
642
diagFromMIStringDiag(const SMDiagnostic & Error,SMRange SourceRange)643 SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
644 SMRange SourceRange) {
645 assert(SourceRange.isValid() && "Invalid source range");
646 SMLoc Loc = SourceRange.Start;
647 bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() &&
648 *Loc.getPointer() == '\'';
649 // Translate the location of the error from the location in the MI string to
650 // the corresponding location in the MIR file.
651 Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() +
652 (HasQuote ? 1 : 0));
653
654 // TODO: Translate any source ranges as well.
655 return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), None,
656 Error.getFixIts());
657 }
658
diagFromBlockStringDiag(const SMDiagnostic & Error,SMRange SourceRange)659 SMDiagnostic MIRParserImpl::diagFromBlockStringDiag(const SMDiagnostic &Error,
660 SMRange SourceRange) {
661 assert(SourceRange.isValid());
662
663 // Translate the location of the error from the location in the llvm IR string
664 // to the corresponding location in the MIR file.
665 auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start);
666 unsigned Line = LineAndColumn.first + Error.getLineNo() - 1;
667 unsigned Column = Error.getColumnNo();
668 StringRef LineStr = Error.getLineContents();
669 SMLoc Loc = Error.getLoc();
670
671 // Get the full line and adjust the column number by taking the indentation of
672 // LLVM IR into account.
673 for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E;
674 L != E; ++L) {
675 if (L.line_number() == Line) {
676 LineStr = *L;
677 Loc = SMLoc::getFromPointer(LineStr.data());
678 auto Indent = LineStr.find(Error.getLineContents());
679 if (Indent != StringRef::npos)
680 Column += Indent;
681 break;
682 }
683 }
684
685 return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(),
686 Error.getMessage(), LineStr, Error.getRanges(),
687 Error.getFixIts());
688 }
689
initNames2RegClasses(const MachineFunction & MF)690 void MIRParserImpl::initNames2RegClasses(const MachineFunction &MF) {
691 if (!Names2RegClasses.empty())
692 return;
693 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
694 for (unsigned I = 0, E = TRI->getNumRegClasses(); I < E; ++I) {
695 const auto *RC = TRI->getRegClass(I);
696 Names2RegClasses.insert(
697 std::make_pair(StringRef(TRI->getRegClassName(RC)).lower(), RC));
698 }
699 }
700
getRegClass(const MachineFunction & MF,StringRef Name)701 const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF,
702 StringRef Name) {
703 initNames2RegClasses(MF);
704 auto RegClassInfo = Names2RegClasses.find(Name);
705 if (RegClassInfo == Names2RegClasses.end())
706 return nullptr;
707 return RegClassInfo->getValue();
708 }
709
MIRParser(std::unique_ptr<MIRParserImpl> Impl)710 MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
711 : Impl(std::move(Impl)) {}
712
~MIRParser()713 MIRParser::~MIRParser() {}
714
parseLLVMModule()715 std::unique_ptr<Module> MIRParser::parseLLVMModule() { return Impl->parse(); }
716
initializeMachineFunction(MachineFunction & MF)717 bool MIRParser::initializeMachineFunction(MachineFunction &MF) {
718 return Impl->initializeMachineFunction(MF);
719 }
720
createMIRParserFromFile(StringRef Filename,SMDiagnostic & Error,LLVMContext & Context)721 std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(StringRef Filename,
722 SMDiagnostic &Error,
723 LLVMContext &Context) {
724 auto FileOrErr = MemoryBuffer::getFile(Filename);
725 if (std::error_code EC = FileOrErr.getError()) {
726 Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
727 "Could not open input file: " + EC.message());
728 return nullptr;
729 }
730 return createMIRParser(std::move(FileOrErr.get()), Context);
731 }
732
733 std::unique_ptr<MIRParser>
createMIRParser(std::unique_ptr<MemoryBuffer> Contents,LLVMContext & Context)734 llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
735 LLVMContext &Context) {
736 auto Filename = Contents->getBufferIdentifier();
737 return llvm::make_unique<MIRParser>(
738 llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context));
739 }
740