1 //=== WebAssemblyRefTypeMem2Local.cpp - WebAssembly RefType Mem2Local -----===//
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 /// \file
10 /// Assign reference type allocas to local addrspace (addrspace(1)) so that
11 /// their loads and stores can be lowered to local.gets/local.sets.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "Utils/WasmAddressSpaces.h"
16 #include "Utils/WebAssemblyTypeUtilities.h"
17 #include "WebAssembly.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/InstVisitor.h"
20 #include "llvm/IR/ValueHandle.h"
21 #include "llvm/Pass.h"
22 using namespace llvm;
23
24 #define DEBUG_TYPE "wasm-ref-type-mem2local"
25
26 namespace {
27 class WebAssemblyRefTypeMem2Local final
28 : public FunctionPass,
29 public InstVisitor<WebAssemblyRefTypeMem2Local> {
getPassName() const30 StringRef getPassName() const override {
31 return "WebAssembly Reference Types Memory to Local";
32 }
33
getAnalysisUsage(AnalysisUsage & AU) const34 void getAnalysisUsage(AnalysisUsage &AU) const override {
35 AU.setPreservesCFG();
36 FunctionPass::getAnalysisUsage(AU);
37 }
38
39 bool runOnFunction(Function &F) override;
40 bool Changed = false;
41
42 public:
43 static char ID;
WebAssemblyRefTypeMem2Local()44 WebAssemblyRefTypeMem2Local() : FunctionPass(ID) {}
45
46 void visitAllocaInst(AllocaInst &AI);
47 };
48 } // End anonymous namespace
49
50 char WebAssemblyRefTypeMem2Local::ID = 0;
51 INITIALIZE_PASS(WebAssemblyRefTypeMem2Local, DEBUG_TYPE,
52 "Assign reference type allocas to local address space", true,
53 false)
54
createWebAssemblyRefTypeMem2Local()55 FunctionPass *llvm::createWebAssemblyRefTypeMem2Local() {
56 return new WebAssemblyRefTypeMem2Local();
57 }
58
visitAllocaInst(AllocaInst & AI)59 void WebAssemblyRefTypeMem2Local::visitAllocaInst(AllocaInst &AI) {
60 if (WebAssembly::isWebAssemblyReferenceType(AI.getAllocatedType())) {
61 Changed = true;
62 IRBuilder<> IRB(AI.getContext());
63 IRB.SetInsertPoint(&AI);
64 auto *NewAI = IRB.CreateAlloca(AI.getAllocatedType(),
65 WebAssembly::WASM_ADDRESS_SPACE_VAR, nullptr,
66 AI.getName() + ".var");
67
68 // The below is basically equivalent to AI.replaceAllUsesWith(NewAI), but we
69 // cannot use it because it requires the old and new types be the same,
70 // which is not true here because the address spaces are different.
71 if (AI.hasValueHandle())
72 ValueHandleBase::ValueIsRAUWd(&AI, NewAI);
73 if (AI.isUsedByMetadata())
74 ValueAsMetadata::handleRAUW(&AI, NewAI);
75 while (!AI.materialized_use_empty()) {
76 Use &U = *AI.materialized_use_begin();
77 U.set(NewAI);
78 }
79
80 AI.eraseFromParent();
81 }
82 }
83
runOnFunction(Function & F)84 bool WebAssemblyRefTypeMem2Local::runOnFunction(Function &F) {
85 LLVM_DEBUG(dbgs() << "********** WebAssembly RefType Mem2Local **********\n"
86 "********** Function: "
87 << F.getName() << '\n');
88
89 if (F.getFnAttribute("target-features")
90 .getValueAsString()
91 .contains("+reference-types"))
92 visit(F);
93 return Changed;
94 }
95