Commit 16f8061c by Eric Holk

Initial Subzero WASM prototype.

BUG= R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1837663002 .
parent 263ac526
...@@ -179,6 +179,9 @@ endif ...@@ -179,6 +179,9 @@ endif
SB_OBJDIR := $(OBJDIR)+Sandboxed SB_OBJDIR := $(OBJDIR)+Sandboxed
SBB_OBJDIR := $(OBJDIR)+SandboxedBrowser SBB_OBJDIR := $(OBJDIR)+SandboxedBrowser
V8_DIR = $(NACL_ROOT)/../v8
V8_CXXFLAGS := -I$(V8_DIR)
$(info -----------------------------------------------) $(info -----------------------------------------------)
$(info Using LLVM_SRC_PATH = $(LLVM_SRC_PATH)) $(info Using LLVM_SRC_PATH = $(LLVM_SRC_PATH))
$(info Using SB_LLVM_PATH = $(SB_LLVM_PATH)) $(info Using SB_LLVM_PATH = $(SB_LLVM_PATH))
...@@ -251,10 +254,19 @@ ifdef GPLUSPLUS ...@@ -251,10 +254,19 @@ ifdef GPLUSPLUS
OBJDIR := $(OBJDIR)+Gplusplus OBJDIR := $(OBJDIR)+Gplusplus
endif endif
BASE_CXXFLAGS := -std=gnu++11 -Wall -Wextra -Werror -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
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
OBJDIR := $(OBJDIR)+Wasm
else
BASE_CXXFLAGS := $(BASE_CXXFLAGS) -Werror -DALLOW_WASM=0
endif
CXXFLAGS := $(LLVM_CXXFLAGS) $(BASE_CXXFLAGS) $(CXX_DEFINES) $(HOST_FLAGS) \ CXXFLAGS := $(LLVM_CXXFLAGS) $(BASE_CXXFLAGS) $(CXX_DEFINES) $(HOST_FLAGS) \
$(STDLIB_FLAGS) $(STDLIB_FLAGS)
SB_CXXFLAGS := $(SB_LLVM_CXXFLAGS) $(BASE_CXXFLAGS) $(BASE_CXX_DEFINES) \ SB_CXXFLAGS := $(SB_LLVM_CXXFLAGS) $(BASE_CXXFLAGS) $(BASE_CXX_DEFINES) \
...@@ -315,6 +327,11 @@ ifndef MINIMAL ...@@ -315,6 +327,11 @@ ifndef MINIMAL
IceTypeConverter.cpp IceTypeConverter.cpp
endif endif
ifdef WASM
SRCS += \
WasmTranslator.cpp
endif
OBJS=$(patsubst %.cpp, $(OBJDIR)/%.o, $(SRCS)) OBJS=$(patsubst %.cpp, $(OBJDIR)/%.o, $(SRCS))
SB_OBJS=$(patsubst %.cpp, $(SB_OBJDIR)/%.o, $(SRCS)) SB_OBJS=$(patsubst %.cpp, $(SB_OBJDIR)/%.o, $(SRCS))
SBB_OBJS=$(patsubst %.cpp, $(SBB_OBJDIR)/%.o, $(SRCS)) SBB_OBJS=$(patsubst %.cpp, $(SBB_OBJDIR)/%.o, $(SRCS))
...@@ -392,9 +409,18 @@ sb_make_symlink: $(NEXES) ...@@ -392,9 +409,18 @@ sb_make_symlink: $(NEXES)
compile_only: $(OBJS) compile_only: $(OBJS)
V8_LIBDIR=$(V8_DIR)/out/native/lib.target
ifdef WASM
V8_LIBS := \
$(V8_LIBDIR)/libv8.so \
$(V8_LIBDIR)/libicuuc.so \
$(V8_LIBDIR)/libicui18n.so
endif
$(OBJDIR)/pnacl-sz: $(OBJS) $(OBJDIR)/pnacl-sz: $(OBJS)
$(CXX) $(LDFLAGS) -o $@ $^ $(LLVM_LDFLAGS) \ $(CXX) $(LDFLAGS) -o $@ $^ $(LLVM_LDFLAGS) \
-Wl,-rpath=$(abspath $(LIBCXX_INSTALL_PATH)/lib) -Wl,-rpath=$(abspath $(LIBCXX_INSTALL_PATH)/lib) $(V8_LIBS)
$(SB_OBJDIR)/pnacl-sz.nonfinal.pexe: $(SB_OBJS) $(SB_OBJDIR)/pnacl-sz.nonfinal.pexe: $(SB_OBJS)
$(SB_CXX) $(SB_LDFLAGS) -o $@ $^ $(SB_LLVM_LDFLAGS) $(SB_CXX) $(SB_LDFLAGS) -o $@ $^ $(SB_LLVM_LDFLAGS)
...@@ -713,6 +739,7 @@ FORMAT_BLACKLIST += ! -name IceParseInstsTest.cpp ...@@ -713,6 +739,7 @@ FORMAT_BLACKLIST += ! -name IceParseInstsTest.cpp
FORMAT_BLACKLIST += ! -name IceParseTypesTest.cpp FORMAT_BLACKLIST += ! -name IceParseTypesTest.cpp
FORMAT_BLACKLIST += ! -name assembler_arm.h FORMAT_BLACKLIST += ! -name assembler_arm.h
FORMAT_BLACKLIST += ! -name assembler_arm.cc FORMAT_BLACKLIST += ! -name assembler_arm.cc
FORMAT_BLACKLIST += ! -path "./wasm-install/*"
format: format:
$(CLANG_FORMAT_PATH)/clang-format -style=LLVM -i \ $(CLANG_FORMAT_PATH)/clang-format -style=LLVM -i \
`find . -regex '.*\.\(c\|h\|cpp\)' $(FORMAT_BLACKLIST)` `find . -regex '.*\.\(c\|h\|cpp\)' $(FORMAT_BLACKLIST)`
......
# Wasm Prototype Experiment Notes
Here's the command I use to test:
```
LD_LIBRARY_PATH=~/nacl/v8/out/native/lib.target make -j48 \
-f Makefile.standalone WASM=1 && \
LD_LIBRARY_PATH=~/nacl/v8/out/native/lib.target ./pnacl-sz -O2 -filetype=asm \
-target=arm32 ./torture-s2wasm-sexpr-wasm/20000112-1.c.s.wast.wasm
```
You'll probably need to adjust your `LD_LIBRARY_PATH` to point to where your v8
libraries are.
You'll need to build v8 as a shared library. Build it like this:
```
make -j48 native component=shared_library
```
`wasm-run-torture-tests.py` can be used to run all the tests, or some subset.
Running a subset will enable verbose output. You can download the torture tests
from the [WebAssembly waterfall](https://wasm-stat.us/console).
#!/usr/bin/env python2
#===- subzero/wasm-run-torture-tests.py - Subzero WASM Torture Test Driver ===//
#
# The Subzero Code Generator
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===-----------------------------------------------------------------------===//
import glob
import os
import sys
success_count = 0
fail_count = 0
failures = []
def run_test(test_file, verbose=False):
global success_count
global fail_count
cmd = """LD_LIBRARY_PATH=../../../../v8/out/native/lib.target ./pnacl-sz \
-filetype=asm -target=arm32 {} -threads=0 -O2 \
-verbose=wasm""".format(test_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)
else:
success_count += 1
print('\033[1;32m[ok]\033[1;m')
verbose = False
if len(sys.argv) > 1:
test_files = sys.argv[1:]
verbose = True
else:
test_files = glob.glob("./torture-s2wasm-sexpr-wasm.old/*.wasm")
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))
...@@ -90,6 +90,8 @@ constexpr bool llvmIr() { return ALLOW_LLVM_IR; } ...@@ -90,6 +90,8 @@ constexpr bool llvmIr() { return ALLOW_LLVM_IR; }
constexpr bool llvmIrAsInput() { return ALLOW_LLVM_IR_AS_INPUT; } constexpr bool llvmIrAsInput() { return ALLOW_LLVM_IR_AS_INPUT; }
/// Return true if ALLOW_MINIMAL_BUILD is defined as a non-zero value /// Return true if ALLOW_MINIMAL_BUILD is defined as a non-zero value
constexpr bool minimal() { return ALLOW_MINIMAL_BUILD; } constexpr bool minimal() { return ALLOW_MINIMAL_BUILD; }
/// Return true if ALLOW_WASM is defined as a non-zero value
constexpr bool wasm() { return ALLOW_WASM; }
/// Return true if NDEBUG is defined /// Return true if NDEBUG is defined
constexpr bool asserts() { constexpr bool asserts() {
......
...@@ -245,6 +245,22 @@ void Cfg::translate() { ...@@ -245,6 +245,22 @@ void Cfg::translate() {
} }
} }
void Cfg::fixPhiNodes() {
for (auto *Node : Nodes) {
// Fix all the phi edges since WASM can't tell how to make them correctly at
// the beginning.
assert(Node);
const auto &InEdges = Node->getInEdges();
for (auto &Instr : Node->getPhis()) {
auto *Phi = llvm::cast<InstPhi>(&Instr);
assert(Phi);
for (SizeT i = 0; i < InEdges.size(); ++i) {
Phi->setLabel(i, InEdges[i]);
}
}
}
}
void Cfg::computeInOutEdges() { void Cfg::computeInOutEdges() {
// Compute the out-edges. // Compute the out-edges.
for (CfgNode *Node : Nodes) for (CfgNode *Node : Nodes)
...@@ -402,7 +418,7 @@ void Cfg::reorderNodes() { ...@@ -402,7 +418,7 @@ void Cfg::reorderNodes() {
// in-edge if the predecessor node was contracted). If this changes in // in-edge if the predecessor node was contracted). If this changes in
// the future, rethink the strategy. // the future, rethink the strategy.
assert(Node->getInEdges().size() >= 1); assert(Node->getInEdges().size() >= 1);
assert(Node->getOutEdges().size() == 1); assert(Node->hasSingleOutEdge());
// If it's a (non-critical) edge where the successor has a single // If it's a (non-critical) edge where the successor has a single
// in-edge, then place it before the successor. // in-edge, then place it before the successor.
......
...@@ -256,6 +256,13 @@ public: ...@@ -256,6 +256,13 @@ public:
Allocator->Deallocate(Array); Allocator->Deallocate(Array);
} }
/// Update Phi labels with InEdges.
///
/// The WASM translator cannot always determine the right incoming edge for a
/// value due to the CFG being built incrementally. The fixPhiNodes pass fills
/// in the correct information once everything is known.
void fixPhiNodes();
private: private:
friend class CfgAllocatorTraits; // for Allocator access. friend class CfgAllocatorTraits; // for Allocator access.
......
...@@ -37,10 +37,20 @@ CfgNode::CfgNode(Cfg *Func, SizeT Number) : Func(Func), Number(Number) { ...@@ -37,10 +37,20 @@ CfgNode::CfgNode(Cfg *Func, SizeT Number) : Func(Func), Number(Number) {
// Adds an instruction to either the Phi list or the regular instruction list. // Adds an instruction to either the Phi list or the regular instruction list.
// Validates that all Phis are added before all regular instructions. // Validates that all Phis are added before all regular instructions.
void CfgNode::appendInst(Inst *Instr) { void CfgNode::appendInst(Inst *Instr, bool AllowPhisAnywhere) {
++InstCountEstimate; ++InstCountEstimate;
if (BuildDefs::wasm()) {
if (llvm::isa<InstSwitch>(Instr) || llvm::isa<InstBr>(Instr)) {
for (auto *N : Instr->getTerminatorEdges()) {
N->addInEdge(this);
addOutEdge(N);
}
}
}
if (auto *Phi = llvm::dyn_cast<InstPhi>(Instr)) { if (auto *Phi = llvm::dyn_cast<InstPhi>(Instr)) {
if (!Insts.empty()) { if (!AllowPhisAnywhere && !Insts.empty()) {
Func->setError("Phi instruction added to the middle of a block"); Func->setError("Phi instruction added to the middle of a block");
return; return;
} }
...@@ -81,6 +91,8 @@ void CfgNode::computePredecessors() { ...@@ -81,6 +91,8 @@ void CfgNode::computePredecessors() {
} }
void CfgNode::computeSuccessors() { void CfgNode::computeSuccessors() {
OutEdges.clear();
InEdges.clear();
OutEdges = Insts.rbegin()->getTerminatorEdges(); OutEdges = Insts.rbegin()->getTerminatorEdges();
} }
...@@ -889,7 +901,7 @@ void CfgNode::contractIfEmpty() { ...@@ -889,7 +901,7 @@ void CfgNode::contractIfEmpty() {
// Make sure there is actually a successor to repoint in-edges to. // Make sure there is actually a successor to repoint in-edges to.
if (OutEdges.empty()) if (OutEdges.empty())
return; return;
assert(OutEdges.size() == 1); assert(hasSingleOutEdge());
// Don't try to delete a self-loop. // Don't try to delete a self-loop.
if (OutEdges[0] == this) if (OutEdges[0] == this)
return; return;
......
...@@ -72,7 +72,7 @@ public: ...@@ -72,7 +72,7 @@ public:
/// @{ /// @{
InstList &getInsts() { return Insts; } InstList &getInsts() { return Insts; }
PhiList &getPhis() { return Phis; } PhiList &getPhis() { return Phis; }
void appendInst(Inst *Instr); void appendInst(Inst *Instr, bool AllowPhisAnywhere = false);
void renumberInstructions(); void renumberInstructions();
/// Rough and generally conservative estimate of the number of instructions in /// Rough and generally conservative estimate of the number of instructions in
/// the block. It is updated when an instruction is added, but not when /// the block. It is updated when an instruction is added, but not when
...@@ -110,6 +110,13 @@ public: ...@@ -110,6 +110,13 @@ public:
void profileExecutionCount(VariableDeclaration *Var); void profileExecutionCount(VariableDeclaration *Var);
void addOutEdge(CfgNode *Out) { OutEdges.push_back(Out); }
void addInEdge(CfgNode *In) { InEdges.push_back(In); }
bool hasSingleOutEdge() const {
return (getOutEdges().size() == 1 || getOutEdges()[0] == getOutEdges()[1]);
}
private: private:
CfgNode(Cfg *Func, SizeT Number); CfgNode(Cfg *Func, SizeT Number);
bool livenessValidateIntervals(Liveness *Liveness) const; bool livenessValidateIntervals(Liveness *Liveness) const;
......
...@@ -329,6 +329,7 @@ struct dev_list_flag {}; ...@@ -329,6 +329,7 @@ struct dev_list_flag {};
"Global initializers"), \ "Global initializers"), \
clEnumValN(Ice::IceV_ConstPoolStats, "cpool", \ clEnumValN(Ice::IceV_ConstPoolStats, "cpool", \
"Constant pool counters"), \ "Constant pool counters"), \
clEnumValN(Ice::IceV_Wasm, "wasm", "WebAssembly builder"), \
clEnumValN(Ice::IceV_All, "all", "Use all verbose options"), \ clEnumValN(Ice::IceV_All, "all", "Use all verbose options"), \
clEnumValN(Ice::IceV_Most, "most", \ clEnumValN(Ice::IceV_Most, "most", \
"Use all verbose options except 'regalloc,global_init'"), \ "Use all verbose options except 'regalloc,global_init'"), \
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "IceConverter.h" #include "IceConverter.h"
#include "IceELFObjectWriter.h" #include "IceELFObjectWriter.h"
#include "PNaClTranslator.h" #include "PNaClTranslator.h"
#include "WasmTranslator.h"
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
...@@ -54,6 +55,11 @@ bool llvmIRInput(const std::string &Filename) { ...@@ -54,6 +55,11 @@ bool llvmIRInput(const std::string &Filename) {
std::regex_match(Filename, std::regex(".*\\.ll")); std::regex_match(Filename, std::regex(".*\\.ll"));
} }
bool wasmInput(const std::string &Filename) {
return BuildDefs::llvmIrAsInput() &&
std::regex_match(Filename, std::regex(".*\\.wasm"));
}
} // end of anonymous namespace } // end of anonymous namespace
void Compiler::run(const Ice::ClFlags &Flags, GlobalContext &Ctx, void Compiler::run(const Ice::ClFlags &Flags, GlobalContext &Ctx,
...@@ -75,13 +81,27 @@ void Compiler::run(const Ice::ClFlags &Flags, GlobalContext &Ctx, ...@@ -75,13 +81,27 @@ void Compiler::run(const Ice::ClFlags &Flags, GlobalContext &Ctx,
std::unique_ptr<Translator> Translator; std::unique_ptr<Translator> Translator;
const std::string IRFilename = Flags.getIRFilename(); const std::string IRFilename = Flags.getIRFilename();
const bool BuildOnRead = Flags.getBuildOnRead() && !llvmIRInput(IRFilename); const bool BuildOnRead = Flags.getBuildOnRead() && !llvmIRInput(IRFilename) &&
!wasmInput(IRFilename);
const bool WasmBuildOnRead = Flags.getBuildOnRead() && wasmInput(IRFilename);
if (BuildOnRead) { if (BuildOnRead) {
std::unique_ptr<PNaClTranslator> PTranslator(new PNaClTranslator(&Ctx)); std::unique_ptr<PNaClTranslator> PTranslator(new PNaClTranslator(&Ctx));
std::unique_ptr<llvm::StreamingMemoryObject> MemObj( std::unique_ptr<llvm::StreamingMemoryObject> MemObj(
new llvm::StreamingMemoryObjectImpl(InputStream.release())); new llvm::StreamingMemoryObjectImpl(InputStream.release()));
PTranslator->translate(IRFilename, std::move(MemObj)); PTranslator->translate(IRFilename, std::move(MemObj));
Translator.reset(PTranslator.release()); Translator.reset(PTranslator.release());
} else if (WasmBuildOnRead) {
if (BuildDefs::wasm()) {
std::unique_ptr<WasmTranslator> WTranslator(new WasmTranslator(&Ctx));
WTranslator->translate(IRFilename, std::move(InputStream));
Translator.reset(WTranslator.release());
} else {
Ctx.getStrError() << "WASM support not enabled\n";
Ctx.getErrorStatus()->assign(EC_Args);
return;
}
} else if (BuildDefs::llvmIr()) { } else if (BuildDefs::llvmIr()) {
if (BuildDefs::browser()) { if (BuildDefs::browser()) {
Ctx.getStrError() Ctx.getStrError()
......
...@@ -341,6 +341,7 @@ enum VerboseItem { ...@@ -341,6 +341,7 @@ enum VerboseItem {
IceV_AvailableRegs = 1 << 21, IceV_AvailableRegs = 1 << 21,
IceV_GlobalInit = 1 << 22, IceV_GlobalInit = 1 << 22,
IceV_ConstPoolStats = 1 << 23, IceV_ConstPoolStats = 1 << 23,
IceV_Wasm = 1 << 24,
IceV_All = ~IceV_None, IceV_All = ~IceV_None,
IceV_Most = IceV_Most =
IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit & ~IceV_ConstPoolStats IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit & ~IceV_ConstPoolStats
......
...@@ -624,6 +624,7 @@ public: ...@@ -624,6 +624,7 @@ public:
Operand *getOperandForTarget(CfgNode *Target) const; Operand *getOperandForTarget(CfgNode *Target) const;
void clearOperandForTarget(CfgNode *Target); void clearOperandForTarget(CfgNode *Target);
CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Liveness *Liveness); Liveness *Liveness);
Inst *lower(Cfg *Func); Inst *lower(Cfg *Func);
......
...@@ -24,20 +24,6 @@ ...@@ -24,20 +24,6 @@
namespace Ice { namespace Ice {
class CfgOptWorkItem final : public OptWorkItem {
CfgOptWorkItem() = delete;
CfgOptWorkItem(const CfgOptWorkItem &) = delete;
CfgOptWorkItem &operator=(const CfgOptWorkItem &) = delete;
public:
CfgOptWorkItem(std::unique_ptr<Cfg> Func) : Func(std::move(Func)) {}
std::unique_ptr<Cfg> getParsedCfg() override { return std::move(Func); }
~CfgOptWorkItem() override = default;
private:
std::unique_ptr<Ice::Cfg> Func;
};
Translator::Translator(GlobalContext *Ctx) Translator::Translator(GlobalContext *Ctx)
: Ctx(Ctx), NextSequenceNumber(GlobalContext::getFirstSequenceNumber()), : Ctx(Ctx), NextSequenceNumber(GlobalContext::getFirstSequenceNumber()),
ErrorStatus() {} ErrorStatus() {}
......
...@@ -74,6 +74,20 @@ protected: ...@@ -74,6 +74,20 @@ protected:
ErrorCode ErrorStatus; ErrorCode ErrorStatus;
}; };
class CfgOptWorkItem final : public OptWorkItem {
CfgOptWorkItem() = delete;
CfgOptWorkItem(const CfgOptWorkItem &) = delete;
CfgOptWorkItem &operator=(const CfgOptWorkItem &) = delete;
public:
CfgOptWorkItem(std::unique_ptr<Cfg> Func) : Func(std::move(Func)) {}
std::unique_ptr<Cfg> getParsedCfg() override { return std::move(Func); }
~CfgOptWorkItem() override = default;
private:
std::unique_ptr<Ice::Cfg> Func;
};
} // end of namespace Ice } // end of namespace Ice
#endif // SUBZERO_SRC_ICETRANSLATOR_H #endif // SUBZERO_SRC_ICETRANSLATOR_H
//===- subzero/src/WasmTranslator.h - WASM to Subzero Translation ---------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares a driver for translating Wasm bitcode into PNaCl bitcode.
///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_WASMTRANSLATOR_H
#define SUBZERO_SRC_WASMTRANSLATOR_H
#include "IceGlobalContext.h"
#include "IceTranslator.h"
namespace v8 {
namespace internal {
class Zone;
namespace wasm {
class FunctionEnv;
} // end of namespace wasm
} // end of namespace internal
} // end of namespace v8
namespace Ice {
class WasmTranslator : public Translator {
WasmTranslator() = delete;
WasmTranslator(const WasmTranslator &) = delete;
WasmTranslator &operator=(const WasmTranslator &) = delete;
template <typename F = std::function<void(Ostream &)>> void log(F Fn) {
if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_Wasm)) {
Fn(Ctx->getStrDump());
Ctx->getStrDump().flush();
}
}
public:
explicit WasmTranslator(GlobalContext *Ctx);
void translate(const std::string &IRFilename,
std::unique_ptr<llvm::DataStreamer> InputStream);
/// Translates a single Wasm function.
///
/// Parameters:
/// Zone - an arena for the V8 code to allocate from.
/// Env - information about the function (signature, variable count, etc.).
/// Base - a pointer to the start of the Wasm module.
/// Start - a pointer to the start of the function within the module.
/// End - a pointer to the end of the function.
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:
std::unique_ptr<uint8_t[]> Buffer;
SizeT BufferSize;
};
}
#endif // SUBZERO_SRC_WASMTRANSLATOR_H
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