diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2024-07-27 23:34:35 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-10-23 18:26:01 +0000 |
| commit | 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch) | |
| tree | 6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp | |
| parent | 6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff) | |
| parent | ac9a064cb179f3425b310fa2847f8764ac970a4d (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp index 2db1b6493cc4..23539a5f4b26 100644 --- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -68,6 +68,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() { initializeLowerGlobalDtorsLegacyPassPass(PR); initializeFixFunctionBitcastsPass(PR); initializeOptimizeReturnedPass(PR); + initializeWebAssemblyRefTypeMem2LocalPass(PR); initializeWebAssemblyArgumentMovePass(PR); initializeWebAssemblySetP2AlignOperandsPass(PR); initializeWebAssemblyReplacePhysRegsPass(PR); @@ -89,7 +90,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() { initializeWebAssemblyMCLowerPrePassPass(PR); initializeWebAssemblyLowerRefTypesIntPtrConvPass(PR); initializeWebAssemblyFixBrTableDefaultsPass(PR); - initializeWebAssemblyDAGToDAGISelPass(PR); + initializeWebAssemblyDAGToDAGISelLegacyPass(PR); } //===----------------------------------------------------------------------===// @@ -127,7 +128,8 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine( "n32:64-S128-ni:1:10:20"), TT, CPU, FS, Options, getEffectiveRelocModel(RM, TT), getEffectiveCodeModel(CM, CodeModel::Large), OL), - TLOF(new WebAssemblyTargetObjectFile()) { + TLOF(new WebAssemblyTargetObjectFile()), + UsesMultivalueABI(Options.MCOptions.getABIName() == "experimental-mv") { // WebAssembly type-checks instructions, but a noreturn function with a return // type that doesn't match the context will cause a check failure. So we lower // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's @@ -200,7 +202,8 @@ public: bool runOnModule(Module &M) override { FeatureBitset Features = coalesceFeatures(M); - std::string FeatureStr = getFeatureString(Features); + std::string FeatureStr = + getFeatureString(Features, WasmTM->getTargetFeatureString()); WasmTM->setTargetFeatureString(FeatureStr); for (auto &F : M) replaceFeatures(F, FeatureStr); @@ -238,12 +241,17 @@ private: return Features; } - std::string getFeatureString(const FeatureBitset &Features) { + static std::string getFeatureString(const FeatureBitset &Features, + StringRef TargetFS) { std::string Ret; for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) { if (Features[KV.Value]) Ret += (StringRef("+") + KV.Key + ",").str(); } + SubtargetFeatures TF{TargetFS}; + for (std::string const &F : TF.getFeatures()) + if (!SubtargetFeatures::isEnabled(F)) + Ret += F + ","; return Ret; } @@ -284,6 +292,17 @@ private: bool Stripped = false; for (auto &GV : M.globals()) { if (GV.isThreadLocal()) { + // replace `@llvm.threadlocal.address.pX(GV)` with `GV`. + for (Use &U : make_early_inc_range(GV.uses())) { + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U.getUser())) { + if (II->getIntrinsicID() == Intrinsic::threadlocal_address && + II->getArgOperand(0) == &GV) { + II->replaceAllUsesWith(&GV); + II->eraseFromParent(); + } + } + } + Stripped = true; GV.setThreadLocal(false); } @@ -366,18 +385,36 @@ FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) { using WebAssembly::WasmEnableEH; using WebAssembly::WasmEnableEmEH; using WebAssembly::WasmEnableEmSjLj; +using WebAssembly::WasmEnableExnref; using WebAssembly::WasmEnableSjLj; static void basicCheckForEHAndSjLj(TargetMachine *TM) { - // Before checking, we make sure TargetOptions.ExceptionModel is the same as + + // You can't enable two modes of EH at the same time + if (WasmEnableEmEH && WasmEnableEH) + report_fatal_error( + "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh"); + // You can't enable two modes of SjLj at the same time + if (WasmEnableEmSjLj && WasmEnableSjLj) + report_fatal_error( + "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj"); + // You can't mix Emscripten EH with Wasm SjLj. + if (WasmEnableEmEH && WasmEnableSjLj) + report_fatal_error( + "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj"); + if (WasmEnableExnref && !WasmEnableEH) + report_fatal_error( + "-wasm-enable-exnref should be used with -wasm-enable-eh"); + + // Here we make sure TargetOptions.ExceptionModel is the same as // MCAsmInfo.ExceptionsType. Normally these have to be the same, because clang // stores the exception model info in LangOptions, which is later transferred // to TargetOptions and MCAsmInfo. But when clang compiles bitcode directly, // clang's LangOptions is not used and thus the exception model info is not // correctly transferred to TargetOptions and MCAsmInfo, so we make sure we - // have the correct exception model in WebAssemblyMCAsmInfo constructor. - // But in this case TargetOptions is still not updated, so we make sure they - // are the same. + // have the correct exception model in WebAssemblyMCAsmInfo constructor. But + // in this case TargetOptions is still not updated, so we make sure they are + // the same. TM->Options.ExceptionModel = TM->getMCAsmInfo()->getExceptionHandlingType(); // Basic Correctness checking related to -exception-model @@ -397,20 +434,8 @@ static void basicCheckForEHAndSjLj(TargetMachine *TM) { TM->Options.ExceptionModel == ExceptionHandling::Wasm) report_fatal_error( "-exception-model=wasm only allowed with at least one of " - "-wasm-enable-eh or -wasm-enable-sjj"); + "-wasm-enable-eh or -wasm-enable-sjlj"); - // You can't enable two modes of EH at the same time - if (WasmEnableEmEH && WasmEnableEH) - report_fatal_error( - "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh"); - // You can't enable two modes of SjLj at the same time - if (WasmEnableEmSjLj && WasmEnableSjLj) - report_fatal_error( - "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj"); - // You can't mix Emscripten EH with Wasm SjLj. - if (WasmEnableEmEH && WasmEnableSjLj) - report_fatal_error( - "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj"); // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim // measure, but some code will error out at compile time in this combination. // See WebAssemblyLowerEmscriptenEHSjLj pass for details. @@ -465,20 +490,14 @@ void WebAssemblyPassConfig::addIRPasses() { } void WebAssemblyPassConfig::addISelPrepare() { - WebAssemblyTargetMachine *WasmTM = - static_cast<WebAssemblyTargetMachine *>(TM); - const WebAssemblySubtarget *Subtarget = - WasmTM->getSubtargetImpl(std::string(WasmTM->getTargetCPU()), - std::string(WasmTM->getTargetFeatureString())); - if (Subtarget->hasReferenceTypes()) { - // We need to remove allocas for reference types - addPass(createPromoteMemoryToRegisterPass(true)); - } + // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that + // loads and stores are promoted to local.gets/local.sets. + addPass(createWebAssemblyRefTypeMem2Local()); // Lower atomics and TLS if necessary addPass(new CoalesceFeaturesAndStripAtomics(&getWebAssemblyTargetMachine())); // This is a no-op if atomics are not used in the module - addPass(createAtomicExpandPass()); + addPass(createAtomicExpandLegacyPass()); TargetPassConfig::addISelPrepare(); } @@ -499,6 +518,10 @@ bool WebAssemblyPassConfig::addInstSelector() { // Eliminate range checks and add default targets to br_table instructions. addPass(createWebAssemblyFixBrTableDefaults()); + // unreachable is terminator, non-terminator instruction after it is not + // allowed. + addPass(createWebAssemblyCleanCodeAfterTrap()); + return false; } |
