Skip to content

Commit a81f5cb

Browse files
committed
Merge branch 'master' into clang_tidy_hook
2 parents 3399f88 + 06f659c commit a81f5cb

19 files changed

Lines changed: 457 additions & 73968 deletions

.clang-tidy

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Checks: 'readability-braces-around-statements'
2+
CheckOptions:
3+
- key: readability-identifier-naming.ClassCase
4+
value: CamelCase
5+
- key: readability-identifier-naming.EnumCase
6+
value: CamelCase
7+
- key: readability-identifier-naming.EnumConstantCase
8+
value: CamelCase
9+
- key: readability-identifier-naming.FunctionCase
10+
value: camelBack
11+
- key: readability-identifier-naming.MemberCase
12+
value: camelBack
13+
- key: readability-identifier-naming.ParameterCase
14+
value: camelBack
15+
- key: readability-identifier-naming.VariableCase
16+
value: camelBack

build-js.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fi
4040
EMCC_ARGS="-std=c++11 --memory-init-file 0"
4141
EMCC_ARGS="$EMCC_ARGS -s ALLOW_MEMORY_GROWTH=1"
4242
EMCC_ARGS="$EMCC_ARGS -s DEMANGLE_SUPPORT=1"
43-
EMCC_ARGS="$EMCC_ARGS -s NO_FILESYSTEM=1"
43+
EMCC_ARGS="$EMCC_ARGS -s NO_FILESYSTEM=0"
4444
EMCC_ARGS="$EMCC_ARGS -s WASM=0"
4545
EMCC_ARGS="$EMCC_ARGS -s ERROR_ON_UNDEFINED_SYMBOLS=1"
4646
EMCC_ARGS="$EMCC_ARGS -s BINARYEN_ASYNC_COMPILATION=0"

src/passes/I64ToI32Lowering.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
366366
builder->makeLoad(4,
367367
curr->signed_,
368368
curr->offset + 4,
369-
1,
369+
std::min(uint32_t(curr->align), uint32_t(4)),
370370
builder->makeGetLocal(ptrTemp, i32),
371371
i32));
372372
} else if (curr->signed_) {
@@ -409,7 +409,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
409409
Store* storeHigh =
410410
builder->makeStore(4,
411411
curr->offset + 4,
412-
1,
412+
std::min(uint32_t(curr->align), uint32_t(4)),
413413
builder->makeGetLocal(ptrTemp, i32),
414414
builder->makeGetLocal(highBits, i32),
415415
i32);

src/passes/SimplifyLocals.cpp

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ struct SimplifyLocals
216216
}
217217
}
218218

