Commit 29acb575 by Eric Holk

Subzero - WASM: Codegen fixes, better test infrastructure

Fixes several bugs in code generation, including handling of booleans, comparisons and shifts. The tests that get through code generation now run successfully (except for the tests that are known to fail on https://wasm-stat.us/). This change also includes improvements to the test infrastructure. The wasm test runner has a list of expected failures to skip. The tests now run in parallel, which significantly cuts down the time to run the whole test suite. Finally, there are some minor improvements to the WASM runtime, including an implementation of syscall20, i.e. getpid(). BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4369 R=kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/1900213002 .
parent cd261e91
......@@ -4,8 +4,9 @@
# that should be removed.
./wasm-install/bin/emscripten/emcc "$1" -s BINARYEN=1 \
-s 'BINARYEN_METHOD="native-wasm"' -O2 \
-s 'BINARYEN_METHOD="native-wasm"' \
--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
clang -m32 a.out.o ./runtime/szrt.c \
./runtime/wasm-runtime.cpp -lm -g
......@@ -9,45 +9,131 @@
#
#===-----------------------------------------------------------------------===//
from __future__ import print_function
import argparse
import glob
import multiprocessing
import os
import Queue
import shutil
import StringIO
import sys
import threading
IGNORED_TESTS = [
IGNORED_TESTS = set([
'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
]
'960521-1.c.wasm', # sbrk
'ipa-sra-2.c.wasm', # sbrk
'pr41463.c.wasm', # sbrk
'20051113-1.c.wasm', # sbrk
'990628-1.c.wasm', # sbrk
'pr41395-2.c.wasm', # sbrk
'pr42614.c.wasm', # sbrk
'pr41395-1.c.wasm', # sbrk
'920810-1.c.wasm', # sbrk
'20000914-1.c.wasm', # sbrk
'pr15262-1.c.wasm', # sbrk
'941014-2.c.wasm', # sbrk
'va-arg-21.c.wasm', # sbrk
'20020406-1.c.wasm', # sbrk
# waterfall known failures
'20010122-1.c.wasm',
'20031003-1.c.wasm',
'20071018-1.c.wasm',
'20071120-1.c.wasm',
'20071220-1.c.wasm',
'20071220-2.c.wasm',
'20101011-1.c.wasm',
'alloca-1.c.wasm',
'bitfld-3.c.wasm',
'bitfld-5.c.wasm',
'builtin-bitops-1.c.wasm',
'conversion.c.wasm',
'eeprof-1.c.wasm',
'frame-address.c.wasm',
'pr17377.c.wasm',
'pr32244-1.c.wasm',
'pr34971.c.wasm',
'pr36765.c.wasm',
'pr39228.c.wasm',
'pr43008.c.wasm',
'pr47237.c.wasm',
'pr60960.c.wasm',
'va-arg-pack-1.c.wasm',
'20000717-5.c.wasm', # abort() (also works without emcc)
'20001203-2.c.wasm', # assert fail (works without emcc)
'20040811-1.c.wasm', # OOB trap
'20070824-1.c.wasm', # abort() (also works without emcc)
'arith-rand-ll.c.wasm', # abort() (works without emcc)
'arith-rand.c.wasm', # abort() (works without emcc)
'pr23135.c.wasm', # OOB trap (works without emcc)
'pr34415.c.wasm', # (empty output?)
'pr36339.c.wasm', # abort() (works without emcc)
'pr38048-2.c.wasm', # abort() (works without emcc)
'pr42691.c.wasm', # abort() (works without emcc)
'pr43220.c.wasm', # OOB trap (works without emcc)
'pr43269.c.wasm', # abort() (works without emcc)
'vla-dealloc-1.c.wasm', # OOB trap (works without emcc)
'20051012-1.c.wasm', # error reading binary
'921208-2.c.wasm', # error reading binary
'920501-1.c.wasm', # error reading binary
'call-trap-1.c.wasm', # error reading binary
'pr44942.c.wasm', # error reading binary
'920625-1.c.wasm', # abort() (also fails without emcc)
'931004-10.c.wasm', # abort() (also fails without emcc)
'931004-12.c.wasm', # abort() (also fails without emcc)
'931004-14.c.wasm', # abort() (also fails without emcc)
'931004-6.c.wasm', # abort() (also fails without emcc)
'pr38051.c.wasm', # (empty output?) (fails without emcc)
'pr38151.c.wasm', # abort() (fails without emcc)
'pr44575.c.wasm', # abort() (fails without emcc)
'strct-stdarg-1.c.wasm', # abort() (fails without emcc)
'strct-varg-1.c.wasm', # abort() (fails without emcc)
'va-arg-22.c.wasm', # abort() (fails without emcc)
'stdarg-3.c.wasm', # abort() (fails without emcc)
'pr56982.c.wasm', # missing setjmp (wasm.js check did not catch)
'20010605-2.c.wasm', # missing __netf2
'20020413-1.c.wasm', # missing __lttf2
'20030914-1.c.wasm', # missing __floatsitf
'20040709-1.c.wasm', # missing __netf2
'20040709-2.c.wasm', # missing __netf2
'20050121-1.c.wasm', # missing __floatsitf
'20080502-1.c.wasm', # missing __eqtf2
'920501-8.c.wasm', # missing __extenddftf2
'930513-1.c.wasm', # missing __extenddftf2
'930622-2.c.wasm', # missing __floatditf
'960215-1.c.wasm', # missing __addtf3
'960405-1.c.wasm', # missing __eqtf2
'960513-1.c.wasm', # missing __subtf3
'align-2.c.wasm', # missing __eqtf2
'complex-6.c.wasm', # missing __subtf3
'complex-7.c.wasm', # missing __netf2
'pr49218.c.wasm', # missing __fixsfti
'pr54471.c.wasm', # missing __multi3
'regstack-1.c.wasm', # missing __addtf3
'stdarg-1.c.wasm', # missing __netf2
'stdarg-2.c.wasm', # missing __floatsitf
'va-arg-5.c.wasm', # missing __eqtf2
'va-arg-6.c.wasm', # missing __eqtf2
'struct-ret-1.c.wasm', # missing __extenddftf2
])
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('--translate-only', action='store_true')
parser.add_argument('tests', nargs='*')
args = parser.parse_args()
OUT_DIR = "./build/wasm-torture"
results_lock = threading.Lock()
compile_count = 0
compile_failures = []
......@@ -55,13 +141,17 @@ run_count = 0
run_failures = []
def run_test(test_file, verbose=False):
global args
global compile_count
global compile_failures
global results_lock
global run_count
global run_failures
global OUT_DIR
global IGNORED_TESTS
run_test = not args.translate_only
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")
......@@ -77,33 +167,42 @@ def run_test(test_file, verbose=False):
if not verbose:
cmd += " &> /dev/null"
sys.stdout.write(test_file + " ...");
out = StringIO.StringIO()
out.write(test_file + " ...");
status = os.system(cmd);
if status != 0:
print('\033[1;31m[compile fail]\033[1;m')
compile_failures.append(test_file)
print('\033[1;31m[compile fail]\033[1;m', file=out)
with results_lock:
compile_failures.append(test_file)
else:
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')
cmd = "clang -g -m32 {} -o {} " + \
"./runtime/szrt.c ./runtime/wasm-runtime.cpp -lm"
cmd = cmd.format(obj_file, exe_file)
if not run_test or os.system(cmd) == 0:
if not run_test or os.system(exe_file) == 0:
with results_lock:
run_count += 1
print('\033[1;32m[ok]\033[1;m', file=out)
else:
run_failures.append(test_file)
print('\033[1;33m[run fail]\033[1;m')
with results_lock:
run_failures.append(test_file)
print('\033[1;33m[run fail]\033[1;m', file=out)
else:
run_failures.append(test_file)
print('\033[1;33m[run fail]\033[1;m')
with results_lock:
run_failures.append(test_file)
print('\033[1;33m[run fail]\033[1;m', file=out)
verbose = False
sys.stdout.write(out.getvalue())
if len(sys.argv) > 1:
test_files = sys.argv[1:]
verbose = True
verbose = args.verbose
if len(args.tests) > 0:
test_files = args.tests
else:
test_files = glob.glob("./emwasm-torture-out/*.wasm")
......@@ -111,18 +210,32 @@ if os.path.exists(OUT_DIR):
shutil.rmtree(OUT_DIR)
os.mkdir(OUT_DIR)
tasks = Queue.Queue()
def worker():
while True:
run_test(tasks.get(), verbose)
tasks.task_done()
for i in range(multiprocessing.cpu_count()):
t = threading.Thread(target=worker)
t.daemon = True
t.start()
for test_file in test_files:
run_test(test_file, verbose)
tasks.put(test_file)
tasks.join()
if len(compile_failures) > 0:
print
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()
print("Run failures:")
print("=============\n")
for f in run_failures:
......
//===- subzero/runtime/wasm-runtime.c - Subzero WASM runtime source -------===//
//===- subzero/runtime/wasm-runtime.cpp - Subzero WASM runtime source -----===//
//
// The Subzero Code Generator
//
......@@ -12,8 +12,19 @@
//
//===----------------------------------------------------------------------===//
#include <cmath>
namespace env {
double floor(double X) { return std::floor(X); }
float floor(float X) { return std::floor(X); }
}
// TODO (eholk): move the C parts outside and use C++ name mangling.
extern "C" {
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -30,6 +41,9 @@ void env$$abort() {
void env$$_abort() { env$$abort(); }
double env$$floor_f(float X) { return env::floor(X); }
double env$$floor_d(double X) { return env::floor(X); }
void env$$exit(int Status) { exit(Status); }
void env$$_exit(int Status) { env$$exit(Status); }
......@@ -44,12 +58,13 @@ UNIMPLEMENTED(setjmp)
UNIMPLEMENTED(longjmp)
UNIMPLEMENTED(__assert_fail)
UNIMPLEMENTED(__builtin_malloc)
UNIMPLEMENTED(__builtin_isinff)
UNIMPLEMENTED(__builtin_isinfl)
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)
......@@ -66,14 +81,17 @@ UNIMPLEMENTED(__multf3)
UNIMPLEMENTED(__multi3)
UNIMPLEMENTED(__lock)
UNIMPLEMENTED(__unlock)
UNIMPLEMENTED(__syscall6)
UNIMPLEMENTED(__syscall20)
UNIMPLEMENTED(__syscall140)
UNIMPLEMENTED(__syscall192)
UNIMPLEMENTED(__syscall6) // sys_close
UNIMPLEMENTED(__syscall140) // sys_llseek
UNIMPLEMENTED(__syscall192) // sys_mmap?
UNIMPLEMENTED(__unordtf2)
UNIMPLEMENTED(__fixunstfsi)
UNIMPLEMENTED(__floatunsitf)
UNIMPLEMENTED(__extenddftf2)
void *wasmPtr(int Index) {
// TODO (eholk): get the mask from the WASM file.
const int MASK = 0x3fffff;
const int MASK = 0xffffff;
Index &= MASK;
return WASM_MEMORY + Index;
......@@ -86,6 +104,10 @@ extern int __szwasm_main(int, const char **);
int main(int argc, const char **argv) { return __szwasm_main(argc, argv); }
int env$$abs(int a) { return abs(a); }
double env$$pow(double x, double y) { return pow(x, y); }
/// sys_write
int env$$__syscall4(int Which, int VarArgs) {
int Fd = WASM_DEREF(int, VarArgs + 0 * sizeof(int));
......@@ -107,6 +129,14 @@ int env$$__syscall5(int Which, int VarArgs) {
return open(Path, Flags, Mode);
}
/// sys_getpid
int env$$__syscall20(int Which, int VarArgs) {
(void)Which;
(void)VarArgs;
return getpid();
}
/// sys_ioctl
int env$$__syscall54(int A, int B) {
int Fd = WASM_DEREF(int, B + 0 * sizeof(int));
......@@ -116,32 +146,26 @@ int env$$__syscall54(int A, int B) {
return -ENOTTY;
}
/// sys_write
int env$$__syscall146(int Which, int VarArgs) {
fprintf(stderr, "syscall146\n");
int Fd = WASM_DEREF(int, VarArgs);
int Iov = WASM_DEREF(int, VarArgs + sizeof(int));
int Iovcnt = WASM_DEREF(int, VarArgs + 2 * sizeof(int));
fprintf(stderr, " Fd=%d, Iov=%d (%p), Iovcnt=%d\n", Fd, Iov, wasmPtr(Iov),
Iovcnt);
int Count = 0;
for (int I = 0; I < Iovcnt; ++I) {
void *Ptr = WASM_REF(void, WASM_DEREF(int, Iov + I * 8));
int Length = WASM_DEREF(int, Iov + I * 8 + 4);
fprintf(stderr, " [%d] write(%d, %p, %d) = ", I, Fd, Ptr, Length);
int Curr = write(Fd, Ptr, Length);
fprintf(stderr, "%d\n", Curr);
if (Curr < 0) {
return -1;
}
Count += Curr;
}
fprintf(stderr, " Count = %d\n", Count);
return Count;
}
} // end of extern "C"
......@@ -229,10 +229,18 @@ bool isComparison(wasm::WasmOpcode Opcode) {
case kExprI64GtS:
case kExprI32GtU:
case kExprI64GtU:
case kExprF32Eq:
case kExprF64Eq:
case kExprF32Ne:
case kExprF64Ne:
case kExprF32Le:
case kExprF64Le:
case kExprF32Lt:
case kExprF64Lt:
case kExprF32Ge:
case kExprF64Ge:
case kExprF32Gt:
case kExprF64Gt:
case kExprI32LeS:
case kExprI64LeS:
case kExprI32GeU:
......@@ -320,11 +328,11 @@ public:
auto *Dest = makeVariable(Vals[0].toOperand()->getType(), Control);
// Multiply by 10 in case more things get added later.
// Multiply by 200 in case more things get added later.
// TODO(eholk): find a better way besides multiplying by some arbitrary
// constant.
auto *Phi = InstPhi::create(Func, Count * 10, Dest);
auto *Phi = InstPhi::create(Func, Count * 200, Dest);
for (uint32_t i = 0; i < Count; ++i) {
auto *Op = Vals[i].toOperand();
assert(Op);
......@@ -393,16 +401,36 @@ public:
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::Sub, Dest, Left, Right));
break;
case kExprF32Sub:
case kExprF64Sub:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fsub,
Dest, Left, Right));
break;
case kExprI32Mul:
case kExprI64Mul:
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::Mul, Dest, Left, Right));
break;
case kExprF32Mul:
case kExprF64Mul:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fmul,
Dest, Left, Right));
break;
case kExprI32DivS:
case kExprI64DivS:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Sdiv,
Dest, Left, Right));
break;
case kExprI32DivU:
case kExprI64DivU:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Udiv,
Dest, Left, Right));
break;
case kExprF32Div:
case kExprF64Div:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fdiv,
Dest, Left, Right));
break;
case kExprI32RemU:
case kExprI64RemU:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Urem,
......@@ -428,30 +456,63 @@ public:
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::Shl, Dest, Left, Right));
break;
case kExprI32Rol: {
case kExprI32Rol:
case kExprI64Rol: {
// TODO(eholk): add rotate as an ICE instruction to make it easier to take
// advantage of hardware support.
// TODO(eholk): don't hardcode so many numbers.
auto *Masked = makeVariable(IceType_i32);
auto *Bottom = makeVariable(IceType_i32);
auto *Top = makeVariable(IceType_i32);
Control()->appendInst(InstArithmetic::create(
Func, InstArithmetic::And, Masked, Right, Ctx->getConstantInt32(31)));
const auto DestTy = Left.toOperand()->getType();
const SizeT BitCount = typeWidthInBytes(DestTy) * CHAR_BIT;
auto *Masked = makeVariable(DestTy);
auto *Bottom = makeVariable(DestTy);
auto *Top = makeVariable(DestTy);
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::And, Masked, Right,
Ctx->getConstantInt(DestTy, BitCount - 1)));
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::Shl, Top, Left, Masked));
auto *RotShift = makeVariable(IceType_i32);
auto *RotShift = makeVariable(DestTy);
Control()->appendInst(InstArithmetic::create(
Func, InstArithmetic::Sub, RotShift,
Ctx->getConstantInt(DestTy, BitCount), Masked));
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Lshr,
Bottom, Left, RotShift));
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::Or, Dest, Top, Bottom));
break;
}
case kExprI32Ror:
case kExprI64Ror: {
// TODO(eholk): add rotate as an ICE instruction to make it easier to take
// advantage of hardware support.
const auto DestTy = Left.toOperand()->getType();
const SizeT BitCount = typeWidthInBytes(DestTy) * CHAR_BIT;
auto *Masked = makeVariable(DestTy);
auto *Bottom = makeVariable(DestTy);
auto *Top = makeVariable(DestTy);
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::Sub, RotShift,
Ctx->getConstantInt32(32), Masked));
InstArithmetic::create(Func, InstArithmetic::And, Masked, Right,
Ctx->getConstantInt(DestTy, BitCount - 1)));
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Lshr,
Bottom, Left, Masked));
Top, Left, Masked));
auto *RotShift = makeVariable(DestTy);
Control()->appendInst(InstArithmetic::create(
Func, InstArithmetic::Sub, RotShift,
Ctx->getConstantInt(DestTy, BitCount), Masked));
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Shl,
Bottom, Left, RotShift));
Control()->appendInst(
InstArithmetic::create(Func, InstArithmetic::Or, Dest, Top, Bottom));
break;
}
case kExprI32ShrU:
case kExprI64ShrU:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Lshr,
Dest, Left, Right));
break;
case kExprI32ShrS:
case kExprI64ShrS:
Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Ashr,
......@@ -532,6 +593,7 @@ public:
InstIcmp::create(Func, InstIcmp::Sge, TmpDest, Left, Right));
Control()->appendInst(
InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprI32GtS:
case kExprI64GtS: {
......@@ -551,6 +613,15 @@ public:
InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprF32Eq:
case kExprF64Eq: {
auto *TmpDest = makeVariable(IceType_i1);
Control()->appendInst(
InstFcmp::create(Func, InstFcmp::Ueq, TmpDest, Left, Right));
Control()->appendInst(
InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprF32Ne:
case kExprF64Ne: {
auto *TmpDest = makeVariable(IceType_i1);
......@@ -569,6 +640,33 @@ public:
InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprF32Lt:
case kExprF64Lt: {
auto *TmpDest = makeVariable(IceType_i1);
Control()->appendInst(
InstFcmp::create(Func, InstFcmp::Ult, TmpDest, Left, Right));
Control()->appendInst(
InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprF32Ge:
case kExprF64Ge: {
auto *TmpDest = makeVariable(IceType_i1);
Control()->appendInst(
InstFcmp::create(Func, InstFcmp::Uge, TmpDest, Left, Right));
Control()->appendInst(
InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
case kExprF32Gt:
case kExprF64Gt: {
auto *TmpDest = makeVariable(IceType_i1);
Control()->appendInst(
InstFcmp::create(Func, InstFcmp::Ugt, TmpDest, Left, Right));
Control()->appendInst(
InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
break;
}
default:
LOG(out << "Unknown binop: " << WasmOpcodes::OpcodeName(Opcode) << "\n");
llvm::report_fatal_error("Uncovered or invalid binop.");
......@@ -598,6 +696,20 @@ public:
Control()->appendInst(InstCast::create(Func, InstCast::Zext, Dest, Tmp));
break;
}
case kExprI32Ctz: {
Dest = makeVariable(IceType_i32);
const auto FnName = Ctx->getGlobalString("llvm.cttz.i32");
bool BadInstrinsic = false;
const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
assert(!BadInstrinsic);
assert(Info);
auto *Call = InstIntrinsicCall::create(
Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
Call->addArg(Input);
Control()->appendInst(Call);
break;
}
case kExprF32Neg: {
Dest = makeVariable(IceType_f32);
Control()->appendInst(InstArithmetic::create(
......@@ -610,6 +722,56 @@ public:
Func, InstArithmetic::Fsub, Dest, Ctx->getConstantDouble(0), Input));
break;
}
case kExprF32Abs: {
Dest = makeVariable(IceType_f32);
const auto FnName = Ctx->getGlobalString("llvm.fabs.f32");
bool BadInstrinsic = false;
const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
assert(!BadInstrinsic);
assert(Info);
auto *Call = InstIntrinsicCall::create(
Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
Call->addArg(Input);
Control()->appendInst(Call);
break;
}
case kExprF64Abs: {
Dest = makeVariable(IceType_f64);
const auto FnName = Ctx->getGlobalString("llvm.fabs.f64");
bool BadInstrinsic = false;
const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
assert(!BadInstrinsic);
assert(Info);
auto *Call = InstIntrinsicCall::create(
Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
Call->addArg(Input);
Control()->appendInst(Call);
break;
}
case kExprF32Floor: {
Dest = makeVariable(IceType_f64);
const auto FnName = Ctx->getGlobalString("env$$floor_f");
constexpr bool HasTailCall = false;
auto *Call = InstCall::create(
Func, 1, Dest, Ctx->getConstantExternSym(FnName), HasTailCall);
Call->addArg(Input);
Control()->appendInst(Call);
break;
}
case kExprF64Floor: {
Dest = makeVariable(IceType_f64);
const auto FnName = Ctx->getGlobalString("env$$floor_d");
constexpr bool HasTailCall = false;
auto *Call = InstCall::create(
Func, 1, Dest, Ctx->getConstantExternSym(FnName), HasTailCall);
Call->addArg(Input);
Control()->appendInst(Call);
break;
}
case kExprI64UConvertI32:
Dest = makeVariable(IceType_i64);
Control()->appendInst(
......@@ -620,6 +782,41 @@ public:
Control()->appendInst(
InstCast::create(Func, InstCast::Sext, Dest, Input));
break;
case kExprI32SConvertF32:
Dest = makeVariable(IceType_i32);
Control()->appendInst(
InstCast::create(Func, InstCast::Fptosi, Dest, Input));
break;
case kExprI32UConvertF32:
Dest = makeVariable(IceType_i32);
Control()->appendInst(
InstCast::create(Func, InstCast::Fptoui, Dest, Input));
break;
case kExprI32SConvertF64:
Dest = makeVariable(IceType_i32);
Control()->appendInst(
InstCast::create(Func, InstCast::Fptosi, Dest, Input));
break;
case kExprI32UConvertF64:
Dest = makeVariable(IceType_i32);
Control()->appendInst(
InstCast::create(Func, InstCast::Fptoui, Dest, Input));
break;
case kExprI32ReinterpretF32:
Dest = makeVariable(IceType_i32);
Control()->appendInst(
InstCast::create(Func, InstCast::Bitcast, Dest, Input));
break;
case kExprI64ReinterpretF64:
Dest = makeVariable(IceType_i64);
Control()->appendInst(
InstCast::create(Func, InstCast::Bitcast, Dest, Input));
break;
case kExprF64ReinterpretI64:
Dest = makeVariable(IceType_f64);
Control()->appendInst(
InstCast::create(Func, InstCast::Bitcast, Dest, Input));
break;
case kExprI32ConvertI64:
Dest = makeVariable(IceType_i32);
Control()->appendInst(
......@@ -630,6 +827,36 @@ public:
Control()->appendInst(
InstCast::create(Func, InstCast::Sitofp, Dest, Input));
break;
case kExprF64UConvertI32:
Dest = makeVariable(IceType_f64);
Control()->appendInst(
InstCast::create(Func, InstCast::Uitofp, Dest, Input));
break;
case kExprF64ConvertF32:
Dest = makeVariable(IceType_f64);
Control()->appendInst(
InstCast::create(Func, InstCast::Fpext, Dest, Input));
break;
case kExprF32SConvertI32:
Dest = makeVariable(IceType_f32);
Control()->appendInst(
InstCast::create(Func, InstCast::Sitofp, Dest, Input));
break;
case kExprF32UConvertI32:
Dest = makeVariable(IceType_f32);
Control()->appendInst(
InstCast::create(Func, InstCast::Uitofp, Dest, Input));
break;
case kExprF32ReinterpretI32:
Dest = makeVariable(IceType_f32);
Control()->appendInst(
InstCast::create(Func, InstCast::Bitcast, Dest, Input));
break;
case kExprF32ConvertF64:
Dest = makeVariable(IceType_f32);
Control()->appendInst(
InstCast::create(Func, InstCast::Fptrunc, Dest, Input));
break;
default:
LOG(out << "Unknown unop: " << WasmOpcodes::OpcodeName(Opcode) << "\n");
llvm::report_fatal_error("Uncovered or invalid unop.");
......@@ -953,7 +1180,8 @@ public:
Node LoadMem(wasm::LocalType Type, MachineType MemType, Node Index,
uint32_t Offset) {
LOG(out << "LoadMem(" << Index << "[" << Offset << "]) = ");
LOG(out << "LoadMem." << toIceType(MemType) << "(" << Index << "[" << Offset
<< "]) = ");
auto *RealAddr = sanitizeAddress(Index, Offset);
......@@ -988,7 +1216,8 @@ public:
return OperandNode(Result);
}
void StoreMem(MachineType Type, Node Index, uint32_t Offset, Node Val) {
LOG(out << "StoreMem(" << Index << "[" << Offset << "] = " << Val << ")"
LOG(out << "StoreMem." << toIceType(Type) << "(" << Index << "[" << Offset
<< "] = " << Val << ")"
<< "\n");
auto *RealAddr = sanitizeAddress(Index, Offset);
......@@ -1101,11 +1330,13 @@ std::unique_ptr<Cfg> WasmTranslator::translateFunction(Zone *Zone,
return Func;
}
// TODO(eholk): compute the correct buffer size. This uses 256k by default,
// which has been big enough for testing but is not a general solution.
constexpr SizeT BufferSize = 256 << 10;
WasmTranslator::WasmTranslator(GlobalContext *Ctx)
: Translator(Ctx), Buffer(new uint8_t[24 << 10]), BufferSize(24 << 10) {
// TODO(eholk): compute the correct buffer size. This uses 24k by default,
// which has been big enough for testing but is not a general solution.
}
: Translator(Ctx), Buffer(new uint8_t[ ::BufferSize]),
BufferSize(::BufferSize) {}
void WasmTranslator::translate(
const std::string &IRFilename,
......@@ -1118,6 +1349,7 @@ void WasmTranslator::translate(
SizeT BytesRead = InputStream->GetBytes(Buffer.get(), BufferSize);
LOG(out << "Read " << BytesRead << " bytes"
<< "\n");
assert(BytesRead < BufferSize);
LOG(out << "Decoding module " << IRFilename << "\n");
......
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