зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 7 changesets (bug 1574865, bug 1611302) for causing bustage in WasmCraneliftCompile.cpp CLOSED TREE
Backed out changeset 05de7598585a (bug 1574865) Backed out changeset f89941b23fce (bug 1574865) Backed out changeset 242e859e580f (bug 1574865) Backed out changeset 247e358f4fc7 (bug 1574865) Backed out changeset bdf099acc592 (bug 1574865) Backed out changeset 48c545152a47 (bug 1574865) Backed out changeset a6bd070aa7f2 (bug 1611302) --HG-- extra : amend_source : dd5db386f287ce1ee2f35d5f4c23bc304a905204
This commit is contained in:
Родитель
b6a7518552
Коммит
796b3ee54c
|
@ -45,7 +45,7 @@ rev = "8069f8f4189982e0b38fa6dc8993dd4fab41f728"
|
|||
[source."https://github.com/bytecodealliance/cranelift"]
|
||||
git = "https://github.com/bytecodealliance/cranelift"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
rev = "98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
|
||||
[source."https://github.com/badboy/failure"]
|
||||
git = "https://github.com/badboy/failure"
|
||||
|
|
|
@ -186,8 +186,8 @@ name = "baldrdash"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-wasm 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"cranelift-wasm 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -643,21 +643,21 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.56.0"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627#eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17#98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.56.0"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627#eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17#98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-bforest 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-codegen-meta 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-codegen-shared 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-bforest 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"cranelift-codegen-meta 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"cranelift-codegen-shared 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -667,16 +667,16 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.56.0"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627#eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17#98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-codegen-shared 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.56.0"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627#eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17#98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
|
@ -686,14 +686,14 @@ source = "git+https://github.com/PLSysSec/lucet_sandbox_compiler?rev=58498599272
|
|||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.56.0"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627#eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17#98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.56.0"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627#eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17#98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
dependencies = [
|
||||
"cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -702,11 +702,11 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cranelift-wasm"
|
||||
version = "0.56.0"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627#eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
source = "git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17#98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
dependencies = [
|
||||
"cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-frontend 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)",
|
||||
"cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"cranelift-frontend 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmparser 0.47.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -4656,14 +4656,14 @@ dependencies = [
|
|||
"checksum coreaudio-sys-utils 0.1.0 (git+https://github.com/ChunMinChang/cubeb-coreaudio-rs?rev=4d8fcc1954df217fbb29166e7ae750bf26d47203)" = "<none>"
|
||||
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
|
||||
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
|
||||
"checksum cranelift-bforest 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)" = "<none>"
|
||||
"checksum cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)" = "<none>"
|
||||
"checksum cranelift-codegen-meta 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)" = "<none>"
|
||||
"checksum cranelift-codegen-shared 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)" = "<none>"
|
||||
"checksum cranelift-bforest 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)" = "<none>"
|
||||
"checksum cranelift-codegen 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)" = "<none>"
|
||||
"checksum cranelift-codegen-meta 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)" = "<none>"
|
||||
"checksum cranelift-codegen-shared 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)" = "<none>"
|
||||
"checksum cranelift-entity 0.41.0 (git+https://github.com/PLSysSec/lucet_sandbox_compiler?rev=58498599272e23ef797bb4304d0f181d7455ca57)" = "<none>"
|
||||
"checksum cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)" = "<none>"
|
||||
"checksum cranelift-frontend 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)" = "<none>"
|
||||
"checksum cranelift-wasm 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=eb20fcab349ce20ac6f8659d1c4b058108d5e627)" = "<none>"
|
||||
"checksum cranelift-entity 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)" = "<none>"
|
||||
"checksum cranelift-frontend 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)" = "<none>"
|
||||
"checksum cranelift-wasm 0.56.0 (git+https://github.com/bytecodealliance/cranelift?rev=98633eeb0d249efae23ee69ec03dc35b7d9bec17)" = "<none>"
|
||||
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||
"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
|
||||
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
||||
|
|
|
@ -71,8 +71,8 @@ failure_derive = { git = "https://github.com/badboy/failure", rev = "64af847bc5f
|
|||
|
||||
[patch.crates-io.cranelift-codegen]
|
||||
git = "https://github.com/bytecodealliance/cranelift"
|
||||
rev = "eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
rev = "98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
|
||||
[patch.crates-io.cranelift-wasm]
|
||||
git = "https://github.com/bytecodealliance/cranelift"
|
||||
rev = "eb20fcab349ce20ac6f8659d1c4b058108d5e627"
|
||||
rev = "98633eeb0d249efae23ee69ec03dc35b7d9bec17"
|
||||
|
|
|
@ -41,7 +41,7 @@ const F32Code = 0x7d;
|
|||
const F64Code = 0x7c;
|
||||
const AnyFuncCode = 0x70;
|
||||
const AnyrefCode = 0x6f;
|
||||
const RefCode = 0x6d;
|
||||
const RefCode = 0x6e;
|
||||
const FuncCode = 0x60;
|
||||
const VoidCode = 0x40;
|
||||
|
||||
|
|
|
@ -10259,6 +10259,32 @@ void CodeGenerator::visitRest(LRest* lir) {
|
|||
false, ToRegister(lir->output()));
|
||||
}
|
||||
|
||||
// A stackmap creation helper. Create a stackmap from a vector of booleans.
|
||||
// The caller owns the resulting stackmap.
|
||||
|
||||
typedef Vector<bool, 128, SystemAllocPolicy> StackMapBoolVector;
|
||||
|
||||
static wasm::StackMap* ConvertStackMapBoolVectorToStackMap(
|
||||
const StackMapBoolVector& vec, bool hasRefs) {
|
||||
wasm::StackMap* stackMap = wasm::StackMap::create(vec.length());
|
||||
if (!stackMap) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hasRefsObserved = false;
|
||||
size_t i = 0;
|
||||
for (bool b : vec) {
|
||||
if (b) {
|
||||
stackMap->setBit(i);
|
||||
hasRefsObserved = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(hasRefs == hasRefsObserved);
|
||||
|
||||
return stackMap;
|
||||
}
|
||||
|
||||
// Create a stackmap from the given safepoint, with the structure:
|
||||
//
|
||||
// <reg dump area, if trap>
|
||||
|
@ -10301,7 +10327,7 @@ static bool CreateStackMapFromLSafepoint(LSafepoint& safepoint,
|
|||
// contain 128 or fewer words, heap allocation is avoided in the majority of
|
||||
// cases. vec[0] is for the lowest address in the map, vec[N-1] is for the
|
||||
// highest address in the map.
|
||||
wasm::StackMapBoolVector vec;
|
||||
StackMapBoolVector vec;
|
||||
|
||||
// Keep track of whether we've actually seen any refs.
|
||||
bool hasRefs = false;
|
||||
|
@ -10378,8 +10404,7 @@ static bool CreateStackMapFromLSafepoint(LSafepoint& safepoint,
|
|||
|
||||
// Convert vec into a wasm::StackMap.
|
||||
MOZ_ASSERT(vec.length() * sizeof(void*) == nTotalBytes);
|
||||
wasm::StackMap* stackMap =
|
||||
wasm::ConvertStackMapBoolVectorToStackMap(vec, hasRefs);
|
||||
wasm::StackMap* stackMap = ConvertStackMapBoolVectorToStackMap(vec, hasRefs);
|
||||
if (!stackMap) {
|
||||
return false;
|
||||
}
|
||||
|
@ -10403,6 +10428,129 @@ static bool CreateStackMapFromLSafepoint(LSafepoint& safepoint,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Generate a stackmap for a function's stack-overflow-at-entry trap, with
|
||||
// the structure:
|
||||
//
|
||||
// <reg dump area>
|
||||
// | ++ <space reserved before trap, if any>
|
||||
// | ++ <space for Frame>
|
||||
// | ++ <inbound arg area>
|
||||
// | |
|
||||
// Lowest Addr Highest Addr
|
||||
//
|
||||
// The caller owns the resulting stackmap. This assumes a grow-down stack.
|
||||
//
|
||||
// For non-debug builds, if the stackmap would contain no pointers, no
|
||||
// stackmap is created, and nullptr is returned. For a debug build, a
|
||||
// stackmap is always created and returned.
|
||||
//
|
||||
// The "space reserved before trap" is the space reserved by
|
||||
// MacroAssembler::wasmReserveStackChecked, in the case where the frame is
|
||||
// "small", as determined by that function.
|
||||
static bool CreateStackMapForFunctionEntryTrap(
|
||||
const wasm::ArgTypeVector& argTypes, const MachineState& trapExitLayout,
|
||||
size_t trapExitLayoutWords, size_t nBytesReservedBeforeTrap,
|
||||
size_t nInboundStackArgBytes, wasm::StackMap** result) {
|
||||
// Ensure this is defined on all return paths.
|
||||
*result = nullptr;
|
||||
|
||||
// The size of the wasm::Frame itself.
|
||||
const size_t nFrameBytes = sizeof(wasm::Frame);
|
||||
|
||||
// The size of the register dump (trap) area.
|
||||
const size_t trapExitLayoutBytes = trapExitLayoutWords * sizeof(void*);
|
||||
|
||||
// This is the total number of bytes covered by the map.
|
||||
const DebugOnly<size_t> nTotalBytes = trapExitLayoutBytes +
|
||||
nBytesReservedBeforeTrap + nFrameBytes +
|
||||
nInboundStackArgBytes;
|
||||
|
||||
// Create the stackmap initially in this vector. Since most frames will
|
||||
// contain 128 or fewer words, heap allocation is avoided in the majority of
|
||||
// cases. vec[0] is for the lowest address in the map, vec[N-1] is for the
|
||||
// highest address in the map.
|
||||
StackMapBoolVector vec;
|
||||
|
||||
// Keep track of whether we've actually seen any refs.
|
||||
bool hasRefs = false;
|
||||
|
||||
// REG DUMP AREA
|
||||
wasm::ExitStubMapVector trapExitExtras;
|
||||
if (!GenerateStackmapEntriesForTrapExit(
|
||||
argTypes, trapExitLayout, trapExitLayoutWords, &trapExitExtras)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(trapExitExtras.length() == trapExitLayoutWords);
|
||||
|
||||
if (!vec.appendN(false, trapExitLayoutWords)) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < trapExitLayoutWords; i++) {
|
||||
vec[i] = trapExitExtras[i];
|
||||
hasRefs |= vec[i];
|
||||
}
|
||||
|
||||
// SPACE RESERVED BEFORE TRAP
|
||||
MOZ_ASSERT(nBytesReservedBeforeTrap % sizeof(void*) == 0);
|
||||
if (!vec.appendN(false, nBytesReservedBeforeTrap / sizeof(void*))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SPACE FOR FRAME
|
||||
if (!vec.appendN(false, nFrameBytes / sizeof(void*))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// INBOUND ARG AREA
|
||||
MOZ_ASSERT(nInboundStackArgBytes % sizeof(void*) == 0);
|
||||
const size_t numStackArgWords = nInboundStackArgBytes / sizeof(void*);
|
||||
|
||||
const size_t wordsSoFar = vec.length();
|
||||
if (!vec.appendN(false, numStackArgWords)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ABIArgIter i(argTypes); !i.done(); i++) {
|
||||
ABIArg argLoc = *i;
|
||||
if (argLoc.kind() == ABIArg::Stack &&
|
||||
argTypes[i.index()] == MIRType::RefOrNull) {
|
||||
uint32_t offset = argLoc.offsetFromArgBase();
|
||||
MOZ_ASSERT(offset < nInboundStackArgBytes);
|
||||
MOZ_ASSERT(offset % sizeof(void*) == 0);
|
||||
vec[wordsSoFar + offset / sizeof(void*)] = true;
|
||||
hasRefs = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
// We saw no references, and this is a non-debug build, so don't bother
|
||||
// building the stackmap.
|
||||
if (!hasRefs) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Convert vec into a wasm::StackMap.
|
||||
MOZ_ASSERT(vec.length() * sizeof(void*) == nTotalBytes);
|
||||
wasm::StackMap* stackMap = ConvertStackMapBoolVectorToStackMap(vec, hasRefs);
|
||||
if (!stackMap) {
|
||||
return false;
|
||||
}
|
||||
stackMap->setExitStubWords(trapExitLayoutWords);
|
||||
|
||||
stackMap->setFrameOffsetFromTop(nFrameBytes / sizeof(void*) +
|
||||
numStackArgWords);
|
||||
#ifdef DEBUG
|
||||
for (uint32_t i = 0; i < nFrameBytes / sizeof(void*); i++) {
|
||||
MOZ_ASSERT(stackMap->getBit(stackMap->numMappedWords -
|
||||
stackMap->frameOffsetFromTop + i) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
*result = stackMap;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodeGenerator::generateWasm(wasm::FuncTypeIdDesc funcTypeId,
|
||||
wasm::BytecodeOffset trapOffset,
|
||||
const wasm::ArgTypeVector& argTypes,
|
||||
|
|
|
@ -13003,9 +13003,9 @@ bool js::wasm::BaselineCompileFunctions(const ModuleEnvironment& env,
|
|||
bool js::wasm::IsValidStackMapKey(bool debugEnabled, const uint8_t* nextPC) {
|
||||
# if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
|
||||
const uint8_t* insn = nextPC;
|
||||
return (insn[-2] == 0x0F && insn[-1] == 0x0B) || // ud2
|
||||
(insn[-2] == 0xFF && (insn[-1] & 0xF8) == 0xD0) || // call *%r_
|
||||
insn[-5] == 0xE8 || // call simm32
|
||||
return (insn[-2] == 0x0F && insn[-1] == 0x0B) || // ud2
|
||||
(insn[-2] == 0xFF && insn[-1] == 0xD0) || // call *%{rax,eax}
|
||||
insn[-5] == 0xE8 || // call simm32
|
||||
(debugEnabled && insn[-5] == 0x0F && insn[-4] == 0x1F &&
|
||||
insn[-3] == 0x44 && insn[-2] == 0x00 &&
|
||||
insn[-1] == 0x00); // nop_five
|
||||
|
|
|
@ -194,12 +194,6 @@ const SymbolicAddressSignature SASigTableSize = {
|
|||
SymbolicAddress::TableSize, _I32, _Infallible, 2, {_PTR, _I32, _END}};
|
||||
const SymbolicAddressSignature SASigFuncRef = {
|
||||
SymbolicAddress::FuncRef, _RoN, _FailOnInvalidRef, 2, {_PTR, _I32, _END}};
|
||||
const SymbolicAddressSignature SASigPreBarrierFiltering = {
|
||||
SymbolicAddress::PreBarrierFiltering,
|
||||
_VOID,
|
||||
_Infallible,
|
||||
2,
|
||||
{_PTR, _PTR, _END}};
|
||||
const SymbolicAddressSignature SASigPostBarrier = {
|
||||
SymbolicAddress::PostBarrier, _VOID, _Infallible, 2, {_PTR, _PTR, _END}};
|
||||
const SymbolicAddressSignature SASigPostBarrierFiltering = {
|
||||
|
@ -1077,11 +1071,6 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) {
|
|||
{ArgType_General, ArgType_General});
|
||||
MOZ_ASSERT(*abiType == ToABIType(SASigPostBarrier));
|
||||
return FuncCast(Instance::postBarrier, *abiType);
|
||||
case SymbolicAddress::PreBarrierFiltering:
|
||||
*abiType = MakeABIFunctionType(ArgType_Int32,
|
||||
{ArgType_General, ArgType_General});
|
||||
MOZ_ASSERT(*abiType == ToABIType(SASigPreBarrierFiltering));
|
||||
return FuncCast(Instance::preBarrierFiltering, *abiType);
|
||||
case SymbolicAddress::PostBarrierFiltering:
|
||||
*abiType = MakeABIFunctionType(ArgType_Int32,
|
||||
{ArgType_General, ArgType_General});
|
||||
|
@ -1219,7 +1208,6 @@ bool wasm::NeedsBuiltinThunk(SymbolicAddress sym) {
|
|||
case SymbolicAddress::TableSet:
|
||||
case SymbolicAddress::TableSize:
|
||||
case SymbolicAddress::FuncRef:
|
||||
case SymbolicAddress::PreBarrierFiltering:
|
||||
case SymbolicAddress::PostBarrier:
|
||||
case SymbolicAddress::PostBarrierFiltering:
|
||||
case SymbolicAddress::StructNew:
|
||||
|
|
|
@ -67,7 +67,6 @@ extern const SymbolicAddressSignature SASigTableInit;
|
|||
extern const SymbolicAddressSignature SASigTableSet;
|
||||
extern const SymbolicAddressSignature SASigTableSize;
|
||||
extern const SymbolicAddressSignature SASigFuncRef;
|
||||
extern const SymbolicAddressSignature SASigPreBarrierFiltering;
|
||||
extern const SymbolicAddressSignature SASigPostBarrier;
|
||||
extern const SymbolicAddressSignature SASigPostBarrierFiltering;
|
||||
extern const SymbolicAddressSignature SASigStructNew;
|
||||
|
|
|
@ -515,7 +515,11 @@ void CompilerEnvironment::computeParameters(Decoder& d, bool gcFeatureOptIn) {
|
|||
|
||||
debug_ = debugEnabled ? DebugEnabled::True : DebugEnabled::False;
|
||||
gcTypes_ = gcEnabled;
|
||||
refTypes_ = true;
|
||||
#ifdef ENABLE_WASM_REFTYPES
|
||||
refTypes_ = !craneliftEnabled;
|
||||
#else
|
||||
refTypes_ = false;
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_MULTI_VALUE
|
||||
multiValues_ = !craneliftEnabled;
|
||||
#else
|
||||
|
@ -623,7 +627,7 @@ void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
|
|||
|
||||
bool gcTypesConfigured = false; // No optimized backend support yet
|
||||
#ifdef ENABLE_WASM_REFTYPES
|
||||
bool refTypesConfigured = true;
|
||||
bool refTypesConfigured = !args.craneliftEnabled;
|
||||
#else
|
||||
bool refTypesConfigured = false;
|
||||
#endif
|
||||
|
|
|
@ -62,13 +62,10 @@ enum class TypeCode {
|
|||
FuncRef = 0x70, // SLEB128(-0x10)
|
||||
|
||||
// A reference to any type.
|
||||
AnyRef = 0x6f, // SLEB128(-0x11)
|
||||
|
||||
// A null reference.
|
||||
NullRef = 0x6e, // SLEB128(-0x12)
|
||||
AnyRef = 0x6f,
|
||||
|
||||
// Type constructor for reference types.
|
||||
Ref = 0x6d,
|
||||
Ref = 0x6e,
|
||||
|
||||
// Type constructor for function types
|
||||
Func = 0x60, // SLEB128(-0x20)
|
||||
|
@ -79,6 +76,9 @@ enum class TypeCode {
|
|||
// The 'empty' case of blocktype.
|
||||
BlockVoid = 0x40, // SLEB128(-0x40)
|
||||
|
||||
// Type designator for null - unofficial, will not appear in the binary format
|
||||
NullRef = 0x39,
|
||||
|
||||
Limit = 0x80
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "wasm/cranelift/baldrapi.h"
|
||||
#include "wasm/cranelift/clifapi.h"
|
||||
#include "wasm/WasmFrameIter.h" // js::wasm::GenerateFunction{Pro,Epi}logue
|
||||
#include "wasm/WasmGC.h"
|
||||
#include "wasm/WasmGenerator.h"
|
||||
|
||||
#include "jit/MacroAssembler-inl.h"
|
||||
|
@ -45,8 +44,6 @@ bool wasm::CraneliftCanCompile() {
|
|||
|
||||
static inline SymbolicAddress ToSymbolicAddress(BD_SymbolicAddress bd) {
|
||||
switch (bd) {
|
||||
case BD_SymbolicAddress::RefFunc:
|
||||
return SymbolicAddress::FuncRef;
|
||||
case BD_SymbolicAddress::MemoryGrow:
|
||||
return SymbolicAddress::MemoryGrow;
|
||||
case BD_SymbolicAddress::MemorySize:
|
||||
|
@ -95,10 +92,6 @@ static inline SymbolicAddress ToSymbolicAddress(BD_SymbolicAddress bd) {
|
|||
return SymbolicAddress::TruncF;
|
||||
case BD_SymbolicAddress::TruncF64:
|
||||
return SymbolicAddress::TruncD;
|
||||
case BD_SymbolicAddress::PreBarrier:
|
||||
return SymbolicAddress::PreBarrierFiltering;
|
||||
case BD_SymbolicAddress::PostBarrier:
|
||||
return SymbolicAddress::PostBarrierFiltering;
|
||||
case BD_SymbolicAddress::Limit:
|
||||
break;
|
||||
}
|
||||
|
@ -107,13 +100,10 @@ static inline SymbolicAddress ToSymbolicAddress(BD_SymbolicAddress bd) {
|
|||
|
||||
static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
const CraneliftCompiledFunc& func,
|
||||
const FuncTypeWithId& funcType,
|
||||
const FuncTypeIdDesc& funcTypeId,
|
||||
uint32_t lineOrBytecode,
|
||||
uint32_t funcBytecodeSize,
|
||||
StackMaps* stackMaps, size_t stackMapsOffset,
|
||||
size_t stackMapsCount, FuncOffsets* offsets) {
|
||||
const FuncTypeIdDesc& funcTypeId = funcType.id;
|
||||
|
||||
FuncOffsets* offsets) {
|
||||
wasm::GenerateFunctionPrologue(masm, funcTypeId, mozilla::Nothing(), offsets);
|
||||
|
||||
// Omit the check when framePushed is small and we know there's no
|
||||
|
@ -121,34 +111,8 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
|||
if (func.framePushed < MAX_UNCHECKED_LEAF_FRAME_SIZE && !func.containsCalls) {
|
||||
masm.reserveStack(func.framePushed);
|
||||
} else {
|
||||
std::pair<CodeOffset, uint32_t> pair = masm.wasmReserveStackChecked(
|
||||
func.framePushed, BytecodeOffset(lineOrBytecode));
|
||||
CodeOffset trapInsnOffset = pair.first;
|
||||
size_t nBytesReservedBeforeTrap = pair.second;
|
||||
|
||||
MachineState trapExitLayout;
|
||||
size_t trapExitLayoutNumWords;
|
||||
GenerateTrapExitMachineState(&trapExitLayout, &trapExitLayoutNumWords);
|
||||
|
||||
size_t nInboundStackArgBytes = StackArgAreaSizeUnaligned(funcType.args());
|
||||
|
||||
ArgTypeVector args(funcType);
|
||||
wasm::StackMap* functionEntryStackMap = nullptr;
|
||||
if (!CreateStackMapForFunctionEntryTrap(
|
||||
args, trapExitLayout, trapExitLayoutNumWords,
|
||||
nBytesReservedBeforeTrap, nInboundStackArgBytes,
|
||||
&functionEntryStackMap)) {
|
||||
return false;
|
||||
}
|
||||
// In debug builds, we'll always have a stack map, even if there are no
|
||||
// refs to track.
|
||||
MOZ_ALWAYS_TRUE(functionEntryStackMap);
|
||||
if (functionEntryStackMap &&
|
||||
!stackMaps->add((uint8_t*)(uintptr_t)trapInsnOffset.offset(),
|
||||
functionEntryStackMap)) {
|
||||
functionEntryStackMap->destroy();
|
||||
return false;
|
||||
}
|
||||
masm.wasmReserveStackChecked(func.framePushed,
|
||||
BytecodeOffset(lineOrBytecode));
|
||||
}
|
||||
MOZ_ASSERT(masm.framePushed() == func.framePushed);
|
||||
|
||||
|
@ -209,11 +173,6 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
|||
}
|
||||
offsets->end = masm.currentOffset();
|
||||
|
||||
for (size_t i = 0; i < stackMapsCount; i++) {
|
||||
auto* maplet = stackMaps->getRef(stackMapsOffset + i);
|
||||
maplet->offsetBy(funcBase);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < func.numMetadata; i++) {
|
||||
const CraneliftMetadataEntry& metadata = func.metadatas[i];
|
||||
|
||||
|
@ -291,7 +250,6 @@ class AutoCranelift {
|
|||
public:
|
||||
explicit AutoCranelift(const ModuleEnvironment& env)
|
||||
: env_(env), compiler_(nullptr) {
|
||||
staticEnv_.refTypesEnabled = env.refTypesEnabled();
|
||||
#ifdef WASM_SUPPORTS_HUGE_MEMORY
|
||||
if (env.hugeMemoryEnabled()) {
|
||||
// In the huge memory configuration, we always reserve the full 4 GB
|
||||
|
@ -355,7 +313,6 @@ CraneliftStaticEnvironment::CraneliftStaticEnvironment()
|
|||
#else
|
||||
platformIsWindows(false),
|
||||
#endif
|
||||
refTypesEnabled(false),
|
||||
staticMemoryBound(0),
|
||||
memoryGuardSize(0),
|
||||
memoryBaseTlsOffset(offsetof(TlsData, memoryBase)),
|
||||
|
@ -469,26 +426,20 @@ bool wasm::CraneliftCompileFunctions(const ModuleEnvironment& env,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t previousStackmapCount = code->stackMaps.length();
|
||||
|
||||
CraneliftFuncCompileInput clifInput(func);
|
||||
clifInput.stackmaps = (BD_Stackmaps*)&code->stackMaps;
|
||||
|
||||
CraneliftCompiledFunc clifFunc;
|
||||
|
||||
if (!cranelift_compile_function(compiler, &clifInput, &clifFunc)) {
|
||||
*error = JS_smprintf("Cranelift error in clifFunc #%u", clifInput.index);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t lineOrBytecode = func.lineOrBytecode;
|
||||
const FuncTypeWithId& funcType = *env.funcTypes[clifInput.index];
|
||||
const FuncTypeIdDesc& funcTypeId = env.funcTypes[clifInput.index]->id;
|
||||
|
||||
FuncOffsets offsets;
|
||||
if (!GenerateCraneliftCode(
|
||||
masm, clifFunc, funcType, lineOrBytecode, funcBytecodeSize,
|
||||
&code->stackMaps, previousStackmapCount,
|
||||
code->stackMaps.length() - previousStackmapCount, &offsets)) {
|
||||
if (!GenerateCraneliftCode(masm, clifFunc, funcTypeId, lineOrBytecode,
|
||||
funcBytecodeSize, &offsets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -584,9 +535,6 @@ BD_ConstantValue global_constantValue(const GlobalDesc* global) {
|
|||
case TypeCode::F64:
|
||||
v.u.f64 = value.f64();
|
||||
break;
|
||||
case TypeCode::Ref:
|
||||
v.u.r = value.ref().forCompiledCode();
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Bad type");
|
||||
}
|
||||
|
@ -604,6 +552,9 @@ size_t global_tlsOffset(const GlobalDesc* global) {
|
|||
// TableDesc
|
||||
|
||||
size_t table_tlsOffset(const TableDesc* table) {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
table->kind == TableKind::FuncRef || table->kind == TableKind::AsmJS,
|
||||
"cranelift doesn't support AnyRef tables yet.");
|
||||
return globalToTlsOffset(table->globalDataOffset);
|
||||
}
|
||||
|
||||
|
@ -638,25 +589,3 @@ size_t funcType_idImmediate(const FuncTypeWithId* funcType) {
|
|||
size_t funcType_idTlsOffset(const FuncTypeWithId* funcType) {
|
||||
return globalToTlsOffset(funcType->id.globalDataOffset());
|
||||
}
|
||||
|
||||
void stackmaps_add(BD_Stackmaps* sink, const uint32_t* bitMap, size_t mappedWords,
|
||||
size_t argsSize, size_t codeOffset) {
|
||||
const uint32_t BitElemSize = sizeof(uint32_t) * 8;
|
||||
|
||||
StackMaps* maps = (StackMaps*)sink;
|
||||
StackMap* map = StackMap::create(mappedWords);
|
||||
MOZ_ALWAYS_TRUE(map);
|
||||
|
||||
// Copy the cranelift stackmap into our spidermonkey one
|
||||
// TODO: Take ownership of the cranelift stackmap and avoid a copy
|
||||
for (uint32_t i = 0; i < mappedWords; i++) {
|
||||
uint32_t bit = (bitMap[i / BitElemSize] >> (i % BitElemSize)) & 0x1;
|
||||
if (bit) {
|
||||
map->setBit(i);
|
||||
}
|
||||
}
|
||||
|
||||
map->setFrameOffsetFromTop((argsSize + sizeof(wasm::Frame)) /
|
||||
sizeof(uintptr_t));
|
||||
MOZ_ALWAYS_TRUE(maps->add((uint8_t*)codeOffset, map));
|
||||
}
|
||||
|
|
|
@ -1389,8 +1389,6 @@ static const char* ThunkedNativeToDescription(SymbolicAddress func) {
|
|||
return "call to native table.size function";
|
||||
case SymbolicAddress::FuncRef:
|
||||
return "call to native func.ref function";
|
||||
case SymbolicAddress::PreBarrierFiltering:
|
||||
return "call to native filtering GC prebarrier (in wasm)";
|
||||
case SymbolicAddress::PostBarrier:
|
||||
return "call to native GC postbarrier (in wasm)";
|
||||
case SymbolicAddress::PostBarrierFiltering:
|
||||
|
|
|
@ -23,150 +23,6 @@
|
|||
namespace js {
|
||||
namespace wasm {
|
||||
|
||||
wasm::StackMap* ConvertStackMapBoolVectorToStackMap(
|
||||
const StackMapBoolVector& vec, bool hasRefs) {
|
||||
wasm::StackMap* stackMap = wasm::StackMap::create(vec.length());
|
||||
if (!stackMap) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hasRefsObserved = false;
|
||||
size_t i = 0;
|
||||
for (bool b : vec) {
|
||||
if (b) {
|
||||
stackMap->setBit(i);
|
||||
hasRefsObserved = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(hasRefs == hasRefsObserved);
|
||||
|
||||
return stackMap;
|
||||
}
|
||||
|
||||
// Generate a stackmap for a function's stack-overflow-at-entry trap, with
|
||||
// the structure:
|
||||
//
|
||||
// <reg dump area>
|
||||
// | ++ <space reserved before trap, if any>
|
||||
// | ++ <space for Frame>
|
||||
// | ++ <inbound arg area>
|
||||
// | |
|
||||
// Lowest Addr Highest Addr
|
||||
//
|
||||
// The caller owns the resulting stackmap. This assumes a grow-down stack.
|
||||
//
|
||||
// For non-debug builds, if the stackmap would contain no pointers, no
|
||||
// stackmap is created, and nullptr is returned. For a debug build, a
|
||||
// stackmap is always created and returned.
|
||||
//
|
||||
// The "space reserved before trap" is the space reserved by
|
||||
// MacroAssembler::wasmReserveStackChecked, in the case where the frame is
|
||||
// "small", as determined by that function.
|
||||
bool CreateStackMapForFunctionEntryTrap(
|
||||
const wasm::ArgTypeVector& argTypes, const MachineState& trapExitLayout,
|
||||
size_t trapExitLayoutWords, size_t nBytesReservedBeforeTrap,
|
||||
size_t nInboundStackArgBytes, wasm::StackMap** result) {
|
||||
// Ensure this is defined on all return paths.
|
||||
*result = nullptr;
|
||||
|
||||
// The size of the wasm::Frame itself.
|
||||
const size_t nFrameBytes = sizeof(wasm::Frame);
|
||||
|
||||
// The size of the register dump (trap) area.
|
||||
const size_t trapExitLayoutBytes = trapExitLayoutWords * sizeof(void*);
|
||||
|
||||
// This is the total number of bytes covered by the map.
|
||||
const DebugOnly<size_t> nTotalBytes = trapExitLayoutBytes +
|
||||
nBytesReservedBeforeTrap + nFrameBytes +
|
||||
nInboundStackArgBytes;
|
||||
|
||||
// Create the stackmap initially in this vector. Since most frames will
|
||||
// contain 128 or fewer words, heap allocation is avoided in the majority of
|
||||
// cases. vec[0] is for the lowest address in the map, vec[N-1] is for the
|
||||
// highest address in the map.
|
||||
StackMapBoolVector vec;
|
||||
|
||||
// Keep track of whether we've actually seen any refs.
|
||||
bool hasRefs = false;
|
||||
|
||||
// REG DUMP AREA
|
||||
wasm::ExitStubMapVector trapExitExtras;
|
||||
if (!GenerateStackmapEntriesForTrapExit(
|
||||
argTypes, trapExitLayout, trapExitLayoutWords, &trapExitExtras)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(trapExitExtras.length() == trapExitLayoutWords);
|
||||
|
||||
if (!vec.appendN(false, trapExitLayoutWords)) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < trapExitLayoutWords; i++) {
|
||||
vec[i] = trapExitExtras[i];
|
||||
hasRefs |= vec[i];
|
||||
}
|
||||
|
||||
// SPACE RESERVED BEFORE TRAP
|
||||
MOZ_ASSERT(nBytesReservedBeforeTrap % sizeof(void*) == 0);
|
||||
if (!vec.appendN(false, nBytesReservedBeforeTrap / sizeof(void*))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SPACE FOR FRAME
|
||||
if (!vec.appendN(false, nFrameBytes / sizeof(void*))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// INBOUND ARG AREA
|
||||
MOZ_ASSERT(nInboundStackArgBytes % sizeof(void*) == 0);
|
||||
const size_t numStackArgWords = nInboundStackArgBytes / sizeof(void*);
|
||||
|
||||
const size_t wordsSoFar = vec.length();
|
||||
if (!vec.appendN(false, numStackArgWords)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ABIArgIter i(argTypes); !i.done(); i++) {
|
||||
ABIArg argLoc = *i;
|
||||
if (argLoc.kind() == ABIArg::Stack &&
|
||||
argTypes[i.index()] == MIRType::RefOrNull) {
|
||||
uint32_t offset = argLoc.offsetFromArgBase();
|
||||
MOZ_ASSERT(offset < nInboundStackArgBytes);
|
||||
MOZ_ASSERT(offset % sizeof(void*) == 0);
|
||||
vec[wordsSoFar + offset / sizeof(void*)] = true;
|
||||
hasRefs = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
// We saw no references, and this is a non-debug build, so don't bother
|
||||
// building the stackmap.
|
||||
if (!hasRefs) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Convert vec into a wasm::StackMap.
|
||||
MOZ_ASSERT(vec.length() * sizeof(void*) == nTotalBytes);
|
||||
wasm::StackMap* stackMap = ConvertStackMapBoolVectorToStackMap(vec, hasRefs);
|
||||
if (!stackMap) {
|
||||
return false;
|
||||
}
|
||||
stackMap->setExitStubWords(trapExitLayoutWords);
|
||||
|
||||
stackMap->setFrameOffsetFromTop(nFrameBytes / sizeof(void*) +
|
||||
numStackArgWords);
|
||||
#ifdef DEBUG
|
||||
for (uint32_t i = 0; i < nFrameBytes / sizeof(void*); i++) {
|
||||
MOZ_ASSERT(stackMap->getBit(stackMap->numMappedWords -
|
||||
stackMap->frameOffsetFromTop + i) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
*result = stackMap;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GenerateStackmapEntriesForTrapExit(const ArgTypeVector& args,
|
||||
const MachineState& trapExitLayout,
|
||||
const size_t trapExitLayoutNumWords,
|
||||
|
|
|
@ -196,7 +196,6 @@ class StackMaps {
|
|||
}
|
||||
bool empty() const { return mapping_.empty(); }
|
||||
size_t length() const { return mapping_.length(); }
|
||||
Maplet* getRef(size_t i) { return &mapping_[i]; }
|
||||
Maplet get(size_t i) const { return mapping_[i]; }
|
||||
Maplet move(size_t i) {
|
||||
Maplet m = mapping_[i];
|
||||
|
@ -295,38 +294,6 @@ static inline size_t StackArgAreaSizeAligned(const T& argTypes) {
|
|||
return AlignStackArgAreaSize(StackArgAreaSizeUnaligned(argTypes));
|
||||
}
|
||||
|
||||
// A stackmap creation helper. Create a stackmap from a vector of booleans.
|
||||
// The caller owns the resulting stackmap.
|
||||
|
||||
typedef Vector<bool, 128, SystemAllocPolicy> StackMapBoolVector;
|
||||
|
||||
wasm::StackMap* ConvertStackMapBoolVectorToStackMap(
|
||||
const StackMapBoolVector& vec, bool hasRefs);
|
||||
|
||||
// Generate a stackmap for a function's stack-overflow-at-entry trap, with
|
||||
// the structure:
|
||||
//
|
||||
// <reg dump area>
|
||||
// | ++ <space reserved before trap, if any>
|
||||
// | ++ <space for Frame>
|
||||
// | ++ <inbound arg area>
|
||||
// | |
|
||||
// Lowest Addr Highest Addr
|
||||
//
|
||||
// The caller owns the resulting stackmap. This assumes a grow-down stack.
|
||||
//
|
||||
// For non-debug builds, if the stackmap would contain no pointers, no
|
||||
// stackmap is created, and nullptr is returned. For a debug build, a
|
||||
// stackmap is always created and returned.
|
||||
//
|
||||
// The "space reserved before trap" is the space reserved by
|
||||
// MacroAssembler::wasmReserveStackChecked, in the case where the frame is
|
||||
// "small", as determined by that function.
|
||||
MOZ_MUST_USE bool CreateStackMapForFunctionEntryTrap(
|
||||
const ArgTypeVector& argTypes, const MachineState& trapExitLayout,
|
||||
size_t trapExitLayoutWords, size_t nBytesReservedBeforeTrap,
|
||||
size_t nInboundStackArgBytes, wasm::StackMap** result);
|
||||
|
||||
// At a resumable wasm trap, the machine's registers are saved on the stack by
|
||||
// (code generated by) GenerateTrapExit(). This function writes into |args| a
|
||||
// vector of booleans describing the ref-ness of the saved integer registers.
|
||||
|
|
|
@ -1006,13 +1006,6 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
|
|||
return FuncRef::fromJSFunction(fun).forCompiledCode();
|
||||
}
|
||||
|
||||
/* static */ void Instance::preBarrierFiltering(Instance* instance,
|
||||
gc::Cell** location) {
|
||||
MOZ_ASSERT(SASigPreBarrierFiltering.failureMode == FailureMode::Infallible);
|
||||
MOZ_ASSERT(location);
|
||||
JSObject::writeBarrierPre(*reinterpret_cast<JSObject**>(location));
|
||||
}
|
||||
|
||||
/* static */ void Instance::postBarrier(Instance* instance,
|
||||
gc::Cell** location) {
|
||||
MOZ_ASSERT(SASigPostBarrier.failureMode == FailureMode::Infallible);
|
||||
|
|
|
@ -228,7 +228,6 @@ class Instance {
|
|||
uint32_t srcOffset, uint32_t len, uint32_t segIndex,
|
||||
uint32_t tableIndex);
|
||||
static void* funcRef(Instance* instance, uint32_t funcIndex);
|
||||
static void preBarrierFiltering(Instance* instance, gc::Cell** location);
|
||||
static void postBarrier(Instance* instance, gc::Cell** location);
|
||||
static void postBarrierFiltering(Instance* instance, gc::Cell** location);
|
||||
static void* structNew(Instance* instance, uint32_t typeIndex);
|
||||
|
|
|
@ -65,6 +65,11 @@ using mozilla::RangedPtr;
|
|||
extern mozilla::Atomic<bool> fuzzingSafe;
|
||||
|
||||
bool wasm::HasReftypesSupport(JSContext* cx) {
|
||||
#ifdef ENABLE_WASM_CRANELIFT
|
||||
if (cx->options().wasmCranelift()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_REFTYPES
|
||||
return true;
|
||||
#else
|
||||
|
|
|
@ -2267,7 +2267,6 @@ enum class SymbolicAddress {
|
|||
TableSet,
|
||||
TableSize,
|
||||
FuncRef,
|
||||
PreBarrierFiltering,
|
||||
PostBarrier,
|
||||
PostBarrierFiltering,
|
||||
StructNew,
|
||||
|
|
|
@ -67,7 +67,6 @@ struct CraneliftStaticEnvironment {
|
|||
bool hasBmi2;
|
||||
bool hasLzcnt;
|
||||
bool platformIsWindows;
|
||||
bool refTypesEnabled;
|
||||
size_t staticMemoryBound;
|
||||
size_t memoryGuardSize;
|
||||
size_t memoryBaseTlsOffset;
|
||||
|
@ -95,8 +94,6 @@ struct CraneliftModuleEnvironment {
|
|||
const js::wasm::ModuleEnvironment& env);
|
||||
};
|
||||
|
||||
struct BD_Stackmaps;
|
||||
|
||||
// Data for a single wasm function to be compiled by Cranelift.
|
||||
// This information is all from the corresponding `js::wasm::FuncCompileInput`
|
||||
// struct, but formatted in a Rust-friendly way.
|
||||
|
@ -107,9 +104,6 @@ struct CraneliftFuncCompileInput {
|
|||
uint32_t index;
|
||||
uint32_t offset_in_module;
|
||||
|
||||
// The stackmaps sink to use when compiling this function
|
||||
BD_Stackmaps* stackmaps;
|
||||
|
||||
// Not bindgen'd because it's inlined.
|
||||
explicit inline CraneliftFuncCompileInput(const js::wasm::FuncCompileInput&);
|
||||
};
|
||||
|
@ -171,7 +165,6 @@ struct BD_ConstantValue {
|
|||
int64_t i64;
|
||||
float f32;
|
||||
double f64;
|
||||
void* r;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -191,15 +184,14 @@ enum class BD_SymbolicAddress : uint32_t {
|
|||
MemoryFill,
|
||||
MemoryFillShared,
|
||||
MemoryInit,
|
||||
TableSize,
|
||||
TableGrow,
|
||||
TableGet,
|
||||
TableSet,
|
||||
TableCopy,
|
||||
TableFill,
|
||||
TableInit,
|
||||
ElemDrop,
|
||||
RefFunc,
|
||||
TableFill,
|
||||
TableGet,
|
||||
TableGrow,
|
||||
TableInit,
|
||||
TableSet,
|
||||
TableSize,
|
||||
FloorF32,
|
||||
FloorF64,
|
||||
CeilF32,
|
||||
|
@ -208,8 +200,6 @@ enum class BD_SymbolicAddress : uint32_t {
|
|||
NearestF64,
|
||||
TruncF32,
|
||||
TruncF64,
|
||||
PreBarrier,
|
||||
PostBarrier,
|
||||
Limit
|
||||
};
|
||||
|
||||
|
@ -245,10 +235,6 @@ const BD_ValType* funcType_results(const js::wasm::FuncTypeWithId*);
|
|||
js::wasm::FuncTypeIdDescKind funcType_idKind(const js::wasm::FuncTypeWithId*);
|
||||
size_t funcType_idImmediate(const js::wasm::FuncTypeWithId*);
|
||||
size_t funcType_idTlsOffset(const js::wasm::FuncTypeWithId*);
|
||||
|
||||
void stackmaps_add(BD_Stackmaps* sink, const uint32_t* bitMap,
|
||||
size_t mappedWords, size_t argsSize, size_t codeOffset);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // wasm_cranelift_baldrapi_h
|
||||
|
|
|
@ -37,7 +37,6 @@ fn main() {
|
|||
.whitelist_function("global_.*")
|
||||
.whitelist_function("table_.*")
|
||||
.whitelist_function("funcType_.*")
|
||||
.whitelist_function("stackmaps_.*")
|
||||
.whitelist_type("Cranelift.*")
|
||||
// The enum classes defined in baldrapi.h and WasmBinaryConstants are all Rust-safe.
|
||||
.rustified_enum("BD_.*|Trap|TypeCode|FuncTypeIdDescKind")
|
||||
|
|
|
@ -30,7 +30,6 @@ use smallvec::SmallVec;
|
|||
|
||||
use crate::compile;
|
||||
use crate::utils::BasicError;
|
||||
use crate::wasm2clif::REF_TYPE;
|
||||
|
||||
use self::low_level::*;
|
||||
|
||||
|
@ -54,9 +53,6 @@ fn typecode_to_type(type_code: TypeCode) -> WasmResult<Option<ir::Type>> {
|
|||
TypeCode::I64 => Ok(Some(ir::types::I64)),
|
||||
TypeCode::F32 => Ok(Some(ir::types::F32)),
|
||||
TypeCode::F64 => Ok(Some(ir::types::F64)),
|
||||
TypeCode::NullRef => Ok(Some(REF_TYPE)),
|
||||
TypeCode::FuncRef => Ok(Some(REF_TYPE)),
|
||||
TypeCode::AnyRef => Ok(Some(REF_TYPE)),
|
||||
TypeCode::BlockVoid => Ok(None),
|
||||
_ => Err(BasicError::new(format!("unknown type code: {:?}", type_code)).into()),
|
||||
}
|
||||
|
@ -109,10 +105,6 @@ impl GlobalDesc {
|
|||
TypeCode::I64 => Ok(pos.ins().iconst(ir::types::I64, v.u.i64)),
|
||||
TypeCode::F32 => Ok(pos.ins().f32const(Ieee32::with_bits(v.u.i32 as u32))),
|
||||
TypeCode::F64 => Ok(pos.ins().f64const(Ieee64::with_bits(v.u.i64 as u64))),
|
||||
TypeCode::Ref | TypeCode::AnyRef | TypeCode::FuncRef | TypeCode::NullRef => {
|
||||
assert!(v.u.r as usize == 0);
|
||||
Ok(pos.ins().null(REF_TYPE))
|
||||
}
|
||||
_ => Err(BasicError::new(format!("unexpected type: {}", v.t as u64)).into()),
|
||||
}
|
||||
}
|
||||
|
@ -238,10 +230,6 @@ impl FuncCompileInput {
|
|||
pub fn bytecode(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.bytecode, self.bytecodeSize) }
|
||||
}
|
||||
|
||||
pub fn stackmaps(&self) -> Stackmaps {
|
||||
Stackmaps(self.stackmaps)
|
||||
}
|
||||
}
|
||||
|
||||
impl CompiledFunc {
|
||||
|
@ -320,25 +308,3 @@ impl StaticEnvironment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Stackmaps(*mut self::low_level::BD_Stackmaps);
|
||||
|
||||
impl Stackmaps {
|
||||
pub fn add_stackmap(
|
||||
&mut self,
|
||||
stack_slots: &ir::StackSlots,
|
||||
offset: CodeOffset,
|
||||
map: cranelift_codegen::binemit::Stackmap,
|
||||
) {
|
||||
unsafe {
|
||||
let bitslice = map.as_slice();
|
||||
low_level::stackmaps_add(
|
||||
self.0,
|
||||
std::mem::transmute(bitslice.as_ptr()),
|
||||
map.mapped_words() as usize,
|
||||
stack_slots.layout_info.unwrap().inbound_args_size as usize,
|
||||
offset as usize,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ use std::fmt;
|
|||
use std::mem;
|
||||
|
||||
use cranelift_codegen::binemit::{
|
||||
Addend, CodeInfo, CodeOffset, NullStackmapSink, NullTrapSink, Reloc, RelocSink, Stackmap,
|
||||
Addend, CodeInfo, CodeOffset, NullStackmapSink, NullTrapSink, Reloc, RelocSink,
|
||||
};
|
||||
use cranelift_codegen::entity::EntityRef;
|
||||
use cranelift_codegen::ir::{self, constant::ConstantOffset, stackslot::StackSize};
|
||||
|
@ -112,10 +112,10 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn compile(&mut self, stackmaps: bindings::Stackmaps) -> CodegenResult<()> {
|
||||
pub fn compile(&mut self) -> CodegenResult<()> {
|
||||
let info = self.context.compile(&*self.isa)?;
|
||||
debug!("Optimized wasm function IR: {}", self);
|
||||
self.binemit(info, stackmaps)
|
||||
self.binemit(info)
|
||||
}
|
||||
|
||||
/// Translate the WebAssembly code to Cranelift IR.
|
||||
|
@ -146,7 +146,7 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
}
|
||||
|
||||
/// Emit binary machine code to `emitter`.
|
||||
fn binemit(&mut self, info: CodeInfo, stackmaps: bindings::Stackmaps) -> CodegenResult<()> {
|
||||
fn binemit(&mut self, info: CodeInfo) -> CodegenResult<()> {
|
||||
let total_size = info.total_size as usize;
|
||||
let frame_pushed = self.frame_pushed();
|
||||
let contains_calls = self.contains_calls();
|
||||
|
@ -161,7 +161,7 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
// Generate metadata about function calls and traps now that the emitter knows where the
|
||||
// Cranelift code is going to end up.
|
||||
let mut metadata = mem::replace(&mut self.current_func.metadata, vec![]);
|
||||
self.emit_metadata(&mut metadata, stackmaps);
|
||||
self.emit_metadata(&mut metadata);
|
||||
mem::swap(&mut metadata, &mut self.current_func.metadata);
|
||||
|
||||
// TODO: If we can get a pointer into `size` pre-allocated bytes of memory, we wouldn't
|
||||
|
@ -185,6 +185,9 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
);
|
||||
let mut trap_sink = NullTrapSink {};
|
||||
|
||||
// TODO (bug 1574865) Support reference types and stackmaps in Baldrdash.
|
||||
let mut stackmap_sink = NullStackmapSink {};
|
||||
|
||||
unsafe {
|
||||
let code_buffer = &mut self.current_func.code_buffer;
|
||||
self.context.emit_to_memory(
|
||||
|
@ -192,7 +195,7 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
code_buffer.as_mut_ptr(),
|
||||
emit_env,
|
||||
&mut trap_sink,
|
||||
&mut NullStackmapSink {},
|
||||
&mut stackmap_sink,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -210,13 +213,7 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
fn frame_pushed(&self) -> StackSize {
|
||||
// Cranelift computes the total stack frame size including the pushed return address,
|
||||
// standard SM prologue pushes, and its own stack slots.
|
||||
let total = self
|
||||
.context
|
||||
.func
|
||||
.stack_slots
|
||||
.layout_info
|
||||
.expect("No frame")
|
||||
.frame_size;
|
||||
let total = self.context.func.stack_slots.frame_size.expect("No frame");
|
||||
let sm_pushed = StackSize::from(self.isa.flags().baldrdash_prologue_words())
|
||||
* mem::size_of::<usize>() as StackSize;
|
||||
total
|
||||
|
@ -251,20 +248,11 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
///
|
||||
/// We don't get enough callbacks through the `RelocSink` trait to generate all the metadata we
|
||||
/// need.
|
||||
fn emit_metadata(
|
||||
&self,
|
||||
metadata: &mut Vec<bindings::MetadataEntry>,
|
||||
mut stackmaps: bindings::Stackmaps,
|
||||
) {
|
||||
fn emit_metadata(&self, metadata: &mut Vec<bindings::MetadataEntry>) {
|
||||
let encinfo = self.isa.encoding_info();
|
||||
let func = &self.context.func;
|
||||
let stack_slots = &func.stack_slots;
|
||||
for ebb in func.layout.ebbs() {
|
||||
let mut pending_safepoint = None;
|
||||
for (offset, inst, inst_size) in func.inst_offsets(ebb, &encinfo) {
|
||||
if let Some(stackmap) = pending_safepoint.take() {
|
||||
stackmaps.add_stackmap(stack_slots, offset + inst_size, stackmap);
|
||||
}
|
||||
let opcode = func.dfg[inst].opcode();
|
||||
match opcode {
|
||||
ir::Opcode::Call => self.call_metadata(metadata, inst, offset + inst_size),
|
||||
|
@ -274,11 +262,6 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
ir::Opcode::Trap | ir::Opcode::Trapif | ir::Opcode::Trapff => {
|
||||
self.trap_metadata(metadata, inst, offset)
|
||||
}
|
||||
ir::Opcode::Safepoint => {
|
||||
let args = func.dfg.inst_args(inst);
|
||||
let stackmap = Stackmap::from_values(&args, func, &*self.isa);
|
||||
pending_safepoint = Some(stackmap);
|
||||
}
|
||||
ir::Opcode::Load
|
||||
| ir::Opcode::LoadComplex
|
||||
| ir::Opcode::Uload8
|
||||
|
@ -331,8 +314,6 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(pending_safepoint.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,10 +157,6 @@ fn make_shared_flags(
|
|||
sb.enable("use_pinned_reg_as_heap_base")?;
|
||||
}
|
||||
|
||||
if env.refTypesEnabled {
|
||||
sb.enable("enable_safepoints")?;
|
||||
}
|
||||
|
||||
Ok(settings::Flags::new(sb))
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ pub unsafe extern "C" fn cranelift_compile_function(
|
|||
return false;
|
||||
};
|
||||
|
||||
if let Err(e) = compiler.compile(data.stackmaps()) {
|
||||
if let Err(e) = compiler.compile() {
|
||||
error!("Cranelift compilation error: {}\n", e);
|
||||
info!("Compiled function: {}", compiler);
|
||||
return false;
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
//! The code here deals with adapting the `cranelift_wasm` module to the specifics of BaldrMonkey's
|
||||
//! internal data structures.
|
||||
|
||||
use crate::bindings::GlobalDesc;
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use cranelift_codegen::cursor::{Cursor, FuncCursor};
|
||||
|
@ -47,11 +45,6 @@ pub const POINTER_SIZE: i32 = 8;
|
|||
#[cfg(target_pointer_width = "32")]
|
||||
pub const POINTER_SIZE: i32 = 4;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub const REF_TYPE: ir::Type = ir::types::R64;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub const REF_TYPE: ir::Type = ir::types::R32;
|
||||
|
||||
/// Convert a TlsData offset into a `Offset32` for a global decl.
|
||||
fn offset32(offset: usize) -> ir::immediates::Offset32 {
|
||||
assert!(offset <= i32::max_value() as usize);
|
||||
|
@ -114,7 +107,6 @@ enum FailureMode {
|
|||
NotZero {
|
||||
internal_ret: bool,
|
||||
},
|
||||
InvalidRef,
|
||||
}
|
||||
|
||||
/// A description of builtin call to the `wasm::Instance`.
|
||||
|
@ -186,24 +178,6 @@ const FN_TABLE_SIZE: InstanceCall = InstanceCall {
|
|||
ret: Some(ir::types::I32),
|
||||
failure_mode: FailureMode::Infallible,
|
||||
};
|
||||
const FN_TABLE_GROW: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::TableGrow,
|
||||
arguments: &[REF_TYPE, ir::types::I32, ir::types::I32],
|
||||
ret: Some(ir::types::I32),
|
||||
failure_mode: FailureMode::Infallible,
|
||||
};
|
||||
const FN_TABLE_GET: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::TableGet,
|
||||
arguments: &[ir::types::I32, ir::types::I32],
|
||||
ret: Some(REF_TYPE),
|
||||
failure_mode: FailureMode::InvalidRef,
|
||||
};
|
||||
const FN_TABLE_SET: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::TableSet,
|
||||
arguments: &[ir::types::I32, REF_TYPE, ir::types::I32],
|
||||
ret: Some(ir::types::I32),
|
||||
failure_mode: FailureMode::NotZero { internal_ret: true },
|
||||
};
|
||||
const FN_TABLE_COPY: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::TableCopy,
|
||||
arguments: &[
|
||||
|
@ -216,12 +190,6 @@ const FN_TABLE_COPY: InstanceCall = InstanceCall {
|
|||
ret: Some(ir::types::I32),
|
||||
failure_mode: FailureMode::NotZero { internal_ret: true },
|
||||
};
|
||||
const FN_TABLE_FILL: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::TableFill,
|
||||
arguments: &[ir::types::I32, REF_TYPE, ir::types::I32, ir::types::I32],
|
||||
ret: Some(ir::types::I32),
|
||||
failure_mode: FailureMode::NotZero { internal_ret: true },
|
||||
};
|
||||
const FN_TABLE_INIT: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::TableInit,
|
||||
arguments: &[
|
||||
|
@ -240,24 +208,6 @@ const FN_ELEM_DROP: InstanceCall = InstanceCall {
|
|||
ret: Some(ir::types::I32),
|
||||
failure_mode: FailureMode::NotZero { internal_ret: true },
|
||||
};
|
||||
const FN_REF_FUNC: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::RefFunc,
|
||||
arguments: &[ir::types::I32],
|
||||
ret: Some(REF_TYPE),
|
||||
failure_mode: FailureMode::InvalidRef,
|
||||
};
|
||||
const FN_PRE_BARRIER: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::PreBarrier,
|
||||
arguments: &[POINTER_TYPE],
|
||||
ret: None,
|
||||
failure_mode: FailureMode::Infallible,
|
||||
};
|
||||
const FN_POST_BARRIER: InstanceCall = InstanceCall {
|
||||
address: SymbolicAddress::PostBarrier,
|
||||
arguments: &[POINTER_TYPE],
|
||||
ret: None,
|
||||
failure_mode: FailureMode::Infallible,
|
||||
};
|
||||
|
||||
// Custom trap codes specific to this embedding
|
||||
|
||||
|
@ -560,14 +510,14 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
|||
let mut sig = ir::Signature::new(call_conv);
|
||||
sig.params.push(ir::AbiParam::new(POINTER_TYPE));
|
||||
for argument in call.arguments {
|
||||
sig.params.push(ir::AbiParam::new(*argument));
|
||||
sig.params.push(ir::AbiParam::new(*argument).uext());
|
||||
}
|
||||
sig.params.push(ir::AbiParam::special(
|
||||
POINTER_TYPE,
|
||||
ir::ArgumentPurpose::VMContext,
|
||||
));
|
||||
if let Some(ret) = &call.ret {
|
||||
sig.returns.push(ir::AbiParam::new(*ret));
|
||||
sig.returns.push(ir::AbiParam::new(*ret).uext());
|
||||
}
|
||||
sig
|
||||
});
|
||||
|
@ -608,40 +558,6 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
|||
Some(ret)
|
||||
}
|
||||
}
|
||||
FailureMode::InvalidRef => {
|
||||
let invalid = pos.ins().is_invalid(ret);
|
||||
pos.ins()
|
||||
.trapnz(invalid, ir::TrapCode::User(TRAP_THROW_REPORTED));
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn global_address(
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
global: &GlobalDesc,
|
||||
) -> (ir::GlobalValue, Offset32) {
|
||||
assert!(!global.is_constant());
|
||||
|
||||
// This is a global variable. Here we don't care if it is mutable or not.
|
||||
let vmctx_gv = self.get_vmctx_gv(func);
|
||||
let offset = global.tls_offset();
|
||||
|
||||
// Some globals are represented as a pointer to the actual data, in which case we
|
||||
// must do an extra dereference to get to them. Also, in that case, the pointer
|
||||
// itself is immutable, so we mark it `readonly` here to assist Cranelift in commoning
|
||||
// up what would otherwise be multiple adjacent reads of the value.
|
||||
if global.is_indirect() {
|
||||
let gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx_gv,
|
||||
offset: offset32(offset),
|
||||
global_type: POINTER_TYPE,
|
||||
readonly: true,
|
||||
});
|
||||
(gv, 0.into())
|
||||
} else {
|
||||
(vmctx_gv, offset32(offset))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -672,21 +588,33 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
return Ok(GlobalVariable::Const(global.emit_constant(&mut pos)?));
|
||||
}
|
||||
|
||||
match global.value_type()? {
|
||||
ir::types::R32 | ir::types::R64 => {
|
||||
return Ok(GlobalVariable::Custom);
|
||||
}
|
||||
_ => {
|
||||
let (base_gv, offset) = self.global_address(func, &global);
|
||||
let mem_ty = global.value_type()?;
|
||||
// This is a global variable. Here we don't care if it is mutable or not.
|
||||
let vmctx_gv = self.get_vmctx_gv(func);
|
||||
let offset = global.tls_offset();
|
||||
|
||||
Ok(GlobalVariable::Memory {
|
||||
gv: base_gv,
|
||||
ty: mem_ty,
|
||||
offset,
|
||||
})
|
||||
}
|
||||
}
|
||||
// Some globals are represented as a pointer to the actual data, in which case we
|
||||
// must do an extra dereference to get to them. Also, in that case, the pointer
|
||||
// itself is immutable, so we mark it `readonly` here to assist Cranelift in commoning
|
||||
// up what would otherwise be multiple adjacent reads of the value.
|
||||
let (base_gv, offset) = if global.is_indirect() {
|
||||
let gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx_gv,
|
||||
offset: offset32(offset),
|
||||
global_type: POINTER_TYPE,
|
||||
readonly: true,
|
||||
});
|
||||
(gv, 0.into())
|
||||
} else {
|
||||
(vmctx_gv, offset32(offset))
|
||||
};
|
||||
|
||||
let mem_ty = global.value_type()?;
|
||||
|
||||
Ok(GlobalVariable::Memory {
|
||||
gv: base_gv,
|
||||
ty: mem_ty,
|
||||
offset,
|
||||
})
|
||||
}
|
||||
|
||||
fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> WasmResult<ir::Heap> {
|
||||
|
@ -757,6 +685,13 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
}
|
||||
|
||||
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table> {
|
||||
// Currently, Baldrdash doesn't support multiple tables.
|
||||
if index.index() != 0 {
|
||||
return Err(WasmError::Unsupported(
|
||||
"only one wasm table supported".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let table_desc = self.get_table(func, index);
|
||||
|
||||
// TODO we'd need a better way to synchronize the shape of GlobalDataDesc and these
|
||||
|
@ -812,6 +747,12 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
) -> WasmResult<ir::Inst> {
|
||||
let wsig = self.env.signature(sig_index);
|
||||
|
||||
// Currently, Baldrdash doesn't support multiple tables.
|
||||
if table_index.index() != 0 {
|
||||
return Err(WasmError::Unsupported(
|
||||
"only one wasm table supported".to_string(),
|
||||
));
|
||||
}
|
||||
let wtable = self.get_table(pos.func, table_index);
|
||||
|
||||
// Follows `MacroAssembler::wasmCallIndirect`:
|
||||
|
@ -1056,49 +997,13 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
table_index: TableIndex,
|
||||
_table: ir::Table,
|
||||
) -> WasmResult<ir::Value> {
|
||||
assert!(table_index.index() == 0);
|
||||
let table_index = pos.ins().iconst(ir::types::I32, table_index.index() as i64);
|
||||
Ok(self
|
||||
.instance_call(&mut pos, &FN_TABLE_SIZE, &[table_index])
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
fn translate_table_grow(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
table_index: u32,
|
||||
delta: ir::Value,
|
||||
init_value: ir::Value,
|
||||
) -> WasmResult<ir::Value> {
|
||||
let table_index = pos.ins().iconst(ir::types::I32, table_index as i64);
|
||||
Ok(self
|
||||
.instance_call(&mut pos, &FN_TABLE_GROW, &[init_value, delta, table_index])
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
fn translate_table_get(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
table_index: u32,
|
||||
index: ir::Value,
|
||||
) -> WasmResult<ir::Value> {
|
||||
let table_index = pos.ins().iconst(ir::types::I32, table_index as i64);
|
||||
Ok(self
|
||||
.instance_call(&mut pos, &FN_TABLE_GET, &[index, table_index])
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
fn translate_table_set(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
table_index: u32,
|
||||
value: ir::Value,
|
||||
index: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
let table_index = pos.ins().iconst(ir::types::I32, table_index as i64);
|
||||
self.instance_call(&mut pos, &FN_TABLE_SET, &[index, value, table_index]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_table_copy(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
|
@ -1110,30 +1015,14 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
src: ir::Value,
|
||||
len: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
let dst_index = pos
|
||||
assert!(dst_table_index.index() == 0);
|
||||
assert!(src_table_index.index() == 0);
|
||||
// Slightly lower the amount of SSA nodes as `dst == src`
|
||||
let index = pos
|
||||
.ins()
|
||||
.iconst(ir::types::I32, dst_table_index.index() as i64);
|
||||
let src_index = pos
|
||||
.ins()
|
||||
.iconst(ir::types::I32, src_table_index.index() as i64);
|
||||
self.instance_call(
|
||||
&mut pos,
|
||||
&FN_TABLE_COPY,
|
||||
&[dst, src, len, dst_index, src_index],
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_table_fill(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
table_index: u32,
|
||||
dst: ir::Value,
|
||||
val: ir::Value,
|
||||
len: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
let table_index = pos.ins().iconst(ir::types::I32, table_index as i64);
|
||||
self.instance_call(&mut pos, &FN_TABLE_FILL, &[dst, val, len, table_index]);
|
||||
let ret = self.instance_call(&mut pos, &FN_TABLE_COPY, &[dst, src, len, index, index]);
|
||||
debug_assert!(ret.is_none());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1147,6 +1036,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
src: ir::Value,
|
||||
len: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
assert!(table_index.index() == 0);
|
||||
let seg_index = pos.ins().iconst(ir::types::I32, seg_index as i64);
|
||||
let table_index = pos.ins().iconst(ir::types::I32, table_index.index() as i64);
|
||||
let ret = self.instance_call(
|
||||
|
@ -1165,61 +1055,6 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_ref_func(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
func_index: u32,
|
||||
) -> WasmResult<ir::Value> {
|
||||
let func_index = pos.ins().iconst(ir::types::I32, func_index as i64);
|
||||
Ok(self
|
||||
.instance_call(&mut pos, &FN_REF_FUNC, &[func_index])
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
fn translate_custom_global_get(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
global_index: GlobalIndex,
|
||||
) -> WasmResult<ir::Value> {
|
||||
let global = self.env.global(global_index);
|
||||
let ty = global.value_type()?;
|
||||
debug_assert!(ty == ir::types::R32 || ty == ir::types::R64);
|
||||
|
||||
let (base_gv, offset) = self.global_address(pos.func, &global);
|
||||
let addr = pos.ins().global_value(POINTER_TYPE, base_gv);
|
||||
let flags = ir::MemFlags::trusted();
|
||||
Ok(pos.ins().load(ty, flags, addr, offset))
|
||||
}
|
||||
|
||||
fn translate_custom_global_set(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
global_index: GlobalIndex,
|
||||
val: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
let global = self.env.global(global_index);
|
||||
let ty = global.value_type()?;
|
||||
debug_assert!(ty == ir::types::R32 || ty == ir::types::R64);
|
||||
|
||||
let (global_addr_gv, global_addr_offset) = self.global_address(pos.func, &global);
|
||||
let global_addr = pos.ins().global_value(POINTER_TYPE, global_addr_gv);
|
||||
let abs_global_addr = pos.ins().iadd_imm(
|
||||
global_addr,
|
||||
ir::immediates::Imm64::new(global_addr_offset.into()),
|
||||
);
|
||||
|
||||
let res = self.instance_call(&mut pos, &FN_PRE_BARRIER, &[abs_global_addr]);
|
||||
debug_assert!(res.is_none());
|
||||
|
||||
let flags = ir::MemFlags::trusted();
|
||||
pos.ins().store(flags, val, abs_global_addr, offset32(0));
|
||||
|
||||
let res = self.instance_call(&mut pos, &FN_POST_BARRIER, &[abs_global_addr]);
|
||||
debug_assert!(res.is_none());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_loop_header(&mut self, mut pos: FuncCursor) -> WasmResult<()> {
|
||||
let interrupt = self.load_interrupt_flag(&mut pos);
|
||||
pos.ins().trapnz(interrupt, ir::TrapCode::Interrupt);
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"938700819ee5e8988ff462d6a3fb4abe94fcd9f9111033dad9610f444c68f6eb","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"8fdd17d9d8c4bd0cf535599a40d7da0e5bf27fdcef817cd55ab7c580c8eb6a6c","src/cdsl/cpu_modes.rs":"996e45b374cfe85ac47c8c86c4459fe4c04b3158102b4c63b6ee434d5eed6a9e","src/cdsl/encodings.rs":"d884a564815a03c23369bcf31d13b122ae5ba84d0c80eda9312f0c0a829bf794","src/cdsl/formats.rs":"63e638305aa3ca6dd409ddf0e5e9605eeac1cc2631103e42fc6cbc87703d9b63","src/cdsl/instructions.rs":"bc8b65a2bc689ee2837ea0d9771a37791b747ec1b71cb46eae414830f55be581","src/cdsl/isa.rs":"ccabd6848b69eb069c10db61c7e7f86080777495714bb53d03e663c40541be94","src/cdsl/mod.rs":"0aa827923bf4c45e5ee2359573bd863e00f474acd532739f49dcd74a27553882","src/cdsl/operands.rs":"1c3411504de9c83112ff48e0ff1cfbb2e4ba5a9a15c1716f411ef31a4df59899","src/cdsl/recipes.rs":"80b7cd87332229b569e38086ceee8d557e679b9a32ad2e50bdb15c33337c3418","src/cdsl/regs.rs":"05f93ab8504ee82d7cc9811a5b40e5cd004c327577b4c0b3dd957fc422f3c013","src/cdsl/settings.rs":"e6fd9a31925743b93b11f09c9c8271bab6aa2430aa053a2601957b4487df7d77","src/cdsl/type_inference.rs":"1efca8a095ffc899b7527bda6b9d9378c73d7283f8dceaa4819e8af599f8be21","src/cdsl/types.rs":"ff764c9e9c29a05677bff6164e7bc25a0c32655052d77ae580536abba8b1713b","src/cdsl/typevar.rs":"c7e80a3c52755f2d91fb5c3d18413b7c97777bd54d1aece8a17d1bbd9944c46a","src/cdsl/xform.rs":"55da0c3f2403147b535ab6ae5d69c623fbe839edecf2a3af1de84420cd58402d","src/default_map.rs":"101bb0282a124f9c921f6bd095f529e8753621450d783c3273b0b0394c2c5c03","src/error.rs":"e9b11b2feb2d867b94c8810fdc5a6c4e0d9131604a0bfa5340ff2639a55100b4","src/gen_binemit.rs":"515e243420b30d1e01f8ea630282d9b6d78a715e1951f3f20392e19a48164442","src/gen_encodings.rs":"f00cded6b68a9b48c9e3cd39a8b6f0ba136f4062c8f8666109158a72c62c3ed1","src/gen_inst.rs":"fac99641622591c0529c0ef789dd83290a624fc674c91a959f426696f82044de","src/gen_legalizer.rs":"7a68c2b9fd77b6420ecb10539d9af0520374e4f2e30d5a345d98dafde157e6bd","src/gen_registers.rs":"3628949229c1cb5179ec5f655b9a1ddd0504ba74ffb9fb23741c85c9154b696f","src/gen_settings.rs":"f3cc3d31f6cc898f30606caf084f0de220db2d3b1b5e5e4145fa7c9a9a1597e2","src/gen_types.rs":"f6c090e1646a43bf2fe81ae0a7029cc6f7dc6d43285368f56d86c35a21c469a6","src/isa/arm32/mod.rs":"8e09ec1b3caf2d22dce8517b37c356047bfce9a6dea712467d867ed05c4bedaf","src/isa/arm64/mod.rs":"b01f030925d3f2af37d7df1b4a800eb7f0d24f74a46e9154fd8b6752643eb2d5","src/isa/mod.rs":"136141f99f217ba42b9e3f7f47238ab19cc974bb3bef2e2df7f7b5a683989d46","src/isa/riscv/encodings.rs":"8abb1968d917588bc5fc5f5be6dd66bdec23ac456ba65f8138237c8e891e843c","src/isa/riscv/mod.rs":"a7b461a30bbfbc1e3b33645422ff40d5b1761c30cb5d4a8aa12e9a3b7f7aee51","src/isa/riscv/recipes.rs":"c9424cffed54cc4d328879a4613b9f6a2c2b7cde7e6e17b4fccd5f661aaf92f2","src/isa/x86/encodings.rs":"f151bfb4da35c57bb614856ac84f5ac7fd0593a77360623338e6c1c7e5c5ba5f","src/isa/x86/instructions.rs":"e4a92f2b707e0a9af0317041eb9a8bc58a8bedcdbbe35f54dcfaf05699a50675","src/isa/x86/legalize.rs":"fca4a2729fbefded71effb7517c63a3da3648f8ab68968ef014cfc5d5f631cc7","src/isa/x86/mod.rs":"d6e363531df896ab542af664a5f2514f993cfb8ea485d39d8ea1b7a40747267e","src/isa/x86/opcodes.rs":"643bae64cd4050814adfb856046cf650979bec5d251a9d9a6e11bafb5a603c43","src/isa/x86/recipes.rs":"c80a15a90d521eb4752595601087d8797a43f17a5e1b7ed5379e85f7c926cd62","src/isa/x86/registers.rs":"e24c9487f4c257b1089dac6bca0106cc673db77292cd000ca8e0c7e0d0103f63","src/isa/x86/settings.rs":"9087cd57da2852b689bddc296639f9b9e1caa30e8185798891079da8d9340b53","src/lib.rs":"2491b0e74078914cb89d1778fa8174daf723fe76aaf7fed18741237d68f6df32","src/shared/entities.rs":"911b396da11188bd510de004956596f150e27540edd351c74028f99f5f3c79c5","src/shared/formats.rs":"d8cf211c392ec3c54d0101ef31b700c3222bc8e80b69a04b244953e449770336","src/shared/immediates.rs":"e4a57657f6af9853794804eb41c01204a2c13a632f44f55d90e156a4b98c5f65","src/shared/instructions.rs":"9e575d6378a3eb0e297dca41acf86ec6547a2a27600df2d8c500b7648f600e6d","src/shared/legalize.rs":"73e1b42743c324104f5a34120e1598146ce4ee7393137ecb5391b768c61f2605","src/shared/mod.rs":"bc497c14d083c29eefe4935cff9cd1bd138c071bc50f787248727a3858dc69f3","src/shared/settings.rs":"cda96c9599d49b82e5cd43c7d0fd53a197fa8dadcc56dc33566ac47fdd6da607","src/shared/types.rs":"4702df132f4b5d70cc9411ec5221ba0b1bd4479252274e0223ae57b6d0331247","src/srcgen.rs":"dcfc159c8599270f17e6a978c4be255abca51556b5ef0da497faec4a4a1e62ce","src/unique_table.rs":"31aa54330ca4786af772d32e8cb6158b6504b88fa93fe177bf0c6cbe545a8d35"},"package":null}
|
||||
{"files":{"Cargo.toml":"938700819ee5e8988ff462d6a3fb4abe94fcd9f9111033dad9610f444c68f6eb","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"8fdd17d9d8c4bd0cf535599a40d7da0e5bf27fdcef817cd55ab7c580c8eb6a6c","src/cdsl/cpu_modes.rs":"7ceb99df347faf5e69b34a7e0d691e9c148d15587df09e99d46a7d37238d8d06","src/cdsl/encodings.rs":"d884a564815a03c23369bcf31d13b122ae5ba84d0c80eda9312f0c0a829bf794","src/cdsl/formats.rs":"63e638305aa3ca6dd409ddf0e5e9605eeac1cc2631103e42fc6cbc87703d9b63","src/cdsl/instructions.rs":"bc8b65a2bc689ee2837ea0d9771a37791b747ec1b71cb46eae414830f55be581","src/cdsl/isa.rs":"ccabd6848b69eb069c10db61c7e7f86080777495714bb53d03e663c40541be94","src/cdsl/mod.rs":"0aa827923bf4c45e5ee2359573bd863e00f474acd532739f49dcd74a27553882","src/cdsl/operands.rs":"1c3411504de9c83112ff48e0ff1cfbb2e4ba5a9a15c1716f411ef31a4df59899","src/cdsl/recipes.rs":"80b7cd87332229b569e38086ceee8d557e679b9a32ad2e50bdb15c33337c3418","src/cdsl/regs.rs":"05f93ab8504ee82d7cc9811a5b40e5cd004c327577b4c0b3dd957fc422f3c013","src/cdsl/settings.rs":"e6fd9a31925743b93b11f09c9c8271bab6aa2430aa053a2601957b4487df7d77","src/cdsl/type_inference.rs":"1efca8a095ffc899b7527bda6b9d9378c73d7283f8dceaa4819e8af599f8be21","src/cdsl/types.rs":"ff764c9e9c29a05677bff6164e7bc25a0c32655052d77ae580536abba8b1713b","src/cdsl/typevar.rs":"c7e80a3c52755f2d91fb5c3d18413b7c97777bd54d1aece8a17d1bbd9944c46a","src/cdsl/xform.rs":"55da0c3f2403147b535ab6ae5d69c623fbe839edecf2a3af1de84420cd58402d","src/default_map.rs":"101bb0282a124f9c921f6bd095f529e8753621450d783c3273b0b0394c2c5c03","src/error.rs":"e9b11b2feb2d867b94c8810fdc5a6c4e0d9131604a0bfa5340ff2639a55100b4","src/gen_binemit.rs":"515e243420b30d1e01f8ea630282d9b6d78a715e1951f3f20392e19a48164442","src/gen_encodings.rs":"f00cded6b68a9b48c9e3cd39a8b6f0ba136f4062c8f8666109158a72c62c3ed1","src/gen_inst.rs":"fac99641622591c0529c0ef789dd83290a624fc674c91a959f426696f82044de","src/gen_legalizer.rs":"7a68c2b9fd77b6420ecb10539d9af0520374e4f2e30d5a345d98dafde157e6bd","src/gen_registers.rs":"3628949229c1cb5179ec5f655b9a1ddd0504ba74ffb9fb23741c85c9154b696f","src/gen_settings.rs":"f3cc3d31f6cc898f30606caf084f0de220db2d3b1b5e5e4145fa7c9a9a1597e2","src/gen_types.rs":"f6c090e1646a43bf2fe81ae0a7029cc6f7dc6d43285368f56d86c35a21c469a6","src/isa/arm32/mod.rs":"8e09ec1b3caf2d22dce8517b37c356047bfce9a6dea712467d867ed05c4bedaf","src/isa/arm64/mod.rs":"b01f030925d3f2af37d7df1b4a800eb7f0d24f74a46e9154fd8b6752643eb2d5","src/isa/mod.rs":"136141f99f217ba42b9e3f7f47238ab19cc974bb3bef2e2df7f7b5a683989d46","src/isa/riscv/encodings.rs":"8abb1968d917588bc5fc5f5be6dd66bdec23ac456ba65f8138237c8e891e843c","src/isa/riscv/mod.rs":"a7b461a30bbfbc1e3b33645422ff40d5b1761c30cb5d4a8aa12e9a3b7f7aee51","src/isa/riscv/recipes.rs":"c9424cffed54cc4d328879a4613b9f6a2c2b7cde7e6e17b4fccd5f661aaf92f2","src/isa/x86/encodings.rs":"79dcfb10819016da068b34705acd989b79f102577fec36db10e01fad4837b3b3","src/isa/x86/instructions.rs":"e4a92f2b707e0a9af0317041eb9a8bc58a8bedcdbbe35f54dcfaf05699a50675","src/isa/x86/legalize.rs":"fca4a2729fbefded71effb7517c63a3da3648f8ab68968ef014cfc5d5f631cc7","src/isa/x86/mod.rs":"49f0bc05898d1d8565e692ec2550855de15fd6cffa3b5b6e0f8d502cd813e306","src/isa/x86/opcodes.rs":"643bae64cd4050814adfb856046cf650979bec5d251a9d9a6e11bafb5a603c43","src/isa/x86/recipes.rs":"02cff98d27e852410bea7fb035510f78b15e77d133f745d4f052dbbc54a32e44","src/isa/x86/registers.rs":"e24c9487f4c257b1089dac6bca0106cc673db77292cd000ca8e0c7e0d0103f63","src/isa/x86/settings.rs":"9087cd57da2852b689bddc296639f9b9e1caa30e8185798891079da8d9340b53","src/lib.rs":"2491b0e74078914cb89d1778fa8174daf723fe76aaf7fed18741237d68f6df32","src/shared/entities.rs":"911b396da11188bd510de004956596f150e27540edd351c74028f99f5f3c79c5","src/shared/formats.rs":"d8cf211c392ec3c54d0101ef31b700c3222bc8e80b69a04b244953e449770336","src/shared/immediates.rs":"e4a57657f6af9853794804eb41c01204a2c13a632f44f55d90e156a4b98c5f65","src/shared/instructions.rs":"3eaa255634ae32a653fa16be82573d6a5912c766ce92589f13b81867b774a74e","src/shared/legalize.rs":"73e1b42743c324104f5a34120e1598146ce4ee7393137ecb5391b768c61f2605","src/shared/mod.rs":"bc497c14d083c29eefe4935cff9cd1bd138c071bc50f787248727a3858dc69f3","src/shared/settings.rs":"cda96c9599d49b82e5cd43c7d0fd53a197fa8dadcc56dc33566ac47fdd6da607","src/shared/types.rs":"4702df132f4b5d70cc9411ec5221ba0b1bd4479252274e0223ae57b6d0331247","src/srcgen.rs":"dcfc159c8599270f17e6a978c4be255abca51556b5ef0da497faec4a4a1e62ce","src/unique_table.rs":"31aa54330ca4786af772d32e8cb6158b6504b88fa93fe177bf0c6cbe545a8d35"},"package":null}
|
|
@ -37,12 +37,6 @@ impl CpuMode {
|
|||
assert!(self.default_legalize.is_none());
|
||||
self.default_legalize = Some(group.id);
|
||||
}
|
||||
pub fn legalize_value_type(&mut self, lane_type: impl Into<ValueType>, group: &TransformGroup) {
|
||||
assert!(self
|
||||
.typed_legalize
|
||||
.insert(lane_type.into(), group.id)
|
||||
.is_none());
|
||||
}
|
||||
pub fn legalize_type(&mut self, lane_type: impl Into<LaneType>, group: &TransformGroup) {
|
||||
assert!(self
|
||||
.typed_legalize
|
||||
|
|
|
@ -239,22 +239,6 @@ impl PerCpuModeEncodings {
|
|||
self.enc64(inst.bind(R64), template.rex().w());
|
||||
}
|
||||
|
||||
fn enc_r32_r64_ld_st(&mut self, inst: &Instruction, w_bit: bool, template: Template) {
|
||||
self.enc32(inst.clone().bind(R32).bind(Any), template.clone());
|
||||
|
||||
// REX-less encoding must come after REX encoding so we don't use it by
|
||||
// default. Otherwise reg-alloc would never use r8 and up.
|
||||
self.enc64(inst.clone().bind(R32).bind(Any), template.clone().rex());
|
||||
self.enc64(inst.clone().bind(R32).bind(Any), template.clone());
|
||||
|
||||
if w_bit {
|
||||
self.enc64(inst.clone().bind(R64).bind(Any), template.rex().w());
|
||||
} else {
|
||||
self.enc64(inst.clone().bind(R64).bind(Any), template.clone().rex());
|
||||
self.enc64(inst.clone().bind(R64).bind(Any), template);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add encodings for `inst` to X86_64 with and without a REX prefix.
|
||||
fn enc_x86_64(&mut self, inst: impl Into<InstSpec> + Clone, template: Template) {
|
||||
// See above comment about the ordering of rex vs non-rex encodings.
|
||||
|
@ -874,7 +858,6 @@ fn define_memory(
|
|||
|
||||
for recipe in &[rec_st, rec_stDisp8, rec_stDisp32] {
|
||||
e.enc_i32_i64_ld_st(store, true, recipe.opcodes(&MOV_STORE));
|
||||
e.enc_r32_r64_ld_st(store, true, recipe.opcodes(&MOV_STORE));
|
||||
e.enc_x86_64(istore32.bind(I64).bind(Any), recipe.opcodes(&MOV_STORE));
|
||||
e.enc_i32_i64_ld_st(istore16, false, recipe.opcodes(&MOV_STORE_16));
|
||||
}
|
||||
|
@ -906,7 +889,6 @@ fn define_memory(
|
|||
|
||||
for recipe in &[rec_ld, rec_ldDisp8, rec_ldDisp32] {
|
||||
e.enc_i32_i64_ld_st(load, true, recipe.opcodes(&MOV_LOAD));
|
||||
e.enc_r32_r64_ld_st(load, true, recipe.opcodes(&MOV_LOAD));
|
||||
e.enc_x86_64(uload32.bind(I64), recipe.opcodes(&MOV_LOAD));
|
||||
e.enc64(sload32.bind(I64), recipe.opcodes(&MOVSXD).rex().w());
|
||||
e.enc_i32_i64_ld_st(uload16, true, recipe.opcodes(&MOVZX_WORD));
|
||||
|
@ -2347,12 +2329,10 @@ fn define_reftypes(e: &mut PerCpuModeEncodings, shared_defs: &SharedDefinitions,
|
|||
let shared = &shared_defs.instructions;
|
||||
|
||||
let is_null = shared.by_name("is_null");
|
||||
let is_invalid = shared.by_name("is_invalid");
|
||||
let null = shared.by_name("null");
|
||||
let safepoint = shared.by_name("safepoint");
|
||||
|
||||
let rec_is_zero = r.template("is_zero");
|
||||
let rec_is_invalid = r.template("is_invalid");
|
||||
let rec_pu_id_ref = r.template("pu_id_ref");
|
||||
let rec_safepoint = r.recipe("safepoint");
|
||||
|
||||
|
@ -2365,9 +2345,6 @@ fn define_reftypes(e: &mut PerCpuModeEncodings, shared_defs: &SharedDefinitions,
|
|||
// is_null, implemented by testing whether the value is 0.
|
||||
e.enc_r32_r64_rex_only(is_null, rec_is_zero.opcodes(&TEST_REG));
|
||||
|
||||
// is_invalid, implemented by testing whether the value is -1.
|
||||
e.enc_r32_r64_rex_only(is_invalid, rec_is_invalid.opcodes(&CMP_IMM8).rrr(7));
|
||||
|
||||
// safepoint instruction calls sink, no actual encoding.
|
||||
e.enc32_rec(safepoint, rec_safepoint, 0);
|
||||
e.enc64_rec(safepoint, rec_safepoint, 0);
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use crate::cdsl::cpu_modes::CpuMode;
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::types::ReferenceType;
|
||||
|
||||
use crate::shared::types::Bool::B1;
|
||||
use crate::shared::types::Float::{F32, F64};
|
||||
use crate::shared::types::Int::{I16, I32, I64, I8};
|
||||
use crate::shared::types::Reference::{R32, R64};
|
||||
use crate::shared::Definitions as SharedDefinitions;
|
||||
|
||||
mod encodings;
|
||||
|
@ -43,7 +41,6 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
|||
x86_32.legalize_type(I8, widen);
|
||||
x86_32.legalize_type(I16, widen);
|
||||
x86_32.legalize_type(I32, x86_expand);
|
||||
x86_32.legalize_value_type(ReferenceType(R32), x86_expand);
|
||||
x86_32.legalize_type(F32, x86_expand);
|
||||
x86_32.legalize_type(F64, x86_expand);
|
||||
|
||||
|
@ -54,7 +51,6 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
|||
x86_64.legalize_type(I16, widen);
|
||||
x86_64.legalize_type(I32, x86_expand);
|
||||
x86_64.legalize_type(I64, x86_expand);
|
||||
x86_64.legalize_value_type(ReferenceType(R64), x86_expand);
|
||||
x86_64.legalize_type(F32, x86_expand);
|
||||
x86_64.legalize_type(F64, x86_expand);
|
||||
|
||||
|
|
|
@ -3222,26 +3222,6 @@ pub(crate) fn define<'shared>(
|
|||
),
|
||||
);
|
||||
|
||||
recipes.add_template_recipe(
|
||||
EncodingRecipeBuilder::new("is_invalid", &formats.unary, 2 + 3)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![abcd])
|
||||
.emit(
|
||||
r#"
|
||||
// Comparison instruction.
|
||||
{{PUT_OP}}(bits, rex1(in_reg0), sink);
|
||||
modrm_r_bits(in_reg0, bits, sink);
|
||||
sink.put1(0xff);
|
||||
// `setCC` instruction, no REX.
|
||||
use crate::ir::condcodes::IntCC::*;
|
||||
let setcc = 0x90 | icc2opc(Equal);
|
||||
sink.put1(0x0f);
|
||||
sink.put1(setcc as u8);
|
||||
modrm_rr(out_reg0, 0, sink);
|
||||
"#,
|
||||
),
|
||||
);
|
||||
|
||||
recipes.add_recipe(
|
||||
EncodingRecipeBuilder::new("safepoint", &formats.multiary, 0).emit(
|
||||
r#"
|
||||
|
|
|
@ -580,7 +580,6 @@ pub(crate) fn define(
|
|||
.ints(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.simd_lanes(Interval::All)
|
||||
.refs(Interval::All)
|
||||
.build(),
|
||||
);
|
||||
|
||||
|
@ -3191,24 +3190,6 @@ pub(crate) fn define(
|
|||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let a = &Operand::new("a", b1);
|
||||
let x = &Operand::new("x", Ref);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"is_invalid",
|
||||
r#"
|
||||
Reference verification.
|
||||
|
||||
The condition code determines if the reference type in question is
|
||||
invalid or not.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let Cond = &Operand::new("Cond", &imm.intcc);
|
||||
let f = &Operand::new("f", iflags);
|
||||
let a = &Operand::new("a", b1);
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -6,19 +6,10 @@ use alloc::vec::Vec;
|
|||
type Num = u32;
|
||||
const NUM_BITS: usize = core::mem::size_of::<Num>() * 8;
|
||||
|
||||
/// A stack map is a bitmap with one bit per machine word on the stack. Stack
|
||||
/// maps are created at `safepoint` instructions and record all live reference
|
||||
/// values that are on the stack. All slot kinds, except `OutgoingArg` are
|
||||
/// captured in a stack map. The `OutgoingArg`'s will be captured in the callee
|
||||
/// function as `IncomingArg`'s.
|
||||
///
|
||||
/// The first value in the bitmap is of the lowest addressed slot on the stack.
|
||||
/// As all stacks in Isa's supported by Cranelift grow down, this means that
|
||||
/// first value is of the top of the stack and values proceed down the stack.
|
||||
/// Wrapper class for longer bit vectors that cannot be represented by a single BitSet.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Stackmap {
|
||||
bitmap: Vec<BitSet<Num>>,
|
||||
mapped_words: u32,
|
||||
}
|
||||
|
||||
impl Stackmap {
|
||||
|
@ -36,37 +27,32 @@ impl Stackmap {
|
|||
for val in args {
|
||||
if let Some(value_loc) = loc.get(*val) {
|
||||
match *value_loc {
|
||||
ir::ValueLoc::Stack(stack_slot) => {
|
||||
live_ref_in_stack_slot.insert(stack_slot);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
ir::ValueLoc::Stack(stack_slot) => live_ref_in_stack_slot.insert(stack_slot),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// SpiderMonkey stackmap structure:
|
||||
// <trap reg dump> + <general spill> + <frame> + <inbound args>
|
||||
// Bit vector goes from lower addresses to higher addresses.
|
||||
|
||||
// TODO: Get trap register layout from Spidermonkey and prepend to bitvector below.
|
||||
let stack = &func.stack_slots;
|
||||
let info = func.stack_slots.layout_info.unwrap();
|
||||
|
||||
// Refer to the doc comment for `Stackmap` above to understand the
|
||||
// bitmap representation used here.
|
||||
let map_size = (info.frame_size + info.inbound_args_size) as usize;
|
||||
let word_size = isa.pointer_bytes() as usize;
|
||||
let num_words = map_size / word_size;
|
||||
|
||||
let frame_size = stack.frame_size.unwrap();
|
||||
let word_size = ir::stackslot::StackSize::from(isa.pointer_bytes());
|
||||
let num_words = (frame_size / word_size) as usize;
|
||||
let mut vec = alloc::vec::Vec::with_capacity(num_words);
|
||||
|
||||
vec.resize(num_words, false);
|
||||
|
||||
// Frame (includes spills and inbound args).
|
||||
for (ss, ssd) in stack.iter() {
|
||||
if !live_ref_in_stack_slot.contains(&ss)
|
||||
|| ssd.kind == ir::stackslot::StackSlotKind::OutgoingArg
|
||||
{
|
||||
continue;
|
||||
if live_ref_in_stack_slot.contains(&ss) {
|
||||
// Assumption: greater magnitude of offset imply higher address.
|
||||
let index = (((ssd.offset.unwrap().abs() as u32) - ssd.size) / word_size) as usize;
|
||||
vec[index] = true;
|
||||
}
|
||||
|
||||
debug_assert!(ssd.size as usize == word_size);
|
||||
let bytes_from_bottom = info.frame_size as i32 + ssd.offset.unwrap();
|
||||
let words_from_bottom = (bytes_from_bottom as usize) / word_size;
|
||||
vec[words_from_bottom] = true;
|
||||
}
|
||||
|
||||
Self::from_slice(&vec)
|
||||
|
@ -87,10 +73,7 @@ impl Stackmap {
|
|||
}
|
||||
bitmap.push(BitSet(curr_word));
|
||||
}
|
||||
Self {
|
||||
mapped_words: len as u32,
|
||||
bitmap,
|
||||
}
|
||||
Self { bitmap }
|
||||
}
|
||||
|
||||
/// Returns a specified bit.
|
||||
|
@ -100,16 +83,6 @@ impl Stackmap {
|
|||
let word_offset = (bit_index % NUM_BITS) as u8;
|
||||
self.bitmap[word_index].contains(word_offset)
|
||||
}
|
||||
|
||||
/// Returns the raw bitmap that represents this stack map.
|
||||
pub fn as_slice(&self) -> &[BitSet<u32>] {
|
||||
&self.bitmap
|
||||
}
|
||||
|
||||
/// Returns the number of words represented by this stack map.
|
||||
pub fn mapped_words(&self) -> u32 {
|
||||
self.mapped_words
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -53,7 +53,7 @@ pub use crate::ir::libcall::{get_libcall_funcref, get_probestack_funcref, LibCal
|
|||
pub use crate::ir::memflags::MemFlags;
|
||||
pub use crate::ir::progpoint::{ExpandedProgramPoint, ProgramOrder, ProgramPoint};
|
||||
pub use crate::ir::sourceloc::SourceLoc;
|
||||
pub use crate::ir::stackslot::{StackLayoutInfo, StackSlotData, StackSlotKind, StackSlots};
|
||||
pub use crate::ir::stackslot::{StackSlotData, StackSlotKind, StackSlots};
|
||||
pub use crate::ir::table::TableData;
|
||||
pub use crate::ir::trapcode::TrapCode;
|
||||
pub use crate::ir::types::Type;
|
||||
|
|
|
@ -162,23 +162,6 @@ impl fmt::Display for StackSlotData {
|
|||
}
|
||||
}
|
||||
|
||||
/// Stack frame layout information.
|
||||
///
|
||||
/// This is computed by the `layout_stack()` method.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct StackLayoutInfo {
|
||||
/// The total size of the stack frame.
|
||||
///
|
||||
/// This is the distance from the stack pointer in the current function to the stack pointer in
|
||||
/// the calling function, so it includes a pushed return address as well as space for outgoing
|
||||
/// call arguments.
|
||||
pub frame_size: StackSize,
|
||||
|
||||
/// The total size of the stack frame for inbound arguments pushed by the caller.
|
||||
pub inbound_args_size: StackSize,
|
||||
}
|
||||
|
||||
/// Stack frame manager.
|
||||
///
|
||||
/// Keep track of all the stack slots used by a function.
|
||||
|
@ -194,8 +177,14 @@ pub struct StackSlots {
|
|||
/// All the emergency slots.
|
||||
emergency: Vec<StackSlot>,
|
||||
|
||||
/// Layout information computed from `layout_stack`.
|
||||
pub layout_info: Option<StackLayoutInfo>,
|
||||
/// The total size of the stack frame.
|
||||
///
|
||||
/// This is the distance from the stack pointer in the current function to the stack pointer in
|
||||
/// the calling function, so it includes a pushed return address as well as space for outgoing
|
||||
/// call arguments.
|
||||
///
|
||||
/// This is computed by the `layout()` method.
|
||||
pub frame_size: Option<StackSize>,
|
||||
}
|
||||
|
||||
/// Stack slot manager functions that behave mostly like an entity map.
|
||||
|
@ -206,7 +195,7 @@ impl StackSlots {
|
|||
slots: PrimaryMap::new(),
|
||||
outgoing: Vec::new(),
|
||||
emergency: Vec::new(),
|
||||
layout_info: None,
|
||||
frame_size: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,7 +204,7 @@ impl StackSlots {
|
|||
self.slots.clear();
|
||||
self.outgoing.clear();
|
||||
self.emergency.clear();
|
||||
self.layout_info = None;
|
||||
self.frame_size = None;
|
||||
}
|
||||
|
||||
/// Allocate a new stack slot.
|
||||
|
|
|
@ -36,9 +36,8 @@ impl StackRef {
|
|||
/// Get a reference to `ss` using the stack pointer as a base.
|
||||
pub fn sp(ss: StackSlot, frame: &StackSlots) -> Self {
|
||||
let size = frame
|
||||
.layout_info
|
||||
.expect("Stack layout must be computed before referencing stack slots")
|
||||
.frame_size;
|
||||
.frame_size
|
||||
.expect("Stack layout must be computed before referencing stack slots");
|
||||
let slot = &frame[ss];
|
||||
let offset = if slot.kind == StackSlotKind::OutgoingArg {
|
||||
// Outgoing argument slots have offsets relative to our stack pointer.
|
||||
|
|
|
@ -333,7 +333,7 @@ pub fn legalize_signature(
|
|||
|
||||
/// Get register class for a type appearing in a legalized signature.
|
||||
pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
|
||||
if ty.is_int() || ty.is_bool() || ty.is_ref() {
|
||||
if ty.is_int() || ty.is_bool() {
|
||||
GPR
|
||||
} else {
|
||||
FPR
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Computing stack layout.
|
||||
|
||||
use crate::ir::stackslot::{StackOffset, StackSize, StackSlotKind};
|
||||
use crate::ir::{StackLayoutInfo, StackSlots};
|
||||
use crate::ir::StackSlots;
|
||||
use crate::result::{CodegenError, CodegenResult};
|
||||
use core::cmp::{max, min};
|
||||
|
||||
|
@ -44,7 +44,6 @@ pub fn layout_stack(
|
|||
// require the stack to be aligned.
|
||||
|
||||
let mut incoming_min = 0;
|
||||
let mut incoming_max = 0;
|
||||
let mut outgoing_max = 0;
|
||||
let mut min_align = alignment;
|
||||
let mut must_align = is_leaf;
|
||||
|
@ -57,7 +56,6 @@ pub fn layout_stack(
|
|||
match slot.kind {
|
||||
StackSlotKind::IncomingArg => {
|
||||
incoming_min = min(incoming_min, slot.offset.unwrap());
|
||||
incoming_max = max(incoming_max, slot.offset.unwrap() + slot.size as i32);
|
||||
}
|
||||
StackSlotKind::OutgoingArg => {
|
||||
let offset = slot
|
||||
|
@ -121,14 +119,8 @@ pub fn layout_stack(
|
|||
offset &= -(alignment as StackOffset);
|
||||
}
|
||||
|
||||
// Set the computed layout information for the frame
|
||||
let frame_size = (offset as StackSize).wrapping_neg();
|
||||
let inbound_args_size = incoming_max as u32;
|
||||
frame.layout_info = Some(StackLayoutInfo {
|
||||
frame_size,
|
||||
inbound_args_size,
|
||||
});
|
||||
|
||||
frame.frame_size = Some(frame_size);
|
||||
Ok(frame_size)
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"35b63ffdf4ba90faeebe0927f66ff047de2ead02d64f1a9212fe90c6b97a5c39","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"f46f9c5df1b10bad0e87d9c2ad9f5e65bbb6749ac8843cd80ec357daa3b22c3e","src/code_translator.rs":"04c459c97e32d5699bc5aa0c7c414b5d4bf40bcc3ed1bdfcca3a224e584406a4","src/environ/dummy.rs":"32e4dde7732aa386d250ce509e6c35d68e67e6943c07565a137147c9718668da","src/environ/mod.rs":"b6f33f619090ff497b4e22150d77a290f259716374ac2e377b73c47cd1dafe85","src/environ/spec.rs":"ed55da70abd30fd1c39cd303976013e9ef20c5af9736305a22929165c0d32d65","src/func_translator.rs":"8a4b5c8386dc66e47327d3d598ba2f9ca585dc0ef08d6e572b93edefb8b0411c","src/lib.rs":"0dbbb3d5088799c3aaa94b083ca0c2f09906bd8fb36e9c0dd200b8122c50a8b6","src/module_translator.rs":"5e1bf9471d6f4f317bb2fb9b8697b5b08f7950520017c2869e69133e7f17a2b7","src/sections_translator.rs":"158631c43ee07a43790545201e2e597e4d71793e6f4a644851f9e5db4c0a2ef2","src/state/func_state.rs":"cc935f96a703769d075498ec2aa8fe191b8b9e3e5729e25eb409ffb82696d82e","src/state/mod.rs":"20014cb93615467b4d20321b52f67f66040417efcaa739a4804093bb559eed19","src/state/module_state.rs":"2f299b043deb806b48583fe54bbb46708f7d8a1454b7be0eb285568064e5a7f9","src/translation_utils.rs":"c52eeb9b9da46253c3bbe4e58a38e4a03a1a5a913141aa5616722f49e6ba8537","tests/wasm_testsuite.rs":"730304f139371e5ef3fd913ec271fc4db181869b447c6ed26c54313b5c31495c"},"package":null}
|
||||
{"files":{"Cargo.toml":"35b63ffdf4ba90faeebe0927f66ff047de2ead02d64f1a9212fe90c6b97a5c39","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"f46f9c5df1b10bad0e87d9c2ad9f5e65bbb6749ac8843cd80ec357daa3b22c3e","src/code_translator.rs":"fb15f6c92be1d9580aa1d0a0f020fce260f9e3dd5827d363dba78fb6464fdbd1","src/environ/dummy.rs":"b918e7c7afd3be41d7b2b8587a1cb0119640508f475fc086f949a96d01b783d6","src/environ/mod.rs":"b6f33f619090ff497b4e22150d77a290f259716374ac2e377b73c47cd1dafe85","src/environ/spec.rs":"477d925eece0465104941c253f263c1568c917f6979965eeb30030436cc865c3","src/func_translator.rs":"c051fd561b69a305097d8c35c60bae71a7af86e1f0f48399899ac502766f7772","src/lib.rs":"0dbbb3d5088799c3aaa94b083ca0c2f09906bd8fb36e9c0dd200b8122c50a8b6","src/module_translator.rs":"5e1bf9471d6f4f317bb2fb9b8697b5b08f7950520017c2869e69133e7f17a2b7","src/sections_translator.rs":"158631c43ee07a43790545201e2e597e4d71793e6f4a644851f9e5db4c0a2ef2","src/state/func_state.rs":"cc935f96a703769d075498ec2aa8fe191b8b9e3e5729e25eb409ffb82696d82e","src/state/mod.rs":"20014cb93615467b4d20321b52f67f66040417efcaa739a4804093bb559eed19","src/state/module_state.rs":"2f299b043deb806b48583fe54bbb46708f7d8a1454b7be0eb285568064e5a7f9","src/translation_utils.rs":"e3b56d34ab989e9e81a8b30b52fab11c886bfcb783b9c091d1a72ad35fdbe0d0","tests/wasm_testsuite.rs":"730304f139371e5ef3fd913ec271fc4db181869b447c6ed26c54313b5c31495c"},"package":null}
|
|
@ -28,7 +28,7 @@ use crate::state::{ControlStackFrame, ElseData, FuncTranslationState, ModuleTran
|
|||
use crate::translation_utils::{
|
||||
blocktype_params_results, ebb_with_params, f32_translation, f64_translation,
|
||||
};
|
||||
use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex};
|
||||
use crate::translation_utils::{FuncIndex, MemoryIndex, SignatureIndex, TableIndex};
|
||||
use crate::wasm_unsupported;
|
||||
use core::{i32, u32};
|
||||
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
|
||||
|
@ -95,10 +95,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||
let flags = ir::MemFlags::trusted();
|
||||
builder.ins().load(ty, flags, addr, offset)
|
||||
}
|
||||
GlobalVariable::Custom => environ.translate_custom_global_get(
|
||||
builder.cursor(),
|
||||
GlobalIndex::from_u32(*global_index),
|
||||
)?,
|
||||
};
|
||||
state.push1(val);
|
||||
}
|
||||
|
@ -112,14 +108,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||
debug_assert_eq!(ty, builder.func.dfg.value_type(val));
|
||||
builder.ins().store(flags, val, addr, offset);
|
||||
}
|
||||
GlobalVariable::Custom => {
|
||||
let val = state.pop1();
|
||||
environ.translate_custom_global_set(
|
||||
builder.cursor(),
|
||||
GlobalIndex::from_u32(*global_index),
|
||||
val,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
/********************************* Stack misc ***************************************
|
||||
|
@ -132,13 +120,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||
let (arg1, arg2, cond) = state.pop3();
|
||||
state.push1(builder.ins().select(cond, arg1, arg2));
|
||||
}
|
||||
Operator::TypedSelect { ty: _ } => {
|
||||
// We ignore the explicit type parameter as it is only needed for
|
||||
// validation, which we require to have been performed before
|
||||
// translation.
|
||||
let (arg1, arg2, cond) = state.pop3();
|
||||
state.push1(builder.ins().select(cond, arg1, arg2));
|
||||
}
|
||||
Operator::Nop => {
|
||||
// We do nothing
|
||||
}
|
||||
|
@ -975,15 +956,17 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||
Operator::F32Le | Operator::F64Le => {
|
||||
translate_fcmp(FloatCC::LessThanOrEqual, builder, state)
|
||||
}
|
||||
Operator::TypedSelect { .. } => {
|
||||
return Err(wasm_unsupported!("proposed typed select operator {:?}", op))
|
||||
}
|
||||
Operator::RefNull => state.push1(builder.ins().null(environ.reference_type())),
|
||||
Operator::RefIsNull => {
|
||||
let arg = state.pop1();
|
||||
let val = builder.ins().is_null(arg);
|
||||
let val_int = builder.ins().bint(I32, val);
|
||||
state.push1(val_int);
|
||||
state.push1(val);
|
||||
}
|
||||
Operator::RefFunc { function_index } => {
|
||||
state.push1(environ.translate_ref_func(builder.cursor(), *function_index)?);
|
||||
Operator::RefFunc { .. } => {
|
||||
return Err(wasm_unsupported!("proposed ref operator {:?}", op))
|
||||
}
|
||||
Operator::AtomicNotify { .. }
|
||||
| Operator::I32AtomicWait { .. }
|
||||
|
@ -1106,72 +1089,56 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||
table,
|
||||
)?);
|
||||
}
|
||||
Operator::TableGrow { table } => {
|
||||
let delta = state.pop1();
|
||||
let init_value = state.pop1();
|
||||
state.push1(environ.translate_table_grow(
|
||||
builder.cursor(),
|
||||
*table,
|
||||
delta,
|
||||
init_value,
|
||||
)?);
|
||||
}
|
||||
Operator::TableGet { table } => {
|
||||
let index = state.pop1();
|
||||
state.push1(environ.translate_table_get(builder.cursor(), *table, index)?);
|
||||
}
|
||||
Operator::TableSet { table } => {
|
||||
let value = state.pop1();
|
||||
let index = state.pop1();
|
||||
environ.translate_table_set(builder.cursor(), *table, value, index)?;
|
||||
}
|
||||
Operator::TableCopy {
|
||||
dst_table: dst_table_index,
|
||||
src_table: src_table_index,
|
||||
} => {
|
||||
let dst_table = state.get_table(builder.func, *dst_table_index, environ)?;
|
||||
let src_table = state.get_table(builder.func, *src_table_index, environ)?;
|
||||
Operator::TableCopy { .. } => {
|
||||
// The WebAssembly MVP only supports one table and wasmparser will
|
||||
// ensure that the table index specified is zero.
|
||||
let dst_table_index = 0;
|
||||
let dst_table = state.get_table(builder.func, dst_table_index, environ)?;
|
||||
let src_table_index = 0;
|
||||
let src_table = state.get_table(builder.func, src_table_index, environ)?;
|
||||
let len = state.pop1();
|
||||
let src = state.pop1();
|
||||
let dest = state.pop1();
|
||||
environ.translate_table_copy(
|
||||
builder.cursor(),
|
||||
TableIndex::from_u32(*dst_table_index),
|
||||
TableIndex::from_u32(dst_table_index),
|
||||
dst_table,
|
||||
TableIndex::from_u32(*src_table_index),
|
||||
TableIndex::from_u32(src_table_index),
|
||||
src_table,
|
||||
dest,
|
||||
src,
|
||||
len,
|
||||
)?;
|
||||
}
|
||||
Operator::TableFill { table } => {
|
||||
let len = state.pop1();
|
||||
let val = state.pop1();
|
||||
let dest = state.pop1();
|
||||
environ.translate_table_fill(builder.cursor(), *table, dest, val, len)?;
|
||||
}
|
||||
Operator::TableInit {
|
||||
segment,
|
||||
table: table_index,
|
||||
} => {
|
||||
let table = state.get_table(builder.func, *table_index, environ)?;
|
||||
Operator::TableInit { segment, table: _ } => {
|
||||
// The WebAssembly MVP only supports one table and we assume it here.
|
||||
let table_index = 0;
|
||||
let table = state.get_table(builder.func, table_index, environ)?;
|
||||
let len = state.pop1();
|
||||
let src = state.pop1();
|
||||
let dest = state.pop1();
|
||||
environ.translate_table_init(
|
||||
builder.cursor(),
|
||||
*segment,
|
||||
TableIndex::from_u32(*table_index),
|
||||
TableIndex::from_u32(table_index),
|
||||
table,
|
||||
dest,
|
||||
src,
|
||||
len,
|
||||
)?;
|
||||
}
|
||||
Operator::TableFill { .. } => {
|
||||
return Err(wasm_unsupported!("proposed table operator {:?}", op));
|
||||
}
|
||||
Operator::ElemDrop { segment } => {
|
||||
environ.translate_elem_drop(builder.cursor(), *segment)?;
|
||||
}
|
||||
Operator::TableGet { .. } | Operator::TableSet { .. } | Operator::TableGrow { .. } => {
|
||||
return Err(wasm_unsupported!(
|
||||
"proposed reference types operator {:?}",
|
||||
op
|
||||
));
|
||||
}
|
||||
Operator::V128Const { value } => {
|
||||
let data = value.bytes().to_vec().into();
|
||||
let handle = builder.func.dfg.constants.insert(data);
|
||||
|
|
|
@ -426,35 +426,6 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||
Ok(pos.ins().iconst(I32, -1))
|
||||
}
|
||||
|
||||
fn translate_table_grow(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
_table_index: u32,
|
||||
_delta: ir::Value,
|
||||
_init_value: ir::Value,
|
||||
) -> WasmResult<ir::Value> {
|
||||
Ok(pos.ins().iconst(I32, -1))
|
||||
}
|
||||
|
||||
fn translate_table_get(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
_table_index: u32,
|
||||
_index: ir::Value,
|
||||
) -> WasmResult<ir::Value> {
|
||||
Ok(pos.ins().null(self.reference_type()))
|
||||
}
|
||||
|
||||
fn translate_table_set(
|
||||
&mut self,
|
||||
_pos: FuncCursor,
|
||||
_table_index: u32,
|
||||
_value: ir::Value,
|
||||
_index: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_table_copy(
|
||||
&mut self,
|
||||
_pos: FuncCursor,
|
||||
|
@ -469,17 +440,6 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_table_fill(
|
||||
&mut self,
|
||||
_pos: FuncCursor,
|
||||
_table_index: u32,
|
||||
_dst: ir::Value,
|
||||
_val: ir::Value,
|
||||
_len: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_table_init(
|
||||
&mut self,
|
||||
_pos: FuncCursor,
|
||||
|
@ -496,31 +456,6 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||
fn translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_ref_func(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
_func_index: u32,
|
||||
) -> WasmResult<ir::Value> {
|
||||
Ok(pos.ins().null(self.reference_type()))
|
||||
}
|
||||
|
||||
fn translate_custom_global_get(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
_global_index: GlobalIndex,
|
||||
) -> WasmResult<ir::Value> {
|
||||
Ok(pos.ins().iconst(I32, -1))
|
||||
}
|
||||
|
||||
fn translate_custom_global_set(
|
||||
&mut self,
|
||||
_pos: FuncCursor,
|
||||
_global_index: GlobalIndex,
|
||||
_val: ir::Value,
|
||||
) -> WasmResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetEnvironment for DummyEnvironment {
|
||||
|
|
|
@ -36,9 +36,6 @@ pub enum GlobalVariable {
|
|||
/// The global variable's type.
|
||||
ty: ir::Type,
|
||||
},
|
||||
|
||||
/// This is a global variable that needs to be handled by the environment.
|
||||
Custom,
|
||||
}
|
||||
|
||||
/// A WebAssembly translation error.
|
||||
|
@ -340,32 +337,6 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||
table: ir::Table,
|
||||
) -> WasmResult<ir::Value>;
|
||||
|
||||
/// Translate a `table.grow` WebAssembly instruction.
|
||||
fn translate_table_grow(
|
||||
&mut self,
|
||||
pos: FuncCursor,
|
||||
table_index: u32,
|
||||
delta: ir::Value,
|
||||
init_value: ir::Value,
|
||||
) -> WasmResult<ir::Value>;
|
||||
|
||||
/// Translate a `table.get` WebAssembly instruction.
|
||||
fn translate_table_get(
|
||||
&mut self,
|
||||
pos: FuncCursor,
|
||||
table_index: u32,
|
||||
index: ir::Value,
|
||||
) -> WasmResult<ir::Value>;
|
||||
|
||||
/// Translate a `table.set` WebAssembly instruction.
|
||||
fn translate_table_set(
|
||||
&mut self,
|
||||
pos: FuncCursor,
|
||||
table_index: u32,
|
||||
value: ir::Value,
|
||||
index: ir::Value,
|
||||
) -> WasmResult<()>;
|
||||
|
||||
/// Translate a `table.copy` WebAssembly instruction.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn translate_table_copy(
|
||||
|
@ -380,16 +351,6 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||
len: ir::Value,
|
||||
) -> WasmResult<()>;
|
||||
|
||||
/// Translate a `table.fill` WebAssembly instruction.
|
||||
fn translate_table_fill(
|
||||
&mut self,
|
||||
pos: FuncCursor,
|
||||
table_index: u32,
|
||||
dst: ir::Value,
|
||||
val: ir::Value,
|
||||
len: ir::Value,
|
||||
) -> WasmResult<()>;
|
||||
|
||||
/// Translate a `table.init` WebAssembly instruction.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn translate_table_init(
|
||||
|
@ -406,26 +367,6 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||
/// Translate a `elem.drop` WebAssembly instruction.
|
||||
fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
|
||||
|
||||
/// Translate a `ref.func` WebAssembly instruction.
|
||||
fn translate_ref_func(&mut self, pos: FuncCursor, func_index: u32) -> WasmResult<ir::Value>;
|
||||
|
||||
/// Translate a `global.get` WebAssembly instruction at `pos` for a global
|
||||
/// that is custom.
|
||||
fn translate_custom_global_get(
|
||||
&mut self,
|
||||
pos: FuncCursor,
|
||||
global_index: GlobalIndex,
|
||||
) -> WasmResult<ir::Value>;
|
||||
|
||||
/// Translate a `global.set` WebAssembly instruction at `pos` for a global
|
||||
/// that is custom.
|
||||
fn translate_custom_global_set(
|
||||
&mut self,
|
||||
pos: FuncCursor,
|
||||
global_index: GlobalIndex,
|
||||
val: ir::Value,
|
||||
) -> WasmResult<()>;
|
||||
|
||||
/// Emit code at the beginning of every wasm loop.
|
||||
///
|
||||
/// This can be used to insert explicit interrupt or safepoint checking at
|
||||
|
|
|
@ -196,7 +196,6 @@ fn declare_locals<FE: FuncEnvironment + ?Sized>(
|
|||
let constant_handle = builder.func.dfg.constants.insert([0; 16].to_vec().into());
|
||||
builder.ins().vconst(ir::types::I8X16, constant_handle)
|
||||
}
|
||||
NullRef => builder.ins().null(environ.reference_type()),
|
||||
AnyRef => builder.ins().null(environ.reference_type()),
|
||||
AnyFunc => builder.ins().null(environ.reference_type()),
|
||||
ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)),
|
||||
|
|
|
@ -131,9 +131,7 @@ pub fn type_to_type<PE: TargetEnvironment + ?Sized>(
|
|||
wasmparser::Type::F32 => Ok(ir::types::F32),
|
||||
wasmparser::Type::F64 => Ok(ir::types::F64),
|
||||
wasmparser::Type::V128 => Ok(ir::types::I8X16),
|
||||
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc | wasmparser::Type::NullRef => {
|
||||
Ok(environ.reference_type())
|
||||
}
|
||||
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc => Ok(environ.reference_type()),
|
||||
ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)),
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +171,6 @@ pub fn blocktype_params_results(
|
|||
wasmparser::Type::V128 => (&[], &[wasmparser::Type::V128]),
|
||||
wasmparser::Type::AnyRef => (&[], &[wasmparser::Type::AnyRef]),
|
||||
wasmparser::Type::AnyFunc => (&[], &[wasmparser::Type::AnyFunc]),
|
||||
wasmparser::Type::NullRef => (&[], &[wasmparser::Type::NullRef]),
|
||||
wasmparser::Type::EmptyBlockType => (&[], &[]),
|
||||
ty => return Err(wasm_unsupported!("blocktype_params_results: type {:?}", ty)),
|
||||
},
|
||||
|
@ -206,7 +203,7 @@ pub fn ebb_with_params<PE: TargetEnvironment + ?Sized>(
|
|||
wasmparser::Type::F64 => {
|
||||
builder.append_ebb_param(ebb, ir::types::F64);
|
||||
}
|
||||
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc | wasmparser::Type::NullRef => {
|
||||
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc => {
|
||||
builder.append_ebb_param(ebb, environ.reference_type());
|
||||
}
|
||||
wasmparser::Type::V128 => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче