xref: /llvm-project/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp (revision 6a907699d8b4fb35a843ab8fd84ca56ed93fc201)
1 //=== WebAssemblyExceptionInfoTest.cpp - WebAssemblyExceptionInfo unit tests =//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
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/IR/Module.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/TargetSelect.h"
18 #include "llvm/Target/TargetMachine.h"
19 #include "gtest/gtest.h"
20 
21 using namespace llvm;
22 
23 namespace {
24 
25 std::unique_ptr<LLVMTargetMachine> createTargetMachine() {
26   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 
38   return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
39       TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), std::nullopt,
40                                      std::nullopt, CodeGenOptLevel::Default)));
41 }
42 
43 std::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 
67 TEST(WebAssemblyExceptionInfoTest, TEST0) {
68   std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
69   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 void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
79     unreachable
80   }
81 
82 ...
83 ---
84 name: test0
85 liveins:
86   - { reg: '$arguments' }
87   - { reg: '$value_stack' }
88 body: |
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     RETHROW 0, 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     %1:i32 = CATCH &__cpp_exception, 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     BR %bb.7, 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 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     RETHROW 0, 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     RETHROW 0, 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.calculate(*MF);
172   MDF.getBase().analyze(MDT.getBase());
173   WEI.recalculate(*MF, 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 
230 TEST(WebAssemblyExceptionInfoTest, TEST1) {
231   std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
232   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 void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
242     unreachable
243   }
244 
245 ...
246 ---
247 name: test1
248 liveins:
249   - { reg: '$arguments' }
250   - { reg: '$value_stack' }
251 body: |
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     %0:i32 = CATCH &__cpp_exception, implicit-def $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     %1:i32 = CATCH &__cpp_exception, 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     BR %bb.7, 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     BR %bb.9, 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 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     RETHROW 0, 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     RETHROW 0, 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.calculate(*MF);
347   MDF.getBase().analyze(MDT.getBase());
348   WEI.recalculate(*MF, 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