1*10e730a2SDan Gohman //===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
2*10e730a2SDan Gohman //
3*10e730a2SDan Gohman //                     The LLVM Compiler Infrastructure
4*10e730a2SDan Gohman //
5*10e730a2SDan Gohman // This file is distributed under the University of Illinois Open Source
6*10e730a2SDan Gohman // License. See LICENSE.TXT for details.
7*10e730a2SDan Gohman //
8*10e730a2SDan Gohman //===----------------------------------------------------------------------===//
9*10e730a2SDan Gohman ///
10*10e730a2SDan Gohman /// \file
11*10e730a2SDan Gohman /// \brief This file defines the WebAssembly-specific subclass of TargetMachine.
12*10e730a2SDan Gohman ///
13*10e730a2SDan Gohman //===----------------------------------------------------------------------===//
14*10e730a2SDan Gohman 
15*10e730a2SDan Gohman #include "WebAssembly.h"
16*10e730a2SDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17*10e730a2SDan Gohman #include "WebAssemblyTargetMachine.h"
18*10e730a2SDan Gohman #include "WebAssemblyTargetObjectFile.h"
19*10e730a2SDan Gohman #include "WebAssemblyTargetTransformInfo.h"
20*10e730a2SDan Gohman #include "llvm/CodeGen/MachineFunctionPass.h"
21*10e730a2SDan Gohman #include "llvm/CodeGen/Passes.h"
22*10e730a2SDan Gohman #include "llvm/CodeGen/RegAllocRegistry.h"
23*10e730a2SDan Gohman #include "llvm/IR/Function.h"
24*10e730a2SDan Gohman #include "llvm/Support/CommandLine.h"
25*10e730a2SDan Gohman #include "llvm/Support/TargetRegistry.h"
26*10e730a2SDan Gohman #include "llvm/Target/TargetOptions.h"
27*10e730a2SDan Gohman using namespace llvm;
28*10e730a2SDan Gohman 
29*10e730a2SDan Gohman #define DEBUG_TYPE "wasm"
30*10e730a2SDan Gohman 
31*10e730a2SDan Gohman extern "C" void LLVMInitializeWebAssemblyTarget() {
32*10e730a2SDan Gohman   // Register the target.
33*10e730a2SDan Gohman   RegisterTargetMachine<WebAssemblyTargetMachine> X(TheWebAssemblyTarget);
34*10e730a2SDan Gohman }
35*10e730a2SDan Gohman 
36*10e730a2SDan Gohman //===----------------------------------------------------------------------===//
37*10e730a2SDan Gohman // WebAssembly Lowering public interface.
38*10e730a2SDan Gohman //===----------------------------------------------------------------------===//
39*10e730a2SDan Gohman 
40*10e730a2SDan Gohman /// Create an WebAssembly architecture model.
41*10e730a2SDan Gohman ///
42*10e730a2SDan Gohman WebAssemblyTargetMachine::WebAssemblyTargetMachine(
43*10e730a2SDan Gohman     const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
44*10e730a2SDan Gohman     const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
45*10e730a2SDan Gohman     CodeGenOpt::Level OL)
46*10e730a2SDan Gohman     : LLVMTargetMachine(T, TT.isArch64Bit()
47*10e730a2SDan Gohman                                ? "e-p:64:64-i64:64-v128:8:128-n32:64-S128"
48*10e730a2SDan Gohman                                : "e-p:32:32-i64:64-v128:8:128-n32:64-S128",
49*10e730a2SDan Gohman                         TT, CPU, FS, Options, RM, CM, OL),
50*10e730a2SDan Gohman       TLOF(make_unique<WebAssemblyTargetObjectFile>()) {
51*10e730a2SDan Gohman   initAsmInfo();
52*10e730a2SDan Gohman 
53*10e730a2SDan Gohman   // We need a reducible CFG, so disable some optimizations which tend to
54*10e730a2SDan Gohman   // introduce irreducibility.
55*10e730a2SDan Gohman   setRequiresStructuredCFG(true);
56*10e730a2SDan Gohman }
57*10e730a2SDan Gohman 
58*10e730a2SDan Gohman WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}
59*10e730a2SDan Gohman 
60*10e730a2SDan Gohman const WebAssemblySubtarget *
61*10e730a2SDan Gohman WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
62*10e730a2SDan Gohman   Attribute CPUAttr = F.getFnAttribute("target-cpu");
63*10e730a2SDan Gohman   Attribute FSAttr = F.getFnAttribute("target-features");
64*10e730a2SDan Gohman 
65*10e730a2SDan Gohman   std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
66*10e730a2SDan Gohman                         ? CPUAttr.getValueAsString().str()
67*10e730a2SDan Gohman                         : TargetCPU;
68*10e730a2SDan Gohman   std::string FS = !FSAttr.hasAttribute(Attribute::None)
69*10e730a2SDan Gohman                        ? FSAttr.getValueAsString().str()
70*10e730a2SDan Gohman                        : TargetFS;
71*10e730a2SDan Gohman 
72*10e730a2SDan Gohman   auto &I = SubtargetMap[CPU + FS];
73*10e730a2SDan Gohman   if (!I) {
74*10e730a2SDan Gohman     // This needs to be done before we create a new subtarget since any
75*10e730a2SDan Gohman     // creation will depend on the TM and the code generation flags on the
76*10e730a2SDan Gohman     // function that reside in TargetOptions.
77*10e730a2SDan Gohman     resetTargetOptions(F);
78*10e730a2SDan Gohman     I = make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
79*10e730a2SDan Gohman   }
80*10e730a2SDan Gohman   return I.get();
81*10e730a2SDan Gohman }
82*10e730a2SDan Gohman 
83*10e730a2SDan Gohman namespace {
84*10e730a2SDan Gohman /// WebAssembly Code Generator Pass Configuration Options.
85*10e730a2SDan Gohman class WebAssemblyPassConfig final : public TargetPassConfig {
86*10e730a2SDan Gohman public:
87*10e730a2SDan Gohman   WebAssemblyPassConfig(WebAssemblyTargetMachine *TM, PassManagerBase &PM)
88*10e730a2SDan Gohman       : TargetPassConfig(TM, PM) {}
89*10e730a2SDan Gohman 
90*10e730a2SDan Gohman   WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
91*10e730a2SDan Gohman     return getTM<WebAssemblyTargetMachine>();
92*10e730a2SDan Gohman   }
93*10e730a2SDan Gohman 
94*10e730a2SDan Gohman   FunctionPass *createTargetRegisterAllocator(bool) override;
95*10e730a2SDan Gohman   void addFastRegAlloc(FunctionPass *RegAllocPass) override;
96*10e730a2SDan Gohman   void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override;
97*10e730a2SDan Gohman 
98*10e730a2SDan Gohman   void addIRPasses() override;
99*10e730a2SDan Gohman   bool addPreISel() override;
100*10e730a2SDan Gohman   bool addInstSelector() override;
101*10e730a2SDan Gohman   bool addILPOpts() override;
102*10e730a2SDan Gohman   void addPreRegAlloc() override;
103*10e730a2SDan Gohman   void addRegAllocPasses(bool Optimized);
104*10e730a2SDan Gohman   void addPostRegAlloc() override;
105*10e730a2SDan Gohman   void addPreSched2() override;
106*10e730a2SDan Gohman   void addPreEmitPass() override;
107*10e730a2SDan Gohman };
108*10e730a2SDan Gohman } // end anonymous namespace
109*10e730a2SDan Gohman 
110*10e730a2SDan Gohman TargetIRAnalysis WebAssemblyTargetMachine::getTargetIRAnalysis() {
111*10e730a2SDan Gohman   return TargetIRAnalysis([this](Function &F) {
112*10e730a2SDan Gohman     return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
113*10e730a2SDan Gohman   });
114*10e730a2SDan Gohman }
115*10e730a2SDan Gohman 
116*10e730a2SDan Gohman TargetPassConfig *
117*10e730a2SDan Gohman WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
118*10e730a2SDan Gohman   return new WebAssemblyPassConfig(this, PM);
119*10e730a2SDan Gohman }
120*10e730a2SDan Gohman 
121*10e730a2SDan Gohman FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
122*10e730a2SDan Gohman   return nullptr; // No reg alloc
123*10e730a2SDan Gohman }
124*10e730a2SDan Gohman 
125*10e730a2SDan Gohman void WebAssemblyPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
126*10e730a2SDan Gohman   assert(!RegAllocPass && "WebAssembly uses no regalloc!");
127*10e730a2SDan Gohman   addRegAllocPasses(false);
128*10e730a2SDan Gohman }
129*10e730a2SDan Gohman 
130*10e730a2SDan Gohman void WebAssemblyPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
131*10e730a2SDan Gohman   assert(!RegAllocPass && "WebAssembly uses no regalloc!");
132*10e730a2SDan Gohman   addRegAllocPasses(true);
133*10e730a2SDan Gohman }
134*10e730a2SDan Gohman 
135*10e730a2SDan Gohman //===----------------------------------------------------------------------===//
136*10e730a2SDan Gohman // The following functions are called from lib/CodeGen/Passes.cpp to modify
137*10e730a2SDan Gohman // the CodeGen pass sequence.
138*10e730a2SDan Gohman //===----------------------------------------------------------------------===//
139*10e730a2SDan Gohman 
140*10e730a2SDan Gohman void WebAssemblyPassConfig::addIRPasses() {
141*10e730a2SDan Gohman   // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
142*10e730a2SDan Gohman   // control specifically what gets lowered.
143*10e730a2SDan Gohman   addPass(createAtomicExpandPass(&getTM<WebAssemblyTargetMachine>()));
144*10e730a2SDan Gohman 
145*10e730a2SDan Gohman   TargetPassConfig::addIRPasses();
146*10e730a2SDan Gohman }
147*10e730a2SDan Gohman 
148*10e730a2SDan Gohman bool WebAssemblyPassConfig::addPreISel() { return false; }
149*10e730a2SDan Gohman 
150*10e730a2SDan Gohman bool WebAssemblyPassConfig::addInstSelector() {
151*10e730a2SDan Gohman   addPass(
152*10e730a2SDan Gohman       createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
153*10e730a2SDan Gohman   return false;
154*10e730a2SDan Gohman }
155*10e730a2SDan Gohman 
156*10e730a2SDan Gohman bool WebAssemblyPassConfig::addILPOpts() { return true; }
157*10e730a2SDan Gohman 
158*10e730a2SDan Gohman void WebAssemblyPassConfig::addPreRegAlloc() {}
159*10e730a2SDan Gohman 
160*10e730a2SDan Gohman void WebAssemblyPassConfig::addRegAllocPasses(bool Optimized) {}
161*10e730a2SDan Gohman 
162*10e730a2SDan Gohman void WebAssemblyPassConfig::addPostRegAlloc() {}
163*10e730a2SDan Gohman 
164*10e730a2SDan Gohman void WebAssemblyPassConfig::addPreSched2() {}
165*10e730a2SDan Gohman 
166*10e730a2SDan Gohman void WebAssemblyPassConfig::addPreEmitPass() {}
167