WebAssembly / binaryen

Optimizer and compiler/toolchain library for WebAssembly
Apache License 2.0
7.5k stars 746 forks source link

asm2wasm crash #1335

Open vajraBodhi opened 6 years ago

vajraBodhi commented 6 years ago

I got the error message when I used asm2wasm command.

D:\demos\wasm\baidu>asm2wasm a.out.js -o a.wast
Assertion failed: parts.size() == 1, file d:\emsdk-portable\binaryen\master\src\
emscripten-optimizer\parser.h, line 830

The code of a.out.js as follows:

// Capture the output of this into a variable, if you want
(function(fb, parentModule) {
  var Module = {};
  var args = [];
  Module.arguments = [];
  Module.print = parentModule.print;
  Module.printErr = parentModule.printErr;

  Module.cleanups = [];

  var gb = 0;
  // Each module has its own stack
  var STACKTOP = getMemory(TOTAL_STACK);
  assert(STACKTOP % 8 == 0);
  var STACK_MAX = STACKTOP + TOTAL_STACK;
  Module.cleanups.push(function() {
    parentModule['_free'](STACKTOP); // XXX ensure exported
    parentModule['_free'](gb);
  });

// === Auto-generated preamble library stuff ===

//========================================
// Runtime essentials
//========================================

// === Body ===

var ASM_CONSTS = [];

gb = Runtime.alignMemory(getMemory(16400, 4 || 1));

// STATICTOP = STATIC_BASE + 16400;
/* global initializers */  __ATINIT__.push();

/* memory initializer */ allocate([], "i8", ALLOC_NONE, gb);

/* no memory initializer */
// {{PRE_LIBRARY}}

var ASSERTIONS = true;

// All functions here should be maybeExported from jsifier.js

/** @type {function(string, boolean=, number=)} */
function intArrayFromString(stringy, dontAddNull, length) {
  var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;
  var u8array = new Array(len);
  var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
  if (dontAddNull) u8array.length = numBytesWritten;
  return u8array;
}

function intArrayToString(array) {
  var ret = [];
  for (var i = 0; i < array.length; i++) {
    var chr = array[i];
    if (chr > 0xFF) {
      if (ASSERTIONS) {
        assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ')  at offset ' + i + ' not in 0x00-0xFF.');
      }
      chr &= 0xFF;
    }
    ret.push(String.fromCharCode(chr));
  }
  return ret.join('');
}

Module["intArrayFromString"] = intArrayFromString;
Module["intArrayToString"] = intArrayToString;
var setTempRet0 = Runtime.setTempRet0, getTempRet0 = Runtime.getTempRet0;

Module.asmGlobalArg = { "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array, "NaN": NaN, "Infinity": Infinity };

Module.asmLibraryArg = { "abort": abort, "assert": assert, "enlargeMemory": enlargeMemory, "getTotalMemory": getTotalMemory, "abortOnCannotGrowMemory": abortOnCannotGrowMemory, "abortStackOverflow": abortStackOverflow, "setTempRet0": setTempRet0, "getTempRet0": getTempRet0, "DYNAMICTOP_PTR": DYNAMICTOP_PTR, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "gb": gb, "fb": fb };
// EMSCRIPTEN_START_ASM
var asm = (/** @suppress {uselessCode} */ function(global, env, buffer) {
'almost asm';

  var HEAP8 = new global.Int8Array(buffer);
  var HEAP16 = new global.Int16Array(buffer);
  var HEAP32 = new global.Int32Array(buffer);
  var HEAPU8 = new global.Uint8Array(buffer);
  var HEAPU16 = new global.Uint16Array(buffer);
  var HEAPU32 = new global.Uint32Array(buffer);
  var HEAPF32 = new global.Float32Array(buffer);
  var HEAPF64 = new global.Float64Array(buffer);

  var DYNAMICTOP_PTR=env.DYNAMICTOP_PTR|0;
  var tempDoublePtr=env.tempDoublePtr|0;
  var ABORT=env.ABORT|0;
  var STACKTOP=env.STACKTOP|0;
  var STACK_MAX=env.STACK_MAX|0;
  var gb=env.gb|0;
  var fb=env.fb|0;

  var __THREW__ = 0;
  var threwValue = 0;
  var setjmpId = 0;
  var undef = 0;
  var nan = global.NaN, inf = global.Infinity;
  var tempInt = 0, tempBigInt = 0, tempBigIntS = 0, tempValue = 0, tempDouble = 0.0;
  var tempRet0 = 0;

  var Math_floor=global.Math.floor;
  var Math_abs=global.Math.abs;
  var Math_sqrt=global.Math.sqrt;
  var Math_pow=global.Math.pow;
  var Math_cos=global.Math.cos;
  var Math_sin=global.Math.sin;
  var Math_tan=global.Math.tan;
  var Math_acos=global.Math.acos;
  var Math_asin=global.Math.asin;
  var Math_atan=global.Math.atan;
  var Math_atan2=global.Math.atan2;
  var Math_exp=global.Math.exp;
  var Math_log=global.Math.log;
  var Math_ceil=global.Math.ceil;
  var Math_imul=global.Math.imul;
  var Math_min=global.Math.min;
  var Math_max=global.Math.max;
  var Math_clz32=global.Math.clz32;
  var abort=env.abort;
  var assert=env.assert;
  var enlargeMemory=env.enlargeMemory;
  var getTotalMemory=env.getTotalMemory;
  var abortOnCannotGrowMemory=env.abortOnCannotGrowMemory;
  var abortStackOverflow=env.abortStackOverflow;
  var setTempRet0=env.setTempRet0;
  var getTempRet0=env.getTempRet0;
  var tempFloat = 0.0;

// EMSCRIPTEN_START_FUNCS

function stackAlloc(size) {
  size = size|0;
  var ret = 0;
  ret = STACKTOP;
  STACKTOP = (STACKTOP + size)|0;
  STACKTOP = (STACKTOP + 15)&-16;
  if ((STACKTOP|0) >= (STACK_MAX|0)) abortStackOverflow(size|0);

  return ret|0;
}
function stackSave() {
  return STACKTOP|0;
}
function stackRestore(top) {
  top = top|0;
  STACKTOP = top;
}
function establishStackSpace(stackBase, stackMax) {
  stackBase = stackBase|0;
  stackMax = stackMax|0;
  STACKTOP = stackBase;
  STACK_MAX = stackMax;
}

function setThrew(threw, value) {
  threw = threw|0;
  value = value|0;
  if ((__THREW__|0) == 0) {
    __THREW__ = threw;
    threwValue = value;
  }
}

function _get_start() {
 var label = 0, sp = 0;
 sp = STACKTOP;
 return ((gb + (0) | 0)|0);
}
function _get_end() {
 var $0 = 0, $1 = 0, label = 0, sp = 0;
 sp = STACKTOP;
 $0 = HEAP32[(gb + (16384) | 0)>>2]|0;
 $1 = ((gb + (0) | 0) + ($0<<2)|0);
 return ($1|0);
}
function _generate_array($0) {
 $0 = $0|0;
 var $1 = 0, $10 = 0, $11 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, label = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 16|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abortStackOverflow(16|0);
 $1 = $0;
 $2 = 0;
 while(1) {
  $3 = $2;
  $4 = $1;
  $5 = ($3|0)<($4|0);
  if (!($5)) {
   break;
  }
  $6 = $2;
  $7 = $2;
  $8 = ((gb + (0) | 0) + ($7<<2)|0);
  HEAP32[$8>>2] = $6;
  $9 = $2;
  $10 = (($9) + 1)|0;
  $2 = $10;
 }
 $11 = $1;
 HEAP32[(gb + (16384) | 0)>>2] = $11;
 STACKTOP = sp;return;
}
function runPostSets() {
 var temp = 0;
}

// EMSCRIPTEN_END_FUNCS

  return { runPostSets: runPostSets, establishStackSpace: establishStackSpace, stackSave: stackSave, stackRestore: stackRestore, _get_end: _get_end, setThrew: setThrew, stackAlloc: stackAlloc, _generate_array: _generate_array, _get_start: _get_start };
})
// EMSCRIPTEN_END_ASM
(Module.asmGlobalArg, Module.asmLibraryArg, buffer);

var real_setThrew = asm["setThrew"]; asm["setThrew"] = function() {
  assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
  assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  return real_setThrew.apply(null, arguments);
};

var real__generate_array = asm["_generate_array"]; asm["_generate_array"] = function() {
  assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
  assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  return real__generate_array.apply(null, arguments);
};

var real__get_start = asm["_get_start"]; asm["_get_start"] = function() {
  assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
  assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  return real__get_start.apply(null, arguments);
};

var real__get_end = asm["_get_end"]; asm["_get_end"] = function() {
  assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
  assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  return real__get_end.apply(null, arguments);
};
var setThrew = Module["setThrew"] = asm["setThrew"];
var _generate_array = Module["_generate_array"] = asm["_generate_array"];
var runPostSets = Module["runPostSets"] = asm["runPostSets"];
var _get_start = Module["_get_start"] = asm["_get_start"];
var _get_end = Module["_get_end"] = asm["_get_end"];

var NAMED_GLOBALS = {  };
for (var named in NAMED_GLOBALS) {
  Module['_' + named] = gb + NAMED_GLOBALS[named];
}
Module['NAMED_GLOBALS'] = NAMED_GLOBALS;
;

Runtime.registerFunctions([], Module);

// === Auto-generated postamble setup entry stuff ===

__ATPRERUN__.push(runPostSets);

if (runtimeInitialized) {
  // dlopen case: we are being loaded after the system is fully initialized, so just run our prerun and atinit stuff now
  callRuntimeCallbacks(__ATPRERUN__);
  callRuntimeCallbacks(__ATINIT__);
} // otherwise, general dynamic linking case: stuff we added to prerun and init will be executed with the rest of the system as it loads

  // {{MODULE_ADDITIONS}}

  return Module;
});

The a.out.js come from the c code:

// 分配内存,此数组占0x1000*4=16384byte
static int s_array[0x1000];
static int s_current_index = 0;
int* get_start();
int* get_end();
void generate_array(int);
// 暴露给JS使用,得到数组的开始偏移量
int* get_start() { 
    return s_array;
}
// 暴露给JS使用,得到数组的结束偏移量
int* get_end() { 
    return &s_array[s_current_index];
}
// 将生成的数组放进内存中
void generate_array(int count) { 
    for (int i = 0; i < count; ++i) {
        s_array[i] = i;
    }
    s_current_index = count;
}
kripken commented 6 years ago

asm2wasm is built to run on asm.js code, not on regular JS code.

The code here looks like an emscripten shared module? If you build with -s WASM=1 then it should run asm2wasm on the asm.js part of the output for you. (Or if you want to do it manually, you need to split out the asm.js code, you can see in emcc.py how it does it, I think it calls a tool called tools/separate_asm.py)

vajraBodhi commented 6 years ago

@kripken Yes, I want to do it manualy, I will try the method you provided. Thank you.