• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=== 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 
21 using namespace llvm;
22 
23 namespace {
24 
createTargetMachine()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>(TheTarget->createTargetMachine(
39       TT, CPU, FS, TargetOptions(), None, None, CodeGenOpt::Default));
40 }
41 
parseMIR(LLVMContext & Context,std::unique_ptr<MIRParser> & MIR,const TargetMachine & TM,StringRef MIRCode,const char * FuncName,MachineModuleInfo & MMI)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);
49   if (!MIR)
50     return nullptr;
51 
52   std::unique_ptr<Module> M = MIR->parseIRModule();
53   if (!M)
54     return nullptr;
55 
56   M->setDataLayout(TM.createDataLayout());
57 
58   if (MIR->parseMachineFunctions(*M, MMI))
59     return nullptr;
60 
61   return M;
62 }
63 
64 } // namespace
65 
TEST(WebAssemblyExceptionInfoTest,TEST0)66 TEST(WebAssemblyExceptionInfoTest, TEST0) {
67   std::unique_ptr<TargetMachine> TM = createTargetMachine();
68   ASSERT_TRUE(TM);
69 
70   StringRef MIRString = R"MIR(
71 --- |
72   target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
73   target triple = "wasm32-unknown-unknown"
74 
75   declare i32 @__gxx_wasm_personality_v0(...)
76 
77   define hidden void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
78     unreachable
79   }
80 
81 ...
82 ---
83 name: test0
84 liveins:
85   - { reg: '$arguments' }
86   - { reg: '$value_stack' }
87 body: |
88   bb.0:
89     successors: %bb.1, %bb.2
90     liveins: $arguments, $value_stack
91     BR %bb.1, implicit-def dead $arguments
92 
93   bb.1:
94   ; predecessors: %bb.0
95     successors: %bb.7
96     liveins: $value_stack
97     BR %bb.7, implicit-def $arguments
98 
99   bb.2 (landing-pad):
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
105 
106   bb.3 (landing-pad):
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
113 
114   bb.4:
115   ; predecessors: %bb.3
116     successors: %bb.5, %bb.8
117     liveins: $value_stack
118     BR %bb.5, implicit-def dead $arguments
119 
120   bb.5:
121   ; predecessors: %bb.4
122     successors: %bb.7
123     liveins: $value_stack
124     CATCHRET %bb.7, %bb.0, implicit-def dead $arguments
125 
126   bb.6:
127   ; predecessors: %bb.3
128     successors: %bb.10, %bb.9
129     liveins: $value_stack
130     BR %bb.10, implicit-def dead $arguments
131 
132   bb.7:
133   ; predecessors: %bb.5, %bb.1
134     liveins: $value_stack
135     RETURN_VOID implicit-def $arguments
136 
137   bb.8 (landing-pad):
138   ; predecessors: %bb.4
139     successors: %bb.9
140     liveins: $value_stack
141     CATCH_ALL implicit-def $arguments
142     CLEANUPRET implicit-def dead $arguments
143 
144   bb.9 (landing-pad):
145   ; predecessors: %bb.2, %bb.6, %bb.8
146     liveins: $value_stack
147     CATCH_ALL implicit-def $arguments
148     CLEANUPRET implicit-def dead $arguments
149 
150   bb.10:
151   ; predecessors: %bb.6
152     liveins: $value_stack
153     UNREACHABLE implicit-def $arguments
154 )MIR";
155 
156   LLVMContext Context;
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);
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.runOnMachineFunction(*MF);
171   MDF.getBase().analyze(MDT.getBase());
172   WEI.recalculate(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 
TEST(WebAssemblyExceptionInfoTest,TEST1)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 hidden 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     %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
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     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
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     CATCHRET %bb.7, %bb.1, 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     CATCHRET %bb.9, %bb.0, 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_VOID implicit-def $arguments
311 
312   bb.10 (landing-pad):
313   ; predecessors: %bb.4
314     successors: %bb.11
315     liveins: $value_stack
316     CATCH_ALL implicit-def $arguments
317     CLEANUPRET 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 implicit-def $arguments
323     CLEANUPRET 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 =
335       parseMIR(Context, MIR, *TM, MIRString, "test1", MMI);
336   ASSERT_TRUE(M);
337 
338   Function *F = M->getFunction("test1");
339   auto *MF = MMI.getMachineFunction(*F);
340   ASSERT_TRUE(MF);
341 
342   WebAssemblyExceptionInfo WEI;
343   MachineDominatorTree MDT;
344   MachineDominanceFrontier MDF;
345   MDT.runOnMachineFunction(*MF);
346   MDF.getBase().analyze(MDT.getBase());
347   WEI.recalculate(MDT, MDF);
348 
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
352   //     |- bb10 (ehpad)
353   //   |- bb11 (ehpad)
354 
355   auto *MBB1 = MF->getBlockNumbered(1);
356   auto *WE0 = WEI.getExceptionFor(MBB1);
357   ASSERT_TRUE(WE0);
358   EXPECT_EQ(WE0->getEHPad(), MBB1);
359   EXPECT_EQ(WE0->getParentException(), nullptr);
360   EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1);
361 
362   auto *MBB2 = MF->getBlockNumbered(2);
363   WE0 = WEI.getExceptionFor(MBB2);
364   ASSERT_TRUE(WE0);
365   EXPECT_EQ(WE0->getEHPad(), MBB1);
366 
367   auto *MBB7 = MF->getBlockNumbered(7);
368   WE0 = WEI.getExceptionFor(MBB7);
369   ASSERT_TRUE(WE0);
370   EXPECT_EQ(WE0->getEHPad(), MBB1);
371 
372   auto *MBB8 = MF->getBlockNumbered(8);
373   WE0 = WEI.getExceptionFor(MBB8);
374   ASSERT_TRUE(WE0);
375   EXPECT_EQ(WE0->getEHPad(), MBB1);
376 
377   auto *MBB3 = MF->getBlockNumbered(3);
378   auto *WE0_0 = WEI.getExceptionFor(MBB3);
379   ASSERT_TRUE(WE0_0);
380   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
381   EXPECT_EQ(WE0_0->getParentException(), WE0);
382   EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2);
383 
384   auto *MBB4 = MF->getBlockNumbered(4);
385   WE0_0 = WEI.getExceptionFor(MBB4);
386   ASSERT_TRUE(WE0_0);
387   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
388 
389   auto *MBB5 = MF->getBlockNumbered(5);
390   WE0_0 = WEI.getExceptionFor(MBB5);
391   ASSERT_TRUE(WE0_0);
392   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
393 
394   auto *MBB6 = MF->getBlockNumbered(6);
395   WE0_0 = WEI.getExceptionFor(MBB6);
396   ASSERT_TRUE(WE0_0);
397   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
398 
399   auto *MBB12 = MF->getBlockNumbered(12);
400   WE0_0 = WEI.getExceptionFor(MBB12);
401   ASSERT_TRUE(WE0_0);
402   EXPECT_EQ(WE0_0->getEHPad(), MBB3);
403 
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);
410 
411   auto *MBB11 = MF->getBlockNumbered(11);
412   auto *WE0_1 = WEI.getExceptionFor(MBB11);
413   ASSERT_TRUE(WE0_1);
414   EXPECT_EQ(WE0_1->getEHPad(), MBB11);
415   EXPECT_EQ(WE0_1->getParentException(), WE0);
416   EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2);
417 }
418 
419 // Terminate pad test
TEST(WebAssemblyExceptionInfoTest,TEST2)420 TEST(WebAssemblyExceptionInfoTest, TEST2) {
421   std::unique_ptr<TargetMachine> TM = createTargetMachine();
422   ASSERT_TRUE(TM);
423 
424   StringRef MIRString = R"MIR(
425 --- |
426   target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
427   target triple = "wasm32-unknown-unknown"
428 
429   declare i32 @__gxx_wasm_personality_v0(...)
430   declare void @_ZSt9terminatev()
431   declare void @__clang_call_terminate(i8*)
432 
433   define hidden void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
434     unreachable
435   }
436 
437 ...
438 ---
439 name: test2
440 liveins:
441   - { reg: '$arguments' }
442   - { reg: '$value_stack' }
443 body: |
444   bb.0:
445     successors: %bb.3, %bb.1
446     BR %bb.3, implicit-def dead $arguments
447 
448   bb.1 (landing-pad):
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
453 
454   bb.2:
455   ; predecessors: %bb.1
456     successors: %bb.3(0x80000000); %bb.3(200.00%)
457     CATCHRET %bb.3, %bb.0, implicit-def dead $arguments
458 
459   bb.3:
460   ; predecessors: %bb.0, %bb.2
461     RETURN_VOID implicit-def $arguments
462 
463   bb.4 (landing-pad):
464   ; predecessors: %bb.1
465     successors: %bb.5, %bb.6
466     CATCH_ALL implicit-def $arguments
467     BR %bb.5, implicit-def dead $arguments
468 
469   bb.5:
470   ; predecessors: %bb.4
471     CLEANUPRET implicit-def dead $arguments
472 
473   bb.6 (landing-pad):
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
479 
480   bb.7 (landing-pad):
481   ; predecessors: %bb.6
482     CATCH_ALL implicit-def $arguments
483     CALL_VOID @_ZSt9terminatev, implicit-def $arguments
484     UNREACHABLE implicit-def $arguments
485 )MIR";
486 
487   LLVMContext Context;
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);
492   ASSERT_TRUE(M);
493 
494   Function *F = M->getFunction("test2");
495   auto *MF = MMI.getMachineFunction(*F);
496   ASSERT_TRUE(MF);
497 
498   WebAssemblyExceptionInfo WEI;
499   MachineDominatorTree MDT;
500   MachineDominanceFrontier MDF;
501   MDT.runOnMachineFunction(*MF);
502   MDF.getBase().analyze(MDT.getBase());
503   WEI.recalculate(MDT, MDF);
504 
505   // Exception info structure:
506   // |- bb1 (ehpad), bb2, bb4, bb5, bb6, bb7
507   //   |- bb4 (ehpad), bb5, bb6, bb7
508   //     |- bb6 (ehpad), bb7
509   //
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.
513 
514   auto *MBB1 = MF->getBlockNumbered(1);
515   auto *WE0 = WEI.getExceptionFor(MBB1);
516   ASSERT_TRUE(WE0);
517   EXPECT_EQ(WE0->getEHPad(), MBB1);
518   EXPECT_EQ(WE0->getParentException(), nullptr);
519   EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1);
520 
521   auto *MBB2 = MF->getBlockNumbered(2);
522   WE0 = WEI.getExceptionFor(MBB2);
523   ASSERT_TRUE(WE0);
524   EXPECT_EQ(WE0->getEHPad(), MBB1);
525 
526   auto *MBB4 = MF->getBlockNumbered(4);
527   auto *WE0_0 = WEI.getExceptionFor(MBB4);
528   ASSERT_TRUE(WE0_0);
529   EXPECT_EQ(WE0_0->getEHPad(), MBB4);
530   EXPECT_EQ(WE0_0->getParentException(), WE0);
531   EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2);
532 
533   auto *MBB5 = MF->getBlockNumbered(5);
534   WE0_0 = WEI.getExceptionFor(MBB5);
535   ASSERT_TRUE(WE0_0);
536   EXPECT_EQ(WE0_0->getEHPad(), MBB4);
537 
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);
544 
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);
549 }
550