diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-09-24 23:34:52 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-09-24 23:34:52 +0000 |
commit | b513a9fa4f1b68d10f658848e5bff39dab4bb8bd (patch) | |
tree | 3433cf0682329f82b9839ceeff71586505b63ab8 /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | f021808d606eb35434fe54ae3ad2e1992af527b3 (diff) | |
download | bcm5719-llvm-b513a9fa4f1b68d10f658848e5bff39dab4bb8bd.tar.gz bcm5719-llvm-b513a9fa4f1b68d10f658848e5bff39dab4bb8bd.zip |
[Bitcode][Asm] Teach LLVM to read and write operand bundles.
Summary:
This also adds the first set of tests for operand bundles.
The optimizer has not been audited to ensure that it does the right
thing with operand bundles.
Depends on D12456.
Reviewers: reames, chandlerc, majnemer, dexonsmith, kmod, JosephTremoulet, rnk, bogner
Subscribers: maksfb, llvm-commits
Differential Revision: http://reviews.llvm.org/D12457
llvm-svn: 248551
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 82 |
1 files changed, 80 insertions, 2 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index f38f26cd636..165ab6e20c5 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -226,6 +226,8 @@ class BitcodeReader : public GVMaterializer { bool StripDebugInfo = false; + std::vector<std::string> BundleTags; + public: std::error_code error(BitcodeError E, const Twine &Message); std::error_code error(BitcodeError E); @@ -370,6 +372,7 @@ private: std::error_code parseAttributeGroupBlock(); std::error_code parseTypeTable(); std::error_code parseTypeTableBody(); + std::error_code parseOperandBundleTags(); ErrorOr<Value *> recordValue(SmallVectorImpl<uint64_t> &Record, unsigned NameIndex, Triple &TT); @@ -1586,6 +1589,42 @@ std::error_code BitcodeReader::parseTypeTableBody() { } } +std::error_code BitcodeReader::parseOperandBundleTags() { + if (Stream.EnterSubBlock(bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID)) + return error("Invalid record"); + + if (!BundleTags.empty()) + return error("Invalid multiple blocks"); + + SmallVector<uint64_t, 64> Record; + + while (1) { + BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + + switch (Entry.Kind) { + case BitstreamEntry::SubBlock: // Handled for us already. + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return std::error_code(); + case BitstreamEntry::Record: + // The interesting case. + break; + } + + // Tags are implicitly mapped to integers by their order. + + if (Stream.readRecord(Entry.ID, Record) != bitc::OPERAND_BUNDLE_TAG) + return error("Invalid record"); + + // OPERAND_BUNDLE_TAG: [strchr x N] + BundleTags.emplace_back(); + if (convertToString(Record, 0, BundleTags.back())) + return error("Invalid record"); + Record.clear(); + } +} + /// Associate a value with its name from the given index in the provided record. ErrorOr<Value *> BitcodeReader::recordValue(SmallVectorImpl<uint64_t> &Record, unsigned NameIndex, Triple &TT) { @@ -3019,6 +3058,10 @@ std::error_code BitcodeReader::parseModule(bool Resume, if (std::error_code EC = parseUseLists()) return EC; break; + case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: + if (std::error_code EC = parseOperandBundleTags()) + return EC; + break; } continue; @@ -3556,6 +3599,8 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { return nullptr; }; + std::vector<OperandBundleDef> OperandBundles; + // Read all the records. SmallVector<uint64_t, 64> Record; while (1) { @@ -4325,7 +4370,8 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { } } - I = InvokeInst::Create(Callee, NormalBB, UnwindBB, Ops); + I = InvokeInst::Create(Callee, NormalBB, UnwindBB, Ops, OperandBundles); + OperandBundles.clear(); InstructionList.push_back(I); cast<InvokeInst>(I) ->setCallingConv(static_cast<CallingConv::ID>(~(1U << 13) & CCInfo)); @@ -4708,7 +4754,8 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { } } - I = CallInst::Create(FTy, Callee, Args); + I = CallInst::Create(FTy, Callee, Args, OperandBundles); + OperandBundles.clear(); InstructionList.push_back(I); cast<CallInst>(I)->setCallingConv( static_cast<CallingConv::ID>((~(1U << 14) & CCInfo) >> 1)); @@ -4733,6 +4780,30 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { InstructionList.push_back(I); break; } + + case bitc::FUNC_CODE_OPERAND_BUNDLE: { + // A call or an invoke can be optionally prefixed with some variable + // number of operand bundle blocks. These blocks are read into + // OperandBundles and consumed at the next call or invoke instruction. + + if (Record.size() < 1 || Record[0] >= BundleTags.size()) + return error("Invalid record"); + + OperandBundles.emplace_back(); + OperandBundles.back().Tag = BundleTags[Record[0]]; + + std::vector<Value *> &Inputs = OperandBundles.back().Inputs; + + unsigned OpNum = 1; + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return error("Invalid record"); + Inputs.push_back(Op); + } + + continue; + } } // Add instruction to end of current BB. If there is no current BB, reject @@ -4741,6 +4812,10 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { delete I; return error("Invalid instruction with no BB"); } + if (!OperandBundles.empty()) { + delete I; + return error("Operand bundles found with no consumer"); + } CurBB->getInstList().push_back(I); // If this was a terminator instruction, move to the next block. @@ -4757,6 +4832,9 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { OutOfRecordLoop: + if (!OperandBundles.empty()) + return error("Operand bundles found with no consumer"); + // Check the function list for unresolved values. if (Argument *A = dyn_cast<Argument>(ValueList.back())) { if (!A->getParent()) { |