summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer/optimizer-shared.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emscripten-optimizer/optimizer-shared.cpp')
-rw-r--r--src/emscripten-optimizer/optimizer-shared.cpp38
1 files changed, 38 insertions, 0 deletions
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();
+}
+