1 //=== WebAssemblyExceptionInfoTest.cpp - WebAssemblyExceptionInfo unit tests =//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "WebAssemblyExceptionInfo.h"
10 #include "llvm/CodeGen/MIRParser/MIRParser.h"
11 #include "llvm/CodeGen/MachineDominanceFrontier.h"
12 #include "llvm/CodeGen/MachineDominators.h"
13 #include "llvm/CodeGen/MachineModuleInfo.h"
14 #include "llvm/MC/TargetRegistry.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "llvm/Support/TargetSelect.h"
17 #include "llvm/Target/TargetMachine.h"
18 #include "gtest/gtest.h"
24 std::unique_ptr
<LLVMTargetMachine
> createTargetMachine() {
25 auto TT(Triple::normalize("wasm32-unknown-unknown"));
29 LLVMInitializeWebAssemblyTargetInfo();
30 LLVMInitializeWebAssemblyTarget();
31 LLVMInitializeWebAssemblyTargetMC();
34 const Target
*TheTarget
= TargetRegistry::lookupTarget(TT
, Error
);
37 return std::unique_ptr
<LLVMTargetMachine
>(static_cast<LLVMTargetMachine
*>(
38 TheTarget
->createTargetMachine(TT
, CPU
, FS
, TargetOptions(), std::nullopt
,
39 std::nullopt
, CodeGenOptLevel::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
<LLVMTargetMachine
> 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 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 RETHROW 0, implicit-def dead $arguments
107 ; predecessors: %bb.2
108 successors: %bb.4, %bb.6
109 liveins: $value_stack
110 %1:i32 = CATCH &__cpp_exception, 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 BR %bb.7, 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 implicit-def $arguments
138 ; predecessors: %bb.4
140 liveins: $value_stack
141 CATCH_ALL implicit-def $arguments
142 RETHROW 0, implicit-def dead $arguments
145 ; predecessors: %bb.2, %bb.6, %bb.8
146 liveins: $value_stack
147 CATCH_ALL implicit-def $arguments
148 RETHROW 0, 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(*MF
, 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
<LLVMTargetMachine
> 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 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 %0:i32 = CATCH &__cpp_exception, implicit-def $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 %1:i32 = CATCH &__cpp_exception, 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 BR %bb.7, 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 BR %bb.9, 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 implicit-def $arguments
313 ; predecessors: %bb.4
315 liveins: $value_stack
316 CATCH_ALL implicit-def $arguments
317 RETHROW 0, implicit-def dead $arguments
320 ; predecessors: %bb.2, %bb.6, %bb.10
321 liveins: $value_stack
322 CATCH_ALL implicit-def $arguments
323 RETHROW 0, 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(*MF
, 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);