diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-12-18 07:59:06 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-12-18 07:59:06 -0800 |
commit | 56b65a54cb92d2d4a34535f71dbae08d758d3fc3 (patch) | |
tree | 0220d27388eab38587a8fd12140552e0ce513435 | |
parent | e77d99dac0b1ba58c773b4b8c7d8a223ad008624 (diff) | |
parent | 47bc8ba2c47c67d8824c2b7bf35195a079cbed7c (diff) |
Merge branch 'incoming'
-rwxr-xr-x | emar | 3 | ||||
-rwxr-xr-x | emcc | 81 | ||||
-rw-r--r-- | src/compiler.js | 2 | ||||
-rw-r--r-- | src/intertyper.js | 2 | ||||
-rw-r--r-- | src/library.js | 23 | ||||
-rw-r--r-- | src/preamble.js | 19 | ||||
-rw-r--r-- | src/runtime.js | 9 | ||||
-rw-r--r-- | system/include/SDL/SDL_surface.h | 4 | ||||
-rw-r--r-- | system/include/libcxx/ostream | 2 | ||||
-rw-r--r-- | tests/cases/inttoptr.ll | 20 | ||||
-rw-r--r-- | tests/hello_world.ll | 17 | ||||
-rw-r--r-- | tests/hello_world_sdl.cpp | 4 | ||||
-rw-r--r-- | tests/poppler/fontconfig/fontconfig.h (renamed from tests/poppler/include/fontconfig/fontconfig.h) | 0 | ||||
-rw-r--r-- | tests/runner.py | 45 | ||||
-rwxr-xr-x | tools/emconfiguren.py | 2 | ||||
-rwxr-xr-x | tools/emmaken.py | 2 | ||||
-rw-r--r-- | tools/shared.py | 55 |
17 files changed, 197 insertions, 93 deletions
@@ -17,5 +17,6 @@ newargs = [shared.EMLD] + sys.argv[3:] + ['-o='+sys.argv[2]] if DEBUG: print >> sys.stderr, 'emar:', sys.argv, ' ==> ', newargs -os.execvp(shared.EMLD, newargs) +if len(newargs) > 2: + os.execvp(shared.EMLD, newargs) @@ -11,12 +11,12 @@ use emar, emld and emranlib instead of the same command without 'em'. Example uses: - * For configure, instead of ./configure, cmake, etc., run emconfiguren.py + * For configure, instead of ./configure, cmake, etc., run emconfigure.py with that command as an argument, for example - emconfiguren.py ./configure [options] + emconfigure.py ./configure [options] - emconfiguren.py is a tiny script that just sets some environment vars + emconfigure.py is a tiny script that just sets some environment vars as a convenience. The command just shown is equivalent to EMMAKEN_JUST_CONFIGURE=1 RANLIB=PATH/emranlib AR=PATH/emar CXX=PATH/em++ CC=PATH/emcc ./configure [options] @@ -80,10 +80,6 @@ from tools import shared DEBUG = os.environ.get('EMCC_DEBUG') TEMP_DIR = os.environ.get('EMCC_TEMP_DIR') -################### XXX -print >> sys.stderr, '\n***This is a WORK IN PROGRESS***' -################### XXX - if DEBUG: print >> sys.stderr, 'emcc: ', ' '.join(sys.argv) # Handle some global flags @@ -148,16 +144,23 @@ The -c option (which tells gcc not to run the linker) will cause LLVM bitcode to be generated, as %s only generates JavaScript in the final linking stage of building. +The input file(s) can be either source code files that +Clang can handle (C or C++), LLVM bitcode in binary form, +or LLVM assembly files in human-readable form. + ''' % (this, this, this) exit(0) -# If this is a configure-type thing, just do that +# If this is a configure-type thing, do not compile to JavaScript, instead use clang +# to compile to a native binary (using our headers, so things make sense later) CONFIGURE_CONFIG = os.environ.get('EMMAKEN_JUST_CONFIGURE') CMAKE_CONFIG = 'CMakeFiles/cmTryCompileExec.dir' in ' '.join(sys.argv)# or 'CMakeCCompilerId' in ' '.join(sys.argv) if CONFIGURE_CONFIG or CMAKE_CONFIG: - compiler = 'g++' if 'CXXCompiler' in ' '.join(sys.argv) or os.environ.get('EMMAKEN_CXX') else 'gcc' + compiler = shared.CLANG + if not ('CXXCompiler' in ' '.join(sys.argv) or os.environ.get('EMMAKEN_CXX')): + compiler = shared.to_cc(compiler) cmd = [compiler] + shared.EMSDK_OPTS + sys.argv[1:] - if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', cmd + if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', compiler, cmd exit(os.execvp(compiler, cmd)) if os.environ.get('EMMAKEN_COMPILER'): @@ -179,6 +182,7 @@ if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += EMMAKEN_CFLAGS.split(' ') # ---------------- Utilities --------------- SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc') +BITCODE_SUFFIXES = ('.bc', '.o', '.ll') def unsuffixed(name): return '.'.join(name.split('.')[:-1]) @@ -266,6 +270,12 @@ try: closure = int(newargs[i+1]) newargs[i] = '' newargs[i+1] = '' + elif newargs[i] == '-MF': # clang cannot handle this, so we fake it + f = open(newargs[i+1], 'w') + f.write('\n') + f.close() + newargs[i] = '' + newargs[i+1] = '' newargs = [ arg for arg in newargs if arg is not '' ] if llvm_opt_level is None: llvm_opt_level = 1 if opt_level >= 1 else 0 @@ -289,14 +299,23 @@ try: for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params, # right now we just assume that what is left contains no more |-x OPT| things arg = newargs[i] - if arg.endswith(SOURCE_SUFFIXES + ('.bc', '.o')): # we already removed -o <target>, so all these should be inputs - input_files.append(arg) + if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES): # we already removed -o <target>, so all these should be inputs newargs[i] = '' - if arg.endswith(SOURCE_SUFFIXES): - has_source_inputs = True + if os.path.exists(arg): + if arg.endswith(SOURCE_SUFFIXES): + input_files.append(arg) + has_source_inputs = True + else: + # this should be bitcode, make sure it is valid + if arg.endswith('.ll') or shared.Building.is_bitcode(arg): + input_files.append(arg) + else: + print >> sys.stderr, 'emcc: %s: Not valid LLVM bitcode' % arg + else: + print >> sys.stderr, 'emcc: %s: No such file or directory' % arg newargs = [ arg for arg in newargs if arg is not '' ] - assert len(input_files) > 0, 'emcc: no input files specified' + assert len(input_files) > 0, 'emcc: no input files' newargs += CC_ADDITIONAL_ARGS @@ -334,24 +353,29 @@ try: ## Compile source code to bitcode - if DEBUG: print >> sys.stderr, 'emcc: compiling to bitcode' + if DEBUG: print >> sys.stderr, 'emcc: compiling to bitcode (%s)' % str(sys.argv) # First, generate LLVM bitcode. For each input file, we get base.o with bitcode - newargs = newargs + ['-emit-llvm', '-c'] - for input_file in input_files: if input_file.endswith(SOURCE_SUFFIXES): - args = newargs + [input_file, '-o', in_temp(unsuffixed_basename(input_file) + '.o')] + args = newargs + ['-emit-llvm', '-c', input_file, '-o', in_temp(unsuffixed_basename(input_file) + '.o')] if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args) Popen([call] + args).communicate() - else: - shutil.copyfile(input_file, in_temp(unsuffixed_basename(input_file) + '.o')) + else: # bitcode + if input_file.endswith(('.bc', '.o')): + shutil.copyfile(input_file, in_temp(unsuffixed_basename(input_file) + '.o')) + else: #.ll + shared.Building.llvm_as(input_file, in_temp(unsuffixed_basename(input_file) + '.o')) # Optimize, if asked to if llvm_opt_level > 0: if DEBUG: print >> sys.stderr, 'emcc: LLVM opts' for input_file in input_files: - shared.Building.llvm_opt(in_temp(unsuffixed_basename(input_file) + '.o'), LLVM_INTERNAL_OPT_LEVEL, safe=llvm_opt_level < 2) + try: + shared.Building.llvm_opt(in_temp(unsuffixed_basename(input_file) + '.o'), LLVM_INTERNAL_OPT_LEVEL, safe=llvm_opt_level < 2) + except: + # This might be an invalid input, which will get ignored during linking later anyhow + print >> sys.stderr, 'emcc: warning: LLVM opt failed to run on %s, continuing without optimization' % input_file # If we were just asked to generate bitcode, stop there if final_suffix not in ['js', 'html']: @@ -364,9 +388,12 @@ try: else: assert not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) # We have a specified target (-o <target>), which is not JavaScript or HTML, and - # we have multiple files: Link them. TODO: Pass complex linker args along - shared.Building.link(map(lambda input_file: in_temp(unsuffixed_basename(input_file) + '.o'), input_files), specified_target) - + # we have multiple files: Link them TODO: llvm link-time opts? + ld_args = map(lambda input_file: in_temp(unsuffixed_basename(input_file) + '.o'), input_files) + \ + ['-o', specified_target] + #[arg.split('-Wl,')[1] for arg in filter(lambda arg: arg.startswith('-Wl,'), sys.argv)] + if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(ld_args) + Popen([shared.LLVM_LINK] + ld_args).communicate() exit(0) ## Continue on to create JavaScript @@ -389,7 +416,7 @@ try: if need_dlmalloc and not has_dlmalloc: # We need to build and link dlmalloc in if DEBUG: print >> sys.stderr, 'emcc: including dlmalloc' - Popen([shared.EMCC, shared.path_from_root('src', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')]).communicate() + Popen([shared.EMCC, shared.path_from_root('src', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')], stdout=PIPE, stderr=PIPE).communicate() if llvm_opt_level > 0: shared.Building.llvm_opt(in_temp('dlmalloc.o'), LLVM_INTERNAL_OPT_LEVEL, safe=llvm_opt_level < 2) extra_files_to_link.append(in_temp('dlmalloc.o')) @@ -408,7 +435,7 @@ try: if len(input_files) + len(extra_files_to_link) > 1: shared.Building.link(map(lambda input_file: in_temp(unsuffixed_basename(input_file) + '.o'), input_files) + extra_files_to_link, in_temp(target_basename + '.bc')) - # TODO: LLVM link-time opts? + # TODO: LLVM link-time opts? here and/or elsewhere? else: shutil.move(in_temp(unsuffixed_basename(input_files[0]) + '.o'), in_temp(target_basename + '.bc')) diff --git a/src/compiler.js b/src/compiler.js index 2dea5797..33f0e1fb 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -152,7 +152,7 @@ if (!MICRO_OPTS || !RELOOP || ASSERTIONS || CHECK_SIGNS || CHECK_OVERFLOWS || IN print('// Note: For maximum-speed code, see "Optimizing Code" on the Emscripten wiki, https://github.com/kripken/emscripten/wiki/Optimizing-Code'); } -if (CORRECT_SIGNS || CORRECT_OVERFLOWS || CORRECT_ROUNDINGS) { +if (DOUBLE_MODE || I64_MODE || CORRECT_SIGNS || CORRECT_OVERFLOWS || CORRECT_ROUNDINGS) { print('// Note: Some Emscripten settings may limit the speed of the generated code.'); } diff --git a/src/intertyper.js b/src/intertyper.js index ba9e3f0d..4b4544ae 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -801,7 +801,7 @@ function intertyper(data, sidePass, baseLineNums) { var segments = splitTokenList(item.tokens.slice(1)); for (var i = 1; i <= 4; i++) { if (segments[i-1]) { - if (i > 1 && segments[i-1].length == 1 && segments[0].length > 1) { + if (i > 1 && segments[i-1].length == 1 && segments[0].length > 1 && !isType(segments[i-1][0].text)) { segments[i-1].unshift(segments[0][0]); // Add the type from the first segment, they are all alike } item['param'+i] = parseLLVMSegment(segments[i-1]); diff --git a/src/library.js b/src/library.js index 2a4a5e7d..1747155f 100644 --- a/src/library.js +++ b/src/library.js @@ -2111,15 +2111,12 @@ LibraryManager.library = { // TODO: We could in theory slice off the top of the HEAP when // sbrk gets a negative increment in |bytes|... var self = _sbrk; - if (!self.STATICTOP) { - STATICTOP = alignMemoryPage(STATICTOP); - self.STATICTOP = STATICTOP; - self.DATASIZE = 0; - } else { - assert(self.STATICTOP == STATICTOP, "No one should touch the heap!"); + if (!self.called) { + STATICTOP = alignMemoryPage(STATICTOP); // make sure we start out aligned + self.called = true; } - var ret = STATICTOP + self.DATASIZE; - self.DATASIZE += alignMemoryPage(bytes); + var ret = STATICTOP; + if (bytes != 0) Runtime.staticAlloc(bytes); return ret; // Previous break location. }, open64: 'open', @@ -4323,6 +4320,16 @@ LibraryManager.library = { _fputs(str, _stdout); // XXX stderr etc. }, + _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEi__deps: ['fputs', '$libcxx'], + _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEi: function(stream, num) { + _fputs(allocate(intArrayFromString(num.toString()), 'i8', ALLOC_STACK), _stdout); + }, + + _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRS3_S4_E__deps: ['fputc', '$libcxx'], + _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRS3_S4_E: function(stream, x) { + _fputc('\n'.charCodeAt(0), _stdout); + }, + // glibc _ZNSt8ios_base4InitC1Ev: function() { diff --git a/src/preamble.js b/src/preamble.js index cd9138d4..51e22390 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -23,6 +23,15 @@ var ACCEPTABLE_SAFE_HEAP_ERRORS = 0; function SAFE_HEAP_ACCESS(dest, type, store, ignore) { //if (dest === A_NUMBER) print ([dest, type, store] + ' ' + new Error().stack); // Something like this may be useful, in debugging + +#if USE_TYPED_ARRAYS + // When using typed arrays, reads over the top of TOTAL_MEMORY will fail silently, so we must + // correct that by growing TOTAL_MEMORY as needed. Without typed arrays, memory is a normal + // JS array so it will work (potentially slowly, depending on the engine). + assert(dest < STATICTOP); + assert(STATICTOP <= TOTAL_MEMORY); +#endif + #if USE_TYPED_ARRAYS == 2 return; // It is legitimate to violate the load-store assumption in this case #endif @@ -452,10 +461,10 @@ function allocate(slab, types, allocator) { size = slab.length; } - var ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, 1)); - var singleType = typeof types === 'string' ? types : null; + var ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + var i = 0, type; while (i < size) { var curr = zeroinit ? 0 : slab[i]; @@ -533,12 +542,11 @@ var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32; var STACK_ROOT, STACKTOP, STACK_MAX; var STATICTOP; #if USE_TYPED_ARRAYS -var LAST_STATICTOP; function enlargeMemory() { - // LAST_STATICTOP is the previous top, TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top. + // TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top. #if ASSERTIONS printErr('Warning: Enlarging memory arrays, this is not fast! ' + [STATICTOP, TOTAL_MEMORY]); - assert(STATICTOP >= TOTAL_MEMORY && LAST_STATICTOP < TOTAL_MEMORY); + assert(STATICTOP >= TOTAL_MEMORY); assert(TOTAL_MEMORY > 4); // So the loop below will not be infinite #endif while (TOTAL_MEMORY <= STATICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it @@ -610,6 +618,7 @@ var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}}; var base = intArrayFromString('(null)'); // So printing %s of NULL gives '(null)' // Also this ensures we leave 0 as an invalid address, 'NULL' +STATICTOP = base.length; for (var i = 0; i < base.length; i++) { {{{ makeSetValue(0, 'i', 'base[i]', 'i8') }}} } diff --git a/src/runtime.js b/src/runtime.js index 0b36f967..e1a6db39 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -10,7 +10,7 @@ var RuntimeGenerator = { alloc: function(size, type, init) { var ret = type + 'TOP'; if (ASSERTIONS) { - ret += '; assert(' + size + ' > 0, "Trying to allocate 0")'; + ret += '; assert(' + size + ' != 0, "Trying to allocate 0")'; } if (init) { ret += '; _memset(' + type + 'TOP, 0, ' + size + ')'; @@ -54,11 +54,10 @@ var RuntimeGenerator = { return ret += 'STACKTOP = __stackBase__'; }, - // An allocation that cannot be free'd + // An allocation that cannot normally be free'd (except through sbrk, which once + // called, takes control of STATICTOP) staticAlloc: function(size) { - var ret = ''; - if (USE_TYPED_ARRAYS) ret += 'LAST_STATICTOP = STATICTOP;' - ret += RuntimeGenerator.alloc(size, 'STATIC', INIT_HEAP); + var ret = RuntimeGenerator.alloc(size, 'STATIC', INIT_HEAP); if (USE_TYPED_ARRAYS) ret += '; if (STATICTOP >= TOTAL_MEMORY) enlargeMemory();' return ret; }, diff --git a/system/include/SDL/SDL_surface.h b/system/include/SDL/SDL_surface.h index 77b58258..ecf89606 100644 --- a/system/include/SDL/SDL_surface.h +++ b/system/include/SDL/SDL_surface.h @@ -59,7 +59,9 @@ extern "C" { /** * Evaluates to true if the surface needs to be locked before access. */ -#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0) +#define SDL_MUSTLOCK(S) 1 + /* XXX Emscripten: we always need to lock. + (((S)->flags & SDL_RLEACCEL) != 0) */ /** * \brief A collection of pixels used in software blitting. diff --git a/system/include/libcxx/ostream b/system/include/libcxx/ostream index dd28e686..f7cbb8a2 100644 --- a/system/include/libcxx/ostream +++ b/system/include/libcxx/ostream @@ -1181,6 +1181,7 @@ basic_ostream<_CharT, _Traits>::seekp(off_type __off, ios_base::seekdir __dir) return *this; } +*/ template <class _CharT, class _Traits> inline _LIBCPP_INLINE_VISIBILITY basic_ostream<_CharT, _Traits>& @@ -1209,6 +1210,7 @@ flush(basic_ostream<_CharT, _Traits>& __os) return __os; } +/* #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template <class _Stream, class _Tp> diff --git a/tests/cases/inttoptr.ll b/tests/cases/inttoptr.ll new file mode 100644 index 00000000..c70904c8 --- /dev/null +++ b/tests/cases/inttoptr.ll @@ -0,0 +1,20 @@ +; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-pc-linux-gnu" + +@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] + +; [#uses=1] +declare i32 @puts(i8*) + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32 ; [#uses=2] + %0 = alloca i32 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + %sz.i7 = inttoptr i32 64 to i32* ; [#uses=1 type=i32*] + store i32 184, i32* %sz.i7, align 8, !tbaa !1610 + %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + ret i32 0 +} diff --git a/tests/hello_world.ll b/tests/hello_world.ll new file mode 100644 index 00000000..adeac7eb --- /dev/null +++ b/tests/hello_world.ll @@ -0,0 +1,17 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + store i32 0, i32* %retval + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + ret i32 1 +} + +; [#uses=1] +declare i32 @printf(i8*, ...) diff --git a/tests/hello_world_sdl.cpp b/tests/hello_world_sdl.cpp index f3fb8ae7..df69b055 100644 --- a/tests/hello_world_sdl.cpp +++ b/tests/hello_world_sdl.cpp @@ -8,7 +8,7 @@ int main() { SDL_Init(SDL_INIT_VIDEO); SDL_Surface *screen = SDL_SetVideoMode(256, 256, 32, SDL_SWSURFACE); - SDL_LockSurface(screen); + if (SDL_MUSTLOCK(screen)) SDL_LockSurface(screen); for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { *((char*)screen->pixels + i*256*4 + j*4 + 0) = i; @@ -17,7 +17,7 @@ int main() { *((char*)screen->pixels + i*256*4 + j*4 + 3) = 255; } } - SDL_UnlockSurface(screen); + if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); printf("you should see a colored cube."); diff --git a/tests/poppler/include/fontconfig/fontconfig.h b/tests/poppler/fontconfig/fontconfig.h index 4efa4507..4efa4507 100644 --- a/tests/poppler/include/fontconfig/fontconfig.h +++ b/tests/poppler/fontconfig/fontconfig.h diff --git a/tests/runner.py b/tests/runner.py index 9224cb4b..e62e7681 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -1964,8 +1964,8 @@ if 'benchmark' not in str(sys.argv): main_name = os.path.join(self.get_dir(), 'main.cpp') open(main_name, 'w').write(main) - Building.emmaken(supp_name) - Building.emmaken(main_name) + Building.emcc(supp_name) + Building.emcc(main_name) all_name = os.path.join(self.get_dir(), 'all.bc') Building.link([supp_name + '.o', main_name + '.o'], all_name) @@ -3482,12 +3482,12 @@ at function.:blag int main() { - std::cout << "hello world"; + std::cout << "hello world" << std::endl << 77 << "." << std::endl; return 0; } ''' - self.do_run(src, 'hello world') + self.do_run(src, 'hello world\n77.\n') def test_stdvec(self): src = ''' @@ -3564,9 +3564,9 @@ at function.:blag # emcc should build in dlmalloc automatically, and do all the sign correction etc. for it try_delete(os.path.join(self.get_dir(), 'src.cpp.o.js')) - # XXX find out why we fail without TOTAL_MEMORY here. that should not happen! - output = Popen([EMCC, '-g', '-s', 'TOTAL_MEMORY=104857600', path_from_root('tests', 'dlmalloc_test.c'), + output = Popen([EMCC, path_from_root('tests', 'dlmalloc_test.c'), '-o', os.path.join(self.get_dir(), 'src.cpp.o.js')], stdout=PIPE, stderr=PIPE).communicate() + #print output self.do_run('x', '*1,0*', ['200', '1'], no_build=True) self.do_run('x', '*400,0*', ['400', '400'], no_build=True) @@ -3782,7 +3782,7 @@ at function.:blag freetype = self.get_freetype() poppler = self.get_library('poppler', - [os.path.join('poppler', '.libs', 'libpoppler.so.13.0.0.bc'), + [os.path.join('poppler', '.libs', 'libpoppler.so.13.0.0'), os.path.join('goo', '.libs', 'libgoo.a.bc'), os.path.join('fofi', '.libs', 'libfofi.a.bc'), os.path.join('splash', '.libs', 'libsplash.a.bc'), @@ -3825,7 +3825,7 @@ at function.:blag shutil.copy(path_from_root('tests', 'openjpeg', 'opj_config.h'), self.get_dir()) lib = self.get_library('openjpeg', - [os.path.join('bin', 'libopenjpeg.so.1.4.0.bc'), + [os.path.join('bin', 'libopenjpeg.so.1.4.0'), os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/index.c.o'.split('/')), os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/convert.c.o'.split('/')), os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/color.c.o'.split('/')), @@ -4484,8 +4484,8 @@ Child2:9 main_name = os.path.join(self.get_dir(), 'main.cpp') open(main_name, 'w').write(main) - Building.emmaken(module_name, ['-g']) - Building.emmaken(main_name, ['-g']) + Building.emcc(module_name, ['-g']) + Building.emcc(main_name, ['-g']) all_name = os.path.join(self.get_dir(), 'all.bc') Building.link([module_name + '.o', main_name + '.o'], all_name) @@ -4889,11 +4889,6 @@ TT = %s del T # T is just a shape for the specific subclasses, we don't test it itself class other(RunnerCore): - def test_reminder(self): - raise Exception('''Fix emmaken.py and emconfiguren.py, they should work but mention they are deprecated - Test emconfigure - configure in test_zlib looks broken''') - def test_emcc(self): def clear(): for name in os.listdir(self.get_dir()): @@ -4939,6 +4934,13 @@ Options that are modified or new in %s include: assert os.path.exists(target), 'Expected %s to exist since args are %s : %s' % (target, str(args), '\n'.join(output)) self.assertContained('hello, world!', self.run_llvm_interpreter([target])) + # emcc src.ll ==> generates .js + clear() + output = Popen([compiler, path_from_root('tests', 'hello_world.ll')], stdout=PIPE, stderr=PIPE).communicate() + assert len(output[0]) == 0, output[0] + assert os.path.exists('a.out.js'), '\n'.join(output) + self.assertContained('hello, world!', run_js('a.out.js')) + # dlmalloc. dlmalloc is special in that it is the only part of libc that is (1) hard to write well, and # very speed-sensitive. So we do not implement it in JS in library.js, instead we compile it from source for source, has_malloc in [('hello_world' + suffix, False), ('hello_malloc.cpp', True)]: @@ -5057,12 +5059,11 @@ Options that are modified or new in %s include: assert os.path.exists('combined.bc'), '\n'.join(output) self.assertContained('side got: hello from main, over', self.run_llvm_interpreter(['combined.bc'])) - # TODO: compile .ll inputs to emcc into .bc # TODO: test normal project linking, static and dynamic: get_library should not need to be told what to link! # TODO: when ready, switch tools/shared building to use emcc over emmaken # TODO: when this is done, more test runner to test these (i.e., test all -Ox thoroughly) # TODO: emscripten tutorial with emcc - # TODO: deprecate llvm optimizations etc. in emscripten.py. + # TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py. # Finally, do some web browser tests def run_browser(html_file, message): @@ -5147,8 +5148,14 @@ else: Building.COMPILER = CLANG - # Pick the JS engine to benchmark - JS_ENGINE = JS_ENGINES[1] + # Pick the JS engine to benchmark. If you specify one, it will be picked. For example, python tests/runner.py benchmark SPIDERMONKEY_ENGINE + JS_ENGINE = JS_ENGINES[0] + for i in range(1, len(sys.argv)): + arg = sys.argv[i] + if not arg.startswith('test_'): + JS_ENGINE = eval(arg) + sys.argv[i] = None + sys.argv = filter(lambda arg: arg is not None, sys.argv) print 'Benchmarking JS engine:', JS_ENGINE Building.COMPILER_TEST_OPTS = [] diff --git a/tools/emconfiguren.py b/tools/emconfiguren.py index 28cb6366..4987fbbd 100755 --- a/tools/emconfiguren.py +++ b/tools/emconfiguren.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -#raise Exception('emconfiguren is deprecated!') +raise Exception('emconfiguren is deprecated! use "emconfigure" (no "n")') ''' This is a helper script for emmaken.py. See docs in that file for more info. diff --git a/tools/emmaken.py b/tools/emmaken.py index 1192eb85..a3a9a721 100755 --- a/tools/emmaken.py +++ b/tools/emmaken.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -#raise Exception('emmaken is deprecated!') +raise Exception('emmaken is deprecated! use "emcc"') ''' emmaken - the emscripten make proxy tool diff --git a/tools/shared.py b/tools/shared.py index 1b5f5d09..f109d9d2 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -77,6 +77,8 @@ if USE_EMSDK: '-U__APPLE__' ] COMPILER_OPTS += EMSDK_OPTS +else: + EMSDK_OPTS = [] # Engine tweaks @@ -222,11 +224,11 @@ class Building: @staticmethod def get_building_env(): env = os.environ.copy() - env['CC'] = EMMAKEN #EMCC - env['CXX'] = EMMAKEN #EMXX - env['AR'] = EMMAKEN #EMAR - env['RANLIB'] = EMMAKEN #EMRANLIB - env['LIBTOOL'] = EMMAKEN #EMLIBTOOL + env['CC'] = EMCC + env['CXX'] = EMXX + env['AR'] = EMAR + env['RANLIB'] = EMRANLIB + env['LIBTOOL'] = EMLIBTOOL env['EMMAKEN_COMPILER'] = Building.COMPILER env['EMSCRIPTEN_TOOLS'] = path_from_root('tools') env['CFLAGS'] = env['EMMAKEN_CFLAGS'] = ' '.join(COMPILER_OPTS + Building.COMPILER_TEST_OPTS) # Normal CFLAGS is ignored by some configure's. @@ -334,19 +336,20 @@ class Building: assert os.path.exists(filename + '.o.ll'), 'Could not create .ll file: ' + output @staticmethod - def llvm_as(filename): + def llvm_as(input_filename, output_filename=None): # LLVM assembly ==> LLVM binary - try: - os.remove(target) - except: - pass - output = Popen([LLVM_AS, filename + '.o.ll', '-o=' + filename + '.o'], stdout=PIPE).communicate()[0] - assert os.path.exists(filename + '.o'), 'Could not create bc file: ' + output + if output_filename is None: + # use test runner conventions + output_filename = input_filename + '.o' + input_filename = input_filename + '.o.ll' + try_delete(output_filename) + output = Popen([LLVM_AS, input_filename, '-o=' + output_filename], stdout=PIPE).communicate()[0] + assert os.path.exists(output_filename), 'Could not create bc file: ' + output @staticmethod - def llvm_nm(filename): + def llvm_nm(filename, stdout=PIPE, stderr=None): # LLVM binary ==> list of symbols - output = Popen([LLVM_NM, filename], stdout=PIPE).communicate()[0] + output = Popen([LLVM_NM, filename], stdout=stdout, stderr=stderr).communicate()[0] class ret: defs = [] undefs = [] @@ -359,13 +362,10 @@ class Building: ret.defs.append(symbol) return ret - @staticmethod # TODO: make this use emcc instead of emmaken - def emmaken(filename, args=[], stdout=None, stderr=None, env=None): - try: - os.remove(filename + '.o') - except: - pass - Popen([EMMAKEN, filename] + args + ['-o', filename + '.o'], stdout=stdout, stderr=stderr, env=env).communicate()[0] + @staticmethod + def emcc(filename, args=[], stdout=None, stderr=None, env=None): + try_delete(filename + '.o') + Popen([EMCC, filename] + args + ['-o', filename + '.o'], stdout=stdout, stderr=stderr, env=env).communicate()[0] assert os.path.exists(filename + '.o'), 'Could not create bc file' @staticmethod @@ -533,3 +533,16 @@ class Building: return filename + '.cc.js' + @staticmethod + def is_bitcode(filename): + # checks if a file contains LLVM bitcode + # if the file doesn't exist or doesn't have valid symbols, it isn't bitcode + try: + defs = Building.llvm_nm(filename, stderr=PIPE) + assert len(defs.defs + defs.undefs) > 0 + except: + return False + # look for magic signature + b = open(filename, 'r').read(4) + return b[0] == 'B' and b[1] == 'C' + |