OLD | NEW |
(Empty) | |
| 1 //===- NaClBitcodeMungeWriter.cpp - Write munged bitcode --------*- C++ -*-===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // Implements method NaClMungedBitcode.write(), which writes out a munged |
| 11 // list of bitcode records using a bitstream writer. |
| 12 |
| 13 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" |
| 14 |
| 15 #include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h" |
| 16 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| 17 |
| 18 using namespace llvm; |
| 19 |
| 20 namespace { |
| 21 |
| 22 // For debugging. When true, shows each PNaCl record that is |
| 23 // emitted to the bitcode file. |
| 24 static bool DebugEmitRecord = false; |
| 25 |
| 26 // State of bitcode writing. |
| 27 struct WriteState { |
| 28 // The block ID associated with the block being written. |
| 29 int WriteBlockID = -1; |
| 30 // The SetBID for the blockinfo block. |
| 31 int SetBID = -1; |
| 32 // The stack of maximum abbreviation indices allowed by block enter record. |
| 33 SmallVector<uint64_t, 3> AbbrevIndexLimitStack; |
| 34 // The set of write flags to use. |
| 35 const NaClMungedBitcode::WriteFlags &Flags; |
| 36 // The results of the attempted write. |
| 37 NaClMungedBitcode::WriteResults Results; |
| 38 |
| 39 WriteState(const NaClMungedBitcode::WriteFlags &Flags) : Flags(Flags) {} |
| 40 |
| 41 // Returns stream to print error message to. |
| 42 raw_ostream &Error() { |
| 43 ++Results.NumErrors; |
| 44 return Flags.getErrStream() << "Error (Block " << WriteBlockID << "): "; |
| 45 } |
| 46 |
| 47 // Returns stream to print error message to, assuming that |
| 48 // the error message can be repaired if Flags.TryToRecover is true. |
| 49 raw_ostream &RecoverableError() { |
| 50 if (Flags.getTryToRecover()) |
| 51 ++Results.NumRepairs; |
| 52 return Error(); |
| 53 } |
| 54 |
| 55 // Converts the abbreviation record to the corresponding abbreviation. |
| 56 // Returns nullptr if unable to build abbreviation. |
| 57 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); |
| 58 |
| 59 // Emits the given record to the bitcode file. Returns true if |
| 60 // successful. |
| 61 bool emitRecord(NaClBitstreamWriter &Writer, |
| 62 const NaClBitcodeAbbrevRecord &Record); |
| 63 |
| 64 // Adds any missing end blocks to written bitcode. |
| 65 void writeMissingEndBlocks(NaClBitstreamWriter &Writer) { |
| 66 while (!AbbrevIndexLimitStack.empty()) { |
| 67 Writer.ExitBlock(); |
| 68 AbbrevIndexLimitStack.pop_back(); |
| 69 } |
| 70 } |
| 71 }; |
| 72 |
| 73 bool WriteState::emitRecord(NaClBitstreamWriter &Writer, |
| 74 const NaClBitcodeAbbrevRecord &Record) { |
| 75 size_t NumValues = Record.Values.size(); |
| 76 if (DebugEmitRecord) { |
| 77 errs() << "Emit " << Record.Abbrev << ": <" << Record.Code; |
| 78 for (size_t i = 0; i < NumValues; ++i) { |
| 79 errs() << ", " << Record.Values[i]; |
| 80 } |
| 81 errs() << ">\n"; |
| 82 } |
| 83 |
| 84 switch (Record.Code) { |
| 85 case naclbitc::BLK_CODE_ENTER: { |
| 86 unsigned NumBits = NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); |
| 87 WriteBlockID = -1; |
| 88 if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) { |
| 89 RecoverableError() |
| 90 << "Uses illegal abbreviation index in enter block record: " |
| 91 << Record << "\n"; |
| 92 if (!Flags.getTryToRecover()) |
| 93 return false; |
| 94 } |
| 95 if (NumValues == 2) { |
| 96 WriteBlockID = Record.Values[0]; |
| 97 NumBits = Record.Values[1]; |
| 98 if (NumBits > 32 || NumBits < 2) { |
| 99 RecoverableError() |
| 100 << "Bit size " << NumBits << " for record should be " |
| 101 << (NumBits > 32 ? "<= 32" : ">= 2") << ": " << Record << "\n"; |
| 102 if (!Flags.getTryToRecover()) |
| 103 return false; |
| 104 NumBits = 32; |
| 105 } |
| 106 } else { |
| 107 Error() << "Values for enter record should be of size 2, but found " |
| 108 << NumValues << ": " << Record << "\n"; |
| 109 return false; |
| 110 } |
| 111 uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1; |
| 112 AbbrevIndexLimitStack.push_back(MaxAbbrev); |
| 113 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { |
| 114 unsigned DefaultMaxBits = |
| 115 NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); |
| 116 if (NumBits != DefaultMaxBits) { |
| 117 RecoverableError() |
| 118 << "Numbits entry for abbreviations record not " |
| 119 << DefaultMaxBits << " but found " << NumBits << |
| 120 ": " << Record << "\n"; |
| 121 if (!Flags.getTryToRecover()) |
| 122 return false; |
| 123 } |
| 124 Writer.EnterBlockInfoBlock(); |
| 125 } else { |
| 126 NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); |
| 127 Writer.EnterSubblock(WriteBlockID, CurCodeLen); |
| 128 } |
| 129 break; |
| 130 } |
| 131 case naclbitc::BLK_CODE_EXIT: |
| 132 if (Record.Abbrev != naclbitc::END_BLOCK) { |
| 133 RecoverableError() |
| 134 << "Uses illegal abbreviation index in exit block record: " |
| 135 << Record << "\n"; |
| 136 if (!Flags.getTryToRecover()) |
| 137 return false; |
| 138 } |
| 139 if (NumValues != 0) { |
| 140 RecoverableError() << "Exit block should not have values: " |
| 141 << Record << "\n"; |
| 142 if (!Flags.getTryToRecover()) |
| 143 return false; |
| 144 } |
| 145 if (!AbbrevIndexLimitStack.empty()) |
| 146 AbbrevIndexLimitStack.pop_back(); |
| 147 Writer.ExitBlock(); |
| 148 break; |
| 149 case naclbitc::BLK_CODE_DEFINE_ABBREV: { |
| 150 if (Record.Abbrev != naclbitc::DEFINE_ABBREV) { |
| 151 RecoverableError() |
| 152 << "Uses illegal abbreviation index in define abbreviation record: " |
| 153 << Record << "\n"; |
| 154 if (!Flags.getTryToRecover()) |
| 155 return false; |
| 156 } |
| 157 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record); |
| 158 if (Abbrev == NULL) |
| 159 return Flags.getTryToRecover(); |
| 160 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { |
| 161 Writer.EmitBlockInfoAbbrev(SetBID, Abbrev); |
| 162 } else { |
| 163 Writer.EmitAbbrev(Abbrev); |
| 164 } |
| 165 break; |
| 166 } |
| 167 case naclbitc::BLK_CODE_HEADER: |
| 168 // Note: There is no abbreviation index here. Ignore. |
| 169 for (uint64_t Value : Record.Values) |
| 170 Writer.Emit(Value, 8); |
| 171 break; |
| 172 default: |
| 173 if (AbbrevIndexLimitStack.empty()) { |
| 174 Error() << "Can't write record outside record block: " << Record << "\n"; |
| 175 return false; |
| 176 } |
| 177 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD; |
| 178 if (!UsesDefaultAbbrev |
| 179 && !Writer.isUserRecordAbbreviation(Record.Abbrev)) { |
| 180 // Illegal abbreviation index found. |
| 181 if (Flags.getWriteBadAbbrevIndex()) { |
| 182 Error() << "Uses illegal abbreviation index: " << Record << "\n"; |
| 183 // Generate bad abbreviation index so that the bitcode reader |
| 184 // can be tested. |
| 185 Results.WroteBadAbbrevIndex = true; |
| 186 Writer.EmitCode(Record.Abbrev); |
| 187 // Note: We need to close blocks or the bitcode Writer will terminate |
| 188 // due to assertions. |
| 189 writeMissingEndBlocks(Writer); |
| 190 return false; |
| 191 } |
| 192 RecoverableError() << "Uses illegal abbreviation index: " |
| 193 << Record << "\n"; |
| 194 if (!Flags.getTryToRecover()) |
| 195 return false; |
| 196 UsesDefaultAbbrev = true; |
| 197 } |
| 198 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID |
| 199 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) { |
| 200 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev, |
| 201 // based on the SetBID value. Don't bother to generate SetBID record here. |
| 202 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev |
| 203 // generate the SetBID record. |
| 204 if (NumValues != 1) { |
| 205 Error() << "SetBID record expects 1 value but found " |
| 206 << NumValues << ": " << Record << "\n"; |
| 207 return false; |
| 208 } |
| 209 SetBID = Record.Values[0]; |
| 210 return true; |
| 211 } |
| 212 if (UsesDefaultAbbrev) |
| 213 Writer.EmitRecord(Record.Code, Record.Values); |
| 214 else |
| 215 Writer.EmitRecord(Record.Code, Record.Values, Record.Abbrev); |
| 216 } |
| 217 return true; |
| 218 } |
| 219 |
| 220 static NaClBitCodeAbbrev *deleteAbbrev(NaClBitCodeAbbrev *Abbrev) { |
| 221 Abbrev->dropRef(); |
| 222 return nullptr; |
| 223 } |
| 224 |
| 225 NaClBitCodeAbbrev *WriteState::buildAbbrev( |
| 226 const NaClBitcodeAbbrevRecord &Record) { |
| 227 // Note: Recover by removing abbreviation. |
| 228 NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev(); |
| 229 size_t Index = 0; |
| 230 size_t NumValues = Record.Values.size(); |
| 231 if (NumValues == 0) { |
| 232 RecoverableError() << "Empty abbreviation record not allowed: " |
| 233 << Record << "\n"; |
| 234 return deleteAbbrev(Abbrev); |
| 235 } |
| 236 size_t NumAbbreviations = Record.Values[Index++]; |
| 237 if (NumAbbreviations == 0) { |
| 238 RecoverableError() << "Abbreviation must contain at least one operator: " |
| 239 << Record << "\n"; |
| 240 return deleteAbbrev(Abbrev); |
| 241 } |
| 242 for (size_t Count = 0; Count < NumAbbreviations; ++Count) { |
| 243 if (Index >= NumValues) { |
| 244 RecoverableError() |
| 245 << "Malformed abbreviation found. Expects " << NumAbbreviations |
| 246 << " operands but ound " << Count << ": " << Record << "\n"; |
| 247 return deleteAbbrev(Abbrev); |
| 248 } |
| 249 switch (Record.Values[Index++]) { |
| 250 case 1: |
| 251 if (Index >= NumValues) { |
| 252 RecoverableError() << "Malformed literal abbreviation: " |
| 253 << Record << "\n"; |
| 254 return deleteAbbrev(Abbrev); |
| 255 } |
| 256 Abbrev->Add(NaClBitCodeAbbrevOp(Record.Values[Index++])); |
| 257 break; |
| 258 case 0: { |
| 259 if (Index >= NumValues) { |
| 260 RecoverableError() << "Malformed abbreviation found: " |
| 261 << Record << "\n"; |
| 262 return deleteAbbrev(Abbrev); |
| 263 } |
| 264 unsigned Kind = Record.Values[Index++]; |
| 265 switch (Kind) { |
| 266 case NaClBitCodeAbbrevOp::Fixed: |
| 267 if (Index >= NumValues) { |
| 268 RecoverableError() << "Malformed fixed abbreviation found: " |
| 269 << Record << "\n"; |
| 270 return deleteAbbrev(Abbrev); |
| 271 } |
| 272 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, |
| 273 Record.Values[Index++])); |
| 274 break; |
| 275 case NaClBitCodeAbbrevOp::VBR: |
| 276 if (Index >= NumValues) { |
| 277 RecoverableError() << "Malformed vbr abbreviation found: " |
| 278 << Record << "\n"; |
| 279 return deleteAbbrev(Abbrev); |
| 280 } |
| 281 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, |
| 282 Record.Values[Index++])); |
| 283 break; |
| 284 case NaClBitCodeAbbrevOp::Array: |
| 285 if (Index >= NumValues) { |
| 286 RecoverableError() << "Malformed array abbreviation found: " |
| 287 << Record << "\n"; |
| 288 return deleteAbbrev(Abbrev); |
| 289 } |
| 290 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array)); |
| 291 break; |
| 292 case NaClBitCodeAbbrevOp::Char6: |
| 293 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6)); |
| 294 break; |
| 295 default: |
| 296 RecoverableError() << "Unknown abbreviation kind " << Kind |
| 297 << ": " << Record << "\n"; |
| 298 return deleteAbbrev(Abbrev); |
| 299 } |
| 300 break; |
| 301 } |
| 302 default: |
| 303 RecoverableError() << "Error: Bad literal flag " << Record.Values[Index] |
| 304 << ": " << Record << "\n"; |
| 305 return deleteAbbrev(Abbrev); |
| 306 } |
| 307 } |
| 308 return Abbrev; |
| 309 } |
| 310 |
| 311 } // end of anonymous namespace. |
| 312 |
| 313 NaClMungedBitcode::WriteResults NaClMungedBitcode::writeMaybeRepair( |
| 314 SmallVectorImpl<char> &Buffer, bool AddHeader, |
| 315 const WriteFlags &Flags) const { |
| 316 NaClBitstreamWriter Writer(Buffer); |
| 317 WriteState State(Flags); |
| 318 if (AddHeader) { |
| 319 NaClWriteHeader(Writer, true); |
| 320 } |
| 321 for (const NaClBitcodeAbbrevRecord &Record : *this) { |
| 322 if (!State.emitRecord(Writer, Record)) |
| 323 break; |
| 324 } |
| 325 if (!State.AbbrevIndexLimitStack.empty()) { |
| 326 State.RecoverableError() |
| 327 << "Bitcode missing " << State.AbbrevIndexLimitStack.size() |
| 328 << " close blocks.\n"; |
| 329 if (Flags.getTryToRecover()) |
| 330 State.writeMissingEndBlocks(Writer); |
| 331 } |
| 332 return State.Results; |
| 333 } |
OLD | NEW |