Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1962,6 +1962,19 @@ void BinaryenExpressionPrint(BinaryenExpressionRef expr) {
std::cout << '\n';
}

BinaryenExpressionRef BinaryenExpressionCopy(BinaryenExpressionRef expr,
BinaryenModuleRef module) {
auto* wasm = (Module*)module;
auto* ret = ExpressionManipulator::copy(expr, *wasm);
if (tracing) {
auto id = noteExpression(ret);
std::cout << " expressions[" << id
<< "] = BinaryenExpressionCopy(expressions[" << expressions[expr]
<< "], theModule);\n";
}
return ret;
}

// Specific expression utility

// Block
Expand Down
2 changes: 2 additions & 0 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,8 @@ BINARYEN_API BinaryenExpressionId
BinaryenExpressionGetId(BinaryenExpressionRef expr);
BINARYEN_API BinaryenType BinaryenExpressionGetType(BinaryenExpressionRef expr);
BINARYEN_API void BinaryenExpressionPrint(BinaryenExpressionRef expr);
BINARYEN_API BinaryenExpressionRef
BinaryenExpressionCopy(BinaryenExpressionRef expr, BinaryenModuleRef module);

BINARYEN_API const char* BinaryenBlockGetName(BinaryenExpressionRef expr);
BINARYEN_API BinaryenIndex
Expand Down
3 changes: 3 additions & 0 deletions src/js/binaryen.js-post.js
Original file line number Diff line number Diff line change
Expand Up @@ -2407,6 +2407,9 @@ function wrapModule(module, self) {
self['setDebugLocation'] = function(func, expr, fileIndex, lineNumber, columnNumber) {
return Module['_BinaryenFunctionSetDebugLocation'](func, expr, fileIndex, lineNumber, columnNumber);
};
self['copyExpression'] = function(expr) {
return Module['_BinaryenExpressionCopy'](expr, module);
};

return self;
}
Expand Down
28 changes: 28 additions & 0 deletions test/binaryen.js/copy-expression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
binaryen.setAPITracing(true);

var module = new binaryen.Module();

// Create an expression and copy it
var original = module.block(null, [
module.if(
module.local.get(0, binaryen.i32),
module.i32.const(1),
module.i32.const(2)
)
], binaryen.i32);
var copy = module.copyExpression(original);

// Check that the expression incl. sub-expressions are copies
assert(original !== copy);
var originalIf = binaryen._BinaryenBlockGetChild(original, 0);
var copyIf = binaryen._BinaryenBlockGetChild(copy, 0);
assert(originalIf !== copyIf);
assert(binaryen._BinaryenIfGetCondition(originalIf) !== binaryen._BinaryenIfGetCondition(copyIf));
assert(binaryen._BinaryenIfGetIfTrue(originalIf) !== binaryen._BinaryenIfGetIfTrue(copyIf));
assert(binaryen._BinaryenIfGetIfFalse(originalIf) !== binaryen._BinaryenIfGetIfFalse(copyIf));

binaryen.setAPITracing(false);

// Check that both are otherwise identical, but do it after tracing so
// emitText and tracing output don't conflict on stdout
assert(binaryen.emitText(original) === binaryen.emitText(copy));
37 changes: 37 additions & 0 deletions test/binaryen.js/copy-expression.js.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// beginning a Binaryen API trace
#include <math.h>
#include <map>
#include "binaryen-c.h"
int main() {
std::map<size_t, BinaryenType> types;
std::map<size_t, BinaryenExpressionRef> expressions;
std::map<size_t, BinaryenFunctionRef> functions;
std::map<size_t, BinaryenGlobalRef> globals;
std::map<size_t, BinaryenEventRef> events;
std::map<size_t, BinaryenExportRef> exports;
std::map<size_t, RelooperBlockRef> relooperBlocks;
std::map<size_t, ExpressionRunnerRef> expressionRunners;
BinaryenModuleRef the_module = NULL;
RelooperRef the_relooper = NULL;
the_module = BinaryenModuleCreate();
expressions[size_t(NULL)] = BinaryenExpressionRef(NULL);
expressions[1] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32());
expressions[2] = BinaryenConst(the_module, BinaryenLiteralInt32(1));
expressions[3] = BinaryenConst(the_module, BinaryenLiteralInt32(2));
expressions[4] = BinaryenIf(the_module, expressions[1], expressions[2], expressions[3]);
{
BinaryenExpressionRef children[] = { expressions[4] };
expressions[5] = BinaryenBlock(the_module, NULL, children, 1, BinaryenTypeInt32());
}
expressions[6] = BinaryenExpressionCopy(expressions[5], theModule);
BinaryenBlockGetChild(expressions[5], 0);
BinaryenBlockGetChild(expressions[6], 0);
BinaryenIfGetCondition(expressions[4]);
BinaryenIfGetCondition(expressions[0]); // this is bad
BinaryenIfGetIfTrue(expressions[4]);
BinaryenIfGetIfTrue(expressions[0]); // this is bad
BinaryenIfGetIfFalse(expressions[4]);
BinaryenIfGetIfFalse(expressions[0]); // this is bad
return 0;
}
// ending a Binaryen API trace