Commit 67c7c416 by Eric Holk

Subzero. WASM. Additional progress.

This change includes a number of improvements since the last WASM CL. It compiles against a newer version of V8 that matches the current WASM binary format. Many more WASM instructions are supported, as well as global variable initializers. There is also the beginning of a runtime library that implements some system calls required by the WASM C library. The c2wasm-exe.sh script can be used to compile a C program to a .wasm module, which is then compiled by Subzero into a native executable. This change includes a new Breakpoint instruction, which inserts an unconditional breakpoint into the executable. This has been helpful in debugging code generation for some WASM instructions. The Breakpoint instruction is only completely implemented on X86. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4369 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1876413002 .
parent 397f602c
...@@ -11,3 +11,7 @@ ...@@ -11,3 +11,7 @@
/pnacl-sz /pnacl-sz
/build/ /build/
/crosstest/Output/ /crosstest/Output/
# Ignore WASM torture tests
/torture-s/
/torture-s2wasm-sexpr-wasm/
...@@ -256,15 +256,13 @@ endif ...@@ -256,15 +256,13 @@ endif
BASE_CXXFLAGS := -std=gnu++11 -Wall -Wextra -fno-rtti \ BASE_CXXFLAGS := -std=gnu++11 -Wall -Wextra -fno-rtti \
-fno-exceptions $(OPTLEVEL) $(ASSERTIONS) -g -pedantic \ -fno-exceptions $(OPTLEVEL) $(ASSERTIONS) -g -pedantic \
$(LLVM_EXTRA_WARNINGS) $(CXX_EXTRA) -MP -MD $(LLVM_EXTRA_WARNINGS) $(CXX_EXTRA) -MP -MD -Werror
ifdef WASM ifdef WASM
# The WASM code inherits a lot of V8 code, which does not compile with
# -Werror.
BASE_CXXFLAGS := $(BASE_CXXFLAGS) $(V8_CXXFLAGS) -DALLOW_WASM=1 BASE_CXXFLAGS := $(BASE_CXXFLAGS) $(V8_CXXFLAGS) -DALLOW_WASM=1
OBJDIR := $(OBJDIR)+Wasm OBJDIR := $(OBJDIR)+Wasm
else else
BASE_CXXFLAGS := $(BASE_CXXFLAGS) -Werror -DALLOW_WASM=0 BASE_CXXFLAGS := $(BASE_CXXFLAGS) -DALLOW_WASM=0
endif endif
CXXFLAGS := $(LLVM_CXXFLAGS) $(BASE_CXXFLAGS) $(CXX_DEFINES) $(HOST_FLAGS) \ CXXFLAGS := $(LLVM_CXXFLAGS) $(BASE_CXXFLAGS) $(CXX_DEFINES) $(HOST_FLAGS) \
......
...@@ -18,6 +18,24 @@ You'll need to build v8 as a shared library. Build it like this: ...@@ -18,6 +18,24 @@ You'll need to build v8 as a shared library. Build it like this:
make -j48 native component=shared_library make -j48 native component=shared_library
``` ```
`wasm-run-torture-tests.py` can be used to run all the tests, or some subset. `wasm-run-torture-tests.py` can be used to run all the tests, or some
Running a subset will enable verbose output. You can download the torture tests subset. Running a subset will enable verbose output. You can download the
from the [WebAssembly waterfall](https://wasm-stat.us/console). torture tests from the [WebAssembly waterfall](https://wasm-stat.us/console) or
by running `./fetch-torture-tests.sh`.
To compile and run an executable, do the following from the subzero directory.
```
./pnacl-sz -filetype=obj -o foo.o foo.wasm
clang -m32 foo.o src/wasm-runtime.c
./a.out
```
Other useful commands:
Compile a C file to a .wasm
```
./wasm-install/bin/emscripten/emcc hello-wasm.c -s BINARYEN=1
./wasm-install/bin/sexpr-wasm a.out.wast -o a.out.wasm
```
#!/bin/bash
# TODO (eholk): This script is a hack for debugging and development
# that should be removed.
./wasm-install/bin/emscripten/emcc "$1" -s BINARYEN=1 \
-s 'BINARYEN_METHOD="native-wasm"' -O2 && \
./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
BUILD_PATH=https://storage.googleapis.com/wasm-llvm/builds/git
wget -O - /wasm-torture-s-$BUILDID.tbz2 \
| tar xj
wget -O - $BUILD_PATH/wasm-torture-s2wasm-sexpr-wasm-$BUILDID.tbz2 \
| tar xj
wget -O - $BUILD_PATH/wasm-binaries-$BUILDID.tbz2 \
| tar xj
...@@ -22,13 +22,13 @@ def run_test(test_file, verbose=False): ...@@ -22,13 +22,13 @@ def run_test(test_file, verbose=False):
global fail_count global fail_count
cmd = """LD_LIBRARY_PATH=../../../../v8/out/native/lib.target ./pnacl-sz \ cmd = """LD_LIBRARY_PATH=../../../../v8/out/native/lib.target ./pnacl-sz \
-filetype=asm -target=arm32 {} -threads=0 -O2 \ -filetype=asm -target=x8632 {} -threads=0 -O2 \
-verbose=wasm""".format(test_file) -verbose=wasm""".format(test_file)
if not verbose: if not verbose:
cmd += " &> /dev/null" cmd += " &> /dev/null"
sys.stdout.write(test_file + "..."); sys.stdout.write(test_file + " ...");
status = os.system(cmd); status = os.system(cmd);
if status != 0: if status != 0:
fail_count += 1 fail_count += 1
...@@ -45,7 +45,7 @@ if len(sys.argv) > 1: ...@@ -45,7 +45,7 @@ if len(sys.argv) > 1:
test_files = sys.argv[1:] test_files = sys.argv[1:]
verbose = True verbose = True
else: else:
test_files = glob.glob("./torture-s2wasm-sexpr-wasm.old/*.wasm") test_files = glob.glob("./torture-s2wasm-sexpr-wasm/*.wasm")
for test_file in test_files: for test_file in test_files:
run_test(test_file, verbose) run_test(test_file, verbose)
......
//===- subzero/runtime/wasm-runtime.c - Subzero WASM runtime source -------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the system calls required by the libc that is included
// in WebAssembly programs.
//
//===----------------------------------------------------------------------===//
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern char WASM_MEMORY[];
void env$$abort() {
fprintf(stderr, "Aborting...\n");
abort();
}
void env$$_abort() { env$$abort(); }
#define UNIMPLEMENTED(f) \
void env$$##f() { \
fprintf(stderr, "Unimplemented: " #f "\n"); \
abort(); \
}
UNIMPLEMENTED(sbrk)
UNIMPLEMENTED(pthread_cleanup_push)
UNIMPLEMENTED(pthread_cleanup_pop)
UNIMPLEMENTED(pthread_self)
UNIMPLEMENTED(__lock)
UNIMPLEMENTED(__unlock)
UNIMPLEMENTED(__syscall6)
UNIMPLEMENTED(__syscall140)
void *wasmPtr(int Index) {
// TODO (eholk): get the mask from the WASM file.
const int MASK = 0x3fffff;
Index &= MASK;
return WASM_MEMORY + Index;
}
extern int __szwasm_main(int, 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); }
/// sys_write
int env$$__syscall4(int Which, int VarArgs) {
int Fd = WASM_DEREF(int, VarArgs + 0 * sizeof(int));
int Buffer = WASM_DEREF(int, VarArgs + 1 * sizeof(int));
int Length = WASM_DEREF(int, VarArgs + 2 * sizeof(int));
return write(Fd, WASM_REF(char *, Buffer), Length);
}
/// sys_ioctl
int env$$__syscall54(int A, int B) {
int Fd = WASM_DEREF(int, B + 0 * sizeof(int));
int Op = WASM_DEREF(int, B + 1 * sizeof(int));
int ArgP = WASM_DEREF(int, B + 2 * sizeof(int));
// TODO (eholk): implement sys_ioctl
return -ENOTTY;
}
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;
}
...@@ -599,6 +599,7 @@ void Cfg::processAllocas(bool SortAndCombine) { ...@@ -599,6 +599,7 @@ void Cfg::processAllocas(bool SortAndCombine) {
TimerMarker _(TimerStack::TT_alloca, this); TimerMarker _(TimerStack::TT_alloca, this);
const uint32_t StackAlignment = getTarget()->getStackAlignment(); const uint32_t StackAlignment = getTarget()->getStackAlignment();
CfgNode *EntryNode = getEntryNode(); CfgNode *EntryNode = getEntryNode();
assert(EntryNode);
// LLVM enforces power of 2 alignment. // LLVM enforces power of 2 alignment.
assert(llvm::isPowerOf2_32(StackAlignment)); assert(llvm::isPowerOf2_32(StackAlignment));
// Determine if there are large alignment allocations in the entry block or // Determine if there are large alignment allocations in the entry block or
......
...@@ -105,6 +105,7 @@ const char *Inst::getInstName() const { ...@@ -105,6 +105,7 @@ const char *Inst::getInstName() const {
X(Store, "store"); X(Store, "store");
X(Switch, "switch"); X(Switch, "switch");
X(Assign, "assign"); X(Assign, "assign");
X(Breakpoint, "break");
X(BundleLock, "bundlelock"); X(BundleLock, "bundlelock");
X(BundleUnlock, "bundleunlock"); X(BundleUnlock, "bundleunlock");
X(FakeDef, "fakedef"); X(FakeDef, "fakedef");
...@@ -516,8 +517,10 @@ void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) { ...@@ -516,8 +517,10 @@ void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
NodeList InstSwitch::getTerminatorEdges() const { NodeList InstSwitch::getTerminatorEdges() const {
NodeList OutEdges; NodeList OutEdges;
OutEdges.reserve(NumCases + 1); OutEdges.reserve(NumCases + 1);
assert(LabelDefault);
OutEdges.push_back(LabelDefault); OutEdges.push_back(LabelDefault);
for (SizeT I = 0; I < NumCases; ++I) { for (SizeT I = 0; I < NumCases; ++I) {
assert(Labels[I]);
OutEdges.push_back(Labels[I]); OutEdges.push_back(Labels[I]);
} }
std::sort(OutEdges.begin(), OutEdges.end(), std::sort(OutEdges.begin(), OutEdges.end(),
...@@ -1047,6 +1050,9 @@ void InstTarget::dump(const Cfg *Func) const { ...@@ -1047,6 +1050,9 @@ void InstTarget::dump(const Cfg *Func) const {
Inst::dump(Func); Inst::dump(Func);
} }
InstBreakpoint::InstBreakpoint(Cfg *Func)
: InstHighLevel(Func, Inst::Breakpoint, 0, nullptr) {}
bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
const auto *SrcVar = llvm::dyn_cast<const Variable>(Source); const auto *SrcVar = llvm::dyn_cast<const Variable>(Source);
if (!SrcVar) if (!SrcVar)
......
...@@ -62,6 +62,7 @@ public: ...@@ -62,6 +62,7 @@ public:
Store, Store,
Switch, Switch,
Assign, // not part of LLVM/PNaCl bitcode Assign, // not part of LLVM/PNaCl bitcode
Breakpoint, // not part of LLVM/PNaCl bitcode
BundleLock, // not part of LLVM/PNaCl bitcode BundleLock, // not part of LLVM/PNaCl bitcode
BundleUnlock, // not part of LLVM/PNaCl bitcode BundleUnlock, // not part of LLVM/PNaCl bitcode
FakeDef, // not part of LLVM/PNaCl bitcode FakeDef, // not part of LLVM/PNaCl bitcode
...@@ -976,6 +977,29 @@ private: ...@@ -976,6 +977,29 @@ private:
GlobalString FuncName; GlobalString FuncName;
}; };
/// This instruction inserts an unconditional breakpoint.
///
/// On x86, this assembles into an INT 3 instruction.
///
/// This instruction is primarily meant for debugging the code generator.
class InstBreakpoint : public InstHighLevel {
public:
InstBreakpoint() = delete;
InstBreakpoint(const InstBreakpoint &) = delete;
InstBreakpoint &operator=(const InstBreakpoint &) = delete;
InstBreakpoint(Cfg *Func);
public:
static InstBreakpoint *create(Cfg *Func) {
return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
}
static bool classof(const Inst *Instr) {
return Instr->getKind() == Breakpoint;
}
};
/// The Target instruction is the base class for all target-specific /// The Target instruction is the base class for all target-specific
/// instructions. /// instructions.
class InstTarget : public Inst { class InstTarget : public Inst {
......
...@@ -107,6 +107,7 @@ template <typename TraitsType> struct InstImpl { ...@@ -107,6 +107,7 @@ template <typename TraitsType> struct InstImpl {
Imul, Imul,
ImulImm, ImulImm,
Insertps, Insertps,
Int3,
Jmp, Jmp,
Label, Label,
Lea, Lea,
...@@ -2442,6 +2443,27 @@ template <typename TraitsType> struct InstImpl { ...@@ -2442,6 +2443,27 @@ template <typename TraitsType> struct InstImpl {
explicit InstX86UD2(Cfg *Func); explicit InstX86UD2(Cfg *Func);
}; };
/// Int3 instruction.
class InstX86Int3 final : public InstX86Base {
InstX86Int3() = delete;
InstX86Int3(const InstX86Int3 &) = delete;
InstX86Int3 &operator=(const InstX86Int3 &) = delete;
public:
static InstX86Int3 *create(Cfg *Func) {
return new (Func->allocate<InstX86Int3>()) InstX86Int3(Func);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Instr) {
return InstX86Base::isClassof(Instr, InstX86Base::Int3);
}
private:
explicit InstX86Int3(Cfg *Func);
};
/// Test instruction. /// Test instruction.
class InstX86Test final : public InstX86Base { class InstX86Test final : public InstX86Base {
InstX86Test() = delete; InstX86Test() = delete;
...@@ -2914,6 +2936,7 @@ template <typename TraitsType> struct Insts { ...@@ -2914,6 +2936,7 @@ template <typename TraitsType> struct Insts {
using Icmp = typename InstImpl<TraitsType>::InstX86Icmp; using Icmp = typename InstImpl<TraitsType>::InstX86Icmp;
using Ucomiss = typename InstImpl<TraitsType>::InstX86Ucomiss; using Ucomiss = typename InstImpl<TraitsType>::InstX86Ucomiss;
using UD2 = typename InstImpl<TraitsType>::InstX86UD2; using UD2 = typename InstImpl<TraitsType>::InstX86UD2;
using Int3 = typename InstImpl<TraitsType>::InstX86Int3;
using Test = typename InstImpl<TraitsType>::InstX86Test; using Test = typename InstImpl<TraitsType>::InstX86Test;
using Mfence = typename InstImpl<TraitsType>::InstX86Mfence; using Mfence = typename InstImpl<TraitsType>::InstX86Mfence;
using Store = typename InstImpl<TraitsType>::InstX86Store; using Store = typename InstImpl<TraitsType>::InstX86Store;
......
...@@ -263,6 +263,10 @@ InstImpl<TraitsType>::InstX86UD2::InstX86UD2(Cfg *Func) ...@@ -263,6 +263,10 @@ InstImpl<TraitsType>::InstX86UD2::InstX86UD2(Cfg *Func)
: InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {} : InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {}
template <typename TraitsType> template <typename TraitsType>
InstImpl<TraitsType>::InstX86Int3::InstX86Int3(Cfg *Func)
: InstX86Base(Func, InstX86Base::Int3, 0, nullptr) {}
template <typename TraitsType>
InstImpl<TraitsType>::InstX86Test::InstX86Test(Cfg *Func, Operand *Src1, InstImpl<TraitsType>::InstX86Test::InstX86Test(Cfg *Func, Operand *Src1,
Operand *Src2) Operand *Src2)
: InstX86Base(Func, InstX86Base::Test, 2, nullptr) { : InstX86Base(Func, InstX86Base::Test, 2, nullptr) {
...@@ -1780,6 +1784,30 @@ void InstImpl<TraitsType>::InstX86UD2::dump(const Cfg *Func) const { ...@@ -1780,6 +1784,30 @@ void InstImpl<TraitsType>::InstX86UD2::dump(const Cfg *Func) const {
} }
template <typename TraitsType> template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Int3::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
assert(this->getSrcSize() == 0);
Str << "\t"
"int 3";
}
template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Int3::emitIAS(const Cfg *Func) const {
Assembler *Asm = Func->getAssembler<Assembler>();
Asm->int3();
}
template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Int3::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
Str << "int 3";
}
template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Test::emit(const Cfg *Func) const { void InstImpl<TraitsType>::InstX86Test::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -400,6 +400,9 @@ void TargetLowering::lower() { ...@@ -400,6 +400,9 @@ void TargetLowering::lower() {
case Inst::Br: case Inst::Br:
lowerBr(llvm::cast<InstBr>(Instr)); lowerBr(llvm::cast<InstBr>(Instr));
break; break;
case Inst::Breakpoint:
lowerBreakpoint(llvm::cast<InstBreakpoint>(Instr));
break;
case Inst::Call: case Inst::Call:
lowerCall(llvm::cast<InstCall>(Instr)); lowerCall(llvm::cast<InstCall>(Instr));
break; break;
......
...@@ -375,6 +375,7 @@ protected: ...@@ -375,6 +375,7 @@ protected:
virtual void lowerArithmetic(const InstArithmetic *Instr) = 0; virtual void lowerArithmetic(const InstArithmetic *Instr) = 0;
virtual void lowerAssign(const InstAssign *Instr) = 0; virtual void lowerAssign(const InstAssign *Instr) = 0;
virtual void lowerBr(const InstBr *Instr) = 0; virtual void lowerBr(const InstBr *Instr) = 0;
virtual void lowerBreakpoint(const InstBreakpoint *Instr) = 0;
virtual void lowerCall(const InstCall *Instr) = 0; virtual void lowerCall(const InstCall *Instr) = 0;
virtual void lowerCast(const InstCast *Instr) = 0; virtual void lowerCast(const InstCast *Instr) = 0;
virtual void lowerFcmp(const InstFcmp *Instr) = 0; virtual void lowerFcmp(const InstFcmp *Instr) = 0;
......
...@@ -5818,6 +5818,10 @@ void TargetARM32::lowerSwitch(const InstSwitch *Instr) { ...@@ -5818,6 +5818,10 @@ void TargetARM32::lowerSwitch(const InstSwitch *Instr) {
_br(Instr->getLabelDefault()); _br(Instr->getLabelDefault());
} }
void TargetARM32::lowerBreakpoint(const InstBreakpoint *Instr) {
UnimplementedLoweringError(this, Instr);
}
void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) { void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) {
_trap(); _trap();
} }
......
...@@ -278,6 +278,7 @@ protected: ...@@ -278,6 +278,7 @@ protected:
Operand *Val); Operand *Val);
void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
Operand *Val); Operand *Val);
void lowerBreakpoint(const InstBreakpoint *Instr) override;
void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override; void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
void lowerInsertElement(const InstInsertElement *Instr) override; void lowerInsertElement(const InstInsertElement *Instr) override;
void lowerLoad(const InstLoad *Instr) override; void lowerLoad(const InstLoad *Instr) override;
......
...@@ -1155,6 +1155,10 @@ void TargetMIPS32::lowerSwitch(const InstSwitch *Instr) { ...@@ -1155,6 +1155,10 @@ void TargetMIPS32::lowerSwitch(const InstSwitch *Instr) {
UnimplementedLoweringError(this, Instr); UnimplementedLoweringError(this, Instr);
} }
void TargetMIPS32::lowerBreakpoint(const InstBreakpoint *Instr) {
UnimplementedLoweringError(this, Instr);
}
void TargetMIPS32::lowerUnreachable(const InstUnreachable *Instr) { void TargetMIPS32::lowerUnreachable(const InstUnreachable *Instr) {
UnimplementedLoweringError(this, Instr); UnimplementedLoweringError(this, Instr);
} }
......
...@@ -287,6 +287,7 @@ protected: ...@@ -287,6 +287,7 @@ protected:
Operand *Src0, Operand *Src1); Operand *Src0, Operand *Src1);
void lowerAssign(const InstAssign *Instr) override; void lowerAssign(const InstAssign *Instr) override;
void lowerBr(const InstBr *Instr) override; void lowerBr(const InstBr *Instr) override;
void lowerBreakpoint(const InstBreakpoint *Instr) override;
void lowerCall(const InstCall *Instr) override; void lowerCall(const InstCall *Instr) override;
void lowerCast(const InstCast *Instr) override; void lowerCast(const InstCast *Instr) override;
void lowerExtractElement(const InstExtractElement *Instr) override; void lowerExtractElement(const InstExtractElement *Instr) override;
......
...@@ -247,6 +247,7 @@ protected: ...@@ -247,6 +247,7 @@ protected:
void lowerArithmetic(const InstArithmetic *Instr) override; void lowerArithmetic(const InstArithmetic *Instr) override;
void lowerAssign(const InstAssign *Instr) override; void lowerAssign(const InstAssign *Instr) override;
void lowerBr(const InstBr *Instr) override; void lowerBr(const InstBr *Instr) override;
void lowerBreakpoint(const InstBreakpoint *Instr) override;
void lowerCall(const InstCall *Instr) override; void lowerCall(const InstCall *Instr) override;
void lowerCast(const InstCast *Instr) override; void lowerCast(const InstCast *Instr) override;
void lowerExtractElement(const InstExtractElement *Instr) override; void lowerExtractElement(const InstExtractElement *Instr) override;
...@@ -656,6 +657,7 @@ protected: ...@@ -656,6 +657,7 @@ protected:
AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1); AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
Context.insert<typename Traits::Insts::Insertps>(Dest, Src0, Src1); Context.insert<typename Traits::Insts::Insertps>(Dest, Src0, Src1);
} }
void _int3() { Context.insert<typename Traits::Insts::Int3>(); }
void _jmp(Operand *Target) { void _jmp(Operand *Target) {
AutoMemorySandboxer<> _(this, &Target); AutoMemorySandboxer<> _(this, &Target);
Context.insert<typename Traits::Insts::Jmp>(Target); Context.insert<typename Traits::Insts::Jmp>(Target);
......
...@@ -6096,6 +6096,12 @@ void TargetX86Base<TraitsType>::lowerUnreachable( ...@@ -6096,6 +6096,12 @@ void TargetX86Base<TraitsType>::lowerUnreachable(
} }
template <typename TraitsType> template <typename TraitsType>
void TargetX86Base<TraitsType>::lowerBreakpoint(
const InstBreakpoint * /*Instr*/) {
_int3();
}
template <typename TraitsType>
void TargetX86Base<TraitsType>::lowerRMW(const InstX86FakeRMW *RMW) { void TargetX86Base<TraitsType>::lowerRMW(const InstX86FakeRMW *RMW) {
// If the beacon variable's live range does not end in this instruction, then // If the beacon variable's live range does not end in this instruction, then
// it must end in the modified Store instruction that follows. This means // it must end in the modified Store instruction that follows. This means
......
...@@ -20,11 +20,22 @@ ...@@ -20,11 +20,22 @@
#include "IceGlobalContext.h" #include "IceGlobalContext.h"
#include "IceTranslator.h" #include "IceTranslator.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif // __clang__
#include "llvm/Support/StreamingMemoryObject.h"
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class Zone; class Zone;
namespace wasm { namespace wasm {
class FunctionEnv; struct FunctionBody;
} // end of namespace wasm } // end of namespace wasm
} // end of namespace internal } // end of namespace internal
} // end of namespace v8 } // end of namespace v8
...@@ -53,15 +64,10 @@ public: ...@@ -53,15 +64,10 @@ public:
/// ///
/// Parameters: /// Parameters:
/// Zone - an arena for the V8 code to allocate from. /// Zone - an arena for the V8 code to allocate from.
/// Env - information about the function (signature, variable count, etc.). /// Body - information about the function to translate
/// Base - a pointer to the start of the Wasm module. std::unique_ptr<Cfg>
/// Start - a pointer to the start of the function within the module. translateFunction(v8::internal::Zone *Zone,
/// End - a pointer to the end of the function. v8::internal::wasm::FunctionBody &Body);
std::unique_ptr<Cfg> translateFunction(v8::internal::Zone *Zone,
v8::internal::wasm::FunctionEnv *Env,
const uint8_t *Base,
const uint8_t *Start,
const uint8_t *End);
private: private:
std::unique_ptr<uint8_t[]> Buffer; std::unique_ptr<uint8_t[]> Buffer;
......
#include <stdio.h>
int main(int argc, const char **argv) {
printf("Hello, World!\n");
return 0;
}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void write_int_(int fd, int n) {
if (n > 0) {
write_int_(fd, n / 10);
int rem = n % 10;
char c = '0' + rem;
write(fd, &c, 1);
}
}
void write_int(int fd, int n) {
if (n == 0) {
write(fd, "0", 1);
} else {
if (n < 0) {
write(fd, "-", 1);
write_int_(fd, -n);
} else {
write_int_(fd, n);
}
}
}
void stderr_int(int n) {
write_int(2, n);
write(2, "\n", 1);
}
int main(int argc, const char **argv) {
char *str = "Hello, World!\n";
for (int i = 0; str[i]; ++i) {
putchar(str[i]);
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, const char **argv) {
fputs("Hello,", stdout);
fputs(" ", stdout);
fputs("world\n", stdout);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, const char **argv) {
char *str = "Hello, World!\n";
const int len = strlen(str);
write(1, str, len);
return 0;
}
int foo() { return 5; }
int bar() { return 6; }
int baz() { return 7; }
int (*TABLE[])() = {foo, baz, bar, baz};
int main(int argc, const char **argv) {
int (*f)() = TABLE[argc - 1];
return f();
}
// This is derived from the loop in musl's __fwritex that looks for newlines.
int puts(const char *s);
int main(int argc, const char **argv) {
const char *p = (const char *)argv;
char *s = "Hello\nWorld";
unsigned i = 0;
// Depend on argc to avoid having this whole thing get dead-code-eliminated.
for (i = 14 - argc; i && p[i - 1] != '\n'; i--)
;
puts(s);
return i;
}
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