WasmException.cpp 4.1 KB

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