1*b5893f02SDimitry Andric //===-- CodeGen/AsmPrinter/WasmException.cpp - Wasm Exception Impl --------===//
2*b5893f02SDimitry Andric //
3*b5893f02SDimitry Andric //                     The LLVM Compiler Infrastructure
4*b5893f02SDimitry Andric //
5*b5893f02SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*b5893f02SDimitry Andric // License. See LICENSE.TXT for details.
7*b5893f02SDimitry Andric //
8*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
9*b5893f02SDimitry Andric //
10*b5893f02SDimitry Andric // This file contains support for writing WebAssembly exception info into asm
11*b5893f02SDimitry Andric // files.
12*b5893f02SDimitry Andric //
13*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
14*b5893f02SDimitry Andric 
15*b5893f02SDimitry Andric #include "WasmException.h"
16*b5893f02SDimitry Andric #include "llvm/IR/Mangler.h"
17*b5893f02SDimitry Andric #include "llvm/MC/MCContext.h"
18*b5893f02SDimitry Andric #include "llvm/MC/MCStreamer.h"
19*b5893f02SDimitry Andric using namespace llvm;
20*b5893f02SDimitry Andric 
endModule()21*b5893f02SDimitry Andric void WasmException::endModule() {
22*b5893f02SDimitry Andric   // This is the symbol used in 'throw' and 'if_except' instruction to denote
23*b5893f02SDimitry Andric   // this is a C++ exception. This symbol has to be emitted somewhere once in
24*b5893f02SDimitry Andric   // the module.  Check if the symbol has already been created, i.e., we have at
25*b5893f02SDimitry Andric   // least one 'throw' or 'if_except' instruction in the module, and emit the
26*b5893f02SDimitry Andric   // symbol only if so.
27*b5893f02SDimitry Andric   SmallString<60> NameStr;
28*b5893f02SDimitry Andric   Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout());
29*b5893f02SDimitry Andric   if (Asm->OutContext.lookupSymbol(NameStr)) {
30*b5893f02SDimitry Andric     MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol("__cpp_exception");
31*b5893f02SDimitry Andric     Asm->OutStreamer->EmitLabel(ExceptionSym);
32*b5893f02SDimitry Andric   }
33*b5893f02SDimitry Andric }
34*b5893f02SDimitry Andric 
markFunctionEnd()35*b5893f02SDimitry Andric void WasmException::markFunctionEnd() {
36*b5893f02SDimitry Andric   // Get rid of any dead landing pads.
37*b5893f02SDimitry Andric   if (!Asm->MF->getLandingPads().empty()) {
38*b5893f02SDimitry Andric     auto *NonConstMF = const_cast<MachineFunction *>(Asm->MF);
39*b5893f02SDimitry Andric     // Wasm does not set BeginLabel and EndLabel information for landing pads,
40*b5893f02SDimitry Andric     // so we should set the second argument false.
41*b5893f02SDimitry Andric     NonConstMF->tidyLandingPads(nullptr, /* TidyIfNoBeginLabels */ false);
42*b5893f02SDimitry Andric   }
43*b5893f02SDimitry Andric }
44*b5893f02SDimitry Andric 
endFunction(const MachineFunction * MF)45*b5893f02SDimitry Andric void WasmException::endFunction(const MachineFunction *MF) {
46*b5893f02SDimitry Andric   bool ShouldEmitExceptionTable = false;
47*b5893f02SDimitry Andric   for (const LandingPadInfo &Info : MF->getLandingPads()) {
48*b5893f02SDimitry Andric     if (MF->hasWasmLandingPadIndex(Info.LandingPadBlock)) {
49*b5893f02SDimitry Andric       ShouldEmitExceptionTable = true;
50*b5893f02SDimitry Andric       break;
51*b5893f02SDimitry Andric     }
52*b5893f02SDimitry Andric   }
53*b5893f02SDimitry Andric   if (!ShouldEmitExceptionTable)
54*b5893f02SDimitry Andric     return;
55*b5893f02SDimitry Andric   MCSymbol *LSDALabel = emitExceptionTable();
56*b5893f02SDimitry Andric   assert(LSDALabel && ".GCC_exception_table has not been emitted!");
57*b5893f02SDimitry Andric 
58*b5893f02SDimitry Andric   // Wasm requires every data section symbol to have a .size set. So we emit an
59*b5893f02SDimitry Andric   // end marker and set the size as the difference between the start end the end
60*b5893f02SDimitry Andric   // marker.
61*b5893f02SDimitry Andric   MCSymbol *LSDAEndLabel = Asm->createTempSymbol("GCC_except_table_end");
62*b5893f02SDimitry Andric   Asm->OutStreamer->EmitLabel(LSDAEndLabel);
63*b5893f02SDimitry Andric   MCContext &OutContext = Asm->OutStreamer->getContext();
64*b5893f02SDimitry Andric   const MCExpr *SizeExp = MCBinaryExpr::createSub(
65*b5893f02SDimitry Andric       MCSymbolRefExpr::create(LSDAEndLabel, OutContext),
66*b5893f02SDimitry Andric       MCSymbolRefExpr::create(LSDALabel, OutContext), OutContext);
67*b5893f02SDimitry Andric   Asm->OutStreamer->emitELFSize(LSDALabel, SizeExp);
68*b5893f02SDimitry Andric }
69*b5893f02SDimitry Andric 
70*b5893f02SDimitry Andric // Compute the call-site table for wasm EH. Even though we use the same function
71*b5893f02SDimitry Andric // name to share the common routines, a call site entry in the table corresponds
72*b5893f02SDimitry Andric // to not a call site for possibly-throwing functions but a landing pad. In wasm
73*b5893f02SDimitry Andric // EH the VM is responsible for stack unwinding. After an exception occurs and
74*b5893f02SDimitry Andric // the stack is unwound, the control flow is transferred to wasm 'catch'
75*b5893f02SDimitry Andric // instruction by the VM, after which the personality function is called from
76*b5893f02SDimitry Andric // the compiler-generated code. Refer to WasmEHPrepare pass for more
77*b5893f02SDimitry Andric // information.
computeCallSiteTable(SmallVectorImpl<CallSiteEntry> & CallSites,const SmallVectorImpl<const LandingPadInfo * > & LandingPads,const SmallVectorImpl<unsigned> & FirstActions)78*b5893f02SDimitry Andric void WasmException::computeCallSiteTable(
79*b5893f02SDimitry Andric     SmallVectorImpl<CallSiteEntry> &CallSites,
80*b5893f02SDimitry Andric     const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
81*b5893f02SDimitry Andric     const SmallVectorImpl<unsigned> &FirstActions) {
82*b5893f02SDimitry Andric   MachineFunction &MF = *Asm->MF;
83*b5893f02SDimitry Andric   for (unsigned I = 0, N = LandingPads.size(); I < N; ++I) {
84*b5893f02SDimitry Andric     const LandingPadInfo *Info = LandingPads[I];
85*b5893f02SDimitry Andric     MachineBasicBlock *LPad = Info->LandingPadBlock;
86*b5893f02SDimitry Andric     // We don't emit LSDA for single catch (...).
87*b5893f02SDimitry Andric     if (!MF.hasWasmLandingPadIndex(LPad))
88*b5893f02SDimitry Andric       continue;
89*b5893f02SDimitry Andric     // Wasm EH must maintain the EH pads in the order assigned to them by the
90*b5893f02SDimitry Andric     // WasmEHPrepare pass.
91*b5893f02SDimitry Andric     unsigned LPadIndex = MF.getWasmLandingPadIndex(LPad);
92*b5893f02SDimitry Andric     CallSiteEntry Site = {nullptr, nullptr, Info, FirstActions[I]};
93*b5893f02SDimitry Andric     if (CallSites.size() < LPadIndex + 1)
94*b5893f02SDimitry Andric       CallSites.resize(LPadIndex + 1);
95*b5893f02SDimitry Andric     CallSites[LPadIndex] = Site;
96*b5893f02SDimitry Andric   }
97*b5893f02SDimitry Andric }
98