blob: 095ee0665e1a1870fc6aea443faff5723a2815be [file] [log] [blame]
Heejin Ahn04c48942018-06-25 01:20:21 +00001//=== WebAssemblyExceptionInfoTest.cpp - WebAssebmlyExceptionInfo unit tests =//
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#include "WebAssemblyExceptionInfo.h"
11#include "llvm/CodeGen/MIRParser/MIRParser.h"
12#include "llvm/CodeGen/MachineDominanceFrontier.h"
13#include "llvm/CodeGen/MachineDominators.h"
14#include "llvm/CodeGen/MachineModuleInfo.h"
15#include "llvm/Support/SourceMgr.h"
16#include "llvm/Support/TargetRegistry.h"
17#include "llvm/Support/TargetSelect.h"
18#include "llvm/Target/TargetMachine.h"
19#include "gtest/gtest.h"
20
21using namespace llvm;
22
23namespace {
24
Matthias Braun3d849f62018-11-05 23:49:13 +000025std::unique_ptr<LLVMTargetMachine> createTargetMachine() {
Heejin Ahn04c48942018-06-25 01:20:21 +000026 auto TT(Triple::normalize("wasm32-unknown-unknown"));
27 std::string CPU("");
28 std::string FS("");
29
30 LLVMInitializeWebAssemblyTargetInfo();
31 LLVMInitializeWebAssemblyTarget();
32 LLVMInitializeWebAssemblyTargetMC();
33
34 std::string Error;
35 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
36 assert(TheTarget);
37
Matthias Braun3d849f62018-11-05 23:49:13 +000038 return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>(
39 TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None, None,
40 CodeGenOpt::Default)));
Heejin Ahn04c48942018-06-25 01:20:21 +000041}
42
43std::unique_ptr<Module> parseMIR(LLVMContext &Context,
44 std::unique_ptr<MIRParser> &MIR,
45 const TargetMachine &TM, StringRef MIRCode,
46 const char *FuncName, MachineModuleInfo &MMI) {
47 SMDiagnostic Diagnostic;
48 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
49 MIR = createMIRParser(std::move(MBuffer), Context);
50 if (!MIR)
51 return nullptr;
52
53 std::unique_ptr<Module> M = MIR->parseIRModule();
54 if (!M)
55 return nullptr;
56
57 M->setDataLayout(TM.createDataLayout());
58
59 if (MIR->parseMachineFunctions(*M, MMI))
60 return nullptr;
61
62 return M;
63}
64
65} // namespace
66
67TEST(WebAssemblyExceptionInfoTest, TEST0) {
Matthias Braun3d849f62018-11-05 23:49:13 +000068 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
Heejin Ahn04c48942018-06-25 01:20:21 +000069 ASSERT_TRUE(TM);
70
71 StringRef MIRString = R"MIR(
72--- |
73 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
74 target triple = "wasm32-unknown-unknown"
75
76 declare i32 @__gxx_wasm_personality_v0(...)
77
78 define hidden void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
79 unreachable
80 }
81
82...
83---
84name: test0
85liveins:
86 - { reg: '$arguments' }
87 - { reg: '$value_stack' }
88body: |
89 bb.0:
90 successors: %bb.1, %bb.2
91 liveins: $arguments, $value_stack
92 BR %bb.1, implicit-def dead $arguments
93
94 bb.1:
95 ; predecessors: %bb.0
96 successors: %bb.7
97 liveins: $value_stack
98 BR %bb.7, implicit-def $arguments
99
100 bb.2 (landing-pad):
101 ; predecessors: %bb.0
102 successors: %bb.3, %bb.9
103 liveins: $value_stack
104 CATCH_ALL implicit-def $arguments
105 CLEANUPRET implicit-def dead $arguments
106
107 bb.3 (landing-pad):
108 ; predecessors: %bb.2
109 successors: %bb.4, %bb.6
110 liveins: $value_stack
111 CATCH_ALL implicit-def $arguments
112 BR_IF %bb.4, %58:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
113 BR %bb.6, implicit-def $arguments
114
115 bb.4:
116 ; predecessors: %bb.3
117 successors: %bb.5, %bb.8
118 liveins: $value_stack
119 BR %bb.5, implicit-def dead $arguments
120
121 bb.5:
122 ; predecessors: %bb.4
123 successors: %bb.7
124 liveins: $value_stack
125 CATCHRET %bb.7, %bb.0, implicit-def dead $arguments
126
127 bb.6:
128 ; predecessors: %bb.3
129 successors: %bb.10, %bb.9
130 liveins: $value_stack
131 BR %bb.10, implicit-def dead $arguments
132
133 bb.7:
134 ; predecessors: %bb.5, %bb.1
135 liveins: $value_stack
136 RETURN_VOID implicit-def $arguments
137
138 bb.8 (landing-pad):
139 ; predecessors: %bb.4
140 successors: %bb.9
141 liveins: $value_stack
142 CATCH_ALL implicit-def $arguments
143 CLEANUPRET implicit-def dead $arguments
144
145 bb.9 (landing-pad):
146 ; predecessors: %bb.2, %bb.6, %bb.8
147 liveins: $value_stack
148 CATCH_ALL implicit-def $arguments
149 CLEANUPRET implicit-def dead $arguments
150
151 bb.10:
152 ; predecessors: %bb.6
153 liveins: $value_stack
154 UNREACHABLE implicit-def $arguments
155)MIR";
156
157 LLVMContext Context;
158 std::unique_ptr<MIRParser> MIR;
159 MachineModuleInfo MMI(TM.get());
160 std::unique_ptr<Module> M =
161 parseMIR(Context, MIR, *TM, MIRString, "test0", MMI);
162 ASSERT_TRUE(M);
163
164 Function *F = M->getFunction("test0");
165 auto *MF = MMI.getMachineFunction(*F);
166 ASSERT_TRUE(MF);
167
168 WebAssemblyExceptionInfo WEI;
169 MachineDominatorTree MDT;
170 MachineDominanceFrontier MDF;
171 MDT.runOnMachineFunction(*MF);
172 MDF.getBase().analyze(MDT.getBase());
173 WEI.recalculate(MDT, MDF);
174
175 // Exception info structure:
176 // |- bb2 (ehpad), bb3, bb4, bb5, bb6, bb8, bb9, bb10
177 // |- bb3 (ehpad), bb4, bb5, bb6, bb8, bb10
178 // |- bb8 (ehpad)
179 // |- bb9 (ehpad)
180
181 auto *MBB2 = MF->getBlockNumbered(2);
182 auto *WE0 = WEI.getExceptionFor(MBB2);
183 ASSERT_TRUE(WE0);
184 EXPECT_EQ(WE0->getEHPad(), MBB2);
185 EXPECT_EQ(WE0->getParentException(), nullptr);
186 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1);
187
188 auto *MBB3 = MF->getBlockNumbered(3);
189 auto *WE0_0 = WEI.getExceptionFor(MBB3);
190 ASSERT_TRUE(WE0_0);
191 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
192 EXPECT_EQ(WE0_0->getParentException(), WE0);
193 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2);
194
195 auto *MBB4 = MF->getBlockNumbered(4);
196 WE0_0 = WEI.getExceptionFor(MBB4);
197 ASSERT_TRUE(WE0_0);
198 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
199
200 auto *MBB5 = MF->getBlockNumbered(5);
201 WE0_0 = WEI.getExceptionFor(MBB5);
202 ASSERT_TRUE(WE0_0);
203 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
204
205 auto *MBB6 = MF->getBlockNumbered(6);
206 WE0_0 = WEI.getExceptionFor(MBB6);
207 ASSERT_TRUE(WE0_0);
208 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
209
210 auto *MBB10 = MF->getBlockNumbered(10);
211 WE0_0 = WEI.getExceptionFor(MBB10);
212 ASSERT_TRUE(WE0_0);
213 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
214
215 auto *MBB8 = MF->getBlockNumbered(8);
216 auto *WE0_0_0 = WEI.getExceptionFor(MBB8);
217 ASSERT_TRUE(WE0_0_0);
218 EXPECT_EQ(WE0_0_0->getEHPad(), MBB8);
219 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0);
220 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3);
221
222 auto *MBB9 = MF->getBlockNumbered(9);
223 auto *WE0_1 = WEI.getExceptionFor(MBB9);
224 ASSERT_TRUE(WE0_1);
225 EXPECT_EQ(WE0_1->getEHPad(), MBB9);
226 EXPECT_EQ(WE0_1->getParentException(), WE0);
227 EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2);
228}
229
230TEST(WebAssemblyExceptionInfoTest, TEST1) {
Matthias Braun3d849f62018-11-05 23:49:13 +0000231 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
Heejin Ahn04c48942018-06-25 01:20:21 +0000232 ASSERT_TRUE(TM);
233
234 StringRef MIRString = R"MIR(
235--- |
236 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
237 target triple = "wasm32-unknown-unknown"
238
239 declare i32 @__gxx_wasm_personality_v0(...)
240
241 define hidden void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
242 unreachable
243 }
244
245...
246---
247name: test1
248liveins:
249 - { reg: '$arguments' }
250 - { reg: '$value_stack' }
251body: |
252 bb.0:
253 successors: %bb.9, %bb.1
254 liveins: $arguments, $value_stack
255 BR %bb.9, implicit-def dead $arguments
256
257 bb.1 (landing-pad):
258 ; predecessors: %bb.0
259 successors: %bb.2, %bb.8
260 liveins: $value_stack
261 %52:i32 = CATCH_I32 0, implicit-def dead $arguments
262 BR_IF %bb.2, %32:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
263 BR %bb.8, implicit-def $arguments
264
265 bb.2:
266 ; predecessors: %bb.1
267 successors: %bb.7, %bb.3, %bb.11
268 liveins: $value_stack
269 BR %bb.7, implicit-def dead $arguments
270
271 bb.3 (landing-pad):
272 ; predecessors: %bb.2
273 successors: %bb.4, %bb.6
274 liveins: $value_stack
275 CATCH_ALL implicit-def $arguments
276 BR_IF %bb.4, %43:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
277 BR %bb.6, implicit-def $arguments
278
279 bb.4:
280 ; predecessors: %bb.3
281 successors: %bb.5, %bb.10
282 liveins: $value_stack
283 BR %bb.5, implicit-def dead $arguments
284
285 bb.5:
286 ; predecessors: %bb.4
287 successors: %bb.7(0x80000000); %bb.7(200.00%)
288 liveins: $value_stack
289 CATCHRET %bb.7, %bb.1, implicit-def dead $arguments
290
291 bb.6:
292 ; predecessors: %bb.3
293 successors: %bb.12, %bb.11
294 liveins: $value_stack
295 BR %bb.12, implicit-def dead $arguments
296
297 bb.7:
298 ; predecessors: %bb.2, %bb.5
299 successors: %bb.9(0x80000000); %bb.9(200.00%)
300 liveins: $value_stack
301 CATCHRET %bb.9, %bb.0, implicit-def dead $arguments
302
303 bb.8:
304 ; predecessors: %bb.1
305 liveins: $value_stack
306 UNREACHABLE implicit-def $arguments
307
308 bb.9:
309 ; predecessors: %bb.0, %bb.7
310 liveins: $value_stack
311 RETURN_VOID implicit-def $arguments
312
313 bb.10 (landing-pad):
314 ; predecessors: %bb.4
315 successors: %bb.11
316 liveins: $value_stack
317 CATCH_ALL implicit-def $arguments
318 CLEANUPRET implicit-def dead $arguments
319
320 bb.11 (landing-pad):
321 ; predecessors: %bb.2, %bb.6, %bb.10
322 liveins: $value_stack
323 CATCH_ALL implicit-def $arguments
324 CLEANUPRET implicit-def dead $arguments
325
326 bb.12:
327 ; predecessors: %bb.6
328 liveins: $value_stack
329 UNREACHABLE implicit-def $arguments
330)MIR";
331
332 LLVMContext Context;
333 std::unique_ptr<MIRParser> MIR;
334 MachineModuleInfo MMI(TM.get());
335 std::unique_ptr<Module> M =
336 parseMIR(Context, MIR, *TM, MIRString, "test1", MMI);
337 ASSERT_TRUE(M);
338
339 Function *F = M->getFunction("test1");
340 auto *MF = MMI.getMachineFunction(*F);
341 ASSERT_TRUE(MF);
342
343 WebAssemblyExceptionInfo WEI;
344 MachineDominatorTree MDT;
345 MachineDominanceFrontier MDF;
346 MDT.runOnMachineFunction(*MF);
347 MDF.getBase().analyze(MDT.getBase());
348 WEI.recalculate(MDT, MDF);
349
350 // Exception info structure:
351 // |- bb1 (ehpad), bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb10, bb11, bb12
352 // |- bb3 (ehpad), bb4, bb5, bb6, bb10, bb12
353 // |- bb10 (ehpad)
354 // |- bb11 (ehpad)
355
356 auto *MBB1 = MF->getBlockNumbered(1);
357 auto *WE0 = WEI.getExceptionFor(MBB1);
358 ASSERT_TRUE(WE0);
359 EXPECT_EQ(WE0->getEHPad(), MBB1);
360 EXPECT_EQ(WE0->getParentException(), nullptr);
361 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1);
362
363 auto *MBB2 = MF->getBlockNumbered(2);
364 WE0 = WEI.getExceptionFor(MBB2);
365 ASSERT_TRUE(WE0);
366 EXPECT_EQ(WE0->getEHPad(), MBB1);
367
368 auto *MBB7 = MF->getBlockNumbered(7);
369 WE0 = WEI.getExceptionFor(MBB7);
370 ASSERT_TRUE(WE0);
371 EXPECT_EQ(WE0->getEHPad(), MBB1);
372
373 auto *MBB8 = MF->getBlockNumbered(8);
374 WE0 = WEI.getExceptionFor(MBB8);
375 ASSERT_TRUE(WE0);
376 EXPECT_EQ(WE0->getEHPad(), MBB1);
377
378 auto *MBB3 = MF->getBlockNumbered(3);
379 auto *WE0_0 = WEI.getExceptionFor(MBB3);
380 ASSERT_TRUE(WE0_0);
381 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
382 EXPECT_EQ(WE0_0->getParentException(), WE0);
383 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2);
384
385 auto *MBB4 = MF->getBlockNumbered(4);
386 WE0_0 = WEI.getExceptionFor(MBB4);
387 ASSERT_TRUE(WE0_0);
388 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
389
390 auto *MBB5 = MF->getBlockNumbered(5);
391 WE0_0 = WEI.getExceptionFor(MBB5);
392 ASSERT_TRUE(WE0_0);
393 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
394
395 auto *MBB6 = MF->getBlockNumbered(6);
396 WE0_0 = WEI.getExceptionFor(MBB6);
397 ASSERT_TRUE(WE0_0);
398 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
399
400 auto *MBB12 = MF->getBlockNumbered(12);
401 WE0_0 = WEI.getExceptionFor(MBB12);
402 ASSERT_TRUE(WE0_0);
403 EXPECT_EQ(WE0_0->getEHPad(), MBB3);
404
405 auto *MBB10 = MF->getBlockNumbered(10);
406 auto *WE0_0_0 = WEI.getExceptionFor(MBB10);
407 ASSERT_TRUE(WE0_0_0);
408 EXPECT_EQ(WE0_0_0->getEHPad(), MBB10);
409 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0);
410 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3);
411
412 auto *MBB11 = MF->getBlockNumbered(11);
413 auto *WE0_1 = WEI.getExceptionFor(MBB11);
414 ASSERT_TRUE(WE0_1);
415 EXPECT_EQ(WE0_1->getEHPad(), MBB11);
416 EXPECT_EQ(WE0_1->getParentException(), WE0);
417 EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2);
418}
419
420// Terminate pad test
421TEST(WebAssemblyExceptionInfoTest, TEST2) {
Matthias Braun3d849f62018-11-05 23:49:13 +0000422 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
Heejin Ahn04c48942018-06-25 01:20:21 +0000423 ASSERT_TRUE(TM);
424
425 StringRef MIRString = R"MIR(
426--- |
427 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
428 target triple = "wasm32-unknown-unknown"
429
430 declare i32 @__gxx_wasm_personality_v0(...)
431 declare void @_ZSt9terminatev()
432 declare void @__clang_call_terminate(i8*)
433
434 define hidden void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
435 unreachable
436 }
437
438...
439---
440name: test2
441liveins:
442 - { reg: '$arguments' }
443 - { reg: '$value_stack' }
444body: |
445 bb.0:
446 successors: %bb.3, %bb.1
447 BR %bb.3, implicit-def dead $arguments
448
449 bb.1 (landing-pad):
450 ; predecessors: %bb.0
451 successors: %bb.2, %bb.4
452 %3:i32 = CATCH_I32 0, implicit-def dead $arguments
453 BR %bb.2, implicit-def dead $arguments
454
455 bb.2:
456 ; predecessors: %bb.1
457 successors: %bb.3(0x80000000); %bb.3(200.00%)
458 CATCHRET %bb.3, %bb.0, implicit-def dead $arguments
459
460 bb.3:
461 ; predecessors: %bb.0, %bb.2
462 RETURN_VOID implicit-def $arguments
463
464 bb.4 (landing-pad):
465 ; predecessors: %bb.1
466 successors: %bb.5, %bb.6
467 CATCH_ALL implicit-def $arguments
468 BR %bb.5, implicit-def dead $arguments
469
470 bb.5:
471 ; predecessors: %bb.4
472 CLEANUPRET implicit-def dead $arguments
473
474 bb.6 (landing-pad):
475 ; predecessors: %bb.4
476 successors: %bb.7(0x80000000); %bb.7(200.00%)
477 %6:i32 = CATCH_I32 0, implicit-def dead $arguments
478 CALL_VOID @__clang_call_terminate, %7:i32, implicit-def $arguments
479 UNREACHABLE implicit-def $arguments
480
481 bb.7 (landing-pad):
482 ; predecessors: %bb.6
483 CATCH_ALL implicit-def $arguments
484 CALL_VOID @_ZSt9terminatev, implicit-def $arguments
485 UNREACHABLE implicit-def $arguments
486)MIR";
487
488 LLVMContext Context;
489 std::unique_ptr<MIRParser> MIR;
490 MachineModuleInfo MMI(TM.get());
491 std::unique_ptr<Module> M =
492 parseMIR(Context, MIR, *TM, MIRString, "test2", MMI);
493 ASSERT_TRUE(M);
494
495 Function *F = M->getFunction("test2");
496 auto *MF = MMI.getMachineFunction(*F);
497 ASSERT_TRUE(MF);
498
499 WebAssemblyExceptionInfo WEI;
500 MachineDominatorTree MDT;
501 MachineDominanceFrontier MDF;
502 MDT.runOnMachineFunction(*MF);
503 MDF.getBase().analyze(MDT.getBase());
504 WEI.recalculate(MDT, MDF);
505
506 // Exception info structure:
507 // |- bb1 (ehpad), bb2, bb4, bb5, bb6, bb7
508 // |- bb4 (ehpad), bb5, bb6, bb7
509 // |- bb6 (ehpad), bb7
510 //
511 // Here, bb6 is a terminate pad with a 'catch' instruction, and bb7 is a
512 // terminate pad with a 'catch_all' instruction, In this case we put bb6 and
513 // bb7 into one exception.
514
515 auto *MBB1 = MF->getBlockNumbered(1);
516 auto *WE0 = WEI.getExceptionFor(MBB1);
517 ASSERT_TRUE(WE0);
518 EXPECT_EQ(WE0->getEHPad(), MBB1);
519 EXPECT_EQ(WE0->getParentException(), nullptr);
520 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1);
521
522 auto *MBB2 = MF->getBlockNumbered(2);
523 WE0 = WEI.getExceptionFor(MBB2);
524 ASSERT_TRUE(WE0);
525 EXPECT_EQ(WE0->getEHPad(), MBB1);
526
527 auto *MBB4 = MF->getBlockNumbered(4);
528 auto *WE0_0 = WEI.getExceptionFor(MBB4);
529 ASSERT_TRUE(WE0_0);
530 EXPECT_EQ(WE0_0->getEHPad(), MBB4);
531 EXPECT_EQ(WE0_0->getParentException(), WE0);
532 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2);
533
534 auto *MBB5 = MF->getBlockNumbered(5);
535 WE0_0 = WEI.getExceptionFor(MBB5);
536 ASSERT_TRUE(WE0_0);
537 EXPECT_EQ(WE0_0->getEHPad(), MBB4);
538
539 auto *MBB6 = MF->getBlockNumbered(6);
540 auto *WE0_0_0 = WEI.getExceptionFor(MBB6);
541 ASSERT_TRUE(WE0_0_0);
542 EXPECT_EQ(WE0_0_0->getEHPad(), MBB6);
543 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0);
544 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3);
545
546 auto *MBB7 = MF->getBlockNumbered(7);
547 WE0_0_0 = WEI.getExceptionFor(MBB7);
548 ASSERT_TRUE(WE0_0_0);
549 EXPECT_EQ(WE0_0_0->getEHPad(), MBB6);
550}