summaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm16/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp
diff options
context:
space:
mode:
authorvvvv <[email protected]>2024-02-06 20:01:22 +0300
committervvvv <[email protected]>2024-02-06 20:22:16 +0300
commit0203b7a9a40828bb2bd4c32029b79ff0ea3d1f8f (patch)
treee630d0d5bd0bd29fc8c2d2842ed2cfde781b993a /contrib/libs/llvm16/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp
parentba27db76d99d12a4f1c06960b5449423218614c4 (diff)
llvm16 targets
Diffstat (limited to 'contrib/libs/llvm16/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp')
-rw-r--r--contrib/libs/llvm16/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/contrib/libs/llvm16/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp b/contrib/libs/llvm16/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp
new file mode 100644
index 00000000000..a1e0db69239
--- /dev/null
+++ b/contrib/libs/llvm16/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp
@@ -0,0 +1,203 @@
+//===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements several utility functions for WebAssembly.
+///
+//===----------------------------------------------------------------------===//
+
+#include "WebAssemblyUtilities.h"
+#include "WebAssemblyMachineFunctionInfo.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/MC/MCContext.h"
+using namespace llvm;
+
+// Exception handling & setjmp-longjmp handling related options. These are
+// defined here to be shared between WebAssembly and its subdirectories.
+
+// Emscripten's asm.js-style exception handling
+cl::opt<bool> WebAssembly::WasmEnableEmEH(
+ "enable-emscripten-cxx-exceptions",
+ cl::desc("WebAssembly Emscripten-style exception handling"),
+ cl::init(false));
+// Emscripten's asm.js-style setjmp/longjmp handling
+cl::opt<bool> WebAssembly::WasmEnableEmSjLj(
+ "enable-emscripten-sjlj",
+ cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
+ cl::init(false));
+// Exception handling using wasm EH instructions
+cl::opt<bool>
+ WebAssembly::WasmEnableEH("wasm-enable-eh",
+ cl::desc("WebAssembly exception handling"),
+ cl::init(false));
+// setjmp/longjmp handling using wasm EH instrutions
+cl::opt<bool>
+ WebAssembly::WasmEnableSjLj("wasm-enable-sjlj",
+ cl::desc("WebAssembly setjmp/longjmp handling"),
+ cl::init(false));
+
+// Function names in libc++abi and libunwind
+const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
+const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
+const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
+const char *const WebAssembly::PersonalityWrapperFn =
+ "_Unwind_Wasm_CallPersonality";
+
+/// Test whether MI is a child of some other node in an expression tree.
+bool WebAssembly::isChild(const MachineInstr &MI,
+ const WebAssemblyFunctionInfo &MFI) {
+ if (MI.getNumOperands() == 0)
+ return false;
+ const MachineOperand &MO = MI.getOperand(0);
+ if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
+ return false;
+ Register Reg = MO.getReg();
+ return Reg.isVirtual() && MFI.isVRegStackified(Reg);
+}
+
+bool WebAssembly::mayThrow(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ case WebAssembly::THROW:
+ case WebAssembly::THROW_S:
+ case WebAssembly::RETHROW:
+ case WebAssembly::RETHROW_S:
+ return true;
+ }
+ if (isCallIndirect(MI.getOpcode()))
+ return true;
+ if (!MI.isCall())
+ return false;
+
+ const MachineOperand &MO = getCalleeOp(MI);
+ assert(MO.isGlobal() || MO.isSymbol());
+
+ if (MO.isSymbol()) {
+ // Some intrinsics are lowered to calls to external symbols, which are then
+ // lowered to calls to library functions. Most of libcalls don't throw, but
+ // we only list some of them here now.
+ // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
+ // instead for more accurate info.
+ const char *Name = MO.getSymbolName();
+ if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
+ strcmp(Name, "memset") == 0)
+ return false;
+ return true;
+ }
+
+ const auto *F = dyn_cast<Function>(MO.getGlobal());
+ if (!F)
+ return true;
+ if (F->doesNotThrow())
+ return false;
+ // These functions never throw
+ if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
+ F->getName() == StdTerminateFn)
+ return false;
+
+ // TODO Can we exclude call instructions that are marked as 'nounwind' in the
+ // original LLVm IR? (Even when the callee may throw)
+ return true;
+}
+
+const MachineOperand &WebAssembly::getCalleeOp(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ case WebAssembly::CALL:
+ case WebAssembly::CALL_S:
+ case WebAssembly::RET_CALL:
+ case WebAssembly::RET_CALL_S:
+ return MI.getOperand(MI.getNumExplicitDefs());
+ case WebAssembly::CALL_INDIRECT:
+ case WebAssembly::CALL_INDIRECT_S:
+ case WebAssembly::RET_CALL_INDIRECT:
+ case WebAssembly::RET_CALL_INDIRECT_S:
+ return MI.getOperand(MI.getNumExplicitOperands() - 1);
+ default:
+ llvm_unreachable("Not a call instruction");
+ }
+}
+
+MCSymbolWasm *WebAssembly::getOrCreateFunctionTableSymbol(
+ MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
+ StringRef Name = "__indirect_function_table";
+ MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
+ if (Sym) {
+ if (!Sym->isFunctionTable())
+ Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
+ } else {
+ Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
+ Sym->setFunctionTable();
+ // The default function table is synthesized by the linker.
+ Sym->setUndefined();
+ }
+ // MVP object files can't have symtab entries for tables.
+ if (!(Subtarget && Subtarget->hasReferenceTypes()))
+ Sym->setOmitFromLinkingSection();
+ return Sym;
+}
+
+MCSymbolWasm *WebAssembly::getOrCreateFuncrefCallTableSymbol(
+ MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
+ StringRef Name = "__funcref_call_table";
+ MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
+ if (Sym) {
+ if (!Sym->isFunctionTable())
+ Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
+ } else {
+ Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
+
+ // Setting Weak ensure only one table is left after linking when multiple
+ // modules define the table.
+ Sym->setWeak(true);
+
+ wasm::WasmLimits Limits = {0, 1, 1};
+ wasm::WasmTableType TableType = {wasm::WASM_TYPE_FUNCREF, Limits};
+ Sym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
+ Sym->setTableType(TableType);
+ }
+ // MVP object files can't have symtab entries for tables.
+ if (!(Subtarget && Subtarget->hasReferenceTypes()))
+ Sym->setOmitFromLinkingSection();
+ return Sym;
+}
+
+// Find a catch instruction from an EH pad.
+MachineInstr *WebAssembly::findCatch(MachineBasicBlock *EHPad) {
+ assert(EHPad->isEHPad());
+ auto Pos = EHPad->begin();
+ // Skip any label or debug instructions. Also skip 'end' marker instructions
+ // that may exist after marker placement in CFGStackify.
+ while (Pos != EHPad->end() &&
+ (Pos->isLabel() || Pos->isDebugInstr() || isMarker(Pos->getOpcode())))
+ Pos++;
+ if (Pos != EHPad->end() && WebAssembly::isCatch(Pos->getOpcode()))
+ return &*Pos;
+ return nullptr;
+}
+
+unsigned WebAssembly::getCopyOpcodeForRegClass(const TargetRegisterClass *RC) {
+ assert(RC != nullptr);
+ switch (RC->getID()) {
+ case WebAssembly::I32RegClassID:
+ return WebAssembly::COPY_I32;
+ case WebAssembly::I64RegClassID:
+ return WebAssembly::COPY_I64;
+ case WebAssembly::F32RegClassID:
+ return WebAssembly::COPY_F32;
+ case WebAssembly::F64RegClassID:
+ return WebAssembly::COPY_F64;
+ case WebAssembly::V128RegClassID:
+ return WebAssembly::COPY_V128;
+ case WebAssembly::FUNCREFRegClassID:
+ return WebAssembly::COPY_FUNCREF;
+ case WebAssembly::EXTERNREFRegClassID:
+ return WebAssembly::COPY_EXTERNREF;
+ default:
+ llvm_unreachable("Unexpected register class");
+ }
+}