diff options
Diffstat (limited to 'llvm/lib/CodeGen/MIRParser/MIParser.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MIRParser/MIParser.cpp | 326 |
1 files changed, 225 insertions, 101 deletions
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 6498acc9fa51..076ca943788b 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -28,6 +28,7 @@ #include "llvm/AsmParser/SlotMapping.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#include "llvm/CodeGen/MIRFormatter.h" #include "llvm/CodeGen/MIRPrinter.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -343,6 +344,37 @@ VRegInfo &PerFunctionMIParsingState::getVRegInfoNamed(StringRef RegName) { return *I.first->second; } +static void mapValueToSlot(const Value *V, ModuleSlotTracker &MST, + DenseMap<unsigned, const Value *> &Slots2Values) { + int Slot = MST.getLocalSlot(V); + if (Slot == -1) + return; + Slots2Values.insert(std::make_pair(unsigned(Slot), V)); +} + +/// Creates the mapping from slot numbers to function's unnamed IR values. +static void initSlots2Values(const Function &F, + DenseMap<unsigned, const Value *> &Slots2Values) { + ModuleSlotTracker MST(F.getParent(), /*ShouldInitializeAllMetadata=*/false); + MST.incorporateFunction(F); + for (const auto &Arg : F.args()) + mapValueToSlot(&Arg, MST, Slots2Values); + for (const auto &BB : F) { + mapValueToSlot(&BB, MST, Slots2Values); + for (const auto &I : BB) + mapValueToSlot(&I, MST, Slots2Values); + } +} + +const Value* PerFunctionMIParsingState::getIRValue(unsigned Slot) { + if (Slots2Values.empty()) + initSlots2Values(MF.getFunction(), Slots2Values); + auto ValueInfo = Slots2Values.find(Slot); + if (ValueInfo == Slots2Values.end()) + return nullptr; + return ValueInfo->second; +} + namespace { /// A wrapper struct around the 'MachineOperand' struct that includes a source @@ -370,8 +402,6 @@ class MIParser { PerFunctionMIParsingState &PFS; /// Maps from slot numbers to function's unnamed basic blocks. DenseMap<unsigned, const BasicBlock *> Slots2BasicBlocks; - /// Maps from slot numbers to function's unnamed values. - DenseMap<unsigned, const Value *> Slots2Values; public: MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error, @@ -455,9 +485,12 @@ public: bool parseTargetIndexOperand(MachineOperand &Dest); bool parseCustomRegisterMaskOperand(MachineOperand &Dest); bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest); - bool parseMachineOperand(MachineOperand &Dest, + bool parseMachineOperand(const unsigned OpCode, const unsigned OpIdx, + MachineOperand &Dest, Optional<unsigned> &TiedDefIdx); - bool parseMachineOperandAndTargetFlags(MachineOperand &Dest, + bool parseMachineOperandAndTargetFlags(const unsigned OpCode, + const unsigned OpIdx, + MachineOperand &Dest, Optional<unsigned> &TiedDefIdx); bool parseOffset(int64_t &Offset); bool parseAlignment(unsigned &Alignment); @@ -471,6 +504,10 @@ public: bool parseOptionalAtomicOrdering(AtomicOrdering &Order); bool parseMachineMemoryOperand(MachineMemOperand *&Dest); bool parsePreOrPostInstrSymbol(MCSymbol *&Symbol); + bool parseHeapAllocMarker(MDNode *&Node); + + bool parseTargetImmMnemonic(const unsigned OpCode, const unsigned OpIdx, + MachineOperand &Dest, const MIRFormatter &MF); private: /// Convert the integer literal in the current token into an unsigned integer. @@ -508,8 +545,6 @@ private: const BasicBlock *getIRBlock(unsigned Slot); const BasicBlock *getIRBlock(unsigned Slot, const Function &F); - const Value *getIRValue(unsigned Slot); - /// Get or create an MCSymbol for a given name. MCSymbol *getOrCreateMCSymbol(StringRef Name); @@ -550,6 +585,9 @@ bool MIParser::error(StringRef::iterator Loc, const Twine &Msg) { return true; } +typedef function_ref<bool(StringRef::iterator Loc, const Twine &)> + ErrorCallbackType; + static const char *toString(MIToken::TokenKind TokenKind) { switch (TokenKind) { case MIToken::comma: @@ -906,11 +944,12 @@ bool MIParser::parse(MachineInstr *&MI) { // Parse the remaining machine operands. while (!Token.isNewlineOrEOF() && Token.isNot(MIToken::kw_pre_instr_symbol) && Token.isNot(MIToken::kw_post_instr_symbol) && + Token.isNot(MIToken::kw_heap_alloc_marker) && Token.isNot(MIToken::kw_debug_location) && Token.isNot(MIToken::coloncolon) && Token.isNot(MIToken::lbrace)) { auto Loc = Token.location(); Optional<unsigned> TiedDefIdx; - if (parseMachineOperandAndTargetFlags(MO, TiedDefIdx)) + if (parseMachineOperandAndTargetFlags(OpCode, Operands.size(), MO, TiedDefIdx)) return true; if (OpCode == TargetOpcode::DBG_VALUE && MO.isReg()) MO.setIsDebug(); @@ -932,6 +971,10 @@ bool MIParser::parse(MachineInstr *&MI) { if (Token.is(MIToken::kw_post_instr_symbol)) if (parsePreOrPostInstrSymbol(PostInstrSymbol)) return true; + MDNode *HeapAllocMarker = nullptr; + if (Token.is(MIToken::kw_heap_alloc_marker)) + if (parseHeapAllocMarker(HeapAllocMarker)) + return true; DebugLoc DebugLocation; if (Token.is(MIToken::kw_debug_location)) { @@ -985,6 +1028,8 @@ bool MIParser::parse(MachineInstr *&MI) { MI->setPreInstrSymbol(MF, PreInstrSymbol); if (PostInstrSymbol) MI->setPostInstrSymbol(MF, PostInstrSymbol); + if (HeapAllocMarker) + MI->setHeapAllocMarker(MF, HeapAllocMarker); if (!MemOperands.empty()) MI->setMemRefs(MF, MemOperands); return false; @@ -1138,7 +1183,7 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { Token.is(MIToken::kw_nuw) || Token.is(MIToken::kw_nsw) || Token.is(MIToken::kw_exact) || - Token.is(MIToken::kw_fpexcept)) { + Token.is(MIToken::kw_nofpexcept)) { // Mine frame and fast math flags if (Token.is(MIToken::kw_frame_setup)) Flags |= MachineInstr::FrameSetup; @@ -1164,8 +1209,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { Flags |= MachineInstr::NoSWrap; if (Token.is(MIToken::kw_exact)) Flags |= MachineInstr::IsExact; - if (Token.is(MIToken::kw_fpexcept)) - Flags |= MachineInstr::FPExcept; + if (Token.is(MIToken::kw_nofpexcept)) + Flags |= MachineInstr::NoFPExcept; lex(); } @@ -1485,17 +1530,61 @@ bool MIParser::parseImmediateOperand(MachineOperand &Dest) { return false; } -bool MIParser::parseIRConstant(StringRef::iterator Loc, StringRef StringValue, - const Constant *&C) { +bool MIParser::parseTargetImmMnemonic(const unsigned OpCode, + const unsigned OpIdx, + MachineOperand &Dest, + const MIRFormatter &MF) { + assert(Token.is(MIToken::dot)); + auto Loc = Token.location(); // record start position + size_t Len = 1; // for "." + lex(); + + // Handle the case that mnemonic starts with number. + if (Token.is(MIToken::IntegerLiteral)) { + Len += Token.range().size(); + lex(); + } + + StringRef Src; + if (Token.is(MIToken::comma)) + Src = StringRef(Loc, Len); + else { + assert(Token.is(MIToken::Identifier)); + Src = StringRef(Loc, Len + Token.stringValue().size()); + } + int64_t Val; + if (MF.parseImmMnemonic(OpCode, OpIdx, Src, Val, + [this](StringRef::iterator Loc, const Twine &Msg) + -> bool { return error(Loc, Msg); })) + return true; + + Dest = MachineOperand::CreateImm(Val); + if (!Token.is(MIToken::comma)) + lex(); + return false; +} + +static bool parseIRConstant(StringRef::iterator Loc, StringRef StringValue, + PerFunctionMIParsingState &PFS, const Constant *&C, + ErrorCallbackType ErrCB) { auto Source = StringValue.str(); // The source has to be null terminated. SMDiagnostic Err; - C = parseConstantValue(Source, Err, *MF.getFunction().getParent(), + C = parseConstantValue(Source, Err, *PFS.MF.getFunction().getParent(), &PFS.IRSlots); if (!C) - return error(Loc + Err.getColumnNo(), Err.getMessage()); + return ErrCB(Loc + Err.getColumnNo(), Err.getMessage()); return false; } +bool MIParser::parseIRConstant(StringRef::iterator Loc, StringRef StringValue, + const Constant *&C) { + return ::parseIRConstant( + Loc, StringValue, PFS, C, + [this](StringRef::iterator Loc, const Twine &Msg) -> bool { + return error(Loc, Msg); + }); +} + bool MIParser::parseIRConstant(StringRef::iterator Loc, const Constant *&C) { if (parseIRConstant(Loc, StringRef(Loc, Token.range().end() - Loc), C)) return true; @@ -1628,27 +1717,52 @@ bool MIParser::parseFPImmediateOperand(MachineOperand &Dest) { return false; } -bool MIParser::getUnsigned(unsigned &Result) { +static bool getHexUint(const MIToken &Token, APInt &Result) { + assert(Token.is(MIToken::HexLiteral)); + StringRef S = Token.range(); + assert(S[0] == '0' && tolower(S[1]) == 'x'); + // This could be a floating point literal with a special prefix. + if (!isxdigit(S[2])) + return true; + StringRef V = S.substr(2); + APInt A(V.size()*4, V, 16); + + // If A is 0, then A.getActiveBits() is 0. This isn't a valid bitwidth. Make + // sure it isn't the case before constructing result. + unsigned NumBits = (A == 0) ? 32 : A.getActiveBits(); + Result = APInt(NumBits, ArrayRef<uint64_t>(A.getRawData(), A.getNumWords())); + return false; +} + +static bool getUnsigned(const MIToken &Token, unsigned &Result, + ErrorCallbackType ErrCB) { if (Token.hasIntegerValue()) { const uint64_t Limit = uint64_t(std::numeric_limits<unsigned>::max()) + 1; uint64_t Val64 = Token.integerValue().getLimitedValue(Limit); if (Val64 == Limit) - return error("expected 32-bit integer (too large)"); + return ErrCB(Token.location(), "expected 32-bit integer (too large)"); Result = Val64; return false; } if (Token.is(MIToken::HexLiteral)) { APInt A; - if (getHexUint(A)) + if (getHexUint(Token, A)) return true; if (A.getBitWidth() > 32) - return error("expected 32-bit integer (too large)"); + return ErrCB(Token.location(), "expected 32-bit integer (too large)"); Result = A.getZExtValue(); return false; } return true; } +bool MIParser::getUnsigned(unsigned &Result) { + return ::getUnsigned( + Token, Result, [this](StringRef::iterator Loc, const Twine &Msg) -> bool { + return error(Loc, Msg); + }); +} + bool MIParser::parseMBBReference(MachineBasicBlock *&MBB) { assert(Token.is(MIToken::MachineBasicBlock) || Token.is(MIToken::MachineBasicBlockLabel)); @@ -1728,23 +1842,25 @@ bool MIParser::parseFixedStackObjectOperand(MachineOperand &Dest) { return false; } -bool MIParser::parseGlobalValue(GlobalValue *&GV) { +static bool parseGlobalValue(const MIToken &Token, + PerFunctionMIParsingState &PFS, GlobalValue *&GV, + ErrorCallbackType ErrCB) { switch (Token.kind()) { case MIToken::NamedGlobalValue: { - const Module *M = MF.getFunction().getParent(); + const Module *M = PFS.MF.getFunction().getParent(); GV = M->getNamedValue(Token.stringValue()); if (!GV) - return error(Twine("use of undefined global value '") + Token.range() + - "'"); + return ErrCB(Token.location(), Twine("use of undefined global value '") + + Token.range() + "'"); break; } case MIToken::GlobalValue: { unsigned GVIdx; - if (getUnsigned(GVIdx)) + if (getUnsigned(Token, GVIdx, ErrCB)) return true; if (GVIdx >= PFS.IRSlots.GlobalValues.size()) - return error(Twine("use of undefined global value '@") + Twine(GVIdx) + - "'"); + return ErrCB(Token.location(), Twine("use of undefined global value '@") + + Twine(GVIdx) + "'"); GV = PFS.IRSlots.GlobalValues[GVIdx]; break; } @@ -1754,6 +1870,14 @@ bool MIParser::parseGlobalValue(GlobalValue *&GV) { return false; } +bool MIParser::parseGlobalValue(GlobalValue *&GV) { + return ::parseGlobalValue( + Token, PFS, GV, + [this](StringRef::iterator Loc, const Twine &Msg) -> bool { + return error(Loc, Msg); + }); +} + bool MIParser::parseGlobalAddressOperand(MachineOperand &Dest) { GlobalValue *GV = nullptr; if (parseGlobalValue(GV)) @@ -2295,23 +2419,13 @@ bool MIParser::parseShuffleMaskOperand(MachineOperand &Dest) { if (expectAndConsume(MIToken::lparen)) return error("expected syntax shufflemask(<integer or undef>, ...)"); - SmallVector<Constant *, 32> ShufMask; - LLVMContext &Ctx = MF.getFunction().getContext(); - Type *I32Ty = Type::getInt32Ty(Ctx); - - bool AllZero = true; - bool AllUndef = true; - + SmallVector<int, 32> ShufMask; do { if (Token.is(MIToken::kw_undef)) { - ShufMask.push_back(UndefValue::get(I32Ty)); - AllZero = false; + ShufMask.push_back(-1); } else if (Token.is(MIToken::IntegerLiteral)) { - AllUndef = false; const APSInt &Int = Token.integerValue(); - if (!Int.isNullValue()) - AllZero = false; - ShufMask.push_back(ConstantInt::get(I32Ty, Int.getExtValue())); + ShufMask.push_back(Int.getExtValue()); } else return error("expected integer constant"); @@ -2321,13 +2435,8 @@ bool MIParser::parseShuffleMaskOperand(MachineOperand &Dest) { if (expectAndConsume(MIToken::rparen)) return error("shufflemask should be terminated by ')'."); - if (AllZero || AllUndef) { - VectorType *VT = VectorType::get(I32Ty, ShufMask.size()); - Constant *C = AllZero ? Constant::getNullValue(VT) : UndefValue::get(VT); - Dest = MachineOperand::CreateShuffleMask(C); - } else - Dest = MachineOperand::CreateShuffleMask(ConstantVector::get(ShufMask)); - + ArrayRef<int> MaskAlloc = MF.allocateShuffleMask(ShufMask); + Dest = MachineOperand::CreateShuffleMask(MaskAlloc); return false; } @@ -2402,7 +2511,8 @@ bool MIParser::parseLiveoutRegisterMaskOperand(MachineOperand &Dest) { return false; } -bool MIParser::parseMachineOperand(MachineOperand &Dest, +bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx, + MachineOperand &Dest, Optional<unsigned> &TiedDefIdx) { switch (Token.kind()) { case MIToken::kw_implicit: @@ -2491,6 +2601,13 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest, return parseCustomRegisterMaskOperand(Dest); } else return parseTypedImmediateOperand(Dest); + case MIToken::dot: { + const auto *TII = MF.getSubtarget().getInstrInfo(); + if (const auto *Formatter = TII->getMIRFormatter()) { + return parseTargetImmMnemonic(OpCode, OpIdx, Dest, *Formatter); + } + LLVM_FALLTHROUGH; + } default: // FIXME: Parse the MCSymbol machine operand. return error("expected a machine operand"); @@ -2499,7 +2616,8 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest, } bool MIParser::parseMachineOperandAndTargetFlags( - MachineOperand &Dest, Optional<unsigned> &TiedDefIdx) { + const unsigned OpCode, const unsigned OpIdx, MachineOperand &Dest, + Optional<unsigned> &TiedDefIdx) { unsigned TF = 0; bool HasTargetFlags = false; if (Token.is(MIToken::kw_target_flags)) { @@ -2531,7 +2649,7 @@ bool MIParser::parseMachineOperandAndTargetFlags( return true; } auto Loc = Token.location(); - if (parseMachineOperand(Dest, TiedDefIdx)) + if (parseMachineOperand(OpCode, OpIdx, Dest, TiedDefIdx)) return true; if (!HasTargetFlags) return false; @@ -2592,30 +2710,31 @@ bool MIParser::parseOperandsOffset(MachineOperand &Op) { return false; } -bool MIParser::parseIRValue(const Value *&V) { +static bool parseIRValue(const MIToken &Token, PerFunctionMIParsingState &PFS, + const Value *&V, ErrorCallbackType ErrCB) { switch (Token.kind()) { case MIToken::NamedIRValue: { - V = MF.getFunction().getValueSymbolTable()->lookup(Token.stringValue()); + V = PFS.MF.getFunction().getValueSymbolTable()->lookup(Token.stringValue()); break; } case MIToken::IRValue: { unsigned SlotNumber = 0; - if (getUnsigned(SlotNumber)) + if (getUnsigned(Token, SlotNumber, ErrCB)) return true; - V = getIRValue(SlotNumber); + V = PFS.getIRValue(SlotNumber); break; } case MIToken::NamedGlobalValue: case MIToken::GlobalValue: { GlobalValue *GV = nullptr; - if (parseGlobalValue(GV)) + if (parseGlobalValue(Token, PFS, GV, ErrCB)) return true; V = GV; break; } case MIToken::QuotedIRValue: { const Constant *C = nullptr; - if (parseIRConstant(Token.location(), Token.stringValue(), C)) + if (parseIRConstant(Token.location(), Token.stringValue(), PFS, C, ErrCB)) return true; V = C; break; @@ -2624,10 +2743,17 @@ bool MIParser::parseIRValue(const Value *&V) { llvm_unreachable("The current token should be an IR block reference"); } if (!V) - return error(Twine("use of undefined IR value '") + Token.range() + "'"); + return ErrCB(Token.location(), Twine("use of undefined IR value '") + Token.range() + "'"); return false; } +bool MIParser::parseIRValue(const Value *&V) { + return ::parseIRValue( + Token, PFS, V, [this](StringRef::iterator Loc, const Twine &Msg) -> bool { + return error(Loc, Msg); + }); +} + bool MIParser::getUint64(uint64_t &Result) { if (Token.hasIntegerValue()) { if (Token.integerValue().getActiveBits() > 64) @@ -2648,20 +2774,7 @@ bool MIParser::getUint64(uint64_t &Result) { } bool MIParser::getHexUint(APInt &Result) { - assert(Token.is(MIToken::HexLiteral)); - StringRef S = Token.range(); - assert(S[0] == '0' && tolower(S[1]) == 'x'); - // This could be a floating point literal with a special prefix. - if (!isxdigit(S[2])) - return true; - StringRef V = S.substr(2); - APInt A(V.size()*4, V, 16); - - // If A is 0, then A.getActiveBits() is 0. This isn't a valid bitwidth. Make - // sure it isn't the case before constructing result. - unsigned NumBits = (A == 0) ? 32 : A.getActiveBits(); - Result = APInt(NumBits, ArrayRef<uint64_t>(A.getRawData(), A.getNumWords())); - return false; + return ::getHexUint(Token, Result); } bool MIParser::parseMemoryOperandFlag(MachineMemOperand::Flags &Flags) { @@ -2748,6 +2861,20 @@ bool MIParser::parseMemoryPseudoSourceValue(const PseudoSourceValue *&PSV) { "expected a global value or an external symbol after 'call-entry'"); } break; + case MIToken::kw_custom: { + lex(); + const auto *TII = MF.getSubtarget().getInstrInfo(); + if (const auto *Formatter = TII->getMIRFormatter()) { + if (Formatter->parseCustomPseudoSourceValue( + Token.stringValue(), MF, PFS, PSV, + [this](StringRef::iterator Loc, const Twine &Msg) -> bool { + return error(Loc, Msg); + })) + return true; + } else + return error("unable to parse target custom pseudo source value"); + break; + } default: llvm_unreachable("The current token should be pseudo source value"); } @@ -2759,7 +2886,7 @@ bool MIParser::parseMachinePointerInfo(MachinePointerInfo &Dest) { if (Token.is(MIToken::kw_constant_pool) || Token.is(MIToken::kw_stack) || Token.is(MIToken::kw_got) || Token.is(MIToken::kw_jump_table) || Token.is(MIToken::FixedStackObject) || Token.is(MIToken::StackObject) || - Token.is(MIToken::kw_call_entry)) { + Token.is(MIToken::kw_call_entry) || Token.is(MIToken::kw_custom)) { const PseudoSourceValue *PSV = nullptr; if (parseMemoryPseudoSourceValue(PSV)) return true; @@ -2956,6 +3083,22 @@ bool MIParser::parsePreOrPostInstrSymbol(MCSymbol *&Symbol) { return false; } +bool MIParser::parseHeapAllocMarker(MDNode *&Node) { + assert(Token.is(MIToken::kw_heap_alloc_marker) && + "Invalid token for a heap alloc marker!"); + lex(); + parseMDNode(Node); + if (!Node) + return error("expected a MDNode after 'heap-alloc-marker'"); + if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) || + Token.is(MIToken::lbrace)) + return false; + if (Token.isNot(MIToken::comma)) + return error("expected ',' before the next machine operand"); + lex(); + return false; +} + static void initSlots2BasicBlocks( const Function &F, DenseMap<unsigned, const BasicBlock *> &Slots2BasicBlocks) { @@ -2994,37 +3137,6 @@ const BasicBlock *MIParser::getIRBlock(unsigned Slot, const Function &F) { return getIRBlockFromSlot(Slot, CustomSlots2BasicBlocks); } -static void mapValueToSlot(const Value *V, ModuleSlotTracker &MST, - DenseMap<unsigned, const Value *> &Slots2Values) { - int Slot = MST.getLocalSlot(V); - if (Slot == -1) - return; - Slots2Values.insert(std::make_pair(unsigned(Slot), V)); -} - -/// Creates the mapping from slot numbers to function's unnamed IR values. -static void initSlots2Values(const Function &F, - DenseMap<unsigned, const Value *> &Slots2Values) { - ModuleSlotTracker MST(F.getParent(), /*ShouldInitializeAllMetadata=*/false); - MST.incorporateFunction(F); - for (const auto &Arg : F.args()) - mapValueToSlot(&Arg, MST, Slots2Values); - for (const auto &BB : F) { - mapValueToSlot(&BB, MST, Slots2Values); - for (const auto &I : BB) - mapValueToSlot(&I, MST, Slots2Values); - } -} - -const Value *MIParser::getIRValue(unsigned Slot) { - if (Slots2Values.empty()) - initSlots2Values(MF.getFunction(), Slots2Values); - auto ValueInfo = Slots2Values.find(Slot); - if (ValueInfo == Slots2Values.end()) - return nullptr; - return ValueInfo->second; -} - MCSymbol *MIParser::getOrCreateMCSymbol(StringRef Name) { // FIXME: Currently we can't recognize temporary or local symbols and call all // of the appropriate forms to create them. However, this handles basic cases @@ -3087,3 +3199,15 @@ bool llvm::parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src, SMDiagnostic &Error) { return MIParser(PFS, Error, Src).parseStandaloneMDNode(Node); } + +bool MIRFormatter::parseIRValue(StringRef Src, MachineFunction &MF, + PerFunctionMIParsingState &PFS, const Value *&V, + ErrorCallbackType ErrorCallback) { + MIToken Token; + Src = lexMIToken(Src, Token, [&](StringRef::iterator Loc, const Twine &Msg) { + ErrorCallback(Loc, Msg); + }); + V = nullptr; + + return ::parseIRValue(Token, PFS, V, ErrorCallback); +} |