aboutsummaryrefslogtreecommitdiff
path: root/lib/Bitcode/Writer/BitcodeWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Bitcode/Writer/BitcodeWriter.cpp')
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp104
1 files changed, 74 insertions, 30 deletions
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index b25d2e96d5..ae250ebe16 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/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,41 @@ static void WriteModuleMetadataStore(const Module *M, BitstreamWriter &Stream) {
Stream.ExitBlock();
}
+static void EmitAPInt(SmallVectorImpl<uint64_t> &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 +839,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
} else if (isa<UndefValue>(C)) {
Code = bitc::CST_CODE_UNDEF;
} else if (const ConstantInt *IV = dyn_cast<ConstantInt>(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<ConstantFP>(C)) {
Code = bitc::CST_CODE_FLOAT;
Type *Ty = CFP->getType();
@@ -1137,16 +1152,45 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
case Instruction::Switch:
{
+ // Redefine Vals, since here we need to use 64 bit values
+ // explicitly to store large APInt numbers.
+ SmallVector<uint64_t, 128> Vals64;
+
Code = bitc::FUNC_CODE_INST_SWITCH;
SwitchInst &SI = cast<SwitchInst>(I);
- Vals.push_back(VE.getTypeID(SI.getCondition()->getType()));
- Vals.push_back(VE.getValueID(SI.getCondition()));
- Vals.push_back(VE.getValueID(SI.getDefaultDest()));
+
+ uint32_t SwitchRecordHeader = SI.Hash() | (SWITCH_INST_MAGIC << 16);
+ Vals64.push_back(SwitchRecordHeader);
+
+ Vals64.push_back(VE.getTypeID(SI.getCondition()->getType()));
+ Vals64.push_back(VE.getValueID(SI.getCondition()));
+ Vals64.push_back(VE.getValueID(SI.getDefaultDest()));
+ Vals64.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()));
- Vals.push_back(VE.getValueID(i.getCaseSuccessor()));
+ ConstantRangesSet CRS = i.getCaseValueEx();
+ Vals64.push_back(CRS.getNumItems());
+ for (unsigned ri = 0, rn = CRS.getNumItems(); ri != rn; ++ri) {
+ ConstantRangesSet::Range r = CRS.getItem(ri);
+
+ Vals64.push_back(CRS.isSingleNumber(ri));
+
+ const APInt &Low = r.Low->getValue();
+ const APInt &High = r.High->getValue();
+ unsigned Code, Abbrev; // will unused.
+
+ EmitAPInt(Vals64, Code, Abbrev, Low, true);
+ if (r.Low != r.High)
+ EmitAPInt(Vals64, Code, Abbrev, High, true);
+ }
+ Vals64.push_back(VE.getValueID(i.getCaseSuccessor()));
}
+
+ Stream.EmitRecord(Code, Vals64, AbbrevToUse);
+
+ // Also do expected action - clear external Vals collection:
+ Vals.clear();
+ return;
}
break;
case Instruction::IndirectBr: