aboutsummaryrefslogtreecommitdiff
path: root/tools/shared.py
blob: 4b68555acb322633c9ee0ab35c305f30f44e716a (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
import shutil, time, os
from subprocess import Popen, PIPE, STDOUT

def path_from_root(*pathelems):
  rootpath = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
  return os.path.join(rootpath, *pathelems)

CONFIG_FILE = os.path.expanduser('~/.emscripten')
if not os.path.exists(CONFIG_FILE):
  shutil.copy(path_from_root('settings.py'), CONFIG_FILE)
exec(open(CONFIG_FILE, 'r').read())

# Tools

CLANG=os.path.expanduser(os.path.join(LLVM_ROOT, 'clang++'))
LLVM_LINK=os.path.join(LLVM_ROOT, 'llvm-link')
LLVM_LD=os.path.join(LLVM_ROOT, 'llvm-ld')
LLVM_OPT=os.path.expanduser(os.path.join(LLVM_ROOT, 'opt'))
LLVM_AS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-as'))
LLVM_DIS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-dis'))
LLVM_DIS_OPTS = ['-show-annotations'] # For LLVM 2.8+. For 2.7, you may need to do just    []
LLVM_INTERPRETER=os.path.expanduser(os.path.join(LLVM_ROOT, 'lli'))
LLVM_COMPILER=os.path.expanduser(os.path.join(LLVM_ROOT, 'llc'))

BINDINGS_GENERATOR = path_from_root('tools', 'bindings_generator.py')

# Engine tweaks

#if 'strict' not in str(SPIDERMONKEY_ENGINE): # XXX temporarily disable strict mode until we sort out some stuff
#  SPIDERMONKEY_ENGINE += ['-e', "options('strict')"] # Strict mode in SpiderMonkey. With V8 we check that fallback to non-strict works too

if 'gcparam' not in str(SPIDERMONKEY_ENGINE):
  SPIDERMONKEY_ENGINE += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap

# Utilities

def timeout_run(proc, timeout, note):
  start = time.time()
  if timeout is not None:
    while time.time() - start < timeout and proc.poll() is None:
      time.sleep(0.1)
    if proc.poll() is None:
      proc.kill() # XXX bug: killing emscripten.py does not kill it's child process!
      raise Exception("Timed out: " + note)
  return proc.communicate()[0]

def run_js(engine, filename, args, check_timeout=False, stdout=PIPE, stderr=STDOUT, cwd=None):
  return timeout_run(Popen(engine + [filename] + (['--'] if 'd8' in engine[0] else []) + args,
                     stdout=stdout, stderr=stderr, cwd=cwd), 15*60 if check_timeout else None, 'Execution')

def to_cc(cxx):
  # By default, LLVM_GCC and CLANG are really the C++ versions. This gets an explicit C version
  return cxx.replace('clang++', 'clang').replace('g++', 'gcc')

def line_splitter(data):
  """Silly little tool to split JSON arrays over many lines."""

  out = ''
  counter = 0

  for i in range(len(data)):
    out += data[i]
    if data[i] == ' ' and counter > 60:
      out += '\n'
      counter = 0
    else:
      counter += 1

  return out

def limit_size(string, MAX=80*20):
  if len(string) < MAX: return string
  return string[0:MAX/2] + '\n[..]\n' + string[-MAX/2:]

def pick_llvm_opts(optimization_level, optimize_size, allow_nonportable=False, use_aa=False):
  opts = []
  if optimization_level > 0:
    if allow_nonportable:
      opts.append('-O%d' % optimization_level)
    else:
      # createStandardAliasAnalysisPasses
      if allow_nonportable and use_aa: # ammo.js results indicate this can be nonportable
        opts.append('-tbaa')
        opts.append('-basicaa') # makes fannkuch slow but primes fast

      opts.append('-globalopt')
      opts.append('-ipsccp')
      opts.append('-deadargelim')
      if allow_nonportable: opts.append('-instcombine')
      opts.append('-simplifycfg')

      opts.append('-prune-eh')
      if not optimize_size: opts.append('-inline') # The condition here is a difference with LLVM's createStandardAliasAnalysisPasses
      opts.append('-functionattrs')
      if optimization_level > 2:
        opts.append('-argpromotion')

      # XXX Danger: Can turn a memcpy into something that violates the
      #             load-store consistency hypothesis. See hashnum() in Lua.
      #             Note: this opt is of great importance for raytrace...
      if allow_nonportable: opts.append('-scalarrepl')

      if allow_nonportable: opts.append('-early-cse') # ?
      opts.append('-simplify-libcalls')
      opts.append('-jump-threading')
      if allow_nonportable: opts.append('-correlated-propagation') # ?
      opts.append('-simplifycfg')
      if allow_nonportable: opts.append('-instcombine')

      opts.append('-tailcallelim')
      opts.append('-simplifycfg')
      opts.append('-reassociate')
      opts.append('-loop-rotate')
      opts.append('-licm')
      opts.append('-loop-unswitch') # XXX should depend on optimize_size
      if allow_nonportable: opts.append('-instcombine')
      opts.append('-indvars')
      if allow_nonportable: opts.append('-loop-idiom') # ?
      opts.append('-loop-deletion')
      opts.append('-loop-unroll')
      if allow_nonportable: opts.append('-instcombine')

      # XXX Danger: Messes up Lua output for unknown reasons
      #             Note: this opt is of minor importance for raytrace...
      if optimization_level > 1 and allow_nonportable: opts.append('-gvn')

      opts.append('-memcpyopt') # Danger?
      opts.append('-sccp')

      if allow_nonportable: opts.append('-instcombine')
      opts.append('-jump-threading')
      opts.append('-correlated-propagation')
      opts.append('-dse')
      opts.append('-adce')
      opts.append('-simplifycfg')

      opts.append('-strip-dead-prototypes')
      opts.append('-deadtypeelim')

      if optimization_level > 2: opts.append('-globaldce')

      if optimization_level > 1: opts.append('-constmerge')

  return opts