aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS2
-rw-r--r--LICENSE26
-rwxr-xr-xemcc33
-rw-r--r--emlink.py267
-rw-r--r--src/analyzer.js2
-rw-r--r--src/library.js3464
-rw-r--r--src/library_gl.js7
-rw-r--r--src/library_jansson.js2
-rw-r--r--src/library_openal.js596
-rw-r--r--src/library_path.js134
-rw-r--r--src/library_sdl.js168
-rw-r--r--src/modules.js2
-rw-r--r--src/postamble.js94
-rw-r--r--src/preamble.js73
-rw-r--r--src/settings.js1684
-rw-r--r--src/utility.js6
-rw-r--r--system/include/bsd/sys/mman.h2
-rw-r--r--system/include/libc/math.h8
-rw-r--r--system/include/sys/sendfile.h16
-rw-r--r--tests/cases/i24_mem_ta2.ll (renamed from tests/cases/i32_mem.ll)0
-rw-r--r--tests/cases/i24_mem_ta2.txt (renamed from tests/cases/i32_mem.txt)0
-rw-r--r--tests/cases/structphiparam.ll36
-rw-r--r--tests/cases/structphiparam.txt1
-rw-r--r--tests/cube_explosion.c16
-rw-r--r--tests/cube_explosion.pngbin0 -> 164108 bytes
-rw-r--r--tests/cubegeom.c18
-rw-r--r--tests/cubegeom.pngbin0 -> 216158 bytes
-rw-r--r--tests/cubegeom_color.pngbin0 -> 83030 bytes
-rw-r--r--tests/cubegeom_color2.c16
-rw-r--r--tests/cubegeom_color2.pngbin0 -> 76128 bytes
-rw-r--r--tests/cubegeom_fog.c16
-rw-r--r--tests/cubegeom_fog.pngbin0 -> 46290 bytes
-rw-r--r--tests/cubegeom_glew.c17
-rw-r--r--tests/cubegeom_mt.c16
-rw-r--r--tests/cubegeom_mt.pngbin0 -> 262750 bytes
-rw-r--r--tests/cubegeom_normal.c16
-rw-r--r--tests/cubegeom_normal.pngbin0 -> 28315 bytes
-rw-r--r--tests/cubegeom_normal_dap.c17
-rw-r--r--tests/cubegeom_normal_dap_far.c16
-rw-r--r--tests/cubegeom_normal_dap_far_glda.c16
-rw-r--r--tests/cubegeom_normal_dap_far_glda.pngbin0 -> 13868 bytes
-rw-r--r--tests/cubegeom_normal_dap_far_glda_quad.c16
-rw-r--r--tests/cubegeom_normal_dap_far_glda_quad.pngbin0 -> 18005 bytes
-rw-r--r--tests/cubegeom_normal_dap_far_range.c16
-rw-r--r--tests/cubegeom_normal_dap_far_range.pngbin0 -> 28315 bytes
-rw-r--r--tests/cubegeom_pre.c17
-rw-r--r--tests/cubegeom_pre.pngbin0 -> 173408 bytes
-rw-r--r--tests/cubegeom_pre2.c16
-rw-r--r--tests/cubegeom_pre2.pngbin0 -> 173408 bytes
-rw-r--r--tests/cubegeom_pre2_vao.c16
-rw-r--r--tests/cubegeom_pre2_vao2.c16
-rw-r--r--tests/cubegeom_pre2_vao2.pngbin0 -> 2956 bytes
-rw-r--r--tests/cubegeom_pre3.c16
-rw-r--r--tests/cubegeom_pre_vao.c16
-rw-r--r--tests/cubegeom_pre_vao.pngbin0 -> 173408 bytes
-rw-r--r--tests/cubegeom_texturematrix.c16
-rw-r--r--tests/cubegeom_texturematrix.pngbin0 -> 47014 bytes
-rw-r--r--tests/dirent/test_readdir.c3
-rw-r--r--tests/fcntl-open/src.c3
-rw-r--r--tests/filesystem/output.txt28
-rw-r--r--tests/filesystem/src.js1
-rw-r--r--tests/glbook/CH02_HelloTriangle.pngbin1009 -> 866 bytes
-rw-r--r--tests/glbook/CH08_SimpleVertexShader.pngbin1600 -> 1200 bytes
-rw-r--r--tests/glbook/CH09_SimpleTexture2D.pngbin1943 -> 713 bytes
-rw-r--r--tests/glbook/CH09_TextureCubemap.pngbin3209 -> 2325 bytes
-rw-r--r--tests/glbook/CH09_TextureWrap.pngbin1812 -> 894 bytes
-rw-r--r--tests/glbook/CH10_MultiTexture.pngbin59495 -> 46810 bytes
-rw-r--r--tests/glbook/CH13_ParticleSystem.pngbin4921 -> 4285 bytes
-rw-r--r--tests/htmltest.pngbin743 -> 730 bytes
-rw-r--r--tests/openal_buffers.c187
-rw-r--r--tests/qsort/benchmark.cpp43
-rwxr-xr-xtests/runner.py479
-rw-r--r--tests/sdl_gfx_primitives.pngbin2357 -> 2261 bytes
-rw-r--r--tests/sdl_maprgba.pngbin1875 -> 1862 bytes
-rw-r--r--tests/sdl_rotozoom.pngbin431921 -> 431168 bytes
-rw-r--r--tests/sdl_stb_image.c49
-rw-r--r--tests/sdl_stb_image_data.c55
-rw-r--r--tests/sounds/the_entertainer.wavbin0 -> 264644 bytes
-rw-r--r--tests/stat/test_chmod.c27
-rw-r--r--tests/stat/test_mknod.c8
-rw-r--r--tests/stat/test_stat.c6
-rw-r--r--tests/stdio/test_fgetc_ungetc.c7
-rw-r--r--tests/stdio/test_rename.c107
-rw-r--r--tests/unistd/unlink.c3
-rw-r--r--tests/utime/test_utime.c3
-rw-r--r--third_party/stb_image.c4673
-rw-r--r--tools/asm_module.py271
-rw-r--r--tools/file_packager.py18
-rw-r--r--tools/js-optimizer.js32
-rwxr-xr-xtools/merge_asm.py26
-rw-r--r--tools/shared.py12
-rwxr-xr-xtools/split_asm.py30
92 files changed, 9914 insertions, 3089 deletions
diff --git a/AUTHORS b/AUTHORS
index ea4c8f0b..d3cdd156 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -90,4 +90,6 @@ a license to everyone to use it as detailed in LICENSE.)
* Soeren Balko <soeren.balko@gmail.com>
* Ryan Kelly (ryan@rfk.id.au)
* Michael Lelli <toadking@toadking.com>
+* Yu Kobayashi <yukoba@accelart.jp>
+* Pin Zhang <zhangpin04@gmail.com>
diff --git a/LICENSE b/LICENSE
index 6d090777..f742692e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -66,3 +66,29 @@ IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
+
+==============================================================================
+
+This program uses portions of Node.js source code located in src/library_path.js,
+in accordance with the terms of the MIT license. Node's license follows:
+
+ """
+ Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+ """ \ No newline at end of file
diff --git a/emcc b/emcc
index 91b109b6..8f71883d 100755
--- a/emcc
+++ b/emcc
@@ -53,6 +53,15 @@ from tools import shared, jsrun
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
from tools.response_file import read_response_file
+CXX_SUFFIXES = ('.cpp', '.cxx', '.cc')
+SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
+BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
+DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
+STATICLIB_SUFFIXES = ('.a',)
+ASSEMBLY_SUFFIXES = ('.ll',)
+LIB_PREFIXES = ('', 'lib')
+JS_CONTAINING_SUFFIXES = ('js', 'html')
+
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
# levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get
# llvm opt level 3, and speed-wise emcc level 2 is already the slowest/most optimizing
@@ -532,7 +541,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
if debug_configure: open(tempout, 'a').write('============= ' + arg + '\n' + src + '\n=============\n\n')
except:
pass
- if arg.endswith('.s'):
+ elif arg.endswith('.s'):
if debug_configure: open(tempout, 'a').write('(compiling .s assembly, must use clang\n')
use_js = 0
@@ -615,15 +624,6 @@ if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += shlex.split(EMMAKEN_CFLAGS)
# ---------------- Utilities ---------------
-SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
-BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
-DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
-STATICLIB_SUFFIXES = ('.a',)
-ASSEMBLY_SUFFIXES = ('.ll',)
-LIB_PREFIXES = ('', 'lib')
-
-JS_CONTAINING_SUFFIXES = ('js', 'html')
-
seen_names = {}
def uniquename(name):
if name not in seen_names:
@@ -787,6 +787,7 @@ try:
newargs[i+1] = ''
elif newargs[i].startswith('--minify'):
check_bad_eq(newargs[i])
+ assert newargs[i+1] == '0', '0 is the only supported option for --minify; 1 has been deprecated'
debug_level = max(1, debug_level)
newargs[i] = ''
newargs[i+1] = ''
@@ -1010,7 +1011,7 @@ try:
logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES))
exit(0)
- newargs += CC_ADDITIONAL_ARGS
+ newargs = CC_ADDITIONAL_ARGS + newargs
assert not (Compression.on and final_suffix != 'html'), 'Compression only works when generating HTML'
@@ -1030,6 +1031,10 @@ try:
exec('shared.Settings.' + key + ' = ' + value)
# Apply effects from settings
+ if bind and shared.Settings.ASM_JS:
+ logging.warning('disabling asm.js since embind is not ready for it yet')
+ shared.Settings.ASM_JS = 0
+
if shared.Settings.ASM_JS:
assert opt_level >= 1, 'asm.js requires -O1 or above'
@@ -1083,6 +1088,10 @@ try:
if shared.Settings.DLOPEN_SUPPORT:
shared.Settings.LINKABLE = 1
+ if shared.Settings.STB_IMAGE and final_suffix in JS_CONTAINING_SUFFIXES:
+ input_files.append(shared.path_from_root('third_party', 'stb_image.c'))
+ shared.Settings.EXPORTED_FUNCTIONS += ['_stbi_load', '_stbi_load_from_memory', '_stbi_image_free']
+
## Compile source code to bitcode
logging.debug('compiling to bitcode')
@@ -1097,6 +1106,8 @@ try:
output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
+ if input_file.endswith(CXX_SUFFIXES):
+ args += shared.EMSDK_CXX_OPTS
logging.debug("running:" + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
if not os.path.exists(output_file):
diff --git a/emlink.py b/emlink.py
index d59cb5d3..7311f84a 100644
--- a/emlink.py
+++ b/emlink.py
@@ -6,9 +6,9 @@ Fast static linker for emscripten outputs. Specifically this links asm.js module
See https://github.com/kripken/emscripten/wiki/Linking
'''
-import os, subprocess, sys, re
+import sys
from tools import shared
-from tools import js_optimizer
+from tools.asm_module import AsmModule
try:
me, main, side, out = sys.argv[:4]
@@ -22,269 +22,6 @@ print 'Output:', out
shared.try_delete(out)
-class AsmModule():
- def __init__(self, filename):
- self.filename = filename
- self.js = open(filename).read()
-
- self.start_asm = self.js.find(js_optimizer.start_asm_marker)
- self.start_funcs = self.js.find(js_optimizer.start_funcs_marker)
- self.end_funcs = self.js.rfind(js_optimizer.end_funcs_marker)
- self.end_asm = self.js.rfind(js_optimizer.end_asm_marker)
-
- # pre
- self.pre_js = self.js[:self.start_asm]
-
- # heap initializer
- self.staticbump = int(re.search(shared.JS.memory_staticbump_pattern, self.pre_js).group(1))
- if self.staticbump:
- self.mem_init_js = re.search(shared.JS.memory_initializer_pattern, self.pre_js).group(0)
-
- # global initializers
- global_inits = re.search(shared.JS.global_initializers_pattern, self.pre_js)
- if global_inits:
- self.global_inits_js = global_inits.group(0)
- self.global_inits = map(lambda init: init.split('{')[2][1:].split('(')[0], global_inits.groups(0)[0].split(','))
- else:
- self.global_inits_js = ''
- self.global_inits = []
-
- # imports (and global variables)
- first_var = self.js.find('var ', self.js.find('var ', self.start_asm)+4)
- self.pre_imports_js = self.js[self.start_asm:first_var]
- self.imports_js = self.js[first_var:self.start_funcs]
- self.imports = {}
- for imp in js_optimizer.import_sig.finditer(self.imports_js):
- key, value = imp.group(0).split('var ')[1][:-1].split('=', 1)
- self.imports[key] = value
- #print >> sys.stderr, 'imports', self.imports
-
- # funcs
- self.funcs_js = self.js[self.start_funcs:self.end_funcs]
- self.funcs = set([m.group(2) for m in js_optimizer.func_sig.finditer(self.funcs_js)])
- #print 'funcs', self.funcs
-
- # tables and exports
- post_js = self.js[self.end_funcs:self.end_asm]
- ret = post_js.find('return')
- self.tables_js = post_js[:ret]
- self.exports_js = post_js[ret:]
- self.tables = self.parse_tables(self.tables_js)
- self.exports = set([export.strip() for export in self.exports_js[self.exports_js.find('{')+1:self.exports_js.find('}')].split(',')])
-
- # post
- self.post_js = self.js[self.end_asm:]
- self.sendings = {}
- for sending in [sending.strip() for sending in self.post_js[self.post_js.find('}, { ')+5:self.post_js.find(' }, buffer);')].split(',')]:
- colon = sending.find(':')
- self.sendings[sending[:colon].replace('"', '')] = sending[colon+1:].strip()
- self.module_defs = set(re.findall('var [\w\d_$]+ = Module\["[\w\d_$]+"\] = asm\["[\w\d_$]+"\];\n', self.post_js))
-
- def relocate_into(self, main):
- # heap initializer
- if self.staticbump > 0:
- new_mem_init = self.mem_init_js[:self.mem_init_js.rfind(', ')] + ', Runtime.GLOBAL_BASE+%d)' % main.staticbump
- main.pre_js = re.sub(shared.JS.memory_staticbump_pattern, 'STATICTOP = STATIC_BASE + %d;\n' % (main.staticbump + side.staticbump) + new_mem_init, main.pre_js, count=1)
-
- # Find function name replacements TODO: do not rename duplicate names with duplicate contents, just merge them
- replacements = {}
- for func in self.funcs:
- rep = func
- while rep in main.funcs:
- rep += '_'
- replacements[func] = rep
- #print >> sys.stderr, 'replacements:', replacements
-
- # sendings: add invokes for new tables
- all_sendings = main.sendings
- added_sending = False
- for table in self.tables:
- if table not in main.tables:
- sig = table[table.rfind('_')+1:]
- all_sendings['invoke_%s' % sig] = shared.JS.make_invoke(sig, named=False)
- added_sending = True
-
- # imports
- all_imports = main.imports
- for key, value in self.imports.iteritems():
- if key in self.funcs or key in main.funcs: continue # external function in one module, implemented in the other
- value_concrete = '.' not in value # env.key means it is an import, an external value, and not a concrete one
- main_value = main.imports.get(key)
- main_value_concrete = main_value and '.' not in main_value
- if value_concrete and main_value_concrete: continue # standard global var
- if not main_value or value_concrete:
- if '+' in value:
- # relocate
- value = value.replace('(', '').replace(')', '').replace('| 0', '').replace('|0', '').replace(' ', '')
- left, right = value.split('+')
- assert left == 'H_BASE'
- value = str(main.staticbump + int(right))
- all_imports[key] = value
- if (value_concrete or main_value_concrete) and key in all_sendings:
- del all_sendings[key] # import of external value no longer needed
- main.imports_js = '\n'.join(['var %s = %s;' % (key, value) for key, value in all_imports.iteritems()]) + '\n'
-
- if added_sending:
- sendings_js = ', '.join(['%s: %s' % (key, value) for key, value in all_sendings.iteritems()])
- sendings_start = main.post_js.find('}, { ')+5
- sendings_end = main.post_js.find(' }, buffer);')
- main.post_js = main.post_js[:sendings_start] + sendings_js + main.post_js[sendings_end:]
-
- # check for undefined references to global variables
- def check_import(key, value):
- if value.startswith('+') or value.endswith('|0'): # ignore functions
- if key not in all_sendings:
- print >> sys.stderr, 'warning: external variable %s is still not defined after linking' % key
- for key, value in all_imports.iteritems(): check_import(key, value)
-
- # tables
- f_bases = {}
- f_sizes = {}
- for table, data in self.tables.iteritems():
- main.tables[table] = self.merge_tables(table, main.tables.get(table), data, replacements, f_bases, f_sizes)
- main.combine_tables()
- #print >> sys.stderr, 'f bases', f_bases
-
- # relocate
- temp = shared.Building.js_optimizer(self.filename, ['asm', 'relocate', 'last'], extra_info={
- 'replacements': replacements,
- 'fBases': f_bases,
- 'hBase': main.staticbump
- })
- #print >> sys.stderr, 'relocated side into', temp
- relocated_funcs = AsmModule(temp)
- shared.try_delete(temp)
- main.extra_funcs_js = relocated_funcs.funcs_js.replace(js_optimizer.start_funcs_marker, '\n')
-
- # update function table uses
- ft_marker = 'FUNCTION_TABLE_'
-
- def update_fts(what):
- updates = []
- i = 1 # avoid seeing marker in recursion
- while 1:
- i = what.find(ft_marker, i)
- if i < 0: break;
- start = i
- end = what.find('[', start)
- table = what[i:end]
- if table not in f_sizes:
- # table was not modified
- i += len(ft_marker)
- continue
- nesting = 1
- while nesting > 0:
- next = what.find(']', end+1)
- nesting -= 1
- nesting += what.count('[', end+1, next)
- end = next
- assert end > 0
- mask = what.rfind('&', start, end)
- assert mask > 0 and end - mask <= 13
- fixed = update_fts(what[start:mask+1] + str(f_sizes[table]-1) + ']')
- updates.append((start, end, fixed))
- i = end # additional function table uses were done by recursion
- # apply updates
- if len(updates) == 0: return what
- parts = []
- so_far = 0
- for i in range(len(updates)):
- start, end, fixed = updates[i]
- parts.append(what[so_far:start])
- parts.append(fixed)
- so_far = end+1
- parts.append(what[so_far:])
- return ''.join(parts)
-
- main.funcs_js = update_fts(main.funcs_js)
- main.extra_funcs_js = update_fts(main.extra_funcs_js)
-
- # global initializers
- if self.global_inits:
- my_global_inits = map(lambda init: replacements[init] if init in replacements else init, self.global_inits)
- all_global_inits = map(lambda init: '{ func: function() { %s() } }' % init, main.global_inits + my_global_inits)
- all_global_inits_js = '/* global initializers */ __ATINIT__.push(' + ','.join(all_global_inits) + ');'
- if main.global_inits:
- target = main.global_inits_js
- else:
- target = '// === Body ===\n'
- all_global_inits_js = target + all_global_inits_js
- main.pre_js = main.pre_js.replace(target, all_global_inits_js)
-
- # exports
- def rep_exp(export):
- key, value = export.split(':')
- if key in replacements:
-