aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/NaCl/PNaClABISimplify.cpp
blob: 5678ffaa7f3bc7aec096c696ccd0fa21b0d17d64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//===-- PNaClABISimplify.cpp - Lists PNaCl ABI simplification passes ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the meta-passes "-pnacl-abi-simplify-preopt"
// and "-pnacl-abi-simplify-postopt".  It lists their constituent
// passes.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/NaCl.h"
#include "llvm/PassManager.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/NaCl.h"
#include "llvm/Transforms/Scalar.h"

using namespace llvm;

static cl::opt<bool>
EnableSjLjEH("enable-pnacl-sjlj-eh",
             cl::desc("Enable use of SJLJ-based C++ exception handling "
                      "as part of the pnacl-abi-simplify passes"),
             cl::init(false));

static cl::opt<bool> // XXX EMSCRIPTEN
EnableEmCxxExceptions("enable-emscripten-cxx-exceptions",
                      cl::desc("Enables C++ exceptions in emscripten"),
                      cl::init(false));

void llvm::PNaClABISimplifyAddPreOptPasses(PassManager &PM) {
  if (EnableSjLjEH) {
    // This comes before ExpandTls because it introduces references to
    // a TLS variable, __pnacl_eh_stack.  This comes before
    // InternalizePass because it assumes various variables (including
    // __pnacl_eh_stack) have not been internalized yet.
    PM.add(createPNaClSjLjEHPass());
  } else if (EnableEmCxxExceptions) { // XXX EMSCRIPTEN
    PM.add(createLowerEmExceptionsPass());
  } else {
    // LowerInvoke prevents use of C++ exception handling by removing
    // references to BasicBlocks which handle exceptions.
    PM.add(createLowerInvokePass());
    // Remove landingpad blocks made unreachable by LowerInvoke.
    PM.add(createCFGSimplificationPass());
  }

  PM.add(createLowerEmSetjmpPass()); // XXX EMSCRIPTEN

#if 0 // EMSCRIPTEN: we allow arbitrary symbols to be preserved
  // Internalize all symbols in the module except _start, which is the only
  // symbol a stable PNaCl pexe is allowed to export.
  const char *SymbolsToPreserve[] = { "_start" };
  PM.add(createInternalizePass(SymbolsToPreserve));
#endif

  // LowerExpect converts Intrinsic::expect into branch weights,
  // which can then be removed after BlockPlacement.
#if 0 // XXX EMSCRIPTEN: We support the expect intrinsic.
  PM.add(createLowerExpectIntrinsicPass());
#endif
#if 0 // XXX EMSCRIPTEN: We don't need this.
  // Rewrite unsupported intrinsics to simpler and portable constructs.
  PM.add(createRewriteLLVMIntrinsicsPass());
#endif

  // Expand out some uses of struct types.
  PM.add(createExpandArithWithOverflowPass());
  // ExpandStructRegs must be run after ExpandArithWithOverflow to
  // expand out the insertvalue instructions that
  // ExpandArithWithOverflow introduces.
  PM.add(createExpandStructRegsPass());

  PM.add(createExpandVarArgsPass());
  PM.add(createExpandCtorsPass());
  PM.add(createResolveAliasesPass());
#if 0 // EMSCRIPTEN: no need for tls
  PM.add(createExpandTlsPass());
#endif
  // GlobalCleanup needs to run after ExpandTls because
  // __tls_template_start etc. are extern_weak before expansion
  PM.add(createGlobalCleanupPass());
}

void llvm::PNaClABISimplifyAddPostOptPasses(PassManager &PM) {
#if 0 // XXX EMSCRIPTEN: No need for this.
  PM.add(createRewritePNaClLibraryCallsPass());
#endif

  // We place ExpandByVal after optimization passes because some byval
  // arguments can be expanded away by the ArgPromotion pass.  Leaving
  // in "byval" during optimization also allows some dead stores to be
  // eliminated, because "byval" is a stronger constraint than what
  // ExpandByVal expands it to.
  PM.add(createExpandByValPass());

  // We place ExpandSmallArguments after optimization passes because
  // some optimizations undo its changes.  Note that
  // ExpandSmallArguments requires that ExpandVarArgs has already been
  // run.
#if 0 // EMSCRIPTEN: we don't need to worry about the issue this works around
  PM.add(createExpandSmallArgumentsPass());
#endif
  PM.add(createPromoteI1OpsPass());

  // Optimization passes and ExpandByVal introduce
  // memset/memcpy/memmove intrinsics with a 64-bit size argument.
  // This pass converts those arguments to 32-bit.
  PM.add(createCanonicalizeMemIntrinsicsPass());

#if 0 // XXX EMSCRIPTEN: PNaCl strips metadata to avoid making it ABI-exposed; emscripten doesn't need this.
  // We place StripMetadata after optimization passes because
  // optimizations depend on the metadata.
  PM.add(createStripMetadataPass());
#endif

  // FlattenGlobals introduces ConstantExpr bitcasts of globals which
  // are expanded out later.
  PM.add(createFlattenGlobalsPass());

  // We should not place arbitrary passes after ExpandConstantExpr
  // because they might reintroduce ConstantExprs.
  PM.add(createExpandConstantExprPass());
  // PromoteIntegersPass does not handle constexprs and creates GEPs,
  // so it goes between those passes.
  PM.add(createPromoteIntegersPass());
#if 0 // XXX EMSCRIPTEN: We can handle GEPs in our backend.
  // ExpandGetElementPtr must follow ExpandConstantExpr to expand the
  // getelementptr instructions it creates.
  PM.add(createExpandGetElementPtrPass());
#endif
  // Rewrite atomic and volatile instructions with intrinsic calls.
#if 0 // EMSCRIPTEN: we don't need to fix volatiles etc, and can use llvm intrinsics
  PM.add(createRewriteAtomicsPass());
#endif
  // Remove ``asm("":::"memory")``. This must occur after rewriting
  // atomics: a ``fence seq_cst`` surrounded by ``asm("":::"memory")``
  // has special meaning and is translated differently.
#if 0 // XXX EMSCRIPTEN: asm("":::"memory") does't have special semantics.
  PM.add(createRemoveAsmMemoryPass());
#endif
#if 0 // XXX EMSCRIPTEN: PNaCl replaces pointers with ints to simplify their ABI; empscripten doesn't need this.
  // ReplacePtrsWithInts assumes that getelementptr instructions and
  // ConstantExprs have already been expanded out.
  PM.add(createReplacePtrsWithIntsPass());
#endif

  // We place StripAttributes after optimization passes because many
  // analyses add attributes to reflect their results.
  // StripAttributes must come after ExpandByVal and
  // ExpandSmallArguments.
#if 0 // EMSCRIPTEN: we don't need to worry about the issue this works around
  PM.add(createStripAttributesPass());
#endif

  // Strip dead prototytes to appease the intrinsic ABI checks.
  // ExpandVarArgs leaves around vararg intrinsics, and
  // ReplacePtrsWithInts leaves the lifetime.start/end intrinsics.
#if 0 // XXX EMSCRIPTEN: We just ignore dead prototypes.
  PM.add(createStripDeadPrototypesPass());
#endif

  // Eliminate simple dead code that the post-opt passes could have
  // created.
#if 0 // EMSCRIPTEN: There's no point in running this since we're running DeadCodeElimination right after.
  PM.add(createDeadInstEliminationPass());
#endif
  PM.add(createDeadCodeEliminationPass());
}