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 LLVMContext Context; 32 return LLParser(F.getBuffer(), SM, Err, M, Index, 33 M ? M->getContext() : Context, 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(F, Err, Context, Slots, 95 /*UpgradeDebugInfo*/ true, 96 [](StringRef) { return None; }); 97 } 98 99 static ParsedModuleAndIndex 100 parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, 101 LLVMContext &Context, SlotMapping *Slots, 102 bool UpgradeDebugInfo, 103 DataLayoutCallbackTy DataLayoutCallback) { 104 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 105 MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true); 106 if (std::error_code EC = FileOrErr.getError()) { 107 Err = SMDiagnostic(Filename, SourceMgr::DK_Error, 108 "Could not open input file: " + EC.message()); 109 return {nullptr, nullptr}; 110 } 111 112 return parseAssemblyWithIndex(FileOrErr.get()->getMemBufferRef(), Err, 113 Context, Slots, UpgradeDebugInfo, 114 DataLayoutCallback); 115 } 116 117 ParsedModuleAndIndex 118 llvm::parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, 119 LLVMContext &Context, SlotMapping *Slots, 120 DataLayoutCallbackTy DataLayoutCallback) { 121 return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, 122 /*UpgradeDebugInfo*/ true, 123 DataLayoutCallback); 124 } 125 126 ParsedModuleAndIndex llvm::parseAssemblyFileWithIndexNoUpgradeDebugInfo( 127 StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, 128 SlotMapping *Slots, DataLayoutCallbackTy DataLayoutCallback) { 129 return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, 130 /*UpgradeDebugInfo*/ false, 131 DataLayoutCallback); 132 } 133 134 std::unique_ptr<Module> llvm::parseAssemblyString(StringRef AsmString, 135 SMDiagnostic &Err, 136 LLVMContext &Context, 137 SlotMapping *Slots) { 138 MemoryBufferRef F(AsmString, "<string>"); 139 return parseAssembly(F, Err, Context, Slots); 140 } 141 142 static bool parseSummaryIndexAssemblyInto(MemoryBufferRef F, 143 ModuleSummaryIndex &Index, 144 SMDiagnostic &Err) { 145 SourceMgr SM; 146 std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(F); 147 SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); 148 149 // The parser holds a reference to a context that is unused when parsing the 150 // index, but we need to initialize it. 151 LLVMContext unusedContext; 152 return LLParser(F.getBuffer(), SM, Err, nullptr, &Index, unusedContext) 153 .Run(true, [](StringRef) { return None; }); 154 } 155 156 std::unique_ptr<ModuleSummaryIndex> 157 llvm::parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err) { 158 std::unique_ptr<ModuleSummaryIndex> Index = 159 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false); 160 161 if (parseSummaryIndexAssemblyInto(F, *Index, Err)) 162 return nullptr; 163 164 return Index; 165 } 166 167 std::unique_ptr<ModuleSummaryIndex> 168 llvm::parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err) { 169 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 170 MemoryBuffer::getFileOrSTDIN(Filename); 171 if (std::error_code EC = FileOrErr.getError()) { 172 Err = SMDiagnostic(Filename, SourceMgr::DK_Error, 173 "Could not open input file: " + EC.message()); 174 return nullptr; 175 } 176 177 return parseSummaryIndexAssembly(FileOrErr.get()->getMemBufferRef(), Err); 178 } 179 180 Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, 181 const Module &M, const SlotMapping *Slots) { 182 SourceMgr SM; 183 std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); 184 SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); 185 Constant *C; 186 if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) 187 .parseStandaloneConstantValue(C, Slots)) 188 return nullptr; 189 return C; 190 } 191 192 Type *llvm::parseType(StringRef Asm, SMDiagnostic &Err, const Module &M, 193 const SlotMapping *Slots) { 194 unsigned Read; 195 Type *Ty = parseTypeAtBeginning(Asm, Read, Err, M, Slots); 196 if (!Ty) 197 return nullptr; 198 if (Read != Asm.size()) { 199 SourceMgr SM; 200 std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); 201 SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); 202 Err = SM.GetMessage(SMLoc::getFromPointer(Asm.begin() + Read), 203 SourceMgr::DK_Error, "expected end of string"); 204 return nullptr; 205 } 206 return Ty; 207 } 208 Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read, 209 SMDiagnostic &Err, const Module &M, 210 const SlotMapping *Slots) { 211 SourceMgr SM; 212 std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); 213 SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); 214 Type *Ty; 215 if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) 216 .parseTypeAtBeginning(Ty, Read, Slots)) 217 return nullptr; 218 return Ty; 219 } 220