Line data Source code
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 : /// This file defines the WebAssembly-specific subclass of TargetMachine.
12 : ///
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "WebAssemblyTargetMachine.h"
16 : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17 : #include "WebAssembly.h"
18 : #include "WebAssemblyTargetObjectFile.h"
19 : #include "WebAssemblyTargetTransformInfo.h"
20 : #include "llvm/CodeGen/MachineFunctionPass.h"
21 : #include "llvm/CodeGen/Passes.h"
22 : #include "llvm/CodeGen/RegAllocRegistry.h"
23 : #include "llvm/CodeGen/TargetPassConfig.h"
24 : #include "llvm/IR/Function.h"
25 : #include "llvm/Support/TargetRegistry.h"
26 : #include "llvm/Target/TargetOptions.h"
27 : #include "llvm/Transforms/Scalar.h"
28 : #include "llvm/Transforms/Utils.h"
29 : using namespace llvm;
30 :
31 : #define DEBUG_TYPE "wasm"
32 :
33 : // Emscripten's asm.js-style exception handling
34 : static cl::opt<bool> EnableEmException(
35 : "enable-emscripten-cxx-exceptions",
36 : cl::desc("WebAssembly Emscripten-style exception handling"),
37 : cl::init(false));
38 :
39 : // Emscripten's asm.js-style setjmp/longjmp handling
40 : static cl::opt<bool> EnableEmSjLj(
41 : "enable-emscripten-sjlj",
42 : cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
43 : cl::init(false));
44 :
45 113922 : extern "C" void LLVMInitializeWebAssemblyTarget() {
46 : // Register the target.
47 : RegisterTargetMachine<WebAssemblyTargetMachine> X(
48 113922 : getTheWebAssemblyTarget32());
49 : RegisterTargetMachine<WebAssemblyTargetMachine> Y(
50 113922 : getTheWebAssemblyTarget64());
51 :
52 : // Register backend passes
53 113922 : auto &PR = *PassRegistry::getPassRegistry();
54 113922 : initializeWebAssemblyAddMissingPrototypesPass(PR);
55 113922 : initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);
56 113922 : initializeLowerGlobalDtorsPass(PR);
57 113922 : initializeFixFunctionBitcastsPass(PR);
58 113922 : initializeOptimizeReturnedPass(PR);
59 113922 : initializeWebAssemblyArgumentMovePass(PR);
60 113922 : initializeWebAssemblySetP2AlignOperandsPass(PR);
61 113922 : initializeWebAssemblyEHRestoreStackPointerPass(PR);
62 113922 : initializeWebAssemblyReplacePhysRegsPass(PR);
63 113922 : initializeWebAssemblyPrepareForLiveIntervalsPass(PR);
64 113922 : initializeWebAssemblyOptimizeLiveIntervalsPass(PR);
65 113922 : initializeWebAssemblyStoreResultsPass(PR);
66 113922 : initializeWebAssemblyRegStackifyPass(PR);
67 113922 : initializeWebAssemblyRegColoringPass(PR);
68 113922 : initializeWebAssemblyExplicitLocalsPass(PR);
69 113922 : initializeWebAssemblyFixIrreducibleControlFlowPass(PR);
70 113922 : initializeWebAssemblyLateEHPreparePass(PR);
71 113922 : initializeWebAssemblyExceptionInfoPass(PR);
72 113922 : initializeWebAssemblyCFGSortPass(PR);
73 113922 : initializeWebAssemblyCFGStackifyPass(PR);
74 113922 : initializeWebAssemblyLowerBrUnlessPass(PR);
75 113922 : initializeWebAssemblyRegNumberingPass(PR);
76 113922 : initializeWebAssemblyPeepholePass(PR);
77 113922 : initializeWebAssemblyCallIndirectFixupPass(PR);
78 113922 : }
79 :
80 : //===----------------------------------------------------------------------===//
81 : // WebAssembly Lowering public interface.
82 : //===----------------------------------------------------------------------===//
83 :
84 : static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
85 352 : if (!RM.hasValue())
86 : return Reloc::PIC_;
87 : return *RM;
88 : }
89 :
90 : /// Create an WebAssembly architecture model.
91 : ///
92 352 : WebAssemblyTargetMachine::WebAssemblyTargetMachine(
93 : const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
94 : const TargetOptions &Options, Optional<Reloc::Model> RM,
95 352 : Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
96 : : LLVMTargetMachine(T,
97 352 : TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128"
98 : : "e-m:e-p:32:32-i64:64-n32:64-S128",
99 : TT, CPU, FS, Options, getEffectiveRelocModel(RM),
100 352 : CM ? *CM : CodeModel::Large, OL),
101 1042 : TLOF(new WebAssemblyTargetObjectFile()) {
102 : // WebAssembly type-checks instructions, but a noreturn function with a return
103 : // type that doesn't match the context will cause a check failure. So we lower
104 : // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
105 : // 'unreachable' instructions which is meant for that case.
106 352 : this->Options.TrapUnreachable = true;
107 :
108 : // WebAssembly treats each function as an independent unit. Force
109 : // -ffunction-sections, effectively, so that we can emit them independently.
110 352 : this->Options.FunctionSections = true;
111 352 : this->Options.DataSections = true;
112 352 : this->Options.UniqueSectionNames = true;
113 :
114 352 : initAsmInfo();
115 :
116 : // Note that we don't use setRequiresStructuredCFG(true). It disables
117 : // optimizations than we're ok with, and want, such as critical edge
118 : // splitting and tail merging.
119 352 : }
120 :
121 686 : WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}
122 :
123 : const WebAssemblySubtarget *
124 57729 : WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
125 57729 : Attribute CPUAttr = F.getFnAttribute("target-cpu");
126 57729 : Attribute FSAttr = F.getFnAttribute("target-features");
127 :
128 57729 : std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
129 339 : ? CPUAttr.getValueAsString().str()
130 58068 : : TargetCPU;
131 57729 : std::string FS = !FSAttr.hasAttribute(Attribute::None)
132 33051 : ? FSAttr.getValueAsString().str()
133 90780 : : TargetFS;
134 :
135 80190 : auto &I = SubtargetMap[CPU + FS];
136 57729 : if (!I) {
137 : // This needs to be done before we create a new subtarget since any
138 : // creation will depend on the TM and the code generation flags on the
139 : // function that reside in TargetOptions.
140 293 : resetTargetOptions(F);
141 586 : I = llvm::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
142 : }
143 57729 : return I.get();
144 : }
145 :
146 : namespace {
147 : class StripThreadLocal final : public ModulePass {
148 : // The default thread model for wasm is single, where thread-local variables
149 : // are identical to regular globals and should be treated the same. So this
150 : // pass just converts all GlobalVariables to NotThreadLocal
151 : static char ID;
152 :
153 : public:
154 35 : StripThreadLocal() : ModulePass(ID) {}
155 35 : bool runOnModule(Module &M) override {
156 38 : for (auto &GV : M.globals())
157 : GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal);
158 35 : return true;
159 : }
160 : };
161 : char StripThreadLocal::ID = 0;
162 :
163 : /// WebAssembly Code Generator Pass Configuration Options.
164 : class WebAssemblyPassConfig final : public TargetPassConfig {
165 : public:
166 : WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
167 323 : : TargetPassConfig(TM, PM) {}
168 :
169 : WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
170 305 : return getTM<WebAssemblyTargetMachine>();
171 : }
172 :
173 : FunctionPass *createTargetRegisterAllocator(bool) override;
174 :
175 : void addIRPasses() override;
176 : bool addInstSelector() override;
177 : void addPostRegAlloc() override;
178 305 : bool addGCPasses() override { return false; }
179 : void addPreEmitPass() override;
180 : };
181 : } // end anonymous namespace
182 :
183 : TargetTransformInfo
184 24631 : WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) {
185 24631 : return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
186 : }
187 :
188 : TargetPassConfig *
189 323 : WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
190 323 : return new WebAssemblyPassConfig(*this, PM);
191 : }
192 :
193 305 : FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
194 305 : return nullptr; // No reg alloc
195 : }
196 :
197 : //===----------------------------------------------------------------------===//
198 : // The following functions are called from lib/CodeGen/Passes.cpp to modify
199 : // the CodeGen pass sequence.
200 : //===----------------------------------------------------------------------===//
201 :
202 305 : void WebAssemblyPassConfig::addIRPasses() {
203 305 : if (TM->Options.ThreadModel == ThreadModel::Single) {
204 : // In "single" mode, atomics get lowered to non-atomics.
205 35 : addPass(createLowerAtomicPass());
206 35 : addPass(new StripThreadLocal());
207 : } else {
208 : // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
209 : // control specifically what gets lowered.
210 270 : addPass(createAtomicExpandPass());
211 : }
212 :
213 : // Add signatures to prototype-less function declarations
214 305 : addPass(createWebAssemblyAddMissingPrototypes());
215 :
216 : // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls.
217 305 : addPass(createWebAssemblyLowerGlobalDtors());
218 :
219 : // Fix function bitcasts, as WebAssembly requires caller and callee signatures
220 : // to match.
221 305 : addPass(createWebAssemblyFixFunctionBitcasts());
222 :
223 : // Optimize "returned" function attributes.
224 305 : if (getOptLevel() != CodeGenOpt::None)
225 298 : addPass(createWebAssemblyOptimizeReturned());
226 :
227 : // If exception handling is not enabled and setjmp/longjmp handling is
228 : // enabled, we lower invokes into calls and delete unreachable landingpad
229 : // blocks. Lowering invokes when there is no EH support is done in
230 : // TargetPassConfig::addPassesToHandleExceptions, but this runs after this
231 : // function and SjLj handling expects all invokes to be lowered before.
232 305 : if (!EnableEmException &&
233 303 : TM->Options.ExceptionModel == ExceptionHandling::None) {
234 300 : addPass(createLowerInvokePass());
235 : // The lower invoke pass may create unreachable code. Remove it in order not
236 : // to process dead blocks in setjmp/longjmp handling.
237 300 : addPass(createUnreachableBlockEliminationPass());
238 : }
239 :
240 : // Handle exceptions and setjmp/longjmp if enabled.
241 305 : if (EnableEmException || EnableEmSjLj)
242 3 : addPass(createWebAssemblyLowerEmscriptenEHSjLj(EnableEmException,
243 : EnableEmSjLj));
244 :
245 305 : TargetPassConfig::addIRPasses();
246 305 : }
247 :
248 305 : bool WebAssemblyPassConfig::addInstSelector() {
249 305 : (void)TargetPassConfig::addInstSelector();
250 305 : addPass(
251 305 : createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
252 : // Run the argument-move pass immediately after the ScheduleDAG scheduler
253 : // so that we can fix up the ARGUMENT instructions before anything else
254 : // sees them in the wrong place.
255 305 : addPass(createWebAssemblyArgumentMove());
256 : // Set the p2align operands. This information is present during ISel, however
257 : // it's inconvenient to collect. Collect it now, and update the immediate
258 : // operands.
259 305 : addPass(createWebAssemblySetP2AlignOperands());
260 305 : return false;
261 : }
262 :
263 305 : void WebAssemblyPassConfig::addPostRegAlloc() {
264 : // TODO: The following CodeGen passes don't currently support code containing
265 : // virtual registers. Consider removing their restrictions and re-enabling
266 : // them.
267 :
268 : // These functions all require the NoVRegs property.
269 305 : disablePass(&MachineCopyPropagationID);
270 305 : disablePass(&PostRAMachineSinkingID);
271 305 : disablePass(&PostRASchedulerID);
272 305 : disablePass(&FuncletLayoutID);
273 305 : disablePass(&StackMapLivenessID);
274 305 : disablePass(&LiveDebugValuesID);
275 305 : disablePass(&PatchableFunctionID);
276 305 : disablePass(&ShrinkWrapID);
277 :
278 : TargetPassConfig::addPostRegAlloc();
279 305 : }
280 :
281 305 : void WebAssemblyPassConfig::addPreEmitPass() {
282 305 : TargetPassConfig::addPreEmitPass();
283 :
284 : // Restore __stack_pointer global after an exception is thrown.
285 305 : addPass(createWebAssemblyEHRestoreStackPointer());
286 :
287 : // Now that we have a prologue and epilogue and all frame indices are
288 : // rewritten, eliminate SP and FP. This allows them to be stackified,
289 : // colored, and numbered with the rest of the registers.
290 305 : addPass(createWebAssemblyReplacePhysRegs());
291 :
292 : // Rewrite pseudo call_indirect instructions as real instructions.
293 : // This needs to run before register stackification, because we change the
294 : // order of the arguments.
295 305 : addPass(createWebAssemblyCallIndirectFixup());
296 :
297 305 : if (getOptLevel() != CodeGenOpt::None) {
298 : // LiveIntervals isn't commonly run this late. Re-establish preconditions.
299 298 : addPass(createWebAssemblyPrepareForLiveIntervals());
300 :
301 : // Depend on LiveIntervals and perform some optimizations on it.
302 298 : addPass(createWebAssemblyOptimizeLiveIntervals());
303 :
304 : // Prepare store instructions for register stackifying.
305 298 : addPass(createWebAssemblyStoreResults());
306 :
307 : // Mark registers as representing wasm's value stack. This is a key
308 : // code-compression technique in WebAssembly. We run this pass (and
309 : // StoreResults above) very late, so that it sees as much code as possible,
310 : // including code emitted by PEI and expanded by late tail duplication.
311 298 : addPass(createWebAssemblyRegStackify());
312 :
313 : // Run the register coloring pass to reduce the total number of registers.
314 : // This runs after stackification so that it doesn't consider registers
315 : // that become stackified.
316 298 : addPass(createWebAssemblyRegColoring());
317 : }
318 :
319 : // Eliminate multiple-entry loops. Do this before inserting explicit get_local
320 : // and set_local operators because we create a new variable that we want
321 : // converted into a local.
322 305 : addPass(createWebAssemblyFixIrreducibleControlFlow());
323 :
324 : // Insert explicit get_local and set_local operators.
325 305 : addPass(createWebAssemblyExplicitLocals());
326 :
327 : // Do various transformations for exception handling
328 305 : addPass(createWebAssemblyLateEHPrepare());
329 :
330 : // Sort the blocks of the CFG into topological order, a prerequisite for
331 : // BLOCK and LOOP markers.
332 305 : addPass(createWebAssemblyCFGSort());
333 :
334 : // Insert BLOCK and LOOP markers.
335 305 : addPass(createWebAssemblyCFGStackify());
336 :
337 : // Lower br_unless into br_if.
338 305 : addPass(createWebAssemblyLowerBrUnless());
339 :
340 : // Perform the very last peephole optimizations on the code.
341 305 : if (getOptLevel() != CodeGenOpt::None)
342 298 : addPass(createWebAssemblyPeephole());
343 :
344 : // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
345 305 : addPass(createWebAssemblyRegNumbering());
346 305 : }
|