webruby 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/lib/webruby/environment.rb +4 -0
  3. data/lib/webruby/rake/files.rake +2 -1
  4. data/lib/webruby/rake/mruby.rake +4 -2
  5. data/modules/emscripten/AUTHORS +1 -0
  6. data/modules/emscripten/cmake/Platform/Emscripten.cmake +2 -0
  7. data/modules/emscripten/emcc +96 -40
  8. data/modules/emscripten/emrun +301 -136
  9. data/modules/emscripten/emscripten.py +5 -45
  10. data/modules/emscripten/src/analyzer.js +11 -1
  11. data/modules/emscripten/src/compiler.js +1 -1
  12. data/modules/emscripten/src/emrun_postjs.js +2 -2
  13. data/modules/emscripten/src/emrun_prejs.js +5 -0
  14. data/modules/emscripten/src/emscripten-source-map.min.js +31 -0
  15. data/modules/emscripten/src/library.js +187 -0
  16. data/modules/emscripten/src/library_egl.js +20 -0
  17. data/modules/emscripten/src/library_sdl.js +1 -0
  18. data/modules/emscripten/src/preamble.js +4 -0
  19. data/modules/emscripten/src/relooper/Relooper.cpp +33 -15
  20. data/modules/emscripten/src/relooper/Relooper.h +20 -14
  21. data/modules/emscripten/src/relooper/fuzzer.py +6 -0
  22. data/modules/emscripten/src/relooper/test.cpp +28 -0
  23. data/modules/emscripten/src/relooper/test.txt +211 -166
  24. data/modules/emscripten/src/relooper/test2.txt +20 -20
  25. data/modules/emscripten/src/relooper/test3.txt +41 -41
  26. data/modules/emscripten/src/relooper/test4.txt +26 -26
  27. data/modules/emscripten/src/relooper/test5.txt +52 -52
  28. data/modules/emscripten/src/relooper/test6.txt +19 -19
  29. data/modules/emscripten/src/relooper/test_dead.txt +1 -1
  30. data/modules/emscripten/src/relooper/test_debug.txt +31 -31
  31. data/modules/emscripten/src/relooper/test_fuzz1.txt +50 -50
  32. data/modules/emscripten/src/relooper/test_fuzz2.txt +21 -21
  33. data/modules/emscripten/src/relooper/test_fuzz3.txt +18 -18
  34. data/modules/emscripten/src/relooper/test_fuzz4.txt +28 -28
  35. data/modules/emscripten/src/relooper/test_fuzz5.txt +61 -61
  36. data/modules/emscripten/src/relooper/test_fuzz6.txt +179 -179
  37. data/modules/emscripten/src/relooper/test_inf.txt +846 -846
  38. data/modules/emscripten/src/relooper/testit.sh +15 -15
  39. data/modules/emscripten/system/include/emscripten/emscripten.h +64 -0
  40. data/modules/emscripten/tools/eliminator/asm-eliminator-test-output.js +8 -2
  41. data/modules/emscripten/tools/eliminator/asm-eliminator-test.js +9 -1
  42. data/modules/emscripten/tools/eliminator/eliminator-test-output.js +11 -0
  43. data/modules/emscripten/tools/eliminator/eliminator-test.js +16 -1
  44. data/modules/emscripten/tools/file_packager.py +59 -49
  45. data/modules/emscripten/tools/js-optimizer.js +47 -8
  46. data/modules/emscripten/tools/shared.py +3 -3
  47. data/modules/emscripten/tools/test-js-optimizer-asm-pre-output.js +5 -3
  48. data/modules/emscripten/tools/test-js-optimizer-asm-pre.js +4 -0
  49. data/modules/mruby/INSTALL +11 -6
  50. data/modules/mruby/include/mrbconf.h +0 -3
  51. data/modules/mruby/include/mruby/khash.h +34 -36
  52. data/modules/mruby/include/mruby/string.h +3 -0
  53. data/modules/mruby/include/mruby.h +3 -3
  54. data/modules/mruby/mrblib/string.rb +3 -0
  55. data/modules/mruby/src/class.c +12 -12
  56. data/modules/mruby/src/codegen.c +18 -11
  57. data/modules/mruby/src/hash.c +12 -12
  58. data/modules/mruby/src/kernel.c +3 -3
  59. data/modules/mruby/src/load.c +29 -14
  60. data/modules/mruby/src/numeric.c +1 -1
  61. data/modules/mruby/src/object.c +14 -2
  62. data/modules/mruby/src/state.c +13 -10
  63. data/modules/mruby/src/string.c +1 -3
  64. data/modules/mruby/src/symbol.c +44 -18
  65. data/modules/mruby/src/variable.c +6 -6
  66. data/modules/mruby/test/t/class.rb +34 -0
  67. data/modules/mruby/test/t/module.rb +1 -1
  68. data/modules/mruby/test/t/syntax.rb +28 -0
  69. metadata +5 -13
  70. data/modules/emscripten/src/relooper.js +0 -11516
  71. data/modules/emscripten/src/relooper.js.raw.js +0 -11511
  72. data/modules/emscripten/tools/__init__.pyc +0 -0
  73. data/modules/emscripten/tools/cache.pyc +0 -0
  74. data/modules/emscripten/tools/gen_struct_info.pyc +0 -0
  75. data/modules/emscripten/tools/js_optimizer.pyc +0 -0
  76. data/modules/emscripten/tools/jsrun.pyc +0 -0
  77. data/modules/emscripten/tools/response_file.pyc +0 -0
  78. data/modules/emscripten/tools/shared.pyc +0 -0
  79. data/modules/emscripten/tools/tempfiles.pyc +0 -0
@@ -733,60 +733,20 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
733
733
  # * Run compiler.js on the metadata to emit the shell js code, pre/post-ambles,
734
734
  # JS library dependencies, etc.
735
735
 
