xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRefTypeMem2Local.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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