LLVM  4.0.0
WebAssemblyTargetMachine.cpp
Go to the documentation of this file.
1 //===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief This file defines the WebAssembly-specific subclass of TargetMachine.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "WebAssembly.h"
21 #include "llvm/CodeGen/Passes.h"
24 #include "llvm/IR/Function.h"
27 #include "llvm/Transforms/Scalar.h"
28 using namespace llvm;
29 
30 #define DEBUG_TYPE "wasm"
31 
32 // Emscripten's asm.js-style exception handling
34  "enable-emscripten-cxx-exceptions",
35  cl::desc("WebAssembly Emscripten-style exception handling"),
36  cl::init(false));
37 
38 // Emscripten's asm.js-style setjmp/longjmp handling
40  "enable-emscripten-sjlj",
41  cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
42  cl::init(false));
43 
45  // Register the target.
50 
51  // Register exception handling pass to opt
54 }
55 
56 //===----------------------------------------------------------------------===//
57 // WebAssembly Lowering public interface.
58 //===----------------------------------------------------------------------===//
59 
61  if (!RM.hasValue())
62  return Reloc::PIC_;
63  return *RM;
64 }
65 
66 /// Create an WebAssembly architecture model.
67 ///
69  const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
70  const TargetOptions &Options, Optional<Reloc::Model> RM,
73  TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128"
74  : "e-m:e-p:32:32-i64:64-n32:64-S128",
75  TT, CPU, FS, Options, getEffectiveRelocModel(RM),
76  CM, OL),
78  // WebAssembly type-checks instructions, but a noreturn function with a return
79  // type that doesn't match the context will cause a check failure. So we lower
80  // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
81  // 'unreachable' instructions which is meant for that case.
82  this->Options.TrapUnreachable = true;
83 
84  initAsmInfo();
85 
86  // Note that we don't use setRequiresStructuredCFG(true). It disables
87  // optimizations than we're ok with, and want, such as critical edge
88  // splitting and tail merging.
89 }
90 
92 
95  Attribute CPUAttr = F.getFnAttribute("target-cpu");
96  Attribute FSAttr = F.getFnAttribute("target-features");
97 
98  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
99  ? CPUAttr.getValueAsString().str()
100  : TargetCPU;
101  std::string FS = !FSAttr.hasAttribute(Attribute::None)
102  ? FSAttr.getValueAsString().str()
103  : TargetFS;
104 
105  auto &I = SubtargetMap[CPU + FS];
106  if (!I) {
107  // This needs to be done before we create a new subtarget since any
108  // creation will depend on the TM and the code generation flags on the
109  // function that reside in TargetOptions.
111  I = llvm::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
112  }
113  return I.get();
114 }
115 
116 namespace {
117 /// WebAssembly Code Generator Pass Configuration Options.
118 class WebAssemblyPassConfig final : public TargetPassConfig {
119 public:
120  WebAssemblyPassConfig(WebAssemblyTargetMachine *TM, PassManagerBase &PM)
121  : TargetPassConfig(TM, PM) {}
122 
123  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
124  return getTM<WebAssemblyTargetMachine>();
125  }
126 
127  FunctionPass *createTargetRegisterAllocator(bool) override;
128 
129  void addIRPasses() override;
130  bool addInstSelector() override;
131  void addPostRegAlloc() override;
132  bool addGCPasses() override { return false; }
133  void addPreEmitPass() override;
134 };
135 } // end anonymous namespace
136 
138  return TargetIRAnalysis([this](const Function &F) {
139  return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
140  });
141 }
142 
145  return new WebAssemblyPassConfig(this, PM);
146 }
147 
148 FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
149  return nullptr; // No reg alloc
150 }
151 
152 //===----------------------------------------------------------------------===//
153 // The following functions are called from lib/CodeGen/Passes.cpp to modify
154 // the CodeGen pass sequence.
155 //===----------------------------------------------------------------------===//
156 
157 void WebAssemblyPassConfig::addIRPasses() {
158  if (TM->Options.ThreadModel == ThreadModel::Single)
159  // In "single" mode, atomics get lowered to non-atomics.
160  addPass(createLowerAtomicPass());
161  else
162  // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
163  // control specifically what gets lowered.
164  addPass(createAtomicExpandPass(TM));
165 
166  // Fix function bitcasts, as WebAssembly requires caller and callee signatures
167  // to match.
169 
170  // Optimize "returned" function attributes.
171  if (getOptLevel() != CodeGenOpt::None)
173 
174  // If exception handling is not enabled and setjmp/longjmp handling is
175  // enabled, we lower invokes into calls and delete unreachable landingpad
176  // blocks. Lowering invokes when there is no EH support is done in
177  // TargetPassConfig::addPassesToHandleExceptions, but this runs after this
178  // function and SjLj handling expects all invokes to be lowered before.
179  if (!EnableEmException) {
180  addPass(createLowerInvokePass());
181  // The lower invoke pass may create unreachable code. Remove it in order not
182  // to process dead blocks in setjmp/longjmp handling.
184  }
185 
186  // Handle exceptions and setjmp/longjmp if enabled.
189  EnableEmSjLj));
190 
192 }
193 
194 bool WebAssemblyPassConfig::addInstSelector() {
196  addPass(
197  createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
198  // Run the argument-move pass immediately after the ScheduleDAG scheduler
199  // so that we can fix up the ARGUMENT instructions before anything else
200  // sees them in the wrong place.
202  // Set the p2align operands. This information is present during ISel, however
203  // it's inconvenient to collect. Collect it now, and update the immediate
204  // operands.
206  return false;
207 }
208 
209 void WebAssemblyPassConfig::addPostRegAlloc() {
210  // TODO: The following CodeGen passes don't currently support code containing
211  // virtual registers. Consider removing their restrictions and re-enabling
212  // them.
213 
214  // Has no asserts of its own, but was not written to handle virtual regs.
215  disablePass(&ShrinkWrapID);
216 
217  // These functions all require the NoVRegs property.
218  disablePass(&MachineCopyPropagationID);
219  disablePass(&PostRASchedulerID);
220  disablePass(&FuncletLayoutID);
221  disablePass(&StackMapLivenessID);
222  disablePass(&LiveDebugValuesID);
223  disablePass(&PatchableFunctionID);
224 
226 }
227 
228 void WebAssemblyPassConfig::addPreEmitPass() {
230 
231  // Now that we have a prologue and epilogue and all frame indices are
232  // rewritten, eliminate SP and FP. This allows them to be stackified,
233  // colored, and numbered with the rest of the registers.
235 
236  // Rewrite pseudo call_indirect instructions as real instructions.
237  // This needs to run before register stackification, because we change the
238  // order of the arguments.
240 
241  if (getOptLevel() != CodeGenOpt::None) {
242  // LiveIntervals isn't commonly run this late. Re-establish preconditions.
244 
245  // Depend on LiveIntervals and perform some optimizations on it.
247 
248  // Prepare store instructions for register stackifying.
250 
251  // Mark registers as representing wasm's value stack. This is a key
252  // code-compression technique in WebAssembly. We run this pass (and
253  // StoreResults above) very late, so that it sees as much code as possible,
254  // including code emitted by PEI and expanded by late tail duplication.
255  addPass(createWebAssemblyRegStackify());
256 
257  // Run the register coloring pass to reduce the total number of registers.
258  // This runs after stackification so that it doesn't consider registers
259  // that become stackified.
260  addPass(createWebAssemblyRegColoring());
261  }
262 
263  // Insert explicit get_local and set_local operators.
265 
266  // Eliminate multiple-entry loops.
268 
269  // Put the CFG in structured form; insert BLOCK and LOOP markers.
270  addPass(createWebAssemblyCFGStackify());
271 
272  // Lower br_unless into br_if.
274 
275  // Perform the very last peephole optimizations on the code.
276  if (getOptLevel() != CodeGenOpt::None)
277  addPass(createWebAssemblyPeephole());
278 
279  // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
281 }
FunctionPass * createWebAssemblyCallIndirectFixup()
ModulePass * createWebAssemblyLowerEmscriptenEHSjLj(bool DoEH, bool DoSjLj)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
ModulePass * createWebAssemblyFixFunctionBitcasts()
static cl::opt< bool > EnableEmSjLj("enable-emscripten-sjlj", cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"), cl::init(false))
FunctionPass * createWebAssemblyArgumentMove()
bool hasValue() const
Definition: Optional.h:125
virtual void addIRPasses()
Add common target configurable passes that perform LLVM IR to IR transforms following machine indepen...
Triple TargetTriple
Triple string, CPU name, and target feature strings the TargetMachine instance is created with...
This file a TargetTransformInfo::Concept conforming object specific to the WebAssembly target machine...
char & FuncletLayoutID
This pass lays out funclets contiguously.
FunctionPass * createWebAssemblyRegNumbering()
Analysis pass providing the TargetTransformInfo.
FunctionPass * createWebAssemblyOptimizeLiveIntervals()
TargetIRAnalysis getTargetIRAnalysis() override
Get the TargetIRAnalysis for this target.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition: Function.h:234
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
Definition: Attributes.cpp:185
virtual void addPreEmitPass()
This pass may be implemented by targets that want to run passes immediately before machine code is em...
This file declares the WebAssembly-specific subclass of TargetLoweringObjectFile. ...
FunctionPass * createLowerInvokePass()
Definition: LowerInvoke.cpp:84
FunctionPass * createAtomicExpandPass(const TargetMachine *TM)
No attributes have been set.
Definition: Attributes.h:69
Target-Independent Code Generator Pass Configuration Options.
This file declares the WebAssembly-specific subclass of TargetMachine.
#define F(x, y, z)
Definition: MD5.cpp:51
FunctionPass * createWebAssemblyPrepareForLiveIntervals()
FunctionPass * createUnreachableBlockEliminationPass()
createUnreachableBlockEliminationPass - The LLVM code generator does not work well with unreachable b...
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Definition: STLExtras.h:845
FunctionPass * createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, CodeGenOpt::Level OptLevel)
This pass converts a legalized DAG into a WebAssembly-specific DAG, ready for instruction scheduling...
static Reloc::Model getEffectiveRelocModel(Optional< Reloc::Model > RM)
This file provides WebAssembly-specific target descriptions.
FunctionPass * createWebAssemblySetP2AlignOperands()
virtual bool addInstSelector()
addInstSelector - This method should install an instruction selector pass, which converts from LLVM c...
FunctionPass * createWebAssemblyLowerBrUnless()
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
char & LiveDebugValuesID
LiveDebugValues pass.
This class describes a target machine that is implemented with the LLVM target-independent code gener...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
void initializeWebAssemblyLowerEmscriptenEHSjLjPass(PassRegistry &)
char & MachineCopyPropagationID
MachineCopyPropagation - This pass performs copy propagation on machine instructions.
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:225
static cl::opt< bool > EnableEmException("enable-emscripten-cxx-exceptions", cl::desc("WebAssembly Emscripten-style exception handling"), cl::init(false))
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
char & PostRASchedulerID
createPostRAScheduler - This pass performs post register allocation scheduling.
FunctionPass * createWebAssemblyStoreResults()
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
char & StackMapLivenessID
StackMapLiveness - This pass analyses the register live-out set of stackmap/patchpoint intrinsics and...
FunctionPass * createWebAssemblyRegStackify()
TargetPassConfig * createPassConfig(PassManagerBase &PM) override
Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of ...
FunctionPass * createWebAssemblyExplicitLocals()
WebAssemblyTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Optional< Reloc::Model > RM, CodeModel::Model CM, CodeGenOpt::Level OL)
Create an WebAssembly architecture model.
FunctionPass * createWebAssemblyCFGStackify()
FunctionPass * createWebAssemblyFixIrreducibleControlFlow()
Pass * createLowerAtomicPass()
Target - Wrapper for Target specific information.
virtual void addPostRegAlloc()
This method may be implemented by targets that want to run passes after register allocation pass pipe...
FunctionPass * createWebAssemblyPeephole()
char & PatchableFunctionID
This pass implements the "patchable-function" attribute.
FunctionPass * createWebAssemblyReplacePhysRegs()
#define I(x, y, z)
Definition: MD5.cpp:54
void resetTargetOptions(const Function &F) const
Reset the target options based on the function's attributes.
void LLVMInitializeWebAssemblyTarget()
FunctionPass * createWebAssemblyRegColoring()
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:178
RegisterTargetMachine - Helper template for registering a target machine implementation, for use in the target machine initialization function.
char & ShrinkWrapID
ShrinkWrap pass. Look for the best place to insert save and restore.
Definition: ShrinkWrap.cpp:211
FunctionPass * createWebAssemblyOptimizeReturned()
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
unsigned TrapUnreachable
Emit target-specific trap instruction for 'unreachable' IR instructions.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
Target & getTheWebAssemblyTarget32()
const WebAssemblySubtarget * getSubtargetImpl(const Function &F) const override
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Target & getTheWebAssemblyTarget64()