1 | //===- MIRParser.cpp - MIR serialization format parser implementation -----===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the class that parses the optional LLVM IR and machine |
10 | // functions that are stored in MIR files. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/CodeGen/MIRParser/MIRParser.h" |
15 | #include "llvm/ADT/DenseMap.h" |
16 | #include "llvm/ADT/StringRef.h" |
17 | #include "llvm/AsmParser/Parser.h" |
18 | #include "llvm/AsmParser/SlotMapping.h" |
19 | #include "llvm/CodeGen/MIRParser/MIParser.h" |
20 | #include "llvm/CodeGen/MIRYamlMapping.h" |
21 | #include "llvm/CodeGen/MachineConstantPool.h" |
22 | #include "llvm/CodeGen/MachineFrameInfo.h" |
23 | #include "llvm/CodeGen/MachineFunction.h" |
24 | #include "llvm/CodeGen/MachineFunctionAnalysis.h" |
25 | #include "llvm/CodeGen/MachineModuleInfo.h" |
26 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
27 | #include "llvm/CodeGen/TargetFrameLowering.h" |
28 | #include "llvm/IR/BasicBlock.h" |
29 | #include "llvm/IR/DebugInfoMetadata.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/MemoryBuffer.h" |
37 | #include "llvm/Support/SMLoc.h" |
38 | #include "llvm/Support/SourceMgr.h" |
39 | #include "llvm/Support/YAMLTraits.h" |
40 | #include "llvm/Target/TargetMachine.h" |
41 | #include <memory> |
42 | |
43 | using namespace llvm; |
44 | |
45 | namespace llvm { |
46 | class MDNode; |
47 | class RegisterBank; |
48 | |
49 | /// This class implements the parsing of LLVM IR that's embedded inside a MIR |
50 | /// file. |
51 | class MIRParserImpl { |
52 | SourceMgr SM; |
53 | LLVMContext &Context; |
54 | yaml::Input In; |
55 | StringRef Filename; |
56 | SlotMapping IRSlots; |
57 | std::unique_ptr<PerTargetMIParsingState> Target; |
58 | |
59 | /// True when the MIR file doesn't have LLVM IR. Dummy IR functions are |
60 | /// created and inserted into the given module when this is true. |
61 | bool NoLLVMIR = false; |
62 | /// True when a well formed MIR file does not contain any MIR/machine function |
63 | /// parts. |
64 | bool NoMIRDocuments = false; |
65 | |
66 | std::function<void(Function &)> ProcessIRFunction; |
67 | |
68 | public: |
69 | MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename, |
70 | LLVMContext &Context, |
71 | std::function<void(Function &)> ProcessIRFunction); |
72 | |
73 | void reportDiagnostic(const SMDiagnostic &Diag); |
74 | |
75 | /// Report an error with the given message at unknown location. |
76 | /// |
77 | /// Always returns true. |
78 | bool error(const Twine &Message); |
79 | |
80 | /// Report an error with the given message at the given location. |
81 | /// |
82 | /// Always returns true. |
83 | bool error(SMLoc Loc, const Twine &Message); |
84 | |
85 | /// Report a given error with the location translated from the location in an |
86 | /// embedded string literal to a location in the MIR file. |
87 | /// |
88 | /// Always returns true. |
89 | bool error(const SMDiagnostic &Error, SMRange SourceRange); |
90 | |
91 | /// Try to parse the optional LLVM module and the machine functions in the MIR |
92 | /// file. |
93 | /// |
94 | /// Return null if an error occurred. |
95 | std::unique_ptr<Module> |
96 | parseIRModule(DataLayoutCallbackTy DataLayoutCallback); |
97 | |
98 | /// Create an empty function with the given name. |
99 | Function *createDummyFunction(StringRef Name, Module &M); |
100 | |
101 | bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI, |
102 | ModuleAnalysisManager *FAM = nullptr); |
103 | |
104 | /// Parse the machine function in the current YAML document. |
105 | /// |
106 | /// |
107 | /// Return true if an error occurred. |
108 | bool parseMachineFunction(Module &M, MachineModuleInfo &MMI, |
109 | ModuleAnalysisManager *FAM); |
110 | |
111 | /// Initialize the machine function to the state that's described in the MIR |
112 | /// file. |
113 | /// |
114 | /// Return true if error occurred. |
115 | bool initializeMachineFunction(const yaml::MachineFunction &YamlMF, |
116 | MachineFunction &MF); |
117 | |
118 | bool parseRegisterInfo(PerFunctionMIParsingState &PFS, |
119 | const yaml::MachineFunction &YamlMF); |
120 | |
121 | bool setupRegisterInfo(const PerFunctionMIParsingState &PFS, |
122 | const yaml::MachineFunction &YamlMF); |
123 | |
124 | bool initializeFrameInfo(PerFunctionMIParsingState &PFS, |
125 | const yaml::MachineFunction &YamlMF); |
126 | |
127 | bool initializeCallSiteInfo(PerFunctionMIParsingState &PFS, |
128 | const yaml::MachineFunction &YamlMF); |
129 | |
130 | bool parseCalleeSavedRegister(PerFunctionMIParsingState &PFS, |
131 | std::vector<CalleeSavedInfo> &CSIInfo, |
132 | const yaml::StringValue &RegisterSource, |
133 | bool IsRestored, int FrameIdx); |
134 | |
135 | struct VarExprLoc { |
136 | DILocalVariable *DIVar = nullptr; |
137 | DIExpression *DIExpr = nullptr; |
138 | DILocation *DILoc = nullptr; |
139 | }; |
140 | |
141 | std::optional<VarExprLoc> parseVarExprLoc(PerFunctionMIParsingState &PFS, |
142 | const yaml::StringValue &VarStr, |
143 | const yaml::StringValue &ExprStr, |
144 | const yaml::StringValue &LocStr); |
145 | template <typename T> |
146 | bool parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS, |
147 | const T &Object, |
148 | int FrameIdx); |
149 | |
150 | bool initializeConstantPool(PerFunctionMIParsingState &PFS, |
151 | MachineConstantPool &ConstantPool, |
152 | const yaml::MachineFunction &YamlMF); |
153 | |
154 | bool initializeJumpTableInfo(PerFunctionMIParsingState &PFS, |
155 | const yaml::MachineJumpTable &YamlJTI); |
156 | |
157 | bool parseMachineMetadataNodes(PerFunctionMIParsingState &PFS, |
158 | MachineFunction &MF, |
159 | const yaml::MachineFunction &YMF); |
160 | |
161 | private: |
162 | bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, |
163 | const yaml::StringValue &Source); |
164 | |
165 | bool parseMBBReference(PerFunctionMIParsingState &PFS, |
166 | MachineBasicBlock *&MBB, |
167 | const yaml::StringValue &Source); |
168 | |
169 | bool parseMachineMetadata(PerFunctionMIParsingState &PFS, |
170 | const yaml::StringValue &Source); |
171 | |
172 | /// Return a MIR diagnostic converted from an MI string diagnostic. |
173 | SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error, |
174 | SMRange SourceRange); |
175 | |
176 | /// Return a MIR diagnostic converted from a diagnostic located in a YAML |
177 | /// block scalar string. |
178 | SMDiagnostic diagFromBlockStringDiag(const SMDiagnostic &Error, |
179 | SMRange SourceRange); |
180 | |
181 | void computeFunctionProperties(MachineFunction &MF); |
182 | |
183 | void setupDebugValueTracking(MachineFunction &MF, |
184 | PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF); |
185 | }; |
186 | |
187 | } // end namespace llvm |
188 | |
189 | static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) { |
190 | reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag); |
191 | } |
192 | |
193 | MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, |
194 | StringRef Filename, LLVMContext &Context, |
195 | std::function<void(Function &)> Callback) |
196 | : Context(Context), |
197 | In(SM.getMemoryBuffer(i: SM.AddNewSourceBuffer(F: std::move(Contents), IncludeLoc: SMLoc())) |
198 | ->getBuffer(), |
199 | nullptr, handleYAMLDiag, this), |
200 | Filename(Filename), ProcessIRFunction(Callback) { |
201 | In.setContext(&In); |
202 | } |
203 | |
204 | bool MIRParserImpl::error(const Twine &Message) { |
205 | Context.diagnose(DI: DiagnosticInfoMIRParser( |
206 | DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str()))); |
207 | return true; |
208 | } |
209 | |
210 | bool MIRParserImpl::error(SMLoc Loc, const Twine &Message) { |
211 | Context.diagnose(DI: DiagnosticInfoMIRParser( |
212 | DS_Error, SM.GetMessage(Loc, Kind: SourceMgr::DK_Error, Msg: Message))); |
213 | return true; |
214 | } |
215 | |
216 | bool MIRParserImpl::error(const SMDiagnostic &Error, SMRange SourceRange) { |
217 | assert(Error.getKind() == SourceMgr::DK_Error && "Expected an error" ); |
218 | reportDiagnostic(Diag: diagFromMIStringDiag(Error, SourceRange)); |
219 | return true; |
220 | } |
221 | |
222 | void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) { |
223 | DiagnosticSeverity Kind; |
224 | switch (Diag.getKind()) { |
225 | case SourceMgr::DK_Error: |
226 | Kind = DS_Error; |
227 | break; |
228 | case SourceMgr::DK_Warning: |
229 | Kind = DS_Warning; |
230 | break; |
231 | case SourceMgr::DK_Note: |
232 | Kind = DS_Note; |
233 | break; |
234 | case SourceMgr::DK_Remark: |
235 | llvm_unreachable("remark unexpected" ); |
236 | break; |
237 | } |
238 | Context.diagnose(DI: DiagnosticInfoMIRParser(Kind, Diag)); |
239 | } |
240 | |
241 | std::unique_ptr<Module> |
242 | MIRParserImpl::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) { |
243 | if (!In.setCurrentDocument()) { |
244 | if (In.error()) |
245 | return nullptr; |
246 | // Create an empty module when the MIR file is empty. |
247 | NoMIRDocuments = true; |
248 | auto M = std::make_unique<Module>(args&: Filename, args&: Context); |
249 | if (auto LayoutOverride = |
250 | DataLayoutCallback(M->getTargetTriple(), M->getDataLayoutStr())) |
251 | M->setDataLayout(*LayoutOverride); |
252 | return M; |
253 | } |
254 | |
255 | std::unique_ptr<Module> M; |
256 | // Parse the block scalar manually so that we can return unique pointer |
257 | // without having to go trough YAML traits. |
258 | if (const auto *BSN = |
259 | dyn_cast_or_null<yaml::BlockScalarNode>(Val: In.getCurrentNode())) { |
260 | SMDiagnostic Error; |
261 | M = parseAssembly(F: MemoryBufferRef(BSN->getValue(), Filename), Err&: Error, |
262 | Context, Slots: &IRSlots, DataLayoutCallback); |
263 | if (!M) { |
264 | reportDiagnostic(Diag: diagFromBlockStringDiag(Error, SourceRange: BSN->getSourceRange())); |
265 | return nullptr; |
266 | } |
267 | In.nextDocument(); |
268 | if (!In.setCurrentDocument()) |
269 | NoMIRDocuments = true; |
270 | } else { |
271 | // Create an new, empty module. |
272 | M = std::make_unique<Module>(args&: Filename, args&: Context); |
273 | if (auto LayoutOverride = |
274 | DataLayoutCallback(M->getTargetTriple(), M->getDataLayoutStr())) |
275 | M->setDataLayout(*LayoutOverride); |
276 | NoLLVMIR = true; |
277 | } |
278 | return M; |
279 | } |
280 | |
281 | bool MIRParserImpl::parseMachineFunctions(Module &M, MachineModuleInfo &MMI, |
282 | ModuleAnalysisManager *MAM) { |
283 | if (NoMIRDocuments) |
284 | return false; |
285 | |
286 | // Parse the machine functions. |
287 | do { |
288 | if (parseMachineFunction(M, MMI, FAM: MAM)) |
289 | return true; |
290 | In.nextDocument(); |
291 | } while (In.setCurrentDocument()); |
292 | |
293 | return false; |
294 | } |
295 | |
296 | Function *MIRParserImpl::createDummyFunction(StringRef Name, Module &M) { |
297 | auto &Context = M.getContext(); |
298 | Function *F = |
299 | Function::Create(Ty: FunctionType::get(Result: Type::getVoidTy(C&: Context), isVarArg: false), |
300 | Linkage: Function::ExternalLinkage, N: Name, M); |
301 | BasicBlock *BB = BasicBlock::Create(Context, Name: "entry" , Parent: F); |
302 | new UnreachableInst(Context, BB); |
303 | |
304 | if (ProcessIRFunction) |
305 | ProcessIRFunction(*F); |
306 | |
307 | return F; |
308 | } |
309 | |
310 | bool MIRParserImpl::parseMachineFunction(Module &M, MachineModuleInfo &MMI, |
311 | ModuleAnalysisManager *MAM) { |
312 | // Parse the yaml. |
313 | yaml::MachineFunction YamlMF; |
314 | yaml::EmptyContext Ctx; |
315 | |
316 | const LLVMTargetMachine &TM = MMI.getTarget(); |
317 | YamlMF.MachineFuncInfo = std::unique_ptr<yaml::MachineFunctionInfo>( |
318 | TM.createDefaultFuncInfoYAML()); |
319 | |
320 | yaml::yamlize(io&: In, Val&: YamlMF, false, Ctx); |
321 | if (In.error()) |
322 | return true; |
323 | |
324 | // Search for the corresponding IR function. |
325 | StringRef FunctionName = YamlMF.Name; |
326 | Function *F = M.getFunction(Name: FunctionName); |
327 | if (!F) { |
328 | if (NoLLVMIR) { |
329 | F = createDummyFunction(Name: FunctionName, M); |
330 | } else { |
331 | return error(Message: Twine("function '" ) + FunctionName + |
332 | "' isn't defined in the provided LLVM IR" ); |
333 | } |
334 | } |
335 | |
336 | if (!MAM) { |
337 | if (MMI.getMachineFunction(F: *F) != nullptr) |
338 | return error(Message: Twine("redefinition of machine function '" ) + FunctionName + |
339 | "'" ); |
340 | |
341 | // Create the MachineFunction. |
342 | MachineFunction &MF = MMI.getOrCreateMachineFunction(F&: *F); |
343 | if (initializeMachineFunction(YamlMF, MF)) |
344 | return true; |
345 | } else { |
346 | auto &FAM = |
347 | MAM->getResult<FunctionAnalysisManagerModuleProxy>(IR&: M).getManager(); |
348 | if (FAM.getCachedResult<MachineFunctionAnalysis>(IR&: *F)) |
349 | return error(Message: Twine("redefinition of machine function '" ) + FunctionName + |
350 | "'" ); |
351 | |
352 | // Create the MachineFunction. |
353 | MachineFunction &MF = FAM.getResult<MachineFunctionAnalysis>(IR&: *F).getMF(); |
354 | if (initializeMachineFunction(YamlMF, MF)) |
355 | return true; |
356 | } |
357 | |
358 | return false; |
359 | } |
360 | |
361 | static bool isSSA(const MachineFunction &MF) { |
362 | const MachineRegisterInfo &MRI = MF.getRegInfo(); |
363 | for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { |
364 | Register Reg = Register::index2VirtReg(Index: I); |
365 | if (!MRI.hasOneDef(RegNo: Reg) && !MRI.def_empty(RegNo: Reg)) |
366 | return false; |
367 | |
368 | // Subregister defs are invalid in SSA. |
369 | const MachineOperand *RegDef = MRI.getOneDef(Reg); |
370 | if (RegDef && RegDef->getSubReg() != 0) |
371 | return false; |
372 | } |
373 | return true; |
374 | } |
375 | |
376 | void MIRParserImpl::computeFunctionProperties(MachineFunction &MF) { |
377 | MachineFunctionProperties &Properties = MF.getProperties(); |
378 | |
379 | bool HasPHI = false; |
380 | bool HasInlineAsm = false; |
381 | bool AllTiedOpsRewritten = true, HasTiedOps = false; |
382 | for (const MachineBasicBlock &MBB : MF) { |
383 | for (const MachineInstr &MI : MBB) { |
384 | if (MI.isPHI()) |
385 | HasPHI = true; |
386 | if (MI.isInlineAsm()) |
387 | HasInlineAsm = true; |
388 | for (unsigned I = 0; I < MI.getNumOperands(); ++I) { |
389 | const MachineOperand &MO = MI.getOperand(i: I); |
390 | if (!MO.isReg() || !MO.getReg()) |
391 | continue; |
392 | unsigned DefIdx; |
393 | if (MO.isUse() && MI.isRegTiedToDefOperand(UseOpIdx: I, DefOpIdx: &DefIdx)) { |
394 | HasTiedOps = true; |
395 | if (MO.getReg() != MI.getOperand(i: DefIdx).getReg()) |
396 | AllTiedOpsRewritten = false; |
397 | } |
398 | } |
399 | } |
400 | } |
401 | if (!HasPHI) |
402 | Properties.set(MachineFunctionProperties::Property::NoPHIs); |
403 | MF.setHasInlineAsm(HasInlineAsm); |
404 | |
405 | if (HasTiedOps && AllTiedOpsRewritten) |
406 | Properties.set(MachineFunctionProperties::Property::TiedOpsRewritten); |
407 | |
408 | if (isSSA(MF)) |
409 | Properties.set(MachineFunctionProperties::Property::IsSSA); |
410 | else |
411 | Properties.reset(P: MachineFunctionProperties::Property::IsSSA); |
412 | |
413 | const MachineRegisterInfo &MRI = MF.getRegInfo(); |
414 | if (MRI.getNumVirtRegs() == 0) |
415 | Properties.set(MachineFunctionProperties::Property::NoVRegs); |
416 | } |
417 | |
418 | bool MIRParserImpl::initializeCallSiteInfo( |
419 | PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF) { |
420 | MachineFunction &MF = PFS.MF; |
421 | SMDiagnostic Error; |
422 | const LLVMTargetMachine &TM = MF.getTarget(); |
423 | for (auto &YamlCSInfo : YamlMF.CallSitesInfo) { |
424 | yaml::CallSiteInfo::MachineInstrLoc MILoc = YamlCSInfo.CallLocation; |
425 | if (MILoc.BlockNum >= MF.size()) |
426 | return error(Message: Twine(MF.getName()) + |
427 | Twine(" call instruction block out of range." ) + |
428 | " Unable to reference bb:" + Twine(MILoc.BlockNum)); |
429 | auto CallB = std::next(x: MF.begin(), n: MILoc.BlockNum); |
430 | if (MILoc.Offset >= CallB->size()) |
431 | return error(Message: Twine(MF.getName()) + |
432 | Twine(" call instruction offset out of range." ) + |
433 | " Unable to reference instruction at bb: " + |
434 | Twine(MILoc.BlockNum) + " at offset:" + Twine(MILoc.Offset)); |
435 | auto CallI = std::next(x: CallB->instr_begin(), n: MILoc.Offset); |
436 | if (!CallI->isCall(Type: MachineInstr::IgnoreBundle)) |
437 | return error(Message: Twine(MF.getName()) + |
438 | Twine(" call site info should reference call " |
439 | "instruction. Instruction at bb:" ) + |
440 | Twine(MILoc.BlockNum) + " at offset:" + Twine(MILoc.Offset) + |
441 | " is not a call instruction" ); |
442 | MachineFunction::CallSiteInfo CSInfo; |
443 | for (auto ArgRegPair : YamlCSInfo.ArgForwardingRegs) { |
444 | Register Reg; |
445 | if (parseNamedRegisterReference(PFS, Reg, Src: ArgRegPair.Reg.Value, Error)) |
446 | return error(Error, SourceRange: ArgRegPair.Reg.SourceRange); |
447 | CSInfo.ArgRegPairs.emplace_back(Args&: Reg, Args&: ArgRegPair.ArgNo); |
448 | } |
449 | |
450 | if (TM.Options.EmitCallSiteInfo) |
451 | MF.addCallSiteInfo(CallI: &*CallI, CallInfo: std::move(CSInfo)); |
452 | } |
453 | |
454 | if (YamlMF.CallSitesInfo.size() && !TM.Options.EmitCallSiteInfo) |
455 | return error(Message: Twine("Call site info provided but not used" )); |
456 | return false; |
457 | } |
458 | |
459 | void MIRParserImpl::setupDebugValueTracking( |
460 | MachineFunction &MF, PerFunctionMIParsingState &PFS, |
461 | const yaml::MachineFunction &YamlMF) { |
462 | // Compute the value of the "next instruction number" field. |
463 | unsigned MaxInstrNum = 0; |
464 | for (auto &MBB : MF) |
465 | for (auto &MI : MBB) |
466 | MaxInstrNum = std::max(a: (unsigned)MI.peekDebugInstrNum(), b: MaxInstrNum); |
467 | MF.setDebugInstrNumberingCount(MaxInstrNum); |
468 | |
469 | // Load any substitutions. |
470 | for (const auto &Sub : YamlMF.DebugValueSubstitutions) { |
471 | MF.makeDebugValueSubstitution({Sub.SrcInst, Sub.SrcOp}, |
472 | {Sub.DstInst, Sub.DstOp}, SubReg: Sub.Subreg); |
473 | } |
474 | |
475 | // Flag for whether we're supposed to be using DBG_INSTR_REF. |
476 | MF.setUseDebugInstrRef(YamlMF.UseDebugInstrRef); |
477 | } |
478 | |
479 | bool |
480 | MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF, |
481 | MachineFunction &MF) { |
482 | // TODO: Recreate the machine function. |
483 | if (Target) { |
484 | // Avoid clearing state if we're using the same subtarget again. |
485 | Target->setTarget(MF.getSubtarget()); |
486 | } else { |
487 | Target.reset(p: new PerTargetMIParsingState(MF.getSubtarget())); |
488 | } |
489 | |
490 | MF.setAlignment(YamlMF.Alignment.valueOrOne()); |
491 | MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); |
492 | MF.setHasWinCFI(YamlMF.HasWinCFI); |
493 | |
494 | MF.setCallsEHReturn(YamlMF.CallsEHReturn); |
495 | MF.setCallsUnwindInit(YamlMF.CallsUnwindInit); |
496 | MF.setHasEHCatchret(YamlMF.HasEHCatchret); |
497 | MF.setHasEHScopes(YamlMF.HasEHScopes); |
498 | MF.setHasEHFunclets(YamlMF.HasEHFunclets); |
499 | MF.setIsOutlined(YamlMF.IsOutlined); |
500 | |
501 | if (YamlMF.Legalized) |
502 | MF.getProperties().set(MachineFunctionProperties::Property::Legalized); |
503 | if (YamlMF.RegBankSelected) |
504 | MF.getProperties().set( |
505 | MachineFunctionProperties::Property::RegBankSelected); |
506 | if (YamlMF.Selected) |
507 | MF.getProperties().set(MachineFunctionProperties::Property::Selected); |
508 | if (YamlMF.FailedISel) |
509 | MF.getProperties().set(MachineFunctionProperties::Property::FailedISel); |
510 | if (YamlMF.FailsVerification) |
511 | MF.getProperties().set( |
512 | MachineFunctionProperties::Property::FailsVerification); |
513 | if (YamlMF.TracksDebugUserValues) |
514 | MF.getProperties().set( |
515 | MachineFunctionProperties::Property::TracksDebugUserValues); |
516 | |
517 | PerFunctionMIParsingState PFS(MF, SM, IRSlots, *Target); |
518 | if (parseRegisterInfo(PFS, YamlMF)) |
519 | return true; |
520 | if (!YamlMF.Constants.empty()) { |
521 | auto *ConstantPool = MF.getConstantPool(); |
522 | assert(ConstantPool && "Constant pool must be created" ); |
523 | if (initializeConstantPool(PFS, ConstantPool&: *ConstantPool, YamlMF)) |
524 | return true; |
525 | } |
526 | if (!YamlMF.MachineMetadataNodes.empty() && |
527 | parseMachineMetadataNodes(PFS, MF, YMF: YamlMF)) |
528 | return true; |
529 | |
530 | StringRef BlockStr = YamlMF.Body.Value.Value; |
531 | SMDiagnostic Error; |
532 | SourceMgr BlockSM; |
533 | BlockSM.AddNewSourceBuffer( |
534 | F: MemoryBuffer::getMemBuffer(InputData: BlockStr, BufferName: "" ,/*RequiresNullTerminator=*/false), |
535 | IncludeLoc: SMLoc()); |
536 | PFS.SM = &BlockSM; |
537 | if (parseMachineBasicBlockDefinitions(PFS, Src: BlockStr, Error)) { |
538 | reportDiagnostic( |
539 | Diag: diagFromBlockStringDiag(Error, SourceRange: YamlMF.Body.Value.SourceRange)); |
540 | return true; |
541 | } |
542 | // Check Basic Block Section Flags. |
543 | if (MF.getTarget().getBBSectionsType() == BasicBlockSection::Labels) { |
544 | MF.setBBSectionsType(BasicBlockSection::Labels); |
545 | } else if (MF.hasBBSections()) { |
546 | MF.assignBeginEndSections(); |
547 | } |
548 | PFS.SM = &SM; |
549 | |
550 | // Initialize the frame information after creating all the MBBs so that the |
551 | // MBB references in the frame information can be resolved. |
552 | if (initializeFrameInfo(PFS, YamlMF)) |
553 | return true; |
554 | // Initialize the jump table after creating all the MBBs so that the MBB |
555 | // references can be resolved. |
556 | if (!YamlMF.JumpTableInfo.Entries.empty() && |
557 | initializeJumpTableInfo(PFS, YamlJTI: YamlMF.JumpTableInfo)) |
558 | return true; |
559 | // Parse the machine instructions after creating all of the MBBs so that the |
560 | // parser can resolve the MBB references. |
561 | StringRef InsnStr = YamlMF.Body.Value.Value; |
562 | SourceMgr InsnSM; |
563 | InsnSM.AddNewSourceBuffer( |
564 | F: MemoryBuffer::getMemBuffer(InputData: InsnStr, BufferName: "" , /*RequiresNullTerminator=*/false), |
565 | IncludeLoc: SMLoc()); |
566 | PFS.SM = &InsnSM; |
567 | if (parseMachineInstructions(PFS, Src: InsnStr, Error)) { |
568 | reportDiagnostic( |
569 | Diag: diagFromBlockStringDiag(Error, SourceRange: YamlMF.Body.Value.SourceRange)); |
570 | return true; |
571 | } |
572 | PFS.SM = &SM; |
573 | |
574 | if (setupRegisterInfo(PFS, YamlMF)) |
575 | return true; |
576 | |
577 | if (YamlMF.MachineFuncInfo) { |
578 | const LLVMTargetMachine &TM = MF.getTarget(); |
579 | // Note this is called after the initial constructor of the |
580 | // MachineFunctionInfo based on the MachineFunction, which may depend on the |
581 | // IR. |
582 | |
583 | SMRange SrcRange; |
584 | if (TM.parseMachineFunctionInfo(*YamlMF.MachineFuncInfo, PFS, Error, |
585 | SourceRange&: SrcRange)) { |
586 | return error(Error, SourceRange: SrcRange); |
587 | } |
588 | } |
589 | |
590 | // Set the reserved registers after parsing MachineFuncInfo. The target may |
591 | // have been recording information used to select the reserved registers |
592 | // there. |
593 | // FIXME: This is a temporary workaround until the reserved registers can be |
594 | // serialized. |
595 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
596 | MRI.freezeReservedRegs(); |
597 | |
598 | computeFunctionProperties(MF); |
599 | |
600 | if (initializeCallSiteInfo(PFS, YamlMF)) |
601 | return false; |
602 | |
603 | setupDebugValueTracking(MF, PFS, YamlMF); |
604 | |
605 | MF.getSubtarget().mirFileLoaded(MF); |
606 | |
607 | MF.verify(); |
608 | return false; |
609 | } |
610 | |
611 | bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS, |
612 | const yaml::MachineFunction &YamlMF) { |
613 | MachineFunction &MF = PFS.MF; |
614 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); |
615 | assert(RegInfo.tracksLiveness()); |
616 | if (!YamlMF.TracksRegLiveness) |
617 | RegInfo.invalidateLiveness(); |
618 | |
619 | SMDiagnostic Error; |
620 | // Parse the virtual register information. |
621 | for (const auto &VReg : YamlMF.VirtualRegisters) { |
622 | VRegInfo &Info = PFS.getVRegInfo(Num: VReg.ID.Value); |
623 | if (Info.Explicit) |
624 | return error(Loc: VReg.ID.SourceRange.Start, |
625 | Message: Twine("redefinition of virtual register '%" ) + |
626 | Twine(VReg.ID.Value) + "'" ); |
627 | Info.Explicit = true; |
628 | |
629 | if (VReg.Class.Value == "_" ) { |
630 | Info.Kind = VRegInfo::GENERIC; |
631 | Info.D.RegBank = nullptr; |
632 | } else { |
633 | const auto *RC = Target->getRegClass(Name: VReg.Class.Value); |
634 | if (RC) { |
635 | Info.Kind = VRegInfo::NORMAL; |
636 | Info.D.RC = RC; |
637 | } else { |
638 | const RegisterBank *RegBank = Target->getRegBank(Name: VReg.Class.Value); |
639 | if (!RegBank) |
640 | return error( |
641 | Loc: VReg.Class.SourceRange.Start, |
642 | Message: Twine("use of undefined register class or register bank '" ) + |
643 | VReg.Class.Value + "'" ); |
644 | Info.Kind = VRegInfo::REGBANK; |
645 | Info.D.RegBank = RegBank; |
646 | } |
647 | } |
648 | |
649 | if (!VReg.PreferredRegister.Value.empty()) { |
650 | if (Info.Kind != VRegInfo::NORMAL) |
651 | return error(Loc: VReg.Class.SourceRange.Start, |
652 | Message: Twine("preferred register can only be set for normal vregs" )); |
653 | |
654 | if (parseRegisterReference(PFS, Reg&: Info.PreferredReg, |
655 | Src: VReg.PreferredRegister.Value, Error)) |
656 | return error(Error, SourceRange: VReg.PreferredRegister.SourceRange); |
657 | } |
658 | } |
659 | |
660 | // Parse the liveins. |
661 | for (const auto &LiveIn : YamlMF.LiveIns) { |
662 | Register Reg; |
663 | if (parseNamedRegisterReference(PFS, Reg, Src: LiveIn.Register.Value, Error)) |
664 | return error(Error, SourceRange: LiveIn.Register.SourceRange); |
665 | Register VReg; |
666 | if (!LiveIn.VirtualRegister.Value.empty()) { |
667 | VRegInfo *Info; |
668 | if (parseVirtualRegisterReference(PFS, Info, Src: LiveIn.VirtualRegister.Value, |
669 | Error)) |
670 | return error(Error, SourceRange: LiveIn.VirtualRegister.SourceRange); |
671 | VReg = Info->VReg; |
672 | } |
673 | RegInfo.addLiveIn(Reg, vreg: VReg); |
674 | } |
675 | |
676 | // Parse the callee saved registers (Registers that will |
677 | // be saved for the caller). |
678 | if (YamlMF.CalleeSavedRegisters) { |
679 | SmallVector<MCPhysReg, 16> CalleeSavedRegisters; |
680 | for (const auto &RegSource : *YamlMF.CalleeSavedRegisters) { |
681 | Register Reg; |
682 | if (parseNamedRegisterReference(PFS, Reg, Src: RegSource.Value, Error)) |
683 | return error(Error, SourceRange: RegSource.SourceRange); |
684 | CalleeSavedRegisters.push_back(Elt: Reg); |
685 | } |
686 | RegInfo.setCalleeSavedRegs(CalleeSavedRegisters); |
687 | } |
688 | |
689 | return false; |
690 | } |
691 | |
692 | bool MIRParserImpl::setupRegisterInfo(const PerFunctionMIParsingState &PFS, |
693 | const yaml::MachineFunction &YamlMF) { |
694 | MachineFunction &MF = PFS.MF; |
695 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
696 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
697 | |
698 | bool Error = false; |
699 | // Create VRegs |
700 | auto populateVRegInfo = [&](const VRegInfo &Info, Twine Name) { |
701 | Register Reg = Info.VReg; |
702 | switch (Info.Kind) { |
703 | case VRegInfo::UNKNOWN: |
704 | error(Message: Twine("Cannot determine class/bank of virtual register " ) + |
705 | Name + " in function '" + MF.getName() + "'" ); |
706 | Error = true; |
707 | break; |
708 | case VRegInfo::NORMAL: |
709 | if (!Info.D.RC->isAllocatable()) { |
710 | error(Message: Twine("Cannot use non-allocatable class '" ) + |
711 | TRI->getRegClassName(Class: Info.D.RC) + "' for virtual register " + |
712 | Name + " in function '" + MF.getName() + "'" ); |
713 | Error = true; |
714 | break; |
715 | } |
716 | |
717 | MRI.setRegClass(Reg, RC: Info.D.RC); |
718 | if (Info.PreferredReg != 0) |
719 | MRI.setSimpleHint(VReg: Reg, PrefReg: Info.PreferredReg); |
720 | break; |
721 | case VRegInfo::GENERIC: |
722 | break; |
723 | case VRegInfo::REGBANK: |
724 | MRI.setRegBank(Reg, RegBank: *Info.D.RegBank); |
725 | break; |
726 | } |
727 | }; |
728 | |
729 | for (const auto &P : PFS.VRegInfosNamed) { |
730 | const VRegInfo &Info = *P.second; |
731 | populateVRegInfo(Info, Twine(P.first())); |
732 | } |
733 | |
734 | for (auto P : PFS.VRegInfos) { |
735 | const VRegInfo &Info = *P.second; |
736 | populateVRegInfo(Info, Twine(P.first)); |
737 | } |
738 | |
739 | // Compute MachineRegisterInfo::UsedPhysRegMask |
740 | for (const MachineBasicBlock &MBB : MF) { |
741 | // Make sure MRI knows about registers clobbered by unwinder. |
742 | if (MBB.isEHPad()) |
743 | if (auto *RegMask = TRI->getCustomEHPadPreservedMask(MF)) |
744 | MRI.addPhysRegsUsedFromRegMask(RegMask); |
745 | |
746 | for (const MachineInstr &MI : MBB) { |
747 | for (const MachineOperand &MO : MI.operands()) { |
748 | if (!MO.isRegMask()) |
749 | continue; |
750 | MRI.addPhysRegsUsedFromRegMask(RegMask: MO.getRegMask()); |
751 | } |
752 | } |
753 | } |
754 | |
755 | return Error; |
756 | } |
757 | |
758 | bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS, |
759 | const yaml::MachineFunction &YamlMF) { |
760 | MachineFunction &MF = PFS.MF; |
761 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
762 | const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); |
763 | const Function &F = MF.getFunction(); |
764 | const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo; |
765 | MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken); |
766 | MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken); |
767 | MFI.setHasStackMap(YamlMFI.HasStackMap); |
768 | MFI.setHasPatchPoint(YamlMFI.HasPatchPoint); |
769 | MFI.setStackSize(YamlMFI.StackSize); |
770 | MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment); |
771 | if (YamlMFI.MaxAlignment) |
772 | MFI.ensureMaxAlignment(Alignment: Align(YamlMFI.MaxAlignment)); |
773 | MFI.setAdjustsStack(YamlMFI.AdjustsStack); |
774 | MFI.setHasCalls(YamlMFI.HasCalls); |
775 | if (YamlMFI.MaxCallFrameSize != ~0u) |
776 | MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize); |
777 | MFI.setCVBytesOfCalleeSavedRegisters(YamlMFI.CVBytesOfCalleeSavedRegisters); |
778 | MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment); |
779 | MFI.setHasVAStart(YamlMFI.HasVAStart); |
780 | MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc); |
781 | MFI.setHasTailCall(YamlMFI.HasTailCall); |
782 | MFI.setCalleeSavedInfoValid(YamlMFI.IsCalleeSavedInfoValid); |
783 | MFI.setLocalFrameSize(YamlMFI.LocalFrameSize); |
784 | if (!YamlMFI.SavePoint.Value.empty()) { |
785 | MachineBasicBlock *MBB = nullptr; |
786 | if (parseMBBReference(PFS, MBB, Source: YamlMFI.SavePoint)) |
787 | return true; |
788 | MFI.setSavePoint(MBB); |
789 | } |
790 | if (!YamlMFI.RestorePoint.Value.empty()) { |
791 | MachineBasicBlock *MBB = nullptr; |
792 | if (parseMBBReference(PFS, MBB, Source: YamlMFI.RestorePoint)) |
793 | return true; |
794 | MFI.setRestorePoint(MBB); |
795 | } |
796 | |
797 | std::vector<CalleeSavedInfo> CSIInfo; |
798 | // Initialize the fixed frame objects. |
799 | for (const auto &Object : YamlMF.FixedStackObjects) { |
800 | int ObjectIdx; |
801 | if (Object.Type != yaml::FixedMachineStackObject::SpillSlot) |
802 | ObjectIdx = MFI.CreateFixedObject(Size: Object.Size, SPOffset: Object.Offset, |
803 | IsImmutable: Object.IsImmutable, isAliased: Object.IsAliased); |
804 | else |
805 | ObjectIdx = MFI.CreateFixedSpillStackObject(Size: Object.Size, SPOffset: Object.Offset); |
806 | |
807 | if (!TFI->isSupportedStackID(ID: Object.StackID)) |
808 | return error(Loc: Object.ID.SourceRange.Start, |
809 | Message: Twine("StackID is not supported by target" )); |
810 | MFI.setStackID(ObjectIdx, ID: Object.StackID); |
811 | MFI.setObjectAlignment(ObjectIdx, Alignment: Object.Alignment.valueOrOne()); |
812 | if (!PFS.FixedStackObjectSlots.insert(KV: std::make_pair(x: Object.ID.Value, |
813 | y&: ObjectIdx)) |
814 | .second) |
815 | return error(Loc: Object.ID.SourceRange.Start, |
816 | Message: Twine("redefinition of fixed stack object '%fixed-stack." ) + |
817 | Twine(Object.ID.Value) + "'" ); |
818 | if (parseCalleeSavedRegister(PFS, CSIInfo, RegisterSource: Object.CalleeSavedRegister, |
819 | IsRestored: Object.CalleeSavedRestored, FrameIdx: ObjectIdx)) |
820 | return true; |
821 | if (parseStackObjectsDebugInfo(PFS, Object, FrameIdx: ObjectIdx)) |
822 | return true; |
823 | } |
824 | |
825 | for (const auto &Object : YamlMF.EntryValueObjects) { |
826 | SMDiagnostic Error; |
827 | Register Reg; |
828 | if (parseNamedRegisterReference(PFS, Reg, Src: Object.EntryValueRegister.Value, |
829 | Error)) |
830 | return error(Error, SourceRange: Object.EntryValueRegister.SourceRange); |
831 | if (!Reg.isPhysical()) |
832 | return error(Loc: Object.EntryValueRegister.SourceRange.Start, |
833 | Message: "Expected physical register for entry value field" ); |
834 | std::optional<VarExprLoc> MaybeInfo = parseVarExprLoc( |
835 | PFS, VarStr: Object.DebugVar, ExprStr: Object.DebugExpr, LocStr: Object.DebugLoc); |
836 | if (!MaybeInfo) |
837 | return true; |
838 | if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc) |
839 | PFS.MF.setVariableDbgInfo(Var: MaybeInfo->DIVar, Expr: MaybeInfo->DIExpr, |
840 | Reg: Reg.asMCReg(), Loc: MaybeInfo->DILoc); |
841 | } |
842 | |
843 | // Initialize the ordinary frame objects. |
844 | for (const auto &Object : YamlMF.StackObjects) { |
845 | int ObjectIdx; |
846 | const AllocaInst *Alloca = nullptr; |
847 | const yaml::StringValue &Name = Object.Name; |
848 | if (!Name.Value.empty()) { |
849 | Alloca = dyn_cast_or_null<AllocaInst>( |
850 | Val: F.getValueSymbolTable()->lookup(Name: Name.Value)); |
851 | if (!Alloca) |
852 | return error(Loc: Name.SourceRange.Start, |
853 | Message: "alloca instruction named '" + Name.Value + |
854 | "' isn't defined in the function '" + F.getName() + |
855 | "'" ); |
856 | } |
857 | if (!TFI->isSupportedStackID(ID: Object.StackID)) |
858 | return error(Loc: Object.ID.SourceRange.Start, |
859 | Message: Twine("StackID is not supported by target" )); |
860 | if (Object.Type == yaml::MachineStackObject::VariableSized) |
861 | ObjectIdx = |
862 | MFI.CreateVariableSizedObject(Alignment: Object.Alignment.valueOrOne(), Alloca); |
863 | else |
864 | ObjectIdx = MFI.CreateStackObject( |
865 | Size: Object.Size, Alignment: Object.Alignment.valueOrOne(), |
866 | isSpillSlot: Object.Type == yaml::MachineStackObject::SpillSlot, Alloca, |
867 | ID: Object.StackID); |
868 | MFI.setObjectOffset(ObjectIdx, SPOffset: Object.Offset); |
869 | |
870 | if (!PFS.StackObjectSlots.insert(KV: std::make_pair(x: Object.ID.Value, y&: ObjectIdx)) |
871 | .second) |
872 | return error(Loc: Object.ID.SourceRange.Start, |
873 | Message: Twine("redefinition of stack object '%stack." ) + |
874 | Twine(Object.ID.Value) + "'" ); |
875 | if (parseCalleeSavedRegister(PFS, CSIInfo, RegisterSource: Object.CalleeSavedRegister, |
876 | IsRestored: Object.CalleeSavedRestored, FrameIdx: ObjectIdx)) |
877 | return true; |
878 | if (Object.LocalOffset) |
879 | MFI.mapLocalFrameObject(ObjectIndex: ObjectIdx, Offset: *Object.LocalOffset); |
880 | if (parseStackObjectsDebugInfo(PFS, Object, FrameIdx: ObjectIdx)) |
881 | return true; |
882 | } |
883 | MFI.setCalleeSavedInfo(CSIInfo); |
884 | if (!CSIInfo.empty()) |
885 | MFI.setCalleeSavedInfoValid(true); |
886 | |
887 | // Initialize the various stack object references after initializing the |
888 | // stack objects. |
889 | if (!YamlMFI.StackProtector.Value.empty()) { |
890 | SMDiagnostic Error; |
891 | int FI; |
892 | if (parseStackObjectReference(PFS, FI, Src: YamlMFI.StackProtector.Value, Error)) |
893 | return error(Error, SourceRange: YamlMFI.StackProtector.SourceRange); |
894 | MFI.setStackProtectorIndex(FI); |
895 | } |
896 | |
897 | if (!YamlMFI.FunctionContext.Value.empty()) { |
898 | SMDiagnostic Error; |
899 | int FI; |
900 | if (parseStackObjectReference(PFS, FI, Src: YamlMFI.FunctionContext.Value, Error)) |
901 | return error(Error, SourceRange: YamlMFI.FunctionContext.SourceRange); |
902 | MFI.setFunctionContextIndex(FI); |
903 | } |
904 | |
905 | return false; |
906 | } |
907 | |
908 | bool MIRParserImpl::parseCalleeSavedRegister(PerFunctionMIParsingState &PFS, |
909 | std::vector<CalleeSavedInfo> &CSIInfo, |
910 | const yaml::StringValue &RegisterSource, bool IsRestored, int FrameIdx) { |
911 | if (RegisterSource.Value.empty()) |
912 | return false; |
913 | Register Reg; |
914 | SMDiagnostic Error; |
915 | if (parseNamedRegisterReference(PFS, Reg, Src: RegisterSource.Value, Error)) |
916 | return error(Error, SourceRange: RegisterSource.SourceRange); |
917 | CalleeSavedInfo CSI(Reg, FrameIdx); |
918 | CSI.setRestored(IsRestored); |
919 | CSIInfo.push_back(x: CSI); |
920 | return false; |
921 | } |
922 | |
923 | /// Verify that given node is of a certain type. Return true on error. |
924 | template <typename T> |
925 | static bool typecheckMDNode(T *&Result, MDNode *Node, |
926 | const yaml::StringValue &Source, |
927 | StringRef TypeString, MIRParserImpl &Parser) { |
928 | if (!Node) |
929 | return false; |
930 | Result = dyn_cast<T>(Node); |
931 | if (!Result) |
932 | return Parser.error(Loc: Source.SourceRange.Start, |
933 | Message: "expected a reference to a '" + TypeString + |
934 | "' metadata node" ); |
935 | return false; |
936 | } |
937 | |
938 | std::optional<MIRParserImpl::VarExprLoc> MIRParserImpl::parseVarExprLoc( |
939 | PerFunctionMIParsingState &PFS, const yaml::StringValue &VarStr, |
940 | const yaml::StringValue &ExprStr, const yaml::StringValue &LocStr) { |
941 | MDNode *Var = nullptr; |
942 | MDNode *Expr = nullptr; |
943 | MDNode *Loc = nullptr; |
944 | if (parseMDNode(PFS, Node&: Var, Source: VarStr) || parseMDNode(PFS, Node&: Expr, Source: ExprStr) || |
945 | parseMDNode(PFS, Node&: Loc, Source: LocStr)) |
946 | return std::nullopt; |
947 | DILocalVariable *DIVar = nullptr; |
948 | DIExpression *DIExpr = nullptr; |
949 | DILocation *DILoc = nullptr; |
950 | if (typecheckMDNode(Result&: DIVar, Node: Var, Source: VarStr, TypeString: "DILocalVariable" , Parser&: *this) || |
951 | typecheckMDNode(Result&: DIExpr, Node: Expr, Source: ExprStr, TypeString: "DIExpression" , Parser&: *this) || |
952 | typecheckMDNode(Result&: DILoc, Node: Loc, Source: LocStr, TypeString: "DILocation" , Parser&: *this)) |
953 | return std::nullopt; |
954 | return VarExprLoc{.DIVar: DIVar, .DIExpr: DIExpr, .DILoc: DILoc}; |
955 | } |
956 | |
957 | template <typename T> |
958 | bool MIRParserImpl::parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS, |
959 | const T &Object, int FrameIdx) { |
960 | std::optional<VarExprLoc> MaybeInfo = |
961 | parseVarExprLoc(PFS, VarStr: Object.DebugVar, ExprStr: Object.DebugExpr, LocStr: Object.DebugLoc); |
962 | if (!MaybeInfo) |
963 | return true; |
964 | // Debug information can only be attached to stack objects; Fixed stack |
965 | // objects aren't supported. |
966 | if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc) |
967 | PFS.MF.setVariableDbgInfo(Var: MaybeInfo->DIVar, Expr: MaybeInfo->DIExpr, Slot: FrameIdx, |
968 | Loc: MaybeInfo->DILoc); |
969 | return false; |
970 | } |
971 | |
972 | bool MIRParserImpl::parseMDNode(PerFunctionMIParsingState &PFS, |
973 | MDNode *&Node, const yaml::StringValue &Source) { |
974 | if (Source.Value.empty()) |
975 | return false; |
976 | SMDiagnostic Error; |
977 | if (llvm::parseMDNode(PFS, Node, Src: Source.Value, Error)) |
978 | return error(Error, SourceRange: Source.SourceRange); |
979 | return false; |
980 | } |
981 | |
982 | bool MIRParserImpl::initializeConstantPool(PerFunctionMIParsingState &PFS, |
983 | MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF) { |
984 | DenseMap<unsigned, unsigned> &ConstantPoolSlots = PFS.ConstantPoolSlots; |
985 | const MachineFunction &MF = PFS.MF; |
986 | const auto &M = *MF.getFunction().getParent(); |
987 | SMDiagnostic Error; |
988 | for (const auto &YamlConstant : YamlMF.Constants) { |
989 | if (YamlConstant.IsTargetSpecific) |
990 | // FIXME: Support target-specific constant pools |
991 | return error(Loc: YamlConstant.Value.SourceRange.Start, |
992 | Message: "Can't parse target-specific constant pool entries yet" ); |
993 | const Constant *Value = dyn_cast_or_null<Constant>( |
994 | Val: parseConstantValue(Asm: YamlConstant.Value.Value, Err&: Error, M)); |
995 | if (!Value) |
996 | return error(Error, SourceRange: YamlConstant.Value.SourceRange); |
997 | const Align PrefTypeAlign = |
998 | M.getDataLayout().getPrefTypeAlign(Ty: Value->getType()); |
999 | const Align Alignment = YamlConstant.Alignment.value_or(u: PrefTypeAlign); |
1000 | unsigned Index = ConstantPool.getConstantPoolIndex(C: Value, Alignment); |
1001 | if (!ConstantPoolSlots.insert(KV: std::make_pair(x: YamlConstant.ID.Value, y&: Index)) |
1002 | .second) |
1003 | return error(Loc: YamlConstant.ID.SourceRange.Start, |
1004 | Message: Twine("redefinition of constant pool item '%const." ) + |
1005 | Twine(YamlConstant.ID.Value) + "'" ); |
1006 | } |
1007 | return false; |
1008 | } |
1009 | |
1010 | bool MIRParserImpl::initializeJumpTableInfo(PerFunctionMIParsingState &PFS, |
1011 | const yaml::MachineJumpTable &YamlJTI) { |
1012 | MachineJumpTableInfo *JTI = PFS.MF.getOrCreateJumpTableInfo(JTEntryKind: YamlJTI.Kind); |
1013 | for (const auto &Entry : YamlJTI.Entries) { |
1014 | std::vector<MachineBasicBlock *> Blocks; |
1015 | for (const auto &MBBSource : Entry.Blocks) { |
1016 | MachineBasicBlock *MBB = nullptr; |
1017 | if (parseMBBReference(PFS, MBB, Source: MBBSource.Value)) |
1018 | return true; |
1019 | Blocks.push_back(x: MBB); |
1020 | } |
1021 | unsigned Index = JTI->createJumpTableIndex(DestBBs: Blocks); |
1022 | if (!PFS.JumpTableSlots.insert(KV: std::make_pair(x: Entry.ID.Value, y&: Index)) |
1023 | .second) |
1024 | return error(Loc: Entry.ID.SourceRange.Start, |
1025 | Message: Twine("redefinition of jump table entry '%jump-table." ) + |
1026 | Twine(Entry.ID.Value) + "'" ); |
1027 | } |
1028 | return false; |
1029 | } |
1030 | |
1031 | bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS, |
1032 | MachineBasicBlock *&MBB, |
1033 | const yaml::StringValue &Source) { |
1034 | SMDiagnostic Error; |
1035 | if (llvm::parseMBBReference(PFS, MBB, Src: Source.Value, Error)) |
1036 | return error(Error, SourceRange: Source.SourceRange); |
1037 | return false; |
1038 | } |
1039 | |
1040 | bool MIRParserImpl::parseMachineMetadata(PerFunctionMIParsingState &PFS, |
1041 | const yaml::StringValue &Source) { |
1042 | SMDiagnostic Error; |
1043 | if (llvm::parseMachineMetadata(PFS, Src: Source.Value, SourceRange: Source.SourceRange, Error)) |
1044 | return error(Error, SourceRange: Source.SourceRange); |
1045 | return false; |
1046 | } |
1047 | |
1048 | bool MIRParserImpl::parseMachineMetadataNodes( |
1049 | PerFunctionMIParsingState &PFS, MachineFunction &MF, |
1050 | const yaml::MachineFunction &YMF) { |
1051 | for (const auto &MDS : YMF.MachineMetadataNodes) { |
1052 | if (parseMachineMetadata(PFS, Source: MDS)) |
1053 | return true; |
1054 | } |
1055 | // Report missing definitions from forward referenced nodes. |
1056 | if (!PFS.MachineForwardRefMDNodes.empty()) |
1057 | return error(Loc: PFS.MachineForwardRefMDNodes.begin()->second.second, |
1058 | Message: "use of undefined metadata '!" + |
1059 | Twine(PFS.MachineForwardRefMDNodes.begin()->first) + "'" ); |
1060 | return false; |
1061 | } |
1062 | |
1063 | SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error, |
1064 | SMRange SourceRange) { |
1065 | assert(SourceRange.isValid() && "Invalid source range" ); |
1066 | SMLoc Loc = SourceRange.Start; |
1067 | bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() && |
1068 | *Loc.getPointer() == '\''; |
1069 | // Translate the location of the error from the location in the MI string to |
1070 | // the corresponding location in the MIR file. |
1071 | Loc = Loc.getFromPointer(Ptr: Loc.getPointer() + Error.getColumnNo() + |
1072 | (HasQuote ? 1 : 0)); |
1073 | |
1074 | // TODO: Translate any source ranges as well. |
1075 | return SM.GetMessage(Loc, Kind: Error.getKind(), Msg: Error.getMessage(), Ranges: std::nullopt, |
1076 | FixIts: Error.getFixIts()); |
1077 | } |
1078 | |
1079 | SMDiagnostic MIRParserImpl::diagFromBlockStringDiag(const SMDiagnostic &Error, |
1080 | SMRange SourceRange) { |
1081 | assert(SourceRange.isValid()); |
1082 | |
1083 | // Translate the location of the error from the location in the llvm IR string |
1084 | // to the corresponding location in the MIR file. |
1085 | auto LineAndColumn = SM.getLineAndColumn(Loc: SourceRange.Start); |
1086 | unsigned Line = LineAndColumn.first + Error.getLineNo() - 1; |
1087 | unsigned Column = Error.getColumnNo(); |
1088 | StringRef LineStr = Error.getLineContents(); |
1089 | SMLoc Loc = Error.getLoc(); |
1090 | |
1091 | // Get the full line and adjust the column number by taking the indentation of |
1092 | // LLVM IR into account. |
1093 | for (line_iterator L(*SM.getMemoryBuffer(i: SM.getMainFileID()), false), E; |
1094 | L != E; ++L) { |
1095 | if (L.line_number() == Line) { |
1096 | LineStr = *L; |
1097 | Loc = SMLoc::getFromPointer(Ptr: LineStr.data()); |
1098 | auto Indent = LineStr.find(Str: Error.getLineContents()); |
1099 | if (Indent != StringRef::npos) |
1100 | Column += Indent; |
1101 | break; |
1102 | } |
1103 | } |
1104 | |
1105 | return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(), |
1106 | Error.getMessage(), LineStr, Error.getRanges(), |
1107 | Error.getFixIts()); |
1108 | } |
1109 | |
1110 | MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl) |
1111 | : Impl(std::move(Impl)) {} |
1112 | |
1113 | MIRParser::~MIRParser() = default; |
1114 | |
1115 | std::unique_ptr<Module> |
1116 | MIRParser::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) { |
1117 | return Impl->parseIRModule(DataLayoutCallback); |
1118 | } |
1119 | |
1120 | bool MIRParser::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) { |
1121 | return Impl->parseMachineFunctions(M, MMI); |
1122 | } |
1123 | |
1124 | bool MIRParser::parseMachineFunctions(Module &M, ModuleAnalysisManager &MAM) { |
1125 | auto &MMI = MAM.getResult<MachineModuleAnalysis>(IR&: M).getMMI(); |
1126 | return Impl->parseMachineFunctions(M, MMI, MAM: &MAM); |
1127 | } |
1128 | |
1129 | std::unique_ptr<MIRParser> llvm::createMIRParserFromFile( |
1130 | StringRef Filename, SMDiagnostic &Error, LLVMContext &Context, |
1131 | std::function<void(Function &)> ProcessIRFunction) { |
1132 | auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true); |
1133 | if (std::error_code EC = FileOrErr.getError()) { |
1134 | Error = SMDiagnostic(Filename, SourceMgr::DK_Error, |
1135 | "Could not open input file: " + EC.message()); |
1136 | return nullptr; |
1137 | } |
1138 | return createMIRParser(Contents: std::move(FileOrErr.get()), Context, |
1139 | ProcessIRFunction); |
1140 | } |
1141 | |
1142 | std::unique_ptr<MIRParser> |
1143 | llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents, |
1144 | LLVMContext &Context, |
1145 | std::function<void(Function &)> ProcessIRFunction) { |
1146 | auto Filename = Contents->getBufferIdentifier(); |
1147 | if (Context.shouldDiscardValueNames()) { |
1148 | Context.diagnose(DI: DiagnosticInfoMIRParser( |
1149 | DS_Error, |
1150 | SMDiagnostic( |
1151 | Filename, SourceMgr::DK_Error, |
1152 | "Can't read MIR with a Context that discards named Values" ))); |
1153 | return nullptr; |
1154 | } |
1155 | return std::make_unique<MIRParser>(args: std::make_unique<MIRParserImpl>( |
1156 | args: std::move(Contents), args&: Filename, args&: Context, args&: ProcessIRFunction)); |
1157 | } |
1158 | |