webruby 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
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.