diff options
41 files changed, 539 insertions, 225 deletions
diff --git a/.travis.yml b/.travis.yml index 02b7efd86..861e1407d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,24 +2,41 @@ sudo: false language: cpp matrix: include: - - addons: &gcc5 + + - env: COMPILER_VERSION=3.6 + compiler: clang + addons: &clang36 apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['cmake', 'g++-5'] + sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6'] + packages: ['cmake', 'clang-3.6'] + + - env: COMPILER_VERSION=3.6 COMPILER_FLAGS="-fsanitize=undefined -fsanitize-blacklist=`pwd`/ubsan.blacklist" + compiler: clang + addons: *clang36 + +# - env: COMPILER_VERSION=3.6 COMPILER_FLAGS="-fsanitize=address" +# compiler: clang +# addons: *clang36 +# +# - env: COMPILER_VERSION=3.6 COMPILER_FLAGS="-fsanitize=thread" +# compiler: clang +# addons: *clang36 + + - env: COMPILER_VERSION=5 compiler: gcc - env: COMPILER_VERSION=5 - - addons: &clang37 + addons: &gcc5 apt: - sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7'] - packages: ['cmake', 'clang-3.7'] - compiler: clang - env: COMPILER_VERSION=3.7 -before_script: - - git submodule update --init # Initialize the submodules recorded in the index. + sources: ['ubuntu-toolchain-r-test'] + packages: ['cmake', 'g++-5'] + +before_install: - export CC="${CC}-${COMPILER_VERSION}" - export CXX="${CXX}-${COMPILER_VERSION}" - - $CC --version + script: - - cmake . + - cmake . -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS" - make -j2 - ./check.py + +notifications: + email: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 3771f7090..bcd9eb917 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ SET(support_SOURCES src/support/colors.cpp src/support/command-line.cpp src/support/file.cpp + src/support/safe_integer.cpp ) ADD_LIBRARY(support STATIC ${support_SOURCES}) @@ -11,6 +11,6 @@ make -j #echo "building s2wasm" #g++ -O2 -std=c++11 src/s2wasm-main.cpp src/support/command-line.cpp src/support/file.cpp src/support/colors.cpp -Isrc/ -o bin/s2wasm echo "building interpreter/js" -em++ -std=c++11 src/wasm-js.cpp src/pass.cpp src/passes/MergeBlocks.cpp src/passes/RemoveUnusedBrs.cpp src/passes/RemoveUnusedNames.cpp src/passes/SimplifyLocals.cpp src/emscripten-optimizer/parser.cpp src/emscripten-optimizer/simple_ast.cpp src/emscripten-optimizer/optimizer-shared.cpp src/support/colors.cpp -Isrc/ -o bin/wasm.js -s MODULARIZE=1 -s 'EXPORT_NAME="WasmJS"' --memory-init-file 0 -Oz -s ALLOW_MEMORY_GROWTH=1 -profiling -s DEMANGLE_SUPPORT=1 #-DWASM_JS_DEBUG -DWASM_INTERPRETER_DEBUG=2 +em++ -std=c++11 src/wasm-js.cpp src/pass.cpp src/passes/MergeBlocks.cpp src/passes/RemoveUnusedBrs.cpp src/passes/RemoveUnusedNames.cpp src/passes/SimplifyLocals.cpp src/emscripten-optimizer/parser.cpp src/emscripten-optimizer/simple_ast.cpp src/emscripten-optimizer/optimizer-shared.cpp src/support/colors.cpp src/support/safe_integer.cpp -Isrc/ -o bin/wasm.js -s MODULARIZE=1 -s 'EXPORT_NAME="WasmJS"' --memory-init-file 0 -Oz -s ALLOW_MEMORY_GROWTH=1 -profiling -s DEMANGLE_SUPPORT=1 #-DWASM_JS_DEBUG -DWASM_INTERPRETER_DEBUG=2 cat src/js/wasm.js-post.js >> bin/wasm.js @@ -146,7 +146,9 @@ for t in tests: if t.endswith('.wast') and not t.startswith('spec'): print '..', t t = os.path.join('test', t) - actual, err = subprocess.Popen([os.path.join('bin', 'binaryen-shell'), t, '-print-before'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + cmd = [os.path.join('bin', 'binaryen-shell'), t, '-print-before'] + print ' ', ' '.join(cmd) + actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() assert err.replace('printing before:', '').strip() == '', 'bad err:' + err actual = actual.replace('printing before:\n', '') @@ -273,7 +275,12 @@ if unexpected_result_count: print '\n[ checking example testcases... ]\n' -subprocess.check_call([os.environ.get('CXX') or 'g++', '-std=c++11', os.path.join('test', 'example', 'find_div0s.cpp'), '-Isrc', '-g', '-lsupport', '-Llib/.']) +cmd = [os.environ.get('CXX') or 'g++', '-std=c++11', os.path.join('test', 'example', 'find_div0s.cpp'), '-Isrc', '-g', '-lsupport', '-Llib/.'] +if os.environ.get('COMPILER_FLAGS'): + for f in os.environ.get('COMPILER_FLAGS').split(' '): + cmd.append(f) +print ' '.join(cmd) +subprocess.check_call(cmd) actual = subprocess.Popen(['./a.out'], stdout=subprocess.PIPE).communicate()[0] expected = open(os.path.join('test', 'example', 'find_div0s.txt')).read() if actual != expected: diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 11cb75b30..280624d9b 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -390,8 +390,9 @@ private: } if (ast[1] == MINUS && ast[2][0] == NUM) { double num = -ast[2][1]->getNumber(); - assert(isInteger32(num)); - return Literal((int32_t)num); + if (isSInteger32(num)) return Literal((int32_t)num); + if (isUInteger32(num)) return Literal((uint32_t)num); + assert(false && "expected signed or unsigned int32"); } if (ast[1] == PLUS && ast[2][0] == UNARY_PREFIX && ast[2][1] == MINUS && ast[2][2][0] == NUM) { return Literal((double)-ast[2][2][1]->getNumber()); @@ -917,9 +918,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } else if (what == NUM) { auto ret = allocator.alloc<Const>(); double num = ast[1]->getNumber(); - if (isInteger32(num)) { + if (isSInteger32(num)) { ret->value.type = WasmType::i32; - ret->value.i32 = toInteger32(num); + ret->value.i32 = toSInteger32(num); + } else if (isUInteger32(num)) { + ret->value.type = WasmType::i32; + ret->value.i32 = toUInteger32(num); } else { ret->value.type = WasmType::f64; ret->value.f64 = num; diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 4466fb0e9..6831d81b0 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -14,7 +14,10 @@ * limitations under the License. */ +#include <limits> + #include "optimizer.h" +#include "support/safe_integer.h" using namespace cashew; @@ -26,20 +29,6 @@ IString SIMD_INT8X16_CHECK("SIMD_Int8x16_check"), SIMD_FLOAT32X4_CHECK("SIMD_Float32x4_check"), SIMD_FLOAT64X2_CHECK("SIMD_Float64x2_check"); -bool isInteger(double x) { - return fmod(x, 1) == 0; -} - -bool isInteger32(double x) { - return isInteger(x) && (x == (int32_t)x || x == (uint32_t)x); -} - -int32_t toInteger32(double x) { - if (x == (int32_t)x) return (int32_t)x; - assert(x == (uint32_t)x); - return (uint32_t)x; -} - int parseInt(const char *str) { int ret = *str - '0'; while (*(++str)) { @@ -67,7 +56,7 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFr switch (node[0]->getCString()[0]) { case 'n': { if (node[0] == NUM) { - if (!isInteger(node[1]->getNumber())) return ASM_DOUBLE; + if (!wasm::isInteger(node[1]->getNumber())) return ASM_DOUBLE; return ASM_INT; } else if (node[0] == NAME) { if (asmData) { @@ -176,7 +165,7 @@ AsmSign detectSign(Ref node, IString minifiedFround) { double value = node[1]->getNumber(); if (value < 0) return ASM_SIGNED; if (value > uint32_t(-1) || fmod(value, 1) != 0) return ASM_NONSIGNED; - if (value == int32_t(value)) return ASM_FLEXIBLE; + if (wasm::isSInteger32(value)) return ASM_FLEXIBLE; return ASM_UNSIGNED; } else if (type == NAME) { return ASM_FLEXIBLE; diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index 451a9e286..684fc0164 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -116,10 +116,6 @@ struct AsmData { } }; -bool isInteger(double x); -bool isInteger32(double x); -int32_t toInteger32(double x); - extern cashew::IString ASM_FLOAT_ZERO; extern cashew::IString SIMD_INT8X16_CHECK, diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h index c805ca9f6..da3e6f5c7 100644 --- a/src/emscripten-optimizer/parser.h +++ b/src/emscripten-optimizer/parser.h @@ -22,13 +22,14 @@ #ifndef wasm_parser_h #define wasm_parser_h -#include <vector> -#include <iostream> #include <algorithm> - -#include <stdio.h> +#include <cstdio> +#include <iostream> +#include <limits> +#include <vector> #include "istring.h" +#include "support/safe_integer.h" namespace cashew { @@ -179,10 +180,6 @@ class Parser { static bool hasChar(const char* list, char x) { while (*list) if (*list++ == x) return true; return false; } - static bool is32Bit(double x) { - return x == (int)x || x == (unsigned int)x; - } - // An atomic fragment of something. Stops at a natural boundary. enum FragType { KEYWORD = 0, @@ -249,7 +246,10 @@ class Parser { // 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 - type = (std::find(start, src, '.') == src && is32Bit(num)) ? INT : DOUBLE; + type = (std::find(start, src, '.') == src && + (wasm::isSInteger32(num) || wasm::isUInteger32(num))) + ? INT + : DOUBLE; assert(src > start); } else if (hasChar(OPERATOR_INITS, *src)) { switch (*src) { diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index 712845dea..73037815f 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -17,26 +17,25 @@ #ifndef wasm_simple_ast_h #define wasm_simple_ast_h -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <math.h> - -#include <vector> -#include <ostream> -#include <iostream> +#include <algorithm> +#include <cassert> +#include <cmath> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <functional> #include <iomanip> +#include <iostream> #include <limits> -#include <functional> -#include <algorithm> +#include <ostream> #include <set> -#include <unordered_set> #include <unordered_map> +#include <unordered_set> +#include <vector> #include "parser.h" - #include "snprintf.h" +#include "support/safe_integer.h" #define err(str) fprintf(stderr, str "\n"); #define errv(str, ...) fprintf(stderr, str "\n", __VA_ARGS__); @@ -870,8 +869,8 @@ struct JSPrinter { } else { // integer assert(d >= 0); - unsigned long long uu = (unsigned long long)d; - if (uu == d) { + if (wasm::isUInteger64(d)) { + unsigned long long uu = wasm::toUInteger64(d); bool asHex = e && !finalize; snprintf(buffer, BUFFERSIZE-1, asHex ? "0x%llx" : "%llu", uu); if (asHex) { diff --git a/src/s2wasm.h b/src/s2wasm.h index bd3f12e73..b99a71159 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -160,19 +160,36 @@ private: } int32_t getInt() { - int32_t ret = 0; + const char* loc = s; + uint32_t value = 0; bool neg = false; - if (*s == '-') { + if (*loc == '-') { neg = true; - s++; + loc++; } - while (isdigit(*s)) { - ret *= 10; - ret += (*s - '0'); - s++; + while (isdigit(*loc)) { + uint32_t digit = *loc - '0'; + if (value > std::numeric_limits<uint32_t>::max() / 10) { + abort_on("uint32_t overflow"); + } + value *= 10; + if (value > std::numeric_limits<uint32_t>::max() - digit) { + abort_on("uint32_t overflow"); + } + value += digit; + loc++; } - if (neg) ret = -ret; - return ret; + if (neg) { + uint32_t positive_int_min = + (uint32_t) - (1 + std::numeric_limits<int32_t>::min()) + (uint32_t)1; + if (value > positive_int_min) { + abort_on("negative int32_t overflow"); + } + s = loc; + return -value; + } + s = loc; + return value; } // gets a constant, which may be a relocation for later. @@ -183,7 +200,7 @@ private: return false; } else { // a global constant, we need to fix it up later - Name name = getStrToSep(); + Name name = cleanFunction(getStrToSep()); int offset = 0; if (*s == '+') { s++; @@ -198,19 +215,36 @@ private: } int64_t getInt64() { - int64_t ret = 0; + const char* loc = s; + uint64_t value = 0; bool neg = false; - if (*s == '-') { + if (*loc == '-') { neg = true; - s++; + loc++; } - while (isdigit(*s)) { - ret *= 10; - ret += (*s - '0'); - s++; + while (isdigit(*loc)) { + uint64_t digit = *loc - '0'; + if (value > std::numeric_limits<uint64_t>::max() / 10) { + abort_on("uint64_t overflow"); + } + value *= 10; + if (value > std::numeric_limits<uint64_t>::max() - digit) { + abort_on("uint64_t overflow"); + } + value += digit; + loc++; } - if (neg) ret = -ret; - return ret; + if (neg) { + uint64_t positive_int_min = + (uint64_t) - (1 + std::numeric_limits<int64_t>::min()) + (uint64_t)1; + if (value > positive_int_min) { + abort_on("negative int64_t overflow"); + } + s = loc; + return -value; + } + s = loc; + return value; } Name getCommaSeparated() { @@ -282,6 +316,16 @@ private: abort_on("getType"); } + // The LLVM backend emits function names as name@FUNCTION. We can drop the @ and after it. + Name cleanFunction(Name name) { + if (!strchr(name.str, '@')) return name; + char *temp = strdup(name.str); + *strchr(temp, '@') = 0; + Name ret = cashew::IString(temp, false); + free(temp); + return ret; + } + // processors void scan() { @@ -543,7 +587,7 @@ private: curr = specific; } else { assign = getAssign(); - Name target = getCommaSeparated(); + Name target = cleanFunction(getCommaSeparated()); if (implementedFunctions.count(target) > 0) { auto specific = allocator.alloc<Call>(); specific->target = target; @@ -933,7 +977,7 @@ private: } else if (match(".int64")) { size_t size = raw->size(); raw->resize(size + 8); - (*(int64_t*)(&(*raw)[size])) = getInt(); + (*(int64_t*)(&(*raw)[size])) = getInt64(); zero = false; } else { break; diff --git a/src/support/safe_integer.cpp b/src/support/safe_integer.cpp new file mode 100644 index 000000000..dbe62ca52 --- /dev/null +++ b/src/support/safe_integer.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2016 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cassert> +#include <cmath> +#include <limits> + +#include "support/safe_integer.h" + +using namespace wasm; + +bool wasm::isInteger(double x) { return fmod(x, 1) == 0; } + +bool wasm::isUInteger32(double x) { + return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint32_t>::max(); +} + +bool wasm::isSInteger32(double x) { + return isInteger(x) && x >= std::numeric_limits<int32_t>::min() && + x <= std::numeric_limits<int32_t>::max(); +} + +uint32_t wasm::toUInteger32(double x) { + assert(isUInteger32(x)); + return x < std::numeric_limits<uint32_t>::max() + ? x + : std::numeric_limits<uint32_t>::max(); +} + +int32_t wasm::toSInteger32(double x) { + assert(isSInteger32(x)); + return x > std::numeric_limits<int32_t>::min() && + x < std::numeric_limits<int32_t>::max() + ? x + : (x < 0 ? std::numeric_limits<int32_t>::min() + : std::numeric_limits<int32_t>::max()); +} + +bool wasm::isUInteger64(double x) { + return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint64_t>::max(); +} + +bool wasm::isSInteger64(double x) { + return isInteger(x) && x >= std::numeric_limits<int64_t>::min() && + x <= std::numeric_limits<int64_t>::max(); +} + +uint64_t wasm::toUInteger64(double x) { + assert(isUInteger64(x)); + return x < (double)std::numeric_limits<uint64_t>::max() + ? (uint64_t)x + : std::numeric_limits<uint64_t>::max(); +} + +int64_t wasm::toSInteger64(double x) { + assert(isSInteger64(x)); + return x > (double)std::numeric_limits<int64_t>::min() && + x < (double)std::numeric_limits<int64_t>::max() + ? (int64_t)x + : (x < 0 ? std::numeric_limits<int64_t>::min() + : std::numeric_limits<int64_t>::max()); +} diff --git a/src/support/safe_integer.h b/src/support/safe_integer.h new file mode 100644 index 000000000..f240644c8 --- /dev/null +++ b/src/support/safe_integer.h @@ -0,0 +1,34 @@ +/* + * Copyright 2016 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef wasm_safe_integer_h +#define wasm_safe_integer_h + +#include <cstdint> + +namespace wasm { +bool isInteger(double x); +bool isUInteger32(double x); +bool isSInteger32(double x); +uint32_t toUInteger32(double x); +int32_t toSInteger32(double x); +bool isUInteger64(double x); +bool isSInteger64(double x); +uint64_t toUInteger64(double x); +int64_t toSInteger64(double x); +} // namespace wasm + +#endif // wasm_safe_integer_h diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 76a9b62be..d923b9ecb 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -30,13 +30,40 @@ namespace wasm { struct LEB128 { - int32_t value; - LEB128(int32_t value) : value(value) {} + uint32_t value; + + LEB128(uint32_t value) : value(value) {} + + void write(std::vector<uint8_t>* out) { + uint32_t temp = value; + do { + uint8_t byte = value & 127; + temp >>= 7; + if (temp) { + byte = byte | 128; + } + out.push_back(byte); + } while (temp); + } + + void read(std::function<uint8_t ()> get) { + value = 0; + uint32_t shift = 0; + while (1) { + uint8_t byte = get(); + value |= ((byte & 127) << shift); + if (byte & 128) break; + shift += 7; + } + } }; +// // We mostly stream into a buffer as we create the binary format, however, -// sometimes we need to backtrack and write to a location behind us. -class BufferWithRandomAccess : public std::vector<unsigned char> { +// sometimes we need to backtrack and write to a location behind us - wasm +// is optimized for reading, not writing. +// +class BufferWithRandomAccess : public std::vector<uint8_t> { public: BufferWithRandomAccess& operator<<(int8_t x) { push_back(x); @@ -66,8 +93,7 @@ public: return *this; } BufferWithRandomAccess& operator<<(LEB128 x) { - // XXX TODO - magic + x.write(this); return *this; } @@ -285,6 +311,7 @@ public: writeDataSegments(); writeFunctionTable(); writeEnd(); + finishUp(); } writeMemory() { @@ -367,10 +394,10 @@ public: } o << getFunctionTypeIndex(type); o << int8_t(FunctionEntry::Named | - (FunctionEntry::Import * !!import) | - (FunctionEntry::Locals * (function && function->locals.size() > 0) | - (FunctionEntry::Export) * (wasm.exportsMap[name].count(name) > 0))); - // TODO: name. how can we do an offset? into what section? and how do we know it now? + (FunctionEntry::Import * !!import) | + (FunctionEntry::Locals * (function && function->locals.size() > 0) | + (FunctionEntry::Export) * (wasm.exportsMap[name].count(name) > 0))); + emitString(Name.str); if (function && function->locals.size() > 0) { mapLocals(function); o << uint16_t(numLocalsByType[i32]) @@ -389,10 +416,10 @@ public: writeDataSegments() { o << Section::DataSegments << LEB128(wasm.memory.segments.size()); for (auto& segment : wasm.memory.segments) { - o << int32_t(segment.offset) - << int32_t(XXX) // TODO: where/when do we emit this? - << int32_t(segment.size) - << int8_t(1); // load at program start + o << int32_t(segment.offset); + emitBuffer(segment.data, segment.size); + o << int32_t(segment.size); + o << int8_t(1); // load at program start } } @@ -418,6 +445,37 @@ public: o << Section::End; } + // helpers + + struct Buffer { + const char* data; + size_t size; + size_t pointerLocation; + Buffer(const char* data, size_t size, size_t pointerLocation) : data(data), size(size), pointerLocation(pointerLocation) {} + }; + + std::vector<Buffer> buffersToWrite; + + void emitBuffer(const char* data, size_t size) { + assert(size > 0); + buffersToWrite.emplace_back(data, size, o.size()); + o << uint32_t(0); // placeholder + } + + void emitString(const char *str) { + emitBuffer(str, strlen(str) + 1); + } + + void finishUp() { + // finish buffers + for (auto& buffer : buffersToWrite) { + o.writeAt(buffer.pointerLocation, (uint32_t)o.size()); + for (size_t i = 0; i < buffer.size; i++) { + o << buffer.data[i]; + } + } + } + // AST writing via visitors std::vector<Name> breakStack; diff --git a/src/wasm.h b/src/wasm.h index b1b8d84d4..c4654580a 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -45,13 +45,14 @@ #define wasm_wasm_h #include <cassert> +#include <cmath> #include <cstddef> #include <cstdint> #include <cstring> #include <fstream> #include <map> -#include <vector> #include <string> +#include <vector> #include "compiler-support.h" #include "emscripten-optimizer/simple_ast.h" @@ -200,7 +201,7 @@ struct Literal { } static void printDouble(std::ostream &o, double d) { - if (d == 0 && 1/d < 0) { + if (d == 0 && std::signbit(d)) { o << "-0"; return; } diff --git a/src/wasm2asm.h b/src/wasm2asm.h index 53cb6df78..1a85bc177 100644 --- a/src/wasm2asm.h +++ b/src/wasm2asm.h @@ -22,6 +22,8 @@ #ifndef wasm_wasm2asm_h #define wasm_wasm2asm_h +#include <cmath> + #include "wasm.h" #include "emscripten-optimizer/optimizer.h" #include "mixed_arena.h" @@ -914,7 +916,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { } case f64: { double d = curr->value.f64; - if (d == 0 && 1/d < 0) { // negative zero + if (d == 0 && std::signbit(d)) { // negative zero return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeUnary(MINUS, ValueBuilder::makeDouble(0))); } return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeDouble(curr->value.f64)); diff --git a/test/dot_s/asm_const.s b/test/dot_s/asm_const.s index fc055579d..04c2c8630 100644 --- a/test/dot_s/asm_const.s +++ b/test/dot_s/asm_const.s @@ -6,7 +6,7 @@ main: # @main .result i32 # BB#0: i32.const $push0=, .str - call emscripten_asm_const, $pop0 + call emscripten_asm_const@FUNCTION, $pop0 i32.const $push1=, 0 return $pop1 .Lfunc_end0: diff --git a/test/dot_s/basics.s b/test/dot_s/basics.s index 1c6225738..a37678ff7 100644 --- a/test/dot_s/basics.s +++ b/test/dot_s/basics.s @@ -7,7 +7,7 @@ main: # @main .result i32 # BB#0: i32.const $push0=, .str - call $discard=, puts, $pop0 + call $discard=, puts@FUNCTION, $pop0 i32.const $push1=, 31 i32.shr_s $push2=, $0, $pop1 i32.const $push3=, 30 diff --git a/test/dot_s/exit.s b/test/dot_s/exit.s index 12bf86bf3..2fad9277f 100644 --- a/test/dot_s/exit.s +++ b/test/dot_s/exit.s @@ -6,6 +6,6 @@ main: .result i32 .local i32 i32.const $push0=, 0 - call exit, $pop0 + call exit@FUNCTION, $pop0 .Lfunc_end0: .size main, .Lfunc_end0-main diff --git a/test/dot_s/memops.s b/test/dot_s/memops.s index 893dc6b68..64c967a13 100644 --- a/test/dot_s/memops.s +++ b/test/dot_s/memops.s @@ -7,7 +7,7 @@ _Z6reporti: # @_Z6reporti i32.const $push0=, 8 i32.store $discard=, 0($pop0), $0 i32.const $push1=, .str - call emscripten_asm_const, $pop1 + call emscripten_asm_const@FUNCTION, $pop1 return .Lfunc_end0: .size _Z6reporti, .Lfunc_end0-_Z6reporti @@ -75,7 +75,7 @@ main: # @main i32.ne $push16=, $0, $pop15 br_if $pop16, .LBB1_1 .LBB1_5: - call _Z6reporti, $6 + call _Z6reporti@FUNCTION, $6 i32.const $push17=, 0 i32.const $9=, 1048576 i32.add $12=, $12, $9 diff --git a/test/emcc_hello_world.2asm.js b/test/emcc_hello_world.2asm.js index dbc002e3e..3dfeecd19 100644 --- a/test/emcc_hello_world.2asm.js +++ b/test/emcc_hello_world.2asm.js @@ -137,7 +137,7 @@ function asmFunc(global, env, buffer) { block0 : { $tobool1 = $x != 0.0; if ($tobool1) block1 : { - $mul = $x - 18446744073709551616.0; + $mul = $x - 18446744073709551615.0; $call = +_frexp(+$mul, $e | 0); $4 = HEAPU32[$e >> 2] | 0; $sub = $4 + 4294967232 | 0; diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm index 3b0331011..9dbe000df 100644 --- a/test/emcc_hello_world.fromasm +++ b/test/emcc_hello_world.fromasm @@ -430,7 +430,7 @@ (set_local $$mul (f64.mul (get_local $$x) - (f64.const 18446744073709551616) + (f64.const 18446744073709551615) ) ) (set_local $$call diff --git a/test/emcc_hello_world.wast b/test/emcc_hello_world.wast index bd0adc06f..01cd2f4c1 100644 --- a/test/emcc_hello_world.wast +++ b/test/emcc_hello_world.wast @@ -441,7 +441,7 @@ (set_local $$mul (f64.mul (get_local $$x) - (f64.const 18446744073709551616) + (f64.const 18446744073709551615) ) ) (set_local $$call diff --git a/test/llvm_autogenerated/call.s b/test/llvm_autogenerated/call.s index f406bbaaf..7081c43a8 100644 --- a/test/llvm_autogenerated/call.s +++ b/test/llvm_autogenerated/call.s @@ -4,7 +4,7 @@ .type call_i32_nullary,@function call_i32_nullary: .result i32 - i32.call $push0=, i32_nullary + i32.call $push0=, i32_nullary@FUNCTION return $pop0 .Lfunc_end0: .size call_i32_nullary, .Lfunc_end0-call_i32_nullary @@ -13,7 +13,7 @@ call_i32_nullary: .type call_i64_nullary,@function call_i64_nullary: .result i64 - i64.call $push0=, i64_nullary + i64.call $push0=, i64_nullary@FUNCTION return $pop0 .Lfunc_end1: .size call_i64_nullary, .Lfunc_end1-call_i64_nullary @@ -22,7 +22,7 @@ call_i64_nullary: .type call_float_nullary,@function call_float_nullary: .result f32 - f32.call $push0=, float_nullary + f32.call $push0=, float_nullary@FUNCTION return $pop0 .Lfunc_end2: .size call_float_nullary, .Lfunc_end2-call_float_nullary @@ -31,7 +31,7 @@ call_float_nullary: .type call_double_nullary,@function call_double_nullary: .result f64 - f64.call $push0=, double_nullary + f64.call $push0=, double_nullary@FUNCTION return $pop0 .Lfunc_end3: .size call_double_nullary, .Lfunc_end3-call_double_nullary @@ -39,7 +39,7 @@ call_double_nullary: .globl call_void_nullary .type call_void_nullary,@function call_void_nullary: - call void_nullary + call void_nullary@FUNCTION return .Lfunc_end4: .size call_void_nullary, .Lfunc_end4-call_void_nullary @@ -49,7 +49,7 @@ call_void_nullary: call_i32_unary: .param i32 .result i32 - i32.call $push0=, i32_unary, $0 + i32.call $push0=, i32_unary@FUNCTION, $0 return $pop0 .Lfunc_end5: .size call_i32_unary, .Lfunc_end5-call_i32_unary @@ -59,7 +59,7 @@ call_i32_unary: call_i32_binary: .param i32, i32 .result i32 - i32.call $push0=, i32_binary, $0, $1 + i32.call $push0=, i32_binary@FUNCTION, $0, $1 return $pop0 .Lfunc_end6: .size call_i32_binary, .Lfunc_end6-call_i32_binary @@ -86,7 +86,7 @@ call_indirect_i32: .globl tail_call_void_nullary .type tail_call_void_nullary,@function tail_call_void_nullary: - call void_nullary + call void_nullary@FUNCTION return .Lfunc_end9: .size tail_call_void_nullary, .Lfunc_end9-tail_call_void_nullary @@ -94,7 +94,7 @@ tail_call_void_nullary: .globl fastcc_tail_call_void_nullary .type fastcc_tail_call_void_nullary,@function fastcc_tail_call_void_nullary: - call void_nullary + call void_nullary@FUNCTION return .Lfunc_end10: .size fastcc_tail_call_void_nullary, .Lfunc_end10-fastcc_tail_call_void_nullary @@ -102,7 +102,7 @@ fastcc_tail_call_void_nullary: .globl coldcc_tail_call_void_nullary .type coldcc_tail_call_void_nullary,@function coldcc_tail_call_void_nullary: - call void_nullary + call void_nullary@FUNCTION return .Lfunc_end11: .size coldcc_tail_call_void_nullary, .Lfunc_end11-coldcc_tail_call_void_nullary diff --git a/test/llvm_autogenerated/cfg-stackify.s b/test/llvm_autogenerated/cfg-stackify.s index eec847fa1..121b7d55a 100644 --- a/test/llvm_autogenerated/cfg-stackify.s +++ b/test/llvm_autogenerated/cfg-stackify.s @@ -12,7 +12,7 @@ test0: i32.add $1=, $1, $pop0 i32.ge_s $push1=, $1, $0 br_if $pop1, .LBB0_3 - call something + call something@FUNCTION br .LBB0_1 .LBB0_3: return @@ -31,7 +31,7 @@ test1: i32.add $1=, $1, $pop0 i32.ge_s $push1=, $1, $0 br_if $pop1, .LBB1_3 - call something + call something@FUNCTION br .LBB1_1 .LBB1_3: return @@ -288,7 +288,7 @@ test3: i32.ne $push1=, $0, $0 br_if $pop1, .LBB12_2 .LBB12_3: - call bar + call bar@FUNCTION br .LBB12_1 .LBB12_4: unreachable @@ -463,7 +463,7 @@ test9: loop .LBB18_5 i32.const $push0=, 1 i32.store $1=, 0($0), $pop0 - i32.call $push1=, a + i32.call $push1=, a@FUNCTION i32.and $push2=, $pop1, $1 i32.const $push13=, 0 i32.eq $push14=, $pop2, $pop13 @@ -473,21 +473,21 @@ test9: block .LBB18_4 i32.const $push4=, 2 i32.store $discard=, 0($0), $pop4 - i32.call $push5=, a + i32.call $push5=, a@FUNCTION i32.and $push6=, $pop5, $1 i32.const $push15=, 0 i32.eq $push16=, $pop6, $pop15 br_if $pop16, .LBB18_4 i32.const $push10=, 3 i32.store $discard=, 0($0), $pop10 - i32.call $push11=, a + i32.call $push11=, a@FUNCTION i32.and $push12=, $pop11, $1 br_if $pop12, .LBB18_2 br .LBB18_1 .LBB18_4: i32.const $push7=, 4 i32.store $discard=, 0($0), $pop7 - i32.call $push8=, a + i32.call $push8=, a@FUNCTION i32.and $push9=, $pop8, $1 br_if $pop9, .LBB18_2 br .LBB18_1 diff --git a/test/llvm_autogenerated/f32.s b/test/llvm_autogenerated/f32.s index 53ec18d7f..229f3f7dc 100644 --- a/test/llvm_autogenerated/f32.s +++ b/test/llvm_autogenerated/f32.s @@ -157,7 +157,7 @@ fmax32: fma32: .param f32, f32, f32 .result f32 - f32.call $push0=, fmaf, $0, $1, $2 + f32.call $push0=, fmaf@FUNCTION, $0, $1, $2 return $pop0 .Lfunc_end15: .size fma32, .Lfunc_end15-fma32 diff --git a/test/llvm_autogenerated/f64.s b/test/llvm_autogenerated/f64.s index 423d7cb77..520a1a68d 100644 --- a/test/llvm_autogenerated/f64.s +++ b/test/llvm_autogenerated/f64.s @@ -157,7 +157,7 @@ fmax64: fma64: .param f64, f64, f64 .result f64 - f64.call $push0=, fma, $0, $1, $2 + f64.call $push0=, fma@FUNCTION, $0, $1, $2 return $pop0 .Lfunc_end15: .size fma64, .Lfunc_end15-fma64 diff --git a/test/llvm_autogenerated/frem.s b/test/llvm_autogenerated/frem.s index 44d12adfd..af01a9c2b 100644 --- a/test/llvm_autogenerated/frem.s +++ b/test/llvm_autogenerated/frem.s @@ -5,7 +5,7 @@ frem32: .param f32, f32 .result f32 - f32.call $push0=, fmodf, $0, $1 + f32.call $push0=, fmodf@FUNCTION, $0, $1 return $pop0 .Lfunc_end0: .size frem32, .Lfunc_end0-frem32 @@ -15,7 +15,7 @@ frem32: frem64: .param f64, f64 .result f64 - f64.call $push0=, fmod, $0, $1 + f64.call $push0=, fmod@FUNCTION, $0, $1 return $pop0 .Lfunc_end1: .size frem64, .Lfunc_end1-frem64 diff --git a/test/llvm_autogenerated/global.s b/test/llvm_autogenerated/global.s index 82b1d75d1..3b2432998 100644 --- a/test/llvm_autogenerated/global.s +++ b/test/llvm_autogenerated/global.s @@ -15,7 +15,7 @@ foo: call_memcpy: .param i32, i32, i32 .result i32 - call memcpy, $0, $1, $2 + call memcpy@FUNCTION, $0, $1, $2 return $0 .Lfunc_end1: .size call_memcpy, .Lfunc_end1-call_memcpy @@ -30,7 +30,7 @@ call_memcpy: .type ud,@object .align 2 ud: - .zero 4 + .skip 4 .size ud, 4 .type nil,@object @@ -58,7 +58,7 @@ u32max: .type ud64,@object .align 3 ud64: - .zero 8 + .skip 8 .size ud64, 8 .type nil64,@object @@ -80,7 +80,7 @@ u64max: .type f32ud,@object .align 2 f32ud: - .zero 4 + .skip 4 .size f32ud, 4 .type f32nil,@object @@ -102,7 +102,7 @@ f32two: .type f64ud,@object .align 3 f64ud: - .zero 8 + .skip 8 .size f64ud, 8 .type f64nil,@object @@ -126,7 +126,7 @@ f64two: .globl arr .align 4 arr: - .zero 512 + .skip 512 .size arr, 512 .type ptr,@object @@ -142,7 +142,7 @@ ptr: .globl rom .align 4 rom: - .zero 512 + .skip 512 .size rom, 512 diff --git a/test/llvm_autogenerated/global.wast b/test/llvm_autogenerated/global.wast index 09cf1a1a2..cc453456c 100644 --- a/test/llvm_autogenerated/global.wast +++ b/test/llvm_autogenerated/global.wast @@ -1,5 +1,5 @@ (module - (memory 1184 4294967295 (segment 4 "9\05\00\00") (segment 20 "\01\00\00\00") (segment 24 "*\00\00\00") (segment 28 "\ff\ff\ff\ff") (segment 56 "\00\00\00\00\00\00\00\00") (segment 64 "\ff\ff\ff\ff\ff\ff\ff\ff") (segment 84 "\00\00\00\80") (segment 88 "\00\00\00@") (segment 120 "\00\00\00\00\00\00\00\00") (segment 128 "\00\00\00\00\00\00\00\00") (segment 656 "\e0\00\00\00")) + (memory 1184 4294967295 (segment 4 "9\05\00\00") (segment 20 "\01\00\00\00") (segment 24 "*\00\00\00") (segment 28 "\ff\ff\ff\ff") (segment 56 "\00\00\00\00\01\00\00\00") (segment 64 "\ff\ff\ff\ff\ff\ff\ff\ff") (segment 84 "\00\00\00\80") (segment 88 "\00\00\00@") (segment 120 "\00\00\00\00\00\00\00\80") (segment 128 "\00\00\00\00\00\00\00@") (segment 656 "\e0\00\00\00")) (import $memcpy "env" "memcpy" (param i32 i32 i32)) (export "foo" $foo) (export "call_memcpy" $call_memcpy) diff --git a/test/llvm_autogenerated/legalize.s b/test/llvm_autogenerated/legalize.s index f675652da..53bd6c1ed 100644 --- a/test/llvm_autogenerated/legalize.s +++ b/test/llvm_autogenerated/legalize.s @@ -74,228 +74,228 @@ bigshift: i64.sub $push1=, $pop0, $17 i32.const $184=, 480 i32.add $184=, $279, $184 - call __lshrti3, $184, $1, $2, $pop1 + call __lshrti3@FUNCTION, $184, $1, $2, $pop1 i64.const $push2=, -768 i64.add $33=, $17, $pop2 i32.const $185=, 464 i32.add $185=, $279, $185 - call __ashlti3, $185, $3, $4, $33 + call __ashlti3@FUNCTION, $185, $3, $4, $33 i64.const $push3=, -896 i64.add $push4=, $17, $pop3 i32.const $186=, 496 i32.add $186=, $279, $186 - call __ashlti3, $186, $1, $2, $pop4 + call __ashlti3@FUNCTION, $186, $1, $2, $pop4 i64.const $push5=, 640 i64.sub $34=, $pop5, $17 i32.const $187=, 352 i32.add $187=, $279, $187 - call __lshrti3, $187, $5, $6, $34 + call __lshrti3@FUNCTION, $187, $5, $6, $34 i64.const $push6=, -512 i64.add $35=, $17, $pop6 i32.const $188=, 336 i32.add $188=, $279, $188 - call __ashlti3, $188, $7, $8, $35 + call __ashlti3@FUNCTION, $188, $7, $8, $35 i64.const $push7=, -640 i64.add $36=, $17, $pop7 i32.const $189=, 368 i32.add $189=, $279, $189 - call __ashlti3, $189, $5, $6, $36 + call __ashlti3@FUNCTION, $189, $5, $6, $36 i64.const $push8=, 768 i64.sub $37=, $pop8, $17 i32.const $190=, 432 i32.add $190=, $279, $190 - call __lshrti3, $190, $3, $4, $37 + call __lshrti3@FUNCTION, $190, $3, $4, $37 i64.const $38=, 384 i64.sub $39=, $38, $17 i32.const $191=, 864 i32.add $191=, $279, $191 - call __lshrti3, $191, $9, $10, $39 + call __lshrti3@FUNCTION, $191, $9, $10, $39 i64.const $push9=, -256 i64.add $40=, $17, $pop9 i32.const $192=, 848 i32.add $192=, $279, $192 - call __ashlti3, $192, $11, $12, $40 + call __ashlti3@FUNCTION, $192, $11, $12, $40 i64.const $push10=, -384 i64.add $41=, $17, $pop10 i32.const $193=, 880 i32.add $193=, $279, $193 - call __ashlti3, $193, $9, $10, $41 + call __ashlti3@FUNCTION, $193, $9, $10, $41 i32.const $194=, 1008 i32.add $194=, $279, $194 - call __ashlti3, $194, $15, $16, $17 + call __ashlti3@FUNCTION, $194, $15, $16, $17 i64.const $42=, 128 i64.sub $51=, $42, $17 i32.const $195=, 960 i32.add $195=, $279, $195 - call __lshrti3, $195, $13, $14, $51 + call __lshrti3@FUNCTION, $195, $13, $14, $51 i64.const $push11=, -128 i64.add $43=, $17, $pop11 i32.const $196=, 976 i32.add $196=, $279, $196 - call __ashlti3, $196, $13, $14, $43 + call __ashlti3@FUNCTION, $196, $13, $14, $43 i64.const $44=, 256 i64.sub $45=, $44, $17 i32.const $197=, 816 i32.add $197=, $279, $197 - call __lshrti3, $197, $11, $12, $45 + call __lshrti3@FUNCTION, $197, $11, $12, $45 i64.const $46=, 512 i64.sub $47=, $46, $17 i32.const $198=, 240 i32.add $198=, $279, $198 - call __lshrti3, $198, $7, $8, $47 + call __lshrti3@FUNCTION, $198, $7, $8, $47 i32.const $199=, 912 i32.add $199=, $279, $199 - call __ashlti3, $199, $11, $12, $17 + call __ashlti3@FUNCTION, $199, $11, $12, $17 i32.const $200=, 928 i32.add $200=, $279, $200 - call __lshrti3, $200, $9, $10, $51 + call __lshrti3@FUNCTION, $200, $9, $10, $51 i32.const $201=, 944 i32.add $201=, $279, $201 - call __ashlti3, $201, $9, $10, $43 + call __ashlti3@FUNCTION, $201, $9, $10, $43 i64.sub $48=, $44, $47 i32.const $202=, 80 i32.add $202=, $279, $202 - call __ashlti3, $202, $7, $8, $48 + call __ashlti3@FUNCTION, $202, $7, $8, $48 i64.sub $push12=, $42, $48 i32.const $203=, 96 i32.add $203=, $279, $203 - call __lshrti3, $203, $5, $6, $pop12 + call __lshrti3@FUNCTION, $203, $5, $6, $pop12 i64.sub $49=, $42, $47 i32.const $204=, 112 i32.add $204=, $279, $204 - call __ashlti3, $204, $5, $6, $49 + call __ashlti3@FUNCTION, $204, $5, $6, $49 i32.const $205=, 48 i32.add $205=, $279, $205 - call __lshrti3, $205, $3, $4, $47 + call __lshrti3@FUNCTION, $205, $3, $4, $47 i32.const $206=, 176 i32.add $206=, $279, $206 - call __lshrti3, $206, $7, $8, $45 + call __lshrti3@FUNCTION, $206, $7, $8, $45 i32.const $207=, 288 i32.add $207=, $279, $207 - call __lshrti3, $207, $1, $2, $34 + call __lshrti3@FUNCTION, $207, $1, $2, $34 i32.const $208=, 272 i32.add $208=, $279, $208 - call __ashlti3, $208, $3, $4, $35 + call __ashlti3@FUNCTION, $208, $3, $4, $35 i32.const $209=, 304 i32.add $209=, $279, $209 - call __ashlti3, $209, $1, $2, $36 + call __ashlti3@FUNCTION, $209, $1, $2, $36 i32.const $210=, 128 i32.add $210=, $279, $210 - call __lshrti3, $210, $5, $6, $45 + call __lshrti3@FUNCTION, $210, $5, $6, $45 i64.sub $push13=, $38, $47 i32.const $211=, 144 i32.add $211=, $279, $211 - call __ashlti3, $211, $7, $8, $pop13 + call __ashlti3@FUNCTION, $211, $7, $8, $pop13 i32.const $212=, 160 i32.add $212=, $279, $212 - call __lshrti3, $212, $7, $8, $51 + call __lshrti3@FUNCTION, $212, $7, $8, $51 i32.const $213=, 0 i32.add $213=, $279, $213 - call __lshrti3, $213, $1, $2, $47 + call __lshrti3@FUNCTION, $213, $1, $2, $47 i32.const $214=, 16 i32.add $214=, $279, $214 - call __ashlti3, $214, $3, $4, $49 + call __ashlti3@FUNCTION, $214, $3, $4, $49 i32.const $215=, 32 i32.add $215=, $279, $215 - call __lshrti3, $215, $3, $4, $39 + call __lshrti3@FUNCTION, $215, $3, $4, $39 i32.const $216=, 64 i32.add $216=, $279, $216 - call __ashlti3, $216, $5, $6, $48 + call __ashlti3@FUNCTION, $216, $5, $6, $48 i32.const $217=, 896 i32.add $217=, $279, $217 - call __ashlti3, $217, $9, $10, $17 + call __ashlti3@FUNCTION, $217, $9, $10, $17 i32.const $218=, 256 i32.add $218=, $279, $218 - call __ashlti3, $218, $1, $2, $35 + call __ashlti3@FUNCTION, $218, $1, $2, $35 i32.const $219=, 192 i32.add $219=, $279, $219 - call __lshrti3, $219, $5, $6, $47 + call __lshrti3@FUNCTION, $219, $5, $6, $47 i32.const $220=, 208 i32.add $220=, $279, $220 - call __ashlti3, $220, $7, $8, $49 + call __ashlti3@FUNCTION, $220, $7, $8, $49 i32.const $221=, 224 i32.add $221=, $279, $221 - call __lshrti3, $221, $7, $8, $39 + call __lshrti3@FUNCTION, $221, $7, $8, $39 i32.const $222=, 768 i32.add $222=, $279, $222 - call __lshrti3, $222, $9, $10, $45 + call __lshrti3@FUNCTION, $222, $9, $10, $45 i64.sub $49=, $42, $45 i32.const $223=, 784 i32.add $223=, $279, $223 - call __ashlti3, $223, $11, $12, $49 + call __ashlti3@FUNCTION, $223, $11, $12, $49 i32.const $224=, 800 i32.add $224=, $279, $224 - call __lshrti3, $224, $11, $12, $51 + call __lshrti3@FUNCTION, $224, $11, $12, $51 i32.const $225=, 992 i32.add $225=, $279, $225 - call __ashlti3, $225, $13, $14, $17 + call __ashlti3@FUNCTION, $225, $13, $14, $17 i32.const $226=, 832 i32.add $226=, $279, $226 - call __ashlti3, $226, $9, $10, $40 + call __ashlti3@FUNCTION, $226, $9, $10, $40 i32.const $227=, 384 i32.add $227=, $279, $227 - call __lshrti3, $227, $1, $2, $37 + call __lshrti3@FUNCTION, $227, $1, $2, $37 i64.sub $push14=, $42, $37 i32.const $228=, 400 i32.add $228=, $279, $228 - call __ashlti3, $228, $3, $4, $pop14 + call __ashlti3@FUNCTION, $228, $3, $4, $pop14 i32.const $229=, 416 i32.add $229=, $279, $229 - call __lshrti3, $229, $3, $4, $34 + call __lshrti3@FUNCTION, $229, $3, $4, $34 i32.const $230=, 320 i32.add $230=, $279, $230 - call __ashlti3, $230, $5, $6, $35 + call __ashlti3@FUNCTION, $230, $5, $6, $35 i32.const $231=, 448 i32.add $231=, $279, $231 - call __ashlti3, $231, $1, $2, $33 + call __ashlti3@FUNCTION, $231, $1, $2, $33 i32.const $232=, 736 i32.add $232=, $279, $232 - call __lshrti3, $232, $1, $2, $39 + call __lshrti3@FUNCTION, $232, $1, $2, $39 i32.const $233=, 720 i32.add $233=, $279, $233 - call __ashlti3, $233, $3, $4, $40 + call __ashlti3@FUNCTION, $233, $3, $4, $40 i32.const $234=, 752 i32.add $234=, $279, $234 - call __ashlti3, $234, $1, $2, $41 + call __ashlti3@FUNCTION, $234, $1, $2, $41 i32.const $235=, 592 i32.add $235=, $279, $235 - call __ashlti3, $235, $7, $8, $17 + call __ashlti3@FUNCTION, $235, $7, $8, $17 i32.const $236=, 608 i32.add $236=, $279, $236 - call __lshrti3, $236, $5, $6, $51 + call __lshrti3@FUNCTION, $236, $5, $6, $51 i32.const $237=, 624 i32.add $237=, $279, $237 - call __ashlti3, $237, $5, $6, $43 + call __ashlti3@FUNCTION, $237, $5, $6, $43 i32.const $238=, 688 i32.add $238=, $279, $238 - call __lshrti3, $238, $3, $4, $45 + call __lshrti3@FUNCTION, $238, $3, $4, $45 i32.const $239=, 640 i32.add $239=, $279, $239 - call __lshrti3, $239, $1, $2, $45 + call __lshrti3@FUNCTION, $239, $1, $2, $45 i32.const $240=, 656 i32.add $240=, $279, $240 - call __ashlti3, $240, $3, $4, $49 + call __ashlti3@FUNCTION, $240, $3, $4, $49 i32.const $241=, 672 i32.add $241=, $279, $241 - call __lshrti3, $241, $3, $4, $51 + call __lshrti3@FUNCTION, $241, $3, $4, $51 i32.const $242=, 576 i32.add $242=, $279, $242 - call __ashlti3, $242, $5, $6, $17 + call __ashlti3@FUNCTION, $242, $5, $6, $17 i32.const $243=, 704 i32.add $243=, $279, $243 - call __ashlti3, $243, $1, $2, $40 + call __ashlti3@FUNCTION, $243, $1, $2, $40 i32.const $244=, 528 i32.add $244=, $279, $244 - call __ashlti3, $244, $3, $4, $17 + call __ashlti3@FUNCTION, $244, $3, $4, $17 i32.const $245=, 544 i32.add $245=, $279, $245 - call __lshrti3, $245, $1, $2, $51 + call __lshrti3@FUNCTION, $245, $1, $2, $51 i32.const $246=, 560 i32.add $246=, $279, $246 - call __ashlti3, $246, $1, $2, $43 + call __ashlti3@FUNCTION, $246, $1, $2, $43 i32.const $247=, 512 i32.add $247=, $279, $247 - call __ashlti3, $247, $1, $2, $17 + call __ashlti3@FUNCTION, $247, $1, $2, $17 i32.const $78=, 8 i32.const $248=, 480 i32.add $248=, $279, $248 diff --git a/test/llvm_autogenerated/offset-folding.s b/test/llvm_autogenerated/offset-folding.s index 6c03d5191..897b0d45a 100644 --- a/test/llvm_autogenerated/offset-folding.s +++ b/test/llvm_autogenerated/offset-folding.s @@ -47,7 +47,7 @@ x: .globl y .align 4 y: - .zero 200 + .skip 200 .size y, 200 diff --git a/test/llvm_autogenerated/signext-zeroext.s b/test/llvm_autogenerated/signext-zeroext.s index eadac8294..395166900 100644 --- a/test/llvm_autogenerated/signext-zeroext.s +++ b/test/llvm_autogenerated/signext-zeroext.s @@ -31,7 +31,7 @@ z2s_call: .result i32 i32.const $push0=, 255 i32.and $push1=, $0, $pop0 - i32.call $push2=, z2s_func, $pop1 + i32.call $push2=, z2s_func@FUNCTION, $pop1 return $pop2 .Lfunc_end2: .size z2s_call, .Lfunc_end2-z2s_call @@ -45,7 +45,7 @@ s2z_call: i32.const $1=, 24 i32.shl $push0=, $0, $1 i32.shr_s $push1=, $pop0, $1 - i32.call $push2=, s2z_func, $pop1 + i32.call $push2=, s2z_func@FUNCTION, $pop1 i32.shl $push3=, $pop2, $1 i32.shr_s $push4=, $pop3, $1 return $pop4 diff --git a/test/llvm_autogenerated/store-results.s b/test/llvm_autogenerated/store-results.s index 563ec01e1..6356d5d92 100644 --- a/test/llvm_autogenerated/store-results.s +++ b/test/llvm_autogenerated/store-results.s @@ -54,7 +54,7 @@ bar: .globl pos .align 2 pos: - .zero 12 + .skip 12 .size pos, 12 diff --git a/test/llvm_autogenerated/switch.s b/test/llvm_autogenerated/switch.s index 635d453c5..35fda0849 100644 --- a/test/llvm_autogenerated/switch.s +++ b/test/llvm_autogenerated/switch.s @@ -16,22 +16,22 @@ bar32: block .LBB0_2 tableswitch $0, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_5, .LBB0_6, .LBB0_7 .LBB0_2: - call foo0 + call foo0@FUNCTION br .LBB0_8 .LBB0_3: - call foo1 + call foo1@FUNCTION br .LBB0_8 .LBB0_4: - call foo2 + call foo2@FUNCTION br .LBB0_8 .LBB0_5: - call foo3 + call foo3@FUNCTION br .LBB0_8 .LBB0_6: - call foo4 + call foo4@FUNCTION br .LBB0_8 .LBB0_7: - call foo5 + call foo5@FUNCTION .LBB0_8: return .Lfunc_end0: @@ -54,22 +54,22 @@ bar64: i32.wrap/i64 $push0=, $0 tableswitch $pop0, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_5, .LBB1_6, .LBB1_7 .LBB1_2: - call foo0 + call foo0@FUNCTION br .LBB1_8 .LBB1_3: - call foo1 + call foo1@FUNCTION br .LBB1_8 .LBB1_4: - call foo2 + call foo2@FUNCTION br .LBB1_8 .LBB1_5: - call foo3 + call foo3@FUNCTION br .LBB1_8 .LBB1_6: - call foo4 + call foo4@FUNCTION br .LBB1_8 .LBB1_7: - call foo5 + call foo5@FUNCTION .LBB1_8: return .Lfunc_end1: diff --git a/test/llvm_autogenerated/unreachable.s b/test/llvm_autogenerated/unreachable.s index bd5f85df6..83ec5b4b1 100644 --- a/test/llvm_autogenerated/unreachable.s +++ b/test/llvm_autogenerated/unreachable.s @@ -4,7 +4,7 @@ .type f1,@function f1: .result i32 - call abort + call abort@FUNCTION unreachable .Lfunc_end0: .size f1, .Lfunc_end0-f1 diff --git a/test/llvm_autogenerated/unused-argument.s b/test/llvm_autogenerated/unused-argument.s index 97d72ee2c..48ab32e38 100644 --- a/test/llvm_autogenerated/unused-argument.s +++ b/test/llvm_autogenerated/unused-argument.s @@ -21,7 +21,7 @@ unused_second: .globl call_something .type call_something,@function call_something: - i32.call $discard=, return_something + i32.call $discard=, return_something@FUNCTION return .Lfunc_end2: .size call_something, .Lfunc_end2-call_something diff --git a/test/llvm_autogenerated/userstack.s b/test/llvm_autogenerated/userstack.s index f3ae1cbca..d77c7bc81 100644 --- a/test/llvm_autogenerated/userstack.s +++ b/test/llvm_autogenerated/userstack.s @@ -67,13 +67,34 @@ allocarray: .Lfunc_end2: .size allocarray, .Lfunc_end2-allocarray + .globl allocarray_inbounds + .type allocarray_inbounds,@function +allocarray_inbounds: + .local i32, i32, i32, i32 + i32.const $0=, __stack_pointer + i32.load $0=, 0($0) + i32.const $1=, 32 + i32.sub $3=, $0, $1 + i32.const $1=, __stack_pointer + i32.store $3=, 0($1), $3 + i32.const $push0=, 1 + i32.store $push1=, 12($3), $pop0 + i32.store $discard=, 16($3), $pop1 + i32.const $2=, 32 + i32.add $3=, $3, $2 + i32.const $2=, __stack_pointer + i32.store $3=, 0($2), $3 + return +.Lfunc_end3: + .size allocarray_inbounds, .Lfunc_end3-allocarray_inbounds + .globl dynamic_alloca .type dynamic_alloca,@function dynamic_alloca: .param i32 return -.Lfunc_end3: - .size dynamic_alloca, .Lfunc_end3-dynamic_alloca +.Lfunc_end4: + .size dynamic_alloca, .Lfunc_end4-dynamic_alloca .section ".note.GNU-stack","",@progbits diff --git a/test/llvm_autogenerated/userstack.wast b/test/llvm_autogenerated/userstack.wast index c2083ce2a..d412410f3 100644 --- a/test/llvm_autogenerated/userstack.wast +++ b/test/llvm_autogenerated/userstack.wast @@ -3,6 +3,7 @@ (export "alloca32" $alloca32) (export "alloca3264" $alloca3264) (export "allocarray" $allocarray) + (export "allocarray_inbounds" $allocarray_inbounds) (export "dynamic_alloca" $dynamic_alloca) (func $alloca32 (local $$0 i32) @@ -205,6 +206,68 @@ ) ) ) + (func $allocarray_inbounds + (local $$0 i32) + (local $$1 i32) + (local $$2 i32) + (local $$3 i32) + (block $fake_return_waka123 + (block + (set_local $$0 + (i32.const 0) + ) + (set_local $$0 + (i32.load align=4 + (get_local $$0) + ) + ) + (set_local $$1 + (i32.const 32) + ) + (set_local $$3 + (i32.sub + (get_local $$0) + (get_local $$1) + ) + ) + (set_local $$1 + (i32.const 0) + ) + (set_local $$3 + (i32.store align=4 + (get_local $$1) + (get_local $$3) + ) + ) + (i32.store offset=16 align=4 + (get_local $$3) + (i32.store offset=12 align=4 + (get_local $$3) + (i32.const 1) + ) + ) + (set_local $$2 + (i32.const 32) + ) + (set_local $$3 + (i32.add + (get_local $$3) + (get_local $$2) + ) + ) + (set_local $$2 + (i32.const 0) + ) + (set_local $$3 + (i32.store align=4 + (get_local $$2) + (get_local $$3) + ) + ) + (br $fake_return_waka123) + ) + ) + ) (func $dynamic_alloca (param $$0 i32) (block $fake_return_waka123 (block diff --git a/test/llvm_autogenerated/varargs.s b/test/llvm_autogenerated/varargs.s index 5159dadca..feb0a2659 100644 --- a/test/llvm_autogenerated/varargs.s +++ b/test/llvm_autogenerated/varargs.s @@ -80,7 +80,7 @@ arg_i128: .globl caller_none .type caller_none,@function caller_none: - call callee + call callee@FUNCTION return .Lfunc_end5: .size caller_none, .Lfunc_end5-caller_none diff --git a/test/passes/O.txt b/test/passes/O.txt index dec081fd4..23b39e920 100644 --- a/test/passes/O.txt +++ b/test/passes/O.txt @@ -20203,7 +20203,7 @@ (call $_frexp (f64.mul (get_local $d1) - (f64.const 18446744073709551616) + (f64.const 18446744073709551615) ) (get_local $i5) ) diff --git a/ubsan.blacklist b/ubsan.blacklist new file mode 100644 index 000000000..cd23680dd --- /dev/null +++ b/ubsan.blacklist @@ -0,0 +1,3 @@ +# Work around libstdc++ bug: https://llvm.org/bugs/show_bug.cgi?id=18156 +# Also see: http://lists.llvm.org/pipermail/cfe-dev/2015-January/040945.html +src:*/ios_base.h |