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