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