xref: /freebsd/contrib/llvm-project/llvm/lib/AsmParser/Parser.cpp (revision 27ef5d48c729defb83a8822143dc71ab17f9d68b)
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(F);
30    SM.AddNewSourceBuffer(std::move(Buf), 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>(F.getBufferIdentifier(), Context);
52  
53    if (parseAssemblyInto(F, M.get(), 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(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>(F.getBufferIdentifier(), Context);
81    std::unique_ptr<ModuleSummaryIndex> Index =
82        std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/true);
83  
84    if (parseAssemblyInto(F, M.get(), Index.get(), Err, Slots, UpgradeDebugInfo,
85                          DataLayoutCallback))
86      return {nullptr, nullptr};
87  
88    return {std::move(M), 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        [](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 {nullptr, nullptr};
112    }
113  
114    return parseAssemblyWithIndex(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(F);
149    SM.AddNewSourceBuffer(std::move(Buf), 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(true, [](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=*/false);
162  
163    if (parseSummaryIndexAssemblyInto(F, *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(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(Asm);
192    SM.AddNewSourceBuffer(std::move(Buf), 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(Asm);
209      SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
210      Err = SM.GetMessage(SMLoc::getFromPointer(Asm.begin() + Read),
211                          SourceMgr::DK_Error, "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(Asm);
221    SM.AddNewSourceBuffer(std::move(Buf), 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(Asm);
236    SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
237    MDNode *MD;
238    if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext())
239            .parseDIExpressionBodyAtBeginning(MD, Read, Slots))
240      return nullptr;
241    return dyn_cast<DIExpression>(MD);
242  }
243