Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp

Issue 1113023005: Add abilities to generate bitcode buffers from munged bitcode. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Try to get better patch. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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.HasErrors = true;
44 return errs() << "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.TryToRecover)
51 Results.HasRepairs = true;
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 = naclbitc::DEFAULT_MAX_ABBREV;
jvoung (off chromium) 2015/05/06 22:08:09 Should this also be NaClBitsNeededForValue( naclbi
Karl 2015/05/07 20:09:18 Good catch. Fixing!
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.TryToRecover)
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.TryToRecover)
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.TryToRecover)
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.TryToRecover)
137 return false;
138 }
139 if (NumValues != 0) {
140 RecoverableError() << "Exit block should not have values: "
141 << Record << "\n";
142 if (!Flags.TryToRecover)
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.TryToRecover)
155 return false;
156 }
157 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record);
158 if (Abbrev == NULL)
159 return Flags.TryToRecover;
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 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD;
174 if (!UsesDefaultAbbrev
175 && !Writer.isUserRecordAbbreviation(Record.Abbrev)) {
176 uint64_t BlockAbbrevIndexLimit = 0;
177 if (!AbbrevIndexLimitStack.empty())
178 BlockAbbrevIndexLimit = AbbrevIndexLimitStack.back();
179 // Can't generate abbreviation ID because not enough bits
180 // specified in block ID.
181 raw_ostream &ErrStrm = RecoverableError();
182 ErrStrm << "Uses illegal abbreviation index";
183 if (Record.Abbrev > BlockAbbrevIndexLimit)
jvoung (off chromium) 2015/05/06 22:08:09 When does this > check fail? If for some reason th
Karl 2015/05/07 20:09:18 Decided to simplify this code and be more generic.
184 ErrStrm << ". Must not exceed " << BlockAbbrevIndexLimit;
185 ErrStrm << ": " << Record << "\n";
186 if (!Flags.TryToRecover && !Flags.SaveBadAbbrevIndices)
jvoung (off chromium) 2015/05/06 22:08:09 So this code is saying that SaveBadAbbrevIndices w
Karl 2015/05/07 20:09:18 Hopefully the code is now clearer since I simplifi
jvoung (off chromium) 2015/05/07 21:33:56 Thanks -- I like the new version more.
187 return false;
188 if (Flags.SaveBadAbbrevIndices) {
189 // Note: If this point is reached, the abbreviation is bad and
190 // RecoverOnBadAbbrevID is true. Generate bad abbreviation index
jvoung (off chromium) 2015/05/06 22:08:09 there is no RecoverOnBadAbbrevID anymore You also
Karl 2015/05/07 20:09:18 Again, I simplified this code so that we don't nee
191 // so that the bitcode reader can be tested.
192 Writer.EmitCode(Record.Abbrev);
193 // Note: We need to close blocks or the bitcode Writer will terminate
194 // due to assertions.
195 writeMissingEndBlocks(Writer);
196 Results.SavedBadAbbrevIndices = true;
jvoung (off chromium) 2015/05/06 22:08:09 Perhaps "Save..." should be "Write..." ? In some
Karl 2015/05/07 20:09:18 Hopefully I have clarified that the Save Case (now
197 return false;
198 }
199 UsesDefaultAbbrev = true;
200 }
201 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID
202 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) {
203 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev,
204 // based on the SetBID value. Don't bother to generate SetBID record here.
205 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev
206 // generate the SetBID record.
207 if (NumValues != 1) {
208 Error() << "SetBID record expects 1 value but found "
209 << NumValues << ": " << Record << "\n";
210 return false;
211 }
212 SetBID = Record.Values[0];
213 return true;
214 }
215 if (UsesDefaultAbbrev)
216 Writer.EmitRecord(Record.Code, Record.Values);
217 else
218 Writer.EmitRecord(Record.Code, Record.Values, Record.Abbrev);
219 }
220 return true;
221 }
222
223 static NaClBitCodeAbbrev *deleteAbbrev(NaClBitCodeAbbrev *Abbrev) {
224 Abbrev->dropRef();
225 return nullptr;
226 }
227
228 NaClBitCodeAbbrev *WriteState::buildAbbrev(
229 const NaClBitcodeAbbrevRecord &Record) {
230 // Note: Recover by removing abbreviation.
231 NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
232 size_t Index = 0;
233 size_t NumValues = Record.Values.size();
234 if (NumValues == 0) {
235 RecoverableError() << "Empty abbreviation record not allowed: "
236 << Record << "\n";
237 return deleteAbbrev(Abbrev);
238 }
239 size_t NumAbbreviations = Record.Values[Index++];
240 if (NumAbbreviations == 0) {
241 RecoverableError() << "Abbreviation must contain at least one operator: "
242 << Record << "\n";
243 return deleteAbbrev(Abbrev);
244 }
245 for (size_t Count = 0; Count < NumAbbreviations; ++Count) {
246 if (Index >= NumValues) {
247 RecoverableError()
248 << "Malformed abbreviation found. Expects " << NumAbbreviations
249 << " operands but ound " << Count << ": " << Record << "\n";
250 return deleteAbbrev(Abbrev);
251 }
252 switch (Record.Values[Index++]) {
253 case 1:
254 if (Index >= NumValues) {
255 RecoverableError() << "Malformed literal abbreviation: "
256 << Record << "\n";
257 return deleteAbbrev(Abbrev);
258 }
259 Abbrev->Add(NaClBitCodeAbbrevOp(Record.Values[Index++]));
260 break;
261 case 0: {
262 if (Index >= NumValues) {
263 RecoverableError() << "Malformed abbreviation found: "
264 << Record << "\n";
265 return deleteAbbrev(Abbrev);
266 }
267 unsigned Kind = Record.Values[Index++];
268 switch (Kind) {
269 case NaClBitCodeAbbrevOp::Fixed:
270 if (Index >= NumValues) {
271 RecoverableError() << "Malformed fixed abbreviation found: "
272 << Record << "\n";
273 return deleteAbbrev(Abbrev);
274 }
275 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed,
276 Record.Values[Index++]));
277 break;
278 case NaClBitCodeAbbrevOp::VBR:
279 if (Index >= NumValues) {
280 RecoverableError() << "Malformed vbr abbreviation found: "
281 << Record << "\n";
282 return deleteAbbrev(Abbrev);
283 }
284 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR,
285 Record.Values[Index++]));
286 break;
287 case NaClBitCodeAbbrevOp::Array:
288 if (Index >= NumValues) {
289 RecoverableError() << "Malformed array abbreviation found: "
290 << Record << "\n";
291 return deleteAbbrev(Abbrev);
292 }
293 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array));
294 break;
295 case NaClBitCodeAbbrevOp::Char6:
296 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6));
297 break;
298 default:
299 RecoverableError() << "Unknown abbreviation kind " << Kind
300 << ": " << Record << "\n";
301 return deleteAbbrev(Abbrev);
302 }
303 break;
304 }
305 default:
306 RecoverableError() << "Error: Bad literal flag " << Record.Values[Index]
307 << ": " << Record << "\n";
308 return deleteAbbrev(Abbrev);
309 }
310 }
311 return Abbrev;
312 }
313
314 } // end of anonymous namespace.
315
316 NaClMungedBitcode::WriteResults NaClMungedBitcode::writeMaybeRepair(
317 SmallVectorImpl<char> &Buffer, bool AddHeader,
318 const WriteFlags &Flags) const {
319 NaClBitstreamWriter Writer(Buffer);
320 WriteState State(Flags);
321 if (AddHeader) {
322 NaClWriteHeader(Writer, true);
323 }
324 for (const NaClBitcodeAbbrevRecord &Record : *this) {
325 if (!State.emitRecord(Writer, Record))
326 break;
327 }
328 if (!State.AbbrevIndexLimitStack.empty()) {
329 State.RecoverableError()
330 << "Bitcode missing " << State.AbbrevIndexLimitStack.size()
331 << " close blocks.\n";
332 if (Flags.TryToRecover)
333 State.writeMissingEndBlocks(Writer);
334 }
335 return State.Results;
336 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698