diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm.h | 5 | ||||
-rw-r--r-- | src/emscripten-optimizer/optimizer-shared.cpp | 38 | ||||
-rw-r--r-- | src/emscripten-optimizer/optimizer.h | 9 |
3 files changed, 49 insertions, 3 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 92ef589d2..e44d2b5b1 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -251,9 +251,8 @@ private: return asmToWasmType(detectAsmType(ast, data)); } - bool isUnsignedCoercion(Ref ast) { // TODO: use detectSign? - if (ast[0] == BINARY && ast[1] == TRSHIFT) return true; - return false; + bool isUnsignedCoercion(Ref ast) { + return detectSign(ast) == ASM_UNSIGNED; } // an asm.js binary op can either be a binary or a relational in wasm diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 1c36efc62..054716b14 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -123,3 +123,41 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef) { return ASM_NONE; } +AsmSign detectSign(Ref node) { + IString type = node[0]->getIString(); + if (type == BINARY) { + IString op = node[1]->getIString(); + switch (op.str[0]) { + case '>': { + if (op == TRSHIFT) return ASM_UNSIGNED; + // fallthrough + } + case '|': case '&': case '^': case '<': case '=': case '!': return ASM_SIGNED; + case '+': case '-': return ASM_FLEXIBLE; + case '*': case '/': return ASM_NONSIGNED; // without a coercion, these are double + default: abort(); + } + } else if (type == UNARY_PREFIX) { + IString op = node[1]->getIString(); + switch (op.str[0]) { + case '-': return ASM_FLEXIBLE; + case '+': return ASM_NONSIGNED; // XXX double + case '~': return ASM_SIGNED; + default: abort(); + } + } else if (type == NUM) { + double value = node[1]->getNumber(); + if (value < 0) return ASM_SIGNED; + if (value > uint32_t(-1) || fmod(value, 1) != 0) return ASM_NONSIGNED; + if (value == int32_t(value)) return ASM_FLEXIBLE; + return ASM_UNSIGNED; + } else if (type == NAME) { + return ASM_FLEXIBLE; + } else if (type == CONDITIONAL) { + return detectSign(node[2]); + } else if (type == CALL) { + if (node[1][0] == NAME && node[1][1] == MATH_FROUND) return ASM_NONSIGNED; + } + abort(); +} + diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index 5edcaad87..fe1c18770 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -123,5 +123,14 @@ struct HeapInfo { HeapInfo parseHeap(const char *name); +enum AsmSign { + ASM_FLEXIBLE = 0, // small constants can be signed or unsigned, variables are also flexible + ASM_SIGNED = 1, + ASM_UNSIGNED = 2, + ASM_NONSIGNED = 3, +}; + +extern AsmSign detectSign(cashew::Ref node); + #endif // __optimizer_h__ |