Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 4 additions & 2 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -906,8 +906,10 @@ class WasmBinaryBuilder {
BinaryConsts::ASTNodes readExpression(Expression*& curr);
void pushBlockElements(Block* curr, size_t start, size_t end);
void visitBlock(Block *curr);
Expression* getMaybeBlock(WasmType type);
Expression* getBlock(WasmType type);

// Gets a block of expressions. If it's just one, return that singleton.
Expression* getBlockOrSingleton(WasmType type);

void visitIf(If *curr);
void visitLoop(Loop *curr);
BreakTarget getBreakTarget(int32_t offset);
Expand Down
56 changes: 35 additions & 21 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ void WasmBinaryWriter::writeFunctions() {
if (numLocalsByType[f32]) o << U32LEB(numLocalsByType[f32]) << binaryWasmType(f32);
if (numLocalsByType[f64]) o << U32LEB(numLocalsByType[f64]) << binaryWasmType(f64);

writeExpression(function->body);
recursePossibleBlockContents(function->body);
o << int8_t(BinaryConsts::End);
size_t size = o.size() - start;
assert(size <= std::numeric_limits<uint32_t>::max());
Expand Down Expand Up @@ -1633,7 +1633,7 @@ void WasmBinaryBuilder::readFunctions() {
breakStack.emplace_back(RETURN_BREAK, func->result != none); // the break target for the function scope
assert(expressionStack.empty());
assert(depth == 0);
func->body = getMaybeBlock(func->result);
func->body = getBlockOrSingleton(func->result);
assert(depth == 0);
assert(breakStack.size() == 1);
breakStack.pop_back();
Expand Down Expand Up @@ -2225,38 +2225,34 @@ void WasmBinaryBuilder::visitBlock(Block *curr) {
}
}

Expression* WasmBinaryBuilder::getMaybeBlock(WasmType type) {
Expression* WasmBinaryBuilder::getBlockOrSingleton(WasmType type) {
Name label = getNextLabel();
breakStack.push_back({label, type != none && type != unreachable});
auto start = expressionStack.size();
processExpressions();
size_t end = expressionStack.size();
if (start - end == 1) {
return popExpression();
}
if (start > end) {
throw ParseException("block cannot pop from outside");
}
breakStack.pop_back();
auto* block = allocator.alloc<Block>();
pushBlockElements(block, start, end);
block->name = label;
block->finalize(type);
return block;
}

Expression* WasmBinaryBuilder::getBlock(WasmType type) {
Name label = getNextLabel();
breakStack.push_back({label, type != none && type != unreachable});
auto* block = Builder(wasm).blockify(getMaybeBlock(type));
breakStack.pop_back();
block->cast<Block>()->name = label;
// maybe we don't need a block here?
if (!brokenTo(block)) {
block->name = Name();
if (block->list.size() == 1) {
return block->list[0];
}
}
return block;
}

void WasmBinaryBuilder::visitIf(If *curr) {
if (debug) std::cerr << "zz node: If" << std::endl;
curr->type = getWasmType();
curr->condition = popNonVoidExpression();
curr->ifTrue = getBlock(curr->type);
curr->ifTrue = getBlockOrSingleton(curr->type);
if (lastSeparator == BinaryConsts::Else) {
curr->ifFalse = getBlock(curr->type);
curr->ifFalse = getBlockOrSingleton(curr->type);
}
curr->finalize(curr->type);
if (lastSeparator != BinaryConsts::End) {
Expand All @@ -2269,7 +2265,25 @@ void WasmBinaryBuilder::visitLoop(Loop *curr) {
curr->type = getWasmType();
curr->name = getNextLabel();
breakStack.push_back({curr->name, 0});
curr->body = getMaybeBlock(curr->type);
// find the expressions in the block, and create the body
// a loop may have a list of instructions in wasm, much like
// a block, but it only has a label at the top of the loop,
// so even if we need a block (if there is more than 1
// expression) we never need a label on the block.
auto start = expressionStack.size();
processExpressions();
size_t end = expressionStack.size();
if (end - start == 1) {
curr->body = popExpression();
} else {
if (start > end) {
throw ParseException("block cannot pop from outside");
}
auto* block = allocator.alloc<Block>();
pushBlockElements(block, start, end);
block->finalize(curr->type);
curr->body = block;
}
breakStack.pop_back();
curr->finalize(curr->type);
}
Expand Down
240 changes: 116 additions & 124 deletions test/atomics.wast.fromBinary
Original file line number Diff line number Diff line change
Expand Up @@ -4,165 +4,157 @@
(func $atomic-loadstore (type $0)
(local $var$0 i32)
(local $var$1 i64)
(block $label$0
(drop
(i32.atomic.load8_u offset=4
(get_local $var$0)
)
(drop
(i32.atomic.load8_u offset=4
(get_local $var$0)
)
(drop
(i32.atomic.load16_u offset=4
(get_local $var$0)
)
)
(drop
(i32.atomic.load16_u offset=4
(get_local $var$0)
)
(drop
(i32.atomic.load offset=4
(get_local $var$0)
)
)
(drop
(i32.atomic.load offset=4
(get_local $var$0)
)
(drop
(i64.atomic.load8_u
(get_local $var$0)
)
)
(drop
(i64.atomic.load8_u
(get_local $var$0)
)
(drop
(i64.atomic.load16_u
(get_local $var$0)
)
)
(drop
(i64.atomic.load16_u
(get_local $var$0)
)
(drop
(i64.atomic.load32_u
(get_local $var$0)
)
)
(drop
(i64.atomic.load32_u
(get_local $var$0)
)
(drop
(i64.atomic.load
(get_local $var$0)
)
)
(drop
(i64.atomic.load
(get_local $var$0)
)
(i32.atomic.store offset=4
)
(i32.atomic.store offset=4
(get_local $var$0)
(get_local $var$0)
)
(i32.atomic.store8 offset=4
(get_local $var$0)
(get_local $var$0)
)
(i32.atomic.store16 offset=4
(get_local $var$0)
(get_local $var$0)
)
(i64.atomic.store offset=4
(get_local $var$0)
(get_local $var$1)
)
(i64.atomic.store8 offset=4
(get_local $var$0)
(get_local $var$1)
)
(i64.atomic.store16 offset=4
(get_local $var$0)
(get_local $var$1)
)
(i64.atomic.store32 offset=4
(get_local $var$0)
(get_local $var$1)
)
)
(func $atomic-rmw (type $0)
(local $var$0 i32)
(local $var$1 i64)
(drop
(i32.atomic.rmw.add offset=4
(get_local $var$0)
(get_local $var$0)
)
(i32.atomic.store8 offset=4
)
(drop
(i32.atomic.rmw8_u.add offset=4
(get_local $var$0)
(get_local $var$0)
)
(i32.atomic.store16 offset=4
)
(drop
(i32.atomic.rmw16_u.and
(get_local $var$0)
(get_local $var$0)
)
(i64.atomic.store offset=4
)
(drop
(i64.atomic.rmw32_u.or
(get_local $var$0)
(get_local $var$1)
)
(i64.atomic.store8 offset=4
)
(drop
(i32.atomic.rmw8_u.xchg
(get_local $var$0)
(get_local $var$0)
(get_local $var$1)
)
(i64.atomic.store16 offset=4
)
)
(func $atomic-cmpxchg (type $0)
(local $var$0 i32)
(local $var$1 i64)
(drop
(i32.atomic.rmw.cmpxchg offset=4
(get_local $var$0)
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i32.atomic.rmw8_u.cmpxchg
(get_local $var$0)
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i64.atomic.rmw.cmpxchg offset=4
(get_local $var$0)
(get_local $var$1)
(get_local $var$1)
)
(i64.atomic.store32 offset=4
)
(drop
(i64.atomic.rmw32_u.cmpxchg
(get_local $var$0)
(get_local $var$1)
(get_local $var$1)
)
)
)
(func $atomic-rmw (type $0)
(func $atomic-wait-wake (type $0)
(local $var$0 i32)
(local $var$1 i64)
(block $label$0
(drop
(i32.atomic.rmw.add offset=4
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i32.atomic.rmw8_u.add offset=4
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i32.atomic.rmw16_u.and
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i64.atomic.rmw32_u.or
(get_local $var$0)
(get_local $var$1)
)
)
(drop
(i32.atomic.rmw8_u.xchg
(get_local $var$0)
(get_local $var$0)
)
(drop
(i32.wait
(get_local $var$0)
(get_local $var$0)
(get_local $var$1)
)
)
)
(func $atomic-cmpxchg (type $0)
(local $var$0 i32)
(local $var$1 i64)
(block $label$0
(drop
(i32.atomic.rmw.cmpxchg offset=4
(get_local $var$0)
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i32.atomic.rmw8_u.cmpxchg
(get_local $var$0)
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i64.atomic.rmw.cmpxchg offset=4
(get_local $var$0)
(get_local $var$1)
(get_local $var$1)
)
)
(drop
(i64.atomic.rmw32_u.cmpxchg
(get_local $var$0)
(get_local $var$1)
(get_local $var$1)
)
(drop
(wake
(get_local $var$0)
(get_local $var$0)
)
)
)
(func $atomic-wait-wake (type $0)
(local $var$0 i32)
(local $var$1 i64)
(block $label$0
(drop
(i32.wait
(get_local $var$0)
(get_local $var$0)
(get_local $var$1)
)
)
(drop
(wake
(get_local $var$0)
(get_local $var$0)
)
)
(drop
(i64.wait
(get_local $var$0)
(get_local $var$1)
(get_local $var$1)
)
(drop
(i64.wait
(get_local $var$0)
(get_local $var$1)
(get_local $var$1)
)
)
)
Expand Down
Loading