736
- if DEBUG: logging.debug('emscript: llvm backend')
737
-
738
- # TODO: proper temp files
739
- # TODO: use a single LLVM toolchain instead of normal for source, pnacl for simplification, custom for js backend
740
-
741
- if DEBUG: shutil.copyfile(infile, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp0.ll'))
742
-
743
- extra_opt_args = []
744
- #if DEBUG: extra_opt_args.append('-time-passes')
745
-
746
- if DEBUG: t = time.time()
747
-
748
- if DEBUG: logging.debug(' ..1..')
749
- temp1 = temp_files.get('.1.bc').name
750
- shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'opt'), infile, '-pnacl-abi-simplify-preopt', '-o', temp1] + extra_opt_args))
751
- assert os.path.exists(temp1)
752
- if DEBUG:
753
- shutil.copyfile(temp1, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp1.bc'))
754
- shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'llvm-dis'), 'temp1.bc', '-o', 'temp1.ll']))
755
-
756
- #if DEBUG: logging.debug(' ..2..')
757
- #temp2 = temp_files.get('.2.bc').name
758
- #shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'opt'), temp1, '-O3', '-o', temp2]))
759
- #assert os.path.exists(temp2)
760
- #if DEBUG:
761
- # shutil.copyfile(temp2, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp2.bc'))
762
- # shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'llvm-dis'), 'temp2.bc', '-o', 'temp2.ll']))
763
- temp2 = temp1 # XXX if we optimize the bc, we remove some pnacl clutter, but it also makes varargs stores be 8-byte aligned
764
-
765
- if DEBUG: logging.debug(' ..3..')
766
- temp3 = temp_files.get('.3.bc').name
767
- shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'opt'), temp2, '-pnacl-abi-simplify-postopt', '-o', temp3] + extra_opt_args))
768
- #'-print-after-all'
769
- assert os.path.exists(temp3)
770
- if DEBUG:
771
- shutil.copyfile(temp3, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp3.bc'))
772
- shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'llvm-dis'), 'temp3.bc', '-o', 'temp3.ll']))
773
-
774
736
  if DEBUG:
775
- logging.debug(' emscript: ir simplification took %s seconds' % (time.time() - t))
737
+ logging.debug('emscript: llvm backend')
776
738
  t = time.time()
777
739
 
778
- if DEBUG: logging.debug(' ..4..')
779
- temp4 = temp_files.get('.4.js').name
740
+ temp_js = temp_files.get('.4.js').name
780
741
  backend_compiler = os.path.join(shared.LLVM_ROOT, 'llc')
