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

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: Fix nits. 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
« no previous file with comments | « lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeReader.cpp ('k') | unittests/Bitcode/CMakeLists.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.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 }
OLDNEW
« no previous file with comments | « lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeReader.cpp ('k') | unittests/Bitcode/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698