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
21using namespace llvm;
22
23static 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
37bool 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
45std::unique_ptr<Module>
46llvm::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
58std::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
73static ParsedModuleAndIndex
74parseAssemblyWithIndex(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
90ParsedModuleAndIndex 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
100static ParsedModuleAndIndex
101parseAssemblyFileWithIndex(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
118ParsedModuleAndIndex
119llvm::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
127ParsedModuleAndIndex 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
135std::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
143static 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
157std::unique_ptr<ModuleSummaryIndex>
158llvm::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
168std::unique_ptr<ModuleSummaryIndex>
169llvm::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
181std::unique_ptr<ModuleSummaryIndex>
182llvm::parseSummaryIndexAssemblyString(StringRef AsmString, SMDiagnostic &Err) {
183 MemoryBufferRef F(AsmString, "<string>");
184 return parseSummaryIndexAssembly(F, Err);
185}
186
187Constant *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
199Type *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}
215Type *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

source code of llvm/lib/AsmParser/Parser.cpp