781
- shared.jsrun.timeout_run(subprocess.Popen([backend_compiler, temp3, '-march=js', '-filetype=asm', '-o', temp4], stdout=subprocess.PIPE))
782
- if DEBUG: shutil.copyfile(temp4, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp4.js'))
742
+ shared.jsrun.timeout_run(subprocess.Popen([backend_compiler, infile, '-march=js', '-filetype=asm', '-o', temp_js], stdout=subprocess.PIPE))
783
743
 
784
744
  if DEBUG:
785
745
  logging.debug(' emscript: llvm backend took %s seconds' % (time.time() - t))
786
746
  t = time.time()
787
747
 
788
748
  # Split up output
789
- backend_output = open(temp4).read()
749
+ backend_output = open(temp_js).read()
790
750
  #if DEBUG: print >> sys.stderr, backend_output
791
751
 
792
752
  start_funcs_marker = '// EMSCRIPTEN_START_FUNCTIONS'
@@ -825,7 +785,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
825
785
  else:
826
786
  num = num[:e] + '.0' + num[e:]
827
787
  return m.group(1) + m.group(2) + num
828
- funcs = re.sub(r'([(=,+\-*/%] *)\+(-?)((0x)?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)', lambda m: fix_dot_zero(m), funcs)
788
+ funcs = re.sub(r'([(=,+\-*/%<>:?] *)\+(-?)((0x)?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)', lambda m: fix_dot_zero(m), funcs)
829
789
 
830
790
  # js compiler
831
791
 
@@ -1570,7 +1570,17 @@ function analyzer(data, sidePass) {
1570
1570
  for (var j = 0; j < label.lines.length; j++) {
1571
1571
  var line = label.lines[j];
1572
1572
  if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) {
1573
- // Add a new label
1573
+ if (line.intertype == 'invoke') {
1574
+ // setjmp cannot trigger unwinding, so just reduce the invoke to a call + branch
1575
+ line.intertype = 'call';
1576
+ label.lines.push({
1577
+ intertype: 'branch',
1578
+ label: line.toLabel,
1579
+ lineNum: line.lineNum + 0.01, // XXX legalizing might confuse this
1580
+ });
1581
+ line.toLabel = line.unwindLabel = -2;
1582
+ }
1583
+ // split this label into up to the setjmp (including), then a new label for the rest. longjmp will reach the rest
1574
1584
  var oldLabel = label.ident;
1575
1585
  var newLabel = func.labelIdCounter++;
1576
1586
  if (!func.setjmpTable) func.setjmpTable = [];
@@ -134,7 +134,7 @@ load('settings.js');
134
134
  var settings_file = arguments_[0];
135
135
  var ll_file = arguments_[1];
136
136
  phase = arguments_[2];
137
- if (phase == 'pre') {
137
+ if (phase == 'pre' || phase == 'glue') {
138
138
  additionalLibraries = Array.prototype.slice.call(arguments_, 3);
139
139
  } else {
140
140
  var forwardedDataFile = arguments_[3];
@@ -4,8 +4,8 @@ function emrun_register_handlers() {
4
4
  http.open("POST", "stdio.html", true);
5
5
  http.send(msg);
6
6
  }
7
- // If the address contains localhost, we can assume we're running the test runner and should post stdout logs.
8
- if (document.URL.search("localhost") != -1) {
7
+ // If the address contains localhost, or we are running the page from port 6931, we can assume we're running the test runner and should post stdout logs.
8
+ if (document.URL.search("localhost") != -1 || document.URL.search(":6931/") != -1) {
9
9
  var emrun_http_sequence_number = 1;
10
10
  var prevExit = Module['exit'];
11
11
  var prevPrint = Module['print'];
@@ -0,0 +1,5 @@
1
+ // Route URL GET parameters to argc+argv
2
+ Module['arguments'] = window.location.search.substr(1).trim().split('&');
3
+ // If no args were passed arguments = [''], in which case kill the single empty string.
4
+ if (!Module['arguments'][0])
5
+ Module['arguments'] = [];
@@ -0,0 +1,31 @@
1
+ function define(e,t,n){if(typeof e!="string")throw new TypeError("Expected string, got: "+e);arguments.length==2&&(n=t);if(e in define.modules)throw new Error("Module already defined: "+e);define.modules[e]=n}function Domain(){this.modules={},this._currentModule=null}define.modules={},function(){function e(e){var t=e.split("/"),n=1;while(n<t.length)t[n]===".."?t.splice(n-1,1):t[n]==="."?t.splice(n,1):n++;return t.join("/")}function t(e,t){return e=e.trim(),t=t.trim(),/^\//.test(t)?t:e.replace(/\/*$/,"/")+t}function n(e){var t=e.split("/");return t.pop(),t.join("/")}Domain.prototype.require=function(e,t){if(Array.isArray(e)){var n=e.map(function(e){return this.lookup(e)},this);return t&&t.apply(null,n),undefined}return this.lookup(e)},Domain.prototype.lookup=function(r){/^\./.test(r)&&(r=e(t(n(this._currentModule),r)));if(r in this.modules){var i=this.modules[r];return i}if(r in define.modules){var i=define.modules[r];if(typeof i=="function"){var s={},o=this._currentModule;this._currentModule=r,i(this.require.bind(this),s,{id:r,uri:""}),this._currentModule=o,i=s}return this.modules[r]=i,i}throw new Error("Module not defined: "+r)}}(),define.Domain=Domain,define.globalDomain=new Domain;var require=define.globalDomain.require.bind(define.globalDomain);define("source-map/source-map-generator",["require","exports","module","source-map/base64-vlq","source-map/util","source-map/array-set"],function(e,t,n){function o(e){this._file=i.getArg(e,"file"),this._sourceRoot=i.getArg(e,"sourceRoot",null),this._sources=new s,this._names=new s,this._mappings=[],this._sourcesContents=null}function u(e,t){var n=(e&&e.line)-(t&&t.line);return n?n:(e&&e.column)-(t&&t.column)}function a(e,t){return e=e||"",t=t||"",(e>t)-(e<t)}function f(e,t){return u(e.generated,t.generated)||u(e.original,t.original)||a(e.source,t.source)||a(e.name,t.name)}var r=e("./base64-vlq"),i=e("./util"),s=e("./array-set").ArraySet;o.prototype._version=3,o.fromSourceMap=function(t){var n=t.sourceRoot,r=new o({file:t.file,sourceRoot:n});return t.eachMapping(function(e){var t={generated:{line:e.generatedLine,column:e.generatedColumn}};e.source&&(t.source=e.source,n&&(t.source=i.relative(n,t.source)),t.original={line:e.originalLine,column:e.originalColumn},e.name&&(t.name=e.name)),r.addMapping(t)}),t.sources.forEach(function(e){var n=t.sourceContentFor(e);n&&r.setSourceContent(e,n)}),r},o.prototype.addMapping=function(t){var n=i.getArg(t,"generated"),r=i.getArg(t,"original",null),s=i.getArg(t,"source",null),o=i.getArg(t,"name",null);this._validateMapping(n,r,s,o),s&&!this._sources.has(s)&&this._sources.add(s),o&&!this._names.has(o)&&this._names.add(o),this._mappings.push({generated:n,original:r,source:s,name:o})},o.prototype.setSourceContent=function(t,n){var r=t;this._sourceRoot&&(r=i.relative(this._sourceRoot,r)),n!==null?(this._sourcesContents||(this._sourcesContents={}),this._sourcesContents[i.toSetString(r)]=n):(delete this._sourcesContents[i.toSetString(r)],Object.keys(this._sourcesContents).length===0&&(this._sourcesContents=null))},o.prototype.applySourceMap=function(t,n){n||(n=t.file);var r=this._sourceRoot;r&&(n=i.relative(r,n));var o=new s,u=new s;this._mappings.forEach(function(e){if(e.source===n&&e.original){var s=t.originalPositionFor({line:e.original.line,column:e.original.column});s.source!==null&&(r?e.source=i.relative(r,s.source):e.source=s.source,e.original.line=s.line,e.original.column=s.column,s.name!==null&&e.name!==null&&(e.name=s.name))}var a=e.source;a&&!o.has(a)&&o.add(a);var f=e.name;f&&!u.has(f)&&u.add(f)},this),this._sources=o,this._names=u,t.sources.forEach(function(e){var n=t.sourceContentFor(e);n&&(r&&(e=i.relative(r,e)),this.setSourceContent(e,n))},this)},o.prototype._validateMapping=function(t,n,r,i){if(t&&"line"in t&&"column"in t&&t.line>0&&t.column>=0&&!n&&!r&&!i)return;if(t&&"line"in t&&"column"in t&&n&&"line"in n&&"column"in n&&t.line>0&&t.column>=0&&n.line>0&&n.column>=0&&r)return;throw new Error("Invalid mapping.")},o.prototype._serializeMappings=function(){var t=0,n=1,i=0,s=0,o=0,u=0,a="",l;this._mappings.sort(f);for(var c=0,h=this._mappings.length;c<h;c++){l=this._mappings[c];if(l.generated.line!==n){t=0;while(l.generated.line!==n)a+=";",n++}else if(c>0){if(!f(l,this._mappings[c-1]))continue;a+=","}a+=r.encode(l.generated.column-t),t=l.generated.column,l.source&&l.original&&(a+=r.encode(this._sources.indexOf(l.source)-u),u=this._sources.indexOf(l.source),a+=r.encode(l.original.line-1-s),s=l.original.line-1,a+=r.encode(l.original.column-i),i=l.original.column,l.name&&(a+=r.encode(this._names.indexOf(l.name)-o),o=this._names.indexOf(l.name)))}return a},o.prototype.toJSON=function(){var t={version:this._version,file:this._file,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};return this._sourceRoot&&(t.sourceRoot=this._sourceRoot),this._sourcesContents&&(t.sourcesContent=t.sources.map(function(e){return t.sourceRoot&&(e=i.relative(t.sourceRoot,e)),Object.prototype.hasOwnProperty.call(this._sourcesContents,i.toSetString(e))?this._sourcesContents[i.toSetString(e)]:null},this)),t},o.prototype.toString=function(){return JSON.stringify(this)},t.SourceMapGenerator=o}),define("source-map/base64-vlq",["require","exports","module","source-map/base64"],function(e,t,n){function a(e){return e<0?(-e<<1)+1:(e<<1)+0}function f(e){var t=(e&1)===1,n=e>>1;return t?-n:n}var r=e("./base64"),i=5,s=1<<i,o=s-1,u=s;t.encode=function(t){var n="",s,f=a(t);do s=f&o,f>>>=i,f>0&&(s|=u),n+=r.encode(s);while(f>0);return n},t.decode=function(t){var n=0,s=t.length,a=0,l=0,c,h;do{if(n>=s)throw new Error("Expected more digits in base 64 VLQ value.");h=r.decode(t.charAt(n++)),c=!!(h&u),h&=o,a+=h<<l,l+=i}while(c);return{value:f(a),rest:t.slice(n)}}}),define("source-map/base64",["require","exports","module"],function(e,t,n){var r={},i={};"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("").forEach(function(e,t){r[e]=t,i[t]=e}),t.encode=function(t){if(t in i)return i[t];throw new TypeError("Must be between 0 and 63: "+t)},t.decode=function(t){if(t in r)return r[t];throw new TypeError("Not a valid base 64 digit: "+t)}}),define("source-map/util",["require","exports","module"],function(e,t,n){function r(e,t,n){if(t in e)return e[t];if(arguments.length===3)return n;throw new Error('"'+t+'" is a required argument.')}function s(e){var t=e.match(i);return t?{scheme:t[1],auth:t[3],host:t[4],port:t[6],path:t[7]}:null}function o(e){var t=e.scheme+"://";return e.auth&&(t+=e.auth+"@"),e.host&&(t+=e.host),e.port&&(t+=":"+e.port),e.path&&(t+=e.path),t}function u(e,t){var n;return t.match(i)?t:t.charAt(0)==="/"&&(n=s(e))?(n.path=t,o(n)):e.replace(/\/$/,"")+"/"+t}function a(e){return"$"+e}function f(e){return e.substr(1)}function l(e,t){e=e.replace(/\/$/,"");var n=s(e);return t.charAt(0)=="/"&&n&&n.path=="/"?t.slice(1):t.indexOf(e+"/")===0?t.substr(e.length+1):t}t.getArg=r;var i=/([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/;t.urlParse=s,t.urlGenerate=o,t.join=u,t.toSetString=a,t.fromSetString=f,t.relative=l}),define("source-map/array-set",["require","exports","module","source-map/util"],function(e,t,n){function i(){this._array=[],this._set={}}var r=e("./util");i.fromArray=function(t,n){var r=new i;for(var s=0,o=t.length;s<o;s++)r.add(t[s],n);return r},i.prototype.add=function(t,n){var i=this.has(t),s=this._array.length;(!i||n)&&this._array.push(t),i||(this._set[r.toSetString(t)]=s)},i.prototype.has=function(t){return Object.prototype.hasOwnProperty.call(this._set,r.toSetString(t))},i.prototype.indexOf=function(t){if(this.has(t))return this._set[r.toSetString(t)];throw new Error('"'+t+'" is not in the set.')},i.prototype.at=function(t){if(t>=0&&t<this._array.length)return this._array[t];throw new Error("No element indexed by "+t)},i.prototype.toArray=function(){return this._array.slice()},t.ArraySet=i}),define("source-map/source-map-consumer",["require","exports","module","source-map/util","source-map/binary-search","source-map/array-set","source-map/base64-vlq"],function(e,t,n){function u(e){var t=e;typeof e=="string"&&(t=JSON.parse(e.replace(/^\)\]\}'/,"")));var n=r.getArg(t,"version"),i=r.getArg(t,"sources"),o=r.getArg(t,"names"),u=r.getArg(t,"sourceRoot",null),a=r.getArg(t,"sourcesContent",null),f=r.getArg(t,"mappings"),l=r.getArg(t,"file",null);if(n!==this._version)throw new Error("Unsupported version: "+n);this._names=s.fromArray(o,!0),this._sources=s.fromArray(i,!0),this.sourceRoot=u,this.sourcesContent=a,this.file=l,this._generatedMappings=[],this._originalMappings=[],this._parseMappings(f,u)}var r=e("./util"),i=e("./binary-search"),s=e("./array-set").ArraySet,o=e("./base64-vlq");u.prototype._version=3,Object.defineProperty(u.prototype,"sources",{get:function(){return this._sources.toArray().map(function(e){return this.sourceRoot?r.join(this.sourceRoot,e):e},this)}}),u.prototype._parseMappings=function(t,n){var r=1,i=0,s=0,u=0,a=0,f=0,l=/^[,;]/,c=t,h,p;while(c.length>0)if(c.charAt(0)===";")r++,c=c.slice(1),i=0;else if(c.charAt(0)===",")c=c.slice(1);else{h={},h.generatedLine=r,p=o.decode(c),h.generatedColumn=i+p.value,i=h.generatedColumn,c=p.rest;if(c.length>0&&!l.test(c.charAt(0))){p=o.decode(c),h.source=this._sources.at(a+p.value),a+=p.value,c=p.rest;if(c.length===0||l.test(c.charAt(0)))throw new Error("Found a source, but no line and column");p=o.decode(c),h.originalLine=s+p.value,s=h.originalLine,h.originalLine+=1,c=p.rest;if(c.length===0||l.test(c.charAt(0)))throw new Error("Found a source and line, but no column");p=o.decode(c),h.originalColumn=u+p.value,u=h.originalColumn,c=p.rest,c.length>0&&!l.test(c.charAt(0))&&(p=o.decode(c),h.name=this._names.at(f+p.value),f+=p.value,c=p.rest)}this._generatedMappings.push(h),typeof h.originalLine=="number"&&this._originalMappings.push(h)}this._originalMappings.sort(this._compareOriginalPositions)},u.prototype._compareOriginalPositions=function(t,n){if(t.source>n.source)return 1;if(t.source<n.source)return-1;var r=t.originalLine-n.originalLine;return r===0?t.originalColumn-n.originalColumn:r},u.prototype._compareGeneratedPositions=function(t,n){var r=t.generatedLine-n.generatedLine;return r===0?t.generatedColumn-n.generatedColumn:r},u.prototype._findMapping=function(t,n,r,s,o){if(t[r]<=0)throw new TypeError("Line must be greater than or equal to 1, got "+t[r]);if(t[s]<0)throw new TypeError("Column must be greater than or equal to 0, got "+t[s]);return i.search(t,n,o)},u.prototype.originalPositionFor=function(t){var n={generatedLine:r.getArg(t,"line"),generatedColumn:r.getArg(t,"column")},i=this._findMapping(n,this._generatedMappings,"generatedLine","generatedColumn",this._compareGeneratedPositions);if(i){var s=r.getArg(i,"source",null);return s&&this.sourceRoot&&(s=r.join(this.sourceRoot,s)),{source:s,line:r.getArg(i,"originalLine",null),column:r.getArg(i,"originalColumn",null),name:r.getArg(i,"name",null)}}return{source:null,line:null,column:null,name:null}},u.prototype.sourceContentFor=function(t){if(!this.sourcesContent)return null;this.sourceRoot&&(t=r.relative(this.sourceRoot,t));if(this._sources.has(t))return this.sourcesContent[this._sources.indexOf(t)];var n;if(this.sourceRoot&&(n=r.urlParse(this.sourceRoot))){var i=t.replace(/^file:\/\//,"");if(n.scheme=="file"&&this._sources.has(i))return this.sourcesContent[this._sources.indexOf(i)];if((!n.path||n.path=="/")&&this._sources.has("/"+t))return this.sourcesContent[this._sources.indexOf("/"+t)]}throw new Error('"'+t+'" is not in the SourceMap.')},u.prototype.generatedPositionFor=function(t){var n={source:r.getArg(t,"source"),originalLine:r.getArg(t,"line"),originalColumn:r.getArg(t,"column")};this.sourceRoot&&(n.source=r.relative(this.sourceRoot,n.source));var i=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",this._compareOriginalPositions);return i?{line:r.getArg(i,"generatedLine",null),column:r.getArg(i,"generatedColumn",null)}:{line:null,column:null}},u.GENERATED_ORDER=1,u.ORIGINAL_ORDER=2,u.prototype.eachMapping=function(t,n,i){var s=n||null,o=i||u.GENERATED_ORDER,a;switch(o){case u.GENERATED_ORDER:a=this._generatedMappings;break;case u.ORIGINAL_ORDER:a=this._originalMappings;break;default:throw new Error("Unknown order of iteration.")}var f=this.sourceRoot;a.map(function(e){var t=e.source;return t&&f&&(t=r.join(f,t)),{source:t,generatedLine:e.generatedLine,generatedColumn:e.generatedColumn,originalLine:e.originalLine,originalColumn:e.originalColumn,name:e.name}}).forEach(t,s)},t.SourceMapConsumer=u}),define("source-map/binary-search",["require","exports","module"],function(e,t,n){function r(e,t,n,i,s){var o=Math.floor((t-e)/2)+e,u=s(n,i[o]);return u===0?i[o]:u>0?t-o>1?r(o,t,n,i,s):i[o]:o-e>1?r(e,o,n,i,s):e<0?null:i[e]}t.search=function(t,n,i){return n.length>0?r(-1,n.length,t,n,i):null}}),define("source-map/source-node",["require","exports","module","source-map/source-map-generator","source-map/util"],function(e,t,n){function s(e,t,n,r,i){this.children=[],this.sourceContents={},this.line=e===undefined?null:e,this.column=t===undefined?null:t,this.source=n===undefined?null:n,this.name=i===undefined?null:i,r!=null&&this.add(r)}var r=e("./source-map-generator").SourceMapGenerator,i=e("./util");s.fromStringWithSourceMap=function(t,n){function f(e,t){e===null||e.source===undefined?r.add(t):r.add(new s(e.originalLine,e.originalColumn,e.source,t,e.name))}var r=new s,i=t.split("\n"),o=1,u=0,a=null;return n.eachMapping(function(e){if(a===null){while(o<e.generatedLine)r.add(i.shift()+"\n"),o++;if(u<e.generatedColumn){var t=i[0];r.add(t.substr(0,e.generatedColumn)),i[0]=t.substr(e.generatedColumn),u=e.generatedColumn}}else if(o<e.generatedLine){var n="";do n+=i.shift()+"\n",o++,u=0;while(o<e.generatedLine);if(u<e.generatedColumn){var t=i[0];n+=t.substr(0,e.generatedColumn),i[0]=t.substr(e.generatedColumn),u=e.generatedColumn}f(a,n)}else{var t=i[0],n=t.substr(0,e.generatedColumn-u);i[0]=t.substr(e.generatedColumn-u),u=e.generatedColumn,f(a,n)}a=e},this),f(a,i.join("\n")),n.sources.forEach(function(e){var t=n.sourceContentFor(e);t&&r.setSourceContent(e,t)}),r},s.prototype.add=function(t){if(Array.isArray(t))t.forEach(function(e){this.add(e)},this);else{if(!(t instanceof s||typeof t=="string"))throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+t);t&&this.children.push(t)}return this},s.prototype.prepend=function(t){if(Array.isArray(t))for(var n=t.length-1;n>=0;n--)this.prepend(t[n]);else{if(!(t instanceof s||typeof t=="string"))throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+t);this.children.unshift(t)}return this},s.prototype.walk=function(t){this.children.forEach(function(e){e instanceof s?e.walk(t):e!==""&&t(e,{source:this.source,line:this.line,column:this.column,name:this.name})},this)},s.prototype.join=function(t){var n,r,i=this.children.length;if(i>0){n=[];for(r=0;r<i-1;r++)n.push(this.children[r]),n.push(t);n.push(this.children[r]),this.children=n}return this},s.prototype.replaceRight=function(t,n){var r=this.children[this.children.length-1];return r instanceof s?r.replaceRight(t,n):typeof r=="string"?this.children[this.children.length-1]=r.replace(t,n):this.children.push("".replace(t,n)),this},s.prototype.setSourceContent=function(t,n){this.sourceContents[i.toSetString(t)]=n},s.prototype.walkSourceContents=function(t){this.children.forEach(function(e){e instanceof s&&e.walkSourceContents(t)},this),Object.keys(this.sourceContents).forEach(function(e){t(i.fromSetString(e),this.sourceContents[e])},this)},s.prototype.toString=function(){var t="";return this.walk(function(e){t+=e}),t},s.prototype.toStringWithSourceMap=function(t){var n={code:"",line:1,column:0},i=new r(t),s=!1,o=null,u=null,a=null,f=null;return this.walk(function(e,t){n.code+=e,t.source!==null&&t.line!==null&&t.column!==null?((o!==t.source||u!==t.line||a!==t.column||f!==t.name)&&i.addMapping({source:t.source,original:{line:t.line,column:t.column},generated:{line:n.line,column:n.column},name:t.name}),o=t.source,u=t.line,a=t.column,f=t.name,s=!0):s&&(i.addMapping({generated:{line:n.line,column:n.column}}),o=null,s=!1),e.split("").forEach(function(e){e==="\n"?(n.line++,n.column=0):n.column++})}),this.walkSourceContents(function(e,t){i.setSourceContent(e,t)}),{code:n.code,map:i}},t.SourceNode=s}),window.sourceMap={SourceMapConsumer:require("source-map/source-map-consumer").SourceMapConsumer,SourceMapGenerator:require("source-map/source-map-generator").SourceMapGenerator,SourceNode:require("source-map/source-node").SourceNode}
2
+
3
+ var emscripten_sourcemap_xmlHttp = undefined;
4
+ function emscripten_sourceMapLoaded() {
5
+ if (emscripten_sourcemap_xmlHttp.readyState === 4) {
6
+ Module['removeRunDependency']('sourcemap');
7
+ if (emscripten_sourcemap_xmlHttp.status === 200) {
8
+ emscripten_source_map = new window.sourceMap.SourceMapConsumer(emscripten_sourcemap_xmlHttp.responseText);
9
+ console.log('Source map data loaded.');
10
+ } else {
11
+ console.warn('Source map data loading failed with status code ' + emscripten_sourcemap_xmlHttp.status + '.');
12
+ }
13
+ emscripten_sourcemap_xmlHttp = undefined;
14
+ }
15
+ }
16
+ function emscripten_loadSourceMap() {
17
+ var url = window.location.href+'.map';
18
+ console.log('Loading source map data from ' + url + '..');
19
+ Module['addRunDependency']('sourcemap');
20
+ emscripten_sourcemap_xmlHttp = new XMLHttpRequest();
21
+ emscripten_sourcemap_xmlHttp.onreadystatechange = emscripten_sourceMapLoaded;
22
+ emscripten_sourcemap_xmlHttp.open("GET", url, true);
23
+ emscripten_sourcemap_xmlHttp.send(null);
24
+ }
25
+
26
+ var Module;
27
+ if (Module['preRun'] instanceof Array) {
28
+ Module['preRun'].push(emscripten_loadSourceMap);
29
+ } else {
30
+ Module['preRun'] = [emscripten_loadSourceMap];
31
+ }
@@ -8835,6 +8835,193 @@ LibraryManager.library = {
8835
8835
  }
8836
8836
  },
8837
8837
 
8838
+ // Returns [parentFuncArguments, functionName, paramListName]
8839
+ _emscripten_traverse_stack: function(args) {
8840
+ if (!args || !args.callee || !args.callee.name) {
8841
+ return [null, '', ''];
8842
+ }
8843
+
8844
+ var funstr = args.callee.toString();
8845
+ var funcname = args.callee.name;
8846
+ var str = '(';
8847
+ var first = true;
8848
+ for(i in args) {
8849
+ var a = args[i];
8850
+ if (!first) {
8851
+ str += ", ";
8852
+ }
8853
+ first = false;
8854
+ if (typeof a === 'number' || typeof a === 'string') {
8855
+ str += a;
8856
+ } else {
8857
+ str += '(' + typeof a + ')';
8858
+ }
8859
+ }
8860
+ str += ')';
8861
+ args = args.callee.caller.arguments;
8862
+ if (first)
8863
+ str = '';
8864
+ return [args, funcname, str];
8865
+ },
8866
+
8867
+ emscripten_get_callstack_js__deps: ['_emscripten_traverse_stack'],
8868
+ emscripten_get_callstack_js: function(flags) {
8869
+ var err = new Error();
8870
+ if (!err.stack) {
8871
+ Runtime.warnOnce('emscripten_get_callstack_js is not supported on this browser!');
8872
+ return '';
8873
+ }
8874
+ var callstack = new Error().stack.toString();
8875
+
8876
+ // Find the symbols in the callstack that corresponds to the functions that report callstack information, and remove everyhing up to these from the output.
8877
+ var iThisFunc = callstack.lastIndexOf('_emscripten_log');
8878
+ var iThisFunc2 = callstack.lastIndexOf('_emscripten_get_callstack');
8879
+ var iNextLine = callstack.indexOf('\n', Math.max(iThisFunc, iThisFunc2))+1;
8880
+ callstack = callstack.slice(iNextLine);
8881
+
8882
+ // If user requested to see the original source stack, but no source map information is available, just fall back to showing the JS stack.
8883
+ if (flags & 8/*EM_LOG_C_STACK*/ && typeof emscripten_source_map === 'undefined') {
8884
+ Runtime.warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.');
8885
+ flags ^= 8/*EM_LOG_C_STACK*/;
8886
+ flags |= 16/*EM_LOG_JS_STACK*/;
8887
+ }
8888
+
8889
+ var stack_args = null;
8890
+ if (flags & 128 /*EM_LOG_FUNC_PARAMS*/) {
8891
+ // To get the actual parameters to the functions, traverse the stack via the unfortunately deprecated 'arguments.callee' method, if it works:
8892
+ var stack_args = __emscripten_traverse_stack(arguments);
8893
+ while (stack_args[1].indexOf('_emscripten_') >= 0)
8894
+ stack_args = __emscripten_traverse_stack(stack_args[0]);
8895
+ }
8896
+
8897
+ // Process all lines:
8898
+ lines = callstack.split('\n');
8899
+ callstack = '';
8900
+ var firefoxRe = new RegExp('\\s*(.*?)@(.*):(.*)'); // Extract components of form ' Object._main@http://server.com:4324'
8901
+ var chromeRe = new RegExp('\\s*at (.*?) \\\((.*):(.*):(.*)\\\)'); // Extract components of form ' at Object._main (http://server.com/file.html:4324:12)'
8902
+
8903
+ for(l in lines) {
8904
+ var line = lines[l];
8905
+
8906
+ var jsSymbolName = '';
8907
+ var file = '';
8908
+ var lineno = 0;
8909
+ var column = 0;
8910
+
8911
+ var parts = chromeRe.exec(line);
8912
+ if (parts && parts.length == 5) {
8913
+ jsSymbolName = parts[1];
8914
+ file = parts[2];
8915
+ lineno = parts[3];
8916
+ column = parts[4];
8917
+ } else {
8918
+ parts = firefoxRe.exec(line);
8919
+ if (parts && parts.length == 4) {
8920
+ jsSymbolName = parts[1];
8921
+ file = parts[2];
8922
+ lineno = parts[3];
8923
+ column = 0; // Firefox doesn't carry column information. See https://bugzilla.mozilla.org/show_bug.cgi?id=762556
8924
+ } else {
8925
+ // Was not able to extract this line for demangling/sourcemapping purposes. Output it as-is.
8926
+ callstack += line + '\n';
8927
+ continue;
8928
+ }
8929
+ }
8930
+
8931
+ // Try to demangle the symbol, but fall back to showing the original JS symbol name if not available.
8932
+ var cSymbolName = (flags & 32/*EM_LOG_DEMANGLE*/) ? demangle(jsSymbolName) : jsSymbolName;
8933
+ if (!cSymbolName) {
8934
+ cSymbolName = jsSymbolName;
8935
+ }
8936
+
8937
+ var haveSourceMap = false;
8938
+
8939
+ if (flags & 8/*EM_LOG_C_STACK*/) {
8940
+ var orig = emscripten_source_map.originalPositionFor({line: lineno, column: column});
8941
+ haveSourceMap = (orig && orig.source);
8942
+ if (haveSourceMap) {
8943
+ if (flags & 64/*EM_LOG_NO_PATHS*/) {
8944
+ orig.source = orig.source.substring(orig.source.replace(/\\/g, "/").lastIndexOf('/')+1);
8945
+ }
8946
+ callstack += ' at ' + cSymbolName + ' (' + orig.source + ':' + orig.line + ':' + orig.column + ')\n';
8947
+ }
8948
+ }
8949
+ if ((flags & 16/*EM_LOG_JS_STACK*/) || !haveSourceMap) {
8950
+ if (flags & 64/*EM_LOG_NO_PATHS*/) {
8951
+ file = file.substring(file.replace(/\\/g, "/").lastIndexOf('/')+1);
8952
+ }
8953
+ callstack += (haveSourceMap ? (' = '+jsSymbolName) : (' at '+cSymbolName)) + ' (' + file + ':' + lineno + ':' + column + ')\n';
8954
+ }
8955
+
8956
+ // If we are still keeping track with the callstack by traversing via 'arguments.callee', print the function parameters as well.
8957
+ if (flags & 128 /*EM_LOG_FUNC_PARAMS*/ && stack_args[0]) {
8958
+ if (stack_args[1] == jsSymbolName && stack_args[2].length > 0) {
8959
+ callstack = callstack.replace(/\s+$/, '');
8960
+ callstack += ' with values: ' + stack_args[1] + stack_args[2] + '\n';
8961
+ }
8962
+ stack_args = __emscripten_traverse_stack(stack_args[0]);
8963
+ }
8964
+ }
8965
+ // Trim extra whitespace at the end of the output.
8966
+ callstack = callstack.replace(/\s+$/, '');
8967
+ return callstack;
8968
+ },
8969
+
8970
+ emscripten_get_callstack__deps: ['emscripten_get_callstack_js'],
8971
+ emscripten_get_callstack: function(flags, str, maxbytes) {
8972
+ var callstack = _emscripten_get_callstack_js(flags);
8973
+ // User can query the required amount of bytes to hold the callstack.
8974
+ if (!str || maxbytes <= 0) {
8975
+ return callstack.length+1;
8976
+ }
8977
+ // Truncate output to avoid writing past bounds.
8978
+ if (callstack.length > maxbytes-1) {
8979
+ callstack.slice(0, maxbytes-1);
8980
+ }
8981
+ // Output callstack string as C string to HEAP.
8982
+ writeStringToMemory(callstack, str, false);
8983
+
8984
+ // Return number of bytes written.
8985
+ return callstack.length+1;
8986
+ },
8987
+
8988
+ emscripten_log_js__deps: ['emscripten_get_callstack_js'],
8989
+ emscripten_log_js: function(flags, str) {
8990
+ if (flags & 24/*EM_LOG_C_STACK | EM_LOG_JS_STACK*/) {
8991
+ str = str.replace(/\s+$/, ''); // Ensure the message and the callstack are joined cleanly with exactly one newline.
8992
+ str += (str.length > 0 ? '\n' : '') + _emscripten_get_callstack_js(flags);
8993
+ }
8994
+
8995
+ if (flags & 1 /*EM_LOG_CONSOLE*/) {
8996
+ if (flags & 4 /*EM_LOG_ERROR*/) {
8997
+ console.error(str);
8998
+ } else if (flags & 2 /*EM_LOG_WARN*/) {
8999
+ console.warn(str);
9000
+ } else {
9001
+ console.log(str);
9002
+ }
9003
+ } else if (flags & 6 /*EM_LOG_ERROR|EM_LOG_WARN*/) {
9004
+ Module.printErr(str);
9005
+ } else {
9006
+ Module.print(str);
9007
+ }
9008
+ },
9009
+
9010
+ emscripten_log__deps: ['_formatString', 'emscripten_log_js'],
9011
+ emscripten_log: function(flags, varargs) {
9012
+ // Extract the (optionally-existing) printf format specifier field from varargs.
9013
+ var format = {{{ makeGetValue('varargs', '0', 'i32', undefined, undefined, true) }}};
9014
+ varargs += Math.max(Runtime.getNativeFieldSize('i32'), Runtime.getAlignSize('i32', null, true));
9015
+ var str = '';
9016
+ if (format) {
9017
+ var result = __formatString(format, varargs);
9018
+ for(var i = 0 ; i < result.length; ++i) {
9019
+ str += String.fromCharCode(result[i]);
9020
+ }
9021
+ }
9022
+ _emscripten_log_js(flags, str);
9023
+ },
9024
+
8838
9025
  //============================
8839
9026
  // emscripten vector ops
8840
9027
  //============================
@@ -264,6 +264,26 @@ var LibraryEGL = {
264
264
  return 0;
265
265
  }
266
266
 
267
+ // EGL 1.4 spec says default EGL_CONTEXT_CLIENT_VERSION is GLES1, but this is not supported by Emscripten.
268
+ // So user must pass EGL_CONTEXT_CLIENT_VERSION == 2 to initialize EGL.
269
+ var glesContextVersion = 1;
270
+ for(;;) {
271
+ var param = {{{ makeGetValue('contextAttribs', '0', 'i32') }}};
272
+ if (!param) break;
273
+ var value = {{{ makeGetValue('contextAttribs', '4', 'i32') }}};
274
+ if (param == 0x3098 /*EGL_CONTEXT_CLIENT_VERSION*/) {
275
+ glesContextVersion = value;
276
+ }
277
+ contextAttribs += 8;
278
+ }
279
+ if (glesContextVersion != 2) {
280
+ #if GL_ASSERTIONS
281
+ Module.printErr('When initializing GLES2/WebGL1 via EGL, one must pass EGL_CONTEXT_CLIENT_VERSION = 2 to GL context attributes! GLES version ' + glesContextVersion + ' is not supported!');
282
+ #endif
283
+ EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */);
284
+ return 0; /* EGL_NO_CONTEXT */
285
+ }
286
+
267
287
  _glutInitDisplayMode(0x92 /* GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE */);
268
288
  EGL.windowID = _glutCreateWindow();
269
289
  if (EGL.windowID != 0) {
@@ -1220,6 +1220,7 @@ var LibrarySDL = {
1220
1220
  if (surf) SDL.freeSurface(surf);
1221
1221
  },
1222
1222
 
1223
+ SDL_UpperBlit__deps: ['SDL_LockSurface'],
1223
1224
  SDL_UpperBlit: function(src, srcrect, dst, dstrect) {
1224
1225
  var srcData = SDL.surfaces[src];
1225
1226
  var dstData = SDL.surfaces[dst];
@@ -642,6 +642,10 @@ Module['stringToUTF32'] = stringToUTF32;
642
642
 
643
643
  function demangle(func) {
644
644
  try {
645
+ // Special-case the entry point, since its name differs from other name mangling.
646
+ if (func == 'Object._main' || func == '_main') {
647
+ return 'main()';
648
+ }
645
649
  if (typeof func === 'number') func = Pointer_stringify(func);
646
650
  if (func[0] !== '_') return func;
647
651
  if (func[1] !== '_') return func; // C function
@@ -101,9 +101,7 @@ void Branch::Render(Block *Target, bool SetLabel) {
101
101
 
102
102
  // Block
103
103
 
104
- int Block::IdCounter = 1; // 0 is reserved for clearings
105
-
106
- Block::Block(const char *CodeInit, const char *BranchVarInit) : Parent(NULL), Id(Block::IdCounter++), IsCheckedMultipleEntry(false) {
104
+ Block::Block(const char *CodeInit, const char *BranchVarInit) : Parent(NULL), Id(-1), IsCheckedMultipleEntry(false) {
107
105
  Code = strdup(CodeInit);
108
106
  BranchVar = BranchVarInit ? strdup(BranchVarInit) : NULL;
109
107
  }
@@ -142,6 +140,7 @@ void Block::Render(bool InLoop) {
142
140
  if (!ProcessedBranchesOut.size()) return;
143
141
 
144
142
  bool SetLabel = true; // in some cases it is clear we can avoid setting label, see later
143
+ bool ForceSetLabel = Shape::IsEmulated(Parent);
145
144
 
146
145
  // A setting of the label variable (label = x) is necessary if it can
147
146
  // cause an impact. The main case is where we set label to x, then elsewhere
@@ -210,7 +209,7 @@ void Block::Render(bool InLoop) {
210
209
  Target = DefaultTarget;
211
210
  Details = ProcessedBranchesOut[DefaultTarget];
212
211
  }
213
- bool SetCurrLabel = SetLabel && Target->IsCheckedMultipleEntry;
212
+ bool SetCurrLabel = (SetLabel && Target->IsCheckedMultipleEntry) || ForceSetLabel;
214
213
  bool HasFusedContent = Fused && contains(Fused->InnerMap, Target);
215
214
  bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code;
216
215
  if (iter != ProcessedBranchesOut.end()) {
@@ -272,10 +271,6 @@ void Block::Render(bool InLoop) {
272
271
  }
273
272
  }
274
273
 
275
- // Shape
276
-
277
- int Shape::IdCounter = 0;
278
-
279
274
  // MultipleShape
280
275
 
281
276
  void MultipleShape::RenderLoopPrefix() {
@@ -330,16 +325,19 @@ void LoopShape::Render(bool InLoop) {
330
325
  if (Next) Next->Render(InLoop);
331
326
  };
332
327
 
333
- /*
334
328
  // EmulatedShape
335
329
 
336
330
  void EmulatedShape::Render(bool InLoop) {
331
+ PrintIndented("label = %d;\n", Entry->Id);
332
+ if (Labeled) {
333
+ PrintIndented("L%d: ", Id);
334
+ }
337
335
  PrintIndented("while(1) {\n");
338
336
  Indenter::Indent();
339
- PrintIndented("switch(label) {\n");
337
+ PrintIndented("switch(label|0) {\n");
340
338
  Indenter::Indent();
341
- for (int i = 0; i < Blocks.size(); i++) {
342
- Block *Curr = Blocks[i];
339
+ for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) {
340
+ Block *Curr = *iter;
343
341
  PrintIndented("case %d: {\n", Curr->Id);
344
342
  Indenter::Indent();
345
343
  Curr->Render(InLoop);
@@ -353,11 +351,10 @@ void EmulatedShape::Render(bool InLoop) {
353
351
  PrintIndented("}\n");
354
352
  if (Next) Next->Render(InLoop);
355
353
  };
356
- */
357
354
 
358
355
  // Relooper
359
356
 
360
- Relooper::Relooper() : Root(NULL) {
357
+ Relooper::Relooper() : Root(NULL), Emulate(false), BlockIdCounter(1), ShapeIdCounter(0) { // block ID 0 is reserved for clearings
361
358
  }
362
359
 
363
360
  Relooper::~Relooper() {
@@ -366,6 +363,7 @@ Relooper::~Relooper() {
366
363
  }
367
364
 
368
365
  void Relooper::AddBlock(Block *New) {
366
+ New->Id = BlockIdCounter++;
369
367
  Blocks.push_back(New);
370
368
  }
371
369
 
@@ -461,7 +459,7 @@ void Relooper::Calculate(Block *Entry) {
461
459
  }
462
460
  }
463
461
 
464
- Pre.SplitDeadEnds();
462
+ if (!Emulate) Pre.SplitDeadEnds();
465
463
 
466
464
  // Recursively process the graph
467
465
 
@@ -470,6 +468,7 @@ void Relooper::Calculate(Block *Entry) {
470
468
 
471
469
  // Add a shape to the list of shapes in this Relooper calculation
472
470
  void Notice(Shape *New) {
471
+ New->Id = Parent->ShapeIdCounter++;
473
472
  Parent->Shapes.push_back(New);
474
473
  }
475
474
 
@@ -526,6 +525,21 @@ void Relooper::Calculate(Block *Entry) {
526
525
  return Simple;
527
526
  }
528
527
 
528
+ Shape *MakeEmulated(BlockSet &Blocks, Block *Entry, BlockSet &NextEntries) {
529
+ PrintDebug("creating emulated block with entry #%d and everything it can reach, %d blocks\n", Entry->Id, Blocks.size());
530
+ EmulatedShape *Emulated = new EmulatedShape;
531
+ Notice(Emulated);
532
+ Emulated->Entry = Entry;
533
+ for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) {
534
+ Block *Curr = *iter;
535
+ Emulated->Blocks.insert(Curr);
536
+ Curr->Parent = Emulated;
537
+ Solipsize(Curr, Branch::Continue, Emulated, Blocks);
538
+ }
539
+ Blocks.clear();
540
+ return Emulated;
541
+ }
542
+
529
543
  Shape *MakeLoop(BlockSet &Blocks, BlockSet& Entries, BlockSet &NextEntries) {
530
544
  // Find the inner blocks in this loop. Proceed backwards from the entries until
531
545
  // you reach a seen block, collecting as you go.
@@ -837,6 +851,9 @@ void Relooper::Calculate(Block *Entry) {
837
851
  if (Entries->size() == 0) return Ret;
838
852
  if (Entries->size() == 1) {
839
853
  Block *Curr = *(Entries->begin());
854
+ if (Parent->Emulate) {
855
+ Make(MakeEmulated(Blocks, Curr, *NextEntries));
856
+ }
840
857
  if (Curr->BranchesIn.size() == 0) {
841
858
  // One entry, no looping ==> Simple
842
859
  Make(MakeSimple(Blocks, Curr, *NextEntries));
@@ -844,6 +861,7 @@ void Relooper::Calculate(Block *Entry) {
844
861
  // One entry, looping ==> Loop
845
862
  Make(MakeLoop(Blocks, *Entries, *NextEntries));
846
863
  }
864
+
847
865
  // More than one entry, try to eliminate through a Multiple groups of
848
866
  // independent blocks from an entry/ies. It is important to remove through
849
867
  // multiples as opposed to looping since the former is more performant.