summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-04-26 16:59:41 -0700
committerGitHub <noreply@github.com>2019-04-26 16:59:41 -0700
commitdb9124f1de0478dcac525009b6f1589b44a7edd8 (patch)
treefa26395a0f6cca53cf5cb6e10189f989c5bfa847 /src/emscripten-optimizer
parent87636dccd404a340d75acb1d96301581343f29ca (diff)
downloadbinaryen-db9124f1de0478dcac525009b6f1589b44a7edd8.tar.gz
binaryen-db9124f1de0478dcac525009b6f1589b44a7edd8.tar.bz2
binaryen-db9124f1de0478dcac525009b6f1589b44a7edd8.zip
Apply format changes from #2048 (#2059)
Mass change to apply clang-format to everything. We are applying this in a PR by me so the (git) blame is all mine ;) but @aheejin did all the work to get clang-format set up and all the manual work to tidy up some things to make the output nicer in #2048
Diffstat (limited to 'src/emscripten-optimizer')
-rw-r--r--src/emscripten-optimizer/istring.h109
-rw-r--r--src/emscripten-optimizer/optimizer-shared.cpp234
-rw-r--r--src/emscripten-optimizer/optimizer.h47
-rw-r--r--src/emscripten-optimizer/parser.cpp211
-rw-r--r--src/emscripten-optimizer/parser.h607
-rw-r--r--src/emscripten-optimizer/simple_ast.cpp52
-rw-r--r--src/emscripten-optimizer/simple_ast.h773
-rw-r--r--src/emscripten-optimizer/snprintf.h34
8 files changed, 1209 insertions, 858 deletions
diff --git a/src/emscripten-optimizer/istring.h b/src/emscripten-optimizer/istring.h
index 5c3b094c3..320a3e590 100644
--- a/src/emscripten-optimizer/istring.h
+++ b/src/emscripten-optimizer/istring.h
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-// Interned String type, 100% interned on creation. Comparisons are always just a pointer comparison
+// Interned String type, 100% interned on creation. Comparisons are always just
+// a pointer comparison
#ifndef wasm_istring_h
#define wasm_istring_h
-#include <unordered_set>
-#include <unordered_map>
#include <set>
+#include <unordered_map>
+#include <unordered_set>
-#include <string.h>
+#include <assert.h>
#include <stdint.h>
-#include <stdlib.h>
#include <stdio.h>
-#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
#include "support/threads.h"
#include "support/utilities.h"
@@ -35,9 +36,10 @@
namespace cashew {
struct IString {
- const char *str = nullptr;
+ const char* str = nullptr;
- static size_t hash_c(const char *str) { // see http://www.cse.yorku.ca/~oz/hash.html
+ static size_t
+ hash_c(const char* str) { // see http://www.cse.yorku.ca/~oz/hash.html
unsigned int hash = 5381;
int c;
while ((c = *str++)) {
@@ -46,27 +48,27 @@ struct IString {
return (size_t)hash;
}
- class CStringHash : public std::hash<const char *> {
+ class CStringHash : public std::hash<const char*> {
public:
- size_t operator()(const char *str) const {
- return IString::hash_c(str);
- }
+ size_t operator()(const char* str) const { return IString::hash_c(str); }
};
- class CStringEqual : public std::equal_to<const char *> {
+ class CStringEqual : public std::equal_to<const char*> {
public:
- bool operator()(const char *x, const char *y) const {
+ bool operator()(const char* x, const char* y) const {
return strcmp(x, y) == 0;
}
};
IString() = default;
- IString(const char *s, bool reuse=true) { // if reuse=true, then input is assumed to remain alive; not copied
+ // if reuse=true, then input is assumed to remain alive; not copied
+ IString(const char* s, bool reuse = true) {
assert(s);
set(s, reuse);
}
- void set(const char *s, bool reuse=true) {
- typedef std::unordered_set<const char *, CStringHash, CStringEqual> StringSet;
+ void set(const char* s, bool reuse = true) {
+ typedef std::unordered_set<const char*, CStringHash, CStringEqual>
+ StringSet;
// one global store of strings per thread, we must not access this
// in parallel
thread_local static StringSet strings;
@@ -79,8 +81,8 @@ struct IString {
// exactly once
static std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex);
- // a single global set contains the actual strings, so we allocate each one
- // exactly once.
+ // a single global set contains the actual strings, so we allocate each
+ // one exactly once.
static StringSet globalStrings;
auto globalExisting = globalStrings.find(s);
if (globalExisting == globalStrings.end()) {
@@ -103,56 +105,51 @@ struct IString {
str = s;
}
- void set(const IString &s) {
- str = s.str;
- }
+ void set(const IString& s) { str = s.str; }
- void clear() {
- str = nullptr;
- }
+ void clear() { str = nullptr; }
bool operator==(const IString& other) const {
- //assert((str == other.str) == !strcmp(str, other.str));
+ // assert((str == other.str) == !strcmp(str, other.str));
return str == other.str; // fast!
}
bool operator!=(const IString& other) const {
- //assert((str == other.str) == !strcmp(str, other.str));
+ // assert((str == other.str) == !strcmp(str, other.str));
return str != other.str; // fast!
}
bool operator<(const IString& other) const {
return strcmp(str ? str : "", other.str ? other.str : "") < 0;
}
- char operator[](int x) const {
- return str[x];
- }
+ char operator[](int x) const { return str[x]; }
bool operator!() const { // no string, or empty string
return !str || str[0] == 0;
}
- const char *c_str() const { return str; }
- bool equals(const char *other) const { return !strcmp(str, other); }
+ const char* c_str() const { return str; }
+ bool equals(const char* other) const { return !strcmp(str, other); }
- bool is() const { return str != nullptr; }
+ bool is() const { return str != nullptr; }
bool isNull() const { return str == nullptr; }
- const char* stripPrefix(const char *prefix) const {
- const char *ptr = str;
+ const char* stripPrefix(const char* prefix) const {
+ const char* ptr = str;
while (true) {
- if (*prefix == 0) return ptr;
- if (*ptr == 0) return nullptr;
- if (*ptr++ != *prefix++) return nullptr;
+ if (*prefix == 0)
+ return ptr;
+ if (*ptr == 0)
+ return nullptr;
+ if (*ptr++ != *prefix++)
+ return nullptr;
}
}
- bool startsWith(const char *prefix) const {
+ bool startsWith(const char* prefix) const {
return stripPrefix(prefix) != nullptr;
}
- size_t size() const {
- return str ? strlen(str) : 0;
- }
+ size_t size() const { return str ? strlen(str) : 0; }
};
} // namespace cashew
@@ -161,13 +158,16 @@ struct IString {
namespace std {
-template<> struct hash<cashew::IString> : public unary_function<cashew::IString, size_t> {
+template<>
+struct hash<cashew::IString> : public unary_function<cashew::IString, size_t> {
size_t operator()(const cashew::IString& str) const {
return std::hash<size_t>{}(size_t(str.str));
}
};
-template<> struct equal_to<cashew::IString> : public binary_function<cashew::IString, cashew::IString, bool> {
+template<>
+struct equal_to<cashew::IString>
+ : public binary_function<cashew::IString, cashew::IString, bool> {
bool operator()(const cashew::IString& x, const cashew::IString& y) const {
return x == y;
}
@@ -181,32 +181,31 @@ namespace cashew {
class IStringSet : public std::unordered_set<IString> {
std::vector<char> data;
+
public:
IStringSet() = default;
- IStringSet(const char *init) { // comma-delimited list
+ IStringSet(const char* init) { // comma-delimited list
int size = strlen(init) + 1;
data.resize(size);
- char *curr = &data[0];
+ char* curr = &data[0];
strncpy(curr, init, size);
while (1) {
- char *end = strchr(curr, ' ');
- if (end) *end = 0;
+ char* end = strchr(curr, ' ');
+ if (end)
+ *end = 0;
insert(curr);
- if (!end) break;
+ if (!end)
+ break;
curr = end + 1;
}
}
- bool has(const IString& str) {
- return count(str) > 0;
- }
+ bool has(const IString& str) { return count(str) > 0; }
};
class IOrderedStringSet : public std::set<IString> {
public:
- bool has(const IString& str) {
- return count(str) > 0;
- }
+ bool has(const IString& str) { return count(str) > 0; }
};
} // namespace cashew
diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp
index 81f7949ba..3ac3ca7ea 100644
--- a/src/emscripten-optimizer/optimizer-shared.cpp
+++ b/src/emscripten-optimizer/optimizer-shared.cpp
@@ -23,14 +23,14 @@ using namespace cashew;
IString ASM_FLOAT_ZERO;
-IString SIMD_INT8X16_CHECK("SIMD_Int8x16_check"),
- SIMD_INT16X8_CHECK("SIMD_Int16x8_check"),
- SIMD_INT32X4_CHECK("SIMD_Int32x4_check"),
- SIMD_FLOAT32X4_CHECK("SIMD_Float32x4_check"),
- SIMD_FLOAT64X2_CHECK("SIMD_Float64x2_check"),
- TEMP_RET0("tempRet0");
+IString SIMD_INT8X16_CHECK("SIMD_Int8x16_check");
+IString SIMD_INT16X8_CHECK("SIMD_Int16x8_check");
+IString SIMD_INT32X4_CHECK("SIMD_Int32x4_check");
+IString SIMD_FLOAT32X4_CHECK("SIMD_Float32x4_check");
+IString SIMD_FLOAT64X2_CHECK("SIMD_Float64x2_check");
+IString TEMP_RET0("tempRet0");
-int parseInt(const char *str) {
+int parseInt(const char* str) {
int ret = *str - '0';
while (*(++str)) {
ret *= 10;
@@ -39,7 +39,7 @@ int parseInt(const char *str) {
return ret;
}
-HeapInfo parseHeap(const char *name) {
+HeapInfo parseHeap(const char* name) {
HeapInfo ret;
if (name[0] != 'H' || name[1] != 'E' || name[2] != 'A' || name[3] != 'P') {
ret.valid = false;
@@ -53,33 +53,49 @@ HeapInfo parseHeap(const char *name) {
return ret;
}
-AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFround, bool allowI64) {
+AsmType detectType(Ref node,
+ AsmData* asmData,
+ bool inVarDef,
+ IString minifiedFround,
+ bool allowI64) {
if (node->isString()) {
if (asmData) {
AsmType ret = asmData->getType(node->getCString());
- if (ret != ASM_NONE) return ret;
+ if (ret != ASM_NONE)
+ return ret;
}
if (!inVarDef) {
- if (node == INF || node == NaN) return ASM_DOUBLE;
- if (node == TEMP_RET0) return ASM_INT;
+ if (node == INF || node == NaN)
+ return ASM_DOUBLE;
+ if (node == TEMP_RET0)
+ return ASM_INT;
return ASM_NONE;
}
- // We are in a variable definition, where Math_fround(0) optimized into a global constant becomes f0 = Math_fround(0)
- if (ASM_FLOAT_ZERO.isNull()) ASM_FLOAT_ZERO = node->getIString();
- else assert(node == ASM_FLOAT_ZERO);
+ // We are in a variable definition, where Math_fround(0) optimized into a
+ // global constant becomes f0 = Math_fround(0)
+ if (ASM_FLOAT_ZERO.isNull())
+ ASM_FLOAT_ZERO = node->getIString();
+ else
+ assert(node == ASM_FLOAT_ZERO);
return ASM_FLOAT;
}
if (node->isNumber()) {
- if (!wasm::isInteger(node->getNumber())) return ASM_DOUBLE;
+ if (!wasm::isInteger(node->getNumber()))
+ return ASM_DOUBLE;
return ASM_INT;
}
switch (node[0]->getCString()[0]) {
case 'u': {
if (node[0] == UNARY_PREFIX) {
switch (node[1]->getCString()[0]) {
- case '+': return ASM_DOUBLE;
- case '-': return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64);
- case '!': case '~': return ASM_INT;
+ case '+':
+ return ASM_DOUBLE;
+ case '-':
+ return detectType(
+ node[2], asmData, inVarDef, minifiedFround, allowI64);
+ case '!':
+ case '~':
+ return ASM_INT;
}
break;
}
@@ -89,13 +105,20 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFr
if (node[0] == CALL) {
if (node[1]->isString()) {
IString name = node[1]->getIString();
- if (name == MATH_FROUND || name == minifiedFround) return ASM_FLOAT;
- else if (allowI64 && (name == INT64 || name == INT64_CONST)) return ASM_INT64;
- else if (name == SIMD_FLOAT32X4 || name == SIMD_FLOAT32X4_CHECK) return ASM_FLOAT32X4;
- else if (name == SIMD_FLOAT64X2 || name == SIMD_FLOAT64X2_CHECK) return ASM_FLOAT64X2;
- else if (name == SIMD_INT8X16 || name == SIMD_INT8X16_CHECK) return ASM_INT8X16;
- else if (name == SIMD_INT16X8 || name == SIMD_INT16X8_CHECK) return ASM_INT16X8;
- else if (name == SIMD_INT32X4 || name == SIMD_INT32X4_CHECK) return ASM_INT32X4;
+ if (name == MATH_FROUND || name == minifiedFround)
+ return ASM_FLOAT;
+ else if (allowI64 && (name == INT64 || name == INT64_CONST))
+ return ASM_INT64;
+ else if (name == SIMD_FLOAT32X4 || name == SIMD_FLOAT32X4_CHECK)
+ return ASM_FLOAT32X4;
+ else if (name == SIMD_FLOAT64X2 || name == SIMD_FLOAT64X2_CHECK)
+ return ASM_FLOAT64X2;
+ else if (name == SIMD_INT8X16 || name == SIMD_INT8X16_CHECK)
+ return ASM_INT8X16;
+ else if (name == SIMD_INT16X8 || name == SIMD_INT16X8_CHECK)
+ return ASM_INT16X8;
+ else if (name == SIMD_INT32X4 || name == SIMD_INT32X4_CHECK)
+ return ASM_INT32X4;
}
return ASM_NONE;
} else if (node[0] == CONDITIONAL) {
@@ -106,10 +129,20 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFr
case 'b': {
if (node[0] == BINARY) {
switch (node[1]->getCString()[0]) {
- case '+': case '-':
- case '*': case '/': case '%': return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64);
- case '|': case '&': case '^': case '<': case '>': // handles <<, >>, >>=, <=, >=
- case '=': case '!': { // handles ==, !=
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ return detectType(
+ node[2], asmData, inVarDef, minifiedFround, allowI64);
+ case '|':
+ case '&':
+ case '^':
+ case '<':
+ case '>': // handles <<, >>, >>=, <=, >=
+ case '=':
+ case '!': { // handles ==, !=
return ASM_INT;
}
}
@@ -122,14 +155,15 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFr
} else if (node[0] == SUB) {
assert(node[1]->isString());
HeapInfo info = parseHeap(node[1][1]->getCString());
- if (info.valid) return ASM_NONE;
+ if (info.valid)
+ return ASM_NONE;
return info.floaty ? ASM_DOUBLE : ASM_INT; // XXX ASM_FLOAT?
}
break;
}
}
- //dump("horrible", node);
- //assert(0);
+ // dump("horrible", node);
+ // assert(0);
return ASM_NONE;
}
@@ -145,9 +179,12 @@ AsmSign detectSign(Ref node, IString minifiedFround) {
}
if (node->isNumber()) {
double value = node->getNumber();
- if (value < 0) return ASM_SIGNED;
- if (value > uint32_t(-1) || fmod(value, 1) != 0) return ASM_NONSIGNED;
- if (wasm::isSInteger32(value)) return ASM_FLEXIBLE;
+ if (value < 0)
+ return ASM_SIGNED;
+ if (value > uint32_t(-1) || fmod(value, 1) != 0)
+ return ASM_NONSIGNED;
+ if (wasm::isSInteger32(value))
+ return ASM_FLEXIBLE;
return ASM_UNSIGNED;
}
IString type = node[0]->getIString();
@@ -155,25 +192,44 @@ AsmSign detectSign(Ref node, IString minifiedFround) {
IString op = node[1]->getIString();
switch (op.str[0]) {
case '>': {
- if (op == TRSHIFT) return ASM_UNSIGNED;
+ if (op == TRSHIFT)
+ return ASM_UNSIGNED;
} // fallthrough
- case '|': case '&': case '^': case '<': case '=': case '!': return ASM_SIGNED;
- case '+': case '-': return ASM_FLEXIBLE;
- case '*': case '/': case '%': return ASM_NONSIGNED; // without a coercion, these are double
- default: abort_on(node);
+ case '|':
+ case '&':
+ case '^':
+ case '<':
+ case '=':
+ case '!':
+ return ASM_SIGNED;
+ case '+':
+ case '-':
+ return ASM_FLEXIBLE;
+ case '*':
+ case '/':
+ case '%':
+ return ASM_NONSIGNED; // without a coercion, these are double
+ default:
+ abort_on(node);
}
} 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_on(node);
+ case '-':
+ return ASM_FLEXIBLE;
+ case '+':
+ return ASM_NONSIGNED; // XXX double
+ case '~':
+ return ASM_SIGNED;
+ default:
+ abort_on(node);
}
} else if (type == CONDITIONAL) {
return detectSign(node[2], minifiedFround);
} else if (type == CALL) {
- if (node[1]->isString() && (node[1] == MATH_FROUND || node[1] == minifiedFround)) return ASM_NONSIGNED;
+ if (node[1]->isString() &&
+ (node[1] == MATH_FROUND || node[1] == minifiedFround))
+ return ASM_NONSIGNED;
} else if (type == SEQ) {
return detectSign(node[2], minifiedFround);
}
@@ -183,8 +239,12 @@ AsmSign detectSign(Ref node, IString minifiedFround) {
Ref makeAsmCoercedZero(AsmType type) {
switch (type) {
- case ASM_INT: return ValueBuilder::makeNum(0); break;
- case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0)); break;
+ case ASM_INT:
+ return ValueBuilder::makeNum(0);
+ break;
+ case ASM_DOUBLE:
+ return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0));
+ break;
case ASM_FLOAT: {
if (!ASM_FLOAT_ZERO.isNull()) {
return ValueBuilder::makeName(ASM_FLOAT_ZERO);
@@ -194,46 +254,92 @@ Ref makeAsmCoercedZero(AsmType type) {
break;
}
case ASM_FLOAT32X4: {
- return ValueBuilder::makeCall(SIMD_FLOAT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0));
+ return ValueBuilder::makeCall(SIMD_FLOAT32X4,
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0));
break;
}
case ASM_FLOAT64X2: {
- return ValueBuilder::makeCall(SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0));
+ return ValueBuilder::makeCall(
+ SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0));
break;
}
case ASM_INT8X16: {
- return ValueBuilder::makeCall(SIMD_INT8X16, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0));
+ return ValueBuilder::makeCall(SIMD_INT8X16,
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0));
break;
}
case ASM_INT16X8: {
- return ValueBuilder::makeCall(SIMD_INT16X8, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0));
+ return ValueBuilder::makeCall(SIMD_INT16X8,
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0));
break;
}
case ASM_INT32X4: {
- return ValueBuilder::makeCall(SIMD_INT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0));
+ return ValueBuilder::makeCall(SIMD_INT32X4,
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(0));
break;
}
- default: assert(0);
+ default:
+ assert(0);
}
abort();
}
Ref makeAsmCoercion(Ref node, AsmType type) {
switch (type) {
- case ASM_INT: return ValueBuilder::makeBinary(node, OR, ValueBuilder::makeNum(0));
- case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, node);
- case ASM_FLOAT: return ValueBuilder::makeCall(MATH_FROUND, node);
- case ASM_FLOAT32X4: return ValueBuilder::makeCall(SIMD_FLOAT32X4_CHECK, node);
- case ASM_FLOAT64X2: return ValueBuilder::makeCall(SIMD_FLOAT64X2_CHECK, node);
- case ASM_INT8X16: return ValueBuilder::makeCall(SIMD_INT8X16_CHECK, node);
- case ASM_INT16X8: return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node);
- case ASM_INT32X4: return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node);
+ case ASM_INT:
+ return ValueBuilder::makeBinary(node, OR, ValueBuilder::makeNum(0));
+ case ASM_DOUBLE:
+ return ValueBuilder::makeUnary(PLUS, node);
+ case ASM_FLOAT:
+ return ValueBuilder::makeCall(MATH_FROUND, node);
+ case ASM_FLOAT32X4:
+ return ValueBuilder::makeCall(SIMD_FLOAT32X4_CHECK, node);
+ case ASM_FLOAT64X2:
+ return ValueBuilder::makeCall(SIMD_FLOAT64X2_CHECK, node);
+ case ASM_INT8X16:
+ return ValueBuilder::makeCall(SIMD_INT8X16_CHECK, node);
+ case ASM_INT16X8:
+ return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node);
+ case ASM_INT32X4:
+ return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node);
case ASM_NONE:
- default: return node; // non-validating code, emit nothing XXX this is dangerous, we should only allow this when we know we are not validating
+ default:
+ // non-validating code, emit nothing XXX this is dangerous, we should only
+ // allow this when we know we are not validating
+ return node;
}
}
Ref makeSigning(Ref node, AsmSign sign) {
assert(sign == ASM_SIGNED || sign == ASM_UNSIGNED);
- return ValueBuilder::makeBinary(node, sign == ASM_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0));
+ return ValueBuilder::makeBinary(
+ node, sign == ASM_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0));
}
diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h
index f6b3aa536..36a9322fd 100644
--- a/src/emscripten-optimizer/optimizer.h
+++ b/src/emscripten-optimizer/optimizer.h
@@ -19,11 +19,7 @@
#include "simple_ast.h"
-extern bool preciseF32,
- receiveJSON,
- emitJSON,
- minifyWhitespace,
- last;
+extern bool preciseF32, receiveJSON, emitJSON, minifyWhitespace, last;
extern cashew::Ref extraInfo;
@@ -39,12 +35,16 @@ enum AsmType {
ASM_INT16X8,
ASM_INT32X4,
ASM_INT64, // non-asm.js
- ASM_NONE // number of types
+ ASM_NONE // number of types
};
struct AsmData;
-AsmType detectType(cashew::Ref node, AsmData *asmData=nullptr, bool inVarDef=false, cashew::IString minifiedFround=cashew::IString(), bool allowI64=false);
+AsmType detectType(cashew::Ref node,
+ AsmData* asmData = nullptr,
+ bool inVarDef = false,
+ cashew::IString minifiedFround = cashew::IString(),
+ bool allowI64 = false);
struct AsmData {
struct Local {
@@ -57,23 +57,22 @@ struct AsmData {
Locals locals;
std::vector<cashew::IString> params; // in order
- std::vector<cashew::IString> vars; // in order
+ std::vector<cashew::IString> vars; // in order
AsmType ret;
cashew::Ref func;
AsmType getType(const cashew::IString& name) {
auto ret = locals.find(name);
- if (ret != locals.end()) return ret->second.type;
+ if (ret != locals.end())
+ return ret->second.type;
return ASM_NONE;
}
void setType(const cashew::IString& name, AsmType type) {
locals[name].type = type;
}
- bool isLocal(const cashew::IString& name) {
- return locals.count(name) > 0;
- }
+ bool isLocal(const cashew::IString& name) { return locals.count(name) > 0; }
bool isParam(const cashew::IString& name) {
return isLocal(name) && locals[name].param;
}
@@ -81,8 +80,11 @@ struct AsmData {
return isLocal(name) && !locals[name].param;
}
- AsmData() = default; // if you want to fill in the data yourself
- AsmData(cashew::Ref f); // if you want to read data from f, and modify it as you go (parallel to denormalize)
+ // if you want to fill in the data yourself
+ AsmData() = default;
+ // if you want to read data from f, and modify it as you go (parallel to
+ // denormalize)
+ AsmData(cashew::Ref f);
void denormalize();
@@ -108,13 +110,13 @@ struct AsmData {
extern cashew::IString ASM_FLOAT_ZERO;
-extern cashew::IString SIMD_INT8X16_CHECK,
- SIMD_INT16X8_CHECK,
- SIMD_INT32X4_CHECK,
- SIMD_FLOAT32X4_CHECK,
- SIMD_FLOAT64X2_CHECK;
+extern cashew::IString SIMD_INT8X16_CHECK;
+extern cashew::IString SIMD_INT16X8_CHECK;
+extern cashew::IString SIMD_INT32X4_CHECK;
+extern cashew::IString SIMD_FLOAT32X4_CHECK;
+extern cashew::IString SIMD_FLOAT64X2_CHECK;
-int parseInt(const char *str);
+int parseInt(const char* str);
struct HeapInfo {
bool valid, unsign, floaty;
@@ -122,10 +124,11 @@ struct HeapInfo {
AsmType type;
};
-HeapInfo parseHeap(const char *name);
+HeapInfo parseHeap(const char* name);
enum AsmSign {
- ASM_FLEXIBLE = 0, // small constants can be signed or unsigned, variables are also flexible
+ // small constants can be signed or unsigned, variables are also flexible
+ ASM_FLEXIBLE = 0,
ASM_SIGNED = 1,
ASM_UNSIGNED = 2,
ASM_NONSIGNED = 3,
diff --git a/src/emscripten-optimizer/parser.cpp b/src/emscripten-optimizer/parser.cpp
index 035817090..72740908e 100644
--- a/src/emscripten-optimizer/parser.cpp
+++ b/src/emscripten-optimizer/parser.cpp
@@ -20,117 +20,119 @@ namespace cashew {
// common strings
-IString TOPLEVEL("toplevel"),
- DEFUN("defun"),
- BLOCK("block"),
- VAR("var"),
- CONST("const"),
- CONDITIONAL("conditional"),
- BINARY("binary"),
- RETURN("return"),
- IF("if"),
- ELSE("else"),
- WHILE("while"),
- DO("do"),
- FOR("for"),
- SEQ("seq"),
- SUB("sub"),
- CALL("call"),
- LABEL("label"),
- BREAK("break"),
- CONTINUE("continue"),
- SWITCH("switch"),
- STRING("string"),
- TRY("try"),
- INF("inf"),
- NaN("nan"),
- LLVM_CTTZ_I32("_llvm_cttz_i32"),
- UDIVMODDI4("___udivmoddi4"),
- UNARY_PREFIX("unary-prefix"),
- UNARY_POSTFIX("unary-postfix"),
- MATH_FROUND("Math_fround"),
- MATH_CLZ32("Math_clz32"),
- INT64("i64"),
- INT64_CONST("i64_const"),
- SIMD_FLOAT32X4("SIMD_Float32x4"),
- SIMD_FLOAT64X2("SIMD_Float64x2"),
- SIMD_INT8X16("SIMD_Int8x16"),
- SIMD_INT16X8("SIMD_Int16x8"),
- SIMD_INT32X4("SIMD_Int32x4"),
- PLUS("+"),
- MINUS("-"),
- OR("|"),
- AND("&"),
- XOR("^"),
- L_NOT("!"),
- B_NOT("~"),
- LT("<"),
- GE(">="),
- LE("<="),
- GT(">"),
- EQ("=="),
- NE("!="),
- DIV("/"),
- MOD("%"),
- MUL("*"),
- RSHIFT(">>"),
- LSHIFT("<<"),
- TRSHIFT(">>>"),
- HEAP8("HEAP8"),
- HEAP16("HEAP16"),
- HEAP32("HEAP32"),
- HEAPF32("HEAPF32"),
- HEAPU8("HEAPU8"),
- HEAPU16("HEAPU16"),
- HEAPU32("HEAPU32"),
- HEAPF64("HEAPF64"),
- F0("f0"),
- EMPTY(""),
- FUNCTION("function"),
- OPEN_PAREN("("),
- OPEN_BRACE("["),
- OPEN_CURLY("{"),
- CLOSE_CURLY("}"),
- COMMA(","),
- QUESTION("?"),
- COLON(":"),
- CASE("case"),
- DEFAULT("default"),
- DOT("dot"),
- PERIOD("."),
- NEW("new"),
- ARRAY("array"),
- OBJECT("object"),
- THROW("throw"),
- SET("=");
-
-IStringSet keywords("var const function if else do while for break continue return switch case default throw try catch finally true false null new");
-
-const char *OPERATOR_INITS = "+-*/%<>&^|~=!,?:.",
- *SEPARATORS = "([;{}";
+IString TOPLEVEL("toplevel");
+IString DEFUN("defun");
+IString BLOCK("block");
+IString VAR("var");
+IString CONST("const");
+IString CONDITIONAL("conditional");
+IString BINARY("binary");
+IString RETURN("return");
+IString IF("if");
+IString ELSE("else");
+IString WHILE("while");
+IString DO("do");
+IString FOR("for");
+IString SEQ("seq");
+IString SUB("sub");
+IString CALL("call");
+IString LABEL("label");
+IString BREAK("break");
+IString CONTINUE("continue");
+IString SWITCH("switch");
+IString STRING("string");
+IString TRY("try");
+IString INF("inf");
+IString NaN("nan");
+IString LLVM_CTTZ_I32("_llvm_cttz_i32");
+IString UDIVMODDI4("___udivmoddi4");
+IString UNARY_PREFIX("unary-prefix");
+IString UNARY_POSTFIX("unary-postfix");
+IString MATH_FROUND("Math_fround");
+IString MATH_CLZ32("Math_clz32");
+IString INT64("i64");
+IString INT64_CONST("i64_const");
+IString SIMD_FLOAT32X4("SIMD_Float32x4");
+IString SIMD_FLOAT64X2("SIMD_Float64x2");
+IString SIMD_INT8X16("SIMD_Int8x16");
+IString SIMD_INT16X8("SIMD_Int16x8");
+IString SIMD_INT32X4("SIMD_Int32x4");
+IString PLUS("+");
+IString MINUS("-");
+IString OR("|");
+IString AND("&");
+IString XOR("^");
+IString L_NOT("!");
+IString B_NOT("~");
+IString LT("<");
+IString GE(">=");
+IString LE("<=");
+IString GT(">");
+IString EQ("==");
+IString NE("!=");
+IString DIV("/");
+IString MOD("%");
+IString MUL("*");
+IString RSHIFT(">>");
+IString LSHIFT("<<");
+IString TRSHIFT(">>>");
+IString HEAP8("HEAP8");
+IString HEAP16("HEAP16");
+IString HEAP32("HEAP32");
+IString HEAPF32("HEAPF32");
+IString HEAPU8("HEAPU8");
+IString HEAPU16("HEAPU16");
+IString HEAPU32("HEAPU32");
+IString HEAPF64("HEAPF64");
+IString F0("f0");
+IString EMPTY("");
+IString FUNCTION("function");
+IString OPEN_PAREN("(");
+IString OPEN_BRACE("[");
+IString OPEN_CURLY("{");
+IString CLOSE_CURLY("}");
+IString COMMA(",");
+IString QUESTION("?");
+IString COLON(":");
+IString CASE("case");
+IString DEFAULT("default");
+IString DOT("dot");
+IString PERIOD(".");
+IString NEW("new");
+IString ARRAY("array");
+IString OBJECT("object");
+IString THROW("throw");
+IString SET("=");
+
+IStringSet
+ keywords("var const function if else do while for break continue return "
+ "switch case default throw try catch finally true false null new");
+
+const char *OPERATOR_INITS = "+-*/%<>&^|~=!,?:.", *SEPARATORS = "([;{}";
int MAX_OPERATOR_SIZE = 3;
std::vector<OperatorClass> operatorClasses;
-static std::vector<std::unordered_map<IString, int>> precedences; // op, type => prec
+static std::vector<std::unordered_map<IString, int>>
+ precedences; // op, type => prec
struct Init {
Init() {
// operators, rtl, type
- operatorClasses.emplace_back(".", false, OperatorClass::Binary);
- operatorClasses.emplace_back("! ~ + -", true, OperatorClass::Prefix);
- operatorClasses.emplace_back("* / %", false, OperatorClass::Binary);
- operatorClasses.emplace_back("+ -", false, OperatorClass::Binary);
+ operatorClasses.emplace_back(".", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("! ~ + -", true, OperatorClass::Prefix);
+ operatorClasses.emplace_back("* / %", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("+ -", false, OperatorClass::Binary);
operatorClasses.emplace_back("<< >> >>>", false, OperatorClass::Binary);
operatorClasses.emplace_back("< <= > >=", false, OperatorClass::Binary);
- operatorClasses.emplace_back("== !=", false, OperatorClass::Binary);
- operatorClasses.emplace_back("&", false, OperatorClass::Binary);
- operatorClasses.emplace_back("^", false, OperatorClass::Binary);
- operatorClasses.emplace_back("|", false, OperatorClass::Binary);
- operatorClasses.emplace_back("? :", true, OperatorClass::Tertiary);
- operatorClasses.emplace_back("=", true, OperatorClass::Binary);
- operatorClasses.emplace_back(",", true, OperatorClass::Binary);
+ operatorClasses.emplace_back("== !=", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("&", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("^", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("|", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("? :", true, OperatorClass::Tertiary);
+ operatorClasses.emplace_back("=", true, OperatorClass::Binary);
+ operatorClasses.emplace_back(",", true, OperatorClass::Binary);
precedences.resize(OperatorClass::Tertiary + 1);
@@ -148,11 +150,12 @@ int OperatorClass::getPrecedence(Type type, IString op) {
return precedences[type][op];
}
-bool OperatorClass::getRtl(int prec) {
- return operatorClasses[prec].rtl;
-}
+bool OperatorClass::getRtl(int prec) { return operatorClasses[prec].rtl; }
-bool isIdentInit(char x) { return (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || x == '_' || x == '$'; }
+bool isIdentInit(char x) {
+ return (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || x == '_' ||
+ x == '$';
+}
bool isIdentPart(char x) { return isIdentInit(x) || (x >= '0' && x <= '9'); }
} // namespace cashew
diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h
index 78ed27933..d180ea12c 100644
--- a/src/emscripten-optimizer/parser.h
+++ b/src/emscripten-optimizer/parser.h
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-// Pure parsing. Calls methods on a Builder (template argument) to actually construct the AST
+// Pure parsing. Calls methods on a Builder (template argument) to actually
+// construct the AST
//
-// XXX All parsing methods assume they take ownership of the input string. This lets them reuse
-// parts of it. You will segfault if the input string cannot be reused and written to.
+// XXX All parsing methods assume they take ownership of the input string. This
+// lets them reuse parts of it. You will segfault if the input string cannot
+// be reused and written to.
#ifndef wasm_parser_h
#define wasm_parser_h
@@ -35,89 +37,89 @@ namespace cashew {
// common strings
-extern IString TOPLEVEL,
- DEFUN,
- BLOCK,
- VAR,
- CONST,
- CONDITIONAL,
- BINARY,
- RETURN,
- IF,
- ELSE,
- WHILE,
- DO,
- FOR,
- SEQ,
- SUB,
- CALL,
- LABEL,
- BREAK,
- CONTINUE,
- SWITCH,
- STRING,
- TRY,
- INF,
- NaN,
- LLVM_CTTZ_I32,
- UDIVMODDI4,
- UNARY_PREFIX,
- UNARY_POSTFIX,
- MATH_FROUND,
- MATH_CLZ32,
- INT64,
- INT64_CONST,
- SIMD_FLOAT32X4,
- SIMD_FLOAT64X2,
- SIMD_INT8X16,
- SIMD_INT16X8,
- SIMD_INT32X4,
- PLUS,
- MINUS,
- OR,
- AND,
- XOR,
- L_NOT,
- B_NOT,
- LT,
- GE,
- LE,
- GT,
- EQ,
- NE,
- DIV,
- MOD,
- MUL,
- RSHIFT,
- LSHIFT,
- TRSHIFT,
- HEAP8,
- HEAP16,
- HEAP32,
- HEAPF32,
- HEAPU8,
- HEAPU16,
- HEAPU32,
- HEAPF64,
- F0,
- EMPTY,
- FUNCTION,
- OPEN_PAREN,
- OPEN_BRACE,
- OPEN_CURLY,
- CLOSE_CURLY,
- COMMA,
- QUESTION,
- COLON,
- CASE,
- DEFAULT,
- DOT,
- PERIOD,
- NEW,
- ARRAY,
- OBJECT,
- THROW,
- SET;
+extern IString TOPLEVEL;
+extern IString DEFUN;
+extern IString BLOCK;
+extern IString VAR;
+extern IString CONST;
+extern IString CONDITIONAL;
+extern IString BINARY;
+extern IString RETURN;
+extern IString IF;
+extern IString ELSE;
+extern IString WHILE;
+extern IString DO;
+extern IString FOR;
+extern IString SEQ;
+extern IString SUB;
+extern IString CALL;
+extern IString LABEL;
+extern IString BREAK;
+extern IString CONTINUE;
+extern IString SWITCH;
+extern IString STRING;
+extern IString TRY;
+extern IString INF;
+extern IString NaN;
+extern IString LLVM_CTTZ_I32;
+extern IString UDIVMODDI4;
+extern IString UNARY_PREFIX;
+extern IString UNARY_POSTFIX;
+extern IString MATH_FROUND;
+extern IString MATH_CLZ32;
+extern IString INT64;
+extern IString INT64_CONST;
+extern IString SIMD_FLOAT32X4;
+extern IString SIMD_FLOAT64X2;
+extern IString SIMD_INT8X16;
+extern IString SIMD_INT16X8;
+extern IString SIMD_INT32X4;
+extern IString PLUS;
+extern IString MINUS;
+extern IString OR;
+extern IString AND;
+extern IString XOR;
+extern IString L_NOT;
+extern IString B_NOT;
+extern IString LT;
+extern IString GE;
+extern IString LE;
+extern IString GT;
+extern IString EQ;
+extern IString NE;
+extern IString DIV;
+extern IString MOD;
+extern IString MUL;
+extern IString RSHIFT;
+extern IString LSHIFT;
+extern IString TRSHIFT;
+extern IString HEAP8;
+extern IString HEAP16;
+extern IString HEAP32;
+extern IString HEAPF32;
+extern IString HEAPU8;
+extern IString HEAPU16;
+extern IString HEAPU32;
+extern IString HEAPF64;
+extern IString F0;
+extern IString EMPTY;
+extern IString FUNCTION;
+extern IString OPEN_PAREN;
+extern IString OPEN_BRACE;
+extern IString OPEN_CURLY;
+extern IString CLOSE_CURLY;
+extern IString COMMA;
+extern IString QUESTION;
+extern IString COLON;
+extern IString CASE;
+extern IString DEFAULT;
+extern IString DOT;
+extern IString PERIOD;
+extern IString NEW;
+extern IString ARRAY;
+extern IString OBJECT;
+extern IString THROW;
+extern IString SET;
extern IStringSet keywords;
@@ -126,12 +128,7 @@ extern const char *OPERATOR_INITS, *SEPARATORS;
extern int MAX_OPERATOR_SIZE, LOWEST_PREC;
struct OperatorClass {
- enum Type {
- Binary = 0,
- Prefix = 1,
- Postfix = 2,
- Tertiary = 3
- };
+ enum Type { Binary = 0, Prefix = 1, Postfix = 2, Tertiary = 3 };
IStringSet ops;
bool rtl;
@@ -150,10 +147,11 @@ extern bool isIdentPart(char x);
// parser
-template<class NodeRef, class Builder>
-class Parser {
+template<class NodeRef, class Builder> class Parser {
- static bool isSpace(char x) { return x == 32 || x == 9 || x == 10 || x == 13; } /* space, tab, linefeed/newline, or return */
+ static bool isSpace(char x) {
+ return x == 32 || x == 9 || x == 10 || x == 13;
+ } /* space, tab, linefeed/newline, or return */
static void skipSpace(char*& curr) {
while (*curr) {
if (isSpace(*curr)) {
@@ -162,13 +160,16 @@ class Parser {
}
if (curr[0] == '/' && curr[1] == '/') {
curr += 2;
- while (*curr && *curr != '\n') curr++;
- if (*curr) curr++;
+ while (*curr && *curr != '\n')
+ curr++;
+ if (*curr)
+ curr++;
continue;
}
if (curr[0] == '/' && curr[1] == '*') {
curr += 2;
- while (*curr && (curr[0] != '*' || curr[1] != '/')) curr++;
+ while (*curr && (curr[0] != '*' || curr[1] != '/'))
+ curr++;
curr += 2;
continue;
}
@@ -178,7 +179,12 @@ class Parser {
static bool isDigit(char x) { return x >= '0' && x <= '9'; }
- static bool hasChar(const char* list, char x) { while (*list) if (*list++ == x) return true; return false; }
+ static bool hasChar(const char* list, char x) {
+ while (*list)
+ if (*list++ == x)
+ return true;
+ return false;
+ }
// An atomic fragment of something. Stops at a natural boundary.
enum FragType {
@@ -192,7 +198,9 @@ class Parser {
};
struct Frag {
-#ifndef _MSC_VER // MSVC does not allow unrestricted unions: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
+ // MSVC does not allow unrestricted unions:
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
+#ifndef _MSC_VER
union {
#endif
IString str;
@@ -203,12 +211,10 @@ class Parser {
int size;
FragType type;
- bool isNumber() const {
- return type == INT || type == DOUBLE;
- }
+ bool isNumber() const { return type == INT || type == DOUBLE; }
explicit Frag(char* src) {
- char *start = src;
+ char* start = src;
if (isIdentInit(*src)) {
// read an identifier or a keyword
src++;
@@ -227,15 +233,22 @@ class Parser {
} else if (isDigit(*src) || (src[0] == '.' && isDigit(src[1]))) {
if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) {
// Explicitly parse hex numbers of form "0x...", because strtod
- // supports hex number strings only in C++11, and Visual Studio 2013 does
- // not yet support that functionality.
+ // supports hex number strings only in C++11, and Visual Studio 2013
+ // does not yet support that functionality.
src += 2;
num = 0;
while (1) {
- if (*src >= '0' && *src <= '9') { num *= 16; num += *src - '0'; }
- else if (*src >= 'a' && *src <= 'f') { num *= 16; num += *src - 'a' + 10; }
- else if (*src >= 'A' && *src <= 'F') { num *= 16; num += *src - 'A' + 10; }
- else break;
+ if (*src >= '0' && *src <= '9') {
+ num *= 16;
+ num += *src - '0';
+ } else if (*src >= 'a' && *src <= 'f') {
+ num *= 16;
+ num += *src - 'a' + 10;
+ } else if (*src >= 'A' && *src <= 'F') {
+ num *= 16;
+ num += *src - 'A' + 10;
+ } else
+ break;
src++;
}
} else {
@@ -244,33 +257,69 @@ class Parser {
// asm.js must have a '.' for double values. however, we also tolerate
// uglify's tendency to emit without a '.' (and fix it later with a +).
// for valid asm.js input, the '.' should be enough, and for uglify
- // in the emscripten optimizer pipeline, we use simple_ast where INT/DOUBLE
- // is quite the same at this point anyhow
+ // in the emscripten optimizer pipeline, we use simple_ast where
+ // INT/DOUBLE is quite the same at this point anyhow
type = (std::find(start, src, '.') == src &&
(wasm::isSInteger32(num) || wasm::isUInteger32(num)))
- ? INT
- : DOUBLE;
+ ? INT
+ : DOUBLE;
assert(src > start);
} else if (hasChar(OPERATOR_INITS, *src)) {
switch (*src) {
- case '!': str = src[1] == '=' ? NE : L_NOT; break;
- case '%': str = MOD; break;
- case '&': str = AND; break;
- case '*': str = MUL; break;
- case '+': str = PLUS; break;
- case ',': str = COMMA; break;
- case '-': str = MINUS; break;
- case '.': str = PERIOD; break;
- case '/': str = DIV; break;
- case ':': str = COLON; break;
- case '<': str = src[1] == '<' ? LSHIFT : (src[1] == '=' ? LE : LT); break;
- case '=': str = src[1] == '=' ? EQ : SET; break;
- case '>': str = src[1] == '>' ? (src[2] == '>' ? TRSHIFT : RSHIFT) : (src[1] == '=' ? GE : GT); break;
- case '?': str = QUESTION; break;
- case '^': str = XOR; break;
- case '|': str = OR; break;
- case '~': str = B_NOT; break;
- default: abort();
+ case '!':
+ str = src[1] == '=' ? NE : L_NOT;
+ break;
+ case '%':
+ str = MOD;
+ break;
+ case '&':
+ str = AND;
+ break;
+ case '*':
+ str = MUL;
+ break;
+ case '+':
+ str = PLUS;
+ break;
+ case ',':
+ str = COMMA;
+ break;
+ case '-':
+ str = MINUS;
+ break;
+ case '.':
+ str = PERIOD;
+ break;
+ case '/':
+ str = DIV;
+ break;
+ case ':':
+ str = COLON;
+ break;
+ case '<':
+ str = src[1] == '<' ? LSHIFT : (src[1] == '=' ? LE : LT);
+ break;
+ case '=':
+ str = src[1] == '=' ? EQ : SET;
+ break;
+ case '>':
+ str = src[1] == '>' ? (src[2] == '>' ? TRSHIFT : RSHIFT)
+ : (src[1] == '=' ? GE : GT);
+ break;
+ case '?':
+ str = QUESTION;
+ break;
+ case '^':
+ str = XOR;
+ break;
+ case '|':
+ str = OR;
+ break;
+ case '~':
+ str = B_NOT;
+ break;
+ default:
+ abort();
}
size = strlen(str.str);
#ifndef NDEBUG
@@ -289,10 +338,10 @@ class Parser {
src[1] = temp;
src++;
} else if (*src == '"' || *src == '\'') {
- char *end = strchr(src+1, *src);
+ char* end = strchr(src + 1, *src);
*end = 0;
- str.set(src+1);
- src = end+1;
+ str.set(src + 1);
+ src = end + 1;
type = STRING;
} else {
dump("frag parsing", src);
@@ -304,7 +353,9 @@ class Parser {
struct ExpressionElement {
bool isNode;
-#ifndef _MSC_VER // MSVC does not allow unrestricted unions: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
+ // MSVC does not allow unrestricted unions:
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
+#ifndef _MSC_VER
union {
#endif
NodeRef node;
@@ -326,13 +377,15 @@ class Parser {
};
// This is a list of the current stack of node-operator-node-operator-etc.
- // this works by each parseExpression call appending to the vector; then recursing out, and the toplevel sorts it all
+ // this works by each parseExpression call appending to the vector; then
+ // recursing out, and the toplevel sorts it all
typedef std::vector<ExpressionElement> ExpressionParts;
std::vector<ExpressionParts> expressionPartsStack;
- // Parses an element in a list of such elements, e.g. list of statements in a block, or list of parameters in a call
- NodeRef parseElement(char*& src, const char* seps=";") {
- //dump("parseElement", src);
+ // Parses an element in a list of such elements, e.g. list of statements in a
+ // block, or list of parameters in a call
+ NodeRef parseElement(char*& src, const char* seps = ";") {
+ // dump("parseElement", src);
skipSpace(src);
Frag frag(src);
src += frag.size;
@@ -349,44 +402,67 @@ class Parser {
return parseExpression(parseFrag(frag), src, seps);
}
case SEPARATOR: {
- if (frag.str == OPEN_PAREN) return parseExpression(parseAfterParen(src), src, seps);
- if (frag.str == OPEN_BRACE) return parseExpression(parseAfterBrace(src), src, seps);
- if (frag.str == OPEN_CURLY) return parseExpression(parseAfterCurly(src), src, seps);
+ if (frag.str == OPEN_PAREN)
+ return parseExpression(parseAfterParen(src), src, seps);
+ if (frag.str == OPEN_BRACE)
+ return parseExpression(parseAfterBrace(src), src, seps);
+ if (frag.str == OPEN_CURLY)
+ return parseExpression(parseAfterCurly(src), src, seps);
abort();
}
case OPERATOR: {
return parseExpression(frag.str, src, seps);
}
- default: /* dump("parseElement", src); printf("bad frag type: %d\n", frag.type); */ abort();
+ default:
+ /* dump("parseElement", src); printf("bad frag type: %d\n",frag.type);
+ */
+ abort();
}
return nullptr;
}
NodeRef parseFrag(Frag& frag) {
switch (frag.type) {
- case IDENT: return Builder::makeName(frag.str);
- case STRING: return Builder::makeString(frag.str);
- case INT: return Builder::makeInt(uint32_t(frag.num));
- case DOUBLE: return Builder::makeDouble(frag.num);
- default: abort();
+ case IDENT:
+ return Builder::makeName(frag.str);
+ case STRING:
+ return Builder::makeString(frag.str);
+ case INT:
+ return Builder::makeInt(uint32_t(frag.num));
+ case DOUBLE:
+ return Builder::makeDouble(frag.num);
+ default:
+ abort();
}
return nullptr;
}
NodeRef parseAfterKeyword(Frag& frag, char*& src, const char* seps) {
skipSpace(src);
- if (frag.str == FUNCTION) return parseFunction(src, seps);
- else if (frag.str == VAR) return parseVar(src, seps, false);
- else if (frag.str == CONST) return parseVar(src, seps, true);
- else if (frag.str == RETURN) return parseReturn(src, seps);
- else if (frag.str == IF) return parseIf(src, seps);
- else if (frag.str == DO) return parseDo(src, seps);
- else if (frag.str == WHILE) return parseWhile(src, seps);
- else if (frag.str == BREAK) return parseBreak(src, seps);
- else if (frag.str == CONTINUE) return parseContinue(src, seps);
- else if (frag.str == SWITCH) return parseSwitch(src, seps);
- else if (frag.str == NEW) return parseNew(src, seps);
- else if (frag.str == FOR) return parseFor(src, seps);
+ if (frag.str == FUNCTION)
+ return parseFunction(src, seps);
+ else if (frag.str == VAR)
+ return parseVar(src, seps, false);
+ else if (frag.str == CONST)
+ return parseVar(src, seps, true);
+ else if (frag.str == RETURN)
+ return parseReturn(src, seps);
+ else if (frag.str == IF)
+ return parseIf(src, seps);
+ else if (frag.str == DO)
+ return parseDo(src, seps);
+ else if (frag.str == WHILE)
+ return parseWhile(src, seps);
+ else if (frag.str == BREAK)
+ return parseBreak(src, seps);
+ else if (frag.str == CONTINUE)
+ return parseContinue(src, seps);
+ else if (frag.str == SWITCH)
+ return parseSwitch(src, seps);
+ else if (frag.str == NEW)
+ return parseNew(src, seps);
+ else if (frag.str == FOR)
+ return parseFor(src, seps);
dump(frag.str.str, src);
abort();
return nullptr;
@@ -406,13 +482,15 @@ class Parser {
src++;
while (1) {
skipSpace(src);
- if (*src == ')') break;
+ if (*src == ')')
+ break;
Frag arg(src);
assert(arg.type == IDENT);
src += arg.size;
Builder::appendArgumentToFunction(ret, arg.str);
skipSpace(src);
- if (*src == ')') break;
+ if (*src == ')')
+ break;
if (*src == ',') {
src++;
continue;
@@ -429,7 +507,8 @@ class Parser {
NodeRef ret = Builder::makeVar(is_const);
while (1) {
skipSpace(src);
- if (*src == ';') break;
+ if (*src == ';')
+ break;
Frag name(src);
assert(name.type == IDENT);
NodeRef value;
@@ -442,7 +521,8 @@ class Parser {
}
Builder::appendToVar(ret, name.str, value);
skipSpace(src);
- if (*src == ';') break;
+ if (*src == ';')
+ break;
if (*src == ',') {
src++;
continue;
@@ -458,7 +538,8 @@ class Parser {
NodeRef value = !hasChar(seps, *src) ? parseElement(src, seps) : nullptr;
skipSpace(src);
assert(hasChar(seps, *src));
- if (*src == ';') src++;
+ if (*src == ';')
+ src++;
return Builder::makeReturn(value);
}
@@ -516,14 +597,16 @@ class Parser {
NodeRef parseBreak(char*& src, const char* seps) {
skipSpace(src);
Frag next(src);
- if (next.type == IDENT) src += next.size;
+ if (next.type == IDENT)
+ src += next.size;
return Builder::makeBreak(next.type == IDENT ? next.str : IString());
}
NodeRef parseContinue(char*& src, const char* seps) {
skipSpace(src);
Frag next(src);
- if (next.type == IDENT) src += next.size;
+ if (next.type == IDENT)
+ src += next.size;
return Builder::makeContinue(next.type == IDENT ? next.str : IString());
}
@@ -535,7 +618,8 @@ class Parser {
while (1) {
// find all cases and possibly a default
skipSpace(src);
- if (*src == '}') break;
+ if (*src == '}')
+ break;
Frag next(src);
if (next.type == KEYWORD) {
if (next.str == CASE) {
@@ -575,12 +659,14 @@ class Parser {
src++;
continue;
}
- // otherwise, may be some keyword that happens to start a block (e.g. case 1: _return_ 5)
+ // otherwise, may be some keyword that happens to start a block (e.g.
+ // case 1: _return_ 5)
}
// not case X: or default: or }, so must be some code
skipSpace(src);
bool explicitBlock = *src == '{';
- NodeRef subBlock = explicitBlock ? parseBracketedBlock(src) : parseBlock(src, ";}", CASE, DEFAULT);
+ NodeRef subBlock = explicitBlock ? parseBracketedBlock(src)
+ : parseBlock(src, ";}", CASE, DEFAULT);
Builder::appendCodeToSwitch(ret, subBlock, explicitBlock);
}
skipSpace(src);
@@ -595,34 +681,40 @@ class Parser {
NodeRef parseAfterIdent(Frag& frag, char*& src, const char* seps) {
skipSpace(src);
- if (*src == '(') return parseExpression(parseCall(parseFrag(frag), src), src, seps);
- if (*src == '[') return parseExpression(parseIndexing(parseFrag(frag), src), src, seps);
+ if (*src == '(')
+ return parseExpression(parseCall(parseFrag(frag), src), src, seps);
+ if (*src == '[')
+ return parseExpression(parseIndexing(parseFrag(frag), src), src, seps);
if (*src == ':' && expressionPartsStack.back().size() == 0) {
src++;
skipSpace(src);
NodeRef inner;
- if (*src == '{') { // context lets us know this is not an object, but a block
+ if (*src == '{') {
+ // context lets us know this is not an object, but a block
inner = parseBracketedBlock(src);
} else {
inner = parseElement(src, seps);
}
return Builder::makeLabel(frag.str, inner);
}
- if (*src == '.') return parseExpression(parseDotting(parseFrag(frag), src), src, seps);
+ if (*src == '.')
+ return parseExpression(parseDotting(parseFrag(frag), src), src, seps);
return parseExpression(parseFrag(frag), src, seps);
}
NodeRef parseCall(NodeRef target, char*& src) {
- expressionPartsStack.resize(expressionPartsStack.size()+1);
+ expressionPartsStack.resize(expressionPartsStack.size() + 1);
assert(*src == '(');
src++;
NodeRef ret = Builder::makeCall(target);
while (1) {
skipSpace(src);
- if (*src == ')') break;
+ if (*src == ')')
+ break;
Builder::appendToCall(ret, parseElement(src, ",)"));
skipSpace(src);
- if (*src == ')') break;
+ if (*src == ')')
+ break;
if (*src == ',') {
src++;
continue;
@@ -636,7 +728,7 @@ class Parser {
}
NodeRef parseIndexing(NodeRef target, char*& src) {
- expressionPartsStack.resize(expressionPartsStack.size()+1);
+ expressionPartsStack.resize(expressionPartsStack.size() + 1);
assert(*src == '[');
src++;
NodeRef ret = Builder::makeIndexing(target, parseElement(src, "]"));
@@ -658,7 +750,7 @@ class Parser {
}
NodeRef parseAfterParen(char*& src) {
- expressionPartsStack.resize(expressionPartsStack.size()+1);
+ expressionPartsStack.resize(expressionPartsStack.size() + 1);
skipSpace(src);
NodeRef ret = parseElement(src, ")");
skipSpace(src);
@@ -670,16 +762,18 @@ class Parser {
}
NodeRef parseAfterBrace(char*& src) {
- expressionPartsStack.resize(expressionPartsStack.size()+1);
+ expressionPartsStack.resize(expressionPartsStack.size() + 1);
NodeRef ret = Builder::makeArray();
while (1) {
skipSpace(src);
assert(*src);
- if (*src == ']') break;
+ if (*src == ']')
+ break;
NodeRef element = parseElement(src, ",]");
Builder::appendToArray(ret, element);
skipSpace(src);
- if (*src == ']') break;
+ if (*src == ']')
+ break;
if (*src == ',') {
src++;
continue;
@@ -691,12 +785,13 @@ class Parser {
}
NodeRef parseAfterCurly(char*& src) {
- expressionPartsStack.resize(expressionPartsStack.size()+1);
+ expressionPartsStack.resize(expressionPartsStack.size() + 1);
NodeRef ret = Builder::makeObject();
while (1) {
skipSpace(src);
assert(*src);
- if (*src == '}') break;
+ if (*src == '}')
+ break;
Frag key(src);
assert(key.type == IDENT || key.type == STRING);
src += key.size;
@@ -706,7 +801,8 @@ class Parser {
NodeRef value = parseElement(src, ",}");
Builder::appendToObject(ret, key.str, value);
skipSpace(src);
- if (*src == '}') break;
+ if (*src == '}')
+ break;
if (*src == ',') {
src++;
continue;
@@ -735,12 +831,13 @@ class Parser {
if (op == PERIOD) {
return Builder::makeDot(left, right);
} else {
- return Builder::makeBinary(left, op ,right);
+ return Builder::makeBinary(left, op, right);
}
}
- NodeRef parseExpression(ExpressionElement initial, char*&src, const char* seps) {
- //dump("parseExpression", src);
+ NodeRef
+ parseExpression(ExpressionElement initial, char*& src, const char* seps) {
+ // dump("parseExpression", src);
ExpressionParts& parts = expressionPartsStack.back();
skipSpace(src);
if (*src == 0 || hasChar(seps, *src)) {
@@ -771,55 +868,77 @@ class Parser {
parts.push_back(initial);
}
NodeRef last = parseElement(src, seps);
- if (!top) return last;
+ if (!top)
+ return last;
{
- ExpressionParts& parts = expressionPartsStack.back(); // |parts| may have been invalidated by that call
+ // |parts| may have been invalidated by that call
+ ExpressionParts& parts = expressionPartsStack.back();
// we are the toplevel. sort it all out
// collapse right to left, highest priority first
- //dumpParts(parts, 0);
+ // dumpParts(parts, 0);
for (auto& ops : operatorClasses) {
if (ops.rtl) {
// right to left
- for (int i = parts.size()-1; i >= 0; i--) {
- if (parts[i].isNode) continue;
+ for (int i = parts.size() - 1; i >= 0; i--) {
+ if (parts[i].isNode)
+ continue;
IString op = parts[i].getOp();
- if (!ops.ops.has(op)) continue;
- if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size()-1) {
- parts[i] = makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode());
+ if (!ops.ops.has(op))
+ continue;
+ if (ops.type == OperatorClass::Binary && i > 0 &&
+ i < (int)parts.size() - 1) {
+ parts[i] =
+ makeBinary(parts[i - 1].getNode(), op, parts[i + 1].getNode());
parts.erase(parts.begin() + i + 1);
parts.erase(parts.begin() + i - 1);
- } else if (ops.type == OperatorClass::Prefix && i < (int)parts.size()-1) {
- if (i > 0 && parts[i-1].isNode) continue; // cannot apply prefix operator if it would join two nodes
- parts[i] = Builder::makePrefix(op, parts[i+1].getNode());
+ } else if (ops.type == OperatorClass::Prefix &&
+ i < (int)parts.size() - 1) {
+ if (i > 0 && parts[i - 1].isNode)
+ // cannot apply prefix operator if it would join two nodes
+ continue;
+ parts[i] = Builder::makePrefix(op, parts[i + 1].getNode());
parts.erase(parts.begin() + i + 1);
} else if (ops.type == OperatorClass::Tertiary) {
// we must be at X ? Y : Z
// ^
- //dumpParts(parts, i);
- if (op != COLON) continue;
- assert(i < (int)parts.size()-1 && i >= 3);
- if (parts[i-2].getOp() != QUESTION) continue; // e.g. x ? y ? 1 : 0 : 2
- parts[i-3] = Builder::makeConditional(parts[i-3].getNode(), parts[i-1].getNode(), parts[i+1].getNode());
+ // dumpParts(parts, i);
+ if (op != COLON)
+ continue;
+ assert(i < (int)parts.size() - 1 && i >= 3);
+ if (parts[i - 2].getOp() != QUESTION)
+ continue; // e.g. x ? y ? 1 : 0 : 2
+ parts[i - 3] = Builder::makeConditional(parts[i - 3].getNode(),
+ parts[i - 1].getNode(),
+ parts[i + 1].getNode());
parts.erase(parts.begin() + i - 2, parts.begin() + i + 2);
- i = parts.size(); // basically a reset, due to things like x ? y ? 1 : 0 : 2
+ // basically a reset, due to things like x ? y ? 1 : 0 : 2
+ i = parts.size();
} // TODO: postfix
}
} else {
// left to right
for (int i = 0; i < (int)parts.size(); i++) {
- if (parts[i].isNode) continue;
+ if (parts[i].isNode)
+ continue;
IString op = parts[i].getOp();
- if (!ops.ops.has(op)) continue;
- if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size()-1) {
- parts[i] = makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode());
+ if (!ops.ops.has(op))
+ continue;
+ if (ops.type == OperatorClass::Binary && i > 0 &&
+ i < (int)parts.size() - 1) {
+ parts[i] =
+ makeBinary(parts[i - 1].getNode(), op, parts[i + 1].getNode());
parts.erase(parts.begin() + i + 1);
parts.erase(parts.begin() + i - 1);
i--;
- } else if (ops.type == OperatorClass::Prefix && i < (int)parts.size()-1) {
- if (i > 0 && parts[i-1].isNode) continue; // cannot apply prefix operator if it would join two nodes
- parts[i] = Builder::makePrefix(op, parts[i+1].getNode());
+ } else if (ops.type == OperatorClass::Prefix &&
+ i < (int)parts.size() - 1) {
+ if (i > 0 && parts[i - 1].isNode)
+ // cannot apply prefix operator if it would join two nodes
+ continue;
+ parts[i] = Builder::makePrefix(op, parts[i + 1].getNode());
parts.erase(parts.begin() + i + 1);
- i = std::max(i-2, 0); // allow a previous prefix operator to cascade
+ // allow a previous prefix operator to cascade
+ i = std::max(i - 2, 0);
} // TODO: tertiary, postfix
}
}
@@ -831,25 +950,33 @@ class Parser {
}
}
- // Parses a block of code (e.g. a bunch of statements inside {,}, or the top level of o file)
- NodeRef parseBlock(char*& src, const char* seps=";", IString keywordSep1=IString(), IString keywordSep2=IString()) {
+ // Parses a block of code (e.g. a bunch of statements inside {,}, or the top
+ // level of o file)
+ NodeRef parseBlock(char*& src,
+ const char* seps = ";",
+ IString keywordSep1 = IString(),
+ IString keywordSep2 = IString()) {
NodeRef block = Builder::makeBlock();
- //dump("parseBlock", src);
+ // dump("parseBlock", src);
while (1) {
skipSpace(src);
- if (*src == 0) break;
+ if (*src == 0)
+ break;
if (*src == ';') {
src++; // skip a statement in this block
continue;
}
- if (hasChar(seps, *src)) break;
+ if (hasChar(seps, *src))
+ break;
if (!!keywordSep1) {
Frag next(src);
- if (next.type == KEYWORD && next.str == keywordSep1) break;
+ if (next.type == KEYWORD && next.str == keywordSep1)
+ break;
}
if (!!keywordSep2) {
Frag next(src);
- if (next.type == KEYWORD && next.str == keywordSep2) break;
+ if (next.type == KEYWORD && next.str == keywordSep2)
+ break;
}
NodeRef element = parseElementOrStatement(src, seps);
Builder::appendToBlock(block, element);
@@ -861,25 +988,29 @@ class Parser {
skipSpace(src);
assert(*src == '{');
src++;
- NodeRef block = parseBlock(src, ";}"); // the two are not symmetrical, ; is just internally separating, } is the final one - parseBlock knows all this
+ // the two are not symmetrical, ; is just internally separating, } is the
+ // final one - parseBlock knows all this
+ NodeRef block = parseBlock(src, ";}");
assert(*src == '}');
src++;
return block;
}
- NodeRef parseElementOrStatement(char*& src, const char *seps) {
+ NodeRef parseElementOrStatement(char*& src, const char* seps) {
skipSpace(src);
if (*src == ';') {
src++;
- return Builder::makeBlock(); // we don't need the brackets here, but oh well
+ // we don't need the brackets here, but oh well
+ return Builder::makeBlock();
}
if (*src == '{') { // detect a trivial {} in a statement context
- char *before = src;
+ char* before = src;
src++;
skipSpace(src);
if (*src == '}') {
src++;
- return Builder::makeBlock(); // we don't need the brackets here, but oh well
+ // we don't need the brackets here, but oh well
+ return Builder::makeBlock();
}
src = before;
}
@@ -892,9 +1023,10 @@ class Parser {
return ret;
}
- NodeRef parseMaybeBracketed(char*& src, const char *seps) {
+ NodeRef parseMaybeBracketed(char*& src, const char* seps) {
skipSpace(src);
- return *src == '{' ? parseBracketedBlock(src) : parseElementOrStatement(src, seps);
+ return *src == '{' ? parseBracketedBlock(src)
+ : parseElementOrStatement(src, seps);
}
NodeRef parseParenned(char*& src) {
@@ -910,13 +1042,15 @@ class Parser {
// Debugging
- char *allSource = nullptr;
+ char* allSource = nullptr;
int allSize = 0;
- static void dump(const char *where, char* curr) {
+ static void dump(const char* where, char* curr) {
/*
printf("%s:\n=============\n", where);
- for (int i = 0; i < allSize; i++) printf("%c", allSource[i] ? allSource[i] : '?');
+ for (int i = 0; i < allSize; i++)
+ printf("%c", allSource[i] ? allSource[i] :
+ '?');
printf("\n");
for (int i = 0; i < (curr - allSource); i++) printf(" ");
printf("^\n=============\n");
@@ -927,20 +1061,19 @@ class Parser {
while (*curr) {
if (*curr == '\n') {
newlinesLeft--;
- if (newlinesLeft == 0) break;
+ if (newlinesLeft == 0)
+ break;
}
charsLeft--;
- if (charsLeft == 0) break;
+ if (charsLeft == 0)
+ break;
fprintf(stderr, "%c", *curr++);
}
fprintf(stderr, "\n\n");
}
public:
-
- Parser() {
- expressionPartsStack.resize(1);
- }
+ Parser() { expressionPartsStack.resize(1); }
// Highest-level parsing, as of a JavaScript script file.
NodeRef parseToplevel(char* src) {
diff --git a/src/emscripten-optimizer/simple_ast.cpp b/src/emscripten-optimizer/simple_ast.cpp
index 7575cc6f7..5853b3289 100644
--- a/src/emscripten-optimizer/simple_ast.cpp
+++ b/src/emscripten-optimizer/simple_ast.cpp
@@ -20,37 +20,29 @@ namespace cashew {
// Ref methods
-Ref& Ref::operator[](unsigned x) {
- return (*get())[x];
-}
+Ref& Ref::operator[](unsigned x) { return (*get())[x]; }
-Ref& Ref::operator[](IString x) {
- return (*get())[x];
-}
+Ref& Ref::operator[](IString x) { return (*get())[x]; }
-bool Ref::operator==(const char *str) {
+bool Ref::operator==(const char* str) {
return get()->isString() && !strcmp(get()->str.str, str);
}
-bool Ref::operator!=(const char *str) {
+bool Ref::operator!=(const char* str) {
return get()->isString() ? !!strcmp(get()->str.str, str) : true;
}
-bool Ref::operator==(const IString &str) {
+bool Ref::operator==(const IString& str) {
return get()->isString() && get()->str == str;
}
-bool Ref::operator!=(const IString &str) {
+bool Ref::operator!=(const IString& str) {
return get()->isString() && get()->str != str;
}
-bool Ref::operator==(Ref other) {
- return **this == *other;
-}
+bool Ref::operator==(Ref other) { return **this == *other; }
-bool Ref::operator!() {
- return !get() || get()->isNull();
-}
+bool Ref::operator!() { return !get() || get()->isNull(); }
// Arena
@@ -80,9 +72,13 @@ AssignName* Value::asAssignName() {
return static_cast<AssignName*>(this);
}
-void Value::stringify(std::ostream &os, bool pretty) {
+void Value::stringify(std::ostream& os, bool pretty) {
static int indent = 0;
- #define indentify() { for (int i_ = 0; i_ < indent; i_++) os << " "; }
+#define indentify() \
+ { \
+ for (int i_ = 0; i_ < indent; i_++) \
+ os << " "; \
+ }
switch (type) {
case String: {
if (str.str) {
@@ -93,7 +89,8 @@ void Value::stringify(std::ostream &os, bool pretty) {
break;
}
case Number: {
- os << std::setprecision(17) << num; // doubles can have 17 digits of precision
+ // doubles can have 17 digits of precision
+ os << std::setprecision(17) << num;
break;
}
case Array: {
@@ -108,8 +105,10 @@ void Value::stringify(std::ostream &os, bool pretty) {
}
for (size_t i = 0; i < arr->size(); i++) {
if (i > 0) {
- if (pretty) os << "," << std::endl;
- else os << ", ";
+ if (pretty)
+ os << "," << std::endl;
+ else
+ os << ", ";
}
indentify();
(*arr)[i]->stringify(os, pretty);
@@ -142,7 +141,8 @@ void Value::stringify(std::ostream &os, bool pretty) {
first = false;
} else {
os << ", ";
- if (pretty) os << std::endl;
+ if (pretty)
+ os << std::endl;
}
indentify();
os << '"' << i.first.c_str() << "\": ";
@@ -176,10 +176,12 @@ void Value::stringify(std::ostream &os, bool pretty) {
// dump
-void dump(const char *str, Ref node, bool pretty) {
+void dump(const char* str, Ref node, bool pretty) {
std::cerr << str << ": ";
- if (!!node) node->stringify(std::cerr, pretty);
- else std::cerr << "(nullptr)";
+ if (!!node)
+ node->stringify(std::cerr, pretty);
+ else
+ std::cerr << "(nullptr)";
std::cerr << std::endl;
}
diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h
index 81d20e612..e4f2c1f86 100644
--- a/src/emscripten-optimizer/simple_ast.h
+++ b/src/emscripten-optimizer/simple_ast.h
@@ -33,10 +33,10 @@
#include <unordered_set>
#include <vector>
+#include "mixed_arena.h"
#include "parser.h"
#include "snprintf.h"
#include "support/safe_integer.h"
-#include "mixed_arena.h"
#define err(str) fprintf(stderr, str "\n");
#define errv(str, ...) fprintf(stderr, str "\n", __VA_ARGS__);
@@ -47,13 +47,13 @@ namespace cashew {
struct Value;
struct Ref;
-void dump(const char *str, Ref node, bool pretty=false);
+void dump(const char* str, Ref node, bool pretty = false);
// Reference to a value, plus some operators for convenience
struct Ref {
Value* inst;
- Ref(Value *v=nullptr) : inst(v) {}
+ Ref(Value* v = nullptr) : inst(v) {}
Value* get() { return inst; }
@@ -63,11 +63,16 @@ struct Ref {
Ref& operator[](IString x);
// special conveniences
- bool operator==(const char *str); // comparison to string, which is by value
- bool operator!=(const char *str);
- bool operator==(const IString &str);
- bool operator!=(const IString &str);
- bool operator==(double d) { abort(); return false; } // prevent Ref == number, which is potentially ambiguous; use ->getNumber() == number
+ bool operator==(const char* str); // comparison to string, which is by value
+ bool operator!=(const char* str);
+ bool operator==(const IString& str);
+ bool operator!=(const IString& str);
+ // prevent Ref == number, which is potentially ambiguous; use ->getNumber() ==
+ // number
+ bool operator==(double d) {
+ abort();
+ return false;
+ }
bool operator==(Ref other);
bool operator!(); // check if null, in effect
};
@@ -78,8 +83,7 @@ struct Ref {
// receive an allocator, they all use the global one anyhow
class GlobalMixedArena : public MixedArena {
public:
- template<class T>
- T* alloc() {
+ template<class T> T* alloc() {
auto* ret = static_cast<T*>(allocSpace(sizeof(T), alignof(T)));
new (ret) T();
return ret;
@@ -92,7 +96,8 @@ class ArrayStorage : public ArenaVectorBase<ArrayStorage, Ref> {
public:
void allocate(size_t size) {
allocatedElements = size;
- data = static_cast<Ref*>(arena.allocSpace(sizeof(Ref) * allocatedElements, alignof(Ref)));
+ data = static_cast<Ref*>(
+ arena.allocSpace(sizeof(Ref) * allocatedElements, alignof(Ref)));
}
};
@@ -116,7 +121,9 @@ struct Value {
typedef std::unordered_map<IString, Ref> ObjectStorage;
-#ifdef _MSC_VER // MSVC does not allow unrestricted unions: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
+ // MSVC does not allow unrestricted unions:
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
+#ifdef _MSC_VER
IString str;
#endif
union { // TODO: optimize
@@ -124,44 +131,41 @@ struct Value {
IString str;
#endif
double num;
- ArrayStorage *arr;
+ ArrayStorage* arr;
bool boo;
- ObjectStorage *obj;
+ ObjectStorage* obj;
Ref ref;
};
// constructors all copy their input
Value() {}
- explicit Value(const char *s) {
- setString(s);
- }
- explicit Value(double n) {
- setNumber(n);
- }
- explicit Value(ArrayStorage &a) {
+ explicit Value(const char* s) { setString(s); }
+ explicit Value(double n) { setNumber(n); }
+ explicit Value(ArrayStorage& a) {
setArray();
*arr = a;
}
- // no bool constructor - would endanger the double one (int might convert the wrong way)
+ // no bool constructor - would endanger the double one (int might convert the
+ // wrong way)
- ~Value() {
- free();
- }
+ ~Value() { free(); }
void free() {
- if (type == Array) { arr->clear(); }
- else if (type == Object) delete obj;
+ if (type == Array) {
+ arr->clear();
+ } else if (type == Object)
+ delete obj;
type = Null;
num = 0;
}
- Value& setString(const char *s) {
+ Value& setString(const char* s) {
free();
type = String;
str.set(s);
return *this;
}
- Value& setString(const IString &s) {
+ Value& setString(const IString& s) {
free();
type = String;
str.set(s);
@@ -173,14 +177,14 @@ struct Value {
num = n;
return *this;
}
- Value& setArray(ArrayStorage &a) {
+ Value& setArray(ArrayStorage& a) {
free();
type = Array;
arr = arena.alloc<ArrayStorage>();
*arr = a;
return *this;
}
- Value& setArray(size_t size_hint=0) {
+ Value& setArray(size_t size_hint = 0) {
free();
type = Array;
arr = arena.alloc<ArrayStorage>();
@@ -192,7 +196,8 @@ struct Value {
type = Null;
return *this;
}
- Value& setBool(bool b) { // Bool in the name, as otherwise might overload over int
+ // Bool in the name, as otherwise might overload over int
+ Value& setBool(bool b) {
free();
type = Bool;
boo = b;
@@ -209,22 +214,21 @@ struct Value {
bool isString() { return type == String; }
bool isNumber() { return type == Number; }
- bool isArray() { return type == Array; }
- bool isNull() { return type == Null; }
- bool isBool() { return type == Bool; }
+ bool isArray() { return type == Array; }
+ bool isNull() { return type == Null; }
+ bool isBool() { return type == Bool; }
bool isObject() { return type == Object; }
bool isAssign() { return type == Assign_; }
bool isAssignName() { return type == AssignName_; }
- bool isBool(bool b) { return type == Bool && b == boo; } // avoid overloading == as it might overload over int
+ // avoid overloading == as it might overload over int
+ bool isBool(bool b) { return type == Bool && b == boo; }
// convenience function to check if something is an array and
// also has a certain string as the first element. This is a
// very common operation as the first element defines the node
// type for most ast nodes
- bool isArray(IString name) {
- return isArray() && (*this)[0] == name;
- }
+ bool isArray(IString name) { return isArray() && (*this)[0] == name; }
const char* getCString() {
assert(isString());
@@ -282,7 +286,8 @@ struct Value {
}
bool operator==(const Value& other) {
- if (type != other.type) return false;
+ if (type != other.type)
+ return false;
switch (other.type) {
case String:
return str == other.str;
@@ -303,17 +308,22 @@ struct Value {
}
char* parse(char* curr) {
- #define is_json_space(x) (x == 32 || x == 9 || x == 10 || x == 13) /* space, tab, linefeed/newline, or return */
- #define skip() { while (*curr && is_json_space(*curr)) curr++; }
+ /* space, tab, linefeed/newline, or return */
+#define is_json_space(x) (x == 32 || x == 9 || x == 10 || x == 13)
+#define skip() \
+ { \
+ while (*curr && is_json_space(*curr)) \
+ curr++; \
+ }
skip();
if (*curr == '"') {
// String
curr++;
- char *close = strchr(curr, '"');
+ char* close = strchr(curr, '"');
assert(close);
*close = 0; // end this string, and reuse it straight from the input
setString(curr);
- curr = close+1;
+ curr = close + 1;
} else if (*curr == '[') {
// Array
curr++;
@@ -324,7 +334,8 @@ struct Value {
arr->push_back(temp);
curr = temp->parse(curr);
skip();
- if (*curr == ']') break;
+ if (*curr == ']')
+ break;
assert(*curr == ',');
curr++;
skip();
@@ -353,11 +364,11 @@ struct Value {
while (*curr != '}') {
assert(*curr == '"');
curr++;
- char *close = strchr(curr, '"');
+ char* close = strchr(curr, '"');
assert(close);
*close = 0; // end this string, and reuse it straight from the input
IString key(curr);
- curr = close+1;
+ curr = close + 1;
skip();
assert(*curr == ':');
curr++;
@@ -366,7 +377,8 @@ struct Value {
curr = value->parse(curr);
(*obj)[key] = value;
skip();
- if (*curr == '}') break;
+ if (*curr == '}')
+ break;
assert(*curr == ',');
curr++;
skip();
@@ -374,14 +386,14 @@ struct Value {
curr++;
} else {
// Number
- char *after;
+ char* after;
setNumber(strtod(curr, &after));
curr = after;
}
return curr;
}
- void stringify(std::ostream &os, bool pretty=false);
+ void stringify(std::ostream& os, bool pretty = false);
// String operations
@@ -394,14 +406,13 @@ struct Value {
return arr->size();
}
- bool empty() {
- return size() == 0;
- }
+ bool empty() { return size() == 0; }
void setSize(size_t size) {
assert(isArray());
auto old = arr->size();
- if (old != size) arr->resize(size);
+ if (old != size)
+ arr->resize(size);
if (old < size) {
for (auto i = old; i < size; i++) {
(*arr)[i] = arena.alloc<Value>();
@@ -428,7 +439,8 @@ struct Value {
Ref back() {
assert(isArray());
- if (arr->size() == 0) return nullptr;
+ if (arr->size() == 0)
+ return nullptr;
return arr->back();
}
@@ -440,12 +452,13 @@ struct Value {
int indexOf(Ref other) {
assert(isArray());
for (size_t i = 0; i < arr->size(); i++) {
- if (other == (*arr)[i]) return i;
+ if (other == (*arr)[i])
+ return i;
}
return -1;
}
- Ref map(std::function<Ref (Ref node)> func) {
+ Ref map(std::function<Ref(Ref node)> func) {
assert(isArray());
Ref ret = arena.alloc<Value>();
ret->setArray();
@@ -455,13 +468,14 @@ struct Value {
return ret;
}
- Ref filter(std::function<bool (Ref node)> func) {
+ Ref filter(std::function<bool(Ref node)> func) {
assert(isArray());
Ref ret = arena.alloc<Value>();
ret->setArray();
for (size_t i = 0; i < arr->size(); i++) {
Ref curr = (*arr)[i];
- if (func(curr)) ret->push_back(curr);
+ if (func(curr))
+ ret->push_back(curr);
}
return ret;
}
@@ -502,12 +516,8 @@ struct Assign : public Value {
Assign() : Assign(nullptr, nullptr) {}
- Ref& target() {
- return ref;
- }
- Ref& value() {
- return value_;
- }
+ Ref& target() { return ref; }
+ Ref& value() { return value_; }
};
struct AssignName : public Value {
@@ -521,12 +531,8 @@ struct AssignName : public Value {
AssignName() : AssignName(IString(), nullptr) {}
- IString& target() {
- return target_;
- }
- Ref& value() {
- return ref;
- }
+ IString& target() { return target_; }
+ Ref& value() { return ref; }
};
// JS printing support
@@ -534,7 +540,7 @@ struct AssignName : public Value {
struct JSPrinter {
bool pretty, finalize;
- char *buffer = nullptr;
+ char* buffer = nullptr;
size_t size = 0;
size_t used = 0;
@@ -543,11 +549,10 @@ struct JSPrinter {
Ref ast;
- JSPrinter(bool pretty_, bool finalize_, Ref ast_) : pretty(pretty_), finalize(finalize_), ast(ast_) {}
+ JSPrinter(bool pretty_, bool finalize_, Ref ast_)
+ : pretty(pretty_), finalize(finalize_), ast(ast_) {}
- ~JSPrinter() {
- free(buffer);
- }
+ ~JSPrinter() { free(buffer); }
void printAst() {
print(ast);
@@ -557,7 +562,7 @@ struct JSPrinter {
// Utils
- void ensure(int safety=100) {
+ void ensure(int safety = 100) {
if (size >= used + safety) {
return;
}
@@ -569,7 +574,7 @@ struct JSPrinter {
abort();
}
} else {
- char *buf = (char*)realloc(buffer, size);
+ char* buf = (char*)realloc(buffer, size);
if (!buf) {
free(buffer);
errv("Out of memory allocating %zd bytes for output buffer!", size);
@@ -581,38 +586,45 @@ struct JSPrinter {
void emit(char c) {
maybeSpace(c);
- if (!pretty && c == '}' && buffer[used-1] == ';') used--; // optimize ;} into }, the ; is not separating anything
+ if (!pretty && c == '}' && buffer[used - 1] == ';')
+ used--; // optimize ;} into }, the ; is not separating anything
ensure(1);
buffer[used++] = c;
}
- void emit(const char *s) {
+ void emit(const char* s) {
maybeSpace(*s);
int len = strlen(s);
- ensure(len+1);
- strncpy(buffer + used, s, len+1);
+ ensure(len + 1);
+ strncpy(buffer + used, s, len + 1);
used += len;
}
void newline() {
- if (!pretty) return;
+ if (!pretty)
+ return;
emit('\n');
- for (int i = 0; i < indent; i++) emit(' ');
+ for (int i = 0; i < indent; i++)
+ emit(' ');
}
void space() {
- if (pretty) emit(' ');
+ if (pretty)
+ emit(' ');
}
void safeSpace() {
- if (pretty) emit(' ');
- else possibleSpace = true;
+ if (pretty)
+ emit(' ');
+ else
+ possibleSpace = true;
}
void maybeSpace(char s) {
if (possibleSpace) {
possibleSpace = false;
- if (isIdentPart(s)) emit(' ');
+ if (isIdentPart(s))
+ emit(' ');
}
}
@@ -620,22 +632,22 @@ struct JSPrinter {
return node->isArray() && node[0] == TOPLEVEL && node[1]->size() == 0;
}
- bool isDefun(Ref node) {
- return node->isArray() && node[0] == DEFUN;
- }
+ bool isDefun(Ref node) { return node->isArray() && node[0] == DEFUN; }
bool endsInBlock(Ref node) {
- if (node->isArray() && node[0] == BLOCK) return true;
+ if (node->isArray() && node[0] == BLOCK)
+ return true;
// Check for a label on a block
- if (node->isArray() && node[0] == LABEL && endsInBlock(node[2])) return true;
+ if (node->isArray() && node[0] == LABEL && endsInBlock(node[2]))
+ return true;
// Check for an if
- if (node->isArray() && node[0] == IF && endsInBlock(ifHasElse(node) ? node[3] : node[2])) return true;
+ if (node->isArray() && node[0] == IF &&
+ endsInBlock(ifHasElse(node) ? node[3] : node[2]))
+ return true;
return false;
}
- bool isIf(Ref node) {
- return node->isArray() && node[0] == IF;
- }
+ bool isIf(Ref node) { return node->isArray() && node[0] == IF; }
void print(Ref node) {
ensure();
@@ -658,82 +670,119 @@ struct JSPrinter {
IString type = node[0]->getIString();
switch (type.str[0]) {
case 'a': {
- if (type == ARRAY) printArray(node);
- else abort();
+ if (type == ARRAY)
+ printArray(node);
+ else
+ abort();
break;
}
case 'b': {
- if (type == BINARY) printBinary(node);
- else if (type == BLOCK) printBlock(node);
- else if (type == BREAK) printBreak(node);
- else abort();
+ if (type == BINARY)
+ printBinary(node);
+ else if (type == BLOCK)
+ printBlock(node);
+ else if (type == BREAK)
+ printBreak(node);
+ else
+ abort();
break;
}
case 'c': {
- if (type == CALL) printCall(node);
- else if (type == CONDITIONAL) printConditional(node);
- else if (type == CONTINUE) printContinue(node);
- else abort();
+ if (type == CALL)
+ printCall(node);
+ else if (type == CONDITIONAL)
+ printConditional(node);
+ else if (type == CONTINUE)
+ printContinue(node);
+ else
+ abort();
break;
}
case 'd': {
- if (type == DEFUN) printDefun(node);
- else if (type == DO) printDo(node);
- else if (type == DOT) printDot(node);
- else abort();
+ if (type == DEFUN)
+ printDefun(node);
+ else if (type == DO)
+ printDo(node);
+ else if (type == DOT)
+ printDot(node);
+ else
+ abort();
break;
}
case 'i': {
- if (type == IF) printIf(node);
- else abort();
+ if (type == IF)
+ printIf(node);
+ else
+ abort();
break;
}
case 'l': {
- if (type == LABEL) printLabel(node);
- else abort();
+ if (type == LABEL)
+ printLabel(node);
+ else
+ abort();
break;
}
case 'n': {
- if (type == NEW) printNew(node);
- else abort();
+ if (type == NEW)
+ printNew(node);
+ else
+ abort();
break;
}
case 'o': {
- if (type == OBJECT) printObject(node);
+ if (type == OBJECT)
+ printObject(node);
break;
}
case 'r': {
- if (type == RETURN) printReturn(node);
- else abort();
+ if (type == RETURN)
+ printReturn(node);
+ else
+ abort();
break;
}
case 's': {
- if (type == SUB) printSub(node);
- else if (type == SEQ) printSeq(node);
- else if (type == SWITCH) printSwitch(node);
- else if (type == STRING) printString(node);
- else abort();
+ if (type == SUB)
+ printSub(node);
+ else if (type == SEQ)
+ printSeq(node);
+ else if (type == SWITCH)
+ printSwitch(node);
+ else if (type == STRING)
+ printString(node);
+ else
+ abort();
break;
}
case 't': {
- if (type == TOPLEVEL) printToplevel(node);
- else if (type == TRY) printTry(node);
- else abort();
+ if (type == TOPLEVEL)
+ printToplevel(node);
+ else if (type == TRY)
+ printTry(node);
+ else
+ abort();
break;
}
case 'u': {
- if (type == UNARY_PREFIX) printUnaryPrefix(node);
- else abort();
+ if (type == UNARY_PREFIX)
+ printUnaryPrefix(node);
+ else
+ abort();
break;
}
case 'v': {
- if (type == VAR) printVar(node);
- else abort();
+ if (type == VAR)
+ printVar(node);
+ else
+ abort();
break;
}
case 'w': {
- if (type == WHILE) printWhile(node);
- else abort();
+ if (type == WHILE)
+ printWhile(node);
+ else
+ abort();
break;
}
default: {
@@ -744,10 +793,11 @@ struct JSPrinter {
}
// print a node, and if nothing is emitted, emit something instead
- void print(Ref node, const char *otherwise) {
+ void print(Ref node, const char* otherwise) {
auto last = used;
print(node);
- if (used == last) emit(otherwise);
+ if (used == last)
+ emit(otherwise);
}
void printStats(Ref stats) {
@@ -755,8 +805,10 @@ struct JSPrinter {
for (size_t i = 0; i < stats->size(); i++) {
Ref curr = stats[i];
if (!isNothing(curr)) {
- if (first) first = false;
- else newline();
+ if (first)
+ first = false;
+ else
+ newline();
print(curr);
if (!isDefun(curr) && !endsInBlock(curr) && !isIf(curr)) {
emit(';');
@@ -791,7 +843,8 @@ struct JSPrinter {
emit('(');
Ref args = node[2];
for (size_t i = 0; i < args->size(); i++) {
- if (i > 0) (pretty ? emit(", ") : emit(','));
+ if (i > 0)
+ (pretty ? emit(", ") : emit(','));
emit(args[i]->getCString());
}
emit(')');
@@ -820,7 +873,7 @@ struct JSPrinter {
}
void printAssignName(Ref node) {
- auto *assign = node->asAssignName();
+ auto* assign = node->asAssignName();
emit(assign->target().c_str());
space();
emit('=');
@@ -828,11 +881,9 @@ struct JSPrinter {
printChild(assign->value(), node, 1);
}
- void printName(Ref node) {
- emit(node->getCString());
- }
+ void printName(Ref node) { emit(node->getCString()); }
- static char* numToString(double d, bool finalize=true) {
+ static char* numToString(double d, bool finalize = true) {
// If this number is NaN or infinite then things are a bit tricky. In JS we
// want to eventually use `NaN` and/or `Infinity`, but neither of those
// identifiers are valid in asm.js. Instead we have to explicitly import
@@ -843,28 +894,32 @@ struct JSPrinter {
// asm.js code isn't generated any more
if (std::isnan(d)) {
if (std::signbit(d)) {
- return (char*) "-nan";
+ return (char*)"-nan";
} else {
- return (char*) "nan";
+ return (char*)"nan";
}
} else if (!std::isfinite(d)) {
if (std::signbit(d)) {
- return (char*) "-infinity";
+ return (char*)"-infinity";
} else {
- return (char*) "infinity";
+ return (char*)"infinity";
}
}
bool neg = d < 0;
- if (neg) d = -d;
+ if (neg)
+ d = -d;
// try to emit the fewest necessary characters
bool integer = fmod(d, 1) == 0;
- #define BUFFERSIZE 1000
- static char full_storage_f[BUFFERSIZE], full_storage_e[BUFFERSIZE]; // f is normal, e is scientific for float, x for integer
- static char *storage_f = full_storage_f + 1, *storage_e = full_storage_e + 1; // full has one more char, for a possible '-'
+#define BUFFERSIZE 1000
+ // f is normal, e is scientific for float, x for integer
+ static char full_storage_f[BUFFERSIZE], full_storage_e[BUFFERSIZE];
+ // full has one more char, for a possible '-'
+ static char *storage_f = full_storage_f + 1,
+ *storage_e = full_storage_e + 1;
auto err_f = std::numeric_limits<double>::quiet_NaN();
auto err_e = std::numeric_limits<double>::quiet_NaN();
for (int e = 0; e <= 1; e++) {
- char *buffer = e ? storage_e : storage_f;
+ char* buffer = e ? storage_e : storage_f;
double temp;
if (!integer) {
static char format[6];
@@ -881,10 +936,12 @@ struct JSPrinter {
format[4] = e ? 'e' : 'f';
format[5] = 0;
}
- snprintf(buffer, BUFFERSIZE-1, format, d);
+ snprintf(buffer, BUFFERSIZE - 1, format, d);
sscanf(buffer, "%lf", &temp);
- //errv("%.18f, %.18e => %s => %.18f, %.18e (%d), ", d, d, buffer, temp, temp, temp == d);
- if (temp == d) break;
+ // errv("%.18f, %.18e => %s => %.18f, %.18e (%d), ", d, d,
+ // buffer, temp, temp, temp == d);
+ if (temp == d)
+ break;
}
} else {
// integer
@@ -892,7 +949,7 @@ struct JSPrinter {
if (wasm::isUInteger64(d)) {
unsigned long long uu = wasm::toUInteger64(d);
bool asHex = e && !finalize;
- snprintf(buffer, BUFFERSIZE-1, asHex ? "0x%llx" : "%llu", uu);
+ snprintf(buffer, BUFFERSIZE - 1, asHex ? "0x%llx" : "%llu", uu);
if (asHex) {
unsigned long long tempULL;
sscanf(buffer, "%llx", &tempULL);
@@ -902,43 +959,48 @@ struct JSPrinter {
}
} else {
// too large for a machine integer, just use floats
- snprintf(buffer, BUFFERSIZE-1, e ? "%e" : "%.0f", d); // even on integers, e with a dot is useful, e.g. 1.2e+200
+ // even on integers, e with a dot is useful, e.g. 1.2e+200
+ snprintf(buffer, BUFFERSIZE - 1, e ? "%e" : "%.0f", d);
sscanf(buffer, "%lf", &temp);
}
- //errv("%.18f, %.18e => %s => %.18f, %.18e, %llu (%d)\n", d, d, buffer, temp, temp, uu, temp == d);
+ // errv("%.18f, %.18e => %s => %.18f, %.18e, %llu (%d)\n", d,
+ // d, buffer, temp, temp, uu, temp == d);
}
(e ? err_e : err_f) = fabs(temp - d);
- //errv("current attempt: %.18f => %s", d, buffer);
- //assert(temp == d);
- char *dot = strchr(buffer, '.');
+ // errv("current attempt: %.18f => %s", d, buffer);
+ // assert(temp == d);
+ char* dot = strchr(buffer, '.');
if (dot) {
// remove trailing zeros
- char *end = dot+1;
- while (*end >= '0' && *end <= '9') end++;
+ char* end = dot + 1;
+ while (*end >= '0' && *end <= '9')
+ end++;
end--;
while (*end == '0') {
- char *copy = end;
+ char* copy = end;
do {
copy[0] = copy[1];
} while (*copy++ != 0);
end--;
}
- //errv("%.18f => %s", d, buffer);
+ // errv("%.18f => %s", d, buffer);
// remove preceding zeros
while (*buffer == '0') {
- char *copy = buffer;
+ char* copy = buffer;
do {
copy[0] = copy[1];
} while (*copy++ != 0);
}
- //errv("%.18f ===> %s", d, buffer);
+ // errv("%.18f ===> %s", d, buffer);
} else if (!integer || !e) {
// no dot. try to change 12345000 => 12345e3
- char *end = strchr(buffer, 0);
+ char* end = strchr(buffer, 0);
end--;
- char *test = end;
- // remove zeros, and also doubles can use at most 24 digits, we can truncate any extras even if not zero
- while ((*test == '0' || test - buffer > 24) && test > buffer) test--;
+ char* test = end;
+ // remove zeros, and also doubles can use at most 24 digits, we can
+ // truncate any extras even if not zero
+ while ((*test == '0' || test - buffer > 24) && test > buffer)
+ test--;
int num = end - test;
if (num >= 3) {
test++;
@@ -959,10 +1021,11 @@ struct JSPrinter {
}
}
}
- //errv("..current attempt: %.18f => %s", d, buffer);
+ // errv("..current attempt: %.18f => %s", d, buffer);
}
- //fprintf(stderr, "options:\n%s\n%s\n (first? %d)\n", storage_e, storage_f, strlen(storage_e) < strlen(storage_f));
- char *ret;
+ // fprintf(stderr, "options:\n%s\n%s\n (first? %d)\n", storage_e, storage_f,
+ // strlen(storage_e) < strlen(storage_f));
+ char* ret;
if (err_e == err_f) {
ret = strlen(storage_e) < strlen(storage_f) ? storage_e : storage_f;
} else {
@@ -976,7 +1039,7 @@ struct JSPrinter {
}
void printNum(Ref node) {
- if (node->getNumber() < 0 && buffer[used-1] == '-') {
+ if (node->getNumber() < 0 && buffer[used - 1] == '-') {
emit(' '); // cannot join - and - to --, looks like the -- operator
}
emit(numToString(node->getNumber(), finalize));
@@ -1005,28 +1068,37 @@ struct JSPrinter {
}
Ref type = node[0];
if (type == BINARY || type == UNARY_PREFIX) {
- return OperatorClass::getPrecedence(type == BINARY ? OperatorClass::Binary : OperatorClass::Prefix, node[1]->getIString());
+ return OperatorClass::getPrecedence(
+ type == BINARY ? OperatorClass::Binary : OperatorClass::Prefix,
+ node[1]->getIString());
} else if (type == SEQ) {
return OperatorClass::getPrecedence(OperatorClass::Binary, COMMA);
} else if (type == CALL) {
- return parent ? OperatorClass::getPrecedence(OperatorClass::Binary, COMMA) : -1; // call arguments are split by commas, but call itself is safe
+ // call arguments are split by commas, but call itself is safe
+ return parent ? OperatorClass::getPrecedence(OperatorClass::Binary, COMMA)
+ : -1;
} else if (type == CONDITIONAL) {
return OperatorClass::getPrecedence(OperatorClass::Tertiary, QUESTION);
}
- // otherwise, this is something that fixes precedence explicitly, and we can ignore
+ // otherwise, this is something that fixes precedence explicitly, and we can
+ // ignore
return -1; // XXX
}
// check whether we need parens for the child, when rendered in the parent
- // @param childPosition -1 means it is printed to the left of parent, 0 means "anywhere", 1 means right
+ // @param childPosition -1 means it is printed to the left of parent, 0 means
+ // "anywhere", 1 means right
bool needParens(Ref parent, Ref child, int childPosition) {
int parentPrecedence = getPrecedence(parent, true);
int childPrecedence = getPrecedence(child, false);
- if (childPrecedence > parentPrecedence) return true; // child is definitely a danger
- if (childPrecedence < parentPrecedence) return false; // definitely cool
+ if (childPrecedence > parentPrecedence)
+ return true; // child is definitely a danger
+ if (childPrecedence < parentPrecedence)
+ return false; // definitely cool
// equal precedence, so associativity (rtl/ltr) is what matters
- // (except for some exceptions, where multiple operators can combine into confusion)
+ // (except for some exceptions, where multiple operators can combine into
+ // confusion)
if (parent->isArray() && parent[0] == UNARY_PREFIX) {
assert(child[0] == UNARY_PREFIX);
if ((parent[1] == PLUS || parent[1] == MINUS) && child[1] == parent[1]) {
@@ -1034,18 +1106,24 @@ struct JSPrinter {
return true;
}
}
- if (childPosition == 0) return true; // child could be anywhere, so always paren
- if (childPrecedence < 0) return false; // both precedences are safe
+ if (childPosition == 0)
+ return true; // child could be anywhere, so always paren
+ if (childPrecedence < 0)
+ return false; // both precedences are safe
// check if child is on the dangerous side
- if (OperatorClass::getRtl(parentPrecedence)) return childPosition < 0;
- else return childPosition > 0;
+ if (OperatorClass::getRtl(parentPrecedence))
+ return childPosition < 0;
+ else
+ return childPosition > 0;
}
- void printChild(Ref child, Ref parent, int childPosition=0) {
+ void printChild(Ref child, Ref parent, int childPosition = 0) {
bool parens = needParens(parent, child, childPosition);
- if (parens) emit('(');
+ if (parens)
+ emit('(');
print(child);
- if (parens) emit(')');
+ if (parens)
+ emit(')');
}
void printBinary(Ref node) {
@@ -1064,20 +1142,23 @@ struct JSPrinter {
// emit a finalized number
int last = used;
print(node[2]);
- ensure(1); // we temporarily append a 0
- char *curr = buffer + last; // ensure might invalidate
+ ensure(1); // we temporarily append a 0
+ char* curr = buffer + last; // ensure might invalidate
buffer[used] = 0;
- if (strstr(curr, "infinity")) return;
- if (strstr(curr, "nan")) return;
- if (strchr(curr, '.')) return; // already a decimal point, all good
- char *e = strchr(curr, 'e');
+ if (strstr(curr, "infinity"))
+ return;
+ if (strstr(curr, "nan"))
+ return;
+ if (strchr(curr, '.'))
+ return; // already a decimal point, all good
+ char* e = strchr(curr, 'e');
if (!e) {
emit(".0");
return;
}
ensure(3);
curr = buffer + last; // ensure might invalidate
- char *end = strchr(curr, 0);
+ char* end = strchr(curr, 0);
while (end >= e) {
end[2] = end[0];
end--;
@@ -1087,8 +1168,8 @@ struct JSPrinter {
used += 2;
return;
}
- if ((buffer[used-1] == '-' && node[1] == MINUS) ||
- (buffer[used-1] == '+' && node[1] == PLUS)) {
+ if ((buffer[used - 1] == '-' && node[1] == MINUS) ||
+ (buffer[used - 1] == '+' && node[1] == PLUS)) {
emit(' '); // cannot join - and - to --, looks like the -- operator
}
emit(node[1]->getCString());
@@ -1112,7 +1193,8 @@ struct JSPrinter {
emit('(');
Ref args = node[2];
for (size_t i = 0; i < args->size(); i++) {
- if (i > 0) (pretty ? emit(", ") : emit(','));
+ if (i > 0)
+ (pretty ? emit(", ") : emit(','));
printChild(args[i], node, 0);
}
emit(')');
@@ -1156,8 +1238,10 @@ struct JSPrinter {
auto curr = used;
printStats(c[1]);
indent--;
- if (curr != used) newline();
- else used--; // avoid the extra indentation we added tentatively
+ if (curr != used)
+ newline();
+ else
+ used--; // avoid the extra indentation we added tentatively
} else {
newline();
}
@@ -1185,7 +1269,8 @@ struct JSPrinter {
emit("var ");
Ref args = node[1];
for (size_t i = 0; i < args->size(); i++) {
- if (i > 0) (pretty ? emit(", ") : emit(','));
+ if (i > 0)
+ (pretty ? emit(", ") : emit(','));
emit(args[i][0]->getCString());
if (args[i]->size() > 1) {
space();
@@ -1292,7 +1377,8 @@ struct JSPrinter {
emit('[');
Ref args = node[1];
for (size_t i = 0; i < args->size(); i++) {
- if (i > 0) (pretty ? emit(", ") : emit(','));
+ if (i > 0)
+ (pretty ? emit(", ") : emit(','));
print(args[i]);
}
emit(']');
@@ -1309,7 +1395,7 @@ struct JSPrinter {
newline();
}
bool needQuote = false;
- const char *str;
+ const char* str;
if (args[i][0]->isArray()) {
assert(args[i][0][0] == STRING);
// A quoted string.
@@ -1319,7 +1405,7 @@ struct JSPrinter {
// Just a raw string, no quotes.
str = args[i][0]->getCString();
}
- const char *check = str;
+ const char* check = str;
while (*check) {
if (!isalnum(*check) && *check != '_' && *check != '$') {
needQuote = true;
@@ -1327,9 +1413,11 @@ struct JSPrinter {
}
check++;
}
- if (needQuote) emit('"');
+ if (needQuote)
+ emit('"');
emit(str);
- if (needQuote) emit('"');
+ if (needQuote)
+ emit('"');
emit(":");
space();
print(args[i][1]);
@@ -1340,7 +1428,6 @@ struct JSPrinter {
}
};
-
// cashew builder
class ValueBuilder {
@@ -1348,40 +1435,40 @@ class ValueBuilder {
return &arena.alloc<Value>()->setString(s);
}
- static Ref makeNull() {
- return &arena.alloc<Value>()->setNull();
- }
+ static Ref makeNull() { return &arena.alloc<Value>()->setNull(); }
public:
- static Ref makeRawArray(int size_hint=0) {
+ static Ref makeRawArray(int size_hint = 0) {
return &arena.alloc<Value>()->setArray(size_hint);
}
static Ref makeToplevel() {
- return &makeRawArray(2)->push_back(makeRawString(TOPLEVEL))
- .push_back(makeRawArray());
+ return &makeRawArray(2)
+ ->push_back(makeRawString(TOPLEVEL))
+ .push_back(makeRawArray());
}
static Ref makeString(IString str) {
- return &makeRawArray(2)->push_back(makeRawString(STRING))
- .push_back(makeRawString(str));
+ return &makeRawArray(2)
+ ->push_back(makeRawString(STRING))
+ .push_back(makeRawString(str));
}
static Ref makeBlock() {
- return &makeRawArray(2)->push_back(makeRawString(BLOCK))
- .push_back(makeRawArray());
+ return &makeRawArray(2)
+ ->push_back(makeRawString(BLOCK))
+ .push_back(makeRawArray());
}
- static Ref makeName(IString name) {
- return makeRawString(name);
- }
+ static Ref makeName(IString name) { return makeRawString(name); }
static void setBlockContent(Ref target, Ref block) {
if (target[0] == TOPLEVEL) {
target[1]->setArray(block[1]->getArray());
} else if (target[0] == DEFUN) {
target[3]->setArray(block[1]->getArray());
- } else abort();
+ } else
+ abort();
}
static void appendToBlock(Ref block, Ref element) {
@@ -1390,35 +1477,38 @@ public:
}
static Ref makeCall(Ref target) {
- return &makeRawArray(3)->push_back(makeRawString(CALL))
- .push_back(target)
- .push_back(makeRawArray());
+ return &makeRawArray(3)
+ ->push_back(makeRawString(CALL))
+ .push_back(target)
+ .push_back(makeRawArray());
}
static Ref makeCall(Ref target, Ref arg) {
- Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL))
- .push_back(target)
- .push_back(makeRawArray());
+ Ref ret = &makeRawArray(3)
+ ->push_back(makeRawString(CALL))
+ .push_back(target)
+ .push_back(makeRawArray());
ret[2]->push_back(arg);
return ret;
}
static Ref makeCall(IString target) {
- Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL))
- .push_back(makeName(target))
- .push_back(makeRawArray());
+ Ref ret = &makeRawArray(3)
+ ->push_back(makeRawString(CALL))
+ .push_back(makeName(target))
+ .push_back(makeRawArray());
return ret;
}
- template<typename ...Ts>
- static Ref makeCall(IString target, Ts... args) {
+ template<typename... Ts> static Ref makeCall(IString target, Ts... args) {
size_t nArgs = sizeof...(Ts);
Ref callArgs = makeRawArray(nArgs);
Ref argArray[] = {args...};
for (size_t i = 0; i < nArgs; ++i) {
callArgs->push_back(argArray[i]);
}
- return &makeRawArray(3)->push_back(makeRawString(CALL))
- .push_back(makeName(target))
- .push_back(callArgs);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(CALL))
+ .push_back(makeName(target))
+ .push_back(callArgs);
}
static void appendToCall(Ref call, Ref element) {
@@ -1426,59 +1516,57 @@ public:
call[2]->push_back(element);
}
- static Ref makeStatement(Ref contents) {
- return contents;
- }
+ static Ref makeStatement(Ref contents) { return contents; }
static Ref makeDouble(double num) {
return &arena.alloc<Value>()->setNumber(num);
}
- static Ref makeInt(uint32_t num) {
- return makeDouble(double(num));
- }
- static Ref makeInt(int32_t num) {
- return makeDouble(double(num));
- }
- static Ref makeNum(double num) {
- return makeDouble(num);
- }
+ static Ref makeInt(uint32_t num) { return makeDouble(double(num)); }
+ static Ref makeInt(int32_t num) { return makeDouble(double(num)); }
+ static Ref makeNum(double num) { return makeDouble(num); }
static Ref makeUnary(IString op, Ref value) {
- return &makeRawArray(3)->push_back(makeRawString(UNARY_PREFIX))
- .push_back(makeRawString(op))
- .push_back(value);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(UNARY_PREFIX))
+ .push_back(makeRawString(op))
+ .push_back(value);
}
static Ref makeBinary(Ref left, IString op, Ref right) {
if (op == SET) {
if (left->isString()) {
- return &arena.alloc<AssignName>()->setAssignName(left->getIString(), right);
+ return &arena.alloc<AssignName>()->setAssignName(left->getIString(),
+ right);
} else {
return &arena.alloc<Assign>()->setAssign(left, right);
}
} else if (op == COMMA) {
- return &makeRawArray(3)->push_back(makeRawString(SEQ))
- .push_back(left)
- .push_back(right);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(SEQ))
+ .push_back(left)
+ .push_back(right);
} else {
- return &makeRawArray(4)->push_back(makeRawString(BINARY))
- .push_back(makeRawString(op))
- .push_back(left)
- .push_back(right);
+ return &makeRawArray(4)
+ ->push_back(makeRawString(BINARY))
+ .push_back(makeRawString(op))
+ .push_back(left)
+ .push_back(right);
}
}
static Ref makePrefix(IString op, Ref right) {
- return &makeRawArray(3)->push_back(makeRawString(UNARY_PREFIX))
- .push_back(makeRawString(op))
- .push_back(right);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(UNARY_PREFIX))
+ .push_back(makeRawString(op))
+ .push_back(right);
}
static Ref makeFunction(IString name) {
- return &makeRawArray(4)->push_back(makeRawString(DEFUN))
- .push_back(makeRawString(name))
- .push_back(makeRawArray())
- .push_back(makeRawArray());
+ return &makeRawArray(4)
+ ->push_back(makeRawString(DEFUN))
+ .push_back(makeRawString(name))
+ .push_back(makeRawArray())
+ .push_back(makeRawArray());
}
static void appendArgumentToFunction(Ref func, IString arg) {
@@ -1486,101 +1574,115 @@ public:
func[2]->push_back(makeRawString(arg));
}
- static Ref makeVar(bool is_const=false) {
- return &makeRawArray(2)->push_back(makeRawString(VAR))
- .push_back(makeRawArray());
+ static Ref makeVar(bool is_const = false) {
+ return &makeRawArray(2)
+ ->push_back(makeRawString(VAR))
+ .push_back(makeRawArray());
}
static void appendToVar(Ref var, IString name, Ref value) {
assert(var[0] == VAR);
Ref array = &makeRawArray(1)->push_back(makeRawString(name));
- if (!!value) array->push_back(value);
+ if (!!value)
+ array->push_back(value);
var[1]->push_back(array);
}
static Ref makeReturn(Ref value) {
- return &makeRawArray(2)->push_back(makeRawString(RETURN))
- .push_back(!!value ? value : makeNull());
+ return &makeRawArray(2)
+ ->push_back(makeRawString(RETURN))
+ .push_back(!!value ? value : makeNull());
}
static Ref makeIndexing(Ref target, Ref index) {
- return &makeRawArray(3)->push_back(makeRawString(SUB))
- .push_back(target)
- .push_back(index);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(SUB))
+ .push_back(target)
+ .push_back(index);
}
static Ref makeIf(Ref condition, Ref ifTrue, Ref ifFalse) {
- return &makeRawArray(4)->push_back(makeRawString(IF))
- .push_back(condition)
- .push_back(ifTrue)
- .push_back(!!ifFalse ? ifFalse : makeNull());
+ return &makeRawArray(4)
+ ->push_back(makeRawString(IF))
+ .push_back(condition)
+ .push_back(ifTrue)
+ .push_back(!!ifFalse ? ifFalse : makeNull());
}
static Ref makeConditional(Ref condition, Ref ifTrue, Ref ifFalse) {
- return &makeRawArray(4)->push_back(makeRawString(CONDITIONAL))
- .push_back(condition)
- .push_back(ifTrue)
- .push_back(ifFalse);
+ return &makeRawArray(4)
+ ->push_back(makeRawString(CONDITIONAL))
+ .push_back(condition)
+ .push_back(ifTrue)
+ .push_back(ifFalse);
}
static Ref makeSeq(Ref left, Ref right) {
- return &makeRawArray(3)->push_back(makeRawString(SEQ))
- .push_back(left)
- .push_back(right);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(SEQ))
+ .push_back(left)
+ .push_back(right);
}
static Ref makeDo(Ref body, Ref condition) {
- return &makeRawArray(3)->push_back(makeRawString(DO))
- .push_back(condition)
- .push_back(body);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(DO))
+ .push_back(condition)
+ .push_back(body);
}
static Ref makeWhile(Ref condition, Ref body) {
- return &makeRawArray(3)->push_back(makeRawString(WHILE))
- .push_back(condition)
- .push_back(body);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(WHILE))
+ .push_back(condition)
+ .push_back(body);
}
static Ref makeFor(Ref init, Ref condition, Ref inc, Ref body) {
- return &makeRawArray(5)->push_back(makeRawString(FOR))
- .push_back(init)
- .push_back(condition)
- .push_back(inc)
- .push_back(body);
+ return &makeRawArray(5)
+ ->push_back(makeRawString(FOR))
+ .push_back(init)
+ .push_back(condition)
+ .push_back(inc)
+ .push_back(body);
}
static Ref makeBreak(IString label) {
- return &makeRawArray(2)->push_back(makeRawString(BREAK))
- .push_back(!!label ? makeRawString(label) : makeNull());
+ return &makeRawArray(2)
+ ->push_back(makeRawString(BREAK))
+ .push_back(!!label ? makeRawString(label) : makeNull());
}
static Ref makeContinue(IString label) {
- return &makeRawArray(2)->push_back(makeRawString(CONTINUE))
- .push_back(!!label ? makeRawString(label) : makeNull());
+ return &makeRawArray(2)
+ ->push_back(makeRawString(CONTINUE))
+ .push_back(!!label ? makeRawString(label) : makeNull());
}
static Ref makeLabel(IString name, Ref body) {
- return &makeRawArray(3)->push_back(makeRawString(LABEL))
- .push_back(makeRawString(name))
- .push_back(body);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(LABEL))
+ .push_back(makeRawString(name))
+ .push_back(body);
}
static Ref makeSwitch(Ref input) {
- return &makeRawArray(3)->push_back(makeRawString(SWITCH))
- .push_back(input)
- .push_back(makeRawArray());
+ return &makeRawArray(3)
+ ->push_back(makeRawString(SWITCH))
+ .push_back(input)
+ .push_back(makeRawArray());
}
static void appendCaseToSwitch(Ref switch_, Ref arg) {
assert(switch_[0] == SWITCH);
- switch_[2]->push_back(&makeRawArray(2)->push_back(arg)
- .push_back(makeRawArray()));
+ switch_[2]->push_back(
+ &makeRawArray(2)->push_back(arg).push_back(makeRawArray()));
}
static void appendDefaultToSwitch(Ref switch_) {
assert(switch_[0] == SWITCH);
- switch_[2]->push_back(&makeRawArray(2)->push_back(makeNull())
- .push_back(makeRawArray()));
+ switch_[2]->push_back(
+ &makeRawArray(2)->push_back(makeNull()).push_back(makeRawArray()));
}
static void appendCodeToSwitch(Ref switch_, Ref code, bool explicitBlock) {
@@ -1598,20 +1700,21 @@ public:
static Ref makeTry(Ref try_, Ref arg, Ref catch_) {
assert(try_[0] == BLOCK);
assert(catch_[0] == BLOCK);
- return &makeRawArray(3)->push_back(makeRawString(TRY))
- .push_back(try_)
- .push_back(arg)
- .push_back(catch_);
+ return &makeRawArray(3)
+ ->push_back(makeRawString(TRY))
+ .push_back(try_)
+ .push_back(arg)
+ .push_back(catch_);
}
static Ref makeDot(Ref obj, IString key) {
- return &makeRawArray(3)->push_back(makeRawString(DOT))
- .push_back(obj)
- .push_back(makeRawString(key));
+ return &makeRawArray(3)
+ ->push_back(makeRawString(DOT))
+ .push_back(obj)
+ .push_back(makeRawString(key));
}
- template<typename ...Ts>
- static Ref makeDot(Ref obj, Ref key, Ts... args) {
+ template<typename... Ts> static Ref makeDot(Ref obj, Ref key, Ts... args) {
return makeDot(makeDot(obj, key), args...);
}
@@ -1621,13 +1724,13 @@ public:
}
static Ref makeNew(Ref call) {
- return &makeRawArray(2)->push_back(makeRawString(NEW))
- .push_back(call);
+ return &makeRawArray(2)->push_back(makeRawString(NEW)).push_back(call);
}
static Ref makeArray() {
- return &makeRawArray(2)->push_back(makeRawString(ARRAY))
- .push_back(makeRawArray());
+ return &makeRawArray(2)
+ ->push_back(makeRawString(ARRAY))
+ .push_back(makeRawArray());
}
static void appendToArray(Ref array, Ref element) {
@@ -1636,26 +1739,28 @@ public:
}
static Ref makeObject() {
- return &makeRawArray(2)->push_back(makeRawString(OBJECT))
- .push_back(makeRawArray());
+ return &makeRawArray(2)
+ ->push_back(makeRawString(OBJECT))
+ .push_back(makeRawArray());
}
static void appendToObject(Ref array, IString key, Ref value) {
assert(array[0] == OBJECT);
- array[1]->push_back(&makeRawArray(2)->push_back(makeRawString(key))
- .push_back(value));
+ array[1]->push_back(
+ &makeRawArray(2)->push_back(makeRawString(key)).push_back(value));
}
static void appendToObjectWithQuotes(Ref array, IString key, Ref value) {
assert(array[0] == OBJECT);
- array[1]->push_back(&makeRawArray(2)->push_back(makeString(key))
- .push_back(value));
+ array[1]->push_back(
+ &makeRawArray(2)->push_back(makeString(key)).push_back(value));
}
static Ref makeSub(Ref obj, Ref index) {
- return &makeRawArray(2)->push_back(makeRawString(SUB))
- .push_back(obj)
- .push_back(index);
+ return &makeRawArray(2)
+ ->push_back(makeRawString(SUB))
+ .push_back(obj)
+ .push_back(index);
}
static Ref makePtrShift(Ref ptr, int shifts) {
diff --git a/src/emscripten-optimizer/snprintf.h b/src/emscripten-optimizer/snprintf.h
index 86335661d..22c8d8202 100644
--- a/src/emscripten-optimizer/snprintf.h
+++ b/src/emscripten-optimizer/snprintf.h
@@ -19,34 +19,34 @@
#include <stdarg.h>
-// Visual Studio does not support C99, so emulate snprintf support for it manually.
+// Visual Studio does not support C99, so emulate snprintf support for it
+// manually.
#ifdef _MSC_VER
#define snprintf c99_snprintf
-inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
-{
- int count = -1;
+inline int
+c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) {
+ int count = -1;
- if (size != 0)
- count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
- if (count == -1)
- count = _vscprintf(format, ap);
+ if (size != 0)
+ count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
+ if (count == -1)
+ count = _vscprintf(format, ap);
- return count;
+ return count;
}
-inline int c99_snprintf(char* str, size_t size, const char* format, ...)
-{
- int count;
- va_list ap;
+inline int c99_snprintf(char* str, size_t size, const char* format, ...) {
+ int count;
+ va_list ap;
- va_start(ap, format);
- count = c99_vsnprintf(str, size, format, ap);
- va_end(ap);
+ va_start(ap, format);
+ count = c99_vsnprintf(str, size, format, ap);
+ va_end(ap);
- return count;
+ return count;
}
#endif