Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp
35271 views
//===-- CodeGen/AsmPrinter/WasmException.cpp - Wasm Exception Impl --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains support for writing WebAssembly exception info into asm9// files.10//11//===----------------------------------------------------------------------===//1213#include "WasmException.h"14#include "llvm/CodeGen/AsmPrinter.h"15#include "llvm/CodeGen/MachineFunction.h"16#include "llvm/IR/Mangler.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCStreamer.h"19using namespace llvm;2021void WasmException::endModule() {22// These are symbols used to throw/catch C++ exceptions and C longjmps. These23// symbols have to be emitted somewhere once in the module. Check if each of24// the symbols has already been created, i.e., we have at least one 'throw' or25// 'catch' instruction with the symbol in the module, and emit the symbol only26// if so.27//28// But in dynamic linking, it is in general not possible to come up with a29// module instantiating order in which tag-defining modules are loaded before30// the importing modules. So we make them undefined symbols here, define tags31// in the JS side, and feed them to each importing module.32if (!Asm->isPositionIndependent()) {33for (const char *SymName : {"__cpp_exception", "__c_longjmp"}) {34SmallString<60> NameStr;35Mangler::getNameWithPrefix(NameStr, SymName, Asm->getDataLayout());36if (Asm->OutContext.lookupSymbol(NameStr)) {37MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol(SymName);38Asm->OutStreamer->emitLabel(ExceptionSym);39}40}41}42}4344void WasmException::endFunction(const MachineFunction *MF) {45bool ShouldEmitExceptionTable = false;46for (const LandingPadInfo &Info : MF->getLandingPads()) {47if (MF->hasWasmLandingPadIndex(Info.LandingPadBlock)) {48ShouldEmitExceptionTable = true;49break;50}51}52if (!ShouldEmitExceptionTable)53return;54MCSymbol *LSDALabel = emitExceptionTable();55assert(LSDALabel && ".GCC_exception_table has not been emitted!");5657// Wasm requires every data section symbol to have a .size set. So we emit an58// end marker and set the size as the difference between the start end the end59// marker.60MCSymbol *LSDAEndLabel = Asm->createTempSymbol("GCC_except_table_end");61Asm->OutStreamer->emitLabel(LSDAEndLabel);62MCContext &OutContext = Asm->OutStreamer->getContext();63const MCExpr *SizeExp = MCBinaryExpr::createSub(64MCSymbolRefExpr::create(LSDAEndLabel, OutContext),65MCSymbolRefExpr::create(LSDALabel, OutContext), OutContext);66Asm->OutStreamer->emitELFSize(LSDALabel, SizeExp);67}6869// Compute the call-site table for wasm EH. Even though we use the same function70// name to share the common routines, a call site entry in the table corresponds71// to not a call site for possibly-throwing functions but a landing pad. In wasm72// EH the VM is responsible for stack unwinding. After an exception occurs and73// the stack is unwound, the control flow is transferred to wasm 'catch'74// instruction by the VM, after which the personality function is called from75// the compiler-generated code. Refer to WasmEHPrepare pass for more76// information.77void WasmException::computeCallSiteTable(78SmallVectorImpl<CallSiteEntry> &CallSites,79SmallVectorImpl<CallSiteRange> &CallSiteRanges,80const SmallVectorImpl<const LandingPadInfo *> &LandingPads,81const SmallVectorImpl<unsigned> &FirstActions) {82MachineFunction &MF = *Asm->MF;83for (unsigned I = 0, N = LandingPads.size(); I < N; ++I) {84const LandingPadInfo *Info = LandingPads[I];85MachineBasicBlock *LPad = Info->LandingPadBlock;86// We don't emit LSDA for single catch (...).87if (!MF.hasWasmLandingPadIndex(LPad))88continue;89// Wasm EH must maintain the EH pads in the order assigned to them by the90// WasmEHPrepare pass.91unsigned LPadIndex = MF.getWasmLandingPadIndex(LPad);92CallSiteEntry Site = {nullptr, nullptr, Info, FirstActions[I]};93if (CallSites.size() < LPadIndex + 1)94CallSites.resize(LPadIndex + 1);95CallSites[LPadIndex] = Site;96}97}9899100