1 //===- MIRParser.cpp - MIR serialization format parser implementation -----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the class that parses the optional LLVM IR and machine 11 // functions that are stored in MIR files. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/CodeGen/MIRParser/MIRParser.h" 16 #include "MIParser.h" 17 #include "llvm/ADT/DenseMap.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/StringMap.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/AsmParser/Parser.h" 22 #include "llvm/AsmParser/SlotMapping.h" 23 #include "llvm/CodeGen/MachineFunction.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 #include "llvm/CodeGen/MIRYamlMapping.h" 26 #include "llvm/IR/BasicBlock.h" 27 #include "llvm/IR/DiagnosticInfo.h" 28 #include "llvm/IR/Instructions.h" 29 #include "llvm/IR/LLVMContext.h" 30 #include "llvm/IR/Module.h" 31 #include "llvm/IR/ValueSymbolTable.h" 32 #include "llvm/Support/LineIterator.h" 33 #include "llvm/Support/SMLoc.h" 34 #include "llvm/Support/SourceMgr.h" 35 #include "llvm/Support/MemoryBuffer.h" 36 #include "llvm/Support/YAMLTraits.h" 37 #include <memory> 38 39 using namespace llvm; 40 41 namespace llvm { 42 43 /// This class implements the parsing of LLVM IR that's embedded inside a MIR 44 /// file. 45 class MIRParserImpl { 46 SourceMgr SM; 47 StringRef Filename; 48 LLVMContext &Context; 49 StringMap<std::unique_ptr<yaml::MachineFunction>> Functions; 50 SlotMapping IRSlots; 51 52 public: 53 MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename, 54 LLVMContext &Context); 55 56 void reportDiagnostic(const SMDiagnostic &Diag); 57 58 /// Report an error with the given message at unknown location. 59 /// 60 /// Always returns true. 61 bool error(const Twine &Message); 62 63 /// Report a given error with the location translated from the location in an 64 /// embedded string literal to a location in the MIR file. 65 /// 66 /// Always returns true. 67 bool error(const SMDiagnostic &Error, SMRange SourceRange); 68 69 /// Try to parse the optional LLVM module and the machine functions in the MIR 70 /// file. 71 /// 72 /// Return null if an error occurred. 73 std::unique_ptr<Module> parse(); 74 75 /// Parse the machine function in the current YAML document. 76 /// 77 /// \param NoLLVMIR - set to true when the MIR file doesn't have LLVM IR. 78 /// A dummy IR function is created and inserted into the given module when 79 /// this parameter is true. 80 /// 81 /// Return true if an error occurred. 82 bool parseMachineFunction(yaml::Input &In, Module &M, bool NoLLVMIR); 83 84 /// Initialize the machine function to the state that's described in the MIR 85 /// file. 86 /// 87 /// Return true if error occurred. 88 bool initializeMachineFunction(MachineFunction &MF); 89 90 /// Initialize the machine basic block using it's YAML representation. 91 /// 92 /// Return true if an error occurred. 93 bool initializeMachineBasicBlock( 94 MachineFunction &MF, MachineBasicBlock &MBB, 95 const yaml::MachineBasicBlock &YamlMBB, 96 const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots); 97 98 bool initializeRegisterInfo(MachineRegisterInfo &RegInfo, 99 const yaml::MachineFunction &YamlMF); 100 101 private: 102 /// Return a MIR diagnostic converted from an MI string diagnostic. 103 SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error, 104 SMRange SourceRange); 105 106 /// Return a MIR diagnostic converted from an LLVM assembly diagnostic. 107 SMDiagnostic diagFromLLVMAssemblyDiag(const SMDiagnostic &Error, 108 SMRange SourceRange); 109 110 /// Create an empty function with the given name. 111 void createDummyFunction(StringRef Name, Module &M); 112 }; 113 114 } // end namespace llvm 115 116 MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, 117 StringRef Filename, LLVMContext &Context) 118 : SM(), Filename(Filename), Context(Context) { 119 SM.AddNewSourceBuffer(std::move(Contents), SMLoc()); 120 } 121 122 bool MIRParserImpl::error(const Twine &Message) { 123 Context.diagnose(DiagnosticInfoMIRParser( 124 DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str()))); 125 return true; 126 } 127 128 bool MIRParserImpl::error(const SMDiagnostic &Error, SMRange SourceRange) { 129 assert(Error.getKind() == SourceMgr::DK_Error && "Expected an error"); 130 reportDiagnostic(diagFromMIStringDiag(Error, SourceRange)); 131 return true; 132 } 133 134 void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) { 135 DiagnosticSeverity Kind; 136 switch (Diag.getKind()) { 137 case SourceMgr::DK_Error: 138 Kind = DS_Error; 139 break; 140 case SourceMgr::DK_Warning: 141 Kind = DS_Warning; 142 break; 143 case SourceMgr::DK_Note: 144 Kind = DS_Note; 145 break; 146 } 147 Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag)); 148 } 149 150 static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) { 151 reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag); 152 } 153 154 std::unique_ptr<Module> MIRParserImpl::parse() { 155 yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(), 156 /*Ctxt=*/nullptr, handleYAMLDiag, this); 157 In.setContext(&In); 158 159 if (!In.setCurrentDocument()) { 160 if (In.error()) 161 return nullptr; 162 // Create an empty module when the MIR file is empty. 163 return llvm::make_unique<Module>(Filename, Context); 164 } 165 166 std::unique_ptr<Module> M; 167 bool NoLLVMIR = false; 168 // Parse the block scalar manually so that we can return unique pointer 169 // without having to go trough YAML traits. 170 if (const auto *BSN = 171 dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) { 172 SMDiagnostic Error; 173 M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error, 174 Context, &IRSlots); 175 if (!M) { 176 reportDiagnostic(diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange())); 177 return M; 178 } 179 In.nextDocument(); 180 if (!In.setCurrentDocument()) 181 return M; 182 } else { 183 // Create an new, empty module. 184 M = llvm::make_unique<Module>(Filename, Context); 185 NoLLVMIR = true; 186 } 187 188 // Parse the machine functions. 189 do { 190 if (parseMachineFunction(In, *M, NoLLVMIR)) 191 return nullptr; 192 In.nextDocument(); 193 } while (In.setCurrentDocument()); 194 195 return M; 196 } 197 198 bool MIRParserImpl::parseMachineFunction(yaml::Input &In, Module &M, 199 bool NoLLVMIR) { 200 auto MF = llvm::make_unique<yaml::MachineFunction>(); 201 yaml::yamlize(In, *MF, false); 202 if (In.error()) 203 return true; 204 auto FunctionName = MF->Name; 205 if (Functions.find(FunctionName) != Functions.end()) 206 return error(Twine("redefinition of machine function '") + FunctionName + 207 "'"); 208 Functions.insert(std::make_pair(FunctionName, std::move(MF))); 209 if (NoLLVMIR) 210 createDummyFunction(FunctionName, M); 211 else if (!M.getFunction(FunctionName)) 212 return error(Twine("function '") + FunctionName + 213 "' isn't defined in the provided LLVM IR"); 214 return false; 215 } 216 217 void MIRParserImpl::createDummyFunction(StringRef Name, Module &M) { 218 auto &Context = M.getContext(); 219 Function *F = cast<Function>(M.getOrInsertFunction( 220 Name, FunctionType::get(Type::getVoidTy(Context), false))); 221 BasicBlock *BB = BasicBlock::Create(Context, "entry", F); 222 new UnreachableInst(Context, BB); 223 } 224 225 bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { 226 auto It = Functions.find(MF.getName()); 227 if (It == Functions.end()) 228 return error(Twine("no machine function information for function '") + 229 MF.getName() + "' in the MIR file"); 230 // TODO: Recreate the machine function. 231 const yaml::MachineFunction &YamlMF = *It->getValue(); 232 if (YamlMF.Alignment) 233 MF.setAlignment(YamlMF.Alignment); 234 MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); 235 MF.setHasInlineAsm(YamlMF.HasInlineAsm); 236 if (initializeRegisterInfo(MF.getRegInfo(), YamlMF)) 237 return true; 238 239 const auto &F = *MF.getFunction(); 240 DenseMap<unsigned, MachineBasicBlock *> MBBSlots; 241 for (const auto &YamlMBB : YamlMF.BasicBlocks) { 242 const BasicBlock *BB = nullptr; 243 if (!YamlMBB.Name.empty()) { 244 BB = dyn_cast_or_null<BasicBlock>( 245 F.getValueSymbolTable().lookup(YamlMBB.Name)); 246 if (!BB) 247 return error(Twine("basic block '") + YamlMBB.Name + 248 "' is not defined in the function '" + MF.getName() + "'"); 249 } 250 auto *MBB = MF.CreateMachineBasicBlock(BB); 251 MF.insert(MF.end(), MBB); 252 bool WasInserted = MBBSlots.insert(std::make_pair(YamlMBB.ID, MBB)).second; 253 if (!WasInserted) 254 return error(Twine("redefinition of machine basic block with id #") + 255 Twine(YamlMBB.ID)); 256 } 257 258 // Initialize the machine basic blocks after creating them all so that the 259 // machine instructions parser can resolve the MBB references. 260 unsigned I = 0; 261 for (const auto &YamlMBB : YamlMF.BasicBlocks) { 262 if (initializeMachineBasicBlock(MF, *MF.getBlockNumbered(I++), YamlMBB, 263 MBBSlots)) 264 return true; 265 } 266 return false; 267 } 268 269 bool MIRParserImpl::initializeMachineBasicBlock( 270 MachineFunction &MF, MachineBasicBlock &MBB, 271 const yaml::MachineBasicBlock &YamlMBB, 272 const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots) { 273 MBB.setAlignment(YamlMBB.Alignment); 274 if (YamlMBB.AddressTaken) 275 MBB.setHasAddressTaken(); 276 MBB.setIsLandingPad(YamlMBB.IsLandingPad); 277 SMDiagnostic Error; 278 // Parse the successors. 279 for (const auto &MBBSource : YamlMBB.Successors) { 280 MachineBasicBlock *SuccMBB = nullptr; 281 if (parseMBBReference(SuccMBB, SM, MF, MBBSource.Value, MBBSlots, IRSlots, 282 Error)) 283 return error(Error, MBBSource.SourceRange); 284 // TODO: Report an error when adding the same successor more than once. 285 MBB.addSuccessor(SuccMBB); 286 } 287 // Parse the instructions. 288 for (const auto &MISource : YamlMBB.Instructions) { 289 MachineInstr *MI = nullptr; 290 if (parseMachineInstr(MI, SM, MF, MISource.Value, MBBSlots, IRSlots, Error)) 291 return error(Error, MISource.SourceRange); 292 MBB.insert(MBB.end(), MI); 293 } 294 return false; 295 } 296 297 bool MIRParserImpl::initializeRegisterInfo( 298 MachineRegisterInfo &RegInfo, const yaml::MachineFunction &YamlMF) { 299 assert(RegInfo.isSSA()); 300 if (!YamlMF.IsSSA) 301 RegInfo.leaveSSA(); 302 assert(RegInfo.tracksLiveness()); 303 if (!YamlMF.TracksRegLiveness) 304 RegInfo.invalidateLiveness(); 305 RegInfo.enableSubRegLiveness(YamlMF.TracksSubRegLiveness); 306 return false; 307 } 308 309 SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error, 310 SMRange SourceRange) { 311 assert(SourceRange.isValid() && "Invalid source range"); 312 SMLoc Loc = SourceRange.Start; 313 bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() && 314 *Loc.getPointer() == '\''; 315 // Translate the location of the error from the location in the MI string to 316 // the corresponding location in the MIR file. 317 Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() + 318 (HasQuote ? 1 : 0)); 319 320 // TODO: Translate any source ranges as well. 321 return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), None, 322 Error.getFixIts()); 323 } 324 325 SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error, 326 SMRange SourceRange) { 327 assert(SourceRange.isValid()); 328 329 // Translate the location of the error from the location in the llvm IR string 330 // to the corresponding location in the MIR file. 331 auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start); 332 unsigned Line = LineAndColumn.first + Error.getLineNo() - 1; 333 unsigned Column = Error.getColumnNo(); 334 StringRef LineStr = Error.getLineContents(); 335 SMLoc Loc = Error.getLoc(); 336 337 // Get the full line and adjust the column number by taking the indentation of 338 // LLVM IR into account. 339 for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E; 340 L != E; ++L) { 341 if (L.line_number() == Line) { 342 LineStr = *L; 343 Loc = SMLoc::getFromPointer(LineStr.data()); 344 auto Indent = LineStr.find(Error.getLineContents()); 345 if (Indent != StringRef::npos) 346 Column += Indent; 347 break; 348 } 349 } 350 351 return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(), 352 Error.getMessage(), LineStr, Error.getRanges(), 353 Error.getFixIts()); 354 } 355 356 MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl) 357 : Impl(std::move(Impl)) {} 358 359 MIRParser::~MIRParser() {} 360 361 std::unique_ptr<Module> MIRParser::parseLLVMModule() { return Impl->parse(); } 362 363 bool MIRParser::initializeMachineFunction(MachineFunction &MF) { 364 return Impl->initializeMachineFunction(MF); 365 } 366 367 std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(StringRef Filename, 368 SMDiagnostic &Error, 369 LLVMContext &Context) { 370 auto FileOrErr = MemoryBuffer::getFile(Filename); 371 if (std::error_code EC = FileOrErr.getError()) { 372 Error = SMDiagnostic(Filename, SourceMgr::DK_Error, 373 "Could not open input file: " + EC.message()); 374 return nullptr; 375 } 376 return createMIRParser(std::move(FileOrErr.get()), Context); 377 } 378 379 std::unique_ptr<MIRParser> 380 llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents, 381 LLVMContext &Context) { 382 auto Filename = Contents->getBufferIdentifier(); 383 return llvm::make_unique<MIRParser>( 384 llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context)); 385 } 386