1 //===-- CodeGen/AsmPrinter/WasmException.cpp - Wasm Exception Impl --------===// 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 // This file contains support for writing WebAssembly exception info into asm 11 // files. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "WasmException.h" 16 #include "llvm/MC/MCStreamer.h" 17 using namespace llvm; 18 19 void WasmException::markFunctionEnd() { 20 // Get rid of any dead landing pads. 21 if (!Asm->MF->getLandingPads().empty()) { 22 auto *NonConstMF = const_cast<MachineFunction *>(Asm->MF); 23 // Wasm does not set BeginLabel and EndLabel information for landing pads, 24 // so we should set the second argument false. 25 NonConstMF->tidyLandingPads(nullptr, /* TidyIfNoBeginLabels */ false); 26 } 27 } 28 29 void WasmException::endFunction(const MachineFunction *MF) { 30 bool ShouldEmitExceptionTable = false; 31 for (const LandingPadInfo &Info : MF->getLandingPads()) { 32 if (MF->hasWasmLandingPadIndex(Info.LandingPadBlock)) { 33 ShouldEmitExceptionTable = true; 34 break; 35 } 36 } 37 if (!ShouldEmitExceptionTable) 38 return; 39 MCSymbol *LSDALabel = emitExceptionTable(); 40 assert(LSDALabel && ".GCC_exception_table has not been emitted!"); 41 42 // Wasm requires every data section symbol to have a .size set. So we emit an 43 // end marker and set the size as the difference between the start end the end 44 // marker. 45 MCSymbol *LSDAEndLabel = Asm->createTempSymbol("GCC_except_table_end"); 46 Asm->OutStreamer->EmitLabel(LSDAEndLabel); 47 MCContext &OutContext = Asm->OutStreamer->getContext(); 48 const MCExpr *SizeExp = MCBinaryExpr::createSub( 49 MCSymbolRefExpr::create(LSDAEndLabel, OutContext), 50 MCSymbolRefExpr::create(LSDALabel, OutContext), OutContext); 51 Asm->OutStreamer->emitELFSize(LSDALabel, SizeExp); 52 } 53 54 // Compute the call-site table for wasm EH. Even though we use the same function 55 // name to share the common routines, a call site entry in the table corresponds 56 // to not a call site for possibly-throwing functions but a landing pad. In wasm 57 // EH the VM is responsible for stack unwinding. After an exception occurs and 58 // the stack is unwound, the control flow is transferred to wasm 'catch' 59 // instruction by the VM, after which the personality function is called from 60 // the compiler-generated code. Refer to WasmEHPrepare pass for more 61 // information. 62 void WasmException::computeCallSiteTable( 63 SmallVectorImpl<CallSiteEntry> &CallSites, 64 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 65 const SmallVectorImpl<unsigned> &FirstActions) { 66 MachineFunction &MF = *Asm->MF; 67 for (unsigned I = 0, N = LandingPads.size(); I < N; ++I) { 68 const LandingPadInfo *Info = LandingPads[I]; 69 MachineBasicBlock *LPad = Info->LandingPadBlock; 70 // We don't emit LSDA for single catch (...). 71 if (!MF.hasWasmLandingPadIndex(LPad)) 72 continue; 73 // Wasm EH must maintain the EH pads in the order assigned to them by the 74 // WasmEHPrepare pass. 75 unsigned LPadIndex = MF.getWasmLandingPadIndex(LPad); 76 CallSiteEntry Site = {nullptr, nullptr, Info, FirstActions[I]}; 77 if (CallSites.size() < LPadIndex + 1) 78 CallSites.resize(LPadIndex + 1); 79 CallSites[LPadIndex] = Site; 80 } 81 } 82