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