From b6a4640163855cc44a5af5f8a62face3a4cead3c Mon Sep 17 00:00:00 2001 From: Stepan Dyatkovskiy Date: Tue, 8 May 2012 06:36:08 +0000 Subject: 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. llvm-svn: 156374 --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 87 ++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 26 deletions(-) (limited to 'llvm/lib/Bitcode/Writer/BitcodeWriter.cpp') diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index b25d2e9..f8065e3 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -62,7 +62,10 @@ enum { FUNCTION_INST_CAST_ABBREV, FUNCTION_INST_RET_VOID_ABBREV, FUNCTION_INST_RET_VAL_ABBREV, - FUNCTION_INST_UNREACHABLE_ABBREV + FUNCTION_INST_UNREACHABLE_ABBREV, + + // SwitchInst Magic + SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex }; static unsigned GetEncodedCastOpcode(unsigned Opcode) { @@ -719,6 +722,42 @@ static void WriteModuleMetadataStore(const Module *M, BitstreamWriter &Stream) { Stream.ExitBlock(); } +template +static void EmitAPInt(SmallVectorImpl &Vals, + unsigned &Code, unsigned &AbbrevToUse, const APInt &Val, + bool EmitSizeForWideNumbers = false + ) { + if (Val.getBitWidth() <= 64) { + uint64_t V = Val.getSExtValue(); + if ((int64_t)V >= 0) + Vals.push_back(V << 1); + else + Vals.push_back((-V << 1) | 1); + Code = bitc::CST_CODE_INTEGER; + AbbrevToUse = CONSTANTS_INTEGER_ABBREV; + } else { + // Wide integers, > 64 bits in size. + // We have an arbitrary precision integer value to write whose + // bit width is > 64. However, in canonical unsigned integer + // format it is likely that the high bits are going to be zero. + // So, we only write the number of active words. + unsigned NWords = Val.getActiveWords(); + + if (EmitSizeForWideNumbers) + Vals.push_back(NWords); + + const uint64_t *RawWords = Val.getRawData(); + for (unsigned i = 0; i != NWords; ++i) { + int64_t V = RawWords[i]; + if (V >= 0) + Vals.push_back(V << 1); + else + Vals.push_back((-V << 1) | 1); + } + Code = bitc::CST_CODE_WIDE_INTEGER; + } +} + static void WriteConstants(unsigned FirstVal, unsigned LastVal, const ValueEnumerator &VE, BitstreamWriter &Stream, bool isGlobal) { @@ -801,30 +840,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, } else if (isa(C)) { Code = bitc::CST_CODE_UNDEF; } else if (const ConstantInt *IV = dyn_cast(C)) { - if (IV->getBitWidth() <= 64) { - uint64_t V = IV->getSExtValue(); - if ((int64_t)V >= 0) - Record.push_back(V << 1); - else - Record.push_back((-V << 1) | 1); - Code = bitc::CST_CODE_INTEGER; - AbbrevToUse = CONSTANTS_INTEGER_ABBREV; - } else { // Wide integers, > 64 bits in size. - // We have an arbitrary precision integer value to write whose - // bit width is > 64. However, in canonical unsigned integer - // format it is likely that the high bits are going to be zero. - // So, we only write the number of active words. - unsigned NWords = IV->getValue().getActiveWords(); - const uint64_t *RawWords = IV->getValue().getRawData(); - for (unsigned i = 0; i != NWords; ++i) { - int64_t V = RawWords[i]; - if (V >= 0) - Record.push_back(V << 1); - else - Record.push_back((-V << 1) | 1); - } - Code = bitc::CST_CODE_WIDE_INTEGER; - } + EmitAPInt(Record, Code, AbbrevToUse, IV->getValue()); } else if (const ConstantFP *CFP = dyn_cast(C)) { Code = bitc::CST_CODE_FLOAT; Type *Ty = CFP->getType(); @@ -1139,12 +1155,31 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, { Code = bitc::FUNC_CODE_INST_SWITCH; SwitchInst &SI = cast(I); + + uint32_t SwitchRecordHeader = SI.Hash() | (SWITCH_INST_MAGIC << 16); + Vals.push_back(SwitchRecordHeader); + Vals.push_back(VE.getTypeID(SI.getCondition()->getType())); Vals.push_back(VE.getValueID(SI.getCondition())); Vals.push_back(VE.getValueID(SI.getDefaultDest())); + Vals.push_back(SI.getNumCases()); for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) { - Vals.push_back(VE.getValueID(i.getCaseValue())); + ConstantRangesSet CRS = i.getCaseValueEx(); + Vals.push_back(CRS.getNumItems()); + for (unsigned ri = 0, rn = CRS.getNumItems(); ri != rn; ++ri) { + ConstantRangesSet::Range r = CRS.getItem(ri); + + Vals.push_back(CRS.isSingleNumber(ri)); + + const APInt &Low = r.Low->getValue(); + const APInt &High = r.High->getValue(); + unsigned Code, Abbrev; // will unused. + + EmitAPInt(Vals, Code, Abbrev, Low, true); + if (r.Low != r.High) + EmitAPInt(Vals, Code, Abbrev, High, true); + } Vals.push_back(VE.getValueID(i.getCaseSuccessor())); } } -- cgit v1.1