• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- unittest/IceParseInstsTest.cpp - test instruction errors -----------===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include <string>
11 
12 #pragma clang diagnostic push
13 #pragma clang diagnostic ignored "-Wunused-parameter"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
16 #include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
17 #pragma clang diagnostic pop
18 
19 #include "BitcodeMunge.h"
20 #include "unittests/Bitcode/NaClMungeTest.h"
21 
22 using namespace llvm;
23 using namespace naclmungetest;
24 
25 namespace {
26 
27 // The ParseError constant is passed to the BitcodeMunger to prevent translation
28 // when we expect a Parse error.
29 constexpr bool ParseError = true;
30 
31 // Note: alignment stored as 0 or log2(Alignment)+1.
getEncAlignPower(unsigned Power)32 uint64_t getEncAlignPower(unsigned Power) {
33   return Power + 1;
34 }
getEncAlignZero()35 uint64_t getEncAlignZero() { return 0; }
36 
37 /// Test how we report a call arg that refers to nonexistent call argument
TEST(IceParseInstsTest,NonexistentCallArg)38 TEST(IceParseInstsTest, NonexistentCallArg) {
39   const uint64_t BitcodeRecords[] = {
40     1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, 2, Terminator,
41     1, naclbitc::BLK_CODE_ENTER, naclbitc::TYPE_BLOCK_ID_NEW, 2, Terminator,
42     3, naclbitc::TYPE_CODE_NUMENTRY, 3, Terminator,
43     3, naclbitc::TYPE_CODE_INTEGER, 32, Terminator,
44     3, naclbitc::TYPE_CODE_VOID, Terminator,
45     3, naclbitc::TYPE_CODE_FUNCTION, 0, 1, 0, 0, Terminator,
46     0, naclbitc::BLK_CODE_EXIT, Terminator,
47     3, naclbitc::MODULE_CODE_FUNCTION, 2, 0, 1, 3, Terminator,
48     3, naclbitc::MODULE_CODE_FUNCTION, 2, 0, 0, 3, Terminator,
49     1, naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 2, Terminator,
50     3, naclbitc::FUNC_CODE_DECLAREBLOCKS, 1, Terminator,
51       // Note: 100 is a bad value index in next line.
52     3, naclbitc::FUNC_CODE_INST_CALL, 0, 4, 2, 100, Terminator,
53     3, naclbitc::FUNC_CODE_INST_RET, Terminator,
54     0, naclbitc::BLK_CODE_EXIT, Terminator,
55     0, naclbitc::BLK_CODE_EXIT, Terminator
56   };
57 
58   // Show bitcode objdump for BitcodeRecords.
59   NaClObjDumpMunger DumpMunger(ARRAY_TERM(BitcodeRecords));
60   EXPECT_FALSE(DumpMunger.runTest());
61   EXPECT_EQ("      66:4|    3: <34, 0, 4, 2, 100>    |    call void @f0(i32 "
62             "%p0, i32 @f0);\n"
63             "Error(66:4): Invalid relative value id: 100 (Must be <= 4)\n",
64             DumpMunger.getLinesWithSubstring("66:4"));
65 
66   // Show that we get appropriate error when parsing in Subzero.
67   IceTest::SubzeroBitcodeMunger Munger(ARRAY_TERM(BitcodeRecords));
68   EXPECT_FALSE(Munger.runTest(ParseError));
69   EXPECT_EQ("Error(66:4): Invalid function record: <34 0 4 2 100>\n",
70             Munger.getTestResults());
71 
72   // Show that we generate a fatal error when not allowing error recovery.
73   Ice::ClFlags::Flags.setAllowErrorRecovery(false);
74   EXPECT_DEATH(Munger.runTest(ParseError), ".*ERROR: Unable to continue.*");
75 }
76 
77 /// Test how we recognize alignments in alloca instructions.
TEST(IceParseInstsTests,AllocaAlignment)78 TEST(IceParseInstsTests, AllocaAlignment) {
79   const uint64_t BitcodeRecords[] = {
80     1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, 2, Terminator,
81     1,   naclbitc::BLK_CODE_ENTER, naclbitc::TYPE_BLOCK_ID_NEW, 2, Terminator,
82     3,     naclbitc::TYPE_CODE_NUMENTRY, 4, Terminator,
83     3,     naclbitc::TYPE_CODE_INTEGER, 32, Terminator,
84     3,     naclbitc::TYPE_CODE_VOID, Terminator,
85     3,     naclbitc::TYPE_CODE_FUNCTION, 0, 1, 0, Terminator,
86     3,     naclbitc::TYPE_CODE_INTEGER, 8, Terminator,
87     0,   naclbitc::BLK_CODE_EXIT, Terminator,
88     3,   naclbitc::MODULE_CODE_FUNCTION, 2, 0, 0, 3, Terminator,
89     1,   naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 2, Terminator,
90     3,     naclbitc::FUNC_CODE_DECLAREBLOCKS, 1, Terminator,
91     3,     naclbitc::FUNC_CODE_INST_ALLOCA, 1, getEncAlignPower(0), Terminator,
92     3,     naclbitc::FUNC_CODE_INST_RET, Terminator,
93     0,   naclbitc::BLK_CODE_EXIT, Terminator,
94     0, naclbitc::BLK_CODE_EXIT, Terminator};
95 
96   const uint64_t ReplaceIndex = 11; // index for FUNC_CODE_INST_ALLOCA
97 
98   // Show text when alignment is 1.
99   NaClObjDumpMunger DumpMunger(ARRAY_TERM(BitcodeRecords));
100   EXPECT_TRUE(DumpMunger.runTest());
101   EXPECT_EQ("      62:4|    3: <19, 1, 1>            |    %v0 = alloca i8, i32 "
102             "%p0, align 1;\n",
103             DumpMunger.getLinesWithSubstring("62:4"));
104 
105   // Show that we can handle alignment of 1.
106   IceTest::SubzeroBitcodeMunger Munger(ARRAY_TERM(BitcodeRecords));
107   EXPECT_TRUE(Munger.runTest());
108 
109   // Show what happens when changing alignment to 0.
110   const uint64_t Align0[] = {
111       ReplaceIndex, NaClMungedBitcode::Replace,
112       3, naclbitc::FUNC_CODE_INST_ALLOCA, 1, getEncAlignZero(), Terminator,
113   };
114   EXPECT_TRUE(Munger.runTest(ARRAY(Align0)));
115   EXPECT_TRUE(DumpMunger.runTestForAssembly(ARRAY(Align0)));
116   EXPECT_EQ("    %v0 = alloca i8, i32 %p0, align 0;\n",
117             DumpMunger.getLinesWithSubstring("alloca"));
118 
119   // Show what happens when changing alignment to 2**30.
120   const uint64_t Align30[] = {
121       ReplaceIndex, NaClMungedBitcode::Replace,
122       3, naclbitc::FUNC_CODE_INST_ALLOCA, 1, getEncAlignPower(30), Terminator,
123   };
124   EXPECT_FALSE(Munger.runTest(ARRAY(Align30), ParseError));
125   EXPECT_EQ("Error(62:4): Invalid function record: <19 1 31>\n",
126             Munger.getTestResults());
127 
128   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align30)));
129   EXPECT_EQ("    %v0 = alloca i8, i32 %p0, align 0;\n",
130             DumpMunger.getLinesWithSubstring("alloca"));
131   EXPECT_EQ(
132       "Error(62:4): Alignment can't be greater than 2**29. Found: 2**30\n",
133       DumpMunger.getLinesWithSubstring("Error"));
134 
135   // Show what happens when changing alignment to 2**29.
136   const uint64_t Align29[] = {
137       ReplaceIndex, NaClMungedBitcode::Replace,
138       3, naclbitc::FUNC_CODE_INST_ALLOCA, 1, getEncAlignPower(29), Terminator,
139   };
140   EXPECT_TRUE(Munger.runTest(ARRAY(Align29)));
141   EXPECT_TRUE(DumpMunger.runTestForAssembly(ARRAY(Align29)));
142   EXPECT_EQ("    %v0 = alloca i8, i32 %p0, align 536870912;\n",
143             DumpMunger.getLinesWithSubstring("alloca"));
144 }
145 
146 // Test how we recognize alignments in load i32 instructions.
TEST(IceParseInstsTests,LoadI32Alignment)147 TEST(IceParseInstsTests, LoadI32Alignment) {
148   const uint64_t BitcodeRecords[] = {
149     1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, 2, Terminator,
150     1,   naclbitc::BLK_CODE_ENTER, naclbitc::TYPE_BLOCK_ID_NEW, 2, Terminator,
151     3,     naclbitc::TYPE_CODE_NUMENTRY, 2, Terminator,
152     3,     naclbitc::TYPE_CODE_INTEGER, 32, Terminator,
153     3,     naclbitc::TYPE_CODE_FUNCTION, 0, 0, 0, Terminator,
154     0,   naclbitc::BLK_CODE_EXIT, Terminator,
155     3,   naclbitc::MODULE_CODE_FUNCTION, 1, 0, 0, 3, Terminator,
156     1,   naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 2, Terminator,
157     3,     naclbitc::FUNC_CODE_DECLAREBLOCKS, 1, Terminator,
158     3,     naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(0), 0, Terminator,
159     3,     naclbitc::FUNC_CODE_INST_RET, 1, Terminator,
160     0,   naclbitc::BLK_CODE_EXIT, Terminator,
161     0, naclbitc::BLK_CODE_EXIT, Terminator};
162 
163   const uint64_t ReplaceIndex = 9; // index for FUNC_CODE_INST_LOAD
164 
165   // Show text when alignment is 1.
166   NaClObjDumpMunger DumpMunger(ARRAY_TERM(BitcodeRecords));
167   EXPECT_TRUE(DumpMunger.runTest());
168   EXPECT_EQ("      58:4|    3: <20, 1, 1, 0>         |    %v0 = load i32* %p0, "
169             "align 1;\n",
170             DumpMunger.getLinesWithSubstring("58:4"));
171   IceTest::SubzeroBitcodeMunger Munger(ARRAY_TERM(BitcodeRecords));
172   EXPECT_TRUE(Munger.runTest());
173 
174   // Show what happens when changing alignment to 0.
175   const uint64_t Align0[] = {
176       ReplaceIndex, NaClMungedBitcode::Replace,
177       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignZero(), 0, Terminator,
178   };
179   EXPECT_FALSE(Munger.runTest(ARRAY(Align0), ParseError));
180   EXPECT_EQ("Error(58:4): Invalid function record: <20 1 0 0>\n",
181             Munger.getTestResults());
182   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align0)));
183   EXPECT_EQ("    %v0 = load i32* %p0, align 0;\n"
184             "Error(58:4): load: Illegal alignment for i32. Expects: 1\n",
185             DumpMunger.getLinesWithSubstring("load"));
186 
187   // Show what happens when changing alignment to 4.
188   const uint64_t Align4[] = {
189       ReplaceIndex, NaClMungedBitcode::Replace,
190       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(2), 0, Terminator,
191   };
192   EXPECT_FALSE(Munger.runTest(ARRAY(Align4), ParseError));
193   EXPECT_EQ("Error(58:4): Invalid function record: <20 1 3 0>\n",
194             Munger.getTestResults());
195   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align4)));
196   EXPECT_EQ("    %v0 = load i32* %p0, align 4;\n"
197             "Error(58:4): load: Illegal alignment for i32. Expects: 1\n",
198             DumpMunger.getLinesWithSubstring("load"));
199 
200   // Show what happens when changing alignment to 2**29.
201   const uint64_t Align29[] = {
202       ReplaceIndex, NaClMungedBitcode::Replace,
203       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(29), 0, Terminator,
204   };
205   EXPECT_FALSE(Munger.runTest(ARRAY(Align29), ParseError));
206   EXPECT_EQ("Error(58:4): Invalid function record: <20 1 30 0>\n",
207             Munger.getTestResults());
208   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align29)));
209   EXPECT_EQ("    %v0 = load i32* %p0, align 536870912;\n"
210             "Error(58:4): load: Illegal alignment for i32. Expects: 1\n",
211             DumpMunger.getLinesWithSubstring("load"));
212 
213   // Show what happens when changing alignment to 2**30.
214   const uint64_t Align30[] = {
215       ReplaceIndex, NaClMungedBitcode::Replace,
216       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(30), 0, Terminator,
217   };
218   EXPECT_FALSE(Munger.runTest(ARRAY(Align30), ParseError));
219   EXPECT_EQ("Error(58:4): Invalid function record: <20 1 31 0>\n",
220             Munger.getTestResults());
221   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align30)));
222   EXPECT_EQ("    %v0 = load i32* %p0, align 0;\n"
223             "Error(58:4): load: Illegal alignment for i32. Expects: 1\n",
224             DumpMunger.getLinesWithSubstring("load"));
225 }
226 
227 // Test how we recognize alignments in load float instructions.
TEST(IceParseInstsTests,LoadFloatAlignment)228 TEST(IceParseInstsTests, LoadFloatAlignment) {
229   const uint64_t BitcodeRecords[] = {
230     1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, 2, Terminator,
231     1,   naclbitc::BLK_CODE_ENTER, naclbitc::TYPE_BLOCK_ID_NEW, 2, Terminator,
232     3,     naclbitc::TYPE_CODE_NUMENTRY, 3, Terminator,
233     3,     naclbitc::TYPE_CODE_FLOAT, Terminator,
234     3,     naclbitc::TYPE_CODE_INTEGER, 32, Terminator,
235     3,     naclbitc::TYPE_CODE_FUNCTION, 0, 0, 1, Terminator,
236     0,   naclbitc::BLK_CODE_EXIT, Terminator,
237     3,   naclbitc::MODULE_CODE_FUNCTION, 2, 0, 0, 3, Terminator,
238     1,   naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 2, Terminator,
239     3,     naclbitc::FUNC_CODE_DECLAREBLOCKS, 1, Terminator,
240     3,     naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(0), 0, Terminator,
241     3,     naclbitc::FUNC_CODE_INST_RET, 1, Terminator,
242     0,   naclbitc::BLK_CODE_EXIT, Terminator,
243     0, naclbitc::BLK_CODE_EXIT, Terminator};
244 
245   const uint64_t ReplaceIndex = 10; // index for FUNC_CODE_INST_LOAD
246 
247   // Show text when alignment is 1.
248   NaClObjDumpMunger DumpMunger(ARRAY_TERM(BitcodeRecords));
249   EXPECT_TRUE(DumpMunger.runTest());
250   EXPECT_EQ("      58:4|    3: <20, 1, 1, 0>         |    %v0 = load float* "
251             "%p0, align 1;\n",
252             DumpMunger.getLinesWithSubstring("58:4"));
253   IceTest::SubzeroBitcodeMunger Munger(ARRAY_TERM(BitcodeRecords));
254   EXPECT_TRUE(Munger.runTest());
255 
256   // Show what happens when changing alignment to 0.
257   const uint64_t Align0[] = {
258       ReplaceIndex, NaClMungedBitcode::Replace,
259       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignZero(), 0, Terminator,
260   };
261   EXPECT_FALSE(Munger.runTest(ARRAY(Align0), ParseError));
262   EXPECT_EQ("Error(58:4): Invalid function record: <20 1 0 0>\n",
263             Munger.getTestResults());
264   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align0)));
265   EXPECT_EQ(
266       "    %v0 = load float* %p0, align 0;\n"
267             "Error(58:4): load: Illegal alignment for float. Expects: 1 or 4\n",
268             DumpMunger.getLinesWithSubstring("load"));
269 
270   // Show what happens when changing alignment to 4.
271   const uint64_t Align4[] = {
272       ReplaceIndex, NaClMungedBitcode::Replace,
273       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(2), 0, Terminator,
274   };
275   EXPECT_TRUE(Munger.runTest(ARRAY(Align4)));
276   EXPECT_TRUE(DumpMunger.runTestForAssembly(ARRAY(Align4)));
277   EXPECT_EQ("    %v0 = load float* %p0, align 4;\n",
278             DumpMunger.getLinesWithSubstring("load"));
279 
280   const uint64_t Align29[] = {
281       ReplaceIndex, NaClMungedBitcode::Replace,
282       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(29), 0, Terminator,
283   };
284   EXPECT_FALSE(Munger.runTest(ARRAY(Align29), ParseError));
285   EXPECT_EQ("Error(58:4): Invalid function record: <20 1 30 0>\n",
286             Munger.getTestResults());
287   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align29)));
288   EXPECT_EQ(
289       "    %v0 = load float* %p0, align 536870912;\n"
290             "Error(58:4): load: Illegal alignment for float. Expects: 1 or 4\n",
291             DumpMunger.getLinesWithSubstring("load"));
292 
293   // Show what happens when changing alignment to 2**30.
294   const uint64_t Align30[] = {
295       ReplaceIndex, NaClMungedBitcode::Replace,
296       3, naclbitc::FUNC_CODE_INST_LOAD, 1, getEncAlignPower(30), 0, Terminator,
297   };
298   EXPECT_FALSE(Munger.runTest(ARRAY(Align30), ParseError));
299   EXPECT_EQ("Error(58:4): Invalid function record: <20 1 31 0>\n",
300             Munger.getTestResults());
301   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align30)));
302   EXPECT_EQ(
303       "    %v0 = load float* %p0, align 0;\n"
304             "Error(58:4): load: Illegal alignment for float. Expects: 1 or 4\n",
305             DumpMunger.getLinesWithSubstring("load"));
306 }
307 
308 // Test how we recognize alignments in store instructions.
TEST(NaClParseInstsTests,StoreAlignment)309 TEST(NaClParseInstsTests, StoreAlignment) {
310   const uint64_t BitcodeRecords[] = {
311   1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, 2, Terminator,
312   1,   naclbitc::BLK_CODE_ENTER, naclbitc::TYPE_BLOCK_ID_NEW, 2, Terminator,
313   3,     naclbitc::TYPE_CODE_NUMENTRY, 3, Terminator,
314   3,     naclbitc::TYPE_CODE_FLOAT, Terminator,
315   3,     naclbitc::TYPE_CODE_INTEGER, 32, Terminator,
316   3,     naclbitc::TYPE_CODE_FUNCTION, 0, 0, 1, 0, Terminator,
317   0,   naclbitc::BLK_CODE_EXIT, Terminator,
318   3,   naclbitc::MODULE_CODE_FUNCTION, 2, 0, 0, 3, Terminator,
319   1,   naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 2, Terminator,
320   3,     naclbitc::FUNC_CODE_DECLAREBLOCKS, 1, Terminator,
321   3,     naclbitc::FUNC_CODE_INST_STORE, 2, 1, getEncAlignPower(0), Terminator,
322   3,     naclbitc::FUNC_CODE_INST_RET, 1, Terminator,
323   0,   naclbitc::BLK_CODE_EXIT, Terminator,
324   0, naclbitc::BLK_CODE_EXIT, Terminator};
325 
326   const uint64_t ReplaceIndex = 10; // index for FUNC_CODE_INST_STORE
327 
328   // Show text when alignment is 1.
329   NaClObjDumpMunger DumpMunger(BitcodeRecords, array_lengthof(BitcodeRecords),
330                                Terminator);
331   EXPECT_TRUE(DumpMunger.runTest("Good Store Alignment 1"));
332   EXPECT_EQ("      62:4|    3: <24, 2, 1, 1>         |    store float %p1, "
333             "float* %p0, \n",
334             DumpMunger.getLinesWithSubstring("62:4"));
335   IceTest::SubzeroBitcodeMunger Munger(
336       BitcodeRecords, array_lengthof(BitcodeRecords), Terminator);
337   EXPECT_TRUE(Munger.runTest());
338 
339   // Show what happens when changing alignment to 0.
340   const uint64_t Align0[] = {
341       ReplaceIndex, NaClMungedBitcode::Replace,
342       3, naclbitc::FUNC_CODE_INST_STORE, 2, 1, getEncAlignZero(), Terminator,
343   };
344   EXPECT_FALSE(Munger.runTest(ARRAY(Align0), ParseError));
345   EXPECT_EQ("Error(62:4): Invalid function record: <24 2 1 0>\n",
346             Munger.getTestResults());
347   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align0)));
348   EXPECT_EQ(
349       "    store float %p1, float* %p0, align 0;\n"
350       "Error(62:4): store: Illegal alignment for float. Expects: 1 or 4\n",
351       DumpMunger.getLinesWithSubstring("store"));
352 
353   // Show what happens when changing alignment to 4.
354   const uint64_t Align4[] = {
355       ReplaceIndex, NaClMungedBitcode::Replace,
356       3, naclbitc::FUNC_CODE_INST_STORE, 2, 1, getEncAlignPower(2), Terminator,
357   };
358   EXPECT_TRUE(Munger.runTest(ARRAY(Align4)));
359   EXPECT_TRUE(DumpMunger.runTestForAssembly(ARRAY(Align4)));
360 
361   // Show what happens when changing alignment to 8.
362   const uint64_t Align8[] = {
363       ReplaceIndex, NaClMungedBitcode::Replace,
364       3, naclbitc::FUNC_CODE_INST_STORE, 2, 1, getEncAlignPower(3), Terminator,
365   };
366   EXPECT_FALSE(Munger.runTest(ARRAY(Align8), ParseError));
367   EXPECT_EQ("Error(62:4): Invalid function record: <24 2 1 4>\n",
368             Munger.getTestResults());
369   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align8)));
370   EXPECT_EQ(
371       "    store float %p1, float* %p0, align 8;\n"
372       "Error(62:4): store: Illegal alignment for float. Expects: 1 or 4\n",
373       DumpMunger.getLinesWithSubstring("store"));
374 
375   // Show what happens when changing alignment to 2**29.
376   const uint64_t Align29[] = {
377       ReplaceIndex, NaClMungedBitcode::Replace,
378       3, naclbitc::FUNC_CODE_INST_STORE, 2, 1, getEncAlignPower(29), Terminator,
379   };
380   EXPECT_FALSE(Munger.runTest(ARRAY(Align29), ParseError));
381   EXPECT_EQ("Error(62:4): Invalid function record: <24 2 1 30>\n",
382             Munger.getTestResults());
383   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align29)));
384   EXPECT_EQ(
385       "    store float %p1, float* %p0, align 536870912;\n"
386       "Error(62:4): store: Illegal alignment for float. Expects: 1 or 4\n",
387       DumpMunger.getLinesWithSubstring("store"));
388 
389   const uint64_t Align30[] = {
390       ReplaceIndex, NaClMungedBitcode::Replace,
391       // Note: alignment stored as 0 or log2(Alignment)+1.
392       3, naclbitc::FUNC_CODE_INST_STORE, 2, 1, getEncAlignPower(30), Terminator,
393   };
394   EXPECT_FALSE(Munger.runTest(ARRAY(Align30), ParseError));
395   EXPECT_EQ("Error(62:4): Invalid function record: <24 2 1 31>\n",
396             Munger.getTestResults());
397   EXPECT_FALSE(DumpMunger.runTestForAssembly(ARRAY(Align30)));
398   EXPECT_EQ(
399       "    store float %p1, float* %p0, align 0;\n"
400       "Error(62:4): store: Illegal alignment for float. Expects: 1 or 4\n",
401       DumpMunger.getLinesWithSubstring("store"));
402 }
403 
404 } // end of anonymous namespace
405