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"
22using namespace llvm;
23
24#define DEBUG_TYPE "wasm-ref-type-mem2local"
25
26namespace {
27class WebAssemblyRefTypeMem2Local final
28 : public FunctionPass,
29 public InstVisitor<WebAssemblyRefTypeMem2Local> {
30 StringRef getPassName() const override {
31 return "WebAssembly Reference Types Memory to Local";
32 }
33
34 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
42public:
43 static char ID;
44 WebAssemblyRefTypeMem2Local() : FunctionPass(ID) {}
45
46 void visitAllocaInst(AllocaInst &AI);
47};
48} // End anonymous namespace
49
50char WebAssemblyRefTypeMem2Local::ID = 0;
51INITIALIZE_PASS(WebAssemblyRefTypeMem2Local, DEBUG_TYPE,
52 "Assign reference type allocas to local address space", true,
53 false)
54
55FunctionPass *llvm::createWebAssemblyRefTypeMem2Local() {
56 return new WebAssemblyRefTypeMem2Local();
57}
58
59void WebAssemblyRefTypeMem2Local::visitAllocaInst(AllocaInst &AI) {
60 if (WebAssembly::isWebAssemblyReferenceType(Ty: AI.getAllocatedType())) {
61 Changed = true;
62 IRBuilder<> IRB(AI.getContext());
63 IRB.SetInsertPoint(&AI);
64 auto *NewAI = IRB.CreateAlloca(Ty: AI.getAllocatedType(),
65 AddrSpace: WebAssembly::WASM_ADDRESS_SPACE_VAR, ArraySize: nullptr,
66 Name: 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(Old: &AI, New: NewAI);
73 if (AI.isUsedByMetadata())
74 ValueAsMetadata::handleRAUW(From: &AI, To: 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
84bool WebAssemblyRefTypeMem2Local::runOnFunction(Function &F) {
85 LLVM_DEBUG(dbgs() << "********** WebAssembly RefType Mem2Local **********\n"
86 "********** Function: "
87 << F.getName() << '\n');
88
89 if (F.getFnAttribute(Kind: "target-features")
90 .getValueAsString()
91 .contains(Other: "+reference-types"))
92 visit(F);
93 return Changed;
94}
95