mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-04-03 04:52:54 +00:00
Backed out 4 changesets (bug 1626967) for breaking Raptor tests godot-c and wm-c. a=backout
Backed out changeset 985eea91c36c (bug 1626967) Backed out changeset 837dab8ce31c (bug 1626967) Backed out changeset f48ad40e60af (bug 1626967) Backed out changeset 29aaf3ff21ea (bug 1626967) --HG-- extra : amend_source : 8f86b92aa59cde8a0fdc9fec7b9994c79a6f19df
This commit is contained in:
parent
88bbcf97df
commit
b5fa1b7063
@ -55,7 +55,7 @@ rev = "72f813a03cefbdf8e2c58c7410f3556c79429a06"
|
||||
[source."https://github.com/bytecodealliance/wasmtime"]
|
||||
git = "https://github.com/bytecodealliance/wasmtime"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
rev = "5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
|
||||
[source."https://github.com/badboy/failure"]
|
||||
git = "https://github.com/badboy/failure"
|
||||
|
36
Cargo.lock
generated
36
Cargo.lock
generated
@ -715,22 +715,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.62.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=6a68130d5b0296379fae0b8de5fbb8a1499b67a5#6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
version = "0.60.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c#5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.62.0",
|
||||
"cranelift-entity 0.60.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.62.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=6a68130d5b0296379fae0b8de5fbb8a1499b67a5#6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
version = "0.60.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c#5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cranelift-bforest",
|
||||
"cranelift-codegen-meta",
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-entity 0.62.0",
|
||||
"cranelift-entity 0.60.0",
|
||||
"log",
|
||||
"smallvec 1.2.0",
|
||||
"target-lexicon 0.10.0",
|
||||
@ -739,17 +739,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.62.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=6a68130d5b0296379fae0b8de5fbb8a1499b67a5#6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
version = "0.60.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c#5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-entity 0.62.0",
|
||||
"cranelift-entity 0.60.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.62.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=6a68130d5b0296379fae0b8de5fbb8a1499b67a5#6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
version = "0.60.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c#5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
@ -758,13 +758,13 @@ source = "git+https://github.com/PLSysSec/lucet_sandbox_compiler?rev=5e870faf6f9
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.62.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=6a68130d5b0296379fae0b8de5fbb8a1499b67a5#6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
version = "0.60.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c#5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.62.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=6a68130d5b0296379fae0b8de5fbb8a1499b67a5#6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
version = "0.60.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c#5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@ -774,11 +774,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-wasm"
|
||||
version = "0.62.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=6a68130d5b0296379fae0b8de5fbb8a1499b67a5#6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
version = "0.60.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c#5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"cranelift-entity 0.62.0",
|
||||
"cranelift-entity 0.60.0",
|
||||
"cranelift-frontend",
|
||||
"log",
|
||||
"thiserror",
|
||||
|
@ -76,8 +76,8 @@ failure_derive = { git = "https://github.com/badboy/failure", rev = "64af847bc5f
|
||||
|
||||
[patch.crates-io.cranelift-codegen]
|
||||
git = "https://github.com/bytecodealliance/wasmtime"
|
||||
rev = "6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
rev = "5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
|
||||
[patch.crates-io.cranelift-wasm]
|
||||
git = "https://github.com/bytecodealliance/wasmtime"
|
||||
rev = "6a68130d5b0296379fae0b8de5fbb8a1499b67a5"
|
||||
rev = "5cfcbeb59d477e028c6fb312f1cf63aa711fcc3c"
|
||||
|
@ -119,12 +119,11 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
|
||||
// Omit the check when framePushed is small and we know there's no
|
||||
// recursion.
|
||||
if (func.frame_pushed < MAX_UNCHECKED_LEAF_FRAME_SIZE &&
|
||||
!func.contains_calls) {
|
||||
masm.reserveStack(func.frame_pushed);
|
||||
if (func.framePushed < MAX_UNCHECKED_LEAF_FRAME_SIZE && !func.containsCalls) {
|
||||
masm.reserveStack(func.framePushed);
|
||||
} else {
|
||||
std::pair<CodeOffset, uint32_t> pair = masm.wasmReserveStackChecked(
|
||||
func.frame_pushed, BytecodeOffset(lineOrBytecode));
|
||||
func.framePushed, BytecodeOffset(lineOrBytecode));
|
||||
CodeOffset trapInsnOffset = pair.first;
|
||||
size_t nBytesReservedBeforeTrap = pair.second;
|
||||
|
||||
@ -142,11 +141,9 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
&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)) {
|
||||
@ -154,36 +151,36 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(masm.framePushed() == func.frame_pushed);
|
||||
MOZ_ASSERT(masm.framePushed() == func.framePushed);
|
||||
|
||||
// Copy the machine code; handle jump tables and other read-only data below.
|
||||
uint32_t funcBase = masm.currentOffset();
|
||||
if (!masm.appendRawCode(func.code, func.code_size)) {
|
||||
if (!masm.appendRawCode(func.code, func.codeSize)) {
|
||||
return false;
|
||||
}
|
||||
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
|
||||
uint32_t codeEnd = masm.currentOffset();
|
||||
#endif
|
||||
|
||||
wasm::GenerateFunctionEpilogue(masm, func.frame_pushed, offsets);
|
||||
wasm::GenerateFunctionEpilogue(masm, func.framePushed, offsets);
|
||||
|
||||
if (func.num_rodata_relocs > 0) {
|
||||
if (func.numRodataRelocs > 0) {
|
||||
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
|
||||
constexpr size_t jumptableElementSize = 4;
|
||||
|
||||
MOZ_ASSERT(func.jumptables_size % jumptableElementSize == 0);
|
||||
MOZ_ASSERT(func.jumptablesSize % jumptableElementSize == 0);
|
||||
|
||||
// Align the jump tables properly.
|
||||
masm.haltingAlign(jumptableElementSize);
|
||||
|
||||
// Copy over the tables and read-only data.
|
||||
uint32_t rodataBase = masm.currentOffset();
|
||||
if (!masm.appendRawCode(func.code + func.code_size,
|
||||
func.total_size - func.code_size)) {
|
||||
if (!masm.appendRawCode(func.code + func.codeSize,
|
||||
func.totalSize - func.codeSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t numElem = func.jumptables_size / jumptableElementSize;
|
||||
uint32_t numElem = func.jumptablesSize / jumptableElementSize;
|
||||
uint32_t bias = rodataBase - codeEnd;
|
||||
|
||||
// Bias the jump table(s). The table values are negative values
|
||||
@ -198,9 +195,9 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
|
||||
// Patch up the code locations. These represent forward distances that also
|
||||
// become greater, so we add a positive value.
|
||||
for (uint32_t i = 0; i < func.num_rodata_relocs; i++) {
|
||||
MOZ_ASSERT(func.rodata_relocs[i] < func.code_size);
|
||||
masm.addToPCRel4(funcBase + func.rodata_relocs[i], bias);
|
||||
for (uint32_t i = 0; i < func.numRodataRelocs; i++) {
|
||||
MOZ_ASSERT(func.rodataRelocs[i] < func.codeSize);
|
||||
masm.addToPCRel4(funcBase + func.rodataRelocs[i], bias);
|
||||
}
|
||||
#else
|
||||
MOZ_CRASH("No jump table support on this platform");
|
||||
@ -218,11 +215,11 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
maplet->offsetBy(funcBase);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < func.num_metadata; i++) {
|
||||
for (size_t i = 0; i < func.numMetadata; i++) {
|
||||
const CraneliftMetadataEntry& metadata = func.metadatas[i];
|
||||
|
||||
CheckedInt<size_t> offset = funcBase;
|
||||
offset += metadata.code_offset;
|
||||
offset += metadata.codeOffset;
|
||||
if (!offset.isValid()) {
|
||||
return false;
|
||||
}
|
||||
@ -231,16 +228,19 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
// Check code offsets.
|
||||
MOZ_ASSERT(offset.value() >= offsets->normalEntry);
|
||||
MOZ_ASSERT(offset.value() < offsets->ret);
|
||||
MOZ_ASSERT(metadata.module_bytecode_offset != 0);
|
||||
|
||||
// Check bytecode offsets.
|
||||
if (lineOrBytecode > 0) {
|
||||
MOZ_ASSERT(metadata.module_bytecode_offset >= lineOrBytecode);
|
||||
MOZ_ASSERT(metadata.module_bytecode_offset <
|
||||
if (metadata.moduleBytecodeOffset > 0 && lineOrBytecode > 0) {
|
||||
MOZ_ASSERT(metadata.moduleBytecodeOffset >= lineOrBytecode);
|
||||
MOZ_ASSERT(metadata.moduleBytecodeOffset <
|
||||
lineOrBytecode + funcBytecodeSize);
|
||||
}
|
||||
#endif
|
||||
uint32_t bytecodeOffset = metadata.module_bytecode_offset;
|
||||
// TODO(bug 1532716): Cranelift gives null bytecode offsets for symbolic
|
||||
// accesses.
|
||||
uint32_t bytecodeOffset = metadata.moduleBytecodeOffset
|
||||
? metadata.moduleBytecodeOffset
|
||||
: lineOrBytecode;
|
||||
|
||||
switch (metadata.which) {
|
||||
case CraneliftMetadataEntry::Which::DirectCall: {
|
||||
@ -259,14 +259,15 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
masm.append(trap, wasm::TrapSite(offset.value(), trapOffset));
|
||||
break;
|
||||
}
|
||||
case CraneliftMetadataEntry::Which::MemoryAccess: {
|
||||
BytecodeOffset trapOffset(bytecodeOffset);
|
||||
masm.appendOutOfBoundsTrap(trapOffset, offset.value());
|
||||
break;
|
||||
}
|
||||
case CraneliftMetadataEntry::Which::SymbolicAccess: {
|
||||
CodeOffset raOffset(offset.value());
|
||||
CallSiteDesc desc(bytecodeOffset, CallSiteDesc::Symbolic);
|
||||
masm.append(desc, raOffset);
|
||||
|
||||
SymbolicAddress sym =
|
||||
ToSymbolicAddress(BD_SymbolicAddress(metadata.extra));
|
||||
masm.append(SymbolicAccess(raOffset, sym));
|
||||
masm.append(SymbolicAccess(CodeOffset(offset.value()), sym));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -291,15 +292,15 @@ class AutoCranelift {
|
||||
public:
|
||||
explicit AutoCranelift(const ModuleEnvironment& env)
|
||||
: env_(env), compiler_(nullptr) {
|
||||
staticEnv_.ref_types_enabled = env.refTypesEnabled();
|
||||
staticEnv_.refTypesEnabled = env.refTypesEnabled();
|
||||
#ifdef WASM_SUPPORTS_HUGE_MEMORY
|
||||
if (env.hugeMemoryEnabled()) {
|
||||
// In the huge memory configuration, we always reserve the full 4 GB
|
||||
// index space for a heap.
|
||||
staticEnv_.static_memory_bound = HugeIndexRange;
|
||||
staticEnv_.memory_guard_size = HugeOffsetGuardLimit;
|
||||
staticEnv_.staticMemoryBound = HugeIndexRange;
|
||||
staticEnv_.memoryGuardSize = HugeOffsetGuardLimit;
|
||||
} else {
|
||||
staticEnv_.memory_guard_size = OffsetGuardLimit;
|
||||
staticEnv_.memoryGuardSize = OffsetGuardLimit;
|
||||
}
|
||||
#endif
|
||||
// Otherwise, heap bounds are stored in the `boundsCheckLimit` field
|
||||
@ -320,7 +321,7 @@ class AutoCranelift {
|
||||
CraneliftFuncCompileInput::CraneliftFuncCompileInput(
|
||||
const FuncCompileInput& func)
|
||||
: bytecode(func.begin),
|
||||
bytecode_size(func.end - func.begin),
|
||||
bytecodeSize(func.end - func.begin),
|
||||
index(func.index),
|
||||
offset_in_module(func.lineOrBytecode) {}
|
||||
|
||||
@ -330,50 +331,48 @@ static_assert(offsetof(TlsData, boundsCheckLimit) == sizeof(size_t),
|
||||
CraneliftStaticEnvironment::CraneliftStaticEnvironment()
|
||||
:
|
||||
#ifdef JS_CODEGEN_X64
|
||||
has_sse2(Assembler::HasSSE2()),
|
||||
has_sse3(Assembler::HasSSE3()),
|
||||
has_sse41(Assembler::HasSSE41()),
|
||||
has_sse42(Assembler::HasSSE42()),
|
||||
has_popcnt(Assembler::HasPOPCNT()),
|
||||
has_avx(Assembler::HasAVX()),
|
||||
has_bmi1(Assembler::HasBMI1()),
|
||||
has_bmi2(Assembler::HasBMI2()),
|
||||
has_lzcnt(Assembler::HasLZCNT()),
|
||||
hasSse2(Assembler::HasSSE2()),
|
||||
hasSse3(Assembler::HasSSE3()),
|
||||
hasSse41(Assembler::HasSSE41()),
|
||||
hasSse42(Assembler::HasSSE42()),
|
||||
hasPopcnt(Assembler::HasPOPCNT()),
|
||||
hasAvx(Assembler::HasAVX()),
|
||||
hasBmi1(Assembler::HasBMI1()),
|
||||
hasBmi2(Assembler::HasBMI2()),
|
||||
hasLzcnt(Assembler::HasLZCNT()),
|
||||
#else
|
||||
has_sse2(false),
|
||||
has_sse3(false),
|
||||
has_sse41(false),
|
||||
has_sse42(false),
|
||||
has_popcnt(false),
|
||||
has_avx(false),
|
||||
has_bmi1(false),
|
||||
has_bmi2(false),
|
||||
has_lzcnt(false),
|
||||
hasSse2(false),
|
||||
hasSse3(false),
|
||||
hasSse41(false),
|
||||
hasSse42(false),
|
||||
hasPopcnt(false),
|
||||
hasAvx(false),
|
||||
hasBmi1(false),
|
||||
hasBmi2(false),
|
||||
hasLzcnt(false),
|
||||
#endif
|
||||
#if defined(XP_WIN)
|
||||
platform_is_windows(true),
|
||||
platformIsWindows(true),
|
||||
#else
|
||||
platform_is_windows(false),
|
||||
platformIsWindows(false),
|
||||
#endif
|
||||
ref_types_enabled(false),
|
||||
static_memory_bound(0),
|
||||
memory_guard_size(0),
|
||||
memory_base_tls_offset(offsetof(TlsData, memoryBase)),
|
||||
instance_tls_offset(offsetof(TlsData, instance)),
|
||||
interrupt_tls_offset(offsetof(TlsData, interrupt)),
|
||||
cx_tls_offset(offsetof(TlsData, cx)),
|
||||
realm_cx_offset(JSContext::offsetOfRealm()),
|
||||
realm_tls_offset(offsetof(TlsData, realm)),
|
||||
realm_func_import_tls_offset(offsetof(FuncImportTls, realm)),
|
||||
size_of_wasm_frame(sizeof(wasm::Frame)) {
|
||||
refTypesEnabled(false),
|
||||
staticMemoryBound(0),
|
||||
memoryGuardSize(0),
|
||||
memoryBaseTlsOffset(offsetof(TlsData, memoryBase)),
|
||||
instanceTlsOffset(offsetof(TlsData, instance)),
|
||||
interruptTlsOffset(offsetof(TlsData, interrupt)),
|
||||
cxTlsOffset(offsetof(TlsData, cx)),
|
||||
realmCxOffset(JSContext::offsetOfRealm()),
|
||||
realmTlsOffset(offsetof(TlsData, realm)),
|
||||
realmFuncImportTlsOffset(offsetof(FuncImportTls, realm)) {
|
||||
}
|
||||
|
||||
// Most of BaldrMonkey's data structures refer to a "global offset" which is a
|
||||
// byte offset into the `globalArea` field of the `TlsData` struct.
|
||||
//
|
||||
// Cranelift represents global variables with their byte offset from the "VM
|
||||
// context pointer" which is the `WasmTlsReg` pointing to the `TlsData`
|
||||
// struct.
|
||||
// context pointer" which is the `WasmTlsReg` pointing to the `TlsData` struct.
|
||||
//
|
||||
// This function translates between the two.
|
||||
|
||||
@ -516,8 +515,8 @@ bool wasm::CraneliftCompileFunctions(const ModuleEnvironment& env,
|
||||
const CodeRangeVector& codeRanges = code->codeRanges;
|
||||
MOZ_ASSERT(codeRanges.length() >= inputs.length());
|
||||
|
||||
// Within the current batch, functions' code ranges have been added in
|
||||
// the same order as the inputs.
|
||||
// Within the current batch, functions' code ranges have been added in the
|
||||
// same order as the inputs.
|
||||
size_t firstCodeRangeIndex = codeRanges.length() - inputs.length();
|
||||
|
||||
for (size_t i = 0; i < inputs.length(); i++) {
|
||||
|
@ -13,8 +13,8 @@ name = "baldrdash"
|
||||
# cranelift-wasm to pinned commits. If you want to update Cranelift in Gecko,
|
||||
# you should update the following $TOP_LEVEL/Cargo.toml file: look for the
|
||||
# revision (rev) hashes of both cranelift dependencies (codegen and wasm).
|
||||
cranelift-codegen = { version = "0.62.0", default-features = false }
|
||||
cranelift-wasm = "0.62.0"
|
||||
cranelift-codegen = { version = "0.60.0", default-features = false }
|
||||
cranelift-wasm = "0.60.0"
|
||||
log = { version = "0.4.6", default-features = false, features = ["release_max_level_info"] }
|
||||
env_logger = "0.6"
|
||||
smallvec = "1.0"
|
||||
|
@ -57,27 +57,26 @@ struct ModuleEnvironment;
|
||||
// to, but which can't be automatically provided to Rust.
|
||||
|
||||
struct CraneliftStaticEnvironment {
|
||||
bool has_sse2;
|
||||
bool has_sse3;
|
||||
bool has_sse41;
|
||||
bool has_sse42;
|
||||
bool has_popcnt;
|
||||
bool has_avx;
|
||||
bool has_bmi1;
|
||||
bool has_bmi2;
|
||||
bool has_lzcnt;
|
||||
bool platform_is_windows;
|
||||
bool ref_types_enabled;
|
||||
size_t static_memory_bound;
|
||||
size_t memory_guard_size;
|
||||
size_t memory_base_tls_offset;
|
||||
size_t instance_tls_offset;
|
||||
size_t interrupt_tls_offset;
|
||||
size_t cx_tls_offset;
|
||||
size_t realm_cx_offset;
|
||||
size_t realm_tls_offset;
|
||||
size_t realm_func_import_tls_offset;
|
||||
size_t size_of_wasm_frame;
|
||||
bool hasSse2;
|
||||
bool hasSse3;
|
||||
bool hasSse41;
|
||||
bool hasSse42;
|
||||
bool hasPopcnt;
|
||||
bool hasAvx;
|
||||
bool hasBmi1;
|
||||
bool hasBmi2;
|
||||
bool hasLzcnt;
|
||||
bool platformIsWindows;
|
||||
bool refTypesEnabled;
|
||||
size_t staticMemoryBound;
|
||||
size_t memoryGuardSize;
|
||||
size_t memoryBaseTlsOffset;
|
||||
size_t instanceTlsOffset;
|
||||
size_t interruptTlsOffset;
|
||||
size_t cxTlsOffset;
|
||||
size_t realmCxOffset;
|
||||
size_t realmTlsOffset;
|
||||
size_t realmFuncImportTlsOffset;
|
||||
|
||||
// Not bindgen'd because it's inlined.
|
||||
inline CraneliftStaticEnvironment();
|
||||
@ -104,11 +103,11 @@ struct BD_Stackmaps;
|
||||
|
||||
struct CraneliftFuncCompileInput {
|
||||
const uint8_t* bytecode;
|
||||
size_t bytecode_size;
|
||||
size_t bytecodeSize;
|
||||
uint32_t index;
|
||||
uint32_t offset_in_module;
|
||||
|
||||
// The stackmaps sink to use when compiling this function.
|
||||
// The stackmaps sink to use when compiling this function
|
||||
BD_Stackmaps* stackmaps;
|
||||
|
||||
// Not bindgen'd because it's inlined.
|
||||
@ -123,9 +122,15 @@ struct CraneliftFuncCompileInput {
|
||||
// handle them, with a lot of unsafe'ing.
|
||||
|
||||
struct CraneliftMetadataEntry {
|
||||
enum Which { DirectCall, IndirectCall, Trap, SymbolicAccess } which;
|
||||
uint32_t code_offset;
|
||||
uint32_t module_bytecode_offset;
|
||||
enum Which {
|
||||
DirectCall,
|
||||
IndirectCall,
|
||||
Trap,
|
||||
MemoryAccess,
|
||||
SymbolicAccess
|
||||
} which;
|
||||
uint32_t codeOffset;
|
||||
uint32_t moduleBytecodeOffset;
|
||||
size_t extra;
|
||||
};
|
||||
|
||||
@ -134,27 +139,27 @@ struct CraneliftMetadataEntry {
|
||||
// prologue/epilogue etc.
|
||||
|
||||
struct CraneliftCompiledFunc {
|
||||
size_t num_metadata;
|
||||
size_t numMetadata;
|
||||
const CraneliftMetadataEntry* metadatas;
|
||||
|
||||
size_t frame_pushed;
|
||||
bool contains_calls;
|
||||
size_t framePushed;
|
||||
bool containsCalls;
|
||||
|
||||
// The compiled code comprises machine code, relocatable jump tables, and
|
||||
// copyable read-only data, concatenated without padding. The "...Size"
|
||||
// members give the sizes of the individual sections. The code starts at
|
||||
// offsets 0; the other offsets can be derived from the sizes.
|
||||
const uint8_t* code;
|
||||
size_t code_size;
|
||||
size_t jumptables_size;
|
||||
size_t rodata_size;
|
||||
size_t total_size;
|
||||
size_t codeSize;
|
||||
size_t jumptablesSize;
|
||||
size_t rodataSize;
|
||||
size_t totalSize;
|
||||
|
||||
// Relocation information for instructions that reference into the jump tables
|
||||
// and read-only data segments. The relocation information is
|
||||
// machine-specific.
|
||||
size_t num_rodata_relocs;
|
||||
const uint32_t* rodata_relocs;
|
||||
size_t numRodataRelocs;
|
||||
const uint32_t* rodataRelocs;
|
||||
};
|
||||
|
||||
// Possible constant values for initializing globals.
|
||||
|
@ -236,7 +236,7 @@ impl<'a> ModuleEnvironment<'a> {
|
||||
|
||||
impl FuncCompileInput {
|
||||
pub fn bytecode(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.bytecode, self.bytecode_size) }
|
||||
unsafe { slice::from_raw_parts(self.bytecode, self.bytecodeSize) }
|
||||
}
|
||||
|
||||
pub fn stackmaps(&self) -> Stackmaps {
|
||||
@ -246,57 +246,65 @@ impl FuncCompileInput {
|
||||
|
||||
impl CompiledFunc {
|
||||
pub fn reset(&mut self, compiled_func: &compile::CompiledFunc) {
|
||||
self.num_metadata = compiled_func.metadata.len();
|
||||
self.numMetadata = compiled_func.metadata.len();
|
||||
self.metadatas = compiled_func.metadata.as_ptr();
|
||||
|
||||
self.frame_pushed = compiled_func.frame_pushed as usize;
|
||||
self.contains_calls = compiled_func.contains_calls;
|
||||
self.framePushed = compiled_func.frame_pushed as usize;
|
||||
self.containsCalls = compiled_func.contains_calls;
|
||||
|
||||
self.code = compiled_func.code_buffer.as_ptr();
|
||||
self.code_size = compiled_func.code_size as usize;
|
||||
self.jumptables_size = compiled_func.jumptables_size as usize;
|
||||
self.rodata_size = compiled_func.rodata_size as usize;
|
||||
self.total_size = compiled_func.code_buffer.len();
|
||||
self.codeSize = compiled_func.code_size as usize;
|
||||
self.jumptablesSize = compiled_func.jumptables_size as usize;
|
||||
self.rodataSize = compiled_func.rodata_size as usize;
|
||||
self.totalSize = compiled_func.code_buffer.len();
|
||||
|
||||
self.num_rodata_relocs = compiled_func.rodata_relocs.len();
|
||||
self.rodata_relocs = compiled_func.rodata_relocs.as_ptr();
|
||||
self.numRodataRelocs = compiled_func.rodata_relocs.len();
|
||||
self.rodataRelocs = compiled_func.rodata_relocs.as_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataEntry {
|
||||
pub fn direct_call(code_offset: CodeOffset, srcloc: SourceLoc, func_index: FuncIndex) -> Self {
|
||||
pub fn direct_call(code_offset: CodeOffset, func_index: FuncIndex, srcloc: SourceLoc) -> Self {
|
||||
Self {
|
||||
which: CraneliftMetadataEntry_Which_DirectCall,
|
||||
code_offset,
|
||||
module_bytecode_offset: srcloc.bits(),
|
||||
codeOffset: code_offset,
|
||||
moduleBytecodeOffset: srcloc.bits(),
|
||||
extra: func_index.index(),
|
||||
}
|
||||
}
|
||||
pub fn indirect_call(ret_addr: CodeOffset, srcloc: SourceLoc) -> Self {
|
||||
|
||||
pub fn indirect_call(code_offset: CodeOffset, srcloc: SourceLoc) -> Self {
|
||||
Self {
|
||||
which: CraneliftMetadataEntry_Which_IndirectCall,
|
||||
code_offset: ret_addr,
|
||||
module_bytecode_offset: srcloc.bits(),
|
||||
codeOffset: code_offset,
|
||||
moduleBytecodeOffset: srcloc.bits(),
|
||||
extra: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trap(code_offset: CodeOffset, srcloc: SourceLoc, which: Trap) -> Self {
|
||||
Self {
|
||||
which: CraneliftMetadataEntry_Which_Trap,
|
||||
code_offset,
|
||||
module_bytecode_offset: srcloc.bits(),
|
||||
codeOffset: code_offset,
|
||||
moduleBytecodeOffset: srcloc.bits(),
|
||||
extra: which as usize,
|
||||
}
|
||||
}
|
||||
pub fn symbolic_access(
|
||||
code_offset: CodeOffset,
|
||||
srcloc: SourceLoc,
|
||||
sym: SymbolicAddress,
|
||||
) -> Self {
|
||||
|
||||
pub fn memory_access(code_offset: CodeOffset, srcloc: SourceLoc) -> Self {
|
||||
Self {
|
||||
which: CraneliftMetadataEntry_Which_MemoryAccess,
|
||||
codeOffset: code_offset,
|
||||
moduleBytecodeOffset: srcloc.bits(),
|
||||
extra: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn symbolic_access(code_offset: CodeOffset, sym: SymbolicAddress) -> Self {
|
||||
Self {
|
||||
which: CraneliftMetadataEntry_Which_SymbolicAccess,
|
||||
code_offset,
|
||||
module_bytecode_offset: srcloc.bits(),
|
||||
codeOffset: code_offset,
|
||||
moduleBytecodeOffset: 0,
|
||||
extra: sym as usize,
|
||||
}
|
||||
}
|
||||
@ -305,7 +313,7 @@ impl MetadataEntry {
|
||||
impl StaticEnvironment {
|
||||
/// Returns the default calling convention on this machine.
|
||||
pub fn call_conv(&self) -> isa::CallConv {
|
||||
if self.platform_is_windows {
|
||||
if self.platformIsWindows {
|
||||
isa::CallConv::BaldrdashWindows
|
||||
} else {
|
||||
isa::CallConv::BaldrdashSystemV
|
||||
|
@ -22,22 +22,19 @@ use std::fmt;
|
||||
use std::mem;
|
||||
|
||||
use cranelift_codegen::binemit::{
|
||||
Addend, CodeInfo, CodeOffset, NullStackmapSink, Reloc, RelocSink, Stackmap, TrapSink,
|
||||
Addend, CodeInfo, CodeOffset, NullStackmapSink, NullTrapSink, Reloc, RelocSink, Stackmap,
|
||||
};
|
||||
use cranelift_codegen::entity::EntityRef;
|
||||
use cranelift_codegen::ir::{
|
||||
self, constant::ConstantOffset, stackslot::StackSize, ExternalName, JumpTable, SourceLoc,
|
||||
TrapCode,
|
||||
};
|
||||
use cranelift_codegen::ir::{self, constant::ConstantOffset, stackslot::StackSize};
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_codegen::CodegenResult;
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_wasm::{FuncIndex, FuncTranslator, ModuleTranslationState, WasmResult};
|
||||
|
||||
use crate::bindings;
|
||||
use crate::isa::{make_isa, POINTER_SIZE};
|
||||
use crate::isa::make_isa;
|
||||
use crate::utils::DashResult;
|
||||
use crate::wasm2clif::{init_sig, TransEnv, TRAP_THROW_REPORTED};
|
||||
use crate::wasm2clif::{init_sig, TransEnv, POINTER_SIZE, TRAP_THROW_REPORTED};
|
||||
|
||||
// Namespace for user-defined functions.
|
||||
const USER_FUNCTION_NAMESPACE: u32 = 0;
|
||||
@ -161,6 +158,12 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
||||
|
||||
self.current_func.reset(frame_pushed, contains_calls);
|
||||
|
||||
// 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);
|
||||
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
|
||||
// have to allocate and copy here.
|
||||
// TODO(bbouvier) try to get this pointer from the C++ caller, with an unlikely callback to
|
||||
@ -176,28 +179,22 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
||||
}
|
||||
|
||||
{
|
||||
let mut traps = Traps::new();
|
||||
let mut relocs = Relocations::new(
|
||||
let emit_env = &mut EmitEnv::new(
|
||||
&mut self.current_func.metadata,
|
||||
&mut self.current_func.rodata_relocs,
|
||||
);
|
||||
let mut trap_sink = NullTrapSink {};
|
||||
|
||||
let code_buffer = &mut self.current_func.code_buffer;
|
||||
unsafe {
|
||||
let code_buffer = &mut self.current_func.code_buffer;
|
||||
self.context.emit_to_memory(
|
||||
&*self.isa,
|
||||
code_buffer.as_mut_ptr(),
|
||||
&mut relocs,
|
||||
&mut traps,
|
||||
emit_env,
|
||||
&mut trap_sink,
|
||||
&mut NullStackmapSink {},
|
||||
)
|
||||
};
|
||||
|
||||
self.current_func.metadata.append(&mut traps.metadata);
|
||||
}
|
||||
|
||||
if self.static_environ.ref_types_enabled {
|
||||
self.emit_stackmaps(stackmaps);
|
||||
}
|
||||
|
||||
self.current_func.code_size = info.code_size;
|
||||
@ -207,31 +204,6 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Iterate over each instruction to generate a stack map for each instruction that needs it.
|
||||
///
|
||||
/// Note a stackmap is associated to the address of the next instruction following the actual
|
||||
/// instruction needing the stack map. This is because this is the only information
|
||||
/// Spidermonkey has access to when it looks up a stack map (during stack frame iteration).
|
||||
fn emit_stackmaps(&self, mut stackmaps: bindings::Stackmaps) {
|
||||
let encinfo = self.isa.encoding_info();
|
||||
let func = &self.context.func;
|
||||
let stack_slots = &func.stack_slots;
|
||||
for block in func.layout.blocks() {
|
||||
let mut pending_safepoint = None;
|
||||
for (offset, inst, inst_size) in func.inst_offsets(block, &encinfo) {
|
||||
if let Some(stackmap) = pending_safepoint.take() {
|
||||
stackmaps.add_stackmap(stack_slots, offset + inst_size, stackmap);
|
||||
}
|
||||
if func.dfg[inst].opcode() == ir::Opcode::Safepoint {
|
||||
let args = func.dfg.inst_args(inst);
|
||||
let stackmap = Stackmap::from_values(&args, func, &*self.isa);
|
||||
pending_safepoint = Some(stackmap);
|
||||
}
|
||||
}
|
||||
debug_assert!(pending_safepoint.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the `framePushed` argument to pass to `GenerateFunctionPrologue`. This is the
|
||||
/// number of frame bytes used by Cranelift, not counting the values pushed by the standard
|
||||
/// prologue generated by `GenerateFunctionPrologue`.
|
||||
@ -258,6 +230,246 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
||||
// signatures which could be called.
|
||||
!self.context.func.dfg.signatures.is_empty()
|
||||
}
|
||||
|
||||
#[cfg(feature = "cranelift_x86")]
|
||||
fn platform_specific_ignores_metadata(opcode: ir::Opcode) -> bool {
|
||||
match opcode {
|
||||
ir::Opcode::X86Sdivmodx | ir::Opcode::X86Udivmodx => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "cranelift_x86"))]
|
||||
fn platform_specific_ignores_metadata(_opcode: ir::Opcode) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Emit metadata by scanning the compiled function before `emit_to_memory`.
|
||||
///
|
||||
/// - All call sites need metadata: direct, indirect, symbolic.
|
||||
/// - All explicit traps must be registered.
|
||||
///
|
||||
/// 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,
|
||||
) {
|
||||
let encinfo = self.isa.encoding_info();
|
||||
let func = &self.context.func;
|
||||
let stack_slots = &func.stack_slots;
|
||||
for block in func.layout.blocks() {
|
||||
let mut pending_safepoint = None;
|
||||
for (offset, inst, inst_size) in func.inst_offsets(block, &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),
|
||||
ir::Opcode::CallIndirect => {
|
||||
self.indirect_call_metadata(metadata, inst, offset + inst_size)
|
||||
}
|
||||
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
|
||||
| ir::Opcode::Uload8Complex
|
||||
| ir::Opcode::Sload8
|
||||
| ir::Opcode::Sload8Complex
|
||||
| ir::Opcode::Uload16
|
||||
| ir::Opcode::Uload16Complex
|
||||
| ir::Opcode::Sload16
|
||||
| ir::Opcode::Sload16Complex
|
||||
| ir::Opcode::Uload32
|
||||
| ir::Opcode::Uload32Complex
|
||||
| ir::Opcode::Sload32
|
||||
| ir::Opcode::Sload32Complex
|
||||
| ir::Opcode::Store
|
||||
| ir::Opcode::StoreComplex
|
||||
| ir::Opcode::Istore8
|
||||
| ir::Opcode::Istore8Complex
|
||||
| ir::Opcode::Istore16
|
||||
| ir::Opcode::Istore16Complex
|
||||
| ir::Opcode::Istore32
|
||||
| ir::Opcode::Istore32Complex => self.memory_metadata(metadata, inst, offset),
|
||||
|
||||
// Instructions that are not going to trap in our use, even though their opcode
|
||||
// says they can.
|
||||
ir::Opcode::Spill
|
||||
| ir::Opcode::Fill
|
||||
| ir::Opcode::FillNop
|
||||
| ir::Opcode::JumpTableEntry => {}
|
||||
|
||||
_ if BatchCompiler::platform_specific_ignores_metadata(opcode) => {}
|
||||
|
||||
_ => {
|
||||
debug_assert!(!opcode.is_call(), "Missed call opcode");
|
||||
debug_assert!(
|
||||
!opcode.can_trap(),
|
||||
"Missed trap: {}",
|
||||
func.dfg.display_inst(inst, Some(self.isa.as_ref()))
|
||||
);
|
||||
debug_assert!(
|
||||
!opcode.can_load(),
|
||||
"Missed load: {}",
|
||||
func.dfg.display_inst(inst, Some(self.isa.as_ref()))
|
||||
);
|
||||
debug_assert!(
|
||||
!opcode.can_store(),
|
||||
"Missed store: {}",
|
||||
func.dfg.display_inst(inst, Some(self.isa.as_ref()))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(pending_safepoint.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
fn srcloc(&self, inst: ir::Inst) -> ir::SourceLoc {
|
||||
let srcloc = self.context.func.srclocs[inst];
|
||||
debug_assert!(
|
||||
!srcloc.is_default(),
|
||||
"No source location on {}",
|
||||
self.context
|
||||
.func
|
||||
.dfg
|
||||
.display_inst(inst, Some(self.isa.as_ref()))
|
||||
);
|
||||
srcloc
|
||||
}
|
||||
|
||||
/// Emit metadata for direct call `inst`.
|
||||
fn call_metadata(
|
||||
&self,
|
||||
metadata: &mut Vec<bindings::MetadataEntry>,
|
||||
inst: ir::Inst,
|
||||
ret_addr: CodeOffset,
|
||||
) {
|
||||
let func = &self.context.func;
|
||||
|
||||
// This is a direct call, so the callee should be a non-imported wasm
|
||||
// function. We register both the call site *and* the target for relocation.
|
||||
let callee = match func.dfg[inst] {
|
||||
ir::InstructionData::Call { func_ref, .. } => &func.dfg.ext_funcs[func_ref].name,
|
||||
_ => panic!("Bad format for call"),
|
||||
};
|
||||
|
||||
let func_index = match *callee {
|
||||
ir::ExternalName::User {
|
||||
namespace: USER_FUNCTION_NAMESPACE,
|
||||
index,
|
||||
} => FuncIndex::new(index as usize),
|
||||
_ => panic!("Direct call to {} unsupported", callee),
|
||||
};
|
||||
|
||||
metadata.push(bindings::MetadataEntry::direct_call(
|
||||
ret_addr,
|
||||
func_index,
|
||||
self.srcloc(inst),
|
||||
));
|
||||
}
|
||||
|
||||
/// Emit metadata for indirect call `inst`.
|
||||
fn indirect_call_metadata(
|
||||
&self,
|
||||
metadata: &mut Vec<bindings::MetadataEntry>,
|
||||
inst: ir::Inst,
|
||||
ret_addr: CodeOffset,
|
||||
) {
|
||||
// A call_indirect instruction can represent either a table call or a far call to a runtime
|
||||
// function. The CallSiteDesc::Kind enum does distinguish between the two, but it is not
|
||||
// clear that the information is used anywhere. For now, we won't bother distinguishing
|
||||
// them, and mark all calls as `Kind::Dynamic`.
|
||||
//
|
||||
// If we do need to make a distinction in the future, it is probably easiest to add a
|
||||
// `call_far` instruction to Cranelift that encodes like an indirect call, but includes the
|
||||
// callee like a direct call.
|
||||
metadata.push(bindings::MetadataEntry::indirect_call(
|
||||
ret_addr,
|
||||
self.srcloc(inst),
|
||||
));
|
||||
}
|
||||
|
||||
fn trap_metadata(
|
||||
&self,
|
||||
metadata: &mut Vec<bindings::MetadataEntry>,
|
||||
inst: ir::Inst,
|
||||
offset: CodeOffset,
|
||||
) {
|
||||
let func = &self.context.func;
|
||||
let (code, trap_offset) = match func.dfg[inst] {
|
||||
ir::InstructionData::Trap { code, .. } => (code, 0),
|
||||
ir::InstructionData::IntCondTrap { code, .. }
|
||||
| ir::InstructionData::FloatCondTrap { code, .. } => {
|
||||
// This instruction expands to a conditional branch over ud2 on Intel archs.
|
||||
// The actual trap happens on the ud2 instruction.
|
||||
(code, 2)
|
||||
}
|
||||
_ => panic!("Bad format for trap"),
|
||||
};
|
||||
|
||||
// Translate the trap code into one of BaldrMonkey's trap codes.
|
||||
let bd_trap = match code {
|
||||
ir::TrapCode::StackOverflow => bindings::Trap::StackOverflow,
|
||||
ir::TrapCode::HeapOutOfBounds => bindings::Trap::OutOfBounds,
|
||||
ir::TrapCode::OutOfBounds => bindings::Trap::OutOfBounds,
|
||||
ir::TrapCode::TableOutOfBounds => bindings::Trap::OutOfBounds,
|
||||
ir::TrapCode::IndirectCallToNull => bindings::Trap::IndirectCallToNull,
|
||||
ir::TrapCode::BadSignature => bindings::Trap::IndirectCallBadSig,
|
||||
ir::TrapCode::IntegerOverflow => bindings::Trap::IntegerOverflow,
|
||||
ir::TrapCode::IntegerDivisionByZero => bindings::Trap::IntegerDivideByZero,
|
||||
ir::TrapCode::BadConversionToInteger => bindings::Trap::InvalidConversionToInteger,
|
||||
ir::TrapCode::Interrupt => bindings::Trap::CheckInterrupt,
|
||||
ir::TrapCode::UnreachableCodeReached => bindings::Trap::Unreachable,
|
||||
ir::TrapCode::User(x) if x == TRAP_THROW_REPORTED => bindings::Trap::ThrowReported,
|
||||
ir::TrapCode::User(_) => panic!("Uncovered trap code {}", code),
|
||||
};
|
||||
|
||||
metadata.push(bindings::MetadataEntry::trap(
|
||||
offset + trap_offset,
|
||||
self.srcloc(inst),
|
||||
bd_trap,
|
||||
));
|
||||
}
|
||||
|
||||
fn memory_metadata(
|
||||
&self,
|
||||
metadata: &mut Vec<bindings::MetadataEntry>,
|
||||
inst: ir::Inst,
|
||||
offset: CodeOffset,
|
||||
) {
|
||||
let func = &self.context.func;
|
||||
let memflags = match func.dfg[inst] {
|
||||
ir::InstructionData::Load { flags, .. }
|
||||
| ir::InstructionData::LoadComplex { flags, .. }
|
||||
| ir::InstructionData::Store { flags, .. }
|
||||
| ir::InstructionData::StoreComplex { flags, .. } => flags,
|
||||
_ => panic!("Bad format for memory access"),
|
||||
};
|
||||
|
||||
// Some load/store instructions may be accessing VM data structures instead of the
|
||||
// WebAssembly heap. These are tagged with `notrap` since their trapping is not part of
|
||||
// the semantics, i.e. that would be a bug.
|
||||
if memflags.notrap() {
|
||||
return;
|
||||
}
|
||||
|
||||
metadata.push(bindings::MetadataEntry::memory_access(
|
||||
offset,
|
||||
self.srcloc(inst),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> fmt::Display for BatchCompiler<'a, 'b> {
|
||||
@ -267,107 +479,74 @@ impl<'a, 'b> fmt::Display for BatchCompiler<'a, 'b> {
|
||||
}
|
||||
|
||||
/// Create a Cranelift function name representing a WebAssembly function with `index`.
|
||||
pub fn wasm_function_name(func: FuncIndex) -> ExternalName {
|
||||
ExternalName::User {
|
||||
pub fn wasm_function_name(func: FuncIndex) -> ir::ExternalName {
|
||||
ir::ExternalName::User {
|
||||
namespace: USER_FUNCTION_NAMESPACE,
|
||||
index: func.index() as u32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a Cranelift function name representing a builtin function.
|
||||
pub fn symbolic_function_name(sym: bindings::SymbolicAddress) -> ExternalName {
|
||||
ExternalName::User {
|
||||
pub fn symbolic_function_name(sym: bindings::SymbolicAddress) -> ir::ExternalName {
|
||||
ir::ExternalName::User {
|
||||
namespace: SYMBOLIC_FUNCTION_NAMESPACE,
|
||||
index: sym as u32,
|
||||
}
|
||||
}
|
||||
|
||||
struct Relocations<'a> {
|
||||
/// References joined so we can implement `RelocSink`.
|
||||
struct EmitEnv<'a> {
|
||||
metadata: &'a mut Vec<bindings::MetadataEntry>,
|
||||
rodata_relocs: &'a mut Vec<CodeOffset>,
|
||||
}
|
||||
|
||||
impl<'a> Relocations<'a> {
|
||||
fn new(
|
||||
impl<'a> EmitEnv<'a> {
|
||||
pub fn new(
|
||||
metadata: &'a mut Vec<bindings::MetadataEntry>,
|
||||
rodata_relocs: &'a mut Vec<CodeOffset>,
|
||||
) -> Self {
|
||||
Self {
|
||||
) -> EmitEnv<'a> {
|
||||
EmitEnv {
|
||||
metadata,
|
||||
rodata_relocs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RelocSink for Relocations<'a> {
|
||||
/// Add a relocation referencing a block at the current offset.
|
||||
fn reloc_block(&mut self, _at: CodeOffset, _reloc: Reloc, _block_offset: CodeOffset) {
|
||||
unimplemented!("block relocations NYI");
|
||||
impl<'a> RelocSink for EmitEnv<'a> {
|
||||
fn reloc_block(&mut self, _offset: CodeOffset, _reloc: Reloc, _block_offset: CodeOffset) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Add a relocation referencing an external symbol at the current offset.
|
||||
fn reloc_external(
|
||||
&mut self,
|
||||
at: CodeOffset,
|
||||
srcloc: SourceLoc,
|
||||
reloc: Reloc,
|
||||
name: &ExternalName,
|
||||
offset: CodeOffset,
|
||||
_reloc: Reloc,
|
||||
name: &ir::ExternalName,
|
||||
_addend: Addend,
|
||||
) {
|
||||
debug_assert!(!srcloc.is_default());
|
||||
|
||||
// Decode the function name.
|
||||
match *name {
|
||||
ExternalName::User {
|
||||
ir::ExternalName::User {
|
||||
namespace: USER_FUNCTION_NAMESPACE,
|
||||
index,
|
||||
..
|
||||
} => {
|
||||
// A simple function call to another wasm function.
|
||||
let payload_size = match reloc {
|
||||
Reloc::X86CallPCRel4 => 4,
|
||||
_ => panic!("unhandled call relocation"),
|
||||
};
|
||||
|
||||
let func_index = FuncIndex::new(index as usize);
|
||||
|
||||
// The Spidermonkey relocation must point to the next instruction. Cranelift gives
|
||||
// us the exact offset to the immediate, so fix it up by the relocation's size.
|
||||
let offset = at + payload_size;
|
||||
self.metadata.push(bindings::MetadataEntry::direct_call(
|
||||
offset, srcloc, func_index,
|
||||
));
|
||||
// This is a direct function call handled by `call_metadata` above.
|
||||
}
|
||||
|
||||
ExternalName::User {
|
||||
ir::ExternalName::User {
|
||||
namespace: SYMBOLIC_FUNCTION_NAMESPACE,
|
||||
index,
|
||||
} => {
|
||||
let payload_size = match reloc {
|
||||
Reloc::Abs8 => {
|
||||
debug_assert_eq!(POINTER_SIZE, 8);
|
||||
8
|
||||
}
|
||||
_ => panic!("unhandled user-space symbolic call relocation"),
|
||||
};
|
||||
|
||||
// This is a symbolic function reference encoded by `symbolic_function_name()`.
|
||||
let sym = index.into();
|
||||
|
||||
// The Spidermonkey relocation must point to the next instruction.
|
||||
let offset = at + payload_size;
|
||||
self.metadata.push(bindings::MetadataEntry::symbolic_access(
|
||||
offset, srcloc, sym,
|
||||
));
|
||||
// The symbolic access patch address points *after* the stored pointer.
|
||||
let offset = offset + POINTER_SIZE as u32;
|
||||
self.metadata
|
||||
.push(bindings::MetadataEntry::symbolic_access(offset, sym));
|
||||
}
|
||||
|
||||
ExternalName::LibCall(call) => {
|
||||
let payload_size = match reloc {
|
||||
Reloc::Abs8 => {
|
||||
debug_assert_eq!(POINTER_SIZE, 8);
|
||||
8
|
||||
}
|
||||
_ => panic!("unhandled libcall symbolic call relocation"),
|
||||
};
|
||||
|
||||
ir::ExternalName::LibCall(call) => {
|
||||
let sym = match call {
|
||||
ir::LibCall::CeilF32 => bindings::SymbolicAddress::CeilF32,
|
||||
ir::LibCall::CeilF64 => bindings::SymbolicAddress::CeilF64,
|
||||
@ -382,11 +561,10 @@ impl<'a> RelocSink for Relocations<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
// The Spidermonkey relocation must point to the next instruction.
|
||||
let offset = at + payload_size;
|
||||
self.metadata.push(bindings::MetadataEntry::symbolic_access(
|
||||
offset, srcloc, sym,
|
||||
));
|
||||
// The symbolic access patch address points *after* the stored pointer.
|
||||
let offset = offset + POINTER_SIZE as u32;
|
||||
self.metadata
|
||||
.push(bindings::MetadataEntry::symbolic_access(offset, sym));
|
||||
}
|
||||
|
||||
_ => {
|
||||
@ -395,16 +573,10 @@ impl<'a> RelocSink for Relocations<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a relocation referencing a constant.
|
||||
fn reloc_constant(&mut self, _at: CodeOffset, _reloc: Reloc, _const_offset: ConstantOffset) {
|
||||
unimplemented!("constant pool relocations NYI");
|
||||
}
|
||||
|
||||
/// Add a relocation referencing a jump table.
|
||||
fn reloc_jt(&mut self, at: CodeOffset, reloc: Reloc, _jt: JumpTable) {
|
||||
fn reloc_jt(&mut self, offset: CodeOffset, reloc: Reloc, _jt: ir::JumpTable) {
|
||||
match reloc {
|
||||
Reloc::X86PCRelRodata4 => {
|
||||
self.rodata_relocs.push(at);
|
||||
self.rodata_relocs.push(offset);
|
||||
}
|
||||
_ => {
|
||||
panic!("Unhandled/unexpected reloc type");
|
||||
@ -412,54 +584,12 @@ impl<'a> RelocSink for Relocations<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Track call sites information, giving us the return address offset.
|
||||
fn add_call_site(&mut self, opcode: ir::Opcode, ret_addr: CodeOffset, srcloc: SourceLoc) {
|
||||
// Direct calls need a plain relocation, so we don't need to handle them again.
|
||||
if opcode == ir::Opcode::CallIndirect {
|
||||
self.metadata
|
||||
.push(bindings::MetadataEntry::indirect_call(ret_addr, srcloc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Traps {
|
||||
metadata: Vec<bindings::MetadataEntry>,
|
||||
}
|
||||
|
||||
impl Traps {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
metadata: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TrapSink for Traps {
|
||||
/// Add trap information for a specific offset.
|
||||
fn trap(&mut self, trap_offset: CodeOffset, loc: SourceLoc, trap: TrapCode) {
|
||||
// Translate the trap code into one of BaldrMonkey's trap codes.
|
||||
use ir::TrapCode::*;
|
||||
let bd_trap = match trap {
|
||||
StackOverflow => {
|
||||
// Cranelift will give us trap information for every spill/push/call. But
|
||||
// Spidermonkey takes care of tracking stack overflows itself in the function
|
||||
// entries, so we don't have to.
|
||||
return;
|
||||
}
|
||||
HeapOutOfBounds | OutOfBounds | TableOutOfBounds => bindings::Trap::OutOfBounds,
|
||||
IndirectCallToNull => bindings::Trap::IndirectCallToNull,
|
||||
BadSignature => bindings::Trap::IndirectCallBadSig,
|
||||
IntegerOverflow => bindings::Trap::IntegerOverflow,
|
||||
IntegerDivisionByZero => bindings::Trap::IntegerDivideByZero,
|
||||
BadConversionToInteger => bindings::Trap::InvalidConversionToInteger,
|
||||
Interrupt => bindings::Trap::CheckInterrupt,
|
||||
UnreachableCodeReached => bindings::Trap::Unreachable,
|
||||
User(x) if x == TRAP_THROW_REPORTED => bindings::Trap::ThrowReported,
|
||||
User(_) => panic!("Uncovered trap code {}", trap),
|
||||
};
|
||||
|
||||
debug_assert!(!loc.is_default());
|
||||
self.metadata
|
||||
.push(bindings::MetadataEntry::trap(trap_offset, loc, bd_trap));
|
||||
fn reloc_constant(
|
||||
&mut self,
|
||||
_offset: CodeOffset,
|
||||
_reloc: Reloc,
|
||||
_constant_pool_offset: ConstantOffset,
|
||||
) {
|
||||
unimplemented!("constant pools NYI");
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,6 @@ use cranelift_codegen::settings::{self, Configurable};
|
||||
use crate::bindings::StaticEnvironment;
|
||||
use crate::utils::{BasicError, DashResult};
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub const POINTER_SIZE: usize = 8;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub const POINTER_SIZE: usize = 4;
|
||||
|
||||
impl From<isa::LookupError> for BasicError {
|
||||
fn from(err: isa::LookupError) -> BasicError {
|
||||
BasicError::new(err.to_string())
|
||||
@ -109,14 +104,16 @@ fn make_shared_flags(
|
||||
sb.enable("avoid_div_traps")?;
|
||||
|
||||
// Cranelift needs to know how many words are pushed by `GenerateFunctionPrologue` so it can
|
||||
// compute frame pointer offsets accurately. C++'s "sizeof" gives us the number of bytes, which
|
||||
// we translate to the number of words, as expected by Cranelift.
|
||||
debug_assert_eq!(env.size_of_wasm_frame % POINTER_SIZE, 0);
|
||||
let num_words = env.size_of_wasm_frame / POINTER_SIZE;
|
||||
sb.set("baldrdash_prologue_words", &num_words.to_string())?;
|
||||
// compute frame pointer offsets accurately.
|
||||
//
|
||||
// 1. Return address (whether explicitly pushed on ARM or implicitly on x86).
|
||||
// 2. TLS register.
|
||||
// 3. Previous frame pointer.
|
||||
//
|
||||
sb.set("baldrdash_prologue_words", "3")?;
|
||||
|
||||
// Make sure that libcalls use the supplementary VMContext argument.
|
||||
let libcall_call_conv = if env.platform_is_windows {
|
||||
let libcall_call_conv = if env.platformIsWindows {
|
||||
"baldrdash_windows"
|
||||
} else {
|
||||
"baldrdash_system_v"
|
||||
@ -160,7 +157,7 @@ fn make_shared_flags(
|
||||
sb.enable("use_pinned_reg_as_heap_base")?;
|
||||
}
|
||||
|
||||
if env.ref_types_enabled {
|
||||
if env.refTypesEnabled {
|
||||
sb.enable("enable_safepoints")?;
|
||||
}
|
||||
|
||||
@ -171,32 +168,32 @@ fn make_shared_flags(
|
||||
fn make_isa_specific(env: &StaticEnvironment) -> DashResult<isa::Builder> {
|
||||
let mut ib = isa::lookup_by_name("x86_64-unknown-unknown").map_err(BasicError::from)?;
|
||||
|
||||
if !env.has_sse2 {
|
||||
if !env.hasSse2 {
|
||||
return Err("SSE2 is mandatory for Baldrdash!".into());
|
||||
}
|
||||
|
||||
if env.has_sse3 {
|
||||
if env.hasSse3 {
|
||||
ib.enable("has_sse3").map_err(BasicError::from)?;
|
||||
}
|
||||
if env.has_sse41 {
|
||||
if env.hasSse41 {
|
||||
ib.enable("has_sse41").map_err(BasicError::from)?;
|
||||
}
|
||||
if env.has_sse42 {
|
||||
if env.hasSse42 {
|
||||
ib.enable("has_sse42").map_err(BasicError::from)?;
|
||||
}
|
||||
if env.has_popcnt {
|
||||
if env.hasPopcnt {
|
||||
ib.enable("has_popcnt").map_err(BasicError::from)?;
|
||||
}
|
||||
if env.has_avx {
|
||||
if env.hasAvx {
|
||||
ib.enable("has_avx").map_err(BasicError::from)?;
|
||||
}
|
||||
if env.has_bmi1 {
|
||||
if env.hasBmi1 {
|
||||
ib.enable("has_bmi1").map_err(BasicError::from)?;
|
||||
}
|
||||
if env.has_bmi2 {
|
||||
if env.hasBmi2 {
|
||||
ib.enable("has_bmi2").map_err(BasicError::from)?;
|
||||
}
|
||||
if env.has_lzcnt {
|
||||
if env.hasLzcnt {
|
||||
ib.enable("has_lzcnt").map_err(BasicError::from)?;
|
||||
}
|
||||
|
||||
|
@ -36,12 +36,16 @@ use cranelift_wasm::{
|
||||
|
||||
use crate::bindings::{self, SymbolicAddress};
|
||||
use crate::compile::{symbolic_function_name, wasm_function_name};
|
||||
use crate::isa::POINTER_SIZE;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub const POINTER_TYPE: ir::Type = ir::types::I64;
|
||||
const POINTER_TYPE: ir::Type = ir::types::I64;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub const POINTER_TYPE: ir::Type = ir::types::I32;
|
||||
const POINTER_TYPE: ir::Type = ir::types::I32;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
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;
|
||||
@ -393,7 +397,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
let vmctx = self.get_vmctx_gv(pos.func);
|
||||
let gv = pos.func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: vmctx,
|
||||
offset: imm64(self.static_env.instance_tls_offset),
|
||||
offset: imm64(self.static_env.instanceTlsOffset),
|
||||
global_type: POINTER_TYPE,
|
||||
});
|
||||
self.instance_gv = gv.into();
|
||||
@ -413,7 +417,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
let vmctx = self.get_vmctx_gv(pos.func);
|
||||
let gv = pos.func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: vmctx,
|
||||
offset: imm64(self.static_env.interrupt_tls_offset),
|
||||
offset: imm64(self.static_env.interruptTlsOffset),
|
||||
global_type: POINTER_TYPE,
|
||||
});
|
||||
self.interrupt_gv = gv.into();
|
||||
@ -459,7 +463,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
.func
|
||||
.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: vmctx,
|
||||
offset: imm64(self.static_env.cx_tls_offset),
|
||||
offset: imm64(self.static_env.cxTlsOffset),
|
||||
global_type: POINTER_TYPE,
|
||||
})
|
||||
.into();
|
||||
@ -471,7 +475,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
.func
|
||||
.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: vmctx,
|
||||
offset: imm64(self.static_env.realm_tls_offset),
|
||||
offset: imm64(self.static_env.realmTlsOffset),
|
||||
global_type: POINTER_TYPE,
|
||||
})
|
||||
.into();
|
||||
@ -484,7 +488,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
let realm_addr_val = pos.ins().global_value(ptr, self.realm_addr.unwrap());
|
||||
let realm = pos.ins().load(ptr, flags, realm_addr_val, 0);
|
||||
pos.ins()
|
||||
.store(flags, realm, cx, offset32(self.static_env.realm_cx_offset));
|
||||
.store(flags, realm, cx, offset32(self.static_env.realmCxOffset));
|
||||
}
|
||||
|
||||
/// Update the JSContext's realm value in preparation for making an indirect call through
|
||||
@ -494,15 +498,12 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
let flags = ir::MemFlags::trusted();
|
||||
let cx = pos
|
||||
.ins()
|
||||
.load(ptr, flags, vmctx, offset32(self.static_env.cx_tls_offset));
|
||||
let realm = pos.ins().load(
|
||||
ptr,
|
||||
flags,
|
||||
vmctx,
|
||||
offset32(self.static_env.realm_tls_offset),
|
||||
);
|
||||
.load(ptr, flags, vmctx, offset32(self.static_env.cxTlsOffset));
|
||||
let realm = pos
|
||||
.ins()
|
||||
.load(ptr, flags, vmctx, offset32(self.static_env.realmTlsOffset));
|
||||
pos.ins()
|
||||
.store(flags, realm, cx, offset32(self.static_env.realm_cx_offset));
|
||||
.store(flags, realm, cx, offset32(self.static_env.realmCxOffset));
|
||||
}
|
||||
|
||||
/// Update the JSContext's realm value in preparation for making a call to an imported
|
||||
@ -517,15 +518,15 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
let flags = ir::MemFlags::trusted();
|
||||
let cx = pos
|
||||
.ins()
|
||||
.load(ptr, flags, vmctx, offset32(self.static_env.cx_tls_offset));
|
||||
.load(ptr, flags, vmctx, offset32(self.static_env.cxTlsOffset));
|
||||
let realm = pos.ins().load(
|
||||
ptr,
|
||||
flags,
|
||||
gv_addr,
|
||||
offset32(self.static_env.realm_func_import_tls_offset),
|
||||
offset32(self.static_env.realmFuncImportTlsOffset),
|
||||
);
|
||||
pos.ins()
|
||||
.store(flags, realm, cx, offset32(self.static_env.realm_cx_offset));
|
||||
.store(flags, realm, cx, offset32(self.static_env.realmCxOffset));
|
||||
}
|
||||
|
||||
fn load_pinned_reg(&self, pos: &mut FuncCursor, vmctx: ir::Value) {
|
||||
@ -534,7 +535,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
||||
POINTER_TYPE,
|
||||
ir::MemFlags::trusted(),
|
||||
vmctx,
|
||||
self.static_env.memory_base_tls_offset as i32,
|
||||
self.static_env.memoryBaseTlsOffset as i32,
|
||||
);
|
||||
pos.ins().set_pinned_reg(heap_base);
|
||||
}
|
||||
@ -698,7 +699,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
||||
|
||||
let vcmtx = self.get_vmctx_gv(func);
|
||||
|
||||
let bound = self.static_env.static_memory_bound as u64;
|
||||
let bound = self.static_env.staticMemoryBound as u64;
|
||||
let is_static = bound > 0;
|
||||
|
||||
// Get the `TlsData::memoryBase` field.
|
||||
@ -717,7 +718,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
||||
// Get the `TlsData::boundsCheckLimit` field.
|
||||
let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vcmtx,
|
||||
offset: (POINTER_SIZE as i32).into(),
|
||||
offset: POINTER_SIZE.into(),
|
||||
global_type: ir::types::I32,
|
||||
readonly: false,
|
||||
});
|
||||
@ -725,7 +726,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
||||
};
|
||||
|
||||
let min_size = (self.env.min_memory_length() as u64).into();
|
||||
let offset_guard_size = (self.static_env.memory_guard_size as u64).into();
|
||||
let offset_guard_size = (self.static_env.memoryGuardSize as u64).into();
|
||||
|
||||
Ok(func.create_heap(ir::HeapData {
|
||||
base,
|
||||
@ -869,12 +870,9 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
||||
// Handle external tables, set up environment.
|
||||
// A function table call could redirect execution to another module with a different realm,
|
||||
// so switch to this realm just in case.
|
||||
let callee_vmctx = pos.ins().load(
|
||||
POINTER_TYPE,
|
||||
ir::MemFlags::trusted(),
|
||||
entry,
|
||||
POINTER_SIZE as i32,
|
||||
);
|
||||
let callee_vmctx =
|
||||
pos.ins()
|
||||
.load(POINTER_TYPE, ir::MemFlags::trusted(), entry, POINTER_SIZE);
|
||||
self.switch_to_indirect_callee_realm(&mut pos, callee_vmctx);
|
||||
self.load_pinned_reg(&mut pos, callee_vmctx);
|
||||
|
||||
@ -921,12 +919,9 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
||||
let fit_code = pos
|
||||
.ins()
|
||||
.load(POINTER_TYPE, ir::MemFlags::trusted(), gv_addr, 0);
|
||||
let fit_tls = pos.ins().load(
|
||||
POINTER_TYPE,
|
||||
ir::MemFlags::trusted(),
|
||||
gv_addr,
|
||||
POINTER_SIZE as i32,
|
||||
);
|
||||
let fit_tls =
|
||||
pos.ins()
|
||||
.load(POINTER_TYPE, ir::MemFlags::trusted(), gv_addr, POINTER_SIZE);
|
||||
|
||||
// Switch to the callee's realm.
|
||||
self.switch_to_import_realm(&mut pos, fit_tls, gv_addr);
|
||||
@ -1272,6 +1267,6 @@ impl TableInfo {
|
||||
pub fn entry_size(&self) -> i64 {
|
||||
// Each entry is an `wasm::FunctionTableElem` which consists of the code pointer and a new
|
||||
// VM context pointer.
|
||||
(POINTER_SIZE * 2) as i64
|
||||
i64::from(POINTER_SIZE) * 2
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"2826e4035b7d2cffaeb4b093fc3e33475fdd80c2cfae57cbdf1513918808477b","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"23a5c42d477197a947122e662068e681bb9ed31041c0b668c3267c3fce15d39e","src/map.rs":"a3b7f64cae7ec9c2a8038def315bcf90e8751552b1bc1c20b62fbb8c763866c4","src/node.rs":"28f7edd979f7b9712bc4ab30b0d2a1b8ad5485a4b1e8c09f3dcaf501b9b5ccd1","src/path.rs":"a86ee1c882c173e8af96fd53a416a0fb485dd3f045ac590ef313a9d9ecf90f56","src/pool.rs":"f6337b5417f7772e6878a160c1a40629199ff09997bdff18eb2a0ba770158600","src/set.rs":"281eb8b5ead1ffd395946464d881f9bb0e7fb61092aed701d72d2314b5f80994"},"package":null}
|
||||
{"files":{"Cargo.toml":"0590650ee92ca1c67e40e0c18f6861f588bac5240e96049af89a290d28b6c774","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"23a5c42d477197a947122e662068e681bb9ed31041c0b668c3267c3fce15d39e","src/map.rs":"a3b7f64cae7ec9c2a8038def315bcf90e8751552b1bc1c20b62fbb8c763866c4","src/node.rs":"28f7edd979f7b9712bc4ab30b0d2a1b8ad5485a4b1e8c09f3dcaf501b9b5ccd1","src/path.rs":"a86ee1c882c173e8af96fd53a416a0fb485dd3f045ac590ef313a9d9ecf90f56","src/pool.rs":"f6337b5417f7772e6878a160c1a40629199ff09997bdff18eb2a0ba770158600","src/set.rs":"281eb8b5ead1ffd395946464d881f9bb0e7fb61092aed701d72d2314b5f80994"},"package":null}
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
description = "A forest of B+-trees"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
documentation = "https://docs.rs/cranelift-bforest"
|
||||
@ -12,7 +12,7 @@ keywords = ["btree", "forest", "set", "map"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-entity = { path = "../entity", version = "0.62.0", default-features = false }
|
||||
cranelift-entity = { path = "../entity", version = "0.60.0", default-features = false }
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "experimental" }
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"f5c824a81cf3c40bded1bfcc325c15e6109724c3efbbc822d4c5782dbefe9f12","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"84a4b7e3301e3249716958a7aa4ea5ba8c6172e3c02f57ee3880504c4433ff19","src/cdsl/cpu_modes.rs":"996e45b374cfe85ac47c8c86c4459fe4c04b3158102b4c63b6ee434d5eed6a9e","src/cdsl/encodings.rs":"d884a564815a03c23369bcf31d13b122ae5ba84d0c80eda9312f0c0a829bf794","src/cdsl/formats.rs":"63e638305aa3ca6dd409ddf0e5e9605eeac1cc2631103e42fc6cbc87703d9b63","src/cdsl/instructions.rs":"41e1a230501de3f0da3960d8aa375c8bcd60ec62ede94ad61806816acbd8009a","src/cdsl/isa.rs":"ccabd6848b69eb069c10db61c7e7f86080777495714bb53d03e663c40541be94","src/cdsl/mod.rs":"0aa827923bf4c45e5ee2359573bd863e00f474acd532739f49dcd74a27553882","src/cdsl/operands.rs":"1c3411504de9c83112ff48e0ff1cfbb2e4ba5a9a15c1716f411ef31a4df59899","src/cdsl/recipes.rs":"80b7cd87332229b569e38086ceee8d557e679b9a32ad2e50bdb15c33337c3418","src/cdsl/regs.rs":"466a42a43355fc7623fe5d8e8d330622207a3af6a80cb9367bc0f06e224c9ee0","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":"b275053977c0239211c1df35253154ba4dce2519f506088e71104de37d3db862","src/gen_legalizer.rs":"ea229ab9393cc5ba2242f626e74c624ea59314535e74b26602dafb8e96481a72","src/gen_registers.rs":"a904119ed803c9de24dedd15149a65337ffc168bb1d63df53d7fdebfb5f4b158","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":"fd5a7418fa0d47cdf1b823b31553f1549c03e160ffffac9e22d611185774367e","src/isa/x86/encodings.rs":"3ebb8e638df80db4deb554bf79f4d74f1bb581b55daa631f3cb419f0fa29b7f5","src/isa/x86/instructions.rs":"3c1482583b031d2663b31ee8784f0cb61c8abef995afc7c8f8a6e7be010a2ba8","src/isa/x86/legalize.rs":"5b654c2410ab384cfb20815f1114af76a7967472a45b8d60232ddce9d9921682","src/isa/x86/mod.rs":"65953f998ff3fc3b333167e9979fc0f15f976b51ad75272ac19dcaad0981b371","src/isa/x86/opcodes.rs":"b54d7cd8590ef8cd866b169d50c291fa8b33d4de7c69bcb237e1c879873d08e0","src/isa/x86/recipes.rs":"2621264954661fd474024fc6a8f01aed9cc800aaab8273aede3bd36657851c40","src/isa/x86/registers.rs":"4be0a45d8acd465c31746b7976124025b06b453e3f6d587f93efb5af0e12b1a8","src/isa/x86/settings.rs":"49abb46533b3a5415cd033e0a98b5c9561e231f2dd9510d587dc69b204bb6706","src/lib.rs":"2491b0e74078914cb89d1778fa8174daf723fe76aaf7fed18741237d68f6df32","src/shared/entities.rs":"90f774a70e1c2a2e9a553c07a5e80e0fe54cf127434bd83e67274bba4e1a19ba","src/shared/formats.rs":"89ed4074f748637adf56b93ba952e398c45d43e6326d01676885939e3fe8bc4a","src/shared/immediates.rs":"e4a57657f6af9853794804eb41c01204a2c13a632f44f55d90e156a4b98c5f65","src/shared/instructions.rs":"f2b15219f21087dbe30198d40dc426decbe64decadd7efd9bf9f5e26272c72ef","src/shared/legalize.rs":"bc9c3292446c1d338df1c4ce19f3ac5482cfe582a04a5a1e82fc9aaa6aef25ea","src/shared/mod.rs":"c219625990bf15507ac1077b349ce20e5312d4e4707426183676d469e78792b7","src/shared/settings.rs":"2e791624b4e85f9e8adcee7169fe445ca8bcdc97d1da92c92ae9576988ab0470","src/shared/types.rs":"4702df132f4b5d70cc9411ec5221ba0b1bd4479252274e0223ae57b6d0331247","src/srcgen.rs":"dcfc159c8599270f17e6a978c4be255abca51556b5ef0da497faec4a4a1e62ce","src/unique_table.rs":"31aa54330ca4786af772d32e8cb6158b6504b88fa93fe177bf0c6cbe545a8d35"},"package":null}
|
||||
{"files":{"Cargo.toml":"f4c0e8f821dc23fac1e439ff0505fbfb4dd02cf631b629f1d5552b2a9f6dd3a4","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"84a4b7e3301e3249716958a7aa4ea5ba8c6172e3c02f57ee3880504c4433ff19","src/cdsl/cpu_modes.rs":"996e45b374cfe85ac47c8c86c4459fe4c04b3158102b4c63b6ee434d5eed6a9e","src/cdsl/encodings.rs":"d884a564815a03c23369bcf31d13b122ae5ba84d0c80eda9312f0c0a829bf794","src/cdsl/formats.rs":"63e638305aa3ca6dd409ddf0e5e9605eeac1cc2631103e42fc6cbc87703d9b63","src/cdsl/instructions.rs":"41e1a230501de3f0da3960d8aa375c8bcd60ec62ede94ad61806816acbd8009a","src/cdsl/isa.rs":"ccabd6848b69eb069c10db61c7e7f86080777495714bb53d03e663c40541be94","src/cdsl/mod.rs":"0aa827923bf4c45e5ee2359573bd863e00f474acd532739f49dcd74a27553882","src/cdsl/operands.rs":"1c3411504de9c83112ff48e0ff1cfbb2e4ba5a9a15c1716f411ef31a4df59899","src/cdsl/recipes.rs":"80b7cd87332229b569e38086ceee8d557e679b9a32ad2e50bdb15c33337c3418","src/cdsl/regs.rs":"466a42a43355fc7623fe5d8e8d330622207a3af6a80cb9367bc0f06e224c9ee0","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":"b275053977c0239211c1df35253154ba4dce2519f506088e71104de37d3db862","src/gen_legalizer.rs":"ea229ab9393cc5ba2242f626e74c624ea59314535e74b26602dafb8e96481a72","src/gen_registers.rs":"a904119ed803c9de24dedd15149a65337ffc168bb1d63df53d7fdebfb5f4b158","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":"cbf3e7834c7d29de8f3faa4c70dad23167ae22d02fba5d7d518779b34535393d","src/isa/x86/instructions.rs":"3c1482583b031d2663b31ee8784f0cb61c8abef995afc7c8f8a6e7be010a2ba8","src/isa/x86/legalize.rs":"5b654c2410ab384cfb20815f1114af76a7967472a45b8d60232ddce9d9921682","src/isa/x86/mod.rs":"65953f998ff3fc3b333167e9979fc0f15f976b51ad75272ac19dcaad0981b371","src/isa/x86/opcodes.rs":"ddebd2f5a14d9d7e37be0a6dc7467d098a2df554ac1deb41c97e5d16273ed353","src/isa/x86/recipes.rs":"a90c48625cc0c60ae67436e333d330967d4ac67498685c62601b47c94c721e8d","src/isa/x86/registers.rs":"4be0a45d8acd465c31746b7976124025b06b453e3f6d587f93efb5af0e12b1a8","src/isa/x86/settings.rs":"49abb46533b3a5415cd033e0a98b5c9561e231f2dd9510d587dc69b204bb6706","src/lib.rs":"2491b0e74078914cb89d1778fa8174daf723fe76aaf7fed18741237d68f6df32","src/shared/entities.rs":"90f774a70e1c2a2e9a553c07a5e80e0fe54cf127434bd83e67274bba4e1a19ba","src/shared/formats.rs":"89ed4074f748637adf56b93ba952e398c45d43e6326d01676885939e3fe8bc4a","src/shared/immediates.rs":"e4a57657f6af9853794804eb41c01204a2c13a632f44f55d90e156a4b98c5f65","src/shared/instructions.rs":"4528650c9b26bd687458d407f46f3c6531cd6f31249024c94e4bf0b4205d7137","src/shared/legalize.rs":"bc9c3292446c1d338df1c4ce19f3ac5482cfe582a04a5a1e82fc9aaa6aef25ea","src/shared/mod.rs":"c219625990bf15507ac1077b349ce20e5312d4e4707426183676d469e78792b7","src/shared/settings.rs":"2e791624b4e85f9e8adcee7169fe445ca8bcdc97d1da92c92ae9576988ab0470","src/shared/types.rs":"4702df132f4b5d70cc9411ec5221ba0b1bd4479252274e0223ae57b6d0331247","src/srcgen.rs":"dcfc159c8599270f17e6a978c4be255abca51556b5ef0da497faec4a4a1e62ce","src/unique_table.rs":"31aa54330ca4786af772d32e8cb6158b6504b88fa93fe177bf0c6cbe545a8d35"},"package":null}
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "cranelift-codegen-meta"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
description = "Metaprogram for cranelift-codegen code generator library"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||
@ -9,8 +9,8 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen-shared = { path = "../shared", version = "0.62.0" }
|
||||
cranelift-entity = { path = "../../entity", version = "0.62.0" }
|
||||
cranelift-codegen-shared = { path = "../shared", version = "0.60.0" }
|
||||
cranelift-entity = { path = "../../entity", version = "0.60.0" }
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "experimental" }
|
||||
|
@ -205,8 +205,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
recipes.push(EncodingRecipeBuilder::new("UJcall", &formats.call, 4).emit(
|
||||
r#"
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::RiscvCall,
|
||||
sink.reloc_external(Reloc::RiscvCall,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
0);
|
||||
// rd=%x1 is the standard link register.
|
||||
|
@ -156,7 +156,7 @@ impl PerCpuModeEncodings {
|
||||
self.enc64(inst.bind(I32), template.infer_rex());
|
||||
|
||||
// I64 on x86_64: REX.W set; REX.RXB determined at runtime from registers.
|
||||
self.enc64(inst.bind(I64), template.rex().w());
|
||||
self.enc64(inst.bind(I64), template.infer_rex().w());
|
||||
}
|
||||
|
||||
/// Adds I32/I64 encodings as appropriate for a typed instruction.
|
||||
@ -192,7 +192,7 @@ impl PerCpuModeEncodings {
|
||||
self.enc64(inst.bind(B32), template.infer_rex());
|
||||
|
||||
// B64 on x86_64: REX.W set; REX.RXB determined at runtime from registers.
|
||||
self.enc64(inst.bind(B64), template.rex().w());
|
||||
self.enc64(inst.bind(B64), template.infer_rex().w());
|
||||
}
|
||||
|
||||
/// Add encodings for `inst.i32` to X86_32.
|
||||
@ -313,10 +313,10 @@ impl PerCpuModeEncodings {
|
||||
}
|
||||
|
||||
/// Add two encodings for `inst`:
|
||||
/// - X86_32, no REX prefix, since this is not valid in 32-bit mode.
|
||||
/// - X86_32, dynamically infer the REX prefix.
|
||||
/// - X86_64, dynamically infer the REX prefix.
|
||||
fn enc_both_inferred(&mut self, inst: impl Clone + Into<InstSpec>, template: Template) {
|
||||
self.enc32(inst.clone(), template.clone());
|
||||
self.enc32(inst.clone(), template.infer_rex());
|
||||
self.enc64(inst, template.infer_rex());
|
||||
}
|
||||
fn enc_both_inferred_maybe_isap(
|
||||
@ -325,7 +325,7 @@ impl PerCpuModeEncodings {
|
||||
template: Template,
|
||||
isap: Option<SettingPredicateNumber>,
|
||||
) {
|
||||
self.enc32_maybe_isap(inst.clone(), template.clone(), isap);
|
||||
self.enc32_maybe_isap(inst.clone(), template.infer_rex(), isap);
|
||||
self.enc64_maybe_isap(inst, template.infer_rex(), isap);
|
||||
}
|
||||
|
||||
@ -1600,9 +1600,6 @@ fn define_simd(
|
||||
let regspill = shared.by_name("regspill");
|
||||
let sadd_sat = shared.by_name("sadd_sat");
|
||||
let scalar_to_vector = shared.by_name("scalar_to_vector");
|
||||
let sload8x8 = shared.by_name("sload8x8");
|
||||
let sload16x4 = shared.by_name("sload16x4");
|
||||
let sload32x2 = shared.by_name("sload32x2");
|
||||
let spill = shared.by_name("spill");
|
||||
let sqrt = shared.by_name("sqrt");
|
||||
let sshr_imm = shared.by_name("sshr_imm");
|
||||
@ -1610,9 +1607,6 @@ fn define_simd(
|
||||
let store = shared.by_name("store");
|
||||
let store_complex = shared.by_name("store_complex");
|
||||
let uadd_sat = shared.by_name("uadd_sat");
|
||||
let uload8x8 = shared.by_name("uload8x8");
|
||||
let uload16x4 = shared.by_name("uload16x4");
|
||||
let uload32x2 = shared.by_name("uload32x2");
|
||||
let ushr_imm = shared.by_name("ushr_imm");
|
||||
let usub_sat = shared.by_name("usub_sat");
|
||||
let vconst = shared.by_name("vconst");
|
||||
@ -1866,8 +1860,8 @@ fn define_simd(
|
||||
// Store
|
||||
let bound_store = store.bind(vector(ty, sse_vector_size)).bind(Any);
|
||||
e.enc_both_inferred(bound_store.clone(), rec_fst.opcodes(&MOVUPS_STORE));
|
||||
e.enc_both_inferred(bound_store.clone(), rec_fstDisp8.opcodes(&MOVUPS_STORE));
|
||||
e.enc_both_inferred(bound_store, rec_fstDisp32.opcodes(&MOVUPS_STORE));
|
||||
e.enc_both(bound_store.clone(), rec_fstDisp8.opcodes(&MOVUPS_STORE));
|
||||
e.enc_both(bound_store, rec_fstDisp32.opcodes(&MOVUPS_STORE));
|
||||
|
||||
// Store complex
|
||||
let bound_store_complex = store_complex.bind(vector(ty, sse_vector_size));
|
||||
@ -1887,8 +1881,8 @@ fn define_simd(
|
||||
// Load
|
||||
let bound_load = load.bind(vector(ty, sse_vector_size)).bind(Any);
|
||||
e.enc_both_inferred(bound_load.clone(), rec_fld.opcodes(&MOVUPS_LOAD));
|
||||
e.enc_both_inferred(bound_load.clone(), rec_fldDisp8.opcodes(&MOVUPS_LOAD));
|
||||
e.enc_both_inferred(bound_load, rec_fldDisp32.opcodes(&MOVUPS_LOAD));
|
||||
e.enc_both(bound_load.clone(), rec_fldDisp8.opcodes(&MOVUPS_LOAD));
|
||||
e.enc_both(bound_load, rec_fldDisp32.opcodes(&MOVUPS_LOAD));
|
||||
|
||||
// Load complex
|
||||
let bound_load_complex = load_complex.bind(vector(ty, sse_vector_size));
|
||||
@ -1932,24 +1926,6 @@ fn define_simd(
|
||||
e.enc_32_64_rec(bound_copy_nop, rec_stacknull, 0);
|
||||
}
|
||||
|
||||
// SIMD load extend
|
||||
for (inst, opcodes) in &[
|
||||
(uload8x8, &PMOVZXBW),
|
||||
(uload16x4, &PMOVZXWD),
|
||||
(uload32x2, &PMOVZXDQ),
|
||||
(sload8x8, &PMOVSXBW),
|
||||
(sload16x4, &PMOVSXWD),
|
||||
(sload32x2, &PMOVSXDQ),
|
||||
] {
|
||||
let isap = Some(use_sse41_simd);
|
||||
for recipe in &[rec_fld, rec_fldDisp8, rec_fldDisp32] {
|
||||
let inst = *inst;
|
||||
let template = recipe.opcodes(*opcodes);
|
||||
e.enc_both_inferred_maybe_isap(inst.clone().bind(I32), template.clone(), isap);
|
||||
e.enc64_maybe_isap(inst.bind(I64), template.infer_rex(), isap);
|
||||
}
|
||||
}
|
||||
|
||||
// SIMD integer addition
|
||||
for (ty, opcodes) in &[(I8, &PADDB), (I16, &PADDW), (I32, &PADDD), (I64, &PADDQ)] {
|
||||
let iadd = iadd.bind(vector(*ty, sse_vector_size));
|
||||
|
@ -417,30 +417,6 @@ pub static PMINUD: [u8; 4] = [0x66, 0x0f, 0x38, 0x3b];
|
||||
/// xmm1 (SSE4.1).
|
||||
pub static PMINUW: [u8; 4] = [0x66, 0x0f, 0x38, 0x3a];
|
||||
|
||||
/// Sign extend 8 packed 8-bit integers in the low 8 bytes of xmm2/m64 to 8 packed 16-bit
|
||||
/// integers in xmm1 (SSE4.1).
|
||||
pub static PMOVSXBW: [u8; 4] = [0x66, 0x0f, 0x38, 0x20];
|
||||
|
||||
/// Sign extend 4 packed 16-bit integers in the low 8 bytes of xmm2/m64 to 4 packed 32-bit
|
||||
/// integers in xmm1 (SSE4.1).
|
||||
pub static PMOVSXWD: [u8; 4] = [0x66, 0x0f, 0x38, 0x23];
|
||||
|
||||
/// Sign extend 2 packed 32-bit integers in the low 8 bytes of xmm2/m64 to 2 packed 64-bit
|
||||
/// integers in xmm1.
|
||||
pub static PMOVSXDQ: [u8; 4] = [0x66, 0x0f, 0x38, 0x25];
|
||||
|
||||
/// Zero extend 8 packed 8-bit integers in the low 8 bytes of xmm2/m64 to 8 packed 16-bit
|
||||
/// integers in xmm1 (SSE4.1).
|
||||
pub static PMOVZXBW: [u8; 4] = [0x66, 0x0f, 0x38, 0x30];
|
||||
|
||||
/// Zero extend 4 packed 16-bit integers in the low 8 bytes of xmm2/m64 to 4 packed 32-bit
|
||||
/// integers in xmm1 (SSE4.1).
|
||||
pub static PMOVZXWD: [u8; 4] = [0x66, 0x0f, 0x38, 0x33];
|
||||
|
||||
/// Zero extend 2 packed 32-bit integers in the low 8 bytes of xmm2/m64 to 2 packed 64-bit
|
||||
/// integers in xmm1.
|
||||
pub static PMOVZXDQ: [u8; 4] = [0x66, 0x0f, 0x38, 0x35];
|
||||
|
||||
/// Multiply the packed signed word integers in xmm1 and xmm2/m128, and store the low 16 bits of
|
||||
/// the results in xmm1 (SSE2).
|
||||
pub static PMULLW: [u8; 3] = [0x66, 0x0f, 0xd5];
|
||||
|
@ -335,7 +335,6 @@ impl<'builder> Template<'builder> {
|
||||
("Rex".to_string() + opcode, self.op_bytes.len() as u64 + 1)
|
||||
}
|
||||
RecipePrefixKind::InferRex => {
|
||||
assert_eq!(self.w_bit, 0, "A REX.W bit always requires a REX prefix; avoid using `infer_rex().w()` and use `rex().w()` instead.");
|
||||
// Hook up the right function for inferred compute_size().
|
||||
assert!(
|
||||
self.inferred_rex_compute_size.is_some(),
|
||||
@ -1009,7 +1008,7 @@ pub(crate) fn define<'shared>(
|
||||
))
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits, rex2(out_reg0, in_reg0), sink);
|
||||
{{PUT_OP}}(bits, rex2(in_reg0, out_reg0), sink);
|
||||
modrm_rr(out_reg0, in_reg0, sink); // note the flipped register in the ModR/M byte
|
||||
let imm:i64 = lane.into();
|
||||
sink.put1(imm as u8);
|
||||
@ -1258,8 +1257,7 @@ pub(crate) fn define<'shared>(
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::Abs4,
|
||||
sink.reloc_external(Reloc::Abs4,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
0);
|
||||
sink.put4(0);
|
||||
@ -1274,8 +1272,7 @@ pub(crate) fn define<'shared>(
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::Abs8,
|
||||
sink.reloc_external(Reloc::Abs8,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
0);
|
||||
sink.put8(0);
|
||||
@ -1290,8 +1287,7 @@ pub(crate) fn define<'shared>(
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::Abs4,
|
||||
sink.reloc_external(Reloc::Abs4,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
0);
|
||||
// Write the immediate as `!0` for the benefit of BaldrMonkey.
|
||||
@ -1307,8 +1303,7 @@ pub(crate) fn define<'shared>(
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::Abs8,
|
||||
sink.reloc_external(Reloc::Abs8,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
0);
|
||||
// Write the immediate as `!0` for the benefit of BaldrMonkey.
|
||||
@ -1328,8 +1323,7 @@ pub(crate) fn define<'shared>(
|
||||
modrm_riprel(out_reg0, sink);
|
||||
// The addend adjusts for the difference between the end of the
|
||||
// instruction and the beginning of the immediate field.
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::X86PCRel4,
|
||||
sink.reloc_external(Reloc::X86PCRel4,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
-4);
|
||||
sink.put4(0);
|
||||
@ -1348,8 +1342,7 @@ pub(crate) fn define<'shared>(
|
||||
modrm_riprel(out_reg0, sink);
|
||||
// The addend adjusts for the difference between the end of the
|
||||
// instruction and the beginning of the immediate field.
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::X86GOTPCRel4,
|
||||
sink.reloc_external(Reloc::X86GOTPCRel4,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
-4);
|
||||
sink.put4(0);
|
||||
@ -1364,8 +1357,7 @@ pub(crate) fn define<'shared>(
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::Abs4,
|
||||
sink.reloc_external(Reloc::Abs4,
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
0);
|
||||
sink.put4(0);
|
||||
@ -1380,8 +1372,7 @@ pub(crate) fn define<'shared>(
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::Abs8,
|
||||
sink.reloc_external(Reloc::Abs8,
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
0);
|
||||
sink.put8(0);
|
||||
@ -1399,8 +1390,7 @@ pub(crate) fn define<'shared>(
|
||||
modrm_rm(5, out_reg0, sink);
|
||||
// The addend adjusts for the difference between the end of the
|
||||
// instruction and the beginning of the immediate field.
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::X86PCRel4,
|
||||
sink.reloc_external(Reloc::X86PCRel4,
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
-4);
|
||||
sink.put4(0);
|
||||
@ -1418,8 +1408,7 @@ pub(crate) fn define<'shared>(
|
||||
modrm_rm(5, out_reg0, sink);
|
||||
// The addend adjusts for the difference between the end of the
|
||||
// instruction and the beginning of the immediate field.
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::X86GOTPCRel4,
|
||||
sink.reloc_external(Reloc::X86GOTPCRel4,
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
-4);
|
||||
sink.put4(0);
|
||||
@ -1615,7 +1604,7 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r register-indirect store with 8-bit offset of FPR.
|
||||
recipes.add_template_inferred(
|
||||
recipes.add_template_recipe(
|
||||
EncodingRecipeBuilder::new("fstDisp8", &formats.store, 2)
|
||||
.operands_in(vec![fpr, gpr])
|
||||
.inst_predicate(has_small_offset)
|
||||
@ -1637,7 +1626,6 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(offset as u8);
|
||||
"#,
|
||||
),
|
||||
"size_plus_maybe_sib_inreg1_plus_rex_prefix_for_inreg0_inreg1",
|
||||
);
|
||||
|
||||
// XX /r register-indirect store with 32-bit offset.
|
||||
@ -1694,7 +1682,7 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r register-indirect store with 32-bit offset of FPR.
|
||||
recipes.add_template_inferred(
|
||||
recipes.add_template_recipe(
|
||||
EncodingRecipeBuilder::new("fstDisp32", &formats.store, 5)
|
||||
.operands_in(vec![fpr, gpr])
|
||||
.clobbers_flags(false)
|
||||
@ -1715,7 +1703,6 @@ pub(crate) fn define<'shared>(
|
||||
sink.put4(offset as u32);
|
||||
"#,
|
||||
),
|
||||
"size_plus_maybe_sib_inreg1_plus_rex_prefix_for_inreg0_inreg1",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2100,7 +2087,7 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r float load with 8-bit offset.
|
||||
recipes.add_template_inferred(
|
||||
recipes.add_template_recipe(
|
||||
EncodingRecipeBuilder::new("fldDisp8", &formats.load, 2)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![fpr])
|
||||
@ -2123,7 +2110,6 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(offset as u8);
|
||||
"#,
|
||||
),
|
||||
"size_plus_maybe_sib_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0",
|
||||
);
|
||||
|
||||
let has_big_offset =
|
||||
@ -2156,7 +2142,7 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r float load with 32-bit offset.
|
||||
recipes.add_template_inferred(
|
||||
recipes.add_template_recipe(
|
||||
EncodingRecipeBuilder::new("fldDisp32", &formats.load, 5)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![fpr])
|
||||
@ -2179,7 +2165,6 @@ pub(crate) fn define<'shared>(
|
||||
sink.put4(offset as u32);
|
||||
"#,
|
||||
),
|
||||
"size_plus_maybe_sib_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2412,12 +2397,10 @@ pub(crate) fn define<'shared>(
|
||||
{{PUT_OP}}(bits, BASE_REX, sink);
|
||||
// The addend adjusts for the difference between the end of the
|
||||
// instruction and the beginning of the immediate field.
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::X86CallPCRel4,
|
||||
sink.reloc_external(Reloc::X86CallPCRel4,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
-4);
|
||||
sink.put4(0);
|
||||
sink.add_call_site(opcode, func.srclocs[inst]);
|
||||
"#,
|
||||
),
|
||||
);
|
||||
@ -2427,12 +2410,10 @@ pub(crate) fn define<'shared>(
|
||||
r#"
|
||||
sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
|
||||
{{PUT_OP}}(bits, BASE_REX, sink);
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::X86CallPLTRel4,
|
||||
sink.reloc_external(Reloc::X86CallPLTRel4,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
-4);
|
||||
sink.put4(0);
|
||||
sink.add_call_site(opcode, func.srclocs[inst]);
|
||||
"#,
|
||||
),
|
||||
);
|
||||
@ -2445,7 +2426,6 @@ pub(crate) fn define<'shared>(
|
||||
sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
|
||||
{{PUT_OP}}(bits, rex1(in_reg0), sink);
|
||||
modrm_r_bits(in_reg0, bits, sink);
|
||||
sink.add_call_site(opcode, func.srclocs[inst]);
|
||||
"#,
|
||||
),
|
||||
);
|
||||
@ -3335,8 +3315,7 @@ pub(crate) fn define<'shared>(
|
||||
const LEA: u8 = 0x8d;
|
||||
sink.put1(LEA); // lea
|
||||
modrm_riprel(0b111/*out_reg0*/, sink); // 0x3d
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::ElfX86_64TlsGd,
|
||||
sink.reloc_external(Reloc::ElfX86_64TlsGd,
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
-4);
|
||||
sink.put4(0);
|
||||
@ -3346,8 +3325,7 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(0x66); // data16
|
||||
sink.put1(0b01001000); // rex.w
|
||||
sink.put1(0xe8); // call
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::X86CallPLTRel4,
|
||||
sink.reloc_external(Reloc::X86CallPLTRel4,
|
||||
&ExternalName::LibCall(LibCall::ElfTlsGetAddr),
|
||||
-4);
|
||||
sink.put4(0);
|
||||
@ -3368,8 +3346,7 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(0x48); // rex
|
||||
sink.put1(0x8b); // mov
|
||||
modrm_riprel(0b111/*out_reg0*/, sink); // 0x3d
|
||||
sink.reloc_external(func.srclocs[inst],
|
||||
Reloc::MachOX86_64Tlv,
|
||||
sink.reloc_external(Reloc::MachOX86_64Tlv,
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
-4);
|
||||
sink.put4(0);
|
||||
|
@ -1147,123 +1147,6 @@ pub(crate) fn define(
|
||||
.can_store(true),
|
||||
);
|
||||
|
||||
let I16x8 = &TypeVar::new(
|
||||
"I16x8",
|
||||
"A SIMD vector with exactly 8 lanes of 16-bit values",
|
||||
TypeSetBuilder::new()
|
||||
.ints(16..16)
|
||||
.simd_lanes(8..8)
|
||||
.includes_scalars(false)
|
||||
.build(),
|
||||
);
|
||||
let a = &Operand::new("a", I16x8).with_doc("Value loaded");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"uload8x8",
|
||||
r#"
|
||||
Load an 8x8 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i16x8
|
||||
vector.
|
||||
"#,
|
||||
&formats.load,
|
||||
)
|
||||
.operands_in(vec![MemFlags, p, Offset])
|
||||
.operands_out(vec![a])
|
||||
.can_load(true),
|
||||
);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"sload8x8",
|
||||
r#"
|
||||
Load an 8x8 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i16x8
|
||||
vector.
|
||||
"#,
|
||||
&formats.load,
|
||||
)
|
||||
.operands_in(vec![MemFlags, p, Offset])
|
||||
.operands_out(vec![a])
|
||||
.can_load(true),
|
||||
);
|
||||
|
||||
let I32x4 = &TypeVar::new(
|
||||
"I32x4",
|
||||
"A SIMD vector with exactly 4 lanes of 32-bit values",
|
||||
TypeSetBuilder::new()
|
||||
.ints(32..32)
|
||||
.simd_lanes(4..4)
|
||||
.includes_scalars(false)
|
||||
.build(),
|
||||
);
|
||||
let a = &Operand::new("a", I32x4).with_doc("Value loaded");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"uload16x4",
|
||||
r#"
|
||||
Load an 16x4 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i32x4
|
||||
vector.
|
||||
"#,
|
||||
&formats.load,
|
||||
)
|
||||
.operands_in(vec![MemFlags, p, Offset])
|
||||
.operands_out(vec![a])
|
||||
.can_load(true),
|
||||
);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"sload16x4",
|
||||
r#"
|
||||
Load a 16x4 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i32x4
|
||||
vector.
|
||||
"#,
|
||||
&formats.load,
|
||||
)
|
||||
.operands_in(vec![MemFlags, p, Offset])
|
||||
.operands_out(vec![a])
|
||||
.can_load(true),
|
||||
);
|
||||
|
||||
let I64x2 = &TypeVar::new(
|
||||
"I64x2",
|
||||
"A SIMD vector with exactly 2 lanes of 64-bit values",
|
||||
TypeSetBuilder::new()
|
||||
.ints(64..64)
|
||||
.simd_lanes(2..2)
|
||||
.includes_scalars(false)
|
||||
.build(),
|
||||
);
|
||||
let a = &Operand::new("a", I64x2).with_doc("Value loaded");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"uload32x2",
|
||||
r#"
|
||||
Load an 32x2 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i64x2
|
||||
vector.
|
||||
"#,
|
||||
&formats.load,
|
||||
)
|
||||
.operands_in(vec![MemFlags, p, Offset])
|
||||
.operands_out(vec![a])
|
||||
.can_load(true),
|
||||
);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"sload32x2",
|
||||
r#"
|
||||
Load a 32x2 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i64x2
|
||||
vector.
|
||||
"#,
|
||||
&formats.load,
|
||||
)
|
||||
.operands_in(vec![MemFlags, p, Offset])
|
||||
.operands_out(vec![a])
|
||||
.can_load(true),
|
||||
);
|
||||
|
||||
let x = &Operand::new("x", Mem).with_doc("Value to be stored");
|
||||
let a = &Operand::new("a", Mem).with_doc("Value loaded");
|
||||
let Offset =
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"35beecf644d966a002873be06c3f087756b39bb9d206aa465d957df96b6d4304","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"a410bc2f5dcbde499c0cd299c2620bc8111e3c5b3fccdd9e2d85caf3c24fdab3","src/condcodes.rs":"b8d433b2217b86e172d25b6c65a3ce0cc8ca221062cad1b28b0c78d2159fbda9","src/constant_hash.rs":"ffc619f45aad62c6fdcb83553a05879691a72e9a0103375b2d6cc12d52cf72d0","src/constants.rs":"fed03a10a6316e06aa174091db6e7d1fbb5f73c82c31193012ec5ab52f1c603a","src/isa/mod.rs":"428a950eca14acbe783899ccb1aecf15027f8cbe205578308ebde203d10535f3","src/isa/x86/encoding_bits.rs":"7e013fb804b13f9f83a0d517c6f5105856938d08ad378cc44a6fe6a59adef270","src/isa/x86/mod.rs":"01ef4e4d7437f938badbe2137892183c1ac684da0f68a5bec7e06aad34f43b9b","src/lib.rs":"91f26f998f11fb9cb74d2ec171424e29badd417beef023674850ace57149c656"},"package":null}
|
||||
{"files":{"Cargo.toml":"9b4276e6dafee6a97061c404a8418bf6bd683dd6cf4ae1997eafa990d2f20d6b","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"a410bc2f5dcbde499c0cd299c2620bc8111e3c5b3fccdd9e2d85caf3c24fdab3","src/condcodes.rs":"b8d433b2217b86e172d25b6c65a3ce0cc8ca221062cad1b28b0c78d2159fbda9","src/constant_hash.rs":"ffc619f45aad62c6fdcb83553a05879691a72e9a0103375b2d6cc12d52cf72d0","src/constants.rs":"fed03a10a6316e06aa174091db6e7d1fbb5f73c82c31193012ec5ab52f1c603a","src/isa/mod.rs":"428a950eca14acbe783899ccb1aecf15027f8cbe205578308ebde203d10535f3","src/isa/x86/encoding_bits.rs":"7e013fb804b13f9f83a0d517c6f5105856938d08ad378cc44a6fe6a59adef270","src/isa/x86/mod.rs":"01ef4e4d7437f938badbe2137892183c1ac684da0f68a5bec7e06aad34f43b9b","src/lib.rs":"91f26f998f11fb9cb74d2ec171424e29badd417beef023674850ace57149c656"},"package":null}
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
description = "For code shared between cranelift-codegen-meta and cranelift-codegen"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||
|
File diff suppressed because one or more lines are too long
10
third_party/rust/cranelift-codegen/Cargo.toml
vendored
10
third_party/rust/cranelift-codegen/Cargo.toml
vendored
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
description = "Low-level code generator library"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
documentation = "https://docs.rs/cranelift-codegen"
|
||||
@ -13,9 +13,9 @@ build = "build.rs"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen-shared = { path = "./shared", version = "0.62.0" }
|
||||
cranelift-entity = { path = "../entity", version = "0.62.0" }
|
||||
cranelift-bforest = { path = "../bforest", version = "0.62.0" }
|
||||
cranelift-codegen-shared = { path = "./shared", version = "0.60.0" }
|
||||
cranelift-entity = { path = "../entity", version = "0.60.0" }
|
||||
cranelift-bforest = { path = "../bforest", version = "0.60.0" }
|
||||
hashbrown = { version = "0.7", optional = true }
|
||||
target-lexicon = "0.10"
|
||||
log = { version = "0.4.6", default-features = false }
|
||||
@ -30,7 +30,7 @@ byteorder = { version = "1.3.2", default-features = false }
|
||||
# accomodated in `tests`.
|
||||
|
||||
[build-dependencies]
|
||||
cranelift-codegen-meta = { path = "meta", version = "0.62.0" }
|
||||
cranelift-codegen-meta = { path = "meta", version = "0.60.0" }
|
||||
|
||||
[features]
|
||||
default = ["std", "unwind"]
|
||||
|
@ -16,7 +16,7 @@
|
||||
use super::{Addend, CodeInfo, CodeOffset, CodeSink, Reloc};
|
||||
use crate::binemit::stackmap::Stackmap;
|
||||
use crate::ir::entities::Value;
|
||||
use crate::ir::{ConstantOffset, ExternalName, Function, JumpTable, Opcode, SourceLoc, TrapCode};
|
||||
use crate::ir::{ConstantOffset, ExternalName, Function, JumpTable, SourceLoc, TrapCode};
|
||||
use crate::isa::TargetIsa;
|
||||
use core::ptr::write_unaligned;
|
||||
|
||||
@ -78,24 +78,13 @@ pub trait RelocSink {
|
||||
fn reloc_block(&mut self, _: CodeOffset, _: Reloc, _: CodeOffset);
|
||||
|
||||
/// Add a relocation referencing an external symbol at the current offset.
|
||||
fn reloc_external(
|
||||
&mut self,
|
||||
_: CodeOffset,
|
||||
_: SourceLoc,
|
||||
_: Reloc,
|
||||
_: &ExternalName,
|
||||
_: Addend,
|
||||
);
|
||||
fn reloc_external(&mut self, _: CodeOffset, _: Reloc, _: &ExternalName, _: Addend);
|
||||
|
||||
/// Add a relocation referencing a constant.
|
||||
fn reloc_constant(&mut self, _: CodeOffset, _: Reloc, _: ConstantOffset);
|
||||
|
||||
/// Add a relocation referencing a jump table.
|
||||
fn reloc_jt(&mut self, _: CodeOffset, _: Reloc, _: JumpTable);
|
||||
|
||||
/// Track a call site whose return address is the given CodeOffset, for the given opcode. Does
|
||||
/// nothing in general, only useful for certain embedders (SpiderMonkey).
|
||||
fn add_call_site(&mut self, _: Opcode, _: CodeOffset, _: SourceLoc) {}
|
||||
}
|
||||
|
||||
/// A trait for receiving trap codes and offsets.
|
||||
@ -143,15 +132,9 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
|
||||
self.relocs.reloc_block(ofs, rel, block_offset);
|
||||
}
|
||||
|
||||
fn reloc_external(
|
||||
&mut self,
|
||||
srcloc: SourceLoc,
|
||||
rel: Reloc,
|
||||
name: &ExternalName,
|
||||
addend: Addend,
|
||||
) {
|
||||
fn reloc_external(&mut self, rel: Reloc, name: &ExternalName, addend: Addend) {
|
||||
let ofs = self.offset();
|
||||
self.relocs.reloc_external(ofs, srcloc, rel, name, addend);
|
||||
self.relocs.reloc_external(ofs, rel, name, addend);
|
||||
}
|
||||
|
||||
fn reloc_constant(&mut self, rel: Reloc, constant_offset: ConstantOffset) {
|
||||
@ -187,15 +170,6 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
|
||||
let stackmap = Stackmap::from_values(&val_list, func, isa);
|
||||
self.stackmaps.add_stackmap(ofs, stackmap);
|
||||
}
|
||||
|
||||
fn add_call_site(&mut self, opcode: Opcode, loc: SourceLoc) {
|
||||
debug_assert!(
|
||||
opcode.is_call(),
|
||||
"adding call site info for a non-call instruction."
|
||||
);
|
||||
let ret_addr = self.offset();
|
||||
self.relocs.add_call_site(opcode, ret_addr, loc);
|
||||
}
|
||||
}
|
||||
|
||||
/// A `RelocSink` implementation that does nothing, which is convenient when
|
||||
@ -203,18 +177,10 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
|
||||
pub struct NullRelocSink {}
|
||||
|
||||
impl RelocSink for NullRelocSink {
|
||||
fn reloc_block(&mut self, _: CodeOffset, _: Reloc, _: CodeOffset) {}
|
||||
fn reloc_external(
|
||||
&mut self,
|
||||
_: CodeOffset,
|
||||
_: SourceLoc,
|
||||
_: Reloc,
|
||||
_: &ExternalName,
|
||||
_: Addend,
|
||||
) {
|
||||
}
|
||||
fn reloc_block(&mut self, _: u32, _: Reloc, _: u32) {}
|
||||
fn reloc_external(&mut self, _: u32, _: Reloc, _: &ExternalName, _: i64) {}
|
||||
fn reloc_constant(&mut self, _: CodeOffset, _: Reloc, _: ConstantOffset) {}
|
||||
fn reloc_jt(&mut self, _: CodeOffset, _: Reloc, _: JumpTable) {}
|
||||
fn reloc_jt(&mut self, _: u32, _: Reloc, _: JumpTable) {}
|
||||
}
|
||||
|
||||
/// A `TrapSink` implementation that does nothing, which is convenient when
|
||||
|
@ -16,9 +16,7 @@ pub use self::relaxation::relax_branches;
|
||||
pub use self::shrink::shrink_instructions;
|
||||
pub use self::stackmap::Stackmap;
|
||||
use crate::ir::entities::Value;
|
||||
use crate::ir::{
|
||||
ConstantOffset, ExternalName, Function, Inst, JumpTable, Opcode, SourceLoc, TrapCode,
|
||||
};
|
||||
use crate::ir::{ConstantOffset, ExternalName, Function, Inst, JumpTable, SourceLoc, TrapCode};
|
||||
use crate::isa::TargetIsa;
|
||||
pub use crate::regalloc::RegDiversions;
|
||||
use core::fmt;
|
||||
@ -142,7 +140,7 @@ pub trait CodeSink {
|
||||
fn reloc_block(&mut self, _: Reloc, _: CodeOffset);
|
||||
|
||||
/// Add a relocation referencing an external symbol plus the addend at the current offset.
|
||||
fn reloc_external(&mut self, _: SourceLoc, _: Reloc, _: &ExternalName, _: Addend);
|
||||
fn reloc_external(&mut self, _: Reloc, _: &ExternalName, _: Addend);
|
||||
|
||||
/// Add a relocation referencing a constant.
|
||||
fn reloc_constant(&mut self, _: Reloc, _: ConstantOffset);
|
||||
@ -164,11 +162,6 @@ pub trait CodeSink {
|
||||
|
||||
/// Add a stackmap at the current code offset.
|
||||
fn add_stackmap(&mut self, _: &[Value], _: &Function, _: &dyn TargetIsa);
|
||||
|
||||
/// Add a call site for a call with the given opcode, returning at the current offset.
|
||||
fn add_call_site(&mut self, _: Opcode, _: SourceLoc) {
|
||||
// Default implementation doesn't need to do anything.
|
||||
}
|
||||
}
|
||||
|
||||
/// Type of the frame unwind information.
|
||||
|
@ -74,12 +74,6 @@ mod riscv;
|
||||
#[cfg(feature = "x86")]
|
||||
mod x86;
|
||||
|
||||
#[cfg(all(feature = "x86", feature = "unwind"))]
|
||||
/// Expose the register-mapping functionality necessary for exception handling, debug, etc.
|
||||
pub mod fde {
|
||||
pub use super::x86::map_reg;
|
||||
}
|
||||
|
||||
#[cfg(feature = "arm32")]
|
||||
mod arm32;
|
||||
|
||||
|
@ -74,15 +74,10 @@ fn evex2(rm: RegUnit, reg: RegUnit) -> u8 {
|
||||
0x00 | r_ | (b << 1) | (x << 2) | (r << 3)
|
||||
}
|
||||
|
||||
/// Determines whether a REX prefix should be emitted. A REX byte always has 0100 in bits 7:4; bits
|
||||
/// 3:0 correspond to WRXB. W allows certain instructions to declare a 64-bit operand size; because
|
||||
/// [needs_rex] is only used by [infer_rex] and we prevent [infer_rex] from using [w] in
|
||||
/// [Template::build], we do not need to check again whether [w] forces an inferred REX prefix--it
|
||||
/// always does and should be encoded like `.rex().w()`. The RXB are extension of ModR/M or SIB
|
||||
/// fields; see section 2.2.1.2 in the Intel Software Development Manual.
|
||||
/// Determines whether a REX prefix should be emitted.
|
||||
#[inline]
|
||||
fn needs_rex(rex: u8) -> bool {
|
||||
rex != BASE_REX
|
||||
fn needs_rex(bits: u16, rex: u8) -> bool {
|
||||
rex != BASE_REX || EncodingBits::from(bits).rex_w() == 1
|
||||
}
|
||||
|
||||
// Emit a REX prefix.
|
||||
@ -112,7 +107,7 @@ fn put_rexop1<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
/// Emit a single-byte opcode with inferred REX prefix.
|
||||
fn put_dynrexop1<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
debug_assert_eq!(bits & 0x0f00, 0, "Invalid encoding bits for DynRexOp1*");
|
||||
if needs_rex(rex) {
|
||||
if needs_rex(bits, rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(bits as u8);
|
||||
@ -141,7 +136,7 @@ fn put_dynrexop2<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
0x0400,
|
||||
"Invalid encoding bits for DynRexOp2*"
|
||||
);
|
||||
if needs_rex(rex) {
|
||||
if needs_rex(bits, rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(0x0f);
|
||||
@ -195,7 +190,7 @@ fn put_dynrexmp2<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
);
|
||||
let enc = EncodingBits::from(bits);
|
||||
sink.put1(PREFIX[(enc.pp() - 1) as usize]);
|
||||
if needs_rex(rex) {
|
||||
if needs_rex(bits, rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(0x0f);
|
||||
@ -233,7 +228,7 @@ fn put_dynrexmp3<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
);
|
||||
let enc = EncodingBits::from(bits);
|
||||
sink.put1(PREFIX[(enc.pp() - 1) as usize]);
|
||||
if needs_rex(rex) {
|
||||
if needs_rex(bits, rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(0x0f);
|
||||
|
@ -16,6 +16,8 @@ use crate::isa::{self, TargetIsa};
|
||||
use crate::predicates;
|
||||
use crate::regalloc::RegDiversions;
|
||||
|
||||
use cranelift_codegen_shared::isa::x86::EncodingBits;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/encoding-x86.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/legalize-x86.rs"));
|
||||
|
||||
@ -130,28 +132,13 @@ fn size_plus_maybe_sib_or_offset_inreg1_plus_rex_prefix_for_inreg0_inreg1(
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_or_offset_for_inreg_1(sizing, enc, inst, divert, func)
|
||||
+ if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Calculates the size while inferring if the first and second input registers (inreg0, inreg1)
|
||||
/// require a dynamic REX prefix and if the second input register (inreg1) requires a SIB.
|
||||
fn size_plus_maybe_sib_inreg1_plus_rex_prefix_for_inreg0_inreg1(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_for_inreg_1(sizing, enc, inst, divert, func) + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Calculates the size while inferring if the first input register (inreg0) and first output
|
||||
/// register (outreg0) require a dynamic REX and if the first input register (inreg0) requires a
|
||||
/// SIB or offset.
|
||||
@ -162,29 +149,13 @@ fn size_plus_maybe_sib_or_offset_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0(
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_or_offset_for_inreg_0(sizing, enc, inst, divert, func)
|
||||
+ if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Calculates the size while inferring if the first input register (inreg0) and first output
|
||||
/// register (outreg0) require a dynamic REX and if the first input register (inreg0) requires a
|
||||
/// SIB.
|
||||
fn size_plus_maybe_sib_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_for_inreg_0(sizing, enc, inst, divert, func) + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Infers whether a dynamic REX prefix will be emitted, for use with one input reg.
|
||||
///
|
||||
/// A REX prefix is known to be emitted if either:
|
||||
@ -192,39 +163,39 @@ fn size_plus_maybe_sib_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0(
|
||||
/// 2. Registers are used that require REX.R or REX.B bits for encoding.
|
||||
fn size_with_inferred_rex_for_inreg0(
|
||||
sizing: &RecipeSizing,
|
||||
_enc: Encoding,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg);
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Infers whether a dynamic REX prefix will be emitted, based on the second operand.
|
||||
fn size_with_inferred_rex_for_inreg1(
|
||||
sizing: &RecipeSizing,
|
||||
_enc: Encoding,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(1, inst, divert, func, is_extended_reg);
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Infers whether a dynamic REX prefix will be emitted, based on the third operand.
|
||||
fn size_with_inferred_rex_for_inreg2(
|
||||
sizing: &RecipeSizing,
|
||||
_: Encoding,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(2, inst, divert, func, is_extended_reg);
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(2, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
@ -235,13 +206,13 @@ fn size_with_inferred_rex_for_inreg2(
|
||||
/// 2. Registers are used that require REX.R or REX.B bits for encoding.
|
||||
fn size_with_inferred_rex_for_inreg0_inreg1(
|
||||
sizing: &RecipeSizing,
|
||||
_enc: Encoding,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
@ -250,13 +221,13 @@ fn size_with_inferred_rex_for_inreg0_inreg1(
|
||||
/// input register and a single output register.
|
||||
fn size_with_inferred_rex_for_inreg0_outreg0(
|
||||
sizing: &RecipeSizing,
|
||||
_enc: Encoding,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
@ -264,13 +235,13 @@ fn size_with_inferred_rex_for_inreg0_outreg0(
|
||||
/// Infers whether a dynamic REX prefix will be emitted, based on a single output register.
|
||||
fn size_with_inferred_rex_for_outreg0(
|
||||
sizing: &RecipeSizing,
|
||||
_enc: Encoding,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_result(0, inst, divert, func, is_extended_reg);
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
@ -279,13 +250,13 @@ fn size_with_inferred_rex_for_outreg0(
|
||||
/// CMOV uses 3 inputs, with the REX is inferred from reg1 and reg2.
|
||||
fn size_with_inferred_rex_for_cmov(
|
||||
sizing: &RecipeSizing,
|
||||
_enc: Encoding,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(1, inst, divert, func, is_extended_reg)
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg)
|
||||
|| test_input(2, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ use gimli::write::{
|
||||
FrameDescriptionEntry, FrameTable, Result, Writer,
|
||||
};
|
||||
use gimli::{Encoding, Format, LittleEndian, Register, X86_64};
|
||||
use thiserror::Error;
|
||||
|
||||
pub type FDERelocEntry = (FrameUnwindOffset, Reloc);
|
||||
|
||||
@ -75,15 +74,8 @@ fn return_address_reg(isa: &dyn TargetIsa) -> Register {
|
||||
X86_64::RA
|
||||
}
|
||||
|
||||
/// Map Cranelift registers to their corresponding Gimli registers.
|
||||
pub fn map_reg(
|
||||
isa: &dyn TargetIsa,
|
||||
reg: RegUnit,
|
||||
) -> core::result::Result<Register, RegisterMappingError> {
|
||||
if isa.name() != "x86" || isa.pointer_bits() != 64 {
|
||||
return Err(RegisterMappingError::UnsupportedArchitecture);
|
||||
}
|
||||
|
||||
fn map_reg(isa: &dyn TargetIsa, reg: RegUnit) -> Register {
|
||||
assert!(isa.name() == "x86" && isa.pointer_bits() == 64);
|
||||
// Mapping from https://github.com/bytecodealliance/cranelift/pull/902 by @iximeow
|
||||
const X86_GP_REG_MAP: [gimli::Register; 16] = [
|
||||
X86_64::RAX,
|
||||
@ -121,32 +113,21 @@ pub fn map_reg(
|
||||
X86_64::XMM14,
|
||||
X86_64::XMM15,
|
||||
];
|
||||
|
||||
let reg_info = isa.register_info();
|
||||
let bank = reg_info
|
||||
.bank_containing_regunit(reg)
|
||||
.ok_or_else(|| RegisterMappingError::MissingBank)?;
|
||||
let bank = reg_info.bank_containing_regunit(reg).unwrap();
|
||||
match bank.name {
|
||||
"IntRegs" => {
|
||||
// x86 GP registers have a weird mapping to DWARF registers, so we use a
|
||||
// lookup table.
|
||||
Ok(X86_GP_REG_MAP[(reg - bank.first_unit) as usize])
|
||||
X86_GP_REG_MAP[(reg - bank.first_unit) as usize]
|
||||
}
|
||||
"FloatRegs" => X86_XMM_REG_MAP[(reg - bank.first_unit) as usize],
|
||||
_ => {
|
||||
panic!("unsupported register bank: {}", bank.name);
|
||||
}
|
||||
"FloatRegs" => Ok(X86_XMM_REG_MAP[(reg - bank.first_unit) as usize]),
|
||||
_ => Err(RegisterMappingError::UnsupportedRegisterBank(bank.name)),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum RegisterMappingError {
|
||||
#[error("unable to find bank for register info")]
|
||||
MissingBank,
|
||||
#[error("register mapping is currently only implemented for x86_64")]
|
||||
UnsupportedArchitecture,
|
||||
#[error("unsupported register bank: {0}")]
|
||||
UnsupportedRegisterBank(&'static str),
|
||||
}
|
||||
|
||||
fn to_cfi(
|
||||
isa: &dyn TargetIsa,
|
||||
change: &FrameLayoutChange,
|
||||
@ -155,7 +136,7 @@ fn to_cfi(
|
||||
) -> Option<CallFrameInstruction> {
|
||||
Some(match change {
|
||||
FrameLayoutChange::CallFrameAddressAt { reg, offset } => {
|
||||
let mapped = map_reg(isa, *reg).expect("a register mapping from cranelift to gimli");
|
||||
let mapped = map_reg(isa, *reg);
|
||||
let offset = (*offset) as i32;
|
||||
if mapped != *cfa_def_reg && offset != *cfa_def_offset {
|
||||
*cfa_def_reg = mapped;
|
||||
@ -174,7 +155,7 @@ fn to_cfi(
|
||||
FrameLayoutChange::RegAt { reg, cfa_offset } => {
|
||||
assert!(cfa_offset % -8 == 0);
|
||||
let cfa_offset = *cfa_offset as i32;
|
||||
let mapped = map_reg(isa, *reg).expect("a register mapping from cranelift to gimli");
|
||||
let mapped = map_reg(isa, *reg);
|
||||
CallFrameInstruction::Offset(mapped, cfa_offset)
|
||||
}
|
||||
FrameLayoutChange::ReturnAddressAt { cfa_offset } => {
|
||||
|
@ -10,9 +10,6 @@ pub mod settings;
|
||||
#[cfg(feature = "unwind")]
|
||||
mod unwind;
|
||||
|
||||
#[cfg(feature = "unwind")]
|
||||
pub use fde::map_reg;
|
||||
|
||||
use super::super::settings as shared_settings;
|
||||
#[cfg(feature = "testing_hooks")]
|
||||
use crate::binemit::CodeSink;
|
||||
|
@ -902,8 +902,8 @@ fn branch_order(pos: &mut FuncCursor, cfg: &mut ControlFlowGraph, block: Block,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let cond_args = cond_inst_args.as_slice(&pos.func.dfg.value_lists).to_vec();
|
||||
let term_args = term_inst_args.as_slice(&pos.func.dfg.value_lists).to_vec();
|
||||
let cond_args = { cond_inst_args.as_slice(&pos.func.dfg.value_lists).to_vec() };
|
||||
let term_args = { term_inst_args.as_slice(&pos.func.dfg.value_lists).to_vec() };
|
||||
|
||||
match kind {
|
||||
BranchOrderKind::BrnzToBrz(cond_arg) => {
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"b598da46e55aafd9d05c0d90bda8819edcb593141d1992c21b44639910d12981","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"69d539b72460c0aba1d30e0b72efb0c29d61558574d751c784794e14abf41352","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"f6d738a46f1dca8b0c82a5910d86cd572a3585ab7ef9f73dac96962529069190","src/list.rs":"4bf609eb7cc7c000c18da746596d5fcc67eece3f919ee2d76e19f6ac371640d1","src/map.rs":"546b36be4cbbd2423bacbed69cbe114c63538c3f635e15284ab8e4223e717705","src/packed_option.rs":"dccb3dd6fc87eba0101de56417f21cab67a4394831df9fa41e3bbddb70cdf694","src/primary.rs":"30d5e2ab8427fd2b2c29da395812766049e3c40845cc887af3ee233dba91a063","src/set.rs":"b040054b8baa0599e64df9ee841640688e2a73b6eabbdc5a4f15334412db052a","src/sparse.rs":"536e31fdcf64450526f5e5b85e97406c26b998bc7e0d8161b6b449c24265449f"},"package":null}
|
||||
{"files":{"Cargo.toml":"0a7762f80abf6e2dbe73b7020fdbea138e6dab10809b15dc6a08249d58c3c422","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"69d539b72460c0aba1d30e0b72efb0c29d61558574d751c784794e14abf41352","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"f6d738a46f1dca8b0c82a5910d86cd572a3585ab7ef9f73dac96962529069190","src/list.rs":"4bf609eb7cc7c000c18da746596d5fcc67eece3f919ee2d76e19f6ac371640d1","src/map.rs":"546b36be4cbbd2423bacbed69cbe114c63538c3f635e15284ab8e4223e717705","src/packed_option.rs":"dccb3dd6fc87eba0101de56417f21cab67a4394831df9fa41e3bbddb70cdf694","src/primary.rs":"30d5e2ab8427fd2b2c29da395812766049e3c40845cc887af3ee233dba91a063","src/set.rs":"b040054b8baa0599e64df9ee841640688e2a73b6eabbdc5a4f15334412db052a","src/sparse.rs":"536e31fdcf64450526f5e5b85e97406c26b998bc7e0d8161b6b449c24265449f"},"package":null}
|
2
third_party/rust/cranelift-entity/Cargo.toml
vendored
2
third_party/rust/cranelift-entity/Cargo.toml
vendored
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
name = "cranelift-entity"
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
description = "Data structures using entity references as mapping keys"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
documentation = "https://docs.rs/cranelift-entity"
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"0773fd1bf0dd78967f755538d2c62279eae3ce4bc442e2a21b953d9ab039d0b9","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"579d9821aec76570b774c572e2ae0c1b8bc78f112ef2a83027051217f6bb31e4","src/lib.rs":"5197f467d1625ee2b117a168f4b1886b4b69d4250faea6618360a5adc70b4e0c","src/ssa.rs":"0cd620e4d9fbc5e249b782d8d22e8d112a70c0700b5dd312c92ef47a5c5280da","src/switch.rs":"6b7f97799e251f2b4ae6a9892fb911375e2dc9faa5d53ff93ba08988141f1f5b","src/variable.rs":"399437bd7d2ac11a7a748bad7dd1f6dac58824d374ec318f36367a9d077cc225"},"package":null}
|
||||
{"files":{"Cargo.toml":"569136ca3728e465c6ea2d3e5d40226a6518566e17293d2e6f6194593ae3d783","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"af0955c23a5462cc6d4a94c61ac1af5b7546a3d560e91d448452fe5c454d5da6","src/lib.rs":"5197f467d1625ee2b117a168f4b1886b4b69d4250faea6618360a5adc70b4e0c","src/ssa.rs":"339421ee9427ee7017939ca53b7b357f82af79c8a929aeb26fb6165b95f47e93","src/switch.rs":"6b7f97799e251f2b4ae6a9892fb911375e2dc9faa5d53ff93ba08988141f1f5b","src/variable.rs":"399437bd7d2ac11a7a748bad7dd1f6dac58824d374ec318f36367a9d077cc225"},"package":null}
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
description = "Cranelift IR builder helper"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
documentation = "https://docs.rs/cranelift-frontend"
|
||||
@ -11,7 +11,7 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { path = "../codegen", version = "0.62.0", default-features = false }
|
||||
cranelift-codegen = { path = "../codegen", version = "0.60.0", default-features = false }
|
||||
target-lexicon = "0.10"
|
||||
log = { version = "0.4.6", default-features = false }
|
||||
hashbrown = { version = "0.7", optional = true }
|
||||
|
@ -1229,53 +1229,6 @@ block0:
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn undef_vector_vars() {
|
||||
let mut sig = Signature::new(CallConv::SystemV);
|
||||
sig.returns.push(AbiParam::new(I8X16));
|
||||
sig.returns.push(AbiParam::new(B8X16));
|
||||
sig.returns.push(AbiParam::new(F32X4));
|
||||
|
||||
let mut fn_ctx = FunctionBuilderContext::new();
|
||||
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
|
||||
{
|
||||
let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
|
||||
|
||||
let block0 = builder.create_block();
|
||||
let a = Variable::new(0);
|
||||
let b = Variable::new(1);
|
||||
let c = Variable::new(2);
|
||||
builder.declare_var(a, I8X16);
|
||||
builder.declare_var(b, B8X16);
|
||||
builder.declare_var(c, F32X4);
|
||||
builder.switch_to_block(block0);
|
||||
|
||||
let a = builder.use_var(a);
|
||||
let b = builder.use_var(b);
|
||||
let c = builder.use_var(c);
|
||||
builder.ins().return_(&[a, b, c]);
|
||||
|
||||
builder.seal_all_blocks();
|
||||
builder.finalize();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
func.display(None).to_string(),
|
||||
"function %sample() -> i8x16, b8x16, f32x4 system_v {
|
||||
block0:
|
||||
v5 = f32const 0.0
|
||||
v6 = splat.f32x4 v5
|
||||
v2 -> v6
|
||||
v4 = vconst.b8x16 0x00
|
||||
v1 -> v4
|
||||
v3 = vconst.i8x16 0x00
|
||||
v0 -> v3
|
||||
return v0, v1, v2
|
||||
}
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_greatest_divisible_power_of_two() {
|
||||
assert_eq!(64, greatest_divisible_power_of_two(64));
|
||||
|
12
third_party/rust/cranelift-frontend/src/ssa.rs
vendored
12
third_party/rust/cranelift-frontend/src/ssa.rs
vendored
@ -9,7 +9,6 @@
|
||||
|
||||
use crate::Variable;
|
||||
use alloc::vec::Vec;
|
||||
use core::convert::TryInto;
|
||||
use core::mem;
|
||||
use cranelift_codegen::cursor::{Cursor, FuncCursor};
|
||||
use cranelift_codegen::entity::SecondaryMap;
|
||||
@ -186,13 +185,10 @@ fn emit_zero(ty: Type, mut cur: FuncCursor) -> Value {
|
||||
cur.ins().null(ty)
|
||||
} else if ty.is_vector() {
|
||||
let scalar_ty = ty.lane_type();
|
||||
if scalar_ty.is_int() || scalar_ty.is_bool() {
|
||||
let zero = cur.func.dfg.constants.insert(
|
||||
core::iter::repeat(0)
|
||||
.take(ty.bytes().try_into().unwrap())
|
||||
.collect(),
|
||||
);
|
||||
cur.ins().vconst(ty, zero)
|
||||
if scalar_ty.is_int() {
|
||||
cur.ins().iconst(ty, 0)
|
||||
} else if scalar_ty.is_bool() {
|
||||
cur.ins().bconst(ty, false)
|
||||
} else if scalar_ty == F32 {
|
||||
let scalar = cur.ins().f32const(Ieee32::with_bits(0));
|
||||
cur.ins().splat(ty, scalar)
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"e927f5353af12ad52c5eb349db2a62c275ec49616c7109553258d367d8118ee1","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"cce724251d4abc08c6492e1e25c138ab5a0d11e9ac90bc573652b18e034f56ed","src/code_translator.rs":"575fe0fe427dcc5405faf449924fe457cd8a938f86d6fd853e1536427a096dfd","src/environ/dummy.rs":"49bce7a8eb9f21a61c12db537b51ab6bdb3d0e1eb6253084268256d96cae68a5","src/environ/mod.rs":"b6f33f619090ff497b4e22150d77a290f259716374ac2e377b73c47cd1dafe85","src/environ/spec.rs":"3a1543f99bff340c7f6bbe3f7cb8e8ec829e4139957f3c578d5b03e29df50f9e","src/func_translator.rs":"a165063eafedbb8e6b632996f747eeb49a3d6f8a70cab6d741abfc4fd9af892d","src/lib.rs":"05b9994c062faf2065046d1e4d7caffb26823816f367d77ede6918e24fcfa6b0","src/module_translator.rs":"bcdf5a84226b726a73f4be0acb0318ca89c82584460101378e73021d85bd4485","src/sections_translator.rs":"8c4c24308332c63d16fcf19693a7ecff2239e73b4752b0d3830b273fabcee9f1","src/state/func_state.rs":"b114522784984a7cc26a3549c7c17f842885e1232254de81d938f9d155f95aa6","src/state/mod.rs":"20014cb93615467b4d20321b52f67f66040417efcaa739a4804093bb559eed19","src/state/module_state.rs":"2f299b043deb806b48583fe54bbb46708f7d8a1454b7be0eb285568064e5a7f9","src/translation_utils.rs":"cd3ab5f994e02d49baa47148b66599d37f8156cd657b61ae68aefefa32a9d806","tests/wasm_testsuite.rs":"730304f139371e5ef3fd913ec271fc4db181869b447c6ed26c54313b5c31495c"},"package":null}
|
||||
{"files":{"Cargo.toml":"fbabc7ff07bf6a0c7c4ea8b723ae2eb86ee78ce51aa37c41201b98d0064b7db2","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"cce724251d4abc08c6492e1e25c138ab5a0d11e9ac90bc573652b18e034f56ed","src/code_translator.rs":"984f937da07895b5a34106d78762c937879174c9c88105addbc68799211f6a34","src/environ/dummy.rs":"49bce7a8eb9f21a61c12db537b51ab6bdb3d0e1eb6253084268256d96cae68a5","src/environ/mod.rs":"b6f33f619090ff497b4e22150d77a290f259716374ac2e377b73c47cd1dafe85","src/environ/spec.rs":"3a1543f99bff340c7f6bbe3f7cb8e8ec829e4139957f3c578d5b03e29df50f9e","src/func_translator.rs":"a165063eafedbb8e6b632996f747eeb49a3d6f8a70cab6d741abfc4fd9af892d","src/lib.rs":"05b9994c062faf2065046d1e4d7caffb26823816f367d77ede6918e24fcfa6b0","src/module_translator.rs":"bcdf5a84226b726a73f4be0acb0318ca89c82584460101378e73021d85bd4485","src/sections_translator.rs":"8c4c24308332c63d16fcf19693a7ecff2239e73b4752b0d3830b273fabcee9f1","src/state/func_state.rs":"b114522784984a7cc26a3549c7c17f842885e1232254de81d938f9d155f95aa6","src/state/mod.rs":"20014cb93615467b4d20321b52f67f66040417efcaa739a4804093bb559eed19","src/state/module_state.rs":"2f299b043deb806b48583fe54bbb46708f7d8a1454b7be0eb285568064e5a7f9","src/translation_utils.rs":"cd3ab5f994e02d49baa47148b66599d37f8156cd657b61ae68aefefa32a9d806","tests/wasm_testsuite.rs":"730304f139371e5ef3fd913ec271fc4db181869b447c6ed26c54313b5c31495c"},"package":null}
|
9
third_party/rust/cranelift-wasm/Cargo.toml
vendored
9
third_party/rust/cranelift-wasm/Cargo.toml
vendored
@ -1,9 +1,8 @@
|
||||
[package]
|
||||
name = "cranelift-wasm"
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "Translator from WebAssembly to Cranelift IR"
|
||||
documentation = "https://docs.rs/cranelift-wasm"
|
||||
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
categories = ["no-std", "wasm"]
|
||||
@ -13,9 +12,9 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmparser = { version = "0.51.0", default-features = false }
|
||||
cranelift-codegen = { path = "../codegen", version = "0.62.0", default-features = false }
|
||||
cranelift-entity = { path = "../entity", version = "0.62.0" }
|
||||
cranelift-frontend = { path = "../frontend", version = "0.62.0", default-features = false }
|
||||
cranelift-codegen = { path = "../codegen", version = "0.60.0", default-features = false }
|
||||
cranelift-entity = { path = "../entity", version = "0.60.0" }
|
||||
cranelift-frontend = { path = "../frontend", version = "0.60.0", default-features = false }
|
||||
hashbrown = { version = "0.7", optional = true }
|
||||
log = { version = "0.4.6", default-features = false }
|
||||
serde = { version = "1.0.94", features = ["derive"], optional = true }
|
||||
|
@ -32,7 +32,6 @@ use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureInd
|
||||
use crate::wasm_unsupported;
|
||||
use core::{i32, u32};
|
||||
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
use cranelift_codegen::ir::types::*;
|
||||
use cranelift_codegen::ir::{
|
||||
self, ConstantData, InstBuilder, JumpTableData, MemFlags, Value, ValueLabel,
|
||||
@ -652,48 +651,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
} => {
|
||||
translate_load(*offset, ir::Opcode::Load, I8X16, builder, state, environ)?;
|
||||
}
|
||||
Operator::I16x8Load8x8S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
let (flags, base, offset) = prepare_load(*offset, builder, state, environ)?;
|
||||
let loaded = builder.ins().sload8x8(flags, base, offset);
|
||||
state.push1(loaded);
|
||||
}
|
||||
Operator::I16x8Load8x8U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
let (flags, base, offset) = prepare_load(*offset, builder, state, environ)?;
|
||||
let loaded = builder.ins().uload8x8(flags, base, offset);
|
||||
state.push1(loaded);
|
||||
}
|
||||
Operator::I32x4Load16x4S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
let (flags, base, offset) = prepare_load(*offset, builder, state, environ)?;
|
||||
let loaded = builder.ins().sload16x4(flags, base, offset);
|
||||
state.push1(loaded);
|
||||
}
|
||||
Operator::I32x4Load16x4U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
let (flags, base, offset) = prepare_load(*offset, builder, state, environ)?;
|
||||
let loaded = builder.ins().uload16x4(flags, base, offset);
|
||||
state.push1(loaded);
|
||||
}
|
||||
Operator::I64x2Load32x2S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
let (flags, base, offset) = prepare_load(*offset, builder, state, environ)?;
|
||||
let loaded = builder.ins().sload32x2(flags, base, offset);
|
||||
state.push1(loaded);
|
||||
}
|
||||
Operator::I64x2Load32x2U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
let (flags, base, offset) = prepare_load(*offset, builder, state, environ)?;
|
||||
let loaded = builder.ins().uload32x2(flags, base, offset);
|
||||
state.push1(loaded);
|
||||
}
|
||||
/****************************** Store instructions ***********************************
|
||||
* Wasm specifies an integer alignment flag but we drop it in Cranelift.
|
||||
* The memory base address is provided by the environment.
|
||||
@ -1561,7 +1518,13 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
| Operator::I32x4WidenLowI16x8S { .. }
|
||||
| Operator::I32x4WidenHighI16x8S { .. }
|
||||
| Operator::I32x4WidenLowI16x8U { .. }
|
||||
| Operator::I32x4WidenHighI16x8U { .. } => {
|
||||
| Operator::I32x4WidenHighI16x8U { .. }
|
||||
| Operator::I16x8Load8x8S { .. }
|
||||
| Operator::I16x8Load8x8U { .. }
|
||||
| Operator::I32x4Load16x4S { .. }
|
||||
| Operator::I32x4Load16x4U { .. }
|
||||
| Operator::I64x2Load32x2S { .. }
|
||||
| Operator::I64x2Load32x2U { .. } => {
|
||||
return Err(wasm_unsupported!("proposed SIMD operator {:?}", op));
|
||||
}
|
||||
};
|
||||
@ -1733,27 +1696,6 @@ fn get_heap_addr(
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare for a load; factors out common functionality between load and load_extend operations.
|
||||
fn prepare_load<FE: FuncEnvironment + ?Sized>(
|
||||
offset: u32,
|
||||
builder: &mut FunctionBuilder,
|
||||
state: &mut FuncTranslationState,
|
||||
environ: &mut FE,
|
||||
) -> WasmResult<(MemFlags, Value, Offset32)> {
|
||||
let addr32 = state.pop1();
|
||||
|
||||
// We don't yet support multiple linear memories.
|
||||
let heap = state.get_heap(builder.func, 0, environ)?;
|
||||
let (base, offset) = get_heap_addr(heap, addr32, offset, environ.pointer_type(), builder);
|
||||
|
||||
// Note that we don't set `is_aligned` here, even if the load instruction's
|
||||
// alignment immediate says it's aligned, because WebAssembly's immediate
|
||||
// field is just a hint, while Cranelift's aligned flag needs a guarantee.
|
||||
let flags = MemFlags::new();
|
||||
|
||||
Ok((flags, base, offset.into()))
|
||||
}
|
||||
|
||||
/// Translate a load instruction.
|
||||
fn translate_load<FE: FuncEnvironment + ?Sized>(
|
||||
offset: u32,
|
||||
@ -1763,8 +1705,17 @@ fn translate_load<FE: FuncEnvironment + ?Sized>(
|
||||
state: &mut FuncTranslationState,
|
||||
environ: &mut FE,
|
||||
) -> WasmResult<()> {
|
||||
let (flags, base, offset) = prepare_load(offset, builder, state, environ)?;
|
||||
let (load, dfg) = builder.ins().Load(opcode, result_ty, flags, offset, base);
|
||||
let addr32 = state.pop1();
|
||||
// We don't yet support multiple linear memories.
|
||||
let heap = state.get_heap(builder.func, 0, environ)?;
|
||||
let (base, offset) = get_heap_addr(heap, addr32, offset, environ.pointer_type(), builder);
|
||||
// Note that we don't set `is_aligned` here, even if the load instruction's
|
||||
// alignment immediate says it's aligned, because WebAssembly's immediate
|
||||
// field is just a hint, while Cranelift's aligned flag needs a guarantee.
|
||||
let flags = MemFlags::new();
|
||||
let (load, dfg) = builder
|
||||
.ins()
|
||||
.Load(opcode, result_ty, flags, offset.into(), base);
|
||||
state.push1(dfg.first_result(load));
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user