1 | //===- Parser.cpp - Main dispatch module for the Parser library -----------===// |
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 library implements the functionality defined in llvm/AsmParser/Parser.h |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/AsmParser/Parser.h" |
14 | #include "llvm/AsmParser/LLParser.h" |
15 | #include "llvm/IR/DebugInfoMetadata.h" |
16 | #include "llvm/IR/Module.h" |
17 | #include "llvm/IR/ModuleSummaryIndex.h" |
18 | #include "llvm/Support/MemoryBuffer.h" |
19 | #include "llvm/Support/SourceMgr.h" |
20 | #include <system_error> |
21 | |
22 | using namespace llvm; |
23 | |
24 | static bool parseAssemblyInto(MemoryBufferRef F, Module *M, |
25 | ModuleSummaryIndex *Index, SMDiagnostic &Err, |
26 | SlotMapping *Slots, bool UpgradeDebugInfo, |
27 | DataLayoutCallbackTy DataLayoutCallback) { |
28 | SourceMgr SM; |
29 | std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Ref: F); |
30 | SM.AddNewSourceBuffer(F: std::move(Buf), IncludeLoc: SMLoc()); |
31 | |
32 | std::optional<LLVMContext> OptContext; |
33 | return LLParser(F.getBuffer(), SM, Err, M, Index, |
34 | M ? M->getContext() : OptContext.emplace(), Slots) |
35 | .Run(UpgradeDebugInfo, DataLayoutCallback); |
36 | } |
37 | |
38 | bool llvm::parseAssemblyInto(MemoryBufferRef F, Module *M, |
39 | ModuleSummaryIndex *Index, SMDiagnostic &Err, |
40 | SlotMapping *Slots, |
41 | DataLayoutCallbackTy DataLayoutCallback) { |
42 | return ::parseAssemblyInto(F, M, Index, Err, Slots, |
43 | /*UpgradeDebugInfo*/ true, DataLayoutCallback); |
44 | } |
45 | |
46 | std::unique_ptr<Module> |
47 | llvm::parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context, |
48 | SlotMapping *Slots, |
49 | DataLayoutCallbackTy DataLayoutCallback) { |
50 | std::unique_ptr<Module> M = |
51 | std::make_unique<Module>(args: F.getBufferIdentifier(), args&: Context); |
52 | |
53 | if (parseAssemblyInto(F, M: M.get(), Index: nullptr, Err, Slots, DataLayoutCallback)) |
54 | return nullptr; |
55 | |
56 | return M; |
57 | } |
58 | |
59 | std::unique_ptr<Module> llvm::parseAssemblyFile(StringRef Filename, |
60 | SMDiagnostic &Err, |
61 | LLVMContext &Context, |
62 | SlotMapping *Slots) { |
63 | ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = |
64 | MemoryBuffer::getFileOrSTDIN(Filename); |
65 | if (std::error_code EC = FileOrErr.getError()) { |
66 | Err = SMDiagnostic(Filename, SourceMgr::DK_Error, |
67 | "Could not open input file: " + EC.message()); |
68 | return nullptr; |
69 | } |
70 | |
71 | return parseAssembly(F: FileOrErr.get()->getMemBufferRef(), Err, Context, Slots); |
72 | } |
73 | |
74 | static ParsedModuleAndIndex |
75 | parseAssemblyWithIndex(MemoryBufferRef F, SMDiagnostic &Err, |
76 | LLVMContext &Context, SlotMapping *Slots, |
77 | bool UpgradeDebugInfo, |
78 | DataLayoutCallbackTy DataLayoutCallback) { |
79 | std::unique_ptr<Module> M = |
80 | std::make_unique<Module>(args: F.getBufferIdentifier(), args&: Context); |
81 | std::unique_ptr<ModuleSummaryIndex> Index = |
82 | std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/args: true); |
83 | |
84 | if (parseAssemblyInto(F, M: M.get(), Index: Index.get(), Err, Slots, UpgradeDebugInfo, |
85 | DataLayoutCallback)) |
86 | return {.Mod: nullptr, .Index: nullptr}; |
87 | |
88 | return {.Mod: std::move(M), .Index: std::move(Index)}; |
89 | } |
90 | |
91 | ParsedModuleAndIndex llvm::parseAssemblyWithIndex(MemoryBufferRef F, |
92 | SMDiagnostic &Err, |
93 | LLVMContext &Context, |
94 | SlotMapping *Slots) { |
95 | return ::parseAssemblyWithIndex( |
96 | F, Err, Context, Slots, |
97 | /*UpgradeDebugInfo*/ true, |
98 | DataLayoutCallback: [](StringRef, StringRef) { return std::nullopt; }); |
99 | } |
100 | |
101 | static ParsedModuleAndIndex |
102 | parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, |
103 | LLVMContext &Context, SlotMapping *Slots, |
104 | bool UpgradeDebugInfo, |
105 | DataLayoutCallbackTy DataLayoutCallback) { |
106 | ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = |
107 | MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true); |
108 | if (std::error_code EC = FileOrErr.getError()) { |
109 | Err = SMDiagnostic(Filename, SourceMgr::DK_Error, |
110 | "Could not open input file: " + EC.message()); |
111 | return {.Mod: nullptr, .Index: nullptr}; |
112 | } |
113 | |
114 | return parseAssemblyWithIndex(F: FileOrErr.get()->getMemBufferRef(), Err, |
115 | Context, Slots, UpgradeDebugInfo, |
116 | DataLayoutCallback); |
117 | } |
118 | |
119 | ParsedModuleAndIndex |
120 | llvm::parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, |
121 | LLVMContext &Context, SlotMapping *Slots, |
122 | DataLayoutCallbackTy DataLayoutCallback) { |
123 | return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, |
124 | /*UpgradeDebugInfo*/ true, |
125 | DataLayoutCallback); |
126 | } |
127 | |
128 | ParsedModuleAndIndex llvm::parseAssemblyFileWithIndexNoUpgradeDebugInfo( |
129 | StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, |
130 | SlotMapping *Slots, DataLayoutCallbackTy DataLayoutCallback) { |
131 | return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, |
132 | /*UpgradeDebugInfo*/ false, |
133 | DataLayoutCallback); |
134 | } |
135 | |
136 | std::unique_ptr<Module> llvm::parseAssemblyString(StringRef AsmString, |
137 | SMDiagnostic &Err, |
138 | LLVMContext &Context, |
139 | SlotMapping *Slots) { |
140 | MemoryBufferRef F(AsmString, "<string>" ); |
141 | return parseAssembly(F, Err, Context, Slots); |
142 | } |
143 | |
144 | static bool parseSummaryIndexAssemblyInto(MemoryBufferRef F, |
145 | ModuleSummaryIndex &Index, |
146 | SMDiagnostic &Err) { |
147 | SourceMgr SM; |
148 | std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Ref: F); |
149 | SM.AddNewSourceBuffer(F: std::move(Buf), IncludeLoc: SMLoc()); |
150 | |
151 | // The parser holds a reference to a context that is unused when parsing the |
152 | // index, but we need to initialize it. |
153 | LLVMContext unusedContext; |
154 | return LLParser(F.getBuffer(), SM, Err, nullptr, &Index, unusedContext) |
155 | .Run(UpgradeDebugInfo: true, DataLayoutCallback: [](StringRef, StringRef) { return std::nullopt; }); |
156 | } |
157 | |
158 | std::unique_ptr<ModuleSummaryIndex> |
159 | llvm::parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err) { |
160 | std::unique_ptr<ModuleSummaryIndex> Index = |
161 | std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/args: false); |
162 | |
163 | if (parseSummaryIndexAssemblyInto(F, Index&: *Index, Err)) |
164 | return nullptr; |
165 | |
166 | return Index; |
167 | } |
168 | |
169 | std::unique_ptr<ModuleSummaryIndex> |
170 | llvm::parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err) { |
171 | ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = |
172 | MemoryBuffer::getFileOrSTDIN(Filename); |
173 | if (std::error_code EC = FileOrErr.getError()) { |
174 | Err = SMDiagnostic(Filename, SourceMgr::DK_Error, |
175 | "Could not open input file: " + EC.message()); |
176 | return nullptr; |
177 | } |
178 | |
179 | return parseSummaryIndexAssembly(F: FileOrErr.get()->getMemBufferRef(), Err); |
180 | } |
181 | |
182 | std::unique_ptr<ModuleSummaryIndex> |
183 | llvm::parseSummaryIndexAssemblyString(StringRef AsmString, SMDiagnostic &Err) { |
184 | MemoryBufferRef F(AsmString, "<string>" ); |
185 | return parseSummaryIndexAssembly(F, Err); |
186 | } |
187 | |
188 | Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, |
189 | const Module &M, const SlotMapping *Slots) { |
190 | SourceMgr SM; |
191 | std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(InputData: Asm); |
192 | SM.AddNewSourceBuffer(F: std::move(Buf), IncludeLoc: SMLoc()); |
193 | Constant *C; |
194 | if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) |
195 | .parseStandaloneConstantValue(C, Slots)) |
196 | return nullptr; |
197 | return C; |
198 | } |
199 | |
200 | Type *llvm::parseType(StringRef Asm, SMDiagnostic &Err, const Module &M, |
201 | const SlotMapping *Slots) { |
202 | unsigned Read; |
203 | Type *Ty = parseTypeAtBeginning(Asm, Read, Err, M, Slots); |
204 | if (!Ty) |
205 | return nullptr; |
206 | if (Read != Asm.size()) { |
207 | SourceMgr SM; |
208 | std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(InputData: Asm); |
209 | SM.AddNewSourceBuffer(F: std::move(Buf), IncludeLoc: SMLoc()); |
210 | Err = SM.GetMessage(Loc: SMLoc::getFromPointer(Ptr: Asm.begin() + Read), |
211 | Kind: SourceMgr::DK_Error, Msg: "expected end of string" ); |
212 | return nullptr; |
213 | } |
214 | return Ty; |
215 | } |
216 | Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read, |
217 | SMDiagnostic &Err, const Module &M, |
218 | const SlotMapping *Slots) { |
219 | SourceMgr SM; |
220 | std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(InputData: Asm); |
221 | SM.AddNewSourceBuffer(F: std::move(Buf), IncludeLoc: SMLoc()); |
222 | Type *Ty; |
223 | if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) |
224 | .parseTypeAtBeginning(Ty, Read, Slots)) |
225 | return nullptr; |
226 | return Ty; |
227 | } |
228 | |
229 | DIExpression *llvm::parseDIExpressionBodyAtBeginning(StringRef Asm, |
230 | unsigned &Read, |
231 | SMDiagnostic &Err, |
232 | const Module &M, |
233 | const SlotMapping *Slots) { |
234 | SourceMgr SM; |
235 | std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(InputData: Asm); |
236 | SM.AddNewSourceBuffer(F: std::move(Buf), IncludeLoc: SMLoc()); |
237 | MDNode *MD; |
238 | if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) |
239 | .parseDIExpressionBodyAtBeginning(Result&: MD, Read, Slots)) |
240 | return nullptr; |
241 | return dyn_cast<DIExpression>(Val: MD); |
242 | } |
243 | |