diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 71 | ||||
-rw-r--r-- | src/binaryen-c.h | 20 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 64 |
3 files changed, 130 insertions, 25 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 63ce7ee6c..c2ba7fa6b 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -2100,19 +2100,43 @@ void BinaryenModuleAutoDrop(BinaryenModuleRef module) { passRunner.run(); } -size_t BinaryenModuleWrite(BinaryenModuleRef module, char* output, size_t outputSize) { - if (tracing) { - std::cout << " // BinaryenModuleWrite\n"; - } - +static BinaryenBufferSizes writeModule(BinaryenModuleRef module, char* output, size_t outputSize, const char* sourceMapUrl, char* sourceMap, size_t sourceMapSize) { Module* wasm = (Module*)module; BufferWithRandomAccess buffer(false); WasmBinaryWriter writer(wasm, buffer, false); writer.setNamesSection(globalPassOptions.debugInfo); + std::ostringstream os; + if (sourceMapUrl) { + writer.setSourceMap(&os, sourceMapUrl); + } writer.write(); size_t bytes = std::min(buffer.size(), outputSize); std::copy_n(buffer.begin(), bytes, output); - return bytes; + size_t sourceMapBytes = 0; + if (sourceMapUrl) { + auto str = os.str(); + sourceMapBytes = std::min(str.length(), sourceMapSize); + std::copy_n(str.c_str(), sourceMapBytes, sourceMap); + } + return { bytes, sourceMapBytes }; +} + +size_t BinaryenModuleWrite(BinaryenModuleRef module, char* output, size_t outputSize) { + if (tracing) { + std::cout << " // BinaryenModuleWrite\n"; + } + + return writeModule((Module*)module, output, outputSize, nullptr, nullptr, 0).outputBytes; +} + +BinaryenBufferSizes BinaryenModuleWriteWithSourceMap(BinaryenModuleRef module, const char* url, char* output, size_t outputSize, char* sourceMap, size_t sourceMapSize) { + if (tracing) { + std::cout << " // BinaryenModuleWriteWithSourceMap\n"; + } + + assert(url); + assert(sourceMap); + return writeModule((Module*)module, output, outputSize, url, sourceMap, sourceMapSize); } BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize) { @@ -2144,6 +2168,26 @@ void BinaryenModuleInterpret(BinaryenModuleRef module) { ModuleInstance instance(*wasm, &interface); } +BinaryenIndex BinaryenModuleAddDebugInfoFileName(BinaryenModuleRef module, const char* filename) { + if (tracing) { + std::cout << " BinaryenModuleAddDebugInfoFileName(the_module, \"" << filename << "\");\n"; + } + + Module* wasm = (Module*)module; + BinaryenIndex index = wasm->debugInfoFileNames.size(); + wasm->debugInfoFileNames.push_back(filename); + return index; +} + +const char* BinaryenModuleGetDebugInfoFileName(BinaryenModuleRef module, BinaryenIndex index) { + if (tracing) { + std::cout << " BinaryenModuleGetDebugInfoFileName(the_module, \"" << index << "\");\n"; + } + + Module* wasm = (Module*)module; + return index < wasm->debugInfoFileNames.size() ? wasm->debugInfoFileNames.at(index).c_str() : nullptr; +} + // // ======== FunctionType Operations ======== // @@ -2275,6 +2319,21 @@ void BinaryenFunctionRunPasses(BinaryenFunctionRef func, BinaryenModuleRef modul } passRunner.runOnFunction((Function*)func); } +void BinaryenFunctionSetDebugLocation(BinaryenFunctionRef func, BinaryenExpressionRef expr, BinaryenIndex fileIndex, BinaryenIndex lineNumber, BinaryenIndex columnNumber) { + if (tracing) { + std::cout << " BinaryenFunctionSetDebugLocation(functions[" << functions[func] << "], expressions[" << expressions[expr] << "], " << fileIndex << ", " << lineNumber << ", " << columnNumber << ");\n"; + } + + auto* fn = (Function*)func; + auto* ex = (Expression*)expr; + + Function::DebugLocation loc; + loc.fileIndex = fileIndex; + loc.lineNumber = lineNumber; + loc.columnNumber = columnNumber; + + fn->debugLocations[ex] = loc; +} // // =========== Import operations =========== diff --git a/src/binaryen-c.h b/src/binaryen-c.h index b91689c3f..9033a6950 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -697,6 +697,16 @@ void BinaryenModuleAutoDrop(BinaryenModuleRef module); // @return how many bytes were written. This will be less than or equal to outputSize size_t BinaryenModuleWrite(BinaryenModuleRef module, char* output, size_t outputSize); +typedef struct BinaryenBufferSizes { + size_t outputBytes; + size_t sourceMapBytes; +} BinaryenBufferSizes; + +// Serialize a module into binary form including its source map. Uses the currently set +// global debugInfo option. +// @returns how many bytes were written. This will be less than or equal to outputSize +BinaryenBufferSizes BinaryenModuleWriteWithSourceMap(BinaryenModuleRef module, const char* url, char* output, size_t outputSize, char* sourceMap, size_t sourceMapSize); + // Deserialize a module from binary form. BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize); @@ -705,6 +715,13 @@ BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize); // and then destroying the instance. void BinaryenModuleInterpret(BinaryenModuleRef module); +// Adds a debug info file name to the module and returns its index. +BinaryenIndex BinaryenModuleAddDebugInfoFileName(BinaryenModuleRef module, const char* filename); + +// Gets the name of the debug info file at the specified index. Returns `NULL` if it +// does not exist. +const char* BinaryenModuleGetDebugInfoFileName(BinaryenModuleRef module, BinaryenIndex index); + // // ======== FunctionType Operations ======== // @@ -747,6 +764,9 @@ void BinaryenFunctionOptimize(BinaryenFunctionRef func, BinaryenModuleRef module // optimize and shrink level. void BinaryenFunctionRunPasses(BinaryenFunctionRef func, BinaryenModuleRef module, const char **passes, BinaryenIndex numPasses); +// Sets the debug location of the specified `Expression` within the specified `Function`. +void BinaryenFunctionSetDebugLocation(BinaryenFunctionRef func, BinaryenExpressionRef expr, BinaryenIndex fileIndex, BinaryenIndex lineNumber, BinaryenIndex columnNumber); + // // ========== Import Operations ========== // diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 580e9fc4d..5f1ef84fb 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -286,8 +286,8 @@ Module['Module'] = function(module) { // need to make their own Literals, as the C API handles them by value, // which means we would leak them. Instead, this is the only API that // accepts Literals, so fuse it with Literal creation - var literal = _malloc(16); // a single literal in memory. the LLVM C ABI - // makes us pass pointers to this. + var temp = _malloc(16); // a single literal in memory. the LLVM C ABI + // makes us pass pointers to this. this['i32'] = { 'load': function(offset, align, ptr) { @@ -315,8 +315,8 @@ Module['Module'] = function(module) { return Module['_BinaryenStore'](module, 2, offset, align, ptr, value, Module['i32']); }, 'const': function(x) { - Module['_BinaryenLiteralInt32'](literal, x); - return Module['_BinaryenConst'](module, literal); + Module['_BinaryenLiteralInt32'](temp, x); + return Module['_BinaryenConst'](module, temp); }, 'clz': function(value) { return Module['_BinaryenUnary'](module, Module['ClzInt32'], value); @@ -556,8 +556,8 @@ Module['Module'] = function(module) { return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['i64']); }, 'const': function(x, y) { - Module['_BinaryenLiteralInt64'](literal, x, y); - return Module['_BinaryenConst'](module, literal); + Module['_BinaryenLiteralInt64'](temp, x, y); + return Module['_BinaryenConst'](module, temp); }, 'clz': function(value) { return Module['_BinaryenUnary'](module, Module['ClzInt64'], value); @@ -802,12 +802,12 @@ Module['Module'] = function(module) { return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['f32']); }, 'const': function(x) { - Module['_BinaryenLiteralFloat32'](literal, x); - return Module['_BinaryenConst'](module, literal); + Module['_BinaryenLiteralFloat32'](temp, x); + return Module['_BinaryenConst'](module, temp); }, 'const_bits': function(x) { - Module['_BinaryenLiteralFloat32Bits'](literal, x); - return Module['_BinaryenConst'](module, literal); + Module['_BinaryenLiteralFloat32Bits'](temp, x); + return Module['_BinaryenConst'](module, temp); }, 'neg': function(value) { return Module['_BinaryenUnary'](module, Module['NegFloat32'], value); @@ -901,12 +901,12 @@ Module['Module'] = function(module) { return Module['_BinaryenStore'](module, 8, offset, align, ptr, value, Module['f64']); }, 'const': function(x) { - Module['_BinaryenLiteralFloat64'](literal, x); - return Module['_BinaryenConst'](module, literal); + Module['_BinaryenLiteralFloat64'](temp, x); + return Module['_BinaryenConst'](module, temp); }, 'const_bits': function(x, y) { - Module['_BinaryenLiteralFloat64Bits'](literal, x, y); - return Module['_BinaryenConst'](module, literal); + Module['_BinaryenLiteralFloat64Bits'](temp, x, y); + return Module['_BinaryenConst'](module, temp); }, 'neg': function(value) { return Module['_BinaryenUnary'](module, Module['NegFloat64'], value); @@ -1185,16 +1185,42 @@ Module['Module'] = function(module) { Module['_BinaryenModuleDispose'](module); }; var MAX = 1024*1024; // TODO: fix this hard-wired limit - var writeBuffer = null; - this['emitBinary'] = function() { - if (!writeBuffer) writeBuffer = _malloc(MAX); - var bytes = Module['_BinaryenModuleWrite'](module, writeBuffer, MAX); + var outputBuffer = null; + var sourceMapBuffer = null; + this['emitBinary'] = function(sourceMapUrl) { + if (!outputBuffer) outputBuffer = _malloc(MAX); + var bytes = Module['_BinaryenModuleWrite'](module, outputBuffer, MAX); assert(bytes < MAX, 'FIXME: hardcoded limit on module size'); // we should not use the whole buffer - return new Uint8Array(HEAPU8.subarray(writeBuffer, writeBuffer + bytes)); + return new Uint8Array(HEAPU8.subarray(outputBuffer, outputBuffer + bytes)); + }; + this['emitBinaryWithSourceMap'] = function(sourceMapUrl) { + if (!outputBuffer) outputBuffer = _malloc(MAX); + if (!sourceMapBuffer) sourceMapBuffer = _malloc(MAX); + return preserveStack(function() { + Module['_BinaryenModuleWriteWithSourceMap'](temp, module, strToStack(sourceMapUrl), outputBuffer, MAX, sourceMapBuffer, MAX); + var outputBytes = HEAPU32[temp >>> 2]; + var sourceMapBytes = HEAPU32[(temp + 1) >>> 2]; + assert(outputBytes < MAX && sourceMapBytes < MAX, 'FIXME: hardcoded limit on module size'); // see above + return { + 'binary': new Uint8Array(HEAPU8.subarray(outputBuffer, outputBuffer + outputBytes)), + 'sourceMap': Pointer_stringify(sourceMapBuffer) + }; + }); }; this['interpret'] = function() { return Module['_BinaryenModuleInterpret'](module); }; + this['addDebugInfoFileName'] = function(filename) { + return preserveStack(function() { + return Module['_BinaryenModuleAddDebugInfoFileName'](module, strToStack(filename)); + }); + }; + this['getDebugInfoFileName'] = function(index) { + return Pointer_stringify(Module['_BinaryenModuleGetDebugInfoFileName'](module, index)); + }; + this['setDebugLocation'] = function(func, expr, fileIndex, lineNumber, columnNumber) { + return Module['_BinaryenFunctionSetDebugLocation'](func, expr, fileIndex, lineNumber, columnNumber); + }; }; // 'Relooper' interface |