OLD | NEW |
1 //===- NaClBitcodeMunge.h - Bitcode Munger ----------------------*- C++ -*-===// | 1 //===- NaClBitcodeMunge.h - Bitcode Munger ----------------------*- C++ -*-===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // Test harness for generating a PNaCl bitcode memory buffer from | 10 // Test harness for generating a PNaCl bitcode memory buffer from |
11 // an array, and parse/objdump/compress the resulting contents. | 11 // an array, and parse/objdump/compress the resulting contents. |
12 // | 12 // |
13 // Generates a bitcode memory buffer from an array containing 1 or | 13 // Generates a bitcode memory buffer from an array containing 1 or |
14 // more PNaCl records. Used to test errors in PNaCl bitcode. | 14 // more PNaCl records. Used to test errors in PNaCl bitcode. |
15 // | 15 // |
16 // Bitcode records are modeleled using arrays using the format | 16 // Bitcode records are modeled using arrays using the format |
17 // specified in NaClBitcodeMungeUtils.h. | 17 // specified in NaClBitcodeMungeUtils.h. |
18 // | 18 // |
19 // Note: Since the header record doesn't have any abbreviation indices | 19 // Note: Since the header record doesn't have any abbreviation indices |
20 // associated with it, one can use any value. The value will simply be | 20 // associated with it, one can use any value. The value will simply be |
21 // ignored. | 21 // ignored. |
22 // | 22 // |
23 // In addition to specifying the sequence of records, one can also | 23 // In addition to specifying the sequence of records, one can also |
24 // define a sequence of edits to be applied to the original sequence | 24 // define a sequence of edits to be applied to the original sequence |
25 // of records. This allows the same record sequence to be used in | 25 // of records. This allows the same record sequence to be used in |
26 // multiple tests. Again, see NaClBitcodeMungeUtils.h for the | 26 // multiple tests. Again, see NaClBitcodeMungeUtils.h for the |
(...skipping 13 matching lines...) Expand all Loading... |
40 | 40 |
41 #include "llvm/ADT/SmallVector.h" | 41 #include "llvm/ADT/SmallVector.h" |
42 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" | 42 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" |
43 #include "llvm/Support/MemoryBuffer.h" | 43 #include "llvm/Support/MemoryBuffer.h" |
44 #include "llvm/Support/raw_ostream.h" | 44 #include "llvm/Support/raw_ostream.h" |
45 | 45 |
46 #include <string> | 46 #include <string> |
47 | 47 |
48 namespace llvm { | 48 namespace llvm { |
49 | 49 |
50 class NaClBitstreamWriter; | |
51 class NaClBitCodeAbbrev; | 50 class NaClBitCodeAbbrev; |
52 | 51 |
53 /// Base class to run tests on munged bitcode files. | 52 /// Base class to run tests on munged bitcode files. |
54 class NaClBitcodeMunger { | 53 class NaClBitcodeMunger { |
55 public: | 54 public: |
56 /// Creates a bitcode munger, based on the given array of values. | 55 /// Creates a bitcode munger, based on the given array of values. |
57 NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize, | 56 NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize, |
58 uint64_t RecordTerminator) | 57 uint64_t RecordTerminator) |
59 : MungedBitcode(Records, RecordsSize, RecordTerminator), | 58 : MungedBitcode(Records, RecordsSize, RecordTerminator), |
60 RecordTerminator(RecordTerminator), WriteBlockID(-1), SetBID(-1), | 59 RecordTerminator(RecordTerminator), |
61 DumpResults("Error: No previous dump results!\n"), | 60 DumpResults("Error: No previous dump results!\n"), |
62 DumpStream(nullptr), Writer(nullptr), FoundErrors(false), | 61 DumpStream(nullptr), FoundErrors(false), RunAsDeathTest(false) {} |
63 FatalBuffer(), FatalStream(FatalBuffer) {} | 62 |
| 63 /// Returns true if running as death test. |
| 64 bool getRunAsDeathTest() const { |
| 65 return RunAsDeathTest; |
| 66 } |
| 67 |
| 68 /// Sets death test flag. When true, output will be redirected to |
| 69 /// the errs() (rather than buffered) so that the test can be |
| 70 /// debugged. |
| 71 void setRunAsDeathTest(bool NewValue) { |
| 72 RunAsDeathTest = NewValue; |
| 73 } |
64 | 74 |
65 /// Creates MungedInput and DumpStream for running tests, based on | 75 /// Creates MungedInput and DumpStream for running tests, based on |
66 /// given Munges. | 76 /// given Munges. |
67 void setupTest( | 77 void setupTest( |
68 const char *TestName, const uint64_t Munges[], size_t MungesSize, | 78 const char *TestName, const uint64_t Munges[], size_t MungesSize, |
69 bool AddHeader); | 79 bool AddHeader); |
70 | 80 |
71 /// Cleans up state after a test. | 81 /// Cleans up state after a test. |
72 void cleanupTest(); | 82 void cleanupTest(); |
73 | 83 |
74 /// Returns the resulting string generated by the corresponding test. | 84 /// Returns the resulting string generated by the corresponding test. |
75 const std::string &getTestResults() const { | 85 const std::string &getTestResults() const { |
76 return DumpResults; | 86 return DumpResults; |
77 } | 87 } |
78 | 88 |
79 /// Returns the lines containing the given Substring, from the | 89 /// Returns the lines containing the given Substring, from the |
80 /// string getTestResults(). | 90 /// string getTestResults(). |
81 std::string getLinesWithSubstring(const std::string &Substring) const { | 91 std::string getLinesWithSubstring(const std::string &Substring) const { |
82 return getLinesWithTextMatch(Substring, false); | 92 return getLinesWithTextMatch(Substring, false); |
83 } | 93 } |
84 | 94 |
85 /// Returns the lines starting with the given Prefix, from the string | 95 /// Returns the lines starting with the given Prefix, from the string |
86 /// getTestResults(). | 96 /// getTestResults(). |
87 std::string getLinesWithPrefix(const std::string &Prefix) const { | 97 std::string getLinesWithPrefix(const std::string &Prefix) const { |
88 return getLinesWithTextMatch(Prefix, true); | 98 return getLinesWithTextMatch(Prefix, true); |
89 } | 99 } |
90 | 100 |
| 101 /// When NewValue, use error recovery when writing bitcode during |
| 102 /// next test. |
| 103 void setTryToRecoverOnWrite(bool NewValue) { |
| 104 WriteFlags.setTryToRecover(NewValue); |
| 105 } |
| 106 |
| 107 /// When NewValue, write bad abbreviation index into bitcode when |
| 108 /// writing during next test. |
| 109 void setWriteBadAbbrevIndex(bool NewValue) { |
| 110 WriteFlags.setWriteBadAbbrevIndex(NewValue); |
| 111 } |
| 112 |
91 protected: | 113 protected: |
92 // The bitcode records being munged. | 114 // The bitcode records being munged. |
93 NaClMungedBitcode MungedBitcode; | 115 NaClMungedBitcode MungedBitcode; |
94 // The value used as record terminator. | 116 // The value used as record terminator. |
95 uint64_t RecordTerminator; | 117 uint64_t RecordTerminator; |
96 // The block ID associated with the block being written. | |
97 int WriteBlockID; | |
98 // The SetBID for the blockinfo block. | |
99 int SetBID; | |
100 // The results buffer of the last dump. | 118 // The results buffer of the last dump. |
101 std::string DumpResults; | 119 std::string DumpResults; |
102 // The memory buffer containing the munged input. | 120 // The memory buffer containing the munged input. |
103 std::unique_ptr<MemoryBuffer> MungedInput; | 121 std::unique_ptr<MemoryBuffer> MungedInput; |
104 // The stream containing errors and the objdump of the generated bitcode file. | 122 // The stream containing errors and the objdump of the generated bitcode file. |
105 raw_ostream *DumpStream; | 123 raw_ostream *DumpStream; |
106 // The bitstream writer to use to generate the bitcode file. | |
107 NaClBitstreamWriter *Writer; | |
108 // True if any errors were reported. | 124 // True if any errors were reported. |
109 bool FoundErrors; | 125 bool FoundErrors; |
110 // The buffer to hold the generated fatal message. | |
111 std::string FatalBuffer; | |
112 // The stream to write the fatal message to. | |
113 raw_string_ostream FatalStream; | |
114 // The stack of maximum abbreviation indices allowed by block enter record. | |
115 SmallVector<uint64_t, 3> AbbrevIndexLimitStack; | |
116 // The buffer for the contents of the munged input. | 126 // The buffer for the contents of the munged input. |
117 SmallVector<char, 1024> MungedInputBuffer; | 127 SmallVector<char, 1024> MungedInputBuffer; |
| 128 /// The write flags to use when writing bitcode. |
| 129 NaClMungedBitcode::WriteFlags WriteFlags; |
| 130 // Flag to redirect dump stream if running death test. |
| 131 bool RunAsDeathTest; |
118 | 132 |
119 // Records that an error occurred, and returns stream to print error | 133 // Records that an error occurred, and returns stream to print error |
120 // message to. | 134 // message to. |
121 raw_ostream &Error() { | 135 raw_ostream &Error() { |
122 FoundErrors = true; | 136 FoundErrors = true; |
123 return *DumpStream << "Error: "; | 137 return getDumpStream() << "Error: "; |
124 } | |
125 | |
126 // Returns stream to print fatal error message to. | |
127 // Note: Once the fatal error message has been dumped to the stream, | |
128 // one must call ReportFatalError to display the error and terminate | |
129 // execution. | |
130 raw_ostream &Fatal() { | |
131 return FatalStream << "Fatal: "; | |
132 } | |
133 | |
134 // Displays the fatal error message and exits the program. | |
135 void ReportFatalError() { | |
136 report_fatal_error(FatalStream.str()); | |
137 } | 138 } |
138 | 139 |
139 // Returns the lines containing the given Substring, from the string | 140 // Returns the lines containing the given Substring, from the string |
140 // getTestResults(). If MustBePrefix, then Substring must match at | 141 // getTestResults(). If MustBePrefix, then Substring must match at |
141 // the beginning of the line. | 142 // the beginning of the line. |
142 std::string getLinesWithTextMatch(const std::string &Substring, | 143 std::string getLinesWithTextMatch(const std::string &Substring, |
143 bool MustBePrefix = false) const; | 144 bool MustBePrefix = false) const; |
144 | 145 |
145 // Writes out munged bitcode records. | 146 // Returns the log stream to use. When running death tests, redirect output |
146 void writeMungedBitcode(const NaClMungedBitcode &Bitcode, bool AddHeader); | 147 // to the error stream (rather than buffering in DumpStream), so that |
147 | 148 // the output can be seen in gtest death tests. |
148 // Emits the given record to the bitcode file. | 149 raw_ostream &getDumpStream() const { |
149 void emitRecord(const NaClBitcodeAbbrevRecord &Record); | 150 return RunAsDeathTest ? errs() : *DumpStream; |
150 | 151 } |
151 // Converts the abbreviation record to the corresponding abbreviation. | |
152 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); | |
153 }; | 152 }; |
154 | 153 |
155 /// Class to run tests for function llvm::NaClObjDump. | 154 /// Class to run tests for function llvm::NaClObjDump. |
156 class NaClObjDumpMunger : public NaClBitcodeMunger { | 155 class NaClObjDumpMunger : public NaClBitcodeMunger { |
157 public: | 156 public: |
158 | 157 |
159 /// Creates a bitcode munger, based on the given array of values. | 158 /// Creates a bitcode munger, based on the given array of values. |
160 NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize, | 159 NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize, |
161 uint64_t RecordTerminator) | 160 uint64_t RecordTerminator) |
162 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator), | 161 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} |
163 RunAsDeathTest(false) {} | |
164 | 162 |
165 /// Runs function NaClObjDump on the sequence of records associated | 163 /// Runs function NaClObjDump on the sequence of records associated |
166 /// with the instance. The memory buffer containing the bitsequence | 164 /// with the instance. The memory buffer containing the bitsequence |
167 /// associated with the record is automatically generated, and | 165 /// associated with the record is automatically generated, and |
168 /// passed to NaClObjDump. TestName is the name associated with the | 166 /// passed to NaClObjDump. TestName is the name associated with the |
169 /// memory buffer. If AddHeader is true, test assumes that the | 167 /// memory buffer. If AddHeader is true, test assumes that the |
170 /// sequence of records doesn't contain a header record, and the | 168 /// sequence of records doesn't contain a header record, and the |
171 /// test should add one. Arguments NoRecords and NoAssembly are | 169 /// test should add one. Arguments NoRecords and NoAssembly are |
172 /// passed to NaClObjDump. Returns true if test succeeds without | 170 /// passed to NaClObjDump. Returns true if test succeeds without |
173 /// errors. | 171 /// errors. |
174 bool runTestWithFlags(const char *TestName, bool AddHeader, | 172 bool runTestWithFlags(const char *TestName, bool AddHeader, |
175 bool NoRecords, bool NoAssembly) { | 173 bool NoRecords, bool NoAssembly) { |
176 uint64_t NoMunges[] = {0}; | 174 uint64_t NoMunges[] = {0}; |
177 return runTestWithFlags(TestName, NoMunges, 0, AddHeader, NoRecords, | 175 return runTestWithFlags(TestName, NoMunges, 0, AddHeader, NoRecords, |
178 NoAssembly); | 176 NoAssembly); |
179 } | 177 } |
180 | 178 |
181 /// Returns true if running as death test. | |
182 bool getRunAsDeathTest() const { | |
183 return RunAsDeathTest; | |
184 } | |
185 | |
186 /// Sets death test flag. When true, output will be redirected to | |
187 /// the errs() (rather than buffered) so that the test can be | |
188 /// debugged. | |
189 void setRunAsDeathTest(bool NewValue) { | |
190 RunAsDeathTest = NewValue; | |
191 } | |
192 | |
193 /// Same as above except it runs function NaClObjDump with flags | 179 /// Same as above except it runs function NaClObjDump with flags |
194 /// NoRecords and NoAssembly set to false, and AddHeader set to true. | 180 /// NoRecords and NoAssembly set to false, and AddHeader set to true. |
195 bool runTest(const char *TestName) { | 181 bool runTest(const char *TestName) { |
196 return runTestWithFlags(TestName, true, false, false); | 182 return runTestWithFlags(TestName, true, false, false); |
197 } | 183 } |
198 | 184 |
199 /// Same as runTest, but only print out assembly and errors. | 185 /// Same as runTest, but only print out assembly and errors. |
200 bool runTestForAssembly(const char *TestName) { | 186 bool runTestForAssembly(const char *TestName) { |
201 return runTestWithFlags(TestName, true, true, false); | 187 return runTestWithFlags(TestName, true, true, false); |
202 } | 188 } |
(...skipping 25 matching lines...) Expand all Loading... |
228 | 214 |
229 bool runTestForAssembly(const char* TestName, const uint64_t Munges[], | 215 bool runTestForAssembly(const char* TestName, const uint64_t Munges[], |
230 size_t MungesSize) { | 216 size_t MungesSize) { |
231 return runTestWithFlags(TestName, Munges, MungesSize, true, true, false); | 217 return runTestWithFlags(TestName, Munges, MungesSize, true, true, false); |
232 } | 218 } |
233 | 219 |
234 bool runTestForErrors(const char* TestName, const uint64_t Munges[], | 220 bool runTestForErrors(const char* TestName, const uint64_t Munges[], |
235 size_t MungesSize) { | 221 size_t MungesSize) { |
236 return runTestWithFlags(TestName, Munges, MungesSize, true, true, true); | 222 return runTestWithFlags(TestName, Munges, MungesSize, true, true, true); |
237 } | 223 } |
238 | |
239 private: | |
240 // Flag to redirect dump stream if running death test. | |
241 bool RunAsDeathTest; | |
242 | |
243 }; | 224 }; |
244 | 225 |
245 // Class to run tests for function NaClParseBitcodeFile. | 226 // Class to run tests for function NaClParseBitcodeFile. |
246 class NaClParseBitcodeMunger : public NaClBitcodeMunger { | 227 class NaClParseBitcodeMunger : public NaClBitcodeMunger { |
247 public: | 228 public: |
248 NaClParseBitcodeMunger(const uint64_t Records[], size_t RecordsSize, | 229 NaClParseBitcodeMunger(const uint64_t Records[], size_t RecordsSize, |
249 uint64_t RecordTerminator) | 230 uint64_t RecordTerminator) |
250 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} | 231 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} |
251 | 232 |
252 /// Runs function llvm::NaClParseBitcodeFile, and puts error messages | 233 /// Runs function llvm::NaClParseBitcodeFile, and puts error messages |
(...skipping 20 matching lines...) Expand all Loading... |
273 | 254 |
274 bool runTest(const char* TestName) { | 255 bool runTest(const char* TestName) { |
275 uint64_t NoMunges[] = {0}; | 256 uint64_t NoMunges[] = {0}; |
276 return runTest(TestName, NoMunges, 0); | 257 return runTest(TestName, NoMunges, 0); |
277 } | 258 } |
278 }; | 259 }; |
279 | 260 |
280 } // end namespace llvm. | 261 } // end namespace llvm. |
281 | 262 |
282 #endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H | 263 #endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H |
OLD | NEW |