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