219-
void visitGetLocal(GetLocal* curr) {
219+
void optimizeGetLocal(GetLocal* curr) {
220220
auto found = sinkables.find(curr->index);
221221
if (found != sinkables.end()) {
222222
auto* set = (*found->second.item)
@@ -311,8 +311,61 @@ struct SimplifyLocals
311311
static void
312312
visitPost(SimplifyLocals<allowTee, allowStructure, allowNesting>* self,
313313
Expression** currp) {
314+
// Handling invalidations in the case where the current node is a get
315+
// that we sink into is not trivial in general. In the simple case,
316+
// all current sinkables are compatible with each other (otherwise one
317+
// would have invalidated a previous one, and removed it). Given that, if
318+
// we sink one of the sinkables, then that new code cannot invalidate any
319+
// other sinkable - we've already compared them. However, a tricky case
320+
// is when a sinkable contains another sinkable,
321+
//
322+
// (local.set $x
323+
// (block (result i32)
324+
// (A (local.get $y))
325+
// (local.set $y B)
326+
// )
327+
// )
328+
// (C (local.get $y))
329+
// (D (local.get $x))
330+
//
331+
// If we sink the set of $y, we have
332+
//
333+
// (local.set $x
334+
// (block (result i32)
335+
// (A (local.get $y))
336+
// (nop)
337+
// )
338+
// )
339+
// (C B)
340+
// (D (local.get $x))
341+
//
342+
// There is now a risk that the set of $x should be invalidated, because
343+
// if we sink it then A may happen after B (imagine that B contains
344+
// something dangerous for that). To verify the risk, we could recursively
345+
// scan all of B, but that is less efficient. Instead, the key thing is
346+
// that if we sink out an inner part of a set, we should just leave further
347+
// work on it to a later iteration. This is achieved by checking for
348+
// invalidation on the original node, the local.get $y, which is guaranteed
349+
// to invalidate the parent whose inner part was removed (since the inner
350+
// part has a set, and the original node is a get of that same local).
351+
//
352+
// To implement this, if the current node is a get, note it and use it
353+
// for invalidations later down. We must note it since optimizing the get
354+
// may perform arbitrary changes to the graph, including reuse the get.
355+
356+
Expression* original = *currp;
357+
358+
GetLocal originalGet;
359+
360+
if (auto* get = (*currp)->dynCast<GetLocal>()) {
361+
// Note: no visitor for GetLocal, so that we can handle it here.
362+
originalGet = *get;
363+
original = &originalGet;
364+
self->optimizeGetLocal(get);
365+
}
366+
314367
// perform main SetLocal processing here, since we may be the result of
315-
// replaceCurrent, i.e., the visitor was not called.
368+
// replaceCurrent, i.e., no visitor for SetLocal, like GetLocal above.
316369
auto* set = (*currp)->dynCast<SetLocal>();
317370

318371
if (set) {
@@ -332,7 +385,7 @@ struct SimplifyLocals
332385
}
333386

334387
EffectAnalyzer effects(self->getPassOptions());
335-
if (effects.checkPost(*currp)) {
388+
if (effects.checkPost(original)) {
336389
self->checkInvalidations(effects);
337390
}
338391

src/wasm2js.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -830,11 +830,30 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
830830
Ref theSwitch =
831831
ValueBuilder::makeSwitch(makeAsmCoercion(condition, ASM_INT));
832832
ret[1]->push_back(theSwitch);
833+
// First, group the switch targets.
834+
std::map<Name, std::vector<Index>> targetIndexes;
833835
for (size_t i = 0; i < curr->targets.size(); i++) {
834-
ValueBuilder::appendCaseToSwitch(theSwitch, ValueBuilder::makeNum(i));
835-
ValueBuilder::appendCodeToSwitch(
836-
theSwitch, blockify(makeBreakOrContinue(curr->targets[i])), false);
836+
targetIndexes[curr->targets[i]].push_back(i);
837837
}
838+
// Emit group by group.
839+
for (auto& pair : targetIndexes) {
840+
auto target = pair.first;
841+
auto& indexes = pair.second;
842+
if (target != curr->default_) {
843+
for (auto i : indexes) {
844+
ValueBuilder::appendCaseToSwitch(theSwitch,
845+
ValueBuilder::makeNum(i));
846+
}
847+
ValueBuilder::appendCodeToSwitch(
848+
theSwitch, blockify(makeBreakOrContinue(target)), false);
849+
} else {
850+
// For the group going to the same place as the default, we can just
851+
// emit the default itself, which we do at the end.
852+
}
853+
}
854+
// TODO: if the group the default is in is not the largest, we can turn
855+
// the largest into
856+
// the default by using a local and a check on the range
838857
ValueBuilder::appendDefaultToSwitch(theSwitch);
839858
ValueBuilder::appendCodeToSwitch(
840859
theSwitch, blockify(makeBreakOrContinue(curr->default_)), false);

test/binaryen.js/emit_asmjs.js.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function asmFunc(global, env, buffer) {
2828

2929
var FUNCTION_TABLE = [];
3030
return {
31-
main: main
31+
"main": main
3232
};
3333
}
3434

0 commit comments

Comments
 (0)