summaryrefslogtreecommitdiff
path: root/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
commiteb11fae6d08f479c0799db45860a98af528fa6e7 (patch)
tree44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
parentb8a2042aa938069e862750553db0e4d82d25822c (diff)
Notes
Diffstat (limited to 'lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp')
-rw-r--r--lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp81
1 files changed, 61 insertions, 20 deletions
diff --git a/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index d38cde74d2ec..7c10f022cbbc 100644
--- a/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines the WebAssembly-specific subclass of TargetMachine.
+/// This file defines the WebAssembly-specific subclass of TargetMachine.
///
//===----------------------------------------------------------------------===//
@@ -25,6 +25,7 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils.h"
using namespace llvm;
#define DEBUG_TYPE "wasm"
@@ -48,9 +49,31 @@ extern "C" void LLVMInitializeWebAssemblyTarget() {
RegisterTargetMachine<WebAssemblyTargetMachine> Y(
getTheWebAssemblyTarget64());
- // Register exception handling pass to opt
- initializeWebAssemblyLowerEmscriptenEHSjLjPass(
- *PassRegistry::getPassRegistry());
+ // Register backend passes
+ auto &PR = *PassRegistry::getPassRegistry();
+ initializeWebAssemblyAddMissingPrototypesPass(PR);
+ initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);
+ initializeLowerGlobalDtorsPass(PR);
+ initializeFixFunctionBitcastsPass(PR);
+ initializeOptimizeReturnedPass(PR);
+ initializeWebAssemblyArgumentMovePass(PR);
+ initializeWebAssemblySetP2AlignOperandsPass(PR);
+ initializeWebAssemblyReplacePhysRegsPass(PR);
+ initializeWebAssemblyPrepareForLiveIntervalsPass(PR);
+ initializeWebAssemblyOptimizeLiveIntervalsPass(PR);
+ initializeWebAssemblyStoreResultsPass(PR);
+ initializeWebAssemblyRegStackifyPass(PR);
+ initializeWebAssemblyRegColoringPass(PR);
+ initializeWebAssemblyExplicitLocalsPass(PR);
+ initializeWebAssemblyFixIrreducibleControlFlowPass(PR);
+ initializeWebAssemblyLateEHPreparePass(PR);
+ initializeWebAssemblyExceptionInfoPass(PR);
+ initializeWebAssemblyCFGSortPass(PR);
+ initializeWebAssemblyCFGStackifyPass(PR);
+ initializeWebAssemblyLowerBrUnlessPass(PR);
+ initializeWebAssemblyRegNumberingPass(PR);
+ initializeWebAssemblyPeepholePass(PR);
+ initializeWebAssemblyCallIndirectFixupPass(PR);
}
//===----------------------------------------------------------------------===//
@@ -74,11 +97,7 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
: "e-m:e-p:32:32-i64:64-n32:64-S128",
TT, CPU, FS, Options, getEffectiveRelocModel(RM),
CM ? *CM : CodeModel::Large, OL),
- TLOF(TT.isOSBinFormatELF() ?
- static_cast<TargetLoweringObjectFile*>(
- new WebAssemblyTargetObjectFileELF()) :
- static_cast<TargetLoweringObjectFile*>(
- new WebAssemblyTargetObjectFile())) {
+ TLOF(new WebAssemblyTargetObjectFile()) {
// WebAssembly type-checks instructions, but a noreturn function with a return
// type that doesn't match the context will cause a check failure. So we lower
// LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
@@ -87,11 +106,9 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
// WebAssembly treats each function as an independent unit. Force
// -ffunction-sections, effectively, so that we can emit them independently.
- if (!TT.isOSBinFormatELF()) {
- this->Options.FunctionSections = true;
- this->Options.DataSections = true;
- this->Options.UniqueSectionNames = true;
- }
+ this->Options.FunctionSections = true;
+ this->Options.DataSections = true;
+ this->Options.UniqueSectionNames = true;
initAsmInfo();
@@ -126,6 +143,22 @@ WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
}
namespace {
+class StripThreadLocal final : public ModulePass {
+ // The default thread model for wasm is single, where thread-local variables
+ // are identical to regular globals and should be treated the same. So this
+ // pass just converts all GlobalVariables to NotThreadLocal
+ static char ID;
+
+ public:
+ StripThreadLocal() : ModulePass(ID) {}
+ bool runOnModule(Module &M) override {
+ for (auto &GV : M.globals())
+ GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal);
+ return true;
+ }
+};
+char StripThreadLocal::ID = 0;
+
/// WebAssembly Code Generator Pass Configuration Options.
class WebAssemblyPassConfig final : public TargetPassConfig {
public:
@@ -166,13 +199,18 @@ FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
//===----------------------------------------------------------------------===//
void WebAssemblyPassConfig::addIRPasses() {
- if (TM->Options.ThreadModel == ThreadModel::Single)
+ if (TM->Options.ThreadModel == ThreadModel::Single) {
// In "single" mode, atomics get lowered to non-atomics.
addPass(createLowerAtomicPass());
- else
+ addPass(new StripThreadLocal());
+ } else {
// Expand some atomic operations. WebAssemblyTargetLowering has hooks which
// control specifically what gets lowered.
addPass(createAtomicExpandPass());
+ }
+
+ // Add signatures to prototype-less function declarations
+ addPass(createWebAssemblyAddMissingPrototypes());
// Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls.
addPass(createWebAssemblyLowerGlobalDtors());
@@ -190,7 +228,8 @@ void WebAssemblyPassConfig::addIRPasses() {
// blocks. Lowering invokes when there is no EH support is done in
// TargetPassConfig::addPassesToHandleExceptions, but this runs after this
// function and SjLj handling expects all invokes to be lowered before.
- if (!EnableEmException) {
+ if (!EnableEmException &&
+ TM->Options.ExceptionModel == ExceptionHandling::None) {
addPass(createLowerInvokePass());
// The lower invoke pass may create unreachable code. Remove it in order not
// to process dead blocks in setjmp/longjmp handling.
@@ -225,16 +264,15 @@ void WebAssemblyPassConfig::addPostRegAlloc() {
// virtual registers. Consider removing their restrictions and re-enabling
// them.
- // Has no asserts of its own, but was not written to handle virtual regs.
- disablePass(&ShrinkWrapID);
-
// These functions all require the NoVRegs property.
disablePass(&MachineCopyPropagationID);
+ disablePass(&PostRAMachineSinkingID);
disablePass(&PostRASchedulerID);
disablePass(&FuncletLayoutID);
disablePass(&StackMapLivenessID);
disablePass(&LiveDebugValuesID);
disablePass(&PatchableFunctionID);
+ disablePass(&ShrinkWrapID);
TargetPassConfig::addPostRegAlloc();
}
@@ -282,6 +320,9 @@ void WebAssemblyPassConfig::addPreEmitPass() {
// Insert explicit get_local and set_local operators.
addPass(createWebAssemblyExplicitLocals());
+ // Do various transformations for exception handling
+ addPass(createWebAssemblyLateEHPrepare());
+
// Sort the blocks of the CFG into topological order, a prerequisite for
// BLOCK and LOOP markers.
addPass(createWebAssemblyCFGSort());