OSDN Git Service

Subzero, Wasm: Link and run torture tests; bug fixes.
authorEric Holk <eholk@chromium.org>
Mon, 18 Apr 2016 22:08:19 +0000 (15:08 -0700)
committerEric Holk <eholk@chromium.org>
Mon, 18 Apr 2016 22:08:19 +0000 (15:08 -0700)
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 .

c2wasm-exe.sh
fetch-torture-tests.sh
pydir/wasm-run-torture-tests.py
runtime/wasm-runtime.c
src/IceCfg.cpp
src/IceCfgNode.cpp
src/IceCfgNode.h
src/WasmTranslator.cpp

index 4c73ac6..f702988 100755 (executable)
@@ -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
index aef3661..6418417 100755 (executable)
@@ -1,6 +1,6 @@
 #!/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
index c55d94a..7ad50c9 100755 (executable)
 
 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)))
index 0ffb6ca..a7ce49b 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #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));
index 0ff94b4..23c6728 100644 (file)
@@ -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();
index 94acff9..fb3708b 100644 (file)
@@ -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();
 }
 
index 6d7811c..45b25fc 100644 (file)
@@ -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
index 6c1ed24..29f19a4 100644 (file)
@@ -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));