xref: /llvm-project/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp (revision 1562b70eaf6e0b95910fa684dfc53bd5ca6252e7)
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<TargetMachine> 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<TargetMachine>(
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                                  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<TargetMachine> 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_LEGACY 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_LEGACY &__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_LEGACY 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_LEGACY 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 = parseMIR(Context, MIR, *TM, MIRString, MMI);
161   ASSERT_TRUE(M);
162 
163   Function *F = M->getFunction("test0");
164   auto *MF = MMI.getMachineFunction(*F);
165   ASSERT_TRUE(MF);
166 
167   WebAssemblyExceptionInfo WEI;
168   MachineDominatorTree MDT;
169   MachineDominanceFrontier MDF;
170   MDT.recalculate(*MF);
171   MDF.getBase().analyze(MDT);
172   WEI.recalculate(*MF, MDT, MDF);
173 
174   // Exception info structure:
175   // |- bb2 (ehpad), bb3, bb4, bb5, bb6, bb8, bb9, bb10
176   //   |- bb3 (ehpad), bb4, bb5, bb6, bb8, bb10
177   //     |- bb8 (ehpad)
178   //   |- bb9 (ehpad)
179 
180   auto *MBB2 = MF->getBlockNumbered(2);
181   auto *WE0 = WEI.getExceptionFor(MBB2);
182   ASSERT_TRUE(WE0);
183   EXPECT_EQ(WE0->getEHPad(), MBB2);
184   EXPECT_EQ(WE0->getParentException(), nullptr);
185   EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1);
186 
187   auto *MBB3 = MF->getBlockNumbered(3);
188   auto *WE0_0 = WEI.getExceptionFor(MBB3);
189   ASSERT_TRUE(WE0_0);
190   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
191   EXPECT_EQ(WE0_0->getParentException(), WE0);
192   EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2);
193 
194   auto *MBB4 = MF->getBlockNumbered(4);
195   WE0_0 = WEI.getExceptionFor(MBB4);
196   ASSERT_TRUE(WE0_0);
197   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
198 
199   auto *MBB5 = MF->getBlockNumbered(5);
200   WE0_0 = WEI.getExceptionFor(MBB5);
201   ASSERT_TRUE(WE0_0);
202   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
203 
204   auto *MBB6 = MF->getBlockNumbered(6);
205   WE0_0 = WEI.getExceptionFor(MBB6);
206   ASSERT_TRUE(WE0_0);
207   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
208 
209   auto *MBB10 = MF->getBlockNumbered(10);
210   WE0_0 = WEI.getExceptionFor(MBB10);
211   ASSERT_TRUE(WE0_0);
212   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
213 
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);
220 
221   auto *MBB9 = MF->getBlockNumbered(9);
222   auto *WE0_1 = WEI.getExceptionFor(MBB9);
223   ASSERT_TRUE(WE0_1);
224   EXPECT_EQ(WE0_1->getEHPad(), MBB9);
225   EXPECT_EQ(WE0_1->getParentException(), WE0);
226   EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2);
227 }
228 
229 TEST(WebAssemblyExceptionInfoTest, TEST1) {
230   std::unique_ptr<TargetMachine> TM = createTargetMachine();
231   ASSERT_TRUE(TM);
232 
233   StringRef MIRString = R"MIR(
234 --- |
235   target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
236   target triple = "wasm32-unknown-unknown"
237 
238   declare i32 @__gxx_wasm_personality_v0(...)
239 
240   define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
241     unreachable
242   }
243 
244 ...
245 ---
246 name: test1
247 liveins:
248   - { reg: '$arguments' }
249   - { reg: '$value_stack' }
250 body: |
251   bb.0:
252     successors: %bb.9, %bb.1
253     liveins: $arguments, $value_stack
254     BR %bb.9, implicit-def dead $arguments
255 
256   bb.1 (landing-pad):
257   ; predecessors: %bb.0
258     successors: %bb.2, %bb.8
259     liveins: $value_stack
260     %0:i32 = CATCH_LEGACY &__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
263 
264   bb.2:
265   ; predecessors: %bb.1
266     successors: %bb.7, %bb.3, %bb.11
267     liveins: $value_stack
268     BR %bb.7, implicit-def dead $arguments
269 
270   bb.3 (landing-pad):
271   ; predecessors: %bb.2
272     successors: %bb.4, %bb.6
273     liveins: $value_stack
274     %1:i32 = CATCH_LEGACY &__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
277 
278   bb.4:
279   ; predecessors: %bb.3
280     successors: %bb.5, %bb.10
281     liveins: $value_stack
282     BR %bb.5, implicit-def dead $arguments
283 
284   bb.5:
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
289 
290   bb.6:
291   ; predecessors: %bb.3
292     successors: %bb.12, %bb.11
293     liveins: $value_stack
294     BR %bb.12, implicit-def dead $arguments
295 
296   bb.7:
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
301 
302   bb.8:
303   ; predecessors: %bb.1
304     liveins: $value_stack
305     UNREACHABLE implicit-def $arguments
306 
307   bb.9:
308   ; predecessors: %bb.0, %bb.7
309     liveins: $value_stack
310     RETURN implicit-def $arguments
311 
312   bb.10 (landing-pad):
313   ; predecessors: %bb.4
314     successors: %bb.11
315     liveins: $value_stack
316     CATCH_ALL_LEGACY implicit-def $arguments
317     RETHROW 0, implicit-def dead $arguments
318 
319   bb.11 (landing-pad):
320   ; predecessors: %bb.2, %bb.6, %bb.10
321     liveins: $value_stack
322     CATCH_ALL_LEGACY implicit-def $arguments
323     RETHROW 0, implicit-def dead $arguments
324 
325   bb.12:
326   ; predecessors: %bb.6
327     liveins: $value_stack
328     UNREACHABLE implicit-def $arguments
329 )MIR";
330 
331   LLVMContext Context;
332   std::unique_ptr<MIRParser> MIR;
333   MachineModuleInfo MMI(TM.get());
334   std::unique_ptr<Module> M = parseMIR(Context, MIR, *TM, MIRString, MMI);
335   ASSERT_TRUE(M);
336 
337   Function *F = M->getFunction("test1");
338   auto *MF = MMI.getMachineFunction(*F);
339   ASSERT_TRUE(MF);
340 
341   WebAssemblyExceptionInfo WEI;
342   MachineDominatorTree MDT;
343   MachineDominanceFrontier MDF;
344   MDT.recalculate(*MF);
345   MDF.getBase().analyze(MDT);
346   WEI.recalculate(*MF, MDT, MDF);
347 
348   // Exception info structure:
349   // |- bb1 (ehpad), bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb10, bb11, bb12
350   //   |- bb3 (ehpad), bb4, bb5, bb6, bb10, bb12
351   //     |- bb10 (ehpad)
352   //   |- bb11 (ehpad)
353 
354   auto *MBB1 = MF->getBlockNumbered(1);
355   auto *WE0 = WEI.getExceptionFor(MBB1);
356   ASSERT_TRUE(WE0);
357   EXPECT_EQ(WE0->getEHPad(), MBB1);
358   EXPECT_EQ(WE0->getParentException(), nullptr);
359   EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1);
360 
361   auto *MBB2 = MF->getBlockNumbered(2);
362   WE0 = WEI.getExceptionFor(MBB2);
363   ASSERT_TRUE(WE0);
364   EXPECT_EQ(WE0->getEHPad(), MBB1);
365 
366   auto *MBB7 = MF->getBlockNumbered(7);
367   WE0 = WEI.getExceptionFor(MBB7);
368   ASSERT_TRUE(WE0);
369   EXPECT_EQ(WE0->getEHPad(), MBB1);
370 
371   auto *MBB8 = MF->getBlockNumbered(8);
372   WE0 = WEI.getExceptionFor(MBB8);
373   ASSERT_TRUE(WE0);
374   EXPECT_EQ(WE0->getEHPad(), MBB1);
375 
376   auto *MBB3 = MF->getBlockNumbered(3);
377   auto *WE0_0 = WEI.getExceptionFor(MBB3);
378   ASSERT_TRUE(WE0_0);
379   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
380   EXPECT_EQ(WE0_0->getParentException(), WE0);
381   EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2);
382 
383   auto *MBB4 = MF->getBlockNumbered(4);
384   WE0_0 = WEI.getExceptionFor(MBB4);
385   ASSERT_TRUE(WE0_0);
386   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
387 
388   auto *MBB5 = MF->getBlockNumbered(5);
389   WE0_0 = WEI.getExceptionFor(MBB5);
390   ASSERT_TRUE(WE0_0);
391   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
392 
393   auto *MBB6 = MF->getBlockNumbered(6);
394   WE0_0 = WEI.getExceptionFor(MBB6);
395   ASSERT_TRUE(WE0_0);
396   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
397 
398   auto *MBB12 = MF->getBlockNumbered(12);
399   WE0_0 = WEI.getExceptionFor(MBB12);
400   ASSERT_TRUE(WE0_0);
401   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
402 
403   auto *MBB10 = MF->getBlockNumbered(10);
404   auto *WE0_0_0 = WEI.getExceptionFor(MBB10);
405   ASSERT_TRUE(WE0_0_0);
406   EXPECT_EQ(WE0_0_0->getEHPad(), MBB10);
407   EXPECT_EQ(WE0_0_0->getParentException(), WE0_0);
408   EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3);
409 
410   auto *MBB11 = MF->getBlockNumbered(11);
411   auto *WE0_1 = WEI.getExceptionFor(MBB11);
412   ASSERT_TRUE(WE0_1);
413   EXPECT_EQ(WE0_1->getEHPad(), MBB11);
414   EXPECT_EQ(WE0_1->getParentException(), WE0);
415   EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2);
416 }
417