import glob
import os
+import shutil
import sys
-success_count = 0
-fail_count = 0
-failures = []
+IGNORED_TESTS = [
+ 'loop-2f.c.wasm', # mmap not in MVP
+ 'loop-2g.c.wasm', # mmap not in MVP
+
+ '960521-1.c.wasm', # sbrk not in MVP
+
+ 'pr36765.c.wasm', # __builtin_malloc not allowed
+
+ 'pr24716.c.wasm', # infinite loop
+ 'vla-dealloc-1.c.wasm', # infinite loop
+ '20040811-1.c.wasm', # infinite loop
+ '961125-1.c.wasm', # infinite loop
+ '980506-1.c.wasm', # infinite loop
+ '20070824-1.c.wasm', # infinite loop
+ '20140212-1.c.wasm', # infinite loop
+ 'pr59014.c.wasm', # infinite loop
+ 'pr58277-2.c.wasm', # infinite loop
+ 'pr43560.c.wasm', # infinite loop
+ '20000818-1.c.wasm', # infinite loop
+ '20010409-1.c.wasm', # infinite loop
+ 'loop-7.c.wasm', # infinite loop
+ 'pr34415.c.wasm', # infinite loop
+ '20011126-2.c.wasm', # infinite loop
+ 'postmod-1.c.wasm', # infinite loop
+ 'pr17133.c.wasm', # infinite loop
+ '20021024-1.c.wasm', # infinite loop
+ 'pr15296.c.wasm', # infinite loop
+ '990524-1.c.wasm', # infinite loop
+ 'loop-12.c.wasm', # infinite loop
+ '961125-1.c.wasm', # infinite loop
+]
+
+OUT_DIR = "./build/wasm-torture"
+
+compile_count = 0
+compile_failures = []
+
+run_count = 0
+run_failures = []
def run_test(test_file, verbose=False):
- global success_count
- global fail_count
+ global compile_count
+ global compile_failures
+ global run_count
+ global run_failures
+ global OUT_DIR
+ global IGNORED_TESTS
+
+ test_name = os.path.basename(test_file)
+ obj_file = os.path.join(OUT_DIR, test_name + ".o")
+ exe_file = os.path.join(OUT_DIR, test_name + ".exe")
+
+ if not verbose and test_name in IGNORED_TESTS:
+ print("\033[1;34mSkipping {}\033[1;m".format(test_file))
+ return
cmd = """LD_LIBRARY_PATH=../../../../v8/out/native/lib.target ./pnacl-sz \
- -filetype=asm -target=x8632 {} -threads=0 -O2 \
- -verbose=wasm""".format(test_file)
+ -filetype=obj -target=x8632 {} -threads=0 -O2 \
+ -verbose=wasm -o {}""".format(test_file, obj_file)
if not verbose:
cmd += " &> /dev/null"
sys.stdout.write(test_file + " ...");
status = os.system(cmd);
if status != 0:
- fail_count += 1
- print('\033[1;31m[fail]\033[1;m')
- failures.append(test_file)
+ print('\033[1;31m[compile fail]\033[1;m')
+ compile_failures.append(test_file)
else:
- success_count += 1
- print('\033[1;32m[ok]\033[1;m')
+ compile_count += 1
+ # Try to link and run the program.
+ cmd = "clang -g -m32 {} -o {} ./runtime/wasm-runtime.c".format(obj_file,
+ exe_file)
+ if os.system(cmd) == 0:
+ if os.system(exe_file) == 0:
+ run_count += 1
+ print('\033[1;32m[ok]\033[1;m')
+ else:
+ run_failures.append(test_file)
+ print('\033[1;33m[run fail]\033[1;m')
+ else:
+ run_failures.append(test_file)
+ print('\033[1;33m[run fail]\033[1;m')
verbose = False
test_files = sys.argv[1:]
verbose = True
else:
- test_files = glob.glob("./torture-s2wasm-sexpr-wasm/*.wasm")
+ test_files = glob.glob("./emwasm-torture-out/*.wasm")
+
+if os.path.exists(OUT_DIR):
+ shutil.rmtree(OUT_DIR)
+os.mkdir(OUT_DIR)
for test_file in test_files:
run_test(test_file, verbose)
-if len(failures) > 0:
- print("Failures:")
- for f in failures:
- print(" \033[1;31m" + f + "\033[1;m")
-print("{} / {} tests passed".format(success_count, success_count + fail_count))
+if len(compile_failures) > 0:
+ print
+ print("Compilation failures:")
+ print("=====================\n")
+ for f in compile_failures:
+ print(" \033[1;31m" + f + "\033[1;m")
+
+if len(run_failures) > 0:
+ print
+ print("Run failures:")
+ print("=============\n")
+ for f in run_failures:
+ print(" \033[1;33m" + f + "\033[1;m")
+
+print("\n\033[1;32m{}\033[1;m / \033[1;33m{}\033[1;m / {} tests passed"
+ .format(run_count, compile_count - run_count,
+ run_count + len(compile_failures) + len(run_failures)))
//===----------------------------------------------------------------------===//
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
extern char WASM_MEMORY[];
void env$$_abort() { env$$abort(); }
+void env$$exit(int Status) {
+ exit(Status);
+}
+void env$$_exit(int Status) { env$$exit(Status); }
+
#define UNIMPLEMENTED(f) \
void env$$##f() { \
fprintf(stderr, "Unimplemented: " #f "\n"); \
}
UNIMPLEMENTED(sbrk)
+UNIMPLEMENTED(setjmp)
+UNIMPLEMENTED(longjmp)
+UNIMPLEMENTED(__assert_fail)
+UNIMPLEMENTED(__builtin_malloc)
+UNIMPLEMENTED(__builtin_apply)
+UNIMPLEMENTED(__builtin_apply_args)
UNIMPLEMENTED(pthread_cleanup_push)
UNIMPLEMENTED(pthread_cleanup_pop)
UNIMPLEMENTED(pthread_self)
+UNIMPLEMENTED(abs)
+UNIMPLEMENTED(__floatditf)
+UNIMPLEMENTED(__floatsitf)
+UNIMPLEMENTED(__fixtfdi)
+UNIMPLEMENTED(__fixtfsi)
+UNIMPLEMENTED(__fixsfti)
+UNIMPLEMENTED(__netf2)
+UNIMPLEMENTED(__getf2)
+UNIMPLEMENTED(__eqtf2)
+UNIMPLEMENTED(__lttf2)
+UNIMPLEMENTED(__addtf3)
+UNIMPLEMENTED(__subtf3)
+UNIMPLEMENTED(__divtf3)
+UNIMPLEMENTED(__multf3)
+UNIMPLEMENTED(__multi3)
UNIMPLEMENTED(__lock)
UNIMPLEMENTED(__unlock)
UNIMPLEMENTED(__syscall6)
+UNIMPLEMENTED(__syscall20)
UNIMPLEMENTED(__syscall140)
+UNIMPLEMENTED(__syscall192)
void *wasmPtr(int Index) {
// TODO (eholk): get the mask from the WASM file.
return WASM_MEMORY + Index;
}
-extern int __szwasm_main(int, char **);
+extern int __szwasm_main(int, const char **);
#define WASM_REF(Type, Index) ((Type *)wasmPtr(Index))
#define WASM_DEREF(Type, Index) (*WASM_REF(Type, Index))
-int main(int argc, char **argv) { return __szwasm_main(argc, argv); }
+int main(int argc, const char **argv) { return __szwasm_main(argc, argv); }
/// sys_write
int env$$__syscall4(int Which, int VarArgs) {
return write(Fd, WASM_REF(char *, Buffer), Length);
}
+/// sys_open
+int env$$__syscall5(int Which, int VarArgs) {
+ int WasmPath = WASM_DEREF(int, VarArgs);
+ int Flags = WASM_DEREF(int, VarArgs + 4);
+ int Mode = WASM_DEREF(int, VarArgs + 8);
+ const char *Path = WASM_REF(char, WasmPath);
+
+ fprintf(stderr, "sys_open(%s, %d, %d)\n", Path, Flags, Mode);
+
+ return open(Path, Flags, Mode);
+}
+
/// sys_ioctl
int env$$__syscall54(int A, int B) {
int Fd = WASM_DEREF(int, B + 0 * sizeof(int));
#define LOG(Expr) log([&](Ostream & out) { Expr; })
namespace {
+// 64KB
+const uint32_t WASM_PAGE_SIZE = 64 << 10;
std::string toStdString(WasmName Name) {
return std::string(Name.name, Name.length);
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Ne, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32Eq:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Eq, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32LtS:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Slt, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32LeS:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Sle, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32GeU:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Uge, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32LeU:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Ule, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32LtU:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Ult, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32GeS:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Sge, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
}
case kExprI32GtS:
case kExprI64GtS: {
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Sgt, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32GtU:
Control()->appendInst(
InstIcmp::create(Func, InstIcmp::Ugt, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprF32Ne:
Control()->appendInst(
InstFcmp::create(Func, InstFcmp::Une, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprF32Le:
Control()->appendInst(
InstFcmp::create(Func, InstFcmp::Ule, TmpDest, Left, Right));
Control()->appendInst(
- InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
+ InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
default:
auto *Tmp = makeVariable(IceType_i1);
Control()->appendInst(InstIcmp::create(Func, InstIcmp::Eq, Tmp, Input,
Ctx->getConstantInt32(0)));
- Control()->appendInst(InstCast::create(Func, InstCast::Sext, Dest, Tmp));
+ Control()->appendInst(InstCast::create(Func, InstCast::Zext, Dest, Tmp));
+ break;
+ }
+ case kExprI64Eqz: {
+ Dest = makeVariable(IceType_i32);
+ auto *Tmp = makeVariable(IceType_i1);
+ Control()->appendInst(InstIcmp::create(Func, InstIcmp::Eq, Tmp, Input,
+ Ctx->getConstantInt64(0)));
+ Control()->appendInst(InstCast::create(Func, InstCast::Zext, Dest, Tmp));
break;
}
case kExprF32Neg: {
<< "\n");
auto *CondBool = makeVariable(IceType_i1);
- Ctrl->appendInst(InstCast::create(Func, InstCast::Trunc, CondBool, Cond));
+ Ctrl->appendInst(InstIcmp::create(Func, InstIcmp::Ne, CondBool, Cond,
+ Ctx->getConstantInt32(0)));
Ctrl->appendInst(InstBr::create(Func, CondBool, *TrueNode, *FalseNode));
return OperandNode(nullptr);
}
Operand *sanitizeAddress(Operand *Base, uint32_t Offset) {
+ SizeT MemSize = Module->module->min_mem_pages * WASM_PAGE_SIZE;
+ SizeT MemMask = MemSize - 1;
+
+ bool ConstZeroBase = false;
+
// first, add the index and the offset together.
- if (0 != Offset) {
- auto *Addr = makeVariable(IceType_i32);
+ if (auto *ConstBase = llvm::dyn_cast<ConstantInteger32>(Base)) {
+ uint32_t RealOffset = Offset + ConstBase->getValue();
+ RealOffset &= MemMask;
+ Base = Ctx->getConstantInt32(RealOffset);
+ ConstZeroBase = (0 == RealOffset);
+ } else if (0 != Offset) {
+ auto *Addr = makeVariable(Ice::getPointerType());
auto *OffsetConstant = Ctx->getConstantInt32(Offset);
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Add,
Addr, Base, OffsetConstant));
+
Base = Addr;
}
- SizeT MemSize = Module->module->min_mem_pages * (16 << 10);
- auto *WrappedAddr = makeVariable(IceType_i32);
- Control()->appendInst(
- InstArithmetic::create(Func, InstArithmetic::Add, WrappedAddr, Base,
- Ctx->getConstantInt32(MemSize)));
-
- auto ClampedAddr = makeVariable(IceType_i32);
- Control()->appendInst(
- InstArithmetic::create(Func, InstArithmetic::And, ClampedAddr, Base,
- Ctx->getConstantInt32(MemSize - 1)));
+ if (!llvm::dyn_cast<ConstantInteger32>(Base)) {
+ auto *ClampedAddr = makeVariable(Ice::getPointerType());
+ Control()->appendInst(
+ InstArithmetic::create(Func, InstArithmetic::And, ClampedAddr, Base,
+ Ctx->getConstantInt32(MemSize - 1)));
+ Base = ClampedAddr;
+ }
- auto RealAddr = Func->makeVariable(IceType_i32);
+ Ice::Operand *RealAddr = nullptr;
auto MemBase = Ctx->getConstantSym(0, Ctx->getGlobalString("WASM_MEMORY"));
- Control()->appendInst(InstArithmetic::create(
- Func, InstArithmetic::Add, RealAddr, ClampedAddr, MemBase));
+ if (!ConstZeroBase) {
+ auto RealAddrV = Func->makeVariable(Ice::getPointerType());
+ Control()->appendInst(InstArithmetic::create(
+ Func, InstArithmetic::Add, RealAddrV, Base, MemBase));
+
+ RealAddr = RealAddrV;
+ } else {
+ RealAddr = MemBase;
+ }
return RealAddr;
}
}
// Pad the rest with zeros
- SizeT DataSize = Module->min_mem_pages * (64 << 10);
+ SizeT DataSize = Module->min_mem_pages * WASM_PAGE_SIZE;
if (WritePtr < DataSize) {
WasmMemory->addInitializer(VariableDeclaration::ZeroInitializer::create(
Globals.get(), DataSize - WritePtr));
}
- WasmMemory->addInitializer(VariableDeclaration::ZeroInitializer::create(
- Globals.get(), Module->min_mem_pages * (64 << 10)));
-
Globals->push_back(WasmMemory);
lowerGlobals(std::move(Globals));