From 1cce5bf8ef9ee3dc157ae5d8778f84a7a0d1d8b9 Mon Sep 17 00:00:00 2001 From: Stepan Dyatkovskiy Date: Sat, 12 May 2012 10:48:17 +0000 Subject: Recommited r156374 with critical fixes in BitcodeReader/Writer: Ordinary patch for PR1255. Added new case-ranges orientated methods for adding/removing cases in SwitchInst. After this patch cases will internally representated as ConstantArray-s instead of ConstantInt, externally cases wrapped within the ConstantRangesSet object. Old methods of SwitchInst are also works well, but marked as deprecated. So on this stage we have no side effects except that I added support for case ranges in BitcodeReader/Writer, of course test for Bitcode is also added. Old "switch" format is also supported. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156704 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Reader/BitcodeReader.cpp | 82 +++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 7 deletions(-) (limited to 'lib/Bitcode/Reader/BitcodeReader.cpp') diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 040f3438fe..49b6e4f42a 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -28,6 +28,10 @@ #include "llvm/OperandTraits.h" using namespace llvm; +enum { + SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex +}; + void BitcodeReader::materializeForwardReferencedFunctions() { while (!BlockAddrFwdRefs.empty()) { Function *F = BlockAddrFwdRefs.begin()->first; @@ -927,6 +931,16 @@ bool BitcodeReader::ResolveGlobalAndAliasInits() { return false; } +APInt ReadWideAPInt(const uint64_t *Vals, unsigned ActiveWords, + unsigned TypeBits) { + SmallVector Words; + Words.resize(ActiveWords); + for (unsigned i = 0; i != ActiveWords; ++i) + Words[i] = DecodeSignRotatedValue(Vals[i]); + + return APInt(TypeBits, Words); +} + bool BitcodeReader::ParseConstants() { if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID)) return Error("Malformed block record"); @@ -983,13 +997,11 @@ bool BitcodeReader::ParseConstants() { return Error("Invalid WIDE_INTEGER record"); unsigned NumWords = Record.size(); - SmallVector Words; - Words.resize(NumWords); - for (unsigned i = 0; i != NumWords; ++i) - Words[i] = DecodeSignRotatedValue(Record[i]); - V = ConstantInt::get(Context, - APInt(cast(CurTy)->getBitWidth(), - Words)); + + APInt VInt = ReadWideAPInt(&Record[0], NumWords, + cast(CurTy)->getBitWidth()); + V = ConstantInt::get(Context, VInt); + break; } case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval] @@ -2221,6 +2233,62 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { break; } case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...] + // Check magic + if ((Record[0] >> 16) == SWITCH_INST_MAGIC) { + // New SwitchInst format with case ranges. + + Type *OpTy = getTypeByID(Record[1]); + unsigned ValueBitWidth = cast(OpTy)->getBitWidth(); + + Value *Cond = getFnValueByID(Record[2], OpTy); + BasicBlock *Default = getBasicBlock(Record[3]); + if (OpTy == 0 || Cond == 0 || Default == 0) + return Error("Invalid SWITCH record"); + + unsigned NumCases = Record[4]; + + SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases); + InstructionList.push_back(SI); + + unsigned CurIdx = 5; + for (unsigned i = 0; i != NumCases; ++i) { + CRSBuilder CaseBuilder; + unsigned NumItems = Record[CurIdx++]; + for (unsigned ci = 0; ci != NumItems; ++ci) { + bool isSingleNumber = Record[CurIdx++]; + + APInt Low; + unsigned ActiveWords = 1; + if (ValueBitWidth > 64) + ActiveWords = Record[CurIdx++]; + Low = ReadWideAPInt(&Record[CurIdx], ActiveWords, ValueBitWidth); + CurIdx += ActiveWords; + + if (!isSingleNumber) { + ActiveWords = 1; + if (ValueBitWidth > 64) + ActiveWords = Record[CurIdx++]; + APInt High = + ReadWideAPInt(&Record[CurIdx], ActiveWords, ValueBitWidth); + CaseBuilder.add(cast(ConstantInt::get(OpTy, Low)), + cast(ConstantInt::get(OpTy, High))); + CurIdx += ActiveWords; + } else + CaseBuilder.add(cast(ConstantInt::get(OpTy, Low))); + } + BasicBlock *DestBB = getBasicBlock(Record[CurIdx++]); + ConstantRangesSet Case = CaseBuilder.getCase(); + SI->addCase(Case, DestBB); + } + uint16_t Hash = SI->Hash(); + if (Hash != (Record[0] & 0xFFFF)) + return Error("Invalid SWITCH record"); + I = SI; + break; + } + + // Old SwitchInst format without case ranges. + if (Record.size() < 3 || (Record.size() & 1) == 0) return Error("Invalid SWITCH record"); Type *OpTy = getTypeByID(Record[0]); -- cgit v1.2.3-18-g5258