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(F); 29 SM.AddNewSourceBuffer(std::move(Buf), 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>(F.getBufferIdentifier(), Context); 51 52 if (parseAssemblyInto(F, M.get(), 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(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>(F.getBufferIdentifier(), Context); 80 std::unique_ptr<ModuleSummaryIndex> Index = 81 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/true); 82 83 if (parseAssemblyInto(F, M.get(), Index.get(), Err, Slots, UpgradeDebugInfo, 84 DataLayoutCallback)) 85 return {nullptr, nullptr}; 86 87 return {std::move(M), 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 [](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 {nullptr, nullptr}; 111 } 112 113 return parseAssemblyWithIndex(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(F); 148 SM.AddNewSourceBuffer(std::move(Buf), 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(true, [](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=*/false); 161 162 if (parseSummaryIndexAssemblyInto(F, *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(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(Asm); 191 SM.AddNewSourceBuffer(std::move(Buf), 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(Asm); 208 SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); 209 Err = SM.GetMessage(SMLoc::getFromPointer(Asm.begin() + Read), 210 SourceMgr::DK_Error, "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(Asm); 220 SM.AddNewSourceBuffer(std::move(Buf), 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