Commit 085bdae2 by Eric Holk

Subzero, Wasm: Link and run torture tests; bug fixes.

This modifies the torture test script to actually link and run the tests in addition to just translating them. It includes a number of bug fixes as well, particularly in the handling of boolean values. There is some cleanup of memory address handling, and in many cases it can avoid generating useless address computations. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4369 R=jpp@chromium.org Review URL: https://codereview.chromium.org/1890283002 .
parent dd6dcfaf
......@@ -4,7 +4,8 @@
# that should be removed.
./wasm-install/bin/emscripten/emcc "$1" -s BINARYEN=1 \
-s 'BINARYEN_METHOD="native-wasm"' -O2 && \
-s 'BINARYEN_METHOD="native-wasm"' -O2 \
--em-config wasm-install/emscripten_config_vanilla && \
./wasm-install/bin/sexpr-wasm a.out.wast -o a.out.wasm && \
./pnacl-sz a.out.wasm -o a.out.o -filetype=obj -O2 && \
clang -m32 a.out.o runtime/wasm-runtime.c -g
#!/bin/bash
BUILDID=4915
BUILDID=5430
BUILD_PATH=https://storage.googleapis.com/wasm-llvm/builds/git
wget -O - /wasm-torture-s-$BUILDID.tbz2 \
......@@ -11,3 +11,7 @@ wget -O - $BUILD_PATH/wasm-torture-s2wasm-sexpr-wasm-$BUILDID.tbz2 \
wget -O - $BUILD_PATH/wasm-binaries-$BUILDID.tbz2 \
| tar xj
wget -O - \
$BUILD_PATH/wasm-torture-/b/build/slave/linux/build/src/src/work/wasm-install/emscripten_config_vanilla-$BUILDID.tbz2 \
| tar xj
......@@ -11,19 +11,68 @@
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"
......@@ -31,13 +80,24 @@ def run_test(test_file, verbose=False):
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
......@@ -45,13 +105,29 @@ if len(sys.argv) > 1:
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)))
......@@ -13,9 +13,12 @@
//===----------------------------------------------------------------------===//
#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[];
......@@ -27,6 +30,11 @@ void env$$abort() {
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"); \
......@@ -34,13 +42,36 @@ void env$$_abort() { env$$abort(); }
}
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.
......@@ -50,12 +81,12 @@ void *wasmPtr(int Index) {
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) {
......@@ -66,6 +97,18 @@ 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));
......
......@@ -266,8 +266,9 @@ void Cfg::fixPhiNodes() {
void Cfg::computeInOutEdges() {
// Compute the out-edges.
for (CfgNode *Node : Nodes)
for (CfgNode *Node : Nodes) {
Node->computeSuccessors();
}
// Prune any unreachable nodes before computing in-edges.
SizeT NumNodes = getNumNodes();
......
......@@ -28,7 +28,7 @@ namespace Ice {
// Adds an instruction to either the Phi list or the regular instruction list.
// Validates that all Phis are added before all regular instructions.
void CfgNode::appendInst(Inst *Instr, bool AllowPhisAnywhere) {
void CfgNode::appendInst(Inst *Instr) {
++InstCountEstimate;
if (BuildDefs::wasm()) {
......@@ -41,7 +41,7 @@ void CfgNode::appendInst(Inst *Instr, bool AllowPhisAnywhere) {
}
if (auto *Phi = llvm::dyn_cast<InstPhi>(Instr)) {
if (!AllowPhisAnywhere && !Insts.empty()) {
if (!Insts.empty()) {
Func->setError("Phi instruction added to the middle of a block");
return;
}
......@@ -84,6 +84,7 @@ void CfgNode::computePredecessors() {
void CfgNode::computeSuccessors() {
OutEdges.clear();
InEdges.clear();
assert(!Insts.empty());
OutEdges = Insts.rbegin()->getTerminatorEdges();
}
......
......@@ -76,7 +76,7 @@ public:
/// @{
InstList &getInsts() { return Insts; }
PhiList &getPhis() { return Phis; }
void appendInst(Inst *Instr, bool AllowPhisAnywhere = false);
void appendInst(Inst *Instr);
void renumberInstructions();
/// Rough and generally conservative estimate of the number of instructions in
/// the block. It is updated when an instruction is added, but not when
......
......@@ -58,6 +58,8 @@ using v8::internal::wasm::DecodeWasmModule;
#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);
......@@ -466,7 +468,7 @@ public:
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:
......@@ -475,7 +477,7 @@ public:
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:
......@@ -484,7 +486,7 @@ public:
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:
......@@ -493,7 +495,7 @@ public:
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:
......@@ -502,7 +504,7 @@ public:
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:
......@@ -511,7 +513,7 @@ public:
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:
......@@ -520,7 +522,7 @@ public:
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:
......@@ -529,7 +531,7 @@ public:
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: {
......@@ -537,7 +539,7 @@ public:
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:
......@@ -546,7 +548,7 @@ public:
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:
......@@ -555,7 +557,7 @@ public:
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:
......@@ -564,7 +566,7 @@ public:
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:
......@@ -585,7 +587,15 @@ public:
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: {
......@@ -673,7 +683,8 @@ public:
<< "\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);
......@@ -898,30 +909,45 @@ public:
}
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;
}
......@@ -1213,15 +1239,12 @@ void WasmTranslator::translate(
}
// 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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment