aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc17
-rwxr-xr-xemscripten.py11
-rw-r--r--src/analyzer.js2
-rw-r--r--src/intertyper.js2
-rw-r--r--src/library.js37
-rw-r--r--src/library_sdl.js60
-rw-r--r--src/long.js11
-rw-r--r--src/relooper/Relooper.cpp72
-rw-r--r--src/relooper/fuzzer.py4
-rw-r--r--src/relooper/test.txt4
-rw-r--r--tests/cases/invokeundef.ll41
-rw-r--r--tests/cases/longjmp_tiny_noasm_invoke.ll71
-rw-r--r--tests/cases/longjmp_tiny_noasm_invoke.txt2
-rwxr-xr-xtests/fuzz/csmith_driver.py6
-rwxr-xr-xtests/runner.py17
-rw-r--r--tests/sdl_audio.c20
-rw-r--r--tools/shared.py4
17 files changed, 321 insertions, 60 deletions
diff --git a/emcc b/emcc
index e095ced4..d5812ad0 100755
--- a/emcc
+++ b/emcc
@@ -706,19 +706,21 @@ try:
absolute_warning_shown = False
+ settings_changes = []
+
for i in range(len(newargs)):
newargs[i] = newargs[i].strip() # On Windows Vista (and possibly others), excessive spaces in the command line leak into the items in this array, so trim e.g. 'foo.cpp ' -> 'foo.cpp'
if newargs[i].startswith('-O'):
# Let -O default to -O2, which is what gcc does.
requested_level = newargs[i][2:] or '2'
if requested_level == 's':
- print >> sys.stderr, 'emcc: warning: -Os is ignored (use -O0, -O1, -O2)'
- else:
- try:
- opt_level = int(requested_level)
- assert 0 <= opt_level <= 3
- except:
- raise Exception('Invalid optimization level: ' + newargs[i])
+ requested_level = 2
+ settings_changes.append('INLINING_LIMIT=50')
+ try:
+ opt_level = int(requested_level)
+ assert 0 <= opt_level <= 3
+ except:
+ raise Exception('Invalid optimization level: ' + newargs[i])
newargs[i] = ''
elif newargs[i].startswith('--llvm-opts'):
check_bad_eq(newargs[i])
@@ -842,7 +844,6 @@ try:
if closure:
assert os.path.exists(shared.CLOSURE_COMPILER), 'emcc: fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER
- settings_changes = []
for i in range(len(newargs)):
if newargs[i] == '-s':
if is_minus_s_for_emcc(newargs, i):
diff --git a/emscripten.py b/emscripten.py
index 0b9244c2..08ae85c5 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -41,7 +41,8 @@ def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libr
compiler,
engine=compiler_engine,
args=[settings_file, funcs_file, 'funcs', forwarded_file] + libraries,
- stdout=subprocess.PIPE)
+ stdout=subprocess.PIPE,
+ cwd=path_from_root('src'))
tempfiles.try_delete(funcs_file)
return out
@@ -153,7 +154,8 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if out and DEBUG: print >> sys.stderr, ' loading pre from jcache'
if not out:
open(pre_file, 'w').write(pre_input)
- out = jsrun.run_js(compiler, compiler_engine, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE)
+ out = jsrun.run_js(compiler, compiler_engine, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE,
+ cwd=path_from_root('src'))
if jcache:
if DEBUG: print >> sys.stderr, ' saving pre to jcache'
jcache.set(shortkey, keys, out)
@@ -236,7 +238,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
outputs = [output.split('//FORWARDED_DATA:') for output in outputs]
for output in outputs:
- assert len(output) == 2, 'Did not receive forwarded data in an output - process failed? We only got: ' + output[0]
+ assert len(output) == 2, 'Did not receive forwarded data in an output - process failed? We only got: ' + output[0][-300:]
if DEBUG: print >> sys.stderr, ' emscript: phase 2 took %s seconds' % (time.time() - t)
if DEBUG: t = time.time()
@@ -304,7 +306,8 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if DEBUG: t = time.time()
post_file = temp_files.get('.post.ll').name
open(post_file, 'w').write('\n') # no input, just processing of forwarded data
- out = jsrun.run_js(compiler, compiler_engine, [settings_file, post_file, 'post', forwarded_file] + libraries, stdout=subprocess.PIPE)
+ out = jsrun.run_js(compiler, compiler_engine, [settings_file, post_file, 'post', forwarded_file] + libraries, stdout=subprocess.PIPE,
+ cwd=path_from_root('src'))
post, last_forwarded_data = out.split('//FORWARDED_DATA:') # if this fails, perhaps the process failed prior to printing forwarded data?
last_forwarded_json = json.loads(last_forwarded_data)
diff --git a/src/analyzer.js b/src/analyzer.js
index ecb5ea6b..dbbb267d 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -1380,7 +1380,7 @@ function analyzer(data, sidePass) {
var label = func.labels[i];
for (var j = 0; j < label.lines.length; j++) {
var line = label.lines[j];
- if (line.intertype == 'call' && line.ident == setjmp) {
+ if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) {
// Add a new label
var oldIdent = label.ident;
var newIdent = func.labelIdCounter++;
diff --git a/src/intertyper.js b/src/intertyper.js
index 6c88e765..2103ecfa 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -677,7 +677,7 @@ function intertyper(data, sidePass, baseLineNums) {
item.type = item.tokens[1].text;
Types.needAnalysis[item.type] = 0;
while (['@', '%'].indexOf(item.tokens[2].text[0]) == -1 && !(item.tokens[2].text in PARSABLE_LLVM_FUNCTIONS) &&
- item.tokens[2].text != 'null' && item.tokens[2].text != 'asm') {
+ item.tokens[2].text != 'null' && item.tokens[2].text != 'asm' && item.tokens[2].text != 'undef') {
assert(item.tokens[2].text != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
item.tokens.splice(2, 1);
}
diff --git a/src/library.js b/src/library.js
index a288b739..848a2571 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3670,6 +3670,17 @@ LibraryManager.library = {
abs: 'Math.abs',
labs: 'Math.abs',
+#if USE_TYPED_ARRAYS == 2
+ llabs__deps: [function() { Types.preciseI64MathUsed = 1 }],
+ llabs: function(lo, hi) {
+ i64Math.abs(lo, hi);
+ {{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32')]) }}};
+ },
+#else
+ llabs: function(lo, hi) {
+ throw 'unsupported llabs';
+ },
+#endif
exit__deps: ['_exit'],
exit: function(status) {
@@ -5507,6 +5518,14 @@ LibraryManager.library = {
return -a;
},
copysignf: 'copysign',
+ __signbit__deps: ['copysign'],
+ __signbit: function(x) {
+ // We implement using copysign so that we get support
+ // for negative zero (once copysign supports that).
+ return _copysign(1.0, x) < 0;
+ },
+ __signbitf: '__signbit',
+ __signbitd: '__signbit',
hypot: function(a, b) {
return Math.sqrt(a*a + b*b);
},
@@ -6703,6 +6722,13 @@ LibraryManager.library = {
},
// ==========================================================================
+ // sched.h (stubs only - no thread support yet!)
+ // ==========================================================================
+ sched_yield: function() {
+ return 0;
+ },
+
+ // ==========================================================================
// pthread.h (stubs for mutexes only - no thread support yet!)
// ==========================================================================
@@ -6718,8 +6744,15 @@ LibraryManager.library = {
},
pthread_cond_init: function() {},
pthread_cond_destroy: function() {},
- pthread_cond_broadcast: function() {},
- pthread_cond_wait: function() {},
+ pthread_cond_broadcast: function() {
+ return 0;
+ },
+ pthread_cond_wait: function() {
+ return 0;
+ },
+ pthread_cond_timedwait: function() {
+ return 0;
+ },
pthread_self: function() {
//FIXME: assumes only a single thread
return 0;
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 96ae6fa2..d707a8bf 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1463,10 +1463,70 @@ var LibrarySDL = {
return (SDL.music.audio && !SDL.music.audio.paused) ? 1 : 0;
},
+ // http://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer_38.html#SEC38
+ // "Note: Does not check if the channel has been paused."
+ Mix_Playing: function(id) {
+ if (id === -1) {
+ var count = 0;
+ for (var i = 0; i < SDL.audios.length; i++) {
+ count += SDL.Mix_Playing(i);
+ }
+ return count;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio && !info.audio.paused) {
+ return 1;
+ }
+ return 0;
+ },
+
+ Mix_Pause: function(id) {
+ if (id === -1) {
+ for (var i = 0; i<SDL.audios.length;i++) {
+ SDL.Mix_Pause(i);
+ }
+ return;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio) {
+ info.audio.pause();
+ }
+ },
+
+ // http://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer_39.html#SEC39
+ Mix_Paused: function(id) {
+ if (id === -1) {
+ var pausedCount = 0;
+ for (var i = 0; i<SDL.audios.length;i++) {
+ pausedCount += SDL.Mix_Paused(i);
+ }
+ return pausedCount;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio && info.audio.paused) {
+ return 1;
+ }
+ return 0;
+ },
+
Mix_PausedMusic: function() {
return (SDL.music.audio && SDL.music.audio.paused) ? 1 : 0;
},
+ // http://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer_33.html#SEC33
+ Mix_Resume: function(id) {
+ if (id === -1) {
+ for (var i = 0; i<SDL.audios.length;i++) {
+ SDL.Mix_Resume(i);
+ }
+ return;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio) {
+ info.audio.play();
+ }
+ },
+
// SDL TTF
TTF_Init: function() { return 0 },
diff --git a/src/long.js b/src/long.js
index c3b0e605..c3651bd9 100644
--- a/src/long.js
+++ b/src/long.js
@@ -1551,6 +1551,17 @@ var i64Math = (function() { // Emscripten wrapper
HEAP32[tempDoublePtr>>2] = ret.low_;
HEAP32[tempDoublePtr+4>>2] = ret.high_;
},
+ abs: function(l, h) {
+ var x = new goog.math.Long(l, h);
+ var ret;
+ if (x.isNegative()) {
+ ret = x.negate();
+ } else {
+ ret = x;
+ }
+ HEAP32[tempDoublePtr>>2] = ret.low_;
+ HEAP32[tempDoublePtr+4>>2] = ret.high_;
+ },
ensureTemps: function() {
if (Wrapper.ensuredTemps) return;
Wrapper.ensuredTemps = true;
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index 1a7acc15..ae393de3 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -347,17 +347,25 @@ struct RelooperRecursor {
RelooperRecursor(Relooper *ParentInit) : Parent(ParentInit) {}
};
+typedef std::list<Block*> BlockList;
+
void Relooper::Calculate(Block *Entry) {
// Scan and optimize the input
struct PreOptimizer : public RelooperRecursor {
PreOptimizer(Relooper *Parent) : RelooperRecursor(Parent) {}
BlockSet Live;
- void FindLive(Block *Curr) {
- if (Live.find(Curr) != Live.end()) return;
- Live.insert(Curr);
- for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
- FindLive(iter->first);
+ void FindLive(Block *Root) {
+ BlockList ToInvestigate;
+ ToInvestigate.push_back(Root);
+ while (ToInvestigate.size() > 0) {
+ Block *Curr = ToInvestigate.front();
+ ToInvestigate.pop_front();
+ if (Live.find(Curr) != Live.end()) continue;
+ Live.insert(Curr);
+ for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
+ ToInvestigate.push_back(iter->first);
+ }
}
}
@@ -529,7 +537,6 @@ void Relooper::Calculate(Block *Entry) {
// ignore directly reaching the entry itself by another entry.
void FindIndependentGroups(BlockSet &Blocks, BlockSet &Entries, BlockBlockSetMap& IndependentGroups) {
typedef std::map<Block*, Block*> BlockBlockMap;
- typedef std::list<Block*> BlockList;
struct HelperClass {
BlockBlockSetMap& IndependentGroups;
@@ -872,33 +879,38 @@ void Relooper::Calculate(Block *Entry) {
// A flow operation is trivially unneeded if the shape we naturally get to by normal code
// execution is the same as the flow forces us to.
void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) {
- SHAPE_SWITCH(Root, {
- // If there is a next block, we already know at Simple creation time to make direct branches,
- // and we can do nothing more. If there is no next however, then Natural is where we will
- // go to by doing nothing, so we can potentially optimize some branches to direct.
- if (Simple->Next) {
- RemoveUnneededFlows(Simple->Next, Natural);
- } else {
- for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
- Block *Target = iter->first;
- Branch *Details = iter->second;
- if (Details->Type != Branch::Direct && Target->Parent == Natural) {
- Details->Type = Branch::Direct;
- if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
- Multiple->NeedLoop--;
+ Shape *Next = Root;
+ while (Next) {
+ Root = Next;
+ Next = NULL;
+ SHAPE_SWITCH(Root, {
+ // If there is a next block, we already know at Simple creation time to make direct branches,
+ // and we can do nothing more. If there is no next however, then Natural is where we will
+ // go to by doing nothing, so we can potentially optimize some branches to direct.
+ if (Simple->Next) {
+ Next = Simple->Next;
+ } else {
+ for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
+ Block *Target = iter->first;
+ Branch *Details = iter->second;
+ if (Details->Type != Branch::Direct && Target->Parent == Natural) {
+ Details->Type = Branch::Direct;
+ if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
+ Multiple->NeedLoop--;
+ }
}
}
}
- }
- }, {
- for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
- RemoveUnneededFlows(iter->second, Multiple->Next);
- }
- RemoveUnneededFlows(Multiple->Next, Natural);
- }, {
- RemoveUnneededFlows(Loop->Inner, Loop->Inner);
- RemoveUnneededFlows(Loop->Next, Natural);
- });
+ }, {
+ for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ RemoveUnneededFlows(iter->second, Multiple->Next);
+ }
+ Next = Multiple->Next;
+ }, {
+ RemoveUnneededFlows(Loop->Inner, Loop->Inner);
+ Next = Loop->Next;
+ });
+ }
}
// After we know which loops exist, we can calculate which need to be labeled
diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py
index 887eab3b..96929028 100644
--- a/src/relooper/fuzzer.py
+++ b/src/relooper/fuzzer.py
@@ -98,14 +98,14 @@ int main() {
open('fuzz.slow.js', 'w').write(slow)
open('fuzz.cpp', 'w').write(fast)
print '_'
- slow_out = subprocess.Popen(['/home/alon/Dev/mozilla-central/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
+ slow_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
print '.'
subprocess.call(['g++', 'fuzz.cpp', 'Relooper.o', '-o', 'fuzz', '-g'])
print '*'
subprocess.call(['./fuzz'], stdout=open('fuzz.fast.js', 'w'))
print '-'
- fast_out = subprocess.Popen(['/home/alon/Dev/mozilla-central/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
+ fast_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
print
if slow_out != fast_out:
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index b7c8794d..12d0ef39 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -54,7 +54,7 @@ while(1) {
// code 2
if (!($2)) {
var $x_1 = $x_0;
- label = 19;
+ label = 18;
break;
}
// code 3
@@ -64,7 +64,7 @@ while(1) {
var $i_0 = $7;var $x_0 = $5;
}
}
-if (label == 19) {
+if (label == 18) {
// code 7
}
// code 4
diff --git a/tests/cases/invokeundef.ll b/tests/cases/invokeundef.ll
new file mode 100644
index 00000000..9dc1f93d
--- /dev/null
+++ b/tests/cases/invokeundef.ll
@@ -0,0 +1,41 @@
+; ModuleID = '/dev/shm/tmp/src.cpp.o'
+; Just test for compilation here
+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-f128:128:128-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+%struct.CPU_Regs = type { [8 x %union.GenReg32] }
+%union.GenReg32 = type { [1 x i32] }
+
+@cpu_regs = unnamed_addr global %struct.CPU_Regs zeroinitializer, align 32 ; [#uses=2]
+@.str = private unnamed_addr constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1]
+
+; [#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]
+ %1 = load i32* bitcast (i32* getelementptr inbounds (%struct.CPU_Regs* @cpu_regs, i32 0, i32 0, i32 1, i32 0, i32 0) to i32*), align 2 ; [#uses=1]
+ store i16 %1, i16* bitcast (%struct.CPU_Regs* @cpu_regs to i16*), align 2
+ %2 = call i32 @puts(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ store i32 0, i32* %0, align 4
+ %3 = load i32* %0, align 4 ; [#uses=1]
+ store i32 %3, i32* %retval, align 4
+ br label %return
+
+ invoke void undef(%struct.CPU_Regs* noalias @cpu_regs, i32 %99)
+ to label %invcont33 unwind label %lpad106
+
+invcont33:
+ ret i32 %retval1
+
+lpad106:
+ ret i32 %retval1
+
+return: ; preds = %entry
+ %retval1 = load i32* %retval ; [#uses=1]
+ ret i32 %retval1
+}
+
+; [#uses=1]
+declare i32 @puts(i8*)
diff --git a/tests/cases/longjmp_tiny_noasm_invoke.ll b/tests/cases/longjmp_tiny_noasm_invoke.ll
new file mode 100644
index 00000000..e1a72e00
--- /dev/null
+++ b/tests/cases/longjmp_tiny_noasm_invoke.ll
@@ -0,0 +1,71 @@
+; ModuleID = '/tmp/emscripten_temp/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-S128"
+target triple = "i386-pc-linux-gnu"
+
+@_ZL3buf = internal global [20 x i16] zeroinitializer, align 2
+@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00", align 1
+@.str1 = private unnamed_addr constant [6 x i8] c"more\0A\00", align 1
+
+define i32 @main() {
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval
+ %call = invoke i32 @setjmp(i16* getelementptr inbounds ([20 x i16]* @_ZL3buf, i32 0, i32 0)) returns_twice, !dbg !20
+ to label %allgood unwind label %awful
+
+allgood:
+ %tobool = icmp ne i32 %call, 0, !dbg !20
+ br i1 %tobool, label %if.else, label %if.then, !dbg !20
+
+if.then: ; preds = %entry
+ %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0)), !dbg !22
+ call void @longjmp(i16* getelementptr inbounds ([20 x i16]* @_ZL3buf, i32 0, i32 0), i32 10), !dbg !24
+ br label %if.end, !dbg !25
+
+if.else: ; preds = %entry
+ %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str1, i32 0, i32 0)), !dbg !26
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ ret i32 0, !dbg !28
+
+awful:
+ ret i32 1
+}
+
+declare i32 @setjmp(i16*) returns_twice
+
+declare i32 @printf(i8*, ...)
+
+declare void @longjmp(i16*, i32)
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 786449, i32 0, i32 4, metadata !"/tmp/emscripten_temp/src.cpp", metadata !"/home/alon/Dev/emscripten", metadata !"clang version 3.1 (trunk 150936)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !12} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 786478, i32 0, metadata !6, metadata !"main", metadata !"main", metadata !"", metadata !6, i32 7, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @main, null, null, metadata !10} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 786473, metadata !"/tmp/emscripten_temp/src.cpp", metadata !"/home/alon/Dev/emscripten", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 786453, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{metadata !9}
+!9 = metadata !{i32 786468, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!10 = metadata !{metadata !11}
+!11 = metadata !{i32 786468} ; [ DW_TAG_base_type ]
+!12 = metadata !{metadata !13}
+!13 = metadata !{metadata !14}
+!14 = metadata !{i32 786484, i32 0, null, metadata !"buf", metadata !"buf", metadata !"_ZL3buf", metadata !6, i32 5, metadata !15, i32 1, i32 1, [20 x i16]* @_ZL3buf} ; [ DW_TAG_variable ]
+!15 = metadata !{i32 786454, null, metadata !"jmp_buf", metadata !6, i32 279, i64 0, i64 0, i64 0, i32 0, metadata !16} ; [ DW_TAG_typedef ]
+!16 = metadata !{i32 786433, null, metadata !"", null, i32 0, i64 320, i64 16, i32 0, i32 0, metadata !17, metadata !18, i32 0, i32 0} ; [ DW_TAG_array_type ]
+!17 = metadata !{i32 786468, null, metadata !"unsigned short", null, i32 0, i64 16, i64 16, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ]
+!18 = metadata !{metadata !19}
+!19 = metadata !{i32 786465, i64 0, i64 19} ; [ DW_TAG_subrange_type ]
+!20 = metadata !{i32 8, i32 18, metadata !21, null}
+!21 = metadata !{i32 786443, metadata !5, i32 7, i32 22, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
+!22 = metadata !{i32 9, i32 15, metadata !23, null}
+!23 = metadata !{i32 786443, metadata !21, i32 8, i32 31, metadata !6, i32 1} ; [ DW_TAG_lexical_block ]
+!24 = metadata !{i32 10, i32 15, metadata !23, null}
+!25 = metadata !{i32 11, i32 13, metadata !23, null}
+!26 = metadata !{i32 12, i32 15, metadata !27, null}
+!27 = metadata !{i32 786443, metadata !21, i32 11, i32 20, metadata !6, i32 2} ; [ DW_TAG_lexical_block ]
+!28 = metadata !{i32 14, i32 13, metadata !21, null}
diff --git a/tests/cases/longjmp_tiny_noasm_invoke.txt b/tests/cases/longjmp_tiny_noasm_invoke.txt
new file mode 100644
index 00000000..8a0aa386
--- /dev/null
+++ b/tests/cases/longjmp_tiny_noasm_invoke.txt
@@ -0,0 +1,2 @@
+hello world
+more
diff --git a/tests/fuzz/csmith_driver.py b/tests/fuzz/csmith_driver.py
index 6c6965df..5bdef009 100755
--- a/tests/fuzz/csmith_driver.py
+++ b/tests/fuzz/csmith_driver.py
@@ -48,11 +48,11 @@ while 1:
shared.execute([shared.CLANG_CC, filename + '.c', '-o', filename + '3'] + CSMITH_CFLAGS, stderr=PIPE)
print '3) Run natively'
try:
- correct1 = shared.timeout_run(Popen([filename + '1'], stdout=PIPE, stderr=PIPE), 3)
+ correct1 = shared.jsrun.timeout_run(Popen([filename + '1'], stdout=PIPE, stderr=PIPE), 3)
if 'Segmentation fault' in correct1 or len(correct1) < 10: raise Exception('segfault')
- correct2 = shared.timeout_run(Popen([filename + '2'], stdout=PIPE, stderr=PIPE), 3)
+ correct2 = shared.jsrun.timeout_run(Popen([filename + '2'], stdout=PIPE, stderr=PIPE), 3)
if 'Segmentation fault' in correct2 or len(correct2) < 10: raise Exception('segfault')
- correct3 = shared.timeout_run(Popen([filename + '3'], stdout=PIPE, stderr=PIPE), 3)
+ correct3 = shared.jsrun.timeout_run(Popen([filename + '3'], stdout=PIPE, stderr=PIPE), 3)
if 'Segmentation fault' in correct3 or len(correct3) < 10: raise Exception('segfault')
if correct1 != correct3: raise Exception('clang opts change result')
except Exception, e:
diff --git a/tests/runner.py b/tests/runner.py
index 3d3bbdeb..eec4872b 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -1054,6 +1054,19 @@ m_divisor is 1091269979
}
''', 'c = 4ca38a6bd2973f97')
+ def test_i64_llabs(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+ Settings.PRECISE_I64_MATH = 2
+ self.do_run(r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main(int argc, char ** argv) {
+ printf("%lld,%lld\n", llabs(-576460752303423489), llabs(576460752303423489));
+ return 0;
+ }
+ ''', '576460752303423489,576460752303423489')
+
def test_i64_zextneg(self):
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
@@ -8642,6 +8655,7 @@ Options that are modified or new in %s include:
(['-o', 'something.js', '-O2'], 2, None, 0, 1),
(['-o', 'something.js', '-O2', '--closure', '0'], 2, None, 0, 0),
(['-o', 'something.js', '-O2', '-g'], 2, None, 0, 0),
+ (['-o', 'something.js', '-Os'], 2, None, 0, 1),
(['-o', 'something.js', '-O3'], 3, None, 1, 1),
(['-o', 'something.js', '-O3', '--closure', '0'], 3, None, 0, 0),
# and, test compiling to bitcode first
@@ -8693,6 +8707,7 @@ Options that are modified or new in %s include:
(['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var i1 = 0' not in generated, 'registerize is cancelled by -g'),
(['-s', 'INLINING_LIMIT=0'], lambda generated: 'function _dump' in generated, 'no inlining without opts'),
(['-O3', '-s', 'INLINING_LIMIT=0', '--closure', '0'], lambda generated: 'function _dump' not in generated, 'lto/inlining'),
+ (['-Os', '--llvm-lto', '1'], lambda generated: 'function _dump' in generated, '-Os disables inlining'),
(['-s', 'USE_TYPED_ARRAYS=0'], lambda generated: 'new Int32Array' not in generated, 'disable typed arrays'),
(['-s', 'USE_TYPED_ARRAYS=1'], lambda generated: 'IHEAPU = ' in generated, 'typed arrays 1 selected'),
([], lambda generated: 'Module["_dump"]' not in generated, 'dump is not exported by default'),
@@ -11414,7 +11429,7 @@ elif 'benchmark' in str(sys.argv):
try_delete(final_filename)
output = Popen([PYTHON, EMCC, filename, #'-O3',
'-O2', '-s', 'INLINING_LIMIT=0', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0',# '-s', 'EXPLICIT_ZEXT=1',
- '-s', 'ASM_JS=1', '-s', 'USE_MATH_IMUL=1',
+ '-s', 'ASM_JS=1', '-s', 'USE_MATH_IMUL=1', '--llvm-lto', '1',
'-s', 'TOTAL_MEMORY=128*1024*1024', '-s', 'FAST_MEMORY=10*1024*1024',
'-o', final_filename] + shared_args + emcc_args, stdout=PIPE, stderr=self.stderr_redirect).communicate()
assert os.path.exists(final_filename), 'Failed to compile file: ' + output[0]
diff --git a/tests/sdl_audio.c b/tests/sdl_audio.c
index 938df3c4..ce3bf5a9 100644
--- a/tests/sdl_audio.c
+++ b/tests/sdl_audio.c
@@ -6,13 +6,14 @@
Mix_Chunk *sound, *sound2;
-void play2();
+int play2();
-void play() {
+int play() {
int channel = Mix_PlayChannel(-1, sound, 1);
assert(channel == 0);
emscripten_run_script("setTimeout(Module['_play2'], 500)");
+ return channel;
}
void done(int channel) {
@@ -22,11 +23,12 @@ void done(int channel) {
REPORT_RESULT();
}
-void play2() {
+int play2() {
Mix_ChannelFinished(done);
int channel2 = Mix_PlayChannel(-1, sound2, 1);
assert(channel2 == 1);
+ return channel2;
}
int main(int argc, char **argv) {
@@ -40,7 +42,17 @@ int main(int argc, char **argv) {
sound2 = Mix_LoadWAV("sound2.wav");
assert(sound);
- play();
+ int channel = play();
+ printf( "Pausing Channel %d", channel );
+ Mix_Pause(channel);
+ int paused = Mix_Paused(channel);
+ printf( "Channel %d %s", channel, paused ? "is paused" : "is NOT paused" );
+ assert(paused);
+ Mix_Resume(channel);
+ paused = Mix_Paused(channel);
+ printf( "Channel %d %s", channel, paused ? "is paused" : "is NOT paused" );
+ assert(paused == 0);
+
if (argc == 12121) play2(); // keep it alive
emscripten_run_script("element = document.createElement('input');"
diff --git a/tools/shared.py b/tools/shared.py
index 09f6aef4..6434fb06 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -181,7 +181,7 @@ def check_node_version():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.2.6'
+EMSCRIPTEN_VERSION = '1.2.8'
def check_sanity(force=False):
try:
@@ -388,11 +388,11 @@ if USE_EMSDK:
# Note that -nostdinc++ is not needed, since -nostdinc implies that!
EMSDK_OPTS = ['-nostdinc', '-Xclang', '-nobuiltininc', '-Xclang', '-nostdsysteminc',
'-Xclang', '-isystem' + path_from_root('system', 'local', 'include'),
+ '-Xclang', '-isystem' + path_from_root('system', 'include', 'libcxx'),
'-Xclang', '-isystem' + path_from_root('system', 'include'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'emscripten'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'bsd'), # posix stuff
'-Xclang', '-isystem' + path_from_root('system', 'include', 'libc'),
- '-Xclang', '-isystem' + path_from_root('system', 'include', 'libcxx'),
'-Xclang', '-isystem' + path_from_root('system', 'lib', 'libcxxabi', 'include'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'gfx'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'net'),