mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
commit
ff642e0697
46
Cargo.lock
generated
46
Cargo.lock
generated
@ -166,8 +166,8 @@ name = "baldrdash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen 0.43.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-wasm 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -490,20 +490,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-bforest 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen-meta 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-bforest 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen-meta 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -512,36 +512,36 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-codegen 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-wasm"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-frontend 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-frontend 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3351,12 +3351,12 @@ dependencies = [
|
||||
"checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
|
||||
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
|
||||
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
|
||||
"checksum cranelift-bforest 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c88db0c2fc38b2cedee1b94ee2dc7bf80e4ce31467c8005743f485af66e240d8"
|
||||
"checksum cranelift-codegen 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce2e412970cfda0fa11806758d79a46c02b8fa1b91c35a8d3e2b4c947ce0c35"
|
||||
"checksum cranelift-codegen-meta 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43131e662da7e0243cff28edfbc094a62968a4b57849f77a6c1e3685e9e6e1e6"
|
||||
"checksum cranelift-entity 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4ccc3743848cbb53e58b62685703dc12ea553c3bc8f21db76f23c68054eb69a"
|
||||
"checksum cranelift-frontend 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89ecc8b49d4ab98f2c121832fee365da88b7b0ffad77d4e328015b1fd1f7f4b1"
|
||||
"checksum cranelift-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7eccd196ecd01a2394ce05e2259afe5704874816b058541c7cce7794f0e835e"
|
||||
"checksum cranelift-bforest 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3a25dfe4a54449df63d592f2f6346a80350ac835d4be4bacb73c20b034ef763"
|
||||
"checksum cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c3b15a20577e6c823475953a5e25e758d9d3a3148a937d686c09460e5f2f4a0"
|
||||
"checksum cranelift-codegen-meta 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e60ce3551e8172c966fbc6d9bfb90111d5d1cf37306c37dd7527467afe317d1"
|
||||
"checksum cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e124e09cb7dc85fbe2162420aebbe8e9e3b8f9210901be7867416c5beec8226"
|
||||
"checksum cranelift-frontend 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2833c6e1a93c524ce0c2ab31266cdc84d38c906349f79f19378a5e5995727b23"
|
||||
"checksum cranelift-wasm 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e75efb45cd8d8700b4bdc225f0077bc7c615f84a5807ce001d59b4da48d85573"
|
||||
"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
"checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
|
||||
|
@ -8,7 +8,7 @@ support-files =
|
||||
offline/manifest.appcache
|
||||
|
||||
[browser_clearSiteData.js]
|
||||
skip-if = os == 'mac' && !debug # bug 1436395
|
||||
skip-if = true # bug 1436395
|
||||
[browser_siteData.js]
|
||||
skip-if = (os == 'linux') || (os == 'mac' && !debug) || verify # Bug 1439332, Bug 1436395, Bug 1415037
|
||||
[browser_siteData2.js]
|
||||
|
@ -48,6 +48,7 @@ async function testSteps() {
|
||||
|
||||
for (let i = 0; i < data.urlCount; i++) {
|
||||
storages[i].setItem(data.key, data.value);
|
||||
await returnToEventLoop();
|
||||
}
|
||||
|
||||
info("Verifying no more data can be written");
|
||||
|
@ -244,7 +244,10 @@ for (let op of undefinedOpcodes) {
|
||||
// Prefixed opcodes
|
||||
|
||||
function checkIllegalPrefixed(prefix, opcode) {
|
||||
let binary = moduleWithSections([v2vSigSection, declSection([0]), bodySection([funcBody({locals:[], body:[prefix, opcode]})])]);
|
||||
let binary = moduleWithSections([v2vSigSection,
|
||||
declSection([0]),
|
||||
bodySection([funcBody({locals:[],
|
||||
body:[prefix, ...varU32(opcode)]})])]);
|
||||
assertErrorMessage(() => wasmEval(binary), CompileError, /unrecognized opcode/);
|
||||
assertEq(WebAssembly.validate(binary), false);
|
||||
}
|
||||
|
@ -11436,21 +11436,21 @@ bool BaseCompiler::emitBody() {
|
||||
// "Miscellaneous" operations
|
||||
case uint16_t(Op::MiscPrefix): {
|
||||
switch (op.b1) {
|
||||
case uint16_t(MiscOp::I32TruncSSatF32):
|
||||
case uint32_t(MiscOp::I32TruncSSatF32):
|
||||
CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI32<TRUNC_SATURATING>,
|
||||
ValType::F32, ValType::I32));
|
||||
case uint16_t(MiscOp::I32TruncUSatF32):
|
||||
case uint32_t(MiscOp::I32TruncUSatF32):
|
||||
CHECK_NEXT(emitConversionOOM(
|
||||
emitTruncateF32ToI32<TRUNC_UNSIGNED | TRUNC_SATURATING>,
|
||||
ValType::F32, ValType::I32));
|
||||
case uint16_t(MiscOp::I32TruncSSatF64):
|
||||
case uint32_t(MiscOp::I32TruncSSatF64):
|
||||
CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI32<TRUNC_SATURATING>,
|
||||
ValType::F64, ValType::I32));
|
||||
case uint16_t(MiscOp::I32TruncUSatF64):
|
||||
case uint32_t(MiscOp::I32TruncUSatF64):
|
||||
CHECK_NEXT(emitConversionOOM(
|
||||
emitTruncateF64ToI32<TRUNC_UNSIGNED | TRUNC_SATURATING>,
|
||||
ValType::F64, ValType::I32));
|
||||
case uint16_t(MiscOp::I64TruncSSatF32):
|
||||
case uint32_t(MiscOp::I64TruncSSatF32):
|
||||
#ifdef RABALDR_FLOAT_TO_I64_CALLOUT
|
||||
CHECK_NEXT(emitCalloutConversionOOM(
|
||||
emitConvertFloatingToInt64Callout,
|
||||
@ -11460,7 +11460,7 @@ bool BaseCompiler::emitBody() {
|
||||
CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI64<TRUNC_SATURATING>,
|
||||
ValType::F32, ValType::I64));
|
||||
#endif
|
||||
case uint16_t(MiscOp::I64TruncUSatF32):
|
||||
case uint32_t(MiscOp::I64TruncUSatF32):
|
||||
#ifdef RABALDR_FLOAT_TO_I64_CALLOUT
|
||||
CHECK_NEXT(emitCalloutConversionOOM(
|
||||
emitConvertFloatingToInt64Callout,
|
||||
@ -11471,7 +11471,7 @@ bool BaseCompiler::emitBody() {
|
||||
emitTruncateF32ToI64<TRUNC_UNSIGNED | TRUNC_SATURATING>,
|
||||
ValType::F32, ValType::I64));
|
||||
#endif
|
||||
case uint16_t(MiscOp::I64TruncSSatF64):
|
||||
case uint32_t(MiscOp::I64TruncSSatF64):
|
||||
#ifdef RABALDR_FLOAT_TO_I64_CALLOUT
|
||||
CHECK_NEXT(emitCalloutConversionOOM(
|
||||
emitConvertFloatingToInt64Callout,
|
||||
@ -11481,7 +11481,7 @@ bool BaseCompiler::emitBody() {
|
||||
CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI64<TRUNC_SATURATING>,
|
||||
ValType::F64, ValType::I64));
|
||||
#endif
|
||||
case uint16_t(MiscOp::I64TruncUSatF64):
|
||||
case uint32_t(MiscOp::I64TruncUSatF64):
|
||||
#ifdef RABALDR_FLOAT_TO_I64_CALLOUT
|
||||
CHECK_NEXT(emitCalloutConversionOOM(
|
||||
emitConvertFloatingToInt64Callout,
|
||||
@ -11493,44 +11493,44 @@ bool BaseCompiler::emitBody() {
|
||||
ValType::F64, ValType::I64));
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case uint16_t(MiscOp::MemCopy):
|
||||
case uint32_t(MiscOp::MemCopy):
|
||||
CHECK_NEXT(emitMemOrTableCopy(/*isMem=*/true));
|
||||
case uint16_t(MiscOp::DataDrop):
|
||||
case uint32_t(MiscOp::DataDrop):
|
||||
CHECK_NEXT(emitDataOrElemDrop(/*isData=*/true));
|
||||
case uint16_t(MiscOp::MemFill):
|
||||
case uint32_t(MiscOp::MemFill):
|
||||
CHECK_NEXT(emitMemFill());
|
||||
case uint16_t(MiscOp::MemInit):
|
||||
case uint32_t(MiscOp::MemInit):
|
||||
CHECK_NEXT(emitMemOrTableInit(/*isMem=*/true));
|
||||
case uint16_t(MiscOp::TableCopy):
|
||||
case uint32_t(MiscOp::TableCopy):
|
||||
CHECK_NEXT(emitMemOrTableCopy(/*isMem=*/false));
|
||||
case uint16_t(MiscOp::ElemDrop):
|
||||
case uint32_t(MiscOp::ElemDrop):
|
||||
CHECK_NEXT(emitDataOrElemDrop(/*isData=*/false));
|
||||
case uint16_t(MiscOp::TableInit):
|
||||
case uint32_t(MiscOp::TableInit):
|
||||
CHECK_NEXT(emitMemOrTableInit(/*isMem=*/false));
|
||||
#endif // ENABLE_WASM_BULKMEM_OPS
|
||||
#ifdef ENABLE_WASM_REFTYPES
|
||||
case uint16_t(MiscOp::TableGrow):
|
||||
case uint32_t(MiscOp::TableGrow):
|
||||
CHECK_NEXT(emitTableGrow());
|
||||
case uint16_t(MiscOp::TableSize):
|
||||
case uint32_t(MiscOp::TableSize):
|
||||
CHECK_NEXT(emitTableSize());
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GC
|
||||
case uint16_t(MiscOp::StructNew):
|
||||
case uint32_t(MiscOp::StructNew):
|
||||
if (!env_.gcTypesEnabled()) {
|
||||
return iter_.unrecognizedOpcode(&op);
|
||||
}
|
||||
CHECK_NEXT(emitStructNew());
|
||||
case uint16_t(MiscOp::StructGet):
|
||||
case uint32_t(MiscOp::StructGet):
|
||||
if (!env_.gcTypesEnabled()) {
|
||||
return iter_.unrecognizedOpcode(&op);
|
||||
}
|
||||
CHECK_NEXT(emitStructGet());
|
||||
case uint16_t(MiscOp::StructSet):
|
||||
case uint32_t(MiscOp::StructSet):
|
||||
if (!env_.gcTypesEnabled()) {
|
||||
return iter_.unrecognizedOpcode(&op);
|
||||
}
|
||||
CHECK_NEXT(emitStructSet());
|
||||
case uint16_t(MiscOp::StructNarrow):
|
||||
case uint32_t(MiscOp::StructNarrow):
|
||||
if (!env_.gcTypesEnabled()) {
|
||||
return iter_.unrecognizedOpcode(&op);
|
||||
}
|
||||
@ -11545,182 +11545,182 @@ bool BaseCompiler::emitBody() {
|
||||
// Thread operations
|
||||
case uint16_t(Op::ThreadPrefix): {
|
||||
switch (op.b1) {
|
||||
case uint16_t(ThreadOp::Wake):
|
||||
case uint32_t(ThreadOp::Wake):
|
||||
CHECK_NEXT(emitWake());
|
||||
|
||||
case uint16_t(ThreadOp::I32Wait):
|
||||
case uint32_t(ThreadOp::I32Wait):
|
||||
CHECK_NEXT(emitWait(ValType::I32, 4));
|
||||
case uint16_t(ThreadOp::I64Wait):
|
||||
case uint32_t(ThreadOp::I64Wait):
|
||||
CHECK_NEXT(emitWait(ValType::I64, 8));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicLoad):
|
||||
case uint32_t(ThreadOp::I32AtomicLoad):
|
||||
CHECK_NEXT(emitAtomicLoad(ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad):
|
||||
CHECK_NEXT(emitAtomicLoad(ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicLoad8U):
|
||||
case uint32_t(ThreadOp::I32AtomicLoad8U):
|
||||
CHECK_NEXT(emitAtomicLoad(ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicLoad16U):
|
||||
case uint32_t(ThreadOp::I32AtomicLoad16U):
|
||||
CHECK_NEXT(emitAtomicLoad(ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad8U):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad8U):
|
||||
CHECK_NEXT(emitAtomicLoad(ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad16U):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad16U):
|
||||
CHECK_NEXT(emitAtomicLoad(ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad32U):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad32U):
|
||||
CHECK_NEXT(emitAtomicLoad(ValType::I64, Scalar::Uint32));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicStore):
|
||||
case uint32_t(ThreadOp::I32AtomicStore):
|
||||
CHECK_NEXT(emitAtomicStore(ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicStore):
|
||||
case uint32_t(ThreadOp::I64AtomicStore):
|
||||
CHECK_NEXT(emitAtomicStore(ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicStore8U):
|
||||
case uint32_t(ThreadOp::I32AtomicStore8U):
|
||||
CHECK_NEXT(emitAtomicStore(ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicStore16U):
|
||||
case uint32_t(ThreadOp::I32AtomicStore16U):
|
||||
CHECK_NEXT(emitAtomicStore(ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicStore8U):
|
||||
case uint32_t(ThreadOp::I64AtomicStore8U):
|
||||
CHECK_NEXT(emitAtomicStore(ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicStore16U):
|
||||
case uint32_t(ThreadOp::I64AtomicStore16U):
|
||||
CHECK_NEXT(emitAtomicStore(ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicStore32U):
|
||||
case uint32_t(ThreadOp::I64AtomicStore32U):
|
||||
CHECK_NEXT(emitAtomicStore(ValType::I64, Scalar::Uint32));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicAdd):
|
||||
case uint32_t(ThreadOp::I32AtomicAdd):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAdd8U):
|
||||
case uint32_t(ThreadOp::I32AtomicAdd8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAdd16U):
|
||||
case uint32_t(ThreadOp::I32AtomicAdd16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd8U):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd16U):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd32U):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd32U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicFetchAddOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicSub):
|
||||
case uint32_t(ThreadOp::I32AtomicSub):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub):
|
||||
case uint32_t(ThreadOp::I64AtomicSub):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I32AtomicSub8U):
|
||||
case uint32_t(ThreadOp::I32AtomicSub8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I32AtomicSub16U):
|
||||
case uint32_t(ThreadOp::I32AtomicSub16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub8U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub16U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub32U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub32U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicFetchSubOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicAnd):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAnd8U):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAnd16U):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd8U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd16U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd32U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd32U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicFetchAndOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicOr):
|
||||
case uint32_t(ThreadOp::I32AtomicOr):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr):
|
||||
case uint32_t(ThreadOp::I64AtomicOr):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I32AtomicOr8U):
|
||||
case uint32_t(ThreadOp::I32AtomicOr8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I32AtomicOr16U):
|
||||
case uint32_t(ThreadOp::I32AtomicOr16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr8U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr16U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr32U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr32U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicFetchOrOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicXor):
|
||||
case uint32_t(ThreadOp::I32AtomicXor):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor):
|
||||
case uint32_t(ThreadOp::I64AtomicXor):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I32AtomicXor8U):
|
||||
case uint32_t(ThreadOp::I32AtomicXor8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I32AtomicXor16U):
|
||||
case uint32_t(ThreadOp::I32AtomicXor16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor8U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor8U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor16U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor16U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor32U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor32U):
|
||||
CHECK_NEXT(
|
||||
emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicFetchXorOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicXchg):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg):
|
||||
CHECK_NEXT(emitAtomicXchg(ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg):
|
||||
CHECK_NEXT(emitAtomicXchg(ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicXchg8U):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg8U):
|
||||
CHECK_NEXT(emitAtomicXchg(ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicXchg16U):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg16U):
|
||||
CHECK_NEXT(emitAtomicXchg(ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg8U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg8U):
|
||||
CHECK_NEXT(emitAtomicXchg(ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg16U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg16U):
|
||||
CHECK_NEXT(emitAtomicXchg(ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg32U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg32U):
|
||||
CHECK_NEXT(emitAtomicXchg(ValType::I64, Scalar::Uint32));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg):
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg):
|
||||
CHECK_NEXT(emitAtomicCmpXchg(ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg):
|
||||
CHECK_NEXT(emitAtomicCmpXchg(ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg8U):
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg8U):
|
||||
CHECK_NEXT(emitAtomicCmpXchg(ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg16U):
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg16U):
|
||||
CHECK_NEXT(emitAtomicCmpXchg(ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg8U):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg8U):
|
||||
CHECK_NEXT(emitAtomicCmpXchg(ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg16U):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg16U):
|
||||
CHECK_NEXT(emitAtomicCmpXchg(ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg32U):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg32U):
|
||||
CHECK_NEXT(emitAtomicCmpXchg(ValType::I64, Scalar::Uint32));
|
||||
|
||||
default:
|
||||
|
@ -480,16 +480,6 @@ enum class ThreadOp {
|
||||
Limit
|
||||
};
|
||||
|
||||
// Opcodes from Bulk Memory Operations proposal as at 2 Feb 2018. Note,
|
||||
// the opcodes are not actually assigned in that proposal. This is just
|
||||
// an interim assignment.
|
||||
enum class CopyOrFillOp {
|
||||
Copy = 0x01,
|
||||
Fill = 0x02,
|
||||
|
||||
Limit
|
||||
};
|
||||
|
||||
enum class MozOp {
|
||||
// ------------------------------------------------------------------------
|
||||
// These operators are emitted internally when compiling asm.js and are
|
||||
@ -534,10 +524,11 @@ enum class MozOp {
|
||||
};
|
||||
|
||||
struct OpBytes {
|
||||
// The bytes of the opcode have 16-bit representations to allow for a full
|
||||
// b0 is a byte value but has a 16-bit representation to allow for a full
|
||||
// 256-value range plus a sentinel Limit value.
|
||||
uint16_t b0;
|
||||
uint16_t b1;
|
||||
// b1 is a LEB128 value but 32 bits is enough for now.
|
||||
uint32_t b1;
|
||||
|
||||
explicit OpBytes(Op x) {
|
||||
b0 = uint16_t(x);
|
||||
|
@ -70,6 +70,7 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
const CraneliftCompiledFunc& func,
|
||||
const FuncTypeIdDesc& funcTypeId,
|
||||
uint32_t lineOrBytecode,
|
||||
uint32_t funcBytecodeSize,
|
||||
FuncOffsets* offsets) {
|
||||
wasm::GenerateFunctionPrologue(masm, funcTypeId, mozilla::Nothing(), offsets);
|
||||
|
||||
@ -113,11 +114,19 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
CheckedInt<uint32_t> checkedBytecodeOffset = lineOrBytecode;
|
||||
checkedBytecodeOffset += metadata.srcLoc;
|
||||
MOZ_ASSERT(checkedBytecodeOffset.isValid());
|
||||
// Check code offsets.
|
||||
MOZ_ASSERT(offset.value() >= offsets->normalEntry);
|
||||
MOZ_ASSERT(offset.value() < offsets->ret);
|
||||
|
||||
// Check bytecode offsets.
|
||||
if (metadata.srcLoc > 0 && lineOrBytecode > 0) {
|
||||
MOZ_ASSERT(metadata.srcLoc >= lineOrBytecode);
|
||||
MOZ_ASSERT(metadata.srcLoc < lineOrBytecode + funcBytecodeSize);
|
||||
}
|
||||
#endif
|
||||
uint32_t bytecodeOffset = lineOrBytecode + metadata.srcLoc;
|
||||
// TODO(bug 1532716): Cranelift gives null bytecode offsets for symbolic
|
||||
// accesses.
|
||||
uint32_t bytecodeOffset = metadata.srcLoc ? metadata.srcLoc : lineOrBytecode;
|
||||
|
||||
switch (metadata.which) {
|
||||
case CraneliftMetadataEntry::Which::DirectCall: {
|
||||
@ -183,7 +192,9 @@ CraneliftFuncCompileInput::CraneliftFuncCompileInput(
|
||||
const FuncCompileInput& func)
|
||||
: bytecode(func.begin),
|
||||
bytecodeSize(func.end - func.begin),
|
||||
index(func.index) {}
|
||||
index(func.index),
|
||||
offset_in_module(func.lineOrBytecode)
|
||||
{}
|
||||
|
||||
#ifndef WASM_HUGE_MEMORY
|
||||
static_assert(offsetof(TlsData, boundsCheckLimit) == sizeof(size_t),
|
||||
@ -247,40 +258,42 @@ static size_t globalToTlsOffset(size_t globalOffset) {
|
||||
|
||||
CraneliftModuleEnvironment::CraneliftModuleEnvironment(
|
||||
const ModuleEnvironment& env)
|
||||
: env(env), min_memory_length(env.minMemoryLength) {}
|
||||
: env(&env),
|
||||
min_memory_length(env.minMemoryLength)
|
||||
{}
|
||||
|
||||
TypeCode env_unpack(BD_ValType valType) {
|
||||
return TypeCode(UnpackTypeCodeType(PackedTypeCode(valType.packed)));
|
||||
}
|
||||
|
||||
const FuncTypeWithId* env_function_signature(
|
||||
const CraneliftModuleEnvironment* env, size_t funcIndex) {
|
||||
return env->env.funcTypes[funcIndex];
|
||||
const CraneliftModuleEnvironment* wrapper, size_t funcIndex) {
|
||||
return wrapper->env->funcTypes[funcIndex];
|
||||
}
|
||||
|
||||
size_t env_func_import_tls_offset(const CraneliftModuleEnvironment* env,
|
||||
size_t env_func_import_tls_offset(const CraneliftModuleEnvironment* wrapper,
|
||||
size_t funcIndex) {
|
||||
return globalToTlsOffset(env->env.funcImportGlobalDataOffsets[funcIndex]);
|
||||
return globalToTlsOffset(wrapper->env->funcImportGlobalDataOffsets[funcIndex]);
|
||||
}
|
||||
|
||||
bool env_func_is_import(const CraneliftModuleEnvironment* env,
|
||||
bool env_func_is_import(const CraneliftModuleEnvironment* wrapper,
|
||||
size_t funcIndex) {
|
||||
return env->env.funcIsImport(funcIndex);
|
||||
return wrapper->env->funcIsImport(funcIndex);
|
||||
}
|
||||
|
||||
const FuncTypeWithId* env_signature(const CraneliftModuleEnvironment* env,
|
||||
const FuncTypeWithId* env_signature(const CraneliftModuleEnvironment* wrapper,
|
||||
size_t funcTypeIndex) {
|
||||
return &env->env.types[funcTypeIndex].funcType();
|
||||
return &wrapper->env->types[funcTypeIndex].funcType();
|
||||
}
|
||||
|
||||
const TableDesc* env_table(const CraneliftModuleEnvironment* env,
|
||||
const TableDesc* env_table(const CraneliftModuleEnvironment* wrapper,
|
||||
size_t tableIndex) {
|
||||
return &env->env.tables[tableIndex];
|
||||
return &wrapper->env->tables[tableIndex];
|
||||
}
|
||||
|
||||
const GlobalDesc* env_global(const CraneliftModuleEnvironment* env,
|
||||
const GlobalDesc* env_global(const CraneliftModuleEnvironment* wrapper,
|
||||
size_t globalIndex) {
|
||||
return &env->env.globals[globalIndex];
|
||||
return &wrapper->env->globals[globalIndex];
|
||||
}
|
||||
|
||||
bool wasm::CraneliftCompileFunctions(const ModuleEnvironment& env,
|
||||
@ -311,7 +324,9 @@ bool wasm::CraneliftCompileFunctions(const ModuleEnvironment& env,
|
||||
|
||||
for (const FuncCompileInput& func : inputs) {
|
||||
Decoder d(func.begin, func.end, func.lineOrBytecode, error);
|
||||
if (!ValidateFunctionBody(env, func.index, func.end - func.begin, d)) {
|
||||
|
||||
size_t funcBytecodeSize = func.end - func.begin;
|
||||
if (!ValidateFunctionBody(env, func.index, funcBytecodeSize, d)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -328,12 +343,11 @@ bool wasm::CraneliftCompileFunctions(const ModuleEnvironment& env,
|
||||
|
||||
FuncOffsets offsets;
|
||||
if (!GenerateCraneliftCode(masm, clifFunc, funcTypeId, lineOrBytecode,
|
||||
&offsets)) {
|
||||
funcBytecodeSize, &offsets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!code->codeRanges.emplaceBack(func.index, func.lineOrBytecode,
|
||||
offsets)) {
|
||||
if (!code->codeRanges.emplaceBack(func.index, lineOrBytecode, offsets)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3818,49 +3818,49 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
|
||||
// Miscellaneous operations
|
||||
case uint16_t(Op::MiscPrefix): {
|
||||
switch (op.b1) {
|
||||
case uint16_t(MiscOp::I32TruncSSatF32):
|
||||
case uint16_t(MiscOp::I32TruncUSatF32):
|
||||
case uint32_t(MiscOp::I32TruncSSatF32):
|
||||
case uint32_t(MiscOp::I32TruncUSatF32):
|
||||
CHECK(EmitTruncate(f, ValType::F32, ValType::I32,
|
||||
MiscOp(op.b1) == MiscOp::I32TruncUSatF32, true));
|
||||
case uint16_t(MiscOp::I32TruncSSatF64):
|
||||
case uint16_t(MiscOp::I32TruncUSatF64):
|
||||
case uint32_t(MiscOp::I32TruncSSatF64):
|
||||
case uint32_t(MiscOp::I32TruncUSatF64):
|
||||
CHECK(EmitTruncate(f, ValType::F64, ValType::I32,
|
||||
MiscOp(op.b1) == MiscOp::I32TruncUSatF64, true));
|
||||
case uint16_t(MiscOp::I64TruncSSatF32):
|
||||
case uint16_t(MiscOp::I64TruncUSatF32):
|
||||
case uint32_t(MiscOp::I64TruncSSatF32):
|
||||
case uint32_t(MiscOp::I64TruncUSatF32):
|
||||
CHECK(EmitTruncate(f, ValType::F32, ValType::I64,
|
||||
MiscOp(op.b1) == MiscOp::I64TruncUSatF32, true));
|
||||
case uint16_t(MiscOp::I64TruncSSatF64):
|
||||
case uint16_t(MiscOp::I64TruncUSatF64):
|
||||
case uint32_t(MiscOp::I64TruncSSatF64):
|
||||
case uint32_t(MiscOp::I64TruncUSatF64):
|
||||
CHECK(EmitTruncate(f, ValType::F64, ValType::I64,
|
||||
MiscOp(op.b1) == MiscOp::I64TruncUSatF64, true));
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case uint16_t(MiscOp::MemCopy):
|
||||
case uint32_t(MiscOp::MemCopy):
|
||||
CHECK(EmitMemOrTableCopy(f, /*isMem=*/true));
|
||||
case uint16_t(MiscOp::DataDrop):
|
||||
case uint32_t(MiscOp::DataDrop):
|
||||
CHECK(EmitDataOrElemDrop(f, /*isData=*/true));
|
||||
case uint16_t(MiscOp::MemFill):
|
||||
case uint32_t(MiscOp::MemFill):
|
||||
CHECK(EmitMemFill(f));
|
||||
case uint16_t(MiscOp::MemInit):
|
||||
case uint32_t(MiscOp::MemInit):
|
||||
CHECK(EmitMemOrTableInit(f, /*isMem=*/true));
|
||||
case uint16_t(MiscOp::TableCopy):
|
||||
case uint32_t(MiscOp::TableCopy):
|
||||
CHECK(EmitMemOrTableCopy(f, /*isMem=*/false));
|
||||
case uint16_t(MiscOp::ElemDrop):
|
||||
case uint32_t(MiscOp::ElemDrop):
|
||||
CHECK(EmitDataOrElemDrop(f, /*isData=*/false));
|
||||
case uint16_t(MiscOp::TableInit):
|
||||
case uint32_t(MiscOp::TableInit):
|
||||
CHECK(EmitMemOrTableInit(f, /*isMem=*/false));
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_REFTYPES
|
||||
case uint16_t(MiscOp::TableGrow):
|
||||
case uint32_t(MiscOp::TableGrow):
|
||||
CHECK(EmitTableGrow(f));
|
||||
case uint16_t(MiscOp::TableSize):
|
||||
case uint32_t(MiscOp::TableSize):
|
||||
CHECK(EmitTableSize(f));
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GC
|
||||
case uint16_t(MiscOp::StructNew):
|
||||
case uint16_t(MiscOp::StructGet):
|
||||
case uint16_t(MiscOp::StructSet):
|
||||
case uint16_t(MiscOp::StructNarrow):
|
||||
case uint32_t(MiscOp::StructNew):
|
||||
case uint32_t(MiscOp::StructGet):
|
||||
case uint32_t(MiscOp::StructSet):
|
||||
case uint32_t(MiscOp::StructNarrow):
|
||||
// Not yet supported
|
||||
return f.iter().unrecognizedOpcode(&op);
|
||||
#endif
|
||||
@ -3873,182 +3873,182 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
|
||||
// Thread operations
|
||||
case uint16_t(Op::ThreadPrefix): {
|
||||
switch (op.b1) {
|
||||
case uint16_t(ThreadOp::Wake):
|
||||
case uint32_t(ThreadOp::Wake):
|
||||
CHECK(EmitWake(f));
|
||||
|
||||
case uint16_t(ThreadOp::I32Wait):
|
||||
case uint32_t(ThreadOp::I32Wait):
|
||||
CHECK(EmitWait(f, ValType::I32, 4));
|
||||
case uint16_t(ThreadOp::I64Wait):
|
||||
case uint32_t(ThreadOp::I64Wait):
|
||||
CHECK(EmitWait(f, ValType::I64, 8));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicLoad):
|
||||
case uint32_t(ThreadOp::I32AtomicLoad):
|
||||
CHECK(EmitAtomicLoad(f, ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad):
|
||||
CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicLoad8U):
|
||||
case uint32_t(ThreadOp::I32AtomicLoad8U):
|
||||
CHECK(EmitAtomicLoad(f, ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicLoad16U):
|
||||
case uint32_t(ThreadOp::I32AtomicLoad16U):
|
||||
CHECK(EmitAtomicLoad(f, ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad8U):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad8U):
|
||||
CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad16U):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad16U):
|
||||
CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicLoad32U):
|
||||
case uint32_t(ThreadOp::I64AtomicLoad32U):
|
||||
CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Uint32));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicStore):
|
||||
case uint32_t(ThreadOp::I32AtomicStore):
|
||||
CHECK(EmitAtomicStore(f, ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicStore):
|
||||
case uint32_t(ThreadOp::I64AtomicStore):
|
||||
CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicStore8U):
|
||||
case uint32_t(ThreadOp::I32AtomicStore8U):
|
||||
CHECK(EmitAtomicStore(f, ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicStore16U):
|
||||
case uint32_t(ThreadOp::I32AtomicStore16U):
|
||||
CHECK(EmitAtomicStore(f, ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicStore8U):
|
||||
case uint32_t(ThreadOp::I64AtomicStore8U):
|
||||
CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicStore16U):
|
||||
case uint32_t(ThreadOp::I64AtomicStore16U):
|
||||
CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicStore32U):
|
||||
case uint32_t(ThreadOp::I64AtomicStore32U):
|
||||
CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Uint32));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicAdd):
|
||||
case uint32_t(ThreadOp::I32AtomicAdd):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32,
|
||||
AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64,
|
||||
AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAdd8U):
|
||||
case uint32_t(ThreadOp::I32AtomicAdd8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8,
|
||||
AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAdd16U):
|
||||
case uint32_t(ThreadOp::I32AtomicAdd16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint16,
|
||||
AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd8U):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8,
|
||||
AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd16U):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint16,
|
||||
AtomicFetchAddOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAdd32U):
|
||||
case uint32_t(ThreadOp::I64AtomicAdd32U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint32,
|
||||
AtomicFetchAddOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicSub):
|
||||
case uint32_t(ThreadOp::I32AtomicSub):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32,
|
||||
AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub):
|
||||
case uint32_t(ThreadOp::I64AtomicSub):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64,
|
||||
AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I32AtomicSub8U):
|
||||
case uint32_t(ThreadOp::I32AtomicSub8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8,
|
||||
AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I32AtomicSub16U):
|
||||
case uint32_t(ThreadOp::I32AtomicSub16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint16,
|
||||
AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub8U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8,
|
||||
AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub16U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint16,
|
||||
AtomicFetchSubOp));
|
||||
case uint16_t(ThreadOp::I64AtomicSub32U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub32U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint32,
|
||||
AtomicFetchSubOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicAnd):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32,
|
||||
AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64,
|
||||
AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAnd8U):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8,
|
||||
AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I32AtomicAnd16U):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint16,
|
||||
AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd8U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8,
|
||||
AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd16U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint16,
|
||||
AtomicFetchAndOp));
|
||||
case uint16_t(ThreadOp::I64AtomicAnd32U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd32U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint32,
|
||||
AtomicFetchAndOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicOr):
|
||||
case uint32_t(ThreadOp::I32AtomicOr):
|
||||
CHECK(
|
||||
EmitAtomicRMW(f, ValType::I32, Scalar::Int32, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr):
|
||||
case uint32_t(ThreadOp::I64AtomicOr):
|
||||
CHECK(
|
||||
EmitAtomicRMW(f, ValType::I64, Scalar::Int64, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I32AtomicOr8U):
|
||||
case uint32_t(ThreadOp::I32AtomicOr8U):
|
||||
CHECK(
|
||||
EmitAtomicRMW(f, ValType::I32, Scalar::Uint8, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I32AtomicOr16U):
|
||||
case uint32_t(ThreadOp::I32AtomicOr16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint16,
|
||||
AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr8U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr8U):
|
||||
CHECK(
|
||||
EmitAtomicRMW(f, ValType::I64, Scalar::Uint8, AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr16U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint16,
|
||||
AtomicFetchOrOp));
|
||||
case uint16_t(ThreadOp::I64AtomicOr32U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr32U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint32,
|
||||
AtomicFetchOrOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicXor):
|
||||
case uint32_t(ThreadOp::I32AtomicXor):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32,
|
||||
AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor):
|
||||
case uint32_t(ThreadOp::I64AtomicXor):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64,
|
||||
AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I32AtomicXor8U):
|
||||
case uint32_t(ThreadOp::I32AtomicXor8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8,
|
||||
AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I32AtomicXor16U):
|
||||
case uint32_t(ThreadOp::I32AtomicXor16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint16,
|
||||
AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor8U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor8U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8,
|
||||
AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor16U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor16U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint16,
|
||||
AtomicFetchXorOp));
|
||||
case uint16_t(ThreadOp::I64AtomicXor32U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor32U):
|
||||
CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint32,
|
||||
AtomicFetchXorOp));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicXchg):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg):
|
||||
CHECK(EmitAtomicXchg(f, ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg):
|
||||
CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicXchg8U):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg8U):
|
||||
CHECK(EmitAtomicXchg(f, ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicXchg16U):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg16U):
|
||||
CHECK(EmitAtomicXchg(f, ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg8U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg8U):
|
||||
CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg16U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg16U):
|
||||
CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicXchg32U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg32U):
|
||||
CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Uint32));
|
||||
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg):
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg):
|
||||
CHECK(EmitAtomicCmpXchg(f, ValType::I32, Scalar::Int32));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg):
|
||||
CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Int64));
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg8U):
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg8U):
|
||||
CHECK(EmitAtomicCmpXchg(f, ValType::I32, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg16U):
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg16U):
|
||||
CHECK(EmitAtomicCmpXchg(f, ValType::I32, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg8U):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg8U):
|
||||
CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Uint8));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg16U):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg16U):
|
||||
CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Uint16));
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg32U):
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg32U):
|
||||
CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Uint32));
|
||||
|
||||
default:
|
||||
@ -4063,66 +4063,66 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
|
||||
return f.iter().unrecognizedOpcode(&op);
|
||||
}
|
||||
switch (op.b1) {
|
||||
case uint16_t(MozOp::TeeGlobal):
|
||||
case uint32_t(MozOp::TeeGlobal):
|
||||
CHECK(EmitTeeGlobal(f));
|
||||
case uint16_t(MozOp::I32Min):
|
||||
case uint16_t(MozOp::I32Max):
|
||||
case uint32_t(MozOp::I32Min):
|
||||
case uint32_t(MozOp::I32Max):
|
||||
CHECK(EmitMinMax(f, ValType::I32, MIRType::Int32,
|
||||
MozOp(op.b1) == MozOp::I32Max));
|
||||
case uint16_t(MozOp::I32Neg):
|
||||
case uint32_t(MozOp::I32Neg):
|
||||
CHECK(EmitUnaryWithType<MWasmNeg>(f, ValType::I32, MIRType::Int32));
|
||||
case uint16_t(MozOp::I32BitNot):
|
||||
case uint32_t(MozOp::I32BitNot):
|
||||
CHECK(EmitBitNot(f, ValType::I32));
|
||||
case uint16_t(MozOp::I32Abs):
|
||||
case uint32_t(MozOp::I32Abs):
|
||||
CHECK(EmitUnaryWithType<MAbs>(f, ValType::I32, MIRType::Int32));
|
||||
case uint16_t(MozOp::F32TeeStoreF64):
|
||||
case uint32_t(MozOp::F32TeeStoreF64):
|
||||
CHECK(EmitTeeStoreWithCoercion(f, ValType::F32, Scalar::Float64));
|
||||
case uint16_t(MozOp::F64TeeStoreF32):
|
||||
case uint32_t(MozOp::F64TeeStoreF32):
|
||||
CHECK(EmitTeeStoreWithCoercion(f, ValType::F64, Scalar::Float32));
|
||||
case uint16_t(MozOp::I32TeeStore8):
|
||||
case uint32_t(MozOp::I32TeeStore8):
|
||||
CHECK(EmitTeeStore(f, ValType::I32, Scalar::Int8));
|
||||
case uint16_t(MozOp::I32TeeStore16):
|
||||
case uint32_t(MozOp::I32TeeStore16):
|
||||
CHECK(EmitTeeStore(f, ValType::I32, Scalar::Int16));
|
||||
case uint16_t(MozOp::I64TeeStore8):
|
||||
case uint32_t(MozOp::I64TeeStore8):
|
||||
CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int8));
|
||||
case uint16_t(MozOp::I64TeeStore16):
|
||||
case uint32_t(MozOp::I64TeeStore16):
|
||||
CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int16));
|
||||
case uint16_t(MozOp::I64TeeStore32):
|
||||
case uint32_t(MozOp::I64TeeStore32):
|
||||
CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int32));
|
||||
case uint16_t(MozOp::I32TeeStore):
|
||||
case uint32_t(MozOp::I32TeeStore):
|
||||
CHECK(EmitTeeStore(f, ValType::I32, Scalar::Int32));
|
||||
case uint16_t(MozOp::I64TeeStore):
|
||||
case uint32_t(MozOp::I64TeeStore):
|
||||
CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int64));
|
||||
case uint16_t(MozOp::F32TeeStore):
|
||||
case uint32_t(MozOp::F32TeeStore):
|
||||
CHECK(EmitTeeStore(f, ValType::F32, Scalar::Float32));
|
||||
case uint16_t(MozOp::F64TeeStore):
|
||||
case uint32_t(MozOp::F64TeeStore):
|
||||
CHECK(EmitTeeStore(f, ValType::F64, Scalar::Float64));
|
||||
case uint16_t(MozOp::F64Mod):
|
||||
case uint32_t(MozOp::F64Mod):
|
||||
CHECK(EmitRem(f, ValType::F64, MIRType::Double,
|
||||
/* isUnsigned = */ false));
|
||||
case uint16_t(MozOp::F64Sin):
|
||||
case uint32_t(MozOp::F64Sin):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigSinD));
|
||||
case uint16_t(MozOp::F64Cos):
|
||||
case uint32_t(MozOp::F64Cos):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigCosD));
|
||||
case uint16_t(MozOp::F64Tan):
|
||||
case uint32_t(MozOp::F64Tan):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigTanD));
|
||||
case uint16_t(MozOp::F64Asin):
|
||||
case uint32_t(MozOp::F64Asin):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigASinD));
|
||||
case uint16_t(MozOp::F64Acos):
|
||||
case uint32_t(MozOp::F64Acos):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigACosD));
|
||||
case uint16_t(MozOp::F64Atan):
|
||||
case uint32_t(MozOp::F64Atan):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigATanD));
|
||||
case uint16_t(MozOp::F64Exp):
|
||||
case uint32_t(MozOp::F64Exp):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigExpD));
|
||||
case uint16_t(MozOp::F64Log):
|
||||
case uint32_t(MozOp::F64Log):
|
||||
CHECK(EmitUnaryMathBuiltinCall(f, SASigLogD));
|
||||
case uint16_t(MozOp::F64Pow):
|
||||
case uint32_t(MozOp::F64Pow):
|
||||
CHECK(EmitBinaryMathBuiltinCall(f, SASigPowD));
|
||||
case uint16_t(MozOp::F64Atan2):
|
||||
case uint32_t(MozOp::F64Atan2):
|
||||
CHECK(EmitBinaryMathBuiltinCall(f, SASigATan2D));
|
||||
case uint16_t(MozOp::OldCallDirect):
|
||||
case uint32_t(MozOp::OldCallDirect):
|
||||
CHECK(EmitCall(f, /* asmJSFuncDef = */ true));
|
||||
case uint16_t(MozOp::OldCallIndirect):
|
||||
case uint32_t(MozOp::OldCallIndirect):
|
||||
CHECK(EmitCallIndirect(f, /* oldStyle = */ true));
|
||||
|
||||
default:
|
||||
|
@ -817,51 +817,51 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
||||
CHECK(iter.readUnreachable());
|
||||
case uint16_t(Op::MiscPrefix): {
|
||||
switch (op.b1) {
|
||||
case uint16_t(MiscOp::I32TruncSSatF32):
|
||||
case uint16_t(MiscOp::I32TruncUSatF32):
|
||||
case uint32_t(MiscOp::I32TruncSSatF32):
|
||||
case uint32_t(MiscOp::I32TruncUSatF32):
|
||||
CHECK(iter.readConversion(ValType::F32, ValType::I32, ¬hing));
|
||||
case uint16_t(MiscOp::I32TruncSSatF64):
|
||||
case uint16_t(MiscOp::I32TruncUSatF64):
|
||||
case uint32_t(MiscOp::I32TruncSSatF64):
|
||||
case uint32_t(MiscOp::I32TruncUSatF64):
|
||||
CHECK(iter.readConversion(ValType::F64, ValType::I32, ¬hing));
|
||||
case uint16_t(MiscOp::I64TruncSSatF32):
|
||||
case uint16_t(MiscOp::I64TruncUSatF32):
|
||||
case uint32_t(MiscOp::I64TruncSSatF32):
|
||||
case uint32_t(MiscOp::I64TruncUSatF32):
|
||||
CHECK(iter.readConversion(ValType::F32, ValType::I64, ¬hing));
|
||||
case uint16_t(MiscOp::I64TruncSSatF64):
|
||||
case uint16_t(MiscOp::I64TruncUSatF64):
|
||||
case uint32_t(MiscOp::I64TruncSSatF64):
|
||||
case uint32_t(MiscOp::I64TruncUSatF64):
|
||||
CHECK(iter.readConversion(ValType::F64, ValType::I64, ¬hing));
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case uint16_t(MiscOp::MemCopy): {
|
||||
case uint32_t(MiscOp::MemCopy): {
|
||||
uint32_t unusedDestMemIndex;
|
||||
uint32_t unusedSrcMemIndex;
|
||||
CHECK(iter.readMemOrTableCopy(/*isMem=*/true, &unusedDestMemIndex,
|
||||
¬hing, &unusedSrcMemIndex,
|
||||
¬hing, ¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::DataDrop): {
|
||||
case uint32_t(MiscOp::DataDrop): {
|
||||
uint32_t unusedSegIndex;
|
||||
CHECK(iter.readDataOrElemDrop(/*isData=*/true, &unusedSegIndex));
|
||||
}
|
||||
case uint16_t(MiscOp::MemFill):
|
||||
case uint32_t(MiscOp::MemFill):
|
||||
CHECK(iter.readMemFill(¬hing, ¬hing, ¬hing));
|
||||
case uint16_t(MiscOp::MemInit): {
|
||||
case uint32_t(MiscOp::MemInit): {
|
||||
uint32_t unusedSegIndex;
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readMemOrTableInit(/*isMem=*/true, &unusedSegIndex,
|
||||
&unusedTableIndex, ¬hing, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::TableCopy): {
|
||||
case uint32_t(MiscOp::TableCopy): {
|
||||
uint32_t unusedDestTableIndex;
|
||||
uint32_t unusedSrcTableIndex;
|
||||
CHECK(iter.readMemOrTableCopy(
|
||||
/*isMem=*/false, &unusedDestTableIndex, ¬hing,
|
||||
&unusedSrcTableIndex, ¬hing, ¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::ElemDrop): {
|
||||
case uint32_t(MiscOp::ElemDrop): {
|
||||
uint32_t unusedSegIndex;
|
||||
CHECK(iter.readDataOrElemDrop(/*isData=*/false, &unusedSegIndex));
|
||||
}
|
||||
case uint16_t(MiscOp::TableInit): {
|
||||
case uint32_t(MiscOp::TableInit): {
|
||||
uint32_t unusedSegIndex;
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readMemOrTableInit(/*isMem=*/false, &unusedSegIndex,
|
||||
@ -870,17 +870,17 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_REFTYPES
|
||||
case uint16_t(MiscOp::TableGrow): {
|
||||
case uint32_t(MiscOp::TableGrow): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableGrow(&unusedTableIndex, ¬hing, ¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::TableSize): {
|
||||
case uint32_t(MiscOp::TableSize): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableSize(&unusedTableIndex));
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GC
|
||||
case uint16_t(MiscOp::StructNew): {
|
||||
case uint32_t(MiscOp::StructNew): {
|
||||
if (!env.gcTypesEnabled()) {
|
||||
return iter.unrecognizedOpcode(&op);
|
||||
}
|
||||
@ -888,14 +888,14 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
||||
ValidatingOpIter::ValueVector unusedArgs;
|
||||
CHECK(iter.readStructNew(&unusedUint, &unusedArgs));
|
||||
}
|
||||
case uint16_t(MiscOp::StructGet): {
|
||||
case uint32_t(MiscOp::StructGet): {
|
||||
if (!env.gcTypesEnabled()) {
|
||||
return iter.unrecognizedOpcode(&op);
|
||||
}
|
||||
uint32_t unusedUint1, unusedUint2;
|
||||
CHECK(iter.readStructGet(&unusedUint1, &unusedUint2, ¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::StructSet): {
|
||||
case uint32_t(MiscOp::StructSet): {
|
||||
if (!env.gcTypesEnabled()) {
|
||||
return iter.unrecognizedOpcode(&op);
|
||||
}
|
||||
@ -903,7 +903,7 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
||||
CHECK(iter.readStructSet(&unusedUint1, &unusedUint2, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::StructNarrow): {
|
||||
case uint32_t(MiscOp::StructNarrow): {
|
||||
if (!env.gcTypesEnabled()) {
|
||||
return iter.unrecognizedOpcode(&op);
|
||||
}
|
||||
@ -937,168 +937,168 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
||||
#endif
|
||||
case uint16_t(Op::ThreadPrefix): {
|
||||
switch (op.b1) {
|
||||
case uint16_t(ThreadOp::Wake): {
|
||||
case uint32_t(ThreadOp::Wake): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readWake(&addr, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32Wait): {
|
||||
case uint32_t(ThreadOp::I32Wait): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readWait(&addr, ValType::I32, 4, ¬hing, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64Wait): {
|
||||
case uint32_t(ThreadOp::I64Wait): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readWait(&addr, ValType::I64, 8, ¬hing, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicLoad): {
|
||||
case uint32_t(ThreadOp::I32AtomicLoad): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicLoad(&addr, ValType::I32, 4));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicLoad): {
|
||||
case uint32_t(ThreadOp::I64AtomicLoad): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicLoad(&addr, ValType::I64, 8));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicLoad8U): {
|
||||
case uint32_t(ThreadOp::I32AtomicLoad8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicLoad(&addr, ValType::I32, 1));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicLoad16U): {
|
||||
case uint32_t(ThreadOp::I32AtomicLoad16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicLoad(&addr, ValType::I32, 2));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicLoad8U): {
|
||||
case uint32_t(ThreadOp::I64AtomicLoad8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicLoad(&addr, ValType::I64, 1));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicLoad16U): {
|
||||
case uint32_t(ThreadOp::I64AtomicLoad16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicLoad(&addr, ValType::I64, 2));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicLoad32U): {
|
||||
case uint32_t(ThreadOp::I64AtomicLoad32U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicLoad(&addr, ValType::I64, 4));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicStore): {
|
||||
case uint32_t(ThreadOp::I32AtomicStore): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicStore(&addr, ValType::I32, 4, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicStore): {
|
||||
case uint32_t(ThreadOp::I64AtomicStore): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicStore(&addr, ValType::I64, 8, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicStore8U): {
|
||||
case uint32_t(ThreadOp::I32AtomicStore8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicStore(&addr, ValType::I32, 1, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicStore16U): {
|
||||
case uint32_t(ThreadOp::I32AtomicStore16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicStore(&addr, ValType::I32, 2, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicStore8U): {
|
||||
case uint32_t(ThreadOp::I64AtomicStore8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicStore(&addr, ValType::I64, 1, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicStore16U): {
|
||||
case uint32_t(ThreadOp::I64AtomicStore16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicStore(&addr, ValType::I64, 2, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicStore32U): {
|
||||
case uint32_t(ThreadOp::I64AtomicStore32U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicStore(&addr, ValType::I64, 4, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicAdd):
|
||||
case uint16_t(ThreadOp::I32AtomicSub):
|
||||
case uint16_t(ThreadOp::I32AtomicAnd):
|
||||
case uint16_t(ThreadOp::I32AtomicOr):
|
||||
case uint16_t(ThreadOp::I32AtomicXor):
|
||||
case uint16_t(ThreadOp::I32AtomicXchg): {
|
||||
case uint32_t(ThreadOp::I32AtomicAdd):
|
||||
case uint32_t(ThreadOp::I32AtomicSub):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd):
|
||||
case uint32_t(ThreadOp::I32AtomicOr):
|
||||
case uint32_t(ThreadOp::I32AtomicXor):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicRMW(&addr, ValType::I32, 4, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicAdd):
|
||||
case uint16_t(ThreadOp::I64AtomicSub):
|
||||
case uint16_t(ThreadOp::I64AtomicAnd):
|
||||
case uint16_t(ThreadOp::I64AtomicOr):
|
||||
case uint16_t(ThreadOp::I64AtomicXor):
|
||||
case uint16_t(ThreadOp::I64AtomicXchg): {
|
||||
case uint32_t(ThreadOp::I64AtomicAdd):
|
||||
case uint32_t(ThreadOp::I64AtomicSub):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd):
|
||||
case uint32_t(ThreadOp::I64AtomicOr):
|
||||
case uint32_t(ThreadOp::I64AtomicXor):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicRMW(&addr, ValType::I64, 8, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicAdd8U):
|
||||
case uint16_t(ThreadOp::I32AtomicSub8U):
|
||||
case uint16_t(ThreadOp::I32AtomicAnd8U):
|
||||
case uint16_t(ThreadOp::I32AtomicOr8U):
|
||||
case uint16_t(ThreadOp::I32AtomicXor8U):
|
||||
case uint16_t(ThreadOp::I32AtomicXchg8U): {
|
||||
case uint32_t(ThreadOp::I32AtomicAdd8U):
|
||||
case uint32_t(ThreadOp::I32AtomicSub8U):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd8U):
|
||||
case uint32_t(ThreadOp::I32AtomicOr8U):
|
||||
case uint32_t(ThreadOp::I32AtomicXor8U):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicRMW(&addr, ValType::I32, 1, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicAdd16U):
|
||||
case uint16_t(ThreadOp::I32AtomicSub16U):
|
||||
case uint16_t(ThreadOp::I32AtomicAnd16U):
|
||||
case uint16_t(ThreadOp::I32AtomicOr16U):
|
||||
case uint16_t(ThreadOp::I32AtomicXor16U):
|
||||
case uint16_t(ThreadOp::I32AtomicXchg16U): {
|
||||
case uint32_t(ThreadOp::I32AtomicAdd16U):
|
||||
case uint32_t(ThreadOp::I32AtomicSub16U):
|
||||
case uint32_t(ThreadOp::I32AtomicAnd16U):
|
||||
case uint32_t(ThreadOp::I32AtomicOr16U):
|
||||
case uint32_t(ThreadOp::I32AtomicXor16U):
|
||||
case uint32_t(ThreadOp::I32AtomicXchg16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicRMW(&addr, ValType::I32, 2, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicAdd8U):
|
||||
case uint16_t(ThreadOp::I64AtomicSub8U):
|
||||
case uint16_t(ThreadOp::I64AtomicAnd8U):
|
||||
case uint16_t(ThreadOp::I64AtomicOr8U):
|
||||
case uint16_t(ThreadOp::I64AtomicXor8U):
|
||||
case uint16_t(ThreadOp::I64AtomicXchg8U): {
|
||||
case uint32_t(ThreadOp::I64AtomicAdd8U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub8U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd8U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr8U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor8U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicRMW(&addr, ValType::I64, 1, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicAdd16U):
|
||||
case uint16_t(ThreadOp::I64AtomicSub16U):
|
||||
case uint16_t(ThreadOp::I64AtomicAnd16U):
|
||||
case uint16_t(ThreadOp::I64AtomicOr16U):
|
||||
case uint16_t(ThreadOp::I64AtomicXor16U):
|
||||
case uint16_t(ThreadOp::I64AtomicXchg16U): {
|
||||
case uint32_t(ThreadOp::I64AtomicAdd16U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub16U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd16U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr16U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor16U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicRMW(&addr, ValType::I64, 2, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicAdd32U):
|
||||
case uint16_t(ThreadOp::I64AtomicSub32U):
|
||||
case uint16_t(ThreadOp::I64AtomicAnd32U):
|
||||
case uint16_t(ThreadOp::I64AtomicOr32U):
|
||||
case uint16_t(ThreadOp::I64AtomicXor32U):
|
||||
case uint16_t(ThreadOp::I64AtomicXchg32U): {
|
||||
case uint32_t(ThreadOp::I64AtomicAdd32U):
|
||||
case uint32_t(ThreadOp::I64AtomicSub32U):
|
||||
case uint32_t(ThreadOp::I64AtomicAnd32U):
|
||||
case uint32_t(ThreadOp::I64AtomicOr32U):
|
||||
case uint32_t(ThreadOp::I64AtomicXor32U):
|
||||
case uint32_t(ThreadOp::I64AtomicXchg32U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicRMW(&addr, ValType::I64, 4, ¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg): {
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 4, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg): {
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 8, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg8U): {
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 1, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I32AtomicCmpXchg16U): {
|
||||
case uint32_t(ThreadOp::I32AtomicCmpXchg16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 2, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg8U): {
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg8U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 1, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg16U): {
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg16U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 2, ¬hing,
|
||||
¬hing));
|
||||
}
|
||||
case uint16_t(ThreadOp::I64AtomicCmpXchg32U): {
|
||||
case uint32_t(ThreadOp::I64AtomicCmpXchg32U): {
|
||||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 4, ¬hing,
|
||||
¬hing));
|
||||
|
@ -345,19 +345,16 @@ class Encoder {
|
||||
return writeFixedU8(uint8_t(op));
|
||||
}
|
||||
MOZ_MUST_USE bool writeOp(MiscOp op) {
|
||||
static_assert(size_t(MiscOp::Limit) <= 256, "fits");
|
||||
MOZ_ASSERT(size_t(op) < size_t(MiscOp::Limit));
|
||||
return writeFixedU8(uint8_t(Op::MiscPrefix)) && writeFixedU8(uint8_t(op));
|
||||
return writeFixedU8(uint8_t(Op::MiscPrefix)) && writeVarU32(uint32_t(op));
|
||||
}
|
||||
MOZ_MUST_USE bool writeOp(ThreadOp op) {
|
||||
static_assert(size_t(ThreadOp::Limit) <= 256, "fits");
|
||||
MOZ_ASSERT(size_t(op) < size_t(ThreadOp::Limit));
|
||||
return writeFixedU8(uint8_t(Op::ThreadPrefix)) && writeFixedU8(uint8_t(op));
|
||||
return writeFixedU8(uint8_t(Op::ThreadPrefix)) && writeVarU32(uint32_t(op));
|
||||
}
|
||||
MOZ_MUST_USE bool writeOp(MozOp op) {
|
||||
static_assert(size_t(MozOp::Limit) <= 256, "fits");
|
||||
MOZ_ASSERT(size_t(op) < size_t(MozOp::Limit));
|
||||
return writeFixedU8(uint8_t(Op::MozPrefix)) && writeFixedU8(uint8_t(op));
|
||||
return writeFixedU8(uint8_t(Op::MozPrefix)) && writeVarU32(uint32_t(op));
|
||||
}
|
||||
|
||||
// Fixed-length encodings that allow back-patching.
|
||||
|
@ -8,8 +8,8 @@ crate-type = ["rlib"]
|
||||
name = "baldrdash"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = "0.28.0"
|
||||
cranelift-wasm = "0.28.0"
|
||||
cranelift-codegen = "0.29.0"
|
||||
cranelift-wasm = "0.29.0"
|
||||
target-lexicon = "0.2.0"
|
||||
log = { version = "0.4.6", default-features = false, features = ["release_max_level_info"] }
|
||||
env_logger = "0.5.6"
|
||||
|
@ -83,7 +83,8 @@ struct CraneliftStaticEnvironment {
|
||||
// contains.
|
||||
|
||||
struct CraneliftModuleEnvironment {
|
||||
const js::wasm::ModuleEnvironment& env;
|
||||
// This is a pointer and not a reference to work-around a bug in bindgen.
|
||||
const js::wasm::ModuleEnvironment* env;
|
||||
uint32_t min_memory_length;
|
||||
|
||||
// Not bindgen'd because it's inlined.
|
||||
@ -99,6 +100,7 @@ struct CraneliftFuncCompileInput {
|
||||
const uint8_t* bytecode;
|
||||
size_t bytecodeSize;
|
||||
uint32_t index;
|
||||
uint32_t offset_in_module;
|
||||
|
||||
// Not bindgen'd because it's inlined.
|
||||
explicit inline CraneliftFuncCompileInput(const js::wasm::FuncCompileInput&);
|
||||
@ -119,8 +121,8 @@ struct CraneliftMetadataEntry {
|
||||
MemoryAccess,
|
||||
SymbolicAccess
|
||||
} which;
|
||||
uint32_t offset;
|
||||
uint32_t srcLoc;
|
||||
uint32_t offset; // relative to the beginning of the function generated code
|
||||
uint32_t srcLoc; // relative to the beginning of the module bytecode
|
||||
size_t extra;
|
||||
};
|
||||
|
||||
|
@ -106,8 +106,12 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
|
||||
self.context.func.name = wasm_function_name(index);
|
||||
|
||||
let tenv = &mut TransEnv::new(&*self.isa, &self.environ, self.static_environ);
|
||||
self.trans
|
||||
.translate(func.bytecode(), &mut self.context.func, tenv)?;
|
||||
self.trans.translate(
|
||||
func.bytecode(),
|
||||
func.offset_in_module as usize,
|
||||
&mut self.context.func,
|
||||
tenv,
|
||||
)?;
|
||||
|
||||
info!("Translated wasm function {}.", func.index);
|
||||
debug!("Content: {}", self.context.func.display(&*self.isa));
|
||||
|
@ -1301,9 +1301,9 @@ pref("dom.serviceWorkers.disable_open_click_delay", 1000);
|
||||
|
||||
pref("dom.storage.enabled", true);
|
||||
// Whether or not LSNG (Next Generation Local Storage) is enabled.
|
||||
// See bug 1510410 for enabling this on Nightly.
|
||||
// See bug 1517090 for enabling this on Nightly.
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("dom.storage.next_gen", false);
|
||||
pref("dom.storage.next_gen", true);
|
||||
#else
|
||||
pref("dom.storage.next_gen", false);
|
||||
#endif
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"71b82e879926d62dea538644a84ae5e6274f5a57dd7ef3edfc5ae95e2a804986","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"1b23abbfe5850a4cd77ae6ae5dcfc2f678ef36b4032fd7496f2b333c51e63301","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"4868e59ff67db1c504747e4b7e202dd20c9da4cbd73d9fa82d53e5f3406dbb78","src/pool.rs":"6090f8c0e0da16ebee0e31bca66392d0075b3aff529d30d4e716fa20cd0aef99","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":"c88db0c2fc38b2cedee1b94ee2dc7bf80e4ce31467c8005743f485af66e240d8"}
|
||||
{"files":{"Cargo.toml":"d6c5cca60972e64e1abb435d2af6bf8af2fec2d5988d0fda9827f6bba1f6a47c","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"1b23abbfe5850a4cd77ae6ae5dcfc2f678ef36b4032fd7496f2b333c51e63301","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"4868e59ff67db1c504747e4b7e202dd20c9da4cbd73d9fa82d53e5f3406dbb78","src/pool.rs":"6090f8c0e0da16ebee0e31bca66392d0075b3aff529d30d4e716fa20cd0aef99","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":"a3a25dfe4a54449df63d592f2f6346a80350ac835d4be4bacb73c20b034ef763"}
|
@ -13,7 +13,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "cranelift-bforest"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "A forest of B+-trees"
|
||||
documentation = "https://cranelift.readthedocs.io/"
|
||||
@ -23,7 +23,7 @@ categories = ["no-std"]
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/CraneStation/cranelift"
|
||||
[dependencies.cranelift-entity]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"05bb65ad8427efad48f44eac2db25961e6b56374941edf54912469a7b1e7110e","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"559075f0b76a744dd36224e06ff1c2e28ee70aaca9442fc724b116e37028ac52","src/base/settings.rs":"bc6a15221d688bf63114c53493d31070860eb7fae208596374488404a65ee41a","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/isa.rs":"5c9a8173466e69d105245396abd342251eb00e704ab13f179ba1567b339f47e1","src/cdsl/mod.rs":"66ac1b5d095e431bcab88c4b9c5b1492a5d1ca87bcb9c9c3e544ede05b2ba925","src/cdsl/regs.rs":"c45809713e8bf9d097c75991ff8dd4ca215a97e9f83df6407dcc09d76e6fbddb","src/cdsl/settings.rs":"4ddeadf1542cc2ddec0f9e6c22d1637050da519586cd9fec0243c3eab9619f82","src/cdsl/types.rs":"82aff98c094a564ed1a11ca7628bfba66c363d5fff278babbf26a4252b3a5107","src/constant_hash.rs":"b8acd3f8712a4999819d9d9beced2938d9940a5748ba016c182f1132d97eefab","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"cee8f9d4ad1d07e5bd59a9ca875ede3e4143ec4c97b5fd56c3e6f8b1dea64a53","src/gen_settings.rs":"c89aaecf6b6b53e229d052db90ffc43d11b5a69974961615437608ac705ae0dd","src/gen_types.rs":"9b8a06cd025fcb67e2f98f2b3c4697e551119997fd7254dc9ed2f9c5d2e2aa1c","src/isa/arm32/mod.rs":"741da8a24aa31919458349663e0a24e03727a7c2a72d5ebd813c2162cb19c65c","src/isa/arm64/mod.rs":"2b384d84fb2a1b53d6f3882ca18d8b9027161193493361a95406fa357a0822fa","src/isa/mod.rs":"c5ea6469fe770d49ceaa4b9c6370d8df2ac55fffc076fb3852fc5bbc8c096c2b","src/isa/riscv/mod.rs":"690a285d8185e38ad3134ac1dcd1e550e346ebb349f90c7b8b68b38ddd4b7a1f","src/isa/x86/mod.rs":"712a16bc2e0e50112f92bfbc5963e4548db5f701d5f14fd344df5fc76753f641","src/lib.rs":"995c6f1d6e8ca9dda8838b96c92f37f7c78d6d555e1f05b3700a1271760a161c","src/srcgen.rs":"a51b6f7b61110d958c541bc8de61592cb93cca0d6d46b2f5ffe47fca8feedae8","src/unique_table.rs":"f6041df1fa85f2a1ee914b84791e80165a0858a6253c212eaa99ff67cb56af26"},"package":"43131e662da7e0243cff28edfbc094a62968a4b57849f77a6c1e3685e9e6e1e6"}
|
||||
{"files":{"Cargo.toml":"f5ea16920dd3c3f9c1ef903e26b10a913cafb5ac30eb36deabca977de04a62ae","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/isa.rs":"d3ddfc8bd3d691df034a1bacfa27b3e29eb2e7a30923508fa5c7af8d89e8a962","src/cdsl/mod.rs":"66ac1b5d095e431bcab88c4b9c5b1492a5d1ca87bcb9c9c3e544ede05b2ba925","src/cdsl/regs.rs":"b99f24c3ecb46691625dc177b4e18d53e02265bc85a2f827a8d18381fe8f39bb","src/cdsl/settings.rs":"4ddeadf1542cc2ddec0f9e6c22d1637050da519586cd9fec0243c3eab9619f82","src/cdsl/types.rs":"981ebe748973bdf2dee00fa71784f6dcaa6c7648442665f34a59ad97a05fe888","src/constant_hash.rs":"b8acd3f8712a4999819d9d9beced2938d9940a5748ba016c182f1132d97eefab","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"75bbbc0f8dd546c88ed52f350175656300e35e871382a7508e7123e32d4bee1e","src/gen_settings.rs":"4689ede4e460bfcc19511c1055ba359b52f248f4a6d3afd62b1d23bc493b37a1","src/gen_types.rs":"3935da6c6a53f9332e06f74bc3a46270656b4d4231ad28ed2648d7b1d2774e90","src/isa/arm32/mod.rs":"f5b0cbbb2f6c7f00bb9a9bc6f0b1120477ff7ff683a95a6cdbbeed1677b0c9c8","src/isa/arm64/mod.rs":"c234b0df3d36d6d8765ead548e43b5304480e79da9697e14f9d98525919921b3","src/isa/mod.rs":"7038e3aa629afc28707fea379237d3c161ab459d552160438ac75e1137c6246a","src/isa/riscv/mod.rs":"322220fa67cf8623eeb27c7d23f3cc34e05873860248ae99fd02af452c232383","src/isa/x86/mod.rs":"c9183448ffe378e599ec7dc6ae7180c97d3e11d15d7644b93eb1e4a3543222f2","src/lib.rs":"4c73b35cbd68aab9b9c8c86bb71f67555e0e15f36a22101e086a346b01ee8cfb","src/shared/mod.rs":"87b55c291c5e73a9d7cd9a0ebfc8e59501956195268673d0d980de58694f4741","src/shared/settings.rs":"bc6a15221d688bf63114c53493d31070860eb7fae208596374488404a65ee41a","src/shared/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/srcgen.rs":"72435db1e0c984d95c5c5aa758907ed79eaec41ca3203ac661c6acd64c19acce","src/unique_table.rs":"f6041df1fa85f2a1ee914b84791e80165a0858a6253c212eaa99ff67cb56af26"},"package":"3e60ce3551e8172c966fbc6d9bfb90111d5d1cf37306c37dd7527467afe317d1"}
|
@ -13,14 +13,14 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "Metaprogram for cranelift-codegen code generator library"
|
||||
readme = "README.md"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/CraneStation/cranelift"
|
||||
[dependencies.cranelift-entity]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
[badges.maintenance]
|
||||
status = "experimental"
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
//! Definitions for the base Cranelift language.
|
||||
|
||||
pub mod settings;
|
||||
pub mod types;
|
@ -1,192 +1,18 @@
|
||||
use cranelift_entity::PrimaryMap;
|
||||
|
||||
use super::regs::{
|
||||
RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex, RegClassProto,
|
||||
};
|
||||
use super::regs::IsaRegs;
|
||||
use super::settings::SettingGroup;
|
||||
|
||||
pub struct TargetIsa {
|
||||
pub name: &'static str,
|
||||
pub reg_banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
pub reg_classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
pub settings: SettingGroup,
|
||||
pub regs: IsaRegs,
|
||||
}
|
||||
|
||||
impl TargetIsa {
|
||||
pub fn new(name: &'static str, settings: SettingGroup) -> Self {
|
||||
pub fn new(name: &'static str, settings: SettingGroup, regs: IsaRegs) -> Self {
|
||||
Self {
|
||||
name,
|
||||
reg_banks: PrimaryMap::new(),
|
||||
reg_classes: PrimaryMap::new(),
|
||||
settings,
|
||||
regs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TargetIsaBuilder {
|
||||
isa: TargetIsa,
|
||||
}
|
||||
|
||||
impl TargetIsaBuilder {
|
||||
pub fn new(name: &'static str, settings: SettingGroup) -> Self {
|
||||
Self {
|
||||
isa: TargetIsa::new(name, settings),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_reg_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
|
||||
let first_unit = if self.isa.reg_banks.len() == 0 {
|
||||
0
|
||||
} else {
|
||||
let last = &self.isa.reg_banks.last().unwrap();
|
||||
let first_available_unit = (last.first_unit + last.units) as i8;
|
||||
let units = builder.units;
|
||||
let align = if units.is_power_of_two() {
|
||||
units
|
||||
} else {
|
||||
units.next_power_of_two()
|
||||
} as i8;
|
||||
(first_available_unit + align - 1) & -align
|
||||
} as u8;
|
||||
|
||||
self.isa.reg_banks.push(RegBank::new(
|
||||
builder.name,
|
||||
first_unit,
|
||||
builder.units,
|
||||
builder.names,
|
||||
builder.prefix,
|
||||
builder
|
||||
.pressure_tracking
|
||||
.expect("Pressure tracking must be explicitly set"),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn add_reg_class(&mut self, builder: RegClassBuilder) -> RegClassIndex {
|
||||
let class_index = self.isa.reg_classes.next_key();
|
||||
|
||||
// Finish delayed construction of RegClass.
|
||||
let (bank, toprc, start, width) = match builder.proto {
|
||||
RegClassProto::TopLevel(bank_index) => {
|
||||
self.isa
|
||||
.reg_banks
|
||||
.get_mut(bank_index)
|
||||
.unwrap()
|
||||
.toprcs
|
||||
.push(class_index);
|
||||
(bank_index, class_index, builder.start, builder.width)
|
||||
}
|
||||
RegClassProto::SubClass(parent_class_index) => {
|
||||
assert!(builder.width == 0);
|
||||
let (bank, toprc, start, width) = {
|
||||
let parent = self.isa.reg_classes.get(parent_class_index).unwrap();
|
||||
(parent.bank, parent.toprc, parent.start, parent.width)
|
||||
};
|
||||
for reg_class in self.isa.reg_classes.values_mut() {
|
||||
if reg_class.toprc == toprc {
|
||||
reg_class.subclasses.push(class_index);
|
||||
}
|
||||
}
|
||||
let subclass_start = start + builder.start * width;
|
||||
(bank, toprc, subclass_start, width)
|
||||
}
|
||||
};
|
||||
|
||||
let reg_bank_units = self.isa.reg_banks.get(bank).unwrap().units;
|
||||
assert!(start < reg_bank_units);
|
||||
|
||||
let count = if builder.count != 0 {
|
||||
builder.count
|
||||
} else {
|
||||
reg_bank_units / width
|
||||
};
|
||||
|
||||
let reg_class = RegClass::new(builder.name, class_index, width, bank, toprc, count, start);
|
||||
self.isa.reg_classes.push(reg_class);
|
||||
|
||||
let reg_bank = self.isa.reg_banks.get_mut(bank).unwrap();
|
||||
reg_bank.classes.push(class_index);
|
||||
|
||||
class_index
|
||||
}
|
||||
|
||||
/// Checks that the set of register classes satisfies:
|
||||
///
|
||||
/// 1. Closed under intersection: The intersection of any two register
|
||||
/// classes in the set is either empty or identical to a member of the
|
||||
/// set.
|
||||
/// 2. There are no identical classes under different names.
|
||||
/// 3. Classes are sorted topologically such that all subclasses have a
|
||||
/// higher index that the superclass.
|
||||
pub fn finish(self) -> TargetIsa {
|
||||
for reg_bank in self.isa.reg_banks.values() {
|
||||
for i1 in reg_bank.classes.iter() {
|
||||
for i2 in reg_bank.classes.iter() {
|
||||
if i1 >= i2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let rc1 = self.isa.reg_classes.get(*i1).unwrap();
|
||||
let rc2 = self.isa.reg_classes.get(*i2).unwrap();
|
||||
|
||||
let rc1_mask = rc1.mask(0);
|
||||
let rc2_mask = rc2.mask(0);
|
||||
|
||||
assert!(
|
||||
rc1.width != rc2.width || rc1_mask != rc2_mask,
|
||||
"no duplicates"
|
||||
);
|
||||
if rc1.width != rc2.width {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut intersect = Vec::new();
|
||||
for (a, b) in rc1_mask.iter().zip(rc2_mask.iter()) {
|
||||
intersect.push(a & b);
|
||||
}
|
||||
if intersect == vec![0; intersect.len()] {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Classes must be topologically ordered, so the intersection can't be the
|
||||
// superclass.
|
||||
assert!(intersect != rc1_mask);
|
||||
|
||||
// If the intersection is the second one, then it must be a subclass.
|
||||
if intersect == rc2_mask {
|
||||
assert!(self
|
||||
.isa
|
||||
.reg_classes
|
||||
.get(*i1)
|
||||
.unwrap()
|
||||
.subclasses
|
||||
.iter()
|
||||
.find(|x| **x == *i2)
|
||||
.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This limit should be coordinated with the `RegClassMask` and `RegClassIndex` types in
|
||||
// isa/registers.rs of the non-meta code.
|
||||
assert!(
|
||||
self.isa.reg_classes.len() <= 32,
|
||||
"Too many register classes"
|
||||
);
|
||||
|
||||
// The maximum number of top-level register classes which have pressure tracking should be
|
||||
// kept in sync with the MAX_TRACKED_TOPRCS constant in isa/registers.rs of the non-meta
|
||||
// code.
|
||||
let num_toplevel = self
|
||||
.isa
|
||||
.reg_classes
|
||||
.values()
|
||||
.filter(|x| {
|
||||
x.toprc == x.index && self.isa.reg_banks.get(x.bank).unwrap().pressure_tracking
|
||||
})
|
||||
.count();
|
||||
assert!(num_toplevel <= 4, "Too many top-level register classes");
|
||||
|
||||
self.isa
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use cranelift_entity::entity_impl;
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_entity::{entity_impl, EntityRef, PrimaryMap};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct RegBankIndex(u32);
|
||||
@ -178,3 +177,179 @@ impl RegBankBuilder {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IsaRegsBuilder {
|
||||
pub banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
pub classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
}
|
||||
|
||||
impl IsaRegsBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
banks: PrimaryMap::new(),
|
||||
classes: PrimaryMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
|
||||
let first_unit = if self.banks.len() == 0 {
|
||||
0
|
||||
} else {
|
||||
let last = &self.banks.last().unwrap();
|
||||
let first_available_unit = (last.first_unit + last.units) as i8;
|
||||
let units = builder.units;
|
||||
let align = if units.is_power_of_two() {
|
||||
units
|
||||
} else {
|
||||
units.next_power_of_two()
|
||||
} as i8;
|
||||
(first_available_unit + align - 1) & -align
|
||||
} as u8;
|
||||
|
||||
self.banks.push(RegBank::new(
|
||||
builder.name,
|
||||
first_unit,
|
||||
builder.units,
|
||||
builder.names,
|
||||
builder.prefix,
|
||||
builder
|
||||
.pressure_tracking
|
||||
.expect("Pressure tracking must be explicitly set"),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn add_class(&mut self, builder: RegClassBuilder) -> RegClassIndex {
|
||||
let class_index = self.classes.next_key();
|
||||
|
||||
// Finish delayed construction of RegClass.
|
||||
let (bank, toprc, start, width) = match builder.proto {
|
||||
RegClassProto::TopLevel(bank_index) => {
|
||||
self.banks
|
||||
.get_mut(bank_index)
|
||||
.unwrap()
|
||||
.toprcs
|
||||
.push(class_index);
|
||||
(bank_index, class_index, builder.start, builder.width)
|
||||
}
|
||||
RegClassProto::SubClass(parent_class_index) => {
|
||||
assert!(builder.width == 0);
|
||||
let (bank, toprc, start, width) = {
|
||||
let parent = self.classes.get(parent_class_index).unwrap();
|
||||
(parent.bank, parent.toprc, parent.start, parent.width)
|
||||
};
|
||||
for reg_class in self.classes.values_mut() {
|
||||
if reg_class.toprc == toprc {
|
||||
reg_class.subclasses.push(class_index);
|
||||
}
|
||||
}
|
||||
let subclass_start = start + builder.start * width;
|
||||
(bank, toprc, subclass_start, width)
|
||||
}
|
||||
};
|
||||
|
||||
let reg_bank_units = self.banks.get(bank).unwrap().units;
|
||||
assert!(start < reg_bank_units);
|
||||
|
||||
let count = if builder.count != 0 {
|
||||
builder.count
|
||||
} else {
|
||||
reg_bank_units / width
|
||||
};
|
||||
|
||||
let reg_class = RegClass::new(builder.name, class_index, width, bank, toprc, count, start);
|
||||
self.classes.push(reg_class);
|
||||
|
||||
let reg_bank = self.banks.get_mut(bank).unwrap();
|
||||
reg_bank.classes.push(class_index);
|
||||
|
||||
class_index
|
||||
}
|
||||
|
||||
/// Checks that the set of register classes satisfies:
|
||||
///
|
||||
/// 1. Closed under intersection: The intersection of any two register
|
||||
/// classes in the set is either empty or identical to a member of the
|
||||
/// set.
|
||||
/// 2. There are no identical classes under different names.
|
||||
/// 3. Classes are sorted topologically such that all subclasses have a
|
||||
/// higher index that the superclass.
|
||||
pub fn finish(self) -> IsaRegs {
|
||||
for reg_bank in self.banks.values() {
|
||||
for i1 in reg_bank.classes.iter() {
|
||||
for i2 in reg_bank.classes.iter() {
|
||||
if i1 >= i2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let rc1 = self.classes.get(*i1).unwrap();
|
||||
let rc2 = self.classes.get(*i2).unwrap();
|
||||
|
||||
let rc1_mask = rc1.mask(0);
|
||||
let rc2_mask = rc2.mask(0);
|
||||
|
||||
assert!(
|
||||
rc1.width != rc2.width || rc1_mask != rc2_mask,
|
||||
"no duplicates"
|
||||
);
|
||||
if rc1.width != rc2.width {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut intersect = Vec::new();
|
||||
for (a, b) in rc1_mask.iter().zip(rc2_mask.iter()) {
|
||||
intersect.push(a & b);
|
||||
}
|
||||
if intersect == vec![0; intersect.len()] {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Classes must be topologically ordered, so the intersection can't be the
|
||||
// superclass.
|
||||
assert!(intersect != rc1_mask);
|
||||
|
||||
// If the intersection is the second one, then it must be a subclass.
|
||||
if intersect == rc2_mask {
|
||||
assert!(self
|
||||
.classes
|
||||
.get(*i1)
|
||||
.unwrap()
|
||||
.subclasses
|
||||
.iter()
|
||||
.find(|x| **x == *i2)
|
||||
.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This limit should be coordinated with the `RegClassMask` and `RegClassIndex` types in
|
||||
// isa/registers.rs of the non-meta code.
|
||||
assert!(self.classes.len() <= 32, "Too many register classes");
|
||||
|
||||
// The maximum number of top-level register classes which have pressure tracking should be
|
||||
// kept in sync with the MAX_TRACKED_TOPRCS constant in isa/registers.rs of the non-meta
|
||||
// code.
|
||||
let num_toplevel = self
|
||||
.classes
|
||||
.values()
|
||||
.filter(|x| x.toprc == x.index && self.banks.get(x.bank).unwrap().pressure_tracking)
|
||||
.count();
|
||||
assert!(num_toplevel <= 4, "Too many top-level register classes");
|
||||
|
||||
IsaRegs::new(self.banks, self.classes)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IsaRegs {
|
||||
pub banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
pub classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
}
|
||||
|
||||
impl IsaRegs {
|
||||
fn new(
|
||||
banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
) -> Self {
|
||||
Self { banks, classes }
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::base::types as base_types;
|
||||
use crate::shared::types as shared_types;
|
||||
|
||||
// Numbering scheme for value types:
|
||||
//
|
||||
@ -149,9 +149,9 @@ impl From<VectorType> for ValueType {
|
||||
/// A concrete scalar type that can appear as a vector lane too.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum LaneType {
|
||||
BoolType(base_types::Bool),
|
||||
FloatType(base_types::Float),
|
||||
IntType(base_types::Int),
|
||||
BoolType(shared_types::Bool),
|
||||
FloatType(shared_types::Float),
|
||||
IntType(shared_types::Int),
|
||||
}
|
||||
|
||||
impl LaneType {
|
||||
@ -159,12 +159,12 @@ impl LaneType {
|
||||
pub fn doc(self) -> String {
|
||||
match self {
|
||||
LaneType::BoolType(_) => format!("A boolean type with {} bits.", self.lane_bits()),
|
||||
LaneType::FloatType(base_types::Float::F32) => String::from(
|
||||
LaneType::FloatType(shared_types::Float::F32) => String::from(
|
||||
"A 32-bit floating point type represented in the IEEE 754-2008
|
||||
*binary32* interchange format. This corresponds to the :c:type:`float`
|
||||
type in most C implementations.",
|
||||
),
|
||||
LaneType::FloatType(base_types::Float::F64) => String::from(
|
||||
LaneType::FloatType(shared_types::Float::F64) => String::from(
|
||||
"A 64-bit floating point type represented in the IEEE 754-2008
|
||||
*binary64* interchange format. This corresponds to the :c:type:`double`
|
||||
type in most C implementations.",
|
||||
@ -192,17 +192,17 @@ impl LaneType {
|
||||
pub fn number(self) -> u8 {
|
||||
LANE_BASE
|
||||
+ match self {
|
||||
LaneType::BoolType(base_types::Bool::B1) => 0,
|
||||
LaneType::BoolType(base_types::Bool::B8) => 1,
|
||||
LaneType::BoolType(base_types::Bool::B16) => 2,
|
||||
LaneType::BoolType(base_types::Bool::B32) => 3,
|
||||
LaneType::BoolType(base_types::Bool::B64) => 4,
|
||||
LaneType::IntType(base_types::Int::I8) => 5,
|
||||
LaneType::IntType(base_types::Int::I16) => 6,
|
||||
LaneType::IntType(base_types::Int::I32) => 7,
|
||||
LaneType::IntType(base_types::Int::I64) => 8,
|
||||
LaneType::FloatType(base_types::Float::F32) => 9,
|
||||
LaneType::FloatType(base_types::Float::F64) => 10,
|
||||
LaneType::BoolType(shared_types::Bool::B1) => 0,
|
||||
LaneType::BoolType(shared_types::Bool::B8) => 1,
|
||||
LaneType::BoolType(shared_types::Bool::B16) => 2,
|
||||
LaneType::BoolType(shared_types::Bool::B32) => 3,
|
||||
LaneType::BoolType(shared_types::Bool::B64) => 4,
|
||||
LaneType::IntType(shared_types::Int::I8) => 5,
|
||||
LaneType::IntType(shared_types::Int::I16) => 6,
|
||||
LaneType::IntType(shared_types::Int::I32) => 7,
|
||||
LaneType::IntType(shared_types::Int::I64) => 8,
|
||||
LaneType::FloatType(shared_types::Float::F32) => 9,
|
||||
LaneType::FloatType(shared_types::Float::F64) => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -233,40 +233,40 @@ impl fmt::Debug for LaneType {
|
||||
}
|
||||
|
||||
/// Create a LaneType from a given bool variant.
|
||||
impl From<base_types::Bool> for LaneType {
|
||||
fn from(b: base_types::Bool) -> Self {
|
||||
impl From<shared_types::Bool> for LaneType {
|
||||
fn from(b: shared_types::Bool) -> Self {
|
||||
LaneType::BoolType(b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a LaneType from a given float variant.
|
||||
impl From<base_types::Float> for LaneType {
|
||||
fn from(f: base_types::Float) -> Self {
|
||||
impl From<shared_types::Float> for LaneType {
|
||||
fn from(f: shared_types::Float) -> Self {
|
||||
LaneType::FloatType(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a LaneType from a given int variant.
|
||||
impl From<base_types::Int> for LaneType {
|
||||
fn from(i: base_types::Int) -> Self {
|
||||
impl From<shared_types::Int> for LaneType {
|
||||
fn from(i: shared_types::Int) -> Self {
|
||||
LaneType::IntType(i)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator for different lane types.
|
||||
pub struct LaneTypeIterator {
|
||||
bool_iter: base_types::BoolIterator,
|
||||
int_iter: base_types::IntIterator,
|
||||
float_iter: base_types::FloatIterator,
|
||||
bool_iter: shared_types::BoolIterator,
|
||||
int_iter: shared_types::IntIterator,
|
||||
float_iter: shared_types::FloatIterator,
|
||||
}
|
||||
|
||||
impl LaneTypeIterator {
|
||||
/// Create a new lane type iterator.
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
bool_iter: base_types::BoolIterator::new(),
|
||||
int_iter: base_types::IntIterator::new(),
|
||||
float_iter: base_types::FloatIterator::new(),
|
||||
bool_iter: shared_types::BoolIterator::new(),
|
||||
int_iter: shared_types::IntIterator::new(),
|
||||
float_iter: shared_types::FloatIterator::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -388,18 +388,18 @@ impl fmt::Debug for BVType {
|
||||
/// Special types cannot be used to form vectors.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum SpecialType {
|
||||
Flag(base_types::Flag),
|
||||
Flag(shared_types::Flag),
|
||||
}
|
||||
|
||||
impl SpecialType {
|
||||
/// Return a string containing the documentation comment for this special type.
|
||||
pub fn doc(self) -> String {
|
||||
match self {
|
||||
SpecialType::Flag(base_types::Flag::IFlags) => String::from(
|
||||
SpecialType::Flag(shared_types::Flag::IFlags) => String::from(
|
||||
"CPU flags representing the result of an integer comparison. These flags
|
||||
can be tested with an :type:`intcc` condition code.",
|
||||
),
|
||||
SpecialType::Flag(base_types::Flag::FFlags) => String::from(
|
||||
SpecialType::Flag(shared_types::Flag::FFlags) => String::from(
|
||||
"CPU flags representing the result of a floating point comparison. These
|
||||
flags can be tested with a :type:`floatcc` condition code.",
|
||||
),
|
||||
@ -416,8 +416,8 @@ impl SpecialType {
|
||||
/// Find the unique number associated with this special type.
|
||||
pub fn number(self) -> u8 {
|
||||
match self {
|
||||
SpecialType::Flag(base_types::Flag::IFlags) => 1,
|
||||
SpecialType::Flag(base_types::Flag::FFlags) => 2,
|
||||
SpecialType::Flag(shared_types::Flag::IFlags) => 1,
|
||||
SpecialType::Flag(shared_types::Flag::FFlags) => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -425,8 +425,8 @@ impl SpecialType {
|
||||
impl fmt::Display for SpecialType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
SpecialType::Flag(base_types::Flag::IFlags) => write!(f, "iflags"),
|
||||
SpecialType::Flag(base_types::Flag::FFlags) => write!(f, "fflags"),
|
||||
SpecialType::Flag(shared_types::Flag::IFlags) => write!(f, "iflags"),
|
||||
SpecialType::Flag(shared_types::Flag::FFlags) => write!(f, "fflags"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -443,20 +443,20 @@ impl fmt::Debug for SpecialType {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<base_types::Flag> for SpecialType {
|
||||
fn from(f: base_types::Flag) -> Self {
|
||||
impl From<shared_types::Flag> for SpecialType {
|
||||
fn from(f: shared_types::Flag) -> Self {
|
||||
SpecialType::Flag(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpecialTypeIterator {
|
||||
flag_iter: base_types::FlagIterator,
|
||||
flag_iter: shared_types::FlagIterator,
|
||||
}
|
||||
|
||||
impl SpecialTypeIterator {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
flag_iter: base_types::FlagIterator::new(),
|
||||
flag_iter: shared_types::FlagIterator::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,29 +10,30 @@ fn gen_regbank(fmt: &mut Formatter, reg_bank: &RegBank) {
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
fmt.line("RegBank {");
|
||||
fmtln!(fmt, "RegBank {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!(r#"name: "{}","#, reg_bank.name));
|
||||
fmt.line(&format!("first_unit: {},", reg_bank.first_unit));
|
||||
fmt.line(&format!("units: {},", reg_bank.units));
|
||||
fmt.line(&format!("names: &[{}],", names));
|
||||
fmt.line(&format!(r#"prefix: "{}","#, reg_bank.prefix));
|
||||
fmt.line(&format!("first_toprc: {},", reg_bank.toprcs[0].index()));
|
||||
fmt.line(&format!("num_toprcs: {},", reg_bank.toprcs.len()));
|
||||
fmt.line(&format!(
|
||||
fmtln!(fmt, r#"name: "{}","#, reg_bank.name);
|
||||
fmtln!(fmt, "first_unit: {},", reg_bank.first_unit);
|
||||
fmtln!(fmt, "units: {},", reg_bank.units);
|
||||
fmtln!(fmt, "names: &[{}],", names);
|
||||
fmtln!(fmt, r#"prefix: "{}","#, reg_bank.prefix);
|
||||
fmtln!(fmt, "first_toprc: {},", reg_bank.toprcs[0].index());
|
||||
fmtln!(fmt, "num_toprcs: {},", reg_bank.toprcs.len());
|
||||
fmtln!(
|
||||
fmt,
|
||||
"pressure_tracking: {},",
|
||||
if reg_bank.pressure_tracking {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
}
|
||||
));
|
||||
);
|
||||
});
|
||||
fmt.line("},");
|
||||
fmtln!(fmt, "},");
|
||||
}
|
||||
|
||||
fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
|
||||
let reg_bank = isa.reg_banks.get(reg_class.bank).unwrap();
|
||||
let reg_bank = isa.regs.banks.get(reg_class.bank).unwrap();
|
||||
|
||||
let mask: Vec<String> = reg_class
|
||||
.mask(reg_bank.first_unit)
|
||||
@ -41,98 +42,99 @@ fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
|
||||
.collect();
|
||||
let mask = mask.join(", ");
|
||||
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"pub static {}_DATA: RegClassData = RegClassData {{",
|
||||
reg_class.name
|
||||
));
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!(r#"name: "{}","#, reg_class.name));
|
||||
fmt.line(&format!("index: {},", reg_class.index.index()));
|
||||
fmt.line(&format!("width: {},", reg_class.width));
|
||||
fmt.line(&format!("bank: {},", reg_class.bank.index()));
|
||||
fmt.line(&format!("toprc: {},", reg_class.toprc.index()));
|
||||
fmt.line(&format!(
|
||||
"first: {},",
|
||||
reg_bank.first_unit + reg_class.start
|
||||
));
|
||||
fmt.line(&format!("subclasses: {:#x},", reg_class.subclass_mask()));
|
||||
fmt.line(&format!("mask: [{}],", mask));
|
||||
fmt.line("info: &INFO,");
|
||||
fmtln!(fmt, r#"name: "{}","#, reg_class.name);
|
||||
fmtln!(fmt, "index: {},", reg_class.index.index());
|
||||
fmtln!(fmt, "width: {},", reg_class.width);
|
||||
fmtln!(fmt, "bank: {},", reg_class.bank.index());
|
||||
fmtln!(fmt, "toprc: {},", reg_class.toprc.index());
|
||||
fmtln!(fmt, "first: {},", reg_bank.first_unit + reg_class.start);
|
||||
fmtln!(fmt, "subclasses: {:#x},", reg_class.subclass_mask());
|
||||
fmtln!(fmt, "mask: [{}],", mask);
|
||||
fmtln!(fmt, "info: &INFO,");
|
||||
});
|
||||
fmt.line("};");
|
||||
fmt.line("#[allow(dead_code)]");
|
||||
fmt.line(&format!(
|
||||
fmtln!(fmt, "};");
|
||||
|
||||
fmtln!(fmt, "#[allow(dead_code)]");
|
||||
fmtln!(
|
||||
fmt,
|
||||
"pub static {}: RegClass = &{}_DATA;",
|
||||
reg_class.name, reg_class.name
|
||||
));
|
||||
reg_class.name,
|
||||
reg_class.name
|
||||
);
|
||||
}
|
||||
|
||||
fn gen_regbank_units(reg_bank: &RegBank, fmt: &mut Formatter) {
|
||||
for unit in 0..reg_bank.units {
|
||||
let v = unit + reg_bank.first_unit;
|
||||
if (unit as usize) < reg_bank.names.len() {
|
||||
fmt.line(&format!("{} = {},", reg_bank.names[unit as usize], v));
|
||||
fmtln!(fmt, "{} = {},", reg_bank.names[unit as usize], v);
|
||||
continue;
|
||||
}
|
||||
fmt.line(&format!("{}{} = {},", reg_bank.prefix, unit, v));
|
||||
fmtln!(fmt, "{}{} = {},", reg_bank.prefix, unit, v);
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||
// Emit RegInfo.
|
||||
fmt.line("pub static INFO: RegInfo = RegInfo {");
|
||||
fmtln!(fmt, "pub static INFO: RegInfo = RegInfo {");
|
||||
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("banks: &[");
|
||||
fmtln!(fmt, "banks: &[");
|
||||
// Bank descriptors.
|
||||
fmt.indent(|fmt| {
|
||||
for reg_bank in isa.reg_banks.values() {
|
||||
for reg_bank in isa.regs.banks.values() {
|
||||
gen_regbank(fmt, ®_bank);
|
||||
}
|
||||
});
|
||||
fmt.line("],");
|
||||
fmtln!(fmt, "],");
|
||||
// References to register classes.
|
||||
fmt.line("classes: &[");
|
||||
fmtln!(fmt, "classes: &[");
|
||||
fmt.indent(|fmt| {
|
||||
for reg_class in isa.reg_classes.values() {
|
||||
fmt.line(&format!("&{}_DATA,", reg_class.name));
|
||||
for reg_class in isa.regs.classes.values() {
|
||||
fmtln!(fmt, "&{}_DATA,", reg_class.name);
|
||||
}
|
||||
});
|
||||
fmt.line("],");
|
||||
fmtln!(fmt, "],");
|
||||
});
|
||||
fmt.line("};");
|
||||
fmtln!(fmt, "};");
|
||||
|
||||
// Register class descriptors.
|
||||
for rc in isa.reg_classes.values() {
|
||||
for rc in isa.regs.classes.values() {
|
||||
gen_regclass(&isa, rc, fmt);
|
||||
}
|
||||
|
||||
// Emit constants for all the register units.
|
||||
fmt.line("#[allow(dead_code, non_camel_case_types)]");
|
||||
fmt.line("#[derive(Clone, Copy)]");
|
||||
fmt.line("pub enum RU {");
|
||||
fmtln!(fmt, "#[allow(dead_code, non_camel_case_types)]");
|
||||
fmtln!(fmt, "#[derive(Clone, Copy)]");
|
||||
fmtln!(fmt, "pub enum RU {");
|
||||
fmt.indent(|fmt| {
|
||||
for reg_bank in isa.reg_banks.values() {
|
||||
for reg_bank in isa.regs.banks.values() {
|
||||
gen_regbank_units(reg_bank, fmt);
|
||||
}
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
|
||||
// Emit Into conversion for the RU class.
|
||||
fmt.line("impl Into<RegUnit> for RU {");
|
||||
fmtln!(fmt, "impl Into<RegUnit> for RU {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("fn into(self) -> RegUnit {");
|
||||
fmtln!(fmt, "fn into(self) -> RegUnit {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("self as RegUnit");
|
||||
fmtln!(fmt, "self as RegUnit");
|
||||
});
|
||||
fmt.line("}")
|
||||
fmtln!(fmt, "}");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
pub fn generate(isa: &TargetIsa, base_filename: &str, out_dir: &str) -> Result<(), error::Error> {
|
||||
let mut fmt = Formatter::new();
|
||||
gen_isa(&isa, &mut fmt);
|
||||
fmt.update_file(&format!("{}-{}.rs", base_filename, isa.name), out_dir)?;
|
||||
fmt.update_file(format!("{}-{}.rs", base_filename, isa.name), out_dir)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::base;
|
||||
use crate::cdsl::camel_case;
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::settings::{
|
||||
@ -6,6 +5,7 @@ use crate::cdsl::settings::{
|
||||
};
|
||||
use crate::constant_hash::{generate_table, simple_hash};
|
||||
use crate::error;
|
||||
use crate::shared;
|
||||
use crate::srcgen::{Formatter, Match};
|
||||
use crate::unique_table::UniqueTable;
|
||||
use std::collections::HashMap;
|
||||
@ -21,87 +21,92 @@ fn gen_constructor(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatte
|
||||
ParentGroup::None => "builder: Builder",
|
||||
ParentGroup::Shared => "shared: &settings::Flags, builder: Builder",
|
||||
};
|
||||
fmt.line("impl Flags {");
|
||||
fmtln!(fmt, "impl Flags {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.doc_comment(&format!("Create flags {} settings group.", group.name));
|
||||
fmt.line("#[allow(unused_variables)]");
|
||||
fmt.line(&format!("pub fn new({}) -> Self {{", args));
|
||||
fmt.doc_comment(format!("Create flags {} settings group.", group.name));
|
||||
fmtln!(fmt, "#[allow(unused_variables)]");
|
||||
fmtln!(fmt, "pub fn new({}) -> Self {{", args);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!(
|
||||
"let bvec = builder.state_for(\"{}\");",
|
||||
group.name
|
||||
));
|
||||
fmt.line(&format!(
|
||||
fmtln!(fmt, "let bvec = builder.state_for(\"{}\");", group.name);
|
||||
fmtln!(
|
||||
fmt,
|
||||
"let mut {} = Self {{ bytes: [0; {}] }};",
|
||||
group.name,
|
||||
group.byte_size()
|
||||
));
|
||||
fmt.line(&format!(
|
||||
);
|
||||
fmtln!(
|
||||
fmt,
|
||||
"debug_assert_eq!(bvec.len(), {});",
|
||||
group.settings_size
|
||||
));
|
||||
fmt.line(&format!(
|
||||
);
|
||||
fmtln!(
|
||||
fmt,
|
||||
"{}.bytes[0..{}].copy_from_slice(&bvec);",
|
||||
group.name, group.settings_size
|
||||
));
|
||||
group.name,
|
||||
group.settings_size
|
||||
);
|
||||
|
||||
// Now compute the predicates.
|
||||
for p in &group.predicates {
|
||||
fmt.comment(&format!("Precompute #{}.", p.number));
|
||||
fmt.line(&format!("if {} {{", p.render(group)));
|
||||
fmt.comment(format!("Precompute #{}.", p.number));
|
||||
fmtln!(fmt, "if {} {{", p.render(group));
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"{}.bytes[{}] |= 1 << {};",
|
||||
group.name,
|
||||
group.bool_start_byte_offset + p.number / 8,
|
||||
p.number % 8
|
||||
));
|
||||
);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
fmt.line(group.name);
|
||||
fmtln!(fmt, group.name);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
/// Emit Display and FromStr implementations for enum settings.
|
||||
fn gen_to_and_from_str(name: &str, values: &[&'static str], fmt: &mut Formatter) {
|
||||
fmt.line(&format!("impl fmt::Display for {} {{", name));
|
||||
fmtln!(fmt, "impl fmt::Display for {} {{", name);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {");
|
||||
fmtln!(
|
||||
fmt,
|
||||
"fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {"
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("f.write_str(match *self {");
|
||||
fmtln!(fmt, "f.write_str(match *self {");
|
||||
fmt.indent(|fmt| {
|
||||
for v in values.iter() {
|
||||
fmt.line(&format!("{}::{} => \"{}\",", name, camel_case(v), v));
|
||||
fmtln!(fmt, "{}::{} => \"{}\",", name, camel_case(v), v);
|
||||
}
|
||||
});
|
||||
fmt.line("})");
|
||||
fmtln!(fmt, "})");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
|
||||
fmt.line(&format!("impl str::FromStr for {} {{", name));
|
||||
fmtln!(fmt, "impl str::FromStr for {} {{", name);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("type Err = ();");
|
||||
fmt.line("fn from_str(s: &str) -> Result<Self, Self::Err> {");
|
||||
fmtln!(fmt, "type Err = ();");
|
||||
fmtln!(fmt, "fn from_str(s: &str) -> Result<Self, Self::Err> {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("match s {");
|
||||
fmtln!(fmt, "match s {");
|
||||
fmt.indent(|fmt| {
|
||||
for v in values.iter() {
|
||||
fmt.line(&format!("\"{}\" => Ok({}::{}),", v, name, camel_case(v)));
|
||||
fmtln!(fmt, "\"{}\" => Ok({}::{}),", v, name, camel_case(v));
|
||||
}
|
||||
fmt.line("_ => Err(()),");
|
||||
fmtln!(fmt, "_ => Err(()),");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
/// Emit real enum for the Enum settings.
|
||||
@ -113,16 +118,16 @@ fn gen_enum_types(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
};
|
||||
let name = camel_case(setting.name);
|
||||
|
||||
fmt.doc_comment(&format!("Values for `{}.{}`.", group.name, setting.name));
|
||||
fmt.line("#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]");
|
||||
fmt.line(&format!("pub enum {} {{", name));
|
||||
fmt.doc_comment(format!("Values for `{}.{}`.", group.name, setting.name));
|
||||
fmtln!(fmt, "#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]");
|
||||
fmtln!(fmt, "pub enum {} {{", name);
|
||||
fmt.indent(|fmt| {
|
||||
for v in values.iter() {
|
||||
fmt.doc_comment(&format!("`{}`.", v));
|
||||
fmt.line(&format!("{},", camel_case(v)));
|
||||
fmt.doc_comment(format!("`{}`.", v));
|
||||
fmtln!(fmt, "{},", camel_case(v));
|
||||
}
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
|
||||
gen_to_and_from_str(&name, values, fmt);
|
||||
}
|
||||
@ -135,15 +140,15 @@ fn gen_getter(setting: &Setting, fmt: &mut Formatter) {
|
||||
SpecificSetting::Bool(BoolSetting {
|
||||
predicate_number, ..
|
||||
}) => {
|
||||
fmt.line(&format!("pub fn {}(&self) -> bool {{", setting.name));
|
||||
fmtln!(fmt, "pub fn {}(&self) -> bool {{", setting.name);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("self.numbered_predicate({})", predicate_number));
|
||||
fmtln!(fmt, "self.numbered_predicate({})", predicate_number);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
SpecificSetting::Enum(ref values) => {
|
||||
let ty = camel_case(setting.name);
|
||||
fmt.line(&format!("pub fn {}(&self) -> {} {{", setting.name, ty));
|
||||
fmtln!(fmt, "pub fn {}(&self) -> {} {{", setting.name, ty);
|
||||
fmt.indent(|fmt| {
|
||||
let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset));
|
||||
for (i, v) in values.iter().enumerate() {
|
||||
@ -156,56 +161,58 @@ fn gen_getter(setting: &Setting, fmt: &mut Formatter) {
|
||||
m.arm("_", vec![], "panic!(\"Invalid enum value\")");
|
||||
fmt.add_match(m);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
SpecificSetting::Num(_) => {
|
||||
fmt.line(&format!("pub fn {}(&self) -> u8 {{", setting.name));
|
||||
fmtln!(fmt, "pub fn {}(&self) -> u8 {{", setting.name);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("self.bytes[{}]", setting.byte_offset));
|
||||
fmtln!(fmt, "self.bytes[{}]", setting.byte_offset);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_pred_getter(predicate: &Predicate, group: &SettingGroup, fmt: &mut Formatter) {
|
||||
fmt.doc_comment(&format!(
|
||||
"Computed predicate `{}`.",
|
||||
predicate.render(group)
|
||||
));
|
||||
fmt.line(&format!("pub fn {}(&self) -> bool {{", predicate.name));
|
||||
fmt.doc_comment(format!("Computed predicate `{}`.", predicate.render(group)));
|
||||
fmtln!(fmt, "pub fn {}(&self) -> bool {{", predicate.name);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("self.numbered_predicate({})", predicate.number));
|
||||
fmtln!(fmt, "self.numbered_predicate({})", predicate.number);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
/// Emits getters for each setting value.
|
||||
fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
fmt.doc_comment("User-defined settings.");
|
||||
fmt.line("#[allow(dead_code)]");
|
||||
fmt.line("impl Flags {");
|
||||
fmtln!(fmt, "#[allow(dead_code)]");
|
||||
fmtln!(fmt, "impl Flags {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.doc_comment("Get a view of the boolean predicates.");
|
||||
fmt.line("pub fn predicate_view(&self) -> ::settings::PredicateView {");
|
||||
fmtln!(
|
||||
fmt,
|
||||
"pub fn predicate_view(&self) -> ::settings::PredicateView {"
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"::settings::PredicateView::new(&self.bytes[{}..])",
|
||||
group.bool_start_byte_offset
|
||||
));
|
||||
);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
|
||||
if group.settings.len() > 0 {
|
||||
fmt.doc_comment("Dynamic numbered predicate getter.");
|
||||
fmt.line("fn numbered_predicate(&self, p: usize) -> bool {");
|
||||
fmtln!(fmt, "fn numbered_predicate(&self, p: usize) -> bool {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"self.bytes[{} + p / 8] & (1 << (p % 8)) != 0",
|
||||
group.bool_start_byte_offset
|
||||
));
|
||||
);
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
for setting in &group.settings {
|
||||
@ -215,7 +222,7 @@ fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
gen_pred_getter(&predicate, &group, fmt);
|
||||
}
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
@ -240,66 +247,66 @@ fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
let mut descriptor_index_map: HashMap<SettingOrPreset, usize> = HashMap::new();
|
||||
|
||||
// Generate descriptors.
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"static DESCRIPTORS: [detail::Descriptor; {}] = [",
|
||||
group.settings.len() + group.presets.len()
|
||||
));
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
for (idx, setting) in group.settings.iter().enumerate() {
|
||||
fmt.line("detail::Descriptor {");
|
||||
fmtln!(fmt, "detail::Descriptor {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("name: \"{}\",", setting.name));
|
||||
fmt.line(&format!("offset: {},", setting.byte_offset));
|
||||
fmtln!(fmt, "name: \"{}\",", setting.name);
|
||||
fmtln!(fmt, "offset: {},", setting.byte_offset);
|
||||
match setting.specific {
|
||||
SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => {
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"detail: detail::Detail::Bool {{ bit: {} }},",
|
||||
bit_offset
|
||||
));
|
||||
);
|
||||
}
|
||||
SpecificSetting::Enum(ref values) => {
|
||||
let offset = enum_table.add(values);
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"detail: detail::Detail::Enum {{ last: {}, enumerators: {} }},",
|
||||
values.len() - 1,
|
||||
offset
|
||||
));
|
||||
);
|
||||
}
|
||||
SpecificSetting::Num(_) => {
|
||||
fmt.line("detail: detail::Detail::Num,");
|
||||
fmtln!(fmt, "detail: detail::Detail::Num,");
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_index_map.insert(SettingOrPreset::Setting(setting), idx);
|
||||
});
|
||||
fmt.line("},");
|
||||
fmtln!(fmt, "},");
|
||||
}
|
||||
|
||||
for (idx, preset) in group.presets.iter().enumerate() {
|
||||
fmt.line("detail::Descriptor {");
|
||||
fmtln!(fmt, "detail::Descriptor {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("name: \"{}\",", preset.name));
|
||||
fmt.line(&format!("offset: {},", (idx as u8) * group.settings_size));
|
||||
fmt.line("detail: detail::Detail::Preset,");
|
||||
fmtln!(fmt, "name: \"{}\",", preset.name);
|
||||
fmtln!(fmt, "offset: {},", (idx as u8) * group.settings_size);
|
||||
fmtln!(fmt, "detail: detail::Detail::Preset,");
|
||||
});
|
||||
fmt.line("},");
|
||||
fmtln!(fmt, "},");
|
||||
|
||||
descriptor_index_map.insert(SettingOrPreset::Preset(preset), idx);
|
||||
}
|
||||
});
|
||||
fmt.line("];");
|
||||
fmtln!(fmt, "];");
|
||||
|
||||
// Generate enumerators.
|
||||
fmt.line(&format!(
|
||||
"static ENUMERATORS: [&str; {}] = [",
|
||||
enum_table.len()
|
||||
));
|
||||
fmtln!(fmt, "static ENUMERATORS: [&str; {}] = [", enum_table.len());
|
||||
fmt.indent(|fmt| {
|
||||
for enum_val in enum_table.iter() {
|
||||
fmt.line(&format!("\"{}\",", enum_val));
|
||||
fmtln!(fmt, "\"{}\",", enum_val);
|
||||
}
|
||||
});
|
||||
fmt.line("];");
|
||||
fmtln!(fmt, "];");
|
||||
|
||||
// Generate hash table.
|
||||
let mut hash_entries: Vec<SettingOrPreset> = Vec::new();
|
||||
@ -318,40 +325,39 @@ fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
.collect::<Vec<SettingOrPreset>>(),
|
||||
);
|
||||
let hash_table = generate_table(&hash_entries, |entry| simple_hash(entry.name()));
|
||||
fmt.line(&format!(
|
||||
"static HASH_TABLE: [u16; {}] = [",
|
||||
hash_table.len()
|
||||
));
|
||||
fmtln!(fmt, "static HASH_TABLE: [u16; {}] = [", hash_table.len());
|
||||
fmt.indent(|fmt| {
|
||||
for h in &hash_table {
|
||||
match *h {
|
||||
Some(setting_or_preset) => fmt.line(&format!(
|
||||
Some(setting_or_preset) => fmtln!(
|
||||
fmt,
|
||||
"{},",
|
||||
&descriptor_index_map
|
||||
.get(setting_or_preset)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
)),
|
||||
None => fmt.line("0xffff,"),
|
||||
),
|
||||
None => fmtln!(fmt, "0xffff,"),
|
||||
}
|
||||
}
|
||||
});
|
||||
fmt.line("];");
|
||||
fmtln!(fmt, "];");
|
||||
|
||||
// Generate presets.
|
||||
fmt.line(&format!(
|
||||
fmtln!(
|
||||
fmt,
|
||||
"static PRESETS: [(u8, u8); {}] = [",
|
||||
group.presets.len()
|
||||
));
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
for preset in &group.presets {
|
||||
fmt.comment(preset.name);
|
||||
for (mask, value) in preset.layout(&group) {
|
||||
fmt.line(&format!("(0b{:08b}, 0b{:08b}),", mask, value));
|
||||
fmtln!(fmt, "(0b{:08b}, 0b{:08b}),", mask, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
fmt.line("];");
|
||||
fmtln!(fmt, "];");
|
||||
}
|
||||
|
||||
fn gen_template(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
@ -366,63 +372,70 @@ fn gen_template(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
.collect();
|
||||
let default_bytes_str = default_bytes.join(", ");
|
||||
|
||||
fmt.line("static TEMPLATE: detail::Template = detail::Template {");
|
||||
fmtln!(
|
||||
fmt,
|
||||
"static TEMPLATE: detail::Template = detail::Template {"
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("name: \"{}\",", group.name));
|
||||
fmt.line("descriptors: &DESCRIPTORS,");
|
||||
fmt.line("enumerators: &ENUMERATORS,");
|
||||
fmt.line("hash_table: &HASH_TABLE,");
|
||||
fmt.line(&format!("defaults: &[{}],", default_bytes_str));
|
||||
fmt.line("presets: &PRESETS,");
|
||||
fmtln!(fmt, "name: \"{}\",", group.name);
|
||||
fmtln!(fmt, "descriptors: &DESCRIPTORS,");
|
||||
fmtln!(fmt, "enumerators: &ENUMERATORS,");
|
||||
fmtln!(fmt, "hash_table: &HASH_TABLE,");
|
||||
fmtln!(fmt, "defaults: &[{}],", default_bytes_str);
|
||||
fmtln!(fmt, "presets: &PRESETS,");
|
||||
});
|
||||
fmt.line("};");
|
||||
fmtln!(fmt, "};");
|
||||
|
||||
fmt.doc_comment(&format!(
|
||||
fmt.doc_comment(format!(
|
||||
"Create a `settings::Builder` for the {} settings group.",
|
||||
group.name
|
||||
));
|
||||
fmt.line("pub fn builder() -> Builder {");
|
||||
fmtln!(fmt, "pub fn builder() -> Builder {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("Builder::new(&TEMPLATE)");
|
||||
fmtln!(fmt, "Builder::new(&TEMPLATE)");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
fn gen_display(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
fmt.line("impl fmt::Display for Flags {");
|
||||
fmtln!(fmt, "impl fmt::Display for Flags {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {");
|
||||
fmtln!(
|
||||
fmt,
|
||||
"fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {"
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("writeln!(f, \"[{}]\")?;", group.name));
|
||||
fmt.line("for d in &DESCRIPTORS {");
|
||||
fmtln!(fmt, "writeln!(f, \"[{}]\")?;", group.name);
|
||||
fmtln!(fmt, "for d in &DESCRIPTORS {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("if !d.detail.is_preset() {");
|
||||
fmtln!(fmt, "if !d.detail.is_preset() {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("write!(f, \"{} = \", d.name)?;");
|
||||
fmt.line(
|
||||
fmtln!(fmt, "write!(f, \"{} = \", d.name)?;");
|
||||
fmtln!(
|
||||
fmt,
|
||||
"TEMPLATE.format_toml_value(d.detail, self.bytes[d.offset as usize], f)?;",
|
||||
);
|
||||
fmt.line("writeln!(f)?;");
|
||||
fmtln!(fmt, "writeln!(f)?;");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
});
|
||||
fmt.line("}");
|
||||
fmt.line("Ok(())");
|
||||
fmtln!(fmt, "}");
|
||||
fmtln!(fmt, "Ok(())");
|
||||
});
|
||||
fmt.line("}")
|
||||
fmtln!(fmt, "}")
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
}
|
||||
|
||||
fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) {
|
||||
// Generate struct.
|
||||
fmt.line("#[derive(Clone)]");
|
||||
fmt.doc_comment(&format!("Flags group `{}`.", group.name));
|
||||
fmt.line("pub struct Flags {");
|
||||
fmtln!(fmt, "#[derive(Clone)]");
|
||||
fmt.doc_comment(format!("Flags group `{}`.", group.name));
|
||||
fmtln!(fmt, "pub struct Flags {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(&format!("bytes: [u8; {}],", group.byte_size()));
|
||||
fmtln!(fmt, "bytes: [u8; {}],", group.byte_size());
|
||||
});
|
||||
fmt.line("}");
|
||||
fmtln!(fmt, "}");
|
||||
|
||||
gen_constructor(group, parent, fmt);
|
||||
gen_enum_types(group, fmt);
|
||||
@ -433,7 +446,7 @@ fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) {
|
||||
}
|
||||
|
||||
pub fn generate_common(filename: &str, out_dir: &str) -> Result<SettingGroup, error::Error> {
|
||||
let settings = base::settings::generate();
|
||||
let settings = shared::settings::generate();
|
||||
let mut fmt = Formatter::new();
|
||||
gen_group(&settings, ParentGroup::None, &mut fmt);
|
||||
fmt.update_file(filename, out_dir)?;
|
||||
@ -443,6 +456,6 @@ pub fn generate_common(filename: &str, out_dir: &str) -> Result<SettingGroup, er
|
||||
pub fn generate(isa: &TargetIsa, prefix: &str, out_dir: &str) -> Result<(), error::Error> {
|
||||
let mut fmt = Formatter::new();
|
||||
gen_group(&isa.settings, ParentGroup::Shared, &mut fmt);
|
||||
fmt.update_file(&format!("{}-{}.rs", prefix, isa.name), out_dir)?;
|
||||
fmt.update_file(format!("{}-{}.rs", prefix, isa.name), out_dir)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Generate sources with type info.
|
||||
//!
|
||||
//! This generates a `types.rs` file which is included in
|
||||
//! `lib/codegen/ir/types.rs`. The file provides constant definitions for the
|
||||
//! `cranelift-codegen/ir/types.rs`. The file provides constant definitions for the
|
||||
//! most commonly used types, including all of the scalar types.
|
||||
//!
|
||||
//! This ensures that the metaprogram and the generated program see the same
|
||||
@ -21,10 +21,8 @@ fn emit_type(ty: &cdsl_types::ValueType, fmt: &mut srcgen::Formatter) -> Result<
|
||||
))
|
||||
})?;
|
||||
|
||||
let definition = format!("pub const {}: Type = Type({:#x});\n", name, number);
|
||||
|
||||
fmt.doc_comment(&ty.doc());
|
||||
fmt.line(&definition);
|
||||
fmtln!(fmt, "pub const {}: Type = Type({:#x});\n", name, number);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||
|
||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
@ -7,39 +7,45 @@ fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
setting.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let mut isa = TargetIsaBuilder::new("arm32", define_settings(shared_settings));
|
||||
fn define_regs() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "s")
|
||||
.units(64)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("IntRegs", "r")
|
||||
.units(16)
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FlagRegs", "")
|
||||
.units(1)
|
||||
.names(vec!["nzcv"])
|
||||
.track_pressure(false);
|
||||
let flag_reg = isa.add_reg_bank(builder);
|
||||
let flag_reg = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("S", float_regs).count(32);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("D", float_regs).width(2);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("Q", float_regs).width(4);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
isa.finish()
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
let regs = define_regs();
|
||||
TargetIsa::new("arm32", settings, regs)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||
|
||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
@ -7,35 +7,41 @@ fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
setting.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let mut isa = TargetIsaBuilder::new("arm64", define_settings(shared_settings));
|
||||
fn define_registers() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
// The `x31` regunit serves as the stack pointer / zero register depending on context. We
|
||||
// reserve it and don't model the difference.
|
||||
let builder = RegBankBuilder::new("IntRegs", "x")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "v")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FlagRegs", "")
|
||||
.units(1)
|
||||
.names(vec!["nzcv"])
|
||||
.track_pressure(false);
|
||||
let flag_reg = isa.add_reg_bank(builder);
|
||||
let flag_reg = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
isa.finish()
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
let regs = define_registers();
|
||||
TargetIsa::new("arm64", settings, regs)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub enum Isa {
|
||||
|
||||
impl Isa {
|
||||
/// Creates isa target using name.
|
||||
pub fn new(name: &str) -> Option<Self> {
|
||||
pub fn from_name(name: &str) -> Option<Self> {
|
||||
Isa::all()
|
||||
.iter()
|
||||
.cloned()
|
||||
@ -27,31 +27,24 @@ impl Isa {
|
||||
}
|
||||
|
||||
/// Creates isa target from arch.
|
||||
pub fn from_arch(arch: &str) -> Option<Isa> {
|
||||
Isa::all()
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|isa| isa.is_arch_applicable(arch))
|
||||
.next()
|
||||
pub fn from_arch(arch: &str) -> Option<Self> {
|
||||
match arch {
|
||||
"riscv" => Some(Isa::Riscv),
|
||||
"aarch64" => Some(Isa::Arm64),
|
||||
x if ["x86_64", "i386", "i586", "i686"].contains(&x) => Some(Isa::X86),
|
||||
x if x.starts_with("arm") || arch.starts_with("thumb") => Some(Isa::Arm32),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all supported isa targets.
|
||||
pub fn all() -> [Isa; 4] {
|
||||
[Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64]
|
||||
}
|
||||
|
||||
/// Checks if arch is applicable for the isa target.
|
||||
fn is_arch_applicable(&self, arch: &str) -> bool {
|
||||
match *self {
|
||||
Isa::Riscv => arch == "riscv",
|
||||
Isa::X86 => ["x86_64", "i386", "i586", "i686"].contains(&arch),
|
||||
Isa::Arm32 => arch.starts_with("arm") || arch.starts_with("thumb"),
|
||||
Isa::Arm64 => arch == "aarch64",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Isa {
|
||||
// These names should be kept in sync with the crate features.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Isa::Riscv => write!(f, "riscv"),
|
||||
@ -62,11 +55,13 @@ impl fmt::Display for Isa {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define_all(shared_settings: &SettingGroup) -> Vec<TargetIsa> {
|
||||
vec![
|
||||
riscv::define(shared_settings),
|
||||
arm32::define(shared_settings),
|
||||
arm64::define(shared_settings),
|
||||
x86::define(shared_settings),
|
||||
]
|
||||
pub fn define(isas: &Vec<Isa>, shared_settings: &SettingGroup) -> Vec<TargetIsa> {
|
||||
isas.iter()
|
||||
.map(|isa| match isa {
|
||||
Isa::Riscv => riscv::define(shared_settings),
|
||||
Isa::X86 => x86::define(shared_settings),
|
||||
Isa::Arm32 => arm32::define(shared_settings),
|
||||
Isa::Arm64 => arm64::define(shared_settings),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
||||
|
||||
fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
||||
@ -54,24 +54,30 @@ fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
||||
setting.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let mut isa = TargetIsaBuilder::new("riscv", define_settings(shared_settings));
|
||||
fn define_registers() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
let builder = RegBankBuilder::new("IntRegs", "x")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "f")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
isa.finish()
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
let regs = define_registers();
|
||||
TargetIsa::new("riscv", settings, regs)
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
||||
|
||||
pub fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
let mut settings = SettingGroupBuilder::new("x86");
|
||||
|
||||
// CPUID.01H:ECX
|
||||
@ -68,49 +68,49 @@ pub fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
settings.finish()
|
||||
}
|
||||
|
||||
fn define_registers(isa: &mut TargetIsaBuilder) {
|
||||
fn define_registers() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
let builder = RegBankBuilder::new("IntRegs", "r")
|
||||
.units(16)
|
||||
.names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"])
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "xmm")
|
||||
.units(16)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FlagRegs", "")
|
||||
.units(1)
|
||||
.names(vec!["rflags"])
|
||||
.track_pressure(false);
|
||||
let flag_reg = isa.add_reg_bank(builder);
|
||||
let flag_reg = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
let gpr = isa.add_reg_class(builder);
|
||||
let gpr = regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
||||
let fpr = isa.add_reg_class(builder);
|
||||
let fpr = regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::subclass_of("GPR8", gpr, 0, 8);
|
||||
let gpr8 = isa.add_reg_class(builder);
|
||||
let gpr8 = regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::subclass_of("ABCD", gpr8, 0, 4);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::subclass_of("FPR8", fpr, 0, 8);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
|
||||
let mut isa = TargetIsaBuilder::new("x86", settings);
|
||||
|
||||
define_registers(&mut isa);
|
||||
|
||||
isa.finish()
|
||||
let regs = define_registers();
|
||||
TargetIsa::new("x86", settings, regs)
|
||||
}
|
||||
|
@ -1,13 +1,36 @@
|
||||
#[macro_use]
|
||||
mod cdsl;
|
||||
mod srcgen;
|
||||
|
||||
pub mod error;
|
||||
pub mod gen_registers;
|
||||
pub mod gen_settings;
|
||||
pub mod gen_types;
|
||||
pub mod isa;
|
||||
|
||||
mod base;
|
||||
mod gen_registers;
|
||||
mod gen_settings;
|
||||
mod gen_types;
|
||||
|
||||
mod constant_hash;
|
||||
mod srcgen;
|
||||
mod shared;
|
||||
mod unique_table;
|
||||
|
||||
pub fn isa_from_arch(arch: &str) -> Result<isa::Isa, String> {
|
||||
isa::Isa::from_arch(arch).ok_or_else(|| format!("no supported isa found for arch `{}`", arch))
|
||||
}
|
||||
|
||||
/// Generates all the Rust source files used in Cranelift from the meta-language.
|
||||
pub fn generate(isas: &Vec<isa::Isa>, out_dir: &str) -> Result<(), error::Error> {
|
||||
// Common definitions.
|
||||
let shared_settings = gen_settings::generate_common("new_settings.rs", &out_dir)?;
|
||||
|
||||
gen_types::generate("types.rs", &out_dir)?;
|
||||
|
||||
// Per ISA definitions.
|
||||
let isas = isa::define(isas, &shared_settings);
|
||||
|
||||
for isa in isas {
|
||||
gen_registers::generate(&isa, "registers", &out_dir)?;
|
||||
gen_settings::generate(&isa, "new_settings", &out_dir)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
4
third_party/rust/cranelift-codegen-meta/src/shared/mod.rs
vendored
Normal file
4
third_party/rust/cranelift-codegen-meta/src/shared/mod.rs
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
//! Shared definitions for the Cranelift intermediate language.
|
||||
|
||||
pub mod settings;
|
||||
pub mod types;
|
@ -3,6 +3,8 @@
|
||||
//! The `srcgen` module contains generic helper routines and classes for
|
||||
//! generating source code.
|
||||
|
||||
#![macro_use]
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fs;
|
||||
@ -13,6 +15,18 @@ use crate::error;
|
||||
|
||||
static SHIFTWIDTH: usize = 4;
|
||||
|
||||
/// A macro that simplifies the usage of the Formatter by allowing format
|
||||
/// strings.
|
||||
macro_rules! fmtln {
|
||||
($fmt:ident, $fmtstring:expr, $($fmtargs:expr),*) => {
|
||||
$fmt.line(format!($fmtstring, $($fmtargs),*));
|
||||
};
|
||||
|
||||
($fmt:ident, $arg:expr) => {
|
||||
$fmt.line($arg);
|
||||
};
|
||||
}
|
||||
|
||||
pub struct Formatter {
|
||||
indent: usize,
|
||||
lines: Vec<String>,
|
||||
@ -65,8 +79,8 @@ impl Formatter {
|
||||
}
|
||||
|
||||
/// Add an indented line.
|
||||
pub fn line(&mut self, contents: &str) {
|
||||
let indented_line = format!("{}{}\n", self.get_indent(), contents);
|
||||
pub fn line(&mut self, contents: impl AsRef<str>) {
|
||||
let indented_line = format!("{}{}\n", self.get_indent(), contents.as_ref());
|
||||
self.lines.push(indented_line);
|
||||
}
|
||||
|
||||
@ -77,11 +91,15 @@ impl Formatter {
|
||||
}
|
||||
|
||||
/// Write `self.lines` to a file.
|
||||
pub fn update_file(&self, filename: &str, directory: &str) -> Result<(), error::Error> {
|
||||
pub fn update_file(
|
||||
&self,
|
||||
filename: impl AsRef<str>,
|
||||
directory: &str,
|
||||
) -> Result<(), error::Error> {
|
||||
#[cfg(target_family = "windows")]
|
||||
let path_str = format!("{}\\{}", directory, filename);
|
||||
let path_str = format!("{}\\{}", directory, filename.as_ref());
|
||||
#[cfg(not(target_family = "windows"))]
|
||||
let path_str = format!("{}/{}", directory, filename);
|
||||
let path_str = format!("{}/{}", directory, filename.as_ref());
|
||||
|
||||
let path = path::Path::new(&path_str);
|
||||
let mut f = fs::File::create(path)?;
|
||||
@ -99,14 +117,13 @@ impl Formatter {
|
||||
}
|
||||
|
||||
/// Add a comment line.
|
||||
pub fn comment(&mut self, s: &str) {
|
||||
let commented_line = format!("// {}", s);
|
||||
self.line(&commented_line);
|
||||
pub fn comment(&mut self, s: impl AsRef<str>) {
|
||||
fmtln!(self, "// {}", s.as_ref());
|
||||
}
|
||||
|
||||
/// Add a (multi-line) documentation comment.
|
||||
pub fn doc_comment(&mut self, contents: &str) {
|
||||
parse_multiline(contents)
|
||||
pub fn doc_comment(&mut self, contents: impl AsRef<str>) {
|
||||
parse_multiline(contents.as_ref())
|
||||
.iter()
|
||||
.map(|l| {
|
||||
if l.len() == 0 {
|
||||
@ -120,7 +137,7 @@ impl Formatter {
|
||||
|
||||
/// Add a match expression.
|
||||
pub fn add_match(&mut self, m: Match) {
|
||||
self.line(&format!("match {} {{", m.expr));
|
||||
fmtln!(self, "match {} {{", m.expr);
|
||||
self.indent(|fmt| {
|
||||
for (&(ref fields, ref body), ref names) in m.arms.iter() {
|
||||
// name { fields } | name { fields } => { body }
|
||||
@ -135,7 +152,7 @@ impl Formatter {
|
||||
})
|
||||
.collect();
|
||||
let lhs = conditions.join(" | ");
|
||||
fmt.line(&format!("{} => {{", lhs));
|
||||
fmtln!(fmt, "{} => {{", lhs);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line(body);
|
||||
});
|
||||
@ -337,7 +354,7 @@ match x {
|
||||
#[test]
|
||||
fn fmt_can_add_type_to_lines() {
|
||||
let mut fmt = Formatter::new();
|
||||
fmt.line(&format!("pub const {}: Type = Type({:#x});", "example", 0,));
|
||||
fmt.line(format!("pub const {}: Type = Type({:#x});", "example", 0,));
|
||||
let expected_lines = vec!["pub const example: Type = Type(0x0);\n"];
|
||||
assert_eq!(fmt.lines, expected_lines);
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
14
third_party/rust/cranelift-codegen/Cargo.toml
vendored
14
third_party/rust/cranelift-codegen/Cargo.toml
vendored
@ -13,7 +13,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "cranelift-codegen"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
build = "build.rs"
|
||||
description = "Low-level code generator library"
|
||||
@ -24,11 +24,11 @@ categories = ["no-std"]
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/CraneStation/cranelift"
|
||||
[dependencies.cranelift-bforest]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.cranelift-entity]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.failure]
|
||||
@ -52,13 +52,17 @@ default-features = false
|
||||
version = "0.2.0"
|
||||
default-features = false
|
||||
[build-dependencies.cranelift-codegen-meta]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
|
||||
[features]
|
||||
arm32 = []
|
||||
arm64 = []
|
||||
core = ["hashmap_core"]
|
||||
default = ["std"]
|
||||
default = ["std", "x86", "arm32", "arm64", "riscv"]
|
||||
riscv = []
|
||||
std = ["cranelift-entity/std", "cranelift-bforest/std", "target-lexicon/std"]
|
||||
testing_hooks = []
|
||||
x86 = []
|
||||
[badges.maintenance]
|
||||
status = "experimental"
|
||||
|
||||
|
97
third_party/rust/cranelift-codegen/build.rs
vendored
97
third_party/rust/cranelift-codegen/build.rs
vendored
@ -1,7 +1,7 @@
|
||||
// Build script.
|
||||
//
|
||||
// This program is run by Cargo when building lib/codegen. It is used to generate Rust code from
|
||||
// the language definitions in the lib/codegen/meta directory.
|
||||
// This program is run by Cargo when building cranelift-codegen. It is used to generate Rust code from
|
||||
// the language definitions in the cranelift-codegen/meta directory.
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
@ -11,16 +11,11 @@
|
||||
// TARGET
|
||||
// Target triple provided by Cargo.
|
||||
//
|
||||
// CRANELIFT_TARGETS (Optional)
|
||||
// A setting for conditional compilation of isa targets. Possible values can be "native" or
|
||||
// known isa targets separated by ','.
|
||||
//
|
||||
// The build script expects to be run from the directory where this build.rs file lives. The
|
||||
// current directory is used to find the sources.
|
||||
|
||||
use cranelift_codegen_meta as meta;
|
||||
|
||||
use crate::meta::isa::Isa;
|
||||
use std::env;
|
||||
use std::process;
|
||||
use std::time::Instant;
|
||||
@ -30,29 +25,33 @@ fn main() {
|
||||
|
||||
let out_dir = env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set");
|
||||
let target_triple = env::var("TARGET").expect("The TARGET environment variable must be set");
|
||||
let cranelift_targets = env::var("CRANELIFT_TARGETS").ok();
|
||||
let cranelift_targets = cranelift_targets.as_ref().map(|s| s.as_ref());
|
||||
let python = identify_python();
|
||||
|
||||
// Configure isa targets cfg.
|
||||
match isa_targets(cranelift_targets, &target_triple) {
|
||||
Ok(isa_targets) => {
|
||||
for isa in &isa_targets {
|
||||
println!("cargo:rustc-cfg=build_{}", isa.to_string());
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("Error: {}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
let isa_targets = meta::isa::Isa::all()
|
||||
.into_iter()
|
||||
.cloned()
|
||||
.filter(|isa| {
|
||||
let env_key = format!("CARGO_FEATURE_{}", isa.to_string().to_uppercase());
|
||||
env::var(env_key).is_ok()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let isas = if isa_targets.is_empty() {
|
||||
// Try to match native target.
|
||||
let target_name = target_triple.split('-').next().unwrap();
|
||||
let isa = meta::isa_from_arch(&target_name).expect("error when identifying target");
|
||||
println!("cargo:rustc-cfg=feature=\"{}\"", isa);
|
||||
vec![isa]
|
||||
} else {
|
||||
isa_targets
|
||||
};
|
||||
|
||||
let cur_dir = env::current_dir().expect("Can't access current working directory");
|
||||
let crate_dir = cur_dir.as_path();
|
||||
|
||||
// Make sure we rebuild if this build script changes.
|
||||
// I guess that won't happen if you have non-UTF8 bytes in your path names.
|
||||
// The `build.py` script prints out its own dependencies.
|
||||
// Make sure we rebuild if this build script changes (will not happen with
|
||||
// if the path to this file contains non-UTF8 bytes). The `build.py` script
|
||||
// prints out its own dependencies.
|
||||
println!(
|
||||
"cargo:rerun-if-changed={}",
|
||||
crate_dir.join("build.rs").to_str().unwrap()
|
||||
@ -65,6 +64,7 @@ fn main() {
|
||||
// Launch build script with Python. We'll just find python in the path.
|
||||
// Use -B to disable .pyc files, because they cause trouble for vendoring
|
||||
// scripts, and this is a build step that isn't run very often anyway.
|
||||
let python = identify_python();
|
||||
let status = process::Command::new(python)
|
||||
.current_dir(crate_dir)
|
||||
.arg("-B")
|
||||
@ -83,12 +83,15 @@ fn main() {
|
||||
// emitted by the `meta` crate.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if let Err(err) = generate_meta(&out_dir) {
|
||||
if let Err(err) = meta::generate(&isas, &out_dir) {
|
||||
eprintln!("Error: {}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
if let Ok(_) = env::var("CRANELIFT_VERBOSE") {
|
||||
for isa in &isas {
|
||||
println!("cargo:warning=Includes support for {} ISA", isa.to_string());
|
||||
}
|
||||
println!(
|
||||
"cargo:warning=Build step took {:?}.",
|
||||
Instant::now() - start_time
|
||||
@ -97,20 +100,6 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_meta(out_dir: &str) -> Result<(), meta::error::Error> {
|
||||
let shared_settings = meta::gen_settings::generate_common("new_settings.rs", &out_dir)?;
|
||||
let isas = meta::isa::define_all(&shared_settings);
|
||||
|
||||
meta::gen_types::generate("types.rs", &out_dir)?;
|
||||
|
||||
for isa in &isas {
|
||||
meta::gen_registers::generate(&isa, "registers", &out_dir)?;
|
||||
meta::gen_settings::generate(&isa, "new_settings", &out_dir)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn identify_python() -> &'static str {
|
||||
for python in &["python", "python3", "python2.7"] {
|
||||
if process::Command::new(python)
|
||||
@ -123,33 +112,3 @@ fn identify_python() -> &'static str {
|
||||
}
|
||||
panic!("The Cranelift build requires Python (version 2.7 or version 3)");
|
||||
}
|
||||
|
||||
/// Returns isa targets to configure conditional compilation.
|
||||
fn isa_targets(cranelift_targets: Option<&str>, target_triple: &str) -> Result<Vec<Isa>, String> {
|
||||
match cranelift_targets {
|
||||
Some("native") => Isa::from_arch(target_triple.split('-').next().unwrap())
|
||||
.map(|isa| vec![isa])
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"no supported isa found for target triple `{}`",
|
||||
target_triple
|
||||
)
|
||||
}),
|
||||
Some(targets) => {
|
||||
let unknown_isa_targets = targets
|
||||
.split(',')
|
||||
.filter(|target| Isa::new(target).is_none())
|
||||
.collect::<Vec<_>>();
|
||||
let isa_targets = targets.split(',').flat_map(Isa::new).collect::<Vec<_>>();
|
||||
match (unknown_isa_targets.is_empty(), isa_targets.is_empty()) {
|
||||
(true, true) => Ok(Isa::all().to_vec()),
|
||||
(true, _) => Ok(isa_targets),
|
||||
(_, _) => Err(format!(
|
||||
"unknown isa targets: `{}`",
|
||||
unknown_isa_targets.join(", ")
|
||||
)),
|
||||
}
|
||||
}
|
||||
None => Ok(Isa::all().to_vec()),
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +143,12 @@ br_table = Instruction(
|
||||
|
||||
Note that this branch instruction can't pass arguments to the targeted
|
||||
blocks. Split critical edges as needed to work around this.
|
||||
|
||||
Do not confuse this with "tables" in WebAssembly. ``br_table`` is for
|
||||
jump tables with destinations within the current function only -- think
|
||||
of a ``match`` in Rust or a ``switch`` in C. If you want to call a
|
||||
function in a dynamic library, that will typically use
|
||||
``call_indirect``.
|
||||
""",
|
||||
ins=(x, EBB, JT), is_branch=True, is_terminator=True)
|
||||
|
||||
|
@ -375,7 +375,7 @@ for int_ty in [types.i8, types.i16]:
|
||||
)
|
||||
|
||||
for int_ty in [types.i8, types.i16]:
|
||||
for op in [ushr_imm, ishl_imm]:
|
||||
for op in [ishl, ishl_imm, ushr, ushr_imm]:
|
||||
widen.legalize(
|
||||
a << op.bind(int_ty)(b, c),
|
||||
Rtl(
|
||||
@ -384,29 +384,14 @@ for int_ty in [types.i8, types.i16]:
|
||||
a << ireduce.bind(int_ty)(z)
|
||||
))
|
||||
|
||||
widen.legalize(
|
||||
a << ishl.bind(int_ty)(b, c),
|
||||
Rtl(
|
||||
x << uextend.i32(b),
|
||||
z << ishl.i32(x, c),
|
||||
a << ireduce.bind(int_ty)(z)
|
||||
))
|
||||
|
||||
widen.legalize(
|
||||
a << ushr.bind(int_ty)(b, c),
|
||||
Rtl(
|
||||
x << uextend.i32(b),
|
||||
z << ushr.i32(x, c),
|
||||
a << ireduce.bind(int_ty)(z)
|
||||
))
|
||||
|
||||
widen.legalize(
|
||||
a << sshr.bind(int_ty)(b, c),
|
||||
Rtl(
|
||||
x << sextend.i32(b),
|
||||
z << sshr.i32(x, c),
|
||||
a << ireduce.bind(int_ty)(z)
|
||||
))
|
||||
for op in [sshr, sshr_imm]:
|
||||
widen.legalize(
|
||||
a << op.bind(int_ty)(b, c),
|
||||
Rtl(
|
||||
x << sextend.i32(b),
|
||||
z << op.i32(x, c),
|
||||
a << ireduce.bind(int_ty)(z)
|
||||
))
|
||||
|
||||
for w_cc in [
|
||||
intcc.eq, intcc.ne, intcc.ugt, intcc.ult, intcc.uge, intcc.ule
|
||||
@ -570,7 +555,7 @@ widen.legalize(
|
||||
b1 << band_imm(b, imm64(0xcc)),
|
||||
b2 << ushr_imm(b1, imm64(2)),
|
||||
b3 << band_imm(b, imm64(0x33)),
|
||||
b4 << ushr_imm(b3, imm64(2)),
|
||||
b4 << ishl_imm(b3, imm64(2)),
|
||||
c << bor(b2, b4),
|
||||
c1 << band_imm(c, imm64(0xf0)),
|
||||
c2 << ushr_imm(c1, imm64(4)),
|
||||
@ -590,7 +575,7 @@ widen.legalize(
|
||||
b1 << band_imm(b, imm64(0xcccc)),
|
||||
b2 << ushr_imm(b1, imm64(2)),
|
||||
b3 << band_imm(b, imm64(0x3333)),
|
||||
b4 << ushr_imm(b3, imm64(2)),
|
||||
b4 << ishl_imm(b3, imm64(2)),
|
||||
c << bor(b2, b4),
|
||||
c1 << band_imm(c, imm64(0xf0f0)),
|
||||
c2 << ushr_imm(c1, imm64(4)),
|
||||
@ -615,7 +600,7 @@ expand.legalize(
|
||||
b1 << band_imm(b, imm64(0xcccccccc)),
|
||||
b2 << ushr_imm(b1, imm64(2)),
|
||||
b3 << band_imm(b, imm64(0x33333333)),
|
||||
b4 << ushr_imm(b3, imm64(2)),
|
||||
b4 << ishl_imm(b3, imm64(2)),
|
||||
c << bor(b2, b4),
|
||||
c1 << band_imm(c, imm64(0xf0f0f0f0)),
|
||||
c2 << ushr_imm(c1, imm64(4)),
|
||||
@ -643,7 +628,7 @@ expand.legalize(
|
||||
b1 << band_imm(b, imm64(0xcccccccccccccccc)),
|
||||
b2 << ushr_imm(b1, imm64(2)),
|
||||
b3 << band_imm(b, imm64(0x3333333333333333)),
|
||||
b4 << ushr_imm(b3, imm64(2)),
|
||||
b4 << ishl_imm(b3, imm64(2)),
|
||||
c << bor(b2, b4),
|
||||
c1 << band_imm(c, imm64(0xf0f0f0f0f0f0f0f0)),
|
||||
c2 << ushr_imm(c1, imm64(4)),
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Second-level build script.
|
||||
#
|
||||
# This script is run from lib/codegen/build.rs to generate Rust files.
|
||||
# This script is run from cranelift-codegen/build.rs to generate Rust files.
|
||||
|
||||
from __future__ import absolute_import
|
||||
import argparse
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Generate build dependencies for Cargo.
|
||||
|
||||
The `build.py` script is invoked by cargo when building lib/codegen to
|
||||
The `build.py` script is invoked by cargo when building cranelift-codegen to
|
||||
generate Rust code from the instruction descriptions. Cargo needs to know when
|
||||
it is necessary to rerun the build script.
|
||||
|
||||
|
@ -48,8 +48,8 @@ def verify_semantics(inst, src, xforms):
|
||||
arg = rtl_var.rtl[0].expr.args[i]
|
||||
assert isinstance(arg, Var)
|
||||
for val in op.kind.possible_values():
|
||||
s[arg] = val
|
||||
new_variants.append(rtl_var.copy(s))
|
||||
s[arg] = val
|
||||
new_variants.append(rtl_var.copy(s))
|
||||
variants = new_variants
|
||||
|
||||
# For any possible version of the src with concrete enumerated immediates
|
||||
@ -65,7 +65,7 @@ def verify_semantics(inst, src, xforms):
|
||||
matching_xforms = [] # type: List[XForm]
|
||||
for x in xforms:
|
||||
if src.substitution(x.src, {}) is None:
|
||||
continue
|
||||
continue
|
||||
|
||||
# Translate t using x.symtab
|
||||
t = {x.symtab[str(v)]: tv for (v, tv) in t.items()}
|
||||
|
@ -55,13 +55,26 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<Cod
|
||||
let mut offset = 0;
|
||||
let mut divert = RegDiversions::new();
|
||||
|
||||
// The relaxation algorithm iterates to convergence.
|
||||
// First, compute initial offsets for every EBB.
|
||||
{
|
||||
let mut cur = FuncCursor::new(func);
|
||||
while let Some(ebb) = cur.next_ebb() {
|
||||
divert.clear();
|
||||
cur.func.offsets[ebb] = offset;
|
||||
while let Some(inst) = cur.next_inst() {
|
||||
let enc = cur.func.encodings[inst];
|
||||
offset += encinfo.byte_size(enc, inst, &divert, &cur.func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then, run the relaxation algorithm until it converges.
|
||||
let mut go_again = true;
|
||||
while go_again {
|
||||
go_again = false;
|
||||
offset = 0;
|
||||
|
||||
// Visit all instructions in layout order
|
||||
// Visit all instructions in layout order.
|
||||
let mut cur = FuncCursor::new(func);
|
||||
while let Some(ebb) = cur.next_ebb() {
|
||||
divert.clear();
|
||||
@ -81,15 +94,12 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<Cod
|
||||
|
||||
let enc = cur.func.encodings[inst];
|
||||
|
||||
// See if this might be a branch that is out of range.
|
||||
// See if this is a branch has a range and a destination, and if the target is in
|
||||
// range.
|
||||
if let Some(range) = encinfo.branch_range(enc) {
|
||||
if let Some(dest) = cur.func.dfg[inst].branch_destination() {
|
||||
let dest_offset = cur.func.offsets[dest];
|
||||
// This could be an out-of-range branch.
|
||||
// Relax it unless the destination offset has not been computed yet.
|
||||
if !range.contains(offset, dest_offset)
|
||||
&& (dest_offset != 0 || Some(dest) == cur.func.layout.entry_block())
|
||||
{
|
||||
if !range.contains(offset, dest_offset) {
|
||||
offset +=
|
||||
relax_branch(&mut cur, &divert, offset, dest_offset, &encinfo, isa);
|
||||
continue;
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Runtime support for precomputed constant hash tables.
|
||||
//!
|
||||
//! The `lib/codegen/meta-python/constant_hash.py` Python module can generate constant hash tables
|
||||
//! The `cranelift-codegen/meta-python/constant_hash.py` Python module can generate constant hash tables
|
||||
//! using open addressing and quadratic probing. The hash tables are arrays that are guaranteed to:
|
||||
//!
|
||||
//! - Have a power-of-two size.
|
||||
@ -56,7 +56,7 @@ pub fn probe<K: Copy + Eq, T: Table<K> + ?Sized>(
|
||||
}
|
||||
|
||||
/// A primitive hash function for matching opcodes.
|
||||
/// Must match `lib/codegen/meta-python/constant_hash.py` and `lib/codegen/meta/constant_hash.rs`.
|
||||
/// Must match `cranelift-codegen/meta-python/constant_hash.py` and `cranelift-codegen/meta/constant_hash.rs`.
|
||||
pub fn simple_hash(s: &str) -> usize {
|
||||
let mut h: u32 = 5381;
|
||||
for c in s.chars() {
|
||||
|
@ -32,7 +32,7 @@ pub trait InstBuilderBase<'f>: Sized {
|
||||
fn build(self, data: InstructionData, ctrl_typevar: Type) -> (Inst, &'f mut DataFlowGraph);
|
||||
}
|
||||
|
||||
// Include trait code generated by `lib/codegen/meta-python/gen_instr.py`.
|
||||
// Include trait code generated by `cranelift-codegen/meta-python/gen_instr.py`.
|
||||
//
|
||||
// This file defines the `InstBuilder` trait as an extension of `InstBuilderBase` with methods per
|
||||
// instruction format and per opcode.
|
||||
|
@ -114,10 +114,12 @@ impl fmt::Display for GlobalValueData {
|
||||
offset,
|
||||
colocated,
|
||||
} => {
|
||||
if colocated {
|
||||
write!(f, "colocated ")?;
|
||||
}
|
||||
write!(f, "symbol {}", name)?;
|
||||
write!(
|
||||
f,
|
||||
"symbol {}{}",
|
||||
if colocated { "colocated " } else { "" },
|
||||
name
|
||||
)?;
|
||||
let offset_val: i64 = offset.into();
|
||||
if offset_val > 0 {
|
||||
write!(f, "+")?;
|
||||
|
@ -665,6 +665,12 @@ impl FromStr for Ieee32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Ieee32 {
|
||||
fn from(x: f32) -> Self {
|
||||
Ieee32::with_float(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ieee64 {
|
||||
/// Create a new `Ieee64` containing the bits of `x`.
|
||||
pub fn with_bits(x: u64) -> Self {
|
||||
@ -726,6 +732,12 @@ impl FromStr for Ieee64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Ieee64 {
|
||||
fn from(x: f64) -> Self {
|
||||
Ieee64::with_float(x)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -28,7 +28,7 @@ pub type ValueList = entity::EntityList<Value>;
|
||||
/// Memory pool for holding value lists. See `ValueList`.
|
||||
pub type ValueListPool = entity::ListPool<Value>;
|
||||
|
||||
// Include code generated by `lib/codegen/meta-python/gen_instr.py`. This file contains:
|
||||
// Include code generated by `cranelift-codegen/meta-python/gen_instr.py`. This file contains:
|
||||
//
|
||||
// - The `pub enum InstructionFormat` enum with all the instruction formats.
|
||||
// - The `pub enum InstructionData` enum with all the instruction data fields.
|
||||
@ -64,7 +64,7 @@ impl Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
// This trait really belongs in lib/reader where it is used by the `.clif` file parser, but since
|
||||
// This trait really belongs in cranelift-reader where it is used by the `.clif` file parser, but since
|
||||
// it critically depends on the `opcode_name()` function which is needed here anyway, it lives in
|
||||
// this module. This also saves us from running the build script twice to generate code for the two
|
||||
// separate crates.
|
||||
|
@ -31,7 +31,7 @@ const LANE_BASE: u8 = 0x70;
|
||||
/// Start of the 2-lane vector types.
|
||||
const VECTOR_BASE: u8 = LANE_BASE + 16;
|
||||
|
||||
// Include code generated by `lib/codegen/meta/gen_types.rs`. This file contains constant
|
||||
// Include code generated by `cranelift-codegen/meta/gen_types.rs`. This file contains constant
|
||||
// definitions for all the scalar types as well as common vector types for 64, 128, 256, and
|
||||
// 512-bit SIMD vectors.
|
||||
include!(concat!(env!("OUT_DIR"), "/types.rs"));
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::settings::{self, detail, Builder};
|
||||
use core::fmt;
|
||||
|
||||
// Include code generated by `lib/codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// Include code generated by `cranelift-codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// `Flags` struct with an impl for all of the settings defined in
|
||||
// `lib/codegen/meta-python/isa/arm32/settings.py`.
|
||||
// `cranelift-codegen/meta-python/isa/arm32/settings.py`.
|
||||
include!(concat!(env!("OUT_DIR"), "/settings-arm32.rs"));
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::settings::{self, detail, Builder};
|
||||
use core::fmt;
|
||||
|
||||
// Include code generated by `lib/codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// Include code generated by `cranelift-codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// `Flags` struct with an impl for all of the settings defined in
|
||||
// `lib/codegen/meta-python/isa/arm64/settings.py`.
|
||||
// `cranelift-codegen/meta-python/isa/arm64/settings.py`.
|
||||
include!(concat!(env!("OUT_DIR"), "/settings-arm64.rs"));
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Support types for generated encoding tables.
|
||||
//!
|
||||
//! This module contains types and functions for working with the encoding tables generated by
|
||||
//! `lib/codegen/meta-python/gen_encoding.py`.
|
||||
//! `cranelift-codegen/meta-python/gen_encoding.py`.
|
||||
|
||||
use crate::constant_hash::{probe, Table};
|
||||
use crate::ir::{Function, InstructionData, Opcode, Type};
|
||||
|
@ -68,16 +68,16 @@ use failure_derive::Fail;
|
||||
use std::boxed::Box;
|
||||
use target_lexicon::{Architecture, PointerWidth, Triple};
|
||||
|
||||
#[cfg(build_riscv)]
|
||||
#[cfg(feature = "riscv")]
|
||||
mod riscv;
|
||||
|
||||
#[cfg(build_x86)]
|
||||
#[cfg(feature = "x86")]
|
||||
mod x86;
|
||||
|
||||
#[cfg(build_arm32)]
|
||||
#[cfg(feature = "arm32")]
|
||||
mod arm32;
|
||||
|
||||
#[cfg(build_arm64)]
|
||||
#[cfg(feature = "arm64")]
|
||||
mod arm64;
|
||||
|
||||
mod call_conv;
|
||||
@ -90,12 +90,12 @@ mod stack;
|
||||
/// Returns a builder that can create a corresponding `TargetIsa`
|
||||
/// or `Err(LookupError::Unsupported)` if not enabled.
|
||||
macro_rules! isa_builder {
|
||||
($module:ident, $name:ident) => {{
|
||||
#[cfg($name)]
|
||||
($name:ident, $feature:tt) => {{
|
||||
#[cfg(feature = $feature)]
|
||||
fn $name(triple: Triple) -> Result<Builder, LookupError> {
|
||||
Ok($module::isa_builder(triple))
|
||||
Ok($name::isa_builder(triple))
|
||||
};
|
||||
#[cfg(not($name))]
|
||||
#[cfg(not(feature = $feature))]
|
||||
fn $name(_triple: Triple) -> Result<Builder, LookupError> {
|
||||
Err(LookupError::Unsupported)
|
||||
}
|
||||
@ -107,9 +107,9 @@ macro_rules! isa_builder {
|
||||
/// Return a builder that can create a corresponding `TargetIsa`.
|
||||
pub fn lookup(triple: Triple) -> Result<Builder, LookupError> {
|
||||
match triple.architecture {
|
||||
Architecture::Riscv32 | Architecture::Riscv64 => isa_builder!(riscv, build_riscv)(triple),
|
||||
Architecture::Riscv32 | Architecture::Riscv64 => isa_builder!(riscv, "riscv")(triple),
|
||||
Architecture::I386 | Architecture::I586 | Architecture::I686 | Architecture::X86_64 => {
|
||||
isa_builder!(x86, build_x86)(triple)
|
||||
isa_builder!(x86, "x86")(triple)
|
||||
}
|
||||
Architecture::Thumbv6m
|
||||
| Architecture::Thumbv7em
|
||||
@ -118,8 +118,8 @@ pub fn lookup(triple: Triple) -> Result<Builder, LookupError> {
|
||||
| Architecture::Armv4t
|
||||
| Architecture::Armv5te
|
||||
| Architecture::Armv7
|
||||
| Architecture::Armv7s => isa_builder!(arm32, build_arm32)(triple),
|
||||
Architecture::Aarch64 => isa_builder!(arm64, build_arm64)(triple),
|
||||
| Architecture::Armv7s => isa_builder!(arm32, "arm32")(triple),
|
||||
Architecture::Aarch64 => isa_builder!(arm64, "arm64")(triple),
|
||||
_ => Err(LookupError::Unsupported),
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
use crate::settings::{self, detail, Builder};
|
||||
use core::fmt;
|
||||
|
||||
// Include code generated by `lib/codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// Include code generated by `cranelift-codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// `Flags` struct with an impl for all of the settings defined in
|
||||
// `lib/codegen/meta-python/isa/riscv/settings.py`.
|
||||
// `cranelift-codegen/meta-python/isa/riscv/settings.py`.
|
||||
include!(concat!(env!("OUT_DIR"), "/settings-riscv.rs"));
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -115,9 +115,18 @@ impl ArgAssigner for Args {
|
||||
}
|
||||
|
||||
// Try to use an FPR.
|
||||
if ty.is_float() && self.fpr_used < self.fpr_limit {
|
||||
let reg = FPR.unit(self.fpr_used);
|
||||
self.fpr_used += 1;
|
||||
let fpr_offset = if self.call_conv == CallConv::WindowsFastcall {
|
||||
// Float and general registers on windows share the same parameter index.
|
||||
// The used register depends entirely on the parameter index: Even if XMM0
|
||||
// is not used for the first parameter, it cannot be used for the second parameter.
|
||||
debug_assert_eq!(self.fpr_limit, self.gpr.len());
|
||||
&mut self.gpr_used
|
||||
} else {
|
||||
&mut self.fpr_used
|
||||
};
|
||||
if ty.is_float() && *fpr_offset < self.fpr_limit {
|
||||
let reg = FPR.unit(*fpr_offset);
|
||||
*fpr_offset += 1;
|
||||
return ArgumentLoc::Reg(reg).into();
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
use crate::settings::{self, detail, Builder};
|
||||
use core::fmt;
|
||||
|
||||
// Include code generated by `lib/codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// Include code generated by `cranelift-codegen/meta-python/gen_settings.py`. This file contains a public
|
||||
// `Flags` struct with an impl for all of the settings defined in
|
||||
// `lib/codegen/meta-python/isa/x86/settings.py`.
|
||||
// `cranelift-codegen/meta-python/isa/x86/settings.py`.
|
||||
include!(concat!(env!("OUT_DIR"), "/settings-x86.rs"));
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -118,7 +118,7 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
||||
}
|
||||
|
||||
// Include legalization patterns that were generated by `gen_legalizer.py` from the `XForms` in
|
||||
// `lib/codegen/meta-python/base/legalize.py`.
|
||||
// `cranelift-codegen/meta-python/base/legalize.py`.
|
||||
//
|
||||
// Concretely, this defines private functions `narrow()`, and `expand()`.
|
||||
include!(concat!(env!("OUT_DIR"), "/legalizer.rs"));
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Predicate functions for testing instruction fields.
|
||||
//!
|
||||
//! This module defines functions that are used by the instruction predicates defined by
|
||||
//! `lib/codegen/meta-python/cdsl/predicates.py` classes.
|
||||
//! `cranelift-codegen/meta-python/cdsl/predicates.py` classes.
|
||||
//!
|
||||
//! The predicates the operate on integer fields use `Into<i64>` as a shared trait bound. This
|
||||
//! bound is implemented by all the native integer types as well as `Imm64`.
|
||||
|
@ -270,7 +270,7 @@ impl fmt::Display for Pressure {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(build_arm32)]
|
||||
#[cfg(feature = "arm32")]
|
||||
mod tests {
|
||||
use super::Pressure;
|
||||
use crate::isa::{RegClass, TargetIsa};
|
||||
|
@ -1127,7 +1127,7 @@ impl fmt::Display for Solver {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(build_arm32)]
|
||||
#[cfg(feature = "arm32")]
|
||||
mod tests {
|
||||
use super::{Move, Solver};
|
||||
use crate::entity::EntityRef;
|
||||
|
@ -333,7 +333,7 @@ pub mod detail {
|
||||
|
||||
// Include code generated by `meta-python/gen_settings.py`. This file contains a public `Flags`
|
||||
// struct with an impl for all of the settings defined in
|
||||
// `lib/codegen/meta-python/base/settings.py`.
|
||||
// `cranelift-codegen/meta-python/base/settings.py`.
|
||||
include!(concat!(env!("OUT_DIR"), "/settings.rs"));
|
||||
|
||||
/// Wrapper containing flags and optionally a `TargetIsa` trait object.
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"5cf393cd6f9778b92793bce26ed00834913064d7a69f99632cd3703b198a1298","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"139fc0eeed2e8cde2b82b8b7402e8c7cd079a9fbbf1ec692622e5ad0c10d9faf","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"f35031459aca446734726c132c0a571482f1ec2ca8221b352d2e18c74950e977","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"e95e4b2ed36413d80c4c0dcfc19dcf8a9f52e34467aaec196c774fd639747028","src/set.rs":"ec0ff7a9ee674c90ff9d06ea1fd4ab05039369146c2d259f476c6f612417933f","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":"c4ccc3743848cbb53e58b62685703dc12ea553c3bc8f21db76f23c68054eb69a"}
|
||||
{"files":{"Cargo.toml":"bdfb55271249705ca4f66080d59757b97af8872bcd0080c858780d472d6094bc","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"139fc0eeed2e8cde2b82b8b7402e8c7cd079a9fbbf1ec692622e5ad0c10d9faf","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"f35031459aca446734726c132c0a571482f1ec2ca8221b352d2e18c74950e977","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"e95e4b2ed36413d80c4c0dcfc19dcf8a9f52e34467aaec196c774fd639747028","src/set.rs":"ec0ff7a9ee674c90ff9d06ea1fd4ab05039369146c2d259f476c6f612417933f","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":"4e124e09cb7dc85fbe2162420aebbe8e9e3b8f9210901be7867416c5beec8226"}
|
2
third_party/rust/cranelift-entity/Cargo.toml
vendored
2
third_party/rust/cranelift-entity/Cargo.toml
vendored
@ -13,7 +13,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "cranelift-entity"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "Data structures using entity references as mapping keys"
|
||||
documentation = "https://cranelift.readthedocs.io/"
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"ad90f0d52f7e2a3c93100a0ce05c76cb424933153726c6496185e099dadd0ade","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"59033d83472a657704eb0fc2c882c28f8a673156f8371c909a4875451649780e","src/lib.rs":"ca09a18819b35ba4c95ab7ad05f708a16fa059378e948b9f6b9c5af87baeb47b","src/ssa.rs":"88cb07071943f3e72a91c91afb58960689b4d9c56352b3bb7cd5d69288066190","src/switch.rs":"1afa11f037c91d6c87f8c6b88cddddc5f22c2b6ee9d0f05382ed05d0c4f29135","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":"89ecc8b49d4ab98f2c121832fee365da88b7b0ffad77d4e328015b1fd1f7f4b1"}
|
||||
{"files":{"Cargo.toml":"b5d70a2290241ca933b8bc6530f92f784c508d34448f86516ce3ddbdd62c1ba7","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"f3ad024e4895eddf83c8fe19c93ae37709a6bf27db2e1beef153fd742d99defa","src/lib.rs":"1cc2e7aaffa45bccea9e59fcc9d9c5d295a9f7adacd6bd55933834e20e969aef","src/ssa.rs":"88cb07071943f3e72a91c91afb58960689b4d9c56352b3bb7cd5d69288066190","src/switch.rs":"1afa11f037c91d6c87f8c6b88cddddc5f22c2b6ee9d0f05382ed05d0c4f29135","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":"2833c6e1a93c524ce0c2ab31266cdc84d38c906349f79f19378a5e5995727b23"}
|
@ -13,7 +13,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "cranelift-frontend"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "Cranelift IR builder helper"
|
||||
documentation = "https://cranelift.readthedocs.io/"
|
||||
@ -22,7 +22,7 @@ categories = ["no-std"]
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/CraneStation/cranelift"
|
||||
[dependencies.cranelift-codegen]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.hashmap_core]
|
||||
|
175
third_party/rust/cranelift-frontend/src/frontend.rs
vendored
175
third_party/rust/cranelift-frontend/src/frontend.rs
vendored
@ -638,7 +638,7 @@ impl<'a> FunctionBuilder<'a> {
|
||||
|
||||
/// Calls libc.memset
|
||||
///
|
||||
/// Writes `size` bytes of value `ch` to memory starting at `buffer`.
|
||||
/// Writes `size` bytes of i8 value `ch` to memory starting at `buffer`.
|
||||
pub fn call_memset(
|
||||
&mut self,
|
||||
config: TargetFrontendConfig,
|
||||
@ -672,7 +672,7 @@ impl<'a> FunctionBuilder<'a> {
|
||||
&mut self,
|
||||
config: TargetFrontendConfig,
|
||||
buffer: Value,
|
||||
ch: u32,
|
||||
ch: u8,
|
||||
size: u64,
|
||||
buffer_align: u8,
|
||||
) {
|
||||
@ -702,7 +702,7 @@ impl<'a> FunctionBuilder<'a> {
|
||||
let load_and_store_amount = size / access_size;
|
||||
|
||||
if load_and_store_amount > THRESHOLD {
|
||||
let ch = self.ins().iconst(types::I32, i64::from(ch));
|
||||
let ch = self.ins().iconst(types::I8, i64::from(ch));
|
||||
let size = self.ins().iconst(config.pointer_type(), size as i64);
|
||||
self.call_memset(config, buffer, ch, size);
|
||||
} else {
|
||||
@ -1078,6 +1078,175 @@ ebb0:
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_so_small_memcpy() {
|
||||
use core::str::FromStr;
|
||||
use cranelift_codegen::{isa, settings};
|
||||
|
||||
let shared_builder = settings::builder();
|
||||
let shared_flags = settings::Flags::new(shared_builder);
|
||||
|
||||
let triple = ::target_lexicon::Triple::from_str("arm").expect("Couldn't create arm triple");
|
||||
|
||||
let target = isa::lookup(triple)
|
||||
.ok()
|
||||
.map(|b| b.finish(shared_flags))
|
||||
.expect("This test requires arm support.");
|
||||
|
||||
let mut sig = Signature::new(target.default_call_conv());
|
||||
sig.returns.push(AbiParam::new(I32));
|
||||
|
||||
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_ebb();
|
||||
let x = Variable::new(0);
|
||||
let y = Variable::new(16);
|
||||
builder.declare_var(x, target.pointer_type());
|
||||
builder.declare_var(y, target.pointer_type());
|
||||
builder.append_ebb_params_for_function_params(block0);
|
||||
builder.switch_to_block(block0);
|
||||
|
||||
let src = builder.use_var(x);
|
||||
let dest = builder.use_var(y);
|
||||
let size = 8192;
|
||||
builder.emit_small_memcpy(target.frontend_config(), dest, src, size, 8, 8);
|
||||
builder.ins().return_(&[dest]);
|
||||
|
||||
builder.seal_all_blocks();
|
||||
builder.finalize();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
func.display(None).to_string(),
|
||||
"function %sample() -> i32 system_v {
|
||||
sig0 = (i32, i32, i32) system_v
|
||||
fn0 = %Memcpy sig0
|
||||
|
||||
ebb0:
|
||||
v4 = iconst.i32 0
|
||||
v1 -> v4
|
||||
v3 = iconst.i32 0
|
||||
v0 -> v3
|
||||
v2 = iconst.i32 8192
|
||||
call fn0(v1, v0, v2)
|
||||
return v1
|
||||
}
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn small_memset() {
|
||||
use core::str::FromStr;
|
||||
use cranelift_codegen::{isa, settings};
|
||||
|
||||
let shared_builder = settings::builder();
|
||||
let shared_flags = settings::Flags::new(shared_builder);
|
||||
|
||||
let triple = ::target_lexicon::Triple::from_str("arm").expect("Couldn't create arm triple");
|
||||
|
||||
let target = isa::lookup(triple)
|
||||
.ok()
|
||||
.map(|b| b.finish(shared_flags))
|
||||
.expect("This test requires arm support.");
|
||||
|
||||
let mut sig = Signature::new(target.default_call_conv());
|
||||
sig.returns.push(AbiParam::new(I32));
|
||||
|
||||
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_ebb();
|
||||
let y = Variable::new(16);
|
||||
builder.declare_var(y, target.pointer_type());
|
||||
builder.append_ebb_params_for_function_params(block0);
|
||||
builder.switch_to_block(block0);
|
||||
|
||||
let dest = builder.use_var(y);
|
||||
let size = 8;
|
||||
builder.emit_small_memset(target.frontend_config(), dest, 1, size, 8);
|
||||
builder.ins().return_(&[dest]);
|
||||
|
||||
builder.seal_all_blocks();
|
||||
builder.finalize();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
func.display(None).to_string(),
|
||||
"function %sample() -> i32 system_v {
|
||||
ebb0:
|
||||
v2 = iconst.i32 0
|
||||
v0 -> v2
|
||||
v1 = iconst.i64 0x0001_0001_0101
|
||||
store aligned v1, v0
|
||||
return v0
|
||||
}
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_so_small_memset() {
|
||||
use core::str::FromStr;
|
||||
use cranelift_codegen::{isa, settings};
|
||||
|
||||
let shared_builder = settings::builder();
|
||||
let shared_flags = settings::Flags::new(shared_builder);
|
||||
|
||||
let triple = ::target_lexicon::Triple::from_str("arm").expect("Couldn't create arm triple");
|
||||
|
||||
let target = isa::lookup(triple)
|
||||
.ok()
|
||||
.map(|b| b.finish(shared_flags))
|
||||
.expect("This test requires arm support.");
|
||||
|
||||
let mut sig = Signature::new(target.default_call_conv());
|
||||
sig.returns.push(AbiParam::new(I32));
|
||||
|
||||
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_ebb();
|
||||
let y = Variable::new(16);
|
||||
builder.declare_var(y, target.pointer_type());
|
||||
builder.append_ebb_params_for_function_params(block0);
|
||||
builder.switch_to_block(block0);
|
||||
|
||||
let dest = builder.use_var(y);
|
||||
let size = 8192;
|
||||
builder.emit_small_memset(target.frontend_config(), dest, 1, size, 8);
|
||||
builder.ins().return_(&[dest]);
|
||||
|
||||
builder.seal_all_blocks();
|
||||
builder.finalize();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
func.display(None).to_string(),
|
||||
"function %sample() -> i32 system_v {
|
||||
sig0 = (i32, i32, i32) system_v
|
||||
fn0 = %Memset sig0
|
||||
|
||||
ebb0:
|
||||
v4 = iconst.i32 0
|
||||
v0 -> v4
|
||||
v1 = iconst.i8 1
|
||||
v2 = iconst.i32 8192
|
||||
v3 = uextend.i32 v1
|
||||
call fn0(v0, v3, v2)
|
||||
return v0
|
||||
}
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_greatest_divisible_power_of_two() {
|
||||
assert_eq!(64, greatest_divisible_power_of_two(64));
|
||||
|
@ -20,8 +20,8 @@
|
||||
//!
|
||||
//! This API has been designed to help you translate your mutable variables into
|
||||
//! [`SSA`](https://en.wikipedia.org/wiki/Static_single_assignment_form) form.
|
||||
//! [`use_var`](struct.FunctionBuilder.html#method.use_var) will returns the Cranelift IR value
|
||||
//! that corresponds to your mutable variable at a precise point in the program. However, you know
|
||||
//! [`use_var`](struct.FunctionBuilder.html#method.use_var) will return the Cranelift IR value
|
||||
//! that corresponds to your mutable variable at a precise point in the program. However, if you know
|
||||
//! beforehand that one of your variables is defined only once, for instance if it is the result
|
||||
//! of an intermediate expression in an expression-based language, then you can translate it
|
||||
//! directly by the Cranelift IR value returned by the instruction builder. Using the
|
||||
@ -30,7 +30,7 @@
|
||||
//! beforehand if a variable is immutable or not).
|
||||
//!
|
||||
//! The moral is that you should use these three functions to handle all your mutable variables,
|
||||
//! even those that are not present in the source code but artefacts of the translation. It is up
|
||||
//! even those that are not present in the source code but artifacts of the translation. It is up
|
||||
//! to you to keep a mapping between the mutable variables of your language and their `Variable`
|
||||
//! index that is used by Cranelift. Caution: as the `Variable` is used by Cranelift to index an
|
||||
//! array containing information about your mutable variables, when you create a new `Variable`
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"084b95108fcb6c72313a0fe318293c573b8141debf8d7523030eff79169369c8","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"00740be2943fe96d8588d15ec3b812b997f41e4bc9cd27510173889172aff8bc","src/environ/dummy.rs":"caf4468c264720474c65bd7463c7e6c4f54076e05bc034875d44f4da3205c81e","src/environ/mod.rs":"617c147485038dfd797ab0ea71b4cfa9574d95d5d5b1ca362c6b7b6a462cf577","src/environ/spec.rs":"2b1cbb0992d31755c19673de36e2c54df1fd9096f72693ec35de96e8f085c9b8","src/func_translator.rs":"45dfb6b5f642c8c464bd2f75d423e50bc981ccfeae5db52daaa43d3368fac1ec","src/lib.rs":"95183fc86a20687e547d2edbd9868681005f0c3a2ca1ae1471e2ae38098f85c6","src/module_translator.rs":"ac54c24aaa3775f72ccd16d1781be648bb0e83ea83909f933d07e86ef1879213","src/sections_translator.rs":"1fc27a5263effce461d33df837985ec5d59bb719c143d3db6124217befb8735e","src/state.rs":"1b1fa08736702d062c49118fba67f0a13752b4d863c1d11abd90eeb219777a23","src/translation_utils.rs":"50b45794018e1c471694f4f60707329213c9fb4153798a879953a479213b8a56","tests/wasm_testsuite.rs":"217d1f6508e9e0b4e364a8db94164d45b60557e6d9f21776998d32fd51eac06c"},"package":"c7eccd196ecd01a2394ce05e2259afe5704874816b058541c7cce7794f0e835e"}
|
||||
{"files":{"Cargo.toml":"ed12a641047878536a2be05241a6a59b30e029584168d15fe8dff9ef4e226cf7","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"00740be2943fe96d8588d15ec3b812b997f41e4bc9cd27510173889172aff8bc","src/environ/dummy.rs":"42df6db37892ea28e9a004934599d8bbcbd62db52f787486cd81a23f1a563613","src/environ/mod.rs":"617c147485038dfd797ab0ea71b4cfa9574d95d5d5b1ca362c6b7b6a462cf577","src/environ/spec.rs":"1c22dfbf956d80cbf34a6b8087dfb38b1f73a5cf010c341b673dba4286468bfe","src/func_translator.rs":"b27debdc0d17f30ecfa7a9bf4bdeea6054966507b5d398ccd4165574da4f674a","src/lib.rs":"95183fc86a20687e547d2edbd9868681005f0c3a2ca1ae1471e2ae38098f85c6","src/module_translator.rs":"ac54c24aaa3775f72ccd16d1781be648bb0e83ea83909f933d07e86ef1879213","src/sections_translator.rs":"499f6d1ca8a4151dab891d14bb901c292adea13b1daccdd6e2b104fb9f5a49a7","src/state.rs":"1b1fa08736702d062c49118fba67f0a13752b4d863c1d11abd90eeb219777a23","src/translation_utils.rs":"50b45794018e1c471694f4f60707329213c9fb4153798a879953a479213b8a56","tests/wasm_testsuite.rs":"c6eac90ebdb6b58d8247c22e04454d95943c5ab0621084b624eb20c0ce2a96a3"},"package":"e75efb45cd8d8700b4bdc225f0077bc7c615f84a5807ce001d59b4da48d85573"}
|
8
third_party/rust/cranelift-wasm/Cargo.toml
vendored
8
third_party/rust/cranelift-wasm/Cargo.toml
vendored
@ -13,7 +13,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "cranelift-wasm"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "Translator from WebAssembly to Cranelift IR"
|
||||
readme = "README.md"
|
||||
@ -26,15 +26,15 @@ version = "0.2.2"
|
||||
default-features = false
|
||||
|
||||
[dependencies.cranelift-codegen]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.cranelift-entity]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.cranelift-frontend]
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.failure]
|
||||
|
@ -458,7 +458,11 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
||||
self.info.start_func = Some(func_index);
|
||||
}
|
||||
|
||||
fn define_function_body(&mut self, body_bytes: &'data [u8]) -> WasmResult<()> {
|
||||
fn define_function_body(
|
||||
&mut self,
|
||||
body_bytes: &'data [u8],
|
||||
body_offset: usize,
|
||||
) -> WasmResult<()> {
|
||||
let func = {
|
||||
let mut func_environ = DummyFuncEnvironment::new(&self.info, self.return_mode);
|
||||
let func_index =
|
||||
@ -467,7 +471,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
||||
let sig = func_environ.vmctx_sig(self.get_func_type(func_index));
|
||||
let mut func = ir::Function::with_name_signature(name, sig);
|
||||
self.trans
|
||||
.translate(body_bytes, &mut func, &mut func_environ)?;
|
||||
.translate(body_bytes, body_offset, &mut func, &mut func_environ)?;
|
||||
func
|
||||
};
|
||||
self.func_bytecode_sizes.push(body_bytes.len());
|
||||
|
@ -343,7 +343,11 @@ pub trait ModuleEnvironment<'data> {
|
||||
///
|
||||
/// Note there's no `reserve_function_bodies` function because the number of
|
||||
/// functions is already provided by `reserve_func_types`.
|
||||
fn define_function_body(&mut self, body_bytes: &'data [u8]) -> WasmResult<()>;
|
||||
fn define_function_body(
|
||||
&mut self,
|
||||
body_bytes: &'data [u8],
|
||||
body_offset: usize,
|
||||
) -> WasmResult<()>;
|
||||
|
||||
/// Provides the number of data initializers up front. By default this does nothing, but
|
||||
/// implementations can use this to preallocate memory if desired.
|
||||
|
@ -54,10 +54,15 @@ impl FuncTranslator {
|
||||
pub fn translate<FE: FuncEnvironment + ?Sized>(
|
||||
&mut self,
|
||||
code: &[u8],
|
||||
code_offset: usize,
|
||||
func: &mut ir::Function,
|
||||
environ: &mut FE,
|
||||
) -> WasmResult<()> {
|
||||
self.translate_from_reader(BinaryReader::new(code), func, environ)
|
||||
self.translate_from_reader(
|
||||
BinaryReader::new_with_offset(code, code_offset),
|
||||
func,
|
||||
environ,
|
||||
)
|
||||
}
|
||||
|
||||
/// Translate a binary WebAssembly function from a `BinaryReader`.
|
||||
@ -222,11 +227,9 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
|
||||
|
||||
/// Get the current source location from a reader.
|
||||
fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc {
|
||||
// We record source locations as byte code offsets relative to the beginning of the function.
|
||||
// This will wrap around of a single function's byte code is larger than 4 GB, but a) the
|
||||
// WebAssembly format doesn't allow for that, and b) that would hit other Cranelift
|
||||
// implementation limits anyway.
|
||||
ir::SourceLoc::new(reader.current_position() as u32)
|
||||
// We record source locations as byte code offsets relative to the beginning of the file.
|
||||
// This will wrap around if byte code is larger than 4 GB.
|
||||
ir::SourceLoc::new(reader.original_position() as u32)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -270,7 +273,7 @@ mod tests {
|
||||
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
|
||||
|
||||
trans
|
||||
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
|
||||
.translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
|
||||
.unwrap();
|
||||
debug!("{}", ctx.func.display(None));
|
||||
ctx.verify(&flags).unwrap();
|
||||
@ -308,7 +311,7 @@ mod tests {
|
||||
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
|
||||
|
||||
trans
|
||||
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
|
||||
.translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
|
||||
.unwrap();
|
||||
debug!("{}", ctx.func.display(None));
|
||||
ctx.verify(&flags).unwrap();
|
||||
@ -354,7 +357,7 @@ mod tests {
|
||||
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
|
||||
|
||||
trans
|
||||
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
|
||||
.translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
|
||||
.unwrap();
|
||||
debug!("{}", ctx.func.display(None));
|
||||
ctx.verify(&flags).unwrap();
|
||||
|
@ -295,7 +295,8 @@ pub fn parse_code_section<'data>(
|
||||
for body in code {
|
||||
let mut reader = body?.get_binary_reader();
|
||||
let size = reader.bytes_remaining();
|
||||
environ.define_function_body(reader.read_bytes(size)?)?;
|
||||
let offset = reader.original_position();
|
||||
environ.define_function_body(reader.read_bytes(size)?, offset)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use wabt::wat2wasm;
|
||||
|
||||
#[test]
|
||||
fn testsuite() {
|
||||
let mut paths: Vec<_> = fs::read_dir("../../wasmtests")
|
||||
let mut paths: Vec<_> = fs::read_dir("../wasmtests")
|
||||
.unwrap()
|
||||
.map(|r| r.unwrap())
|
||||
.filter(|p| {
|
||||
@ -39,7 +39,7 @@ fn testsuite() {
|
||||
fn use_fallthrough_return() {
|
||||
let flags = Flags::new(settings::builder());
|
||||
handle_module(
|
||||
Path::new("../../wasmtests/use_fallthrough_return.wat"),
|
||||
Path::new("../wasmtests/use_fallthrough_return.wat"),
|
||||
&flags,
|
||||
ReturnMode::FallthroughReturn,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user