1 //=== WebAssemblyExceptionInfoTest.cpp - WebAssebmlyExceptionInfo unit tests =//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
25 std::unique_ptr
<TargetMachine
> createTargetMachine() {
26 auto TT(Triple::normalize("wasm32-unknown-unknown"));
30 LLVMInitializeWebAssemblyTargetInfo();
31 LLVMInitializeWebAssemblyTarget();
32 LLVMInitializeWebAssemblyTargetMC();
35 const Target
*TheTarget
= TargetRegistry::lookupTarget(TT
, Error
);
38 return std::unique_ptr
<TargetMachine
>(TheTarget
->createTargetMachine(
39 TT
, CPU
, FS
, TargetOptions(), None
, None
, CodeGenOpt::Default
));
42 std::unique_ptr
<Module
> parseMIR(LLVMContext
&Context
,
43 std::unique_ptr
<MIRParser
> &MIR
,
44 const TargetMachine
&TM
, StringRef MIRCode
,
45 const char *FuncName
, MachineModuleInfo
&MMI
) {
46 SMDiagnostic Diagnostic
;
47 std::unique_ptr
<MemoryBuffer
> MBuffer
= MemoryBuffer::getMemBuffer(MIRCode
);
48 MIR
= createMIRParser(std::move(MBuffer
), Context
);
52 std::unique_ptr
<Module
> M
= MIR
->parseIRModule();
56 M
->setDataLayout(TM
.createDataLayout());
58 if (MIR
->parseMachineFunctions(*M
, MMI
))
66 TEST(WebAssemblyExceptionInfoTest
, TEST0
) {
67 std::unique_ptr
<TargetMachine
> TM
= createTargetMachine();
70 StringRef MIRString
= R
"MIR(
72 target datalayout = "e
-m
:e
-p
:32:32-i64
:64-n32
:64-S128
"
73 target triple = "wasm32
-unknown
-unknown
"
75 declare i32 @__gxx_wasm_personality_v0(...)
77 define hidden void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
85 - { reg: '$arguments' }
86 - { reg: '$value_stack' }
89 successors: %bb.1, %bb.2
90 liveins: $arguments, $value_stack
91 BR %bb.1, implicit-def dead $arguments
97 BR %bb.7, implicit-def $arguments
100 ; predecessors: %bb.0
101 successors: %bb.3, %bb.9
102 liveins: $value_stack
103 CATCH_ALL implicit-def $arguments
104 CLEANUPRET implicit-def dead $arguments
107 ; predecessors: %bb.2
108 successors: %bb.4, %bb.6
109 liveins: $value_stack
110 CATCH_ALL implicit-def $arguments
111 BR_IF %bb.4, %58:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
112 BR %bb.6, implicit-def $arguments
115 ; predecessors: %bb.3
116 successors: %bb.5, %bb.8
117 liveins: $value_stack
118 BR %bb.5, implicit-def dead $arguments
121 ; predecessors: %bb.4
123 liveins: $value_stack
124 CATCHRET %bb.7, %bb.0, implicit-def dead $arguments
127 ; predecessors: %bb.3
128 successors: %bb.10, %bb.9
129 liveins: $value_stack
130 BR %bb.10, implicit-def dead $arguments
133 ; predecessors: %bb.5, %bb.1
134 liveins: $value_stack
135 RETURN_VOID implicit-def $arguments
138 ; predecessors: %bb.4
140 liveins: $value_stack
141 CATCH_ALL implicit-def $arguments
142 CLEANUPRET implicit-def dead $arguments
145 ; predecessors: %bb.2, %bb.6, %bb.8
146 liveins: $value_stack
147 CATCH_ALL implicit-def $arguments
148 CLEANUPRET implicit-def dead $arguments
151 ; predecessors: %bb.6
152 liveins: $value_stack
153 UNREACHABLE implicit-def $arguments
157 std::unique_ptr
<MIRParser
> MIR
;
158 MachineModuleInfo
MMI(TM
.get());
159 std::unique_ptr
<Module
> M
=
160 parseMIR(Context
, MIR
, *TM
, MIRString
, "test0", MMI
);
163 Function
*F
= M
->getFunction("test0");
164 auto *MF
= MMI
.getMachineFunction(*F
);
167 WebAssemblyExceptionInfo WEI
;
168 MachineDominatorTree MDT
;
169 MachineDominanceFrontier MDF
;
170 MDT
.runOnMachineFunction(*MF
);
171 MDF
.getBase().analyze(MDT
.getBase());
172 WEI
.recalculate(MDT
, MDF
);
174 // Exception info structure:
175 // |- bb2 (ehpad), bb3, bb4, bb5, bb6, bb8, bb9, bb10
176 // |- bb3 (ehpad), bb4, bb5, bb6, bb8, bb10
180 auto *MBB2
= MF
->getBlockNumbered(2);
181 auto *WE0
= WEI
.getExceptionFor(MBB2
);
183 EXPECT_EQ(WE0
->getEHPad(), MBB2
);
184 EXPECT_EQ(WE0
->getParentException(), nullptr);
185 EXPECT_EQ(WE0
->getExceptionDepth(), (unsigned)1);
187 auto *MBB3
= MF
->getBlockNumbered(3);
188 auto *WE0_0
= WEI
.getExceptionFor(MBB3
);
190 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
191 EXPECT_EQ(WE0_0
->getParentException(), WE0
);
192 EXPECT_EQ(WE0_0
->getExceptionDepth(), (unsigned)2);
194 auto *MBB4
= MF
->getBlockNumbered(4);
195 WE0_0
= WEI
.getExceptionFor(MBB4
);
197 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
199 auto *MBB5
= MF
->getBlockNumbered(5);
200 WE0_0
= WEI
.getExceptionFor(MBB5
);
202 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
204 auto *MBB6
= MF
->getBlockNumbered(6);
205 WE0_0
= WEI
.getExceptionFor(MBB6
);
207 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
209 auto *MBB10
= MF
->getBlockNumbered(10);
210 WE0_0
= WEI
.getExceptionFor(MBB10
);
212 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
214 auto *MBB8
= MF
->getBlockNumbered(8);
215 auto *WE0_0_0
= WEI
.getExceptionFor(MBB8
);
216 ASSERT_TRUE(WE0_0_0
);
217 EXPECT_EQ(WE0_0_0
->getEHPad(), MBB8
);
218 EXPECT_EQ(WE0_0_0
->getParentException(), WE0_0
);
219 EXPECT_EQ(WE0_0_0
->getExceptionDepth(), (unsigned)3);
221 auto *MBB9
= MF
->getBlockNumbered(9);
222 auto *WE0_1
= WEI
.getExceptionFor(MBB9
);
224 EXPECT_EQ(WE0_1
->getEHPad(), MBB9
);
225 EXPECT_EQ(WE0_1
->getParentException(), WE0
);
226 EXPECT_EQ(WE0_1
->getExceptionDepth(), (unsigned)2);
229 TEST(WebAssemblyExceptionInfoTest
, TEST1
) {
230 std::unique_ptr
<TargetMachine
> TM
= createTargetMachine();
233 StringRef MIRString
= R
"MIR(
235 target datalayout = "e
-m
:e
-p
:32:32-i64
:64-n32
:64-S128
"
236 target triple = "wasm32
-unknown
-unknown
"
238 declare i32 @__gxx_wasm_personality_v0(...)
240 define hidden void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
248 - { reg: '$arguments' }
249 - { reg: '$value_stack' }
252 successors: %bb.9, %bb.1
253 liveins: $arguments, $value_stack
254 BR %bb.9, implicit-def dead $arguments
257 ; predecessors: %bb.0
258 successors: %bb.2, %bb.8
259 liveins: $value_stack
260 %52:i32 = CATCH_I32 0, implicit-def dead $arguments
261 BR_IF %bb.2, %32:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
262 BR %bb.8, implicit-def $arguments
265 ; predecessors: %bb.1
266 successors: %bb.7, %bb.3, %bb.11
267 liveins: $value_stack
268 BR %bb.7, implicit-def dead $arguments
271 ; predecessors: %bb.2
272 successors: %bb.4, %bb.6
273 liveins: $value_stack
274 CATCH_ALL implicit-def $arguments
275 BR_IF %bb.4, %43:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
276 BR %bb.6, implicit-def $arguments
279 ; predecessors: %bb.3
280 successors: %bb.5, %bb.10
281 liveins: $value_stack
282 BR %bb.5, implicit-def dead $arguments
285 ; predecessors: %bb.4
286 successors: %bb.7(0x80000000); %bb.7(200.00%)
287 liveins: $value_stack
288 CATCHRET %bb.7, %bb.1, implicit-def dead $arguments
291 ; predecessors: %bb.3
292 successors: %bb.12, %bb.11
293 liveins: $value_stack
294 BR %bb.12, implicit-def dead $arguments
297 ; predecessors: %bb.2, %bb.5
298 successors: %bb.9(0x80000000); %bb.9(200.00%)
299 liveins: $value_stack
300 CATCHRET %bb.9, %bb.0, implicit-def dead $arguments
303 ; predecessors: %bb.1
304 liveins: $value_stack
305 UNREACHABLE implicit-def $arguments
308 ; predecessors: %bb.0, %bb.7
309 liveins: $value_stack
310 RETURN_VOID implicit-def $arguments
313 ; predecessors: %bb.4
315 liveins: $value_stack
316 CATCH_ALL implicit-def $arguments
317 CLEANUPRET implicit-def dead $arguments
320 ; predecessors: %bb.2, %bb.6, %bb.10
321 liveins: $value_stack
322 CATCH_ALL implicit-def $arguments
323 CLEANUPRET implicit-def dead $arguments
326 ; predecessors: %bb.6
327 liveins: $value_stack
328 UNREACHABLE implicit-def $arguments
332 std::unique_ptr
<MIRParser
> MIR
;
333 MachineModuleInfo
MMI(TM
.get());
334 std::unique_ptr
<Module
> M
=
335 parseMIR(Context
, MIR
, *TM
, MIRString
, "test1", MMI
);
338 Function
*F
= M
->getFunction("test1");
339 auto *MF
= MMI
.getMachineFunction(*F
);
342 WebAssemblyExceptionInfo WEI
;
343 MachineDominatorTree MDT
;
344 MachineDominanceFrontier MDF
;
345 MDT
.runOnMachineFunction(*MF
);
346 MDF
.getBase().analyze(MDT
.getBase());
347 WEI
.recalculate(MDT
, MDF
);
349 // Exception info structure:
350 // |- bb1 (ehpad), bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb10, bb11, bb12
351 // |- bb3 (ehpad), bb4, bb5, bb6, bb10, bb12
355 auto *MBB1
= MF
->getBlockNumbered(1);
356 auto *WE0
= WEI
.getExceptionFor(MBB1
);
358 EXPECT_EQ(WE0
->getEHPad(), MBB1
);
359 EXPECT_EQ(WE0
->getParentException(), nullptr);
360 EXPECT_EQ(WE0
->getExceptionDepth(), (unsigned)1);
362 auto *MBB2
= MF
->getBlockNumbered(2);
363 WE0
= WEI
.getExceptionFor(MBB2
);
365 EXPECT_EQ(WE0
->getEHPad(), MBB1
);
367 auto *MBB7
= MF
->getBlockNumbered(7);
368 WE0
= WEI
.getExceptionFor(MBB7
);
370 EXPECT_EQ(WE0
->getEHPad(), MBB1
);
372 auto *MBB8
= MF
->getBlockNumbered(8);
373 WE0
= WEI
.getExceptionFor(MBB8
);
375 EXPECT_EQ(WE0
->getEHPad(), MBB1
);
377 auto *MBB3
= MF
->getBlockNumbered(3);
378 auto *WE0_0
= WEI
.getExceptionFor(MBB3
);
380 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
381 EXPECT_EQ(WE0_0
->getParentException(), WE0
);
382 EXPECT_EQ(WE0_0
->getExceptionDepth(), (unsigned)2);
384 auto *MBB4
= MF
->getBlockNumbered(4);
385 WE0_0
= WEI
.getExceptionFor(MBB4
);
387 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
389 auto *MBB5
= MF
->getBlockNumbered(5);
390 WE0_0
= WEI
.getExceptionFor(MBB5
);
392 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
394 auto *MBB6
= MF
->getBlockNumbered(6);
395 WE0_0
= WEI
.getExceptionFor(MBB6
);
397 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
399 auto *MBB12
= MF
->getBlockNumbered(12);
400 WE0_0
= WEI
.getExceptionFor(MBB12
);
402 EXPECT_EQ(WE0_0
->getEHPad(), MBB3
);
404 auto *MBB10
= MF
->getBlockNumbered(10);
405 auto *WE0_0_0
= WEI
.getExceptionFor(MBB10
);
406 ASSERT_TRUE(WE0_0_0
);
407 EXPECT_EQ(WE0_0_0
->getEHPad(), MBB10
);
408 EXPECT_EQ(WE0_0_0
->getParentException(), WE0_0
);
409 EXPECT_EQ(WE0_0_0
->getExceptionDepth(), (unsigned)3);
411 auto *MBB11
= MF
->getBlockNumbered(11);
412 auto *WE0_1
= WEI
.getExceptionFor(MBB11
);
414 EXPECT_EQ(WE0_1
->getEHPad(), MBB11
);
415 EXPECT_EQ(WE0_1
->getParentException(), WE0
);
416 EXPECT_EQ(WE0_1
->getExceptionDepth(), (unsigned)2);
419 // Terminate pad test
420 TEST(WebAssemblyExceptionInfoTest
, TEST2
) {
421 std::unique_ptr
<TargetMachine
> TM
= createTargetMachine();
424 StringRef MIRString
= R
"MIR(
426 target datalayout = "e
-m
:e
-p
:32:32-i64
:64-n32
:64-S128
"
427 target triple = "wasm32
-unknown
-unknown
"
429 declare i32 @__gxx_wasm_personality_v0(...)
430 declare void @_ZSt9terminatev()
431 declare void @__clang_call_terminate(i8*)
433 define hidden void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
441 - { reg: '$arguments' }
442 - { reg: '$value_stack' }
445 successors: %bb.3, %bb.1
446 BR %bb.3, implicit-def dead $arguments
449 ; predecessors: %bb.0
450 successors: %bb.2, %bb.4
451 %3:i32 = CATCH_I32 0, implicit-def dead $arguments
452 BR %bb.2, implicit-def dead $arguments
455 ; predecessors: %bb.1
456 successors: %bb.3(0x80000000); %bb.3(200.00%)
457 CATCHRET %bb.3, %bb.0, implicit-def dead $arguments
460 ; predecessors: %bb.0, %bb.2
461 RETURN_VOID implicit-def $arguments
464 ; predecessors: %bb.1
465 successors: %bb.5, %bb.6
466 CATCH_ALL implicit-def $arguments
467 BR %bb.5, implicit-def dead $arguments
470 ; predecessors: %bb.4
471 CLEANUPRET implicit-def dead $arguments
474 ; predecessors: %bb.4
475 successors: %bb.7(0x80000000); %bb.7(200.00%)
476 %6:i32 = CATCH_I32 0, implicit-def dead $arguments
477 CALL_VOID @__clang_call_terminate, %7:i32, implicit-def $arguments
478 UNREACHABLE implicit-def $arguments
481 ; predecessors: %bb.6
482 CATCH_ALL implicit-def $arguments
483 CALL_VOID @_ZSt9terminatev, implicit-def $arguments
484 UNREACHABLE implicit-def $arguments
488 std::unique_ptr
<MIRParser
> MIR
;
489 MachineModuleInfo
MMI(TM
.get());
490 std::unique_ptr
<Module
> M
=
491 parseMIR(Context
, MIR
, *TM
, MIRString
, "test2", MMI
);
494 Function
*F
= M
->getFunction("test2");
495 auto *MF
= MMI
.getMachineFunction(*F
);
498 WebAssemblyExceptionInfo WEI
;
499 MachineDominatorTree MDT
;
500 MachineDominanceFrontier MDF
;
501 MDT
.runOnMachineFunction(*MF
);
502 MDF
.getBase().analyze(MDT
.getBase());
503 WEI
.recalculate(MDT
, MDF
);
505 // Exception info structure:
506 // |- bb1 (ehpad), bb2, bb4, bb5, bb6, bb7
507 // |- bb4 (ehpad), bb5, bb6, bb7
508 // |- bb6 (ehpad), bb7
510 // Here, bb6 is a terminate pad with a 'catch' instruction, and bb7 is a
511 // terminate pad with a 'catch_all' instruction, In this case we put bb6 and
512 // bb7 into one exception.
514 auto *MBB1
= MF
->getBlockNumbered(1);
515 auto *WE0
= WEI
.getExceptionFor(MBB1
);
517 EXPECT_EQ(WE0
->getEHPad(), MBB1
);
518 EXPECT_EQ(WE0
->getParentException(), nullptr);
519 EXPECT_EQ(WE0
->getExceptionDepth(), (unsigned)1);
521 auto *MBB2
= MF
->getBlockNumbered(2);
522 WE0
= WEI
.getExceptionFor(MBB2
);
524 EXPECT_EQ(WE0
->getEHPad(), MBB1
);
526 auto *MBB4
= MF
->getBlockNumbered(4);
527 auto *WE0_0
= WEI
.getExceptionFor(MBB4
);
529 EXPECT_EQ(WE0_0
->getEHPad(), MBB4
);
530 EXPECT_EQ(WE0_0
->getParentException(), WE0
);
531 EXPECT_EQ(WE0_0
->getExceptionDepth(), (unsigned)2);
533 auto *MBB5
= MF
->getBlockNumbered(5);
534 WE0_0
= WEI
.getExceptionFor(MBB5
);
536 EXPECT_EQ(WE0_0
->getEHPad(), MBB4
);
538 auto *MBB6
= MF
->getBlockNumbered(6);
539 auto *WE0_0_0
= WEI
.getExceptionFor(MBB6
);
540 ASSERT_TRUE(WE0_0_0
);
541 EXPECT_EQ(WE0_0_0
->getEHPad(), MBB6
);
542 EXPECT_EQ(WE0_0_0
->getParentException(), WE0_0
);
543 EXPECT_EQ(WE0_0_0
->getExceptionDepth(), (unsigned)3);
545 auto *MBB7
= MF
->getBlockNumbered(7);
546 WE0_0_0
= WEI
.getExceptionFor(MBB7
);
547 ASSERT_TRUE(WE0_0_0
);
548 EXPECT_EQ(WE0_0_0
->getEHPad(), MBB6
);