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

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

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 9 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/Makefile ('k') | lib/Bitcode/NaCl/Writer/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 //===--- Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp - Bitcode Munger -----===//
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 // Bitcode writer/munger implementation for testing.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Bitcode/NaCl/NaClBitcodeMunge.h"
15
16 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
17 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
18 #include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h"
19 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/MemoryBuffer.h"
24
25 #include <memory>
26
27 using namespace llvm;
28
29 // For debugging. When true, shows each PNaCl record that is
30 // emitted to the bitcode file.
31 static bool DebugEmitRecord = false;
32
33 void NaClBitcodeMunger::setupTest(
34 const char *TestName, const uint64_t Munges[], size_t MungesSize,
35 bool AddHeader) {
36 assert(DumpStream == nullptr && "Test run with DumpStream already defined");
37 assert(MungedInput.get() == nullptr
38 && "Test run with MungedInput already defined");
39 FoundErrors = false;
40 DumpResults.clear(); // Throw away any previous results.
41 std::string DumpBuffer;
42 DumpStream = new raw_string_ostream(DumpResults);
43 SmallVector<char, 0> StreamBuffer;
44 StreamBuffer.reserve(256*1024);
45 NaClBitstreamWriter OutStream(StreamBuffer);
46 Writer = &OutStream;
47
48 if (DebugEmitRecord) {
49 errs() << "*** Run test: " << TestName << "\n";
50 }
51
52 WriteBlockID = -1;
53 SetBID = -1;
54 writeMungedData(Munges, MungesSize, AddHeader);
55
56 std::string OutBuffer;
57 raw_string_ostream BitcodeStrm(OutBuffer);
58 for (SmallVectorImpl<char>::const_iterator
59 Iter = StreamBuffer.begin(), IterEnd = StreamBuffer.end();
60 Iter != IterEnd; ++Iter) {
61 BitcodeStrm << *Iter;
62 }
63 MungedInput = MemoryBuffer::getMemBufferCopy(BitcodeStrm.str(), TestName);
64 }
65
66 void NaClBitcodeMunger::cleanupTest() {
67 MungedInput.reset();
68 assert(DumpStream && "Dump stream removed before cleanup!");
69 DumpStream->flush();
70 delete DumpStream;
71 DumpStream = nullptr;
72 Writer = nullptr;
73 }
74
75 // Return the next line of input (including eoln), starting from
76 // Pos. Then increment Pos past the end of that line.
77 static std::string getLine(const std::string &Input, size_t &Pos) {
78 std::string Line;
79 if (Pos >= Input.size()) {
80 Pos = std::string::npos;
81 return Line;
82 }
83 size_t Eoln = Input.find_first_of("\n", Pos);
84 if (Eoln != std::string::npos) {
85 for (size_t i = Pos; i <= Eoln; ++i)
86 Line.push_back(Input[i]);
87 Pos = Eoln + 1;
88 return Line;
89 }
90 Pos = std::string::npos;
91 return Input.substr(Pos);
92 }
93
94 std::string NaClBitcodeMunger::
95 getLinesWithTextMatch(const std::string &Substring, bool MustBePrefix) const {
96 std::string Messages;
97 size_t LastLinePos = 0;
98 while (1) {
99 std::string Line = getLine(DumpResults, LastLinePos);
100 if (LastLinePos == std::string::npos) break;
101 size_t Pos = Line.find(Substring);
102 if (Pos != std::string::npos && (!MustBePrefix || Pos == 0)) {
103 Messages.append(Line);
104 }
105 }
106 return Messages;
107 }
108
109 void NaClBitcodeMunger::writeMungedData(const uint64_t Munges[],
110 size_t MungesSize, bool AddHeader) {
111 uint64_t RecordCount = 0;
112 size_t MungesIndex = 0;
113 if (AddHeader) {
114 NaClWriteHeader(*Writer, true);
115 }
116 for (size_t RecordsIndex = 0; RecordsIndex < RecordsSize;) {
117 if (MungesIndex < MungesSize && Munges[MungesIndex] == RecordCount) {
118 if (MungesIndex + 2 > MungesSize) {
119 Fatal() << "Munges entry must contain at least 2 elements. Found: "
120 << MungesIndex;
121 ReportFatalError();
122 }
123 ++MungesIndex;
124 switch (Munges[MungesIndex++]) {
125 case NaClBitcodeMunger::AddBefore:
126 emitRecordAtIndex(Munges, MungesSize, MungesIndex);
127 break;
128 case NaClBitcodeMunger::AddAfter:
129 emitRecordAtIndex(Records, RecordsSize, RecordsIndex);
130 ++RecordCount;
131 emitRecordAtIndex(Munges, MungesSize, MungesIndex);
132 break;
133 case NaClBitcodeMunger::Remove:
134 deleteRecord(Records, RecordsSize, RecordsIndex);
135 ++RecordCount;
136 break;
137 case NaClBitcodeMunger::Replace:
138 deleteRecord(Records, RecordsSize, RecordsIndex);
139 emitRecordAtIndex(Munges, MungesSize, MungesIndex);
140 ++RecordCount;
141 break;
142 default:
143 Fatal() << "Munge directive not understood: " << Munges[MungesIndex];
144 ReportFatalError();
145 break;
146 }
147 } else {
148 emitRecordAtIndex(Records, RecordsSize, RecordsIndex);
149 ++RecordCount;
150 }
151 }
152 if (MungesIndex < MungesSize) {
153 Fatal() << "Unprocessed modifications. At index " << MungesIndex << "\n";
154 ReportFatalError();
155 }
156 }
157
158 void NaClBitcodeMunger::deleteRecord(
159 const uint64_t Record[], size_t RecordSize, size_t &Index) {
160 while (Index < RecordSize) {
161 if (Record[Index++] == RecordTerminator)
162 break;
163 }
164 }
165
166 void NaClBitcodeMunger::emitRecordAtIndex(
167 const uint64_t Record[], size_t RecordSize, size_t &Index) {
168 if (Index + 3 > RecordSize) {
169 Fatal() << "Last record doesn't contain at least 3 elements. Found: "
170 << (RecordSize - Index);
171 ReportFatalError();
172 }
173 SmallVector<uint64_t, 32> RecordValues;
174 unsigned AbbrevIndex = static_cast<unsigned>(Record[Index++]);
175 unsigned RecordCode = static_cast<unsigned>(Record[Index++]);
176 while (Index < RecordSize && Record[Index] != RecordTerminator) {
177 RecordValues.push_back(Record[Index++]);
178 }
179 emitRecord(AbbrevIndex, RecordCode, RecordValues);
180 if (Index == RecordSize) {
181 Fatal() << "Last record not followed by terminator.\n";
182 ReportFatalError();
183 }
184 ++Index;
185 }
186
187 void NaClBitcodeMunger::emitRecord(unsigned AbbrevIndex,
188 unsigned RecordCode,
189 SmallVectorImpl<uint64_t> &Values) {
190 if (DebugEmitRecord) {
191 errs() << "Emit " << AbbrevIndex << ": <" << RecordCode;
192 for (size_t i = 0; i < Values.size(); ++i) {
193 errs() << ", " << Values[i];
194 }
195 errs() << ">\n";
196 }
197
198 switch (RecordCode) {
199 case naclbitc::BLK_CODE_ENTER: {
200 unsigned NumBits = naclbitc::DEFAULT_MAX_ABBREV;
201 WriteBlockID = -1;
202 if (AbbrevIndex != naclbitc::ENTER_SUBBLOCK) {
203 Fatal() << "Enter block record code " << RecordCode
204 << " uses illegal abbreviation index " << AbbrevIndex << "\n";
205 ReportFatalError();
206 }
207 if (Values.size() == 2) {
208 WriteBlockID = Values[0];
209 NumBits = Values[1];
210 if (NumBits > 32) {
211 Fatal() << "Error: Bit size " << NumBits
212 << " for record should be <= 32\n";
213 ReportFatalError();
214 }
215 } else {
216 Fatal() << "Error: Values for enter record should be of size 2. Found: "
217 << Values.size();
218 ReportFatalError();
219 }
220 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) {
221 if (NumBits != naclbitc::DEFAULT_MAX_ABBREV) {
222 Fatal()
223 << "Error: Numbits entry for abbreviations record not 2. Found: "
224 << NumBits << "\n";
225 ReportFatalError();
226 }
227 Writer->EnterBlockInfoBlock();
228 } else {
229 Writer->EnterSubblock(WriteBlockID, NumBits);
230 }
231 return;
232 }
233 case naclbitc::BLK_CODE_EXIT:
234 if (AbbrevIndex != naclbitc::END_BLOCK) {
235 Fatal() << "Error: Exit block record code " << RecordCode
236 << " uses illegal abbreviation index " << AbbrevIndex << "\n";
237 ReportFatalError();
238 }
239 if (!Values.empty()) {
240 Fatal() << "Error: Exit block should not have values. Found: "
241 << Values.size() << "\n";
242 ReportFatalError();
243 }
244 Writer->ExitBlock();
245 return;
246 case naclbitc::BLK_CODE_DEFINE_ABBREV: {
247 if (AbbrevIndex != naclbitc::DEFINE_ABBREV) {
248 Fatal() << "Error: Define abbreviation record code " << RecordCode
249 << " uses illegal abbreviation index " << AbbrevIndex << "\n";
250 ReportFatalError();
251 }
252 NaClBitCodeAbbrev *Abbrev = buildAbbrev(RecordCode, Values);
253 if (Abbrev == NULL) return;
254 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) {
255 Writer->EmitBlockInfoAbbrev(SetBID, Abbrev);
256 } else {
257 Writer->EmitAbbrev(Abbrev);
258 }
259 return;
260 }
261 case naclbitc::BLK_CODE_HEADER:
262 // Note: There is no abbreviation index here. Ignore.
263 for (SmallVectorImpl<uint64_t>::const_iterator
264 Iter = Values.begin(), IterEnd = Values.end();
265 Iter != IterEnd; ++Iter) {
266 Writer->Emit(*Iter, 8);
267 }
268 return;
269 default:
270 if ((AbbrevIndex != naclbitc::UNABBREV_RECORD
271 && !Writer->isUserRecordAbbreviation(AbbrevIndex))) {
272 Fatal() << "Error: Record code " << RecordCode
273 << " uses illegal abbreviation index " << AbbrevIndex << "\n";
274 ReportFatalError();
275 }
276 if (AbbrevIndex == naclbitc::UNABBREV_RECORD)
277 Writer->EmitRecord(RecordCode, Values);
278 else
279 Writer->EmitRecord(RecordCode, Values, AbbrevIndex);
280 return;
281 }
282 Fatal() << "emitRecord on unimplemented code" << "\n";
283 ReportFatalError();
284 }
285
286 NaClBitCodeAbbrev *NaClBitcodeMunger::buildAbbrev(
287 unsigned RecordCode, SmallVectorImpl<uint64_t> &Values) {
288 NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
289 for (size_t Index = 0; Index < Values.size(); ) {
290 switch (Values[Index]) {
291 case 1:
292 if (Index + 1 >= Values.size()) {
293 Fatal() << "Malformed literal abbreviation.\n";
294 ReportFatalError();
295 }
296 Abbrev->Add(NaClBitCodeAbbrevOp(Values[++Index]));
297 break;
298 case 0: {
299 if (Index >= Values.size()) {
300 Fatal() << "Malformed abbreviation found.\n";
301 ReportFatalError();
302 }
303 unsigned Kind = Values[++Index];
304 switch (Kind) {
305 case NaClBitCodeAbbrevOp::Fixed:
306 if (Index >= Values.size()) {
307 Fatal() << "Malformed fixed abbreviation found.\n";
308 ReportFatalError();
309 }
310 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed,
311 Values[++Index]));
312 break;
313 case NaClBitCodeAbbrevOp::VBR:
314 if (Index >= Values.size()) {
315 Fatal() << "Malformed vbr abbreviation found.\n";
316 ReportFatalError();
317 }
318 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR,
319 Values[++Index]));
320 break;
321 case NaClBitCodeAbbrevOp::Array:
322 if (Index >= Values.size()) {
323 Fatal() << "Malformed array abbreviation found.\n";
324 ReportFatalError();
325 }
326 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array));
327 break;
328 case NaClBitCodeAbbrevOp::Char6:
329 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6));
330 break;
331 default:
332 Fatal() << "Unknown abbreviation kind. Found: " << Kind << "\n";
333 ReportFatalError();
334 }
335 break;
336 }
337 default:
338 Fatal() << "Error: Bad literal flag in abbreviation. Found: "
339 << Values[Index];
340 ReportFatalError();
341 }
342 }
343 return Abbrev;
344 }
345
346 bool NaClObjDumpMunger::runTestWithFlags(
347 const char *Name, const uint64_t Munges[], size_t MungesSize,
348 bool AddHeader, bool NoRecords, bool NoAssembly) {
349 setupTest(Name, Munges, MungesSize, AddHeader);
350 // TODO(jvoung,kschimpf): Should NaClObjDump take a MemoryBufferRef
351 // like the parser?
352 if (NaClObjDump(MungedInput.get(), *DumpStream, NoRecords, NoAssembly))
353 FoundErrors = true;
354 cleanupTest();
355 return !FoundErrors;
356 }
357
358 bool NaClParseBitcodeMunger::runTest(
359 const char *Name, const uint64_t Munges[], size_t MungesSize,
360 bool VerboseErrors) {
361 bool AddHeader = true;
362 setupTest(Name, Munges, MungesSize, AddHeader);
363 LLVMContext &Context = getGlobalContext();
364 raw_ostream *VerboseStrm = VerboseErrors ? DumpStream : nullptr;
365 ErrorOr<Module *> ModuleOrError =
366 NaClParseBitcodeFile(MungedInput->getMemBufferRef(), Context,
367 VerboseStrm);
368 if (ModuleOrError) {
369 if (VerboseErrors)
370 *DumpStream << "Successful parse!\n";
371 delete ModuleOrError.get();
372 } else {
373 Error() << ModuleOrError.getError().message() << "\n";
374 }
375 cleanupTest();
376 return !FoundErrors;
377 }
OLDNEW
« no previous file with comments | « lib/Bitcode/NaCl/TestUtils/Makefile ('k') | lib/Bitcode/NaCl/Writer/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698