diff options
| author | Peng Guo <peng_guo@apple.com> | 2020-01-08 17:13:24 -0800 |
|---|---|---|
| committer | Daniel Sanders <daniel_l_sanders@apple.com> | 2020-01-08 18:34:21 -0800 |
| commit | be841f89d0014b1e0246a4feae941b2f74abd908 (patch) | |
| tree | c4121d8cfb9ccf6ac8469192ffb5534f3d32e450 /llvm/lib/CodeGen/MIRParser/MIParser.cpp | |
| parent | a63af915288ad9d1049d486833fcd085b620dc6d (diff) | |
| download | bcm5719-llvm-be841f89d0014b1e0246a4feae941b2f74abd908.tar.gz bcm5719-llvm-be841f89d0014b1e0246a4feae941b2f74abd908.zip | |
[MIR] Target specific MIR formating and parsing
Summary:
Added MIRFormatter for target specific MIR formating and parsing with
immediate and custom pseudo source values. Target machine can subclass
MIRFormatter and implement custom logic for printing and parsing
immediate and custom pseudo source values for better readability.
* Target specific immediate mnemonic need to start with "." follows by
identifier string. When MIR parser sees immediate it will call target
specific parsing function.
* Custom pseudo source value need to start with custom follows by
double-quoted string. MIR parser will pass the quoted string to target
specific PSV parsing function.
* MIRFormatter have 2 helper functions to facilitate LLVM value printing
and parsing for custom PSV if they refers LLVM values.
Reviewers: dsanders, arsenm
Reviewed By: dsanders
Subscribers: wdng, jvesely, nhaehnle, hiraditya, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69836
Diffstat (limited to 'llvm/lib/CodeGen/MIRParser/MIParser.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/MIRParser/MIParser.cpp | 265 |
1 files changed, 192 insertions, 73 deletions
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 525c70016a0..0f2648e2bfa 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); @@ -473,6 +506,9 @@ public: 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. /// @@ -551,6 +587,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: @@ -912,7 +951,7 @@ bool MIParser::parse(MachineInstr *&MI) { 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(); @@ -1493,17 +1532,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; @@ -1636,27 +1719,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; +} + +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)); @@ -1736,23 +1844,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; } @@ -1762,6 +1872,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)) @@ -2410,7 +2528,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: @@ -2499,6 +2618,12 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest, return parseCustomRegisterMaskOperand(Dest); } else return parseTypedImmediateOperand(Dest); + case MIToken::dot: { + if (const auto *Formatter = MF.getTarget().getMIRFormatter()) { + return parseTargetImmMnemonic(OpCode, OpIdx, Dest, *Formatter); + } + LLVM_FALLTHROUGH; + } default: // FIXME: Parse the MCSymbol machine operand. return error("expected a machine operand"); @@ -2507,7 +2632,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)) { @@ -2539,7 +2665,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; @@ -2600,30 +2726,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; @@ -2632,10 +2759,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) @@ -2656,20 +2790,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) { @@ -2756,6 +2877,19 @@ bool MIParser::parseMemoryPseudoSourceValue(const PseudoSourceValue *&PSV) { "expected a global value or an external symbol after 'call-entry'"); } break; + case MIToken::kw_custom: { + lex(); + if (const auto *Formatter = MF.getTarget().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"); } @@ -2767,7 +2901,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; @@ -3018,35 +3152,8 @@ 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; + return PFS.getIRValue(Slot); } MCSymbol *MIParser::getOrCreateMCSymbol(StringRef Name) { @@ -3111,3 +3218,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); +} |

