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