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
22using namespace llvm;
23using namespace naclmungetest;
24
25namespace {
26
27// The ParseError constant is passed to the BitcodeMunger to prevent translation
28// when we expect a Parse error.
29constexpr bool ParseError = true;
30
31// Note: alignment stored as 0 or log2(Alignment)+1.
32uint64_t getEncAlignPower(unsigned Power) {
33  return Power + 1;
34}
35uint64_t getEncAlignZero() { return 0; }
36
37/// Test how we report a call arg that refers to nonexistent call argument
38TEST(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.
78TEST(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.
147TEST(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.
228TEST(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.
309TEST(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