diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 993c96166d..df16b8cccb 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -31,6 +31,7 @@ serde_derive = "1.0.8" term = "0.5.1" capstone = "0.3.1" wabt = { version = "0.3", optional = true } +target-lexicon = "0.0.0" [features] default = ["wasm"] diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index 0265419305..02071f872d 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -125,15 +125,15 @@ The ``set`` lines apply settings cumulatively:: test legalizer set opt_level=best - set is_64bit=1 - isa riscv - set is_64bit=0 - isa riscv supports_m=false + set is_pic=1 + isa riscv64 + set is_pic=0 + isa riscv32 supports_m=false function %foo() {} This example will run the legalizer test twice. Both runs will have -``opt_level=best``, but they will have different ``is_64bit`` settings. The 32-bit +``opt_level=best``, but they will have different ``is_pic`` settings. The 32-bit run will also have the RISC-V specific flag ``supports_m`` disabled. The filetests are run automatically as part of `cargo test`, and they can diff --git a/cranelift/filetests/isa/riscv/abi-e.cton b/cranelift/filetests/isa/riscv/abi-e.cton index 50100ebf4e..80b275506c 100644 --- a/cranelift/filetests/isa/riscv/abi-e.cton +++ b/cranelift/filetests/isa/riscv/abi-e.cton @@ -1,6 +1,6 @@ ; Test the legalization of function signatures for RV32E. test legalizer -isa riscv enable_e +target riscv32 enable_e ; regex: V=v\d+ diff --git a/cranelift/filetests/isa/riscv/abi.cton b/cranelift/filetests/isa/riscv/abi.cton index 12371ac537..b3c9513aef 100644 --- a/cranelift/filetests/isa/riscv/abi.cton +++ b/cranelift/filetests/isa/riscv/abi.cton @@ -1,6 +1,6 @@ ; Test the legalization of function signatures. test legalizer -isa riscv +target riscv32 ; regex: V=v\d+ diff --git a/cranelift/filetests/isa/riscv/binary32.cton b/cranelift/filetests/isa/riscv/binary32.cton index 7837672bcc..4d63084f9a 100644 --- a/cranelift/filetests/isa/riscv/binary32.cton +++ b/cranelift/filetests/isa/riscv/binary32.cton @@ -1,6 +1,6 @@ ; Binary emission of 32-bit code. test binemit -isa riscv +target riscv32 function %RV32I(i32 link [%x1]) -> i32 link [%x1] { sig0 = () diff --git a/cranelift/filetests/isa/riscv/encoding.cton b/cranelift/filetests/isa/riscv/encoding.cton index 9dc6f388be..98b5f66db6 100644 --- a/cranelift/filetests/isa/riscv/encoding.cton +++ b/cranelift/filetests/isa/riscv/encoding.cton @@ -1,5 +1,5 @@ test legalizer -isa riscv supports_m=1 +target riscv32 supports_m=1 function %int32(i32, i32) { ebb0(v1: i32, v2: i32): diff --git a/cranelift/filetests/isa/riscv/expand-i32.cton b/cranelift/filetests/isa/riscv/expand-i32.cton index 30048622ca..eb63d7cdcd 100644 --- a/cranelift/filetests/isa/riscv/expand-i32.cton +++ b/cranelift/filetests/isa/riscv/expand-i32.cton @@ -1,11 +1,9 @@ ; Test the legalization of i32 instructions that don't have RISC-V versions. test legalizer -set is_64bit=0 -isa riscv supports_m=1 +target riscv32 supports_m=1 -set is_64bit=1 -isa riscv supports_m=1 +target riscv64 supports_m=1 ; regex: V=v\d+ diff --git a/cranelift/filetests/isa/riscv/legalize-abi.cton b/cranelift/filetests/isa/riscv/legalize-abi.cton index df60b91f81..88c5989db6 100644 --- a/cranelift/filetests/isa/riscv/legalize-abi.cton +++ b/cranelift/filetests/isa/riscv/legalize-abi.cton @@ -1,6 +1,6 @@ ; Test legalizer's handling of ABI boundaries. test legalizer -isa riscv +target riscv32 ; regex: V=v\d+ ; regex: SS=ss\d+ diff --git a/cranelift/filetests/isa/riscv/legalize-i64.cton b/cranelift/filetests/isa/riscv/legalize-i64.cton index f06cf0803a..d043337a21 100644 --- a/cranelift/filetests/isa/riscv/legalize-i64.cton +++ b/cranelift/filetests/isa/riscv/legalize-i64.cton @@ -1,6 +1,6 @@ ; Test the legalization of i64 arithmetic instructions. test legalizer -isa riscv supports_m=1 +target riscv32 supports_m=1 ; regex: V=v\d+ diff --git a/cranelift/filetests/isa/riscv/parse-encoding.cton b/cranelift/filetests/isa/riscv/parse-encoding.cton index e61f43ef84..f79e552e6d 100644 --- a/cranelift/filetests/isa/riscv/parse-encoding.cton +++ b/cranelift/filetests/isa/riscv/parse-encoding.cton @@ -1,6 +1,6 @@ ; Test the parser's support for encoding annotations. test legalizer -isa riscv +target riscv32 function %parse_encoding(i32 [%x5]) -> i32 [%x10] { ; check: function %parse_encoding(i32 [%x5], i32 link [%x1]) -> i32 [%x10], i32 link [%x1] fast { diff --git a/cranelift/filetests/isa/riscv/regmove.cton b/cranelift/filetests/isa/riscv/regmove.cton index c316f74f21..6ec17ef813 100644 --- a/cranelift/filetests/isa/riscv/regmove.cton +++ b/cranelift/filetests/isa/riscv/regmove.cton @@ -1,6 +1,6 @@ ; Test tracking of register moves. test binemit -isa riscv +target riscv32 function %regmoves(i32 link [%x1]) -> i32 link [%x1] { ebb0(v9999: i32): diff --git a/cranelift/filetests/isa/riscv/split-args.cton b/cranelift/filetests/isa/riscv/split-args.cton index 80de18fd7a..dd605de81a 100644 --- a/cranelift/filetests/isa/riscv/split-args.cton +++ b/cranelift/filetests/isa/riscv/split-args.cton @@ -1,6 +1,6 @@ ; Test the legalization of EBB arguments that are split. test legalizer -isa riscv +target riscv32 ; regex: V=v\d+ diff --git a/cranelift/filetests/isa/riscv/verify-encoding.cton b/cranelift/filetests/isa/riscv/verify-encoding.cton index 1aaedf1c89..99ed4697bb 100644 --- a/cranelift/filetests/isa/riscv/verify-encoding.cton +++ b/cranelift/filetests/isa/riscv/verify-encoding.cton @@ -1,5 +1,5 @@ test verifier -isa riscv +target riscv32 function %RV32I(i32 link [%x1]) -> i32 link [%x1] { fn0 = %foo() diff --git a/cranelift/filetests/isa/x86/abcd.cton b/cranelift/filetests/isa/x86/abcd.cton index f0007d795d..67acac970b 100644 --- a/cranelift/filetests/isa/x86/abcd.cton +++ b/cranelift/filetests/isa/x86/abcd.cton @@ -1,5 +1,5 @@ test regalloc -isa x86 +target i686 ; %rdi can't be used in a movsbl instruction, so test that the register ; allocator can move it to a register that can be. diff --git a/cranelift/filetests/isa/x86/abi-bool.cton b/cranelift/filetests/isa/x86/abi-bool.cton index 48ac976a84..fdf21ba055 100644 --- a/cranelift/filetests/isa/x86/abi-bool.cton +++ b/cranelift/filetests/isa/x86/abi-bool.cton @@ -1,6 +1,5 @@ test compile -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %foo(i64, i64, i64, i32) -> b1 system_v { ebb3(v0: i64, v1: i64, v2: i64, v3: i32): diff --git a/cranelift/filetests/isa/x86/abi32.cton b/cranelift/filetests/isa/x86/abi32.cton index 04b8d2ec6f..4b9f5fbcd1 100644 --- a/cranelift/filetests/isa/x86/abi32.cton +++ b/cranelift/filetests/isa/x86/abi32.cton @@ -1,6 +1,6 @@ ; Test the legalization of function signatures. test legalizer -isa x86 +target i686 ; regex: V=v\d+ diff --git a/cranelift/filetests/isa/x86/abi64.cton b/cranelift/filetests/isa/x86/abi64.cton index 121e5cc1a8..209b036ee2 100644 --- a/cranelift/filetests/isa/x86/abi64.cton +++ b/cranelift/filetests/isa/x86/abi64.cton @@ -1,7 +1,6 @@ ; Test the legalization of function signatures. test legalizer -set is_64bit -isa x86 +target x86_64 ; regex: V=v\d+ diff --git a/cranelift/filetests/isa/x86/allones_funcaddrs32.cton b/cranelift/filetests/isa/x86/allones_funcaddrs32.cton index cf0036f4d0..2e3dbf50f3 100644 --- a/cranelift/filetests/isa/x86/allones_funcaddrs32.cton +++ b/cranelift/filetests/isa/x86/allones_funcaddrs32.cton @@ -2,7 +2,7 @@ test binemit set opt_level=best set allones_funcaddrs -isa x86 haswell +target i686 haswell ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/allones_funcaddrs64.cton b/cranelift/filetests/isa/x86/allones_funcaddrs64.cton index 3f47c78052..6edbbcf4d2 100644 --- a/cranelift/filetests/isa/x86/allones_funcaddrs64.cton +++ b/cranelift/filetests/isa/x86/allones_funcaddrs64.cton @@ -1,9 +1,8 @@ ; binary emission of 64-bit code. test binemit -set is_64bit set opt_level=best set allones_funcaddrs -isa x86 haswell +target x86_64 haswell ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount.cton b/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount.cton index c79de42317..595e5e99bb 100644 --- a/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount.cton +++ b/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount.cton @@ -1,7 +1,5 @@ - test compile -set is_64bit -isa x86 baseline +target x86_64 baseline ; clz/ctz on 64 bit operands diff --git a/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount_encoding.cton b/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount_encoding.cton index 72104272e1..16acad9cb6 100644 --- a/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount_encoding.cton +++ b/cranelift/filetests/isa/x86/baseline_clz_ctz_popcount_encoding.cton @@ -1,7 +1,6 @@ test binemit -set is_64bit set opt_level=best -isa x86 baseline +target x86_64 baseline ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/binary32-float.cton b/cranelift/filetests/isa/x86/binary32-float.cton index 7b1a07853a..05847e9f58 100644 --- a/cranelift/filetests/isa/x86/binary32-float.cton +++ b/cranelift/filetests/isa/x86/binary32-float.cton @@ -1,6 +1,6 @@ ; Binary emission of 32-bit floating point code. test binemit -isa x86 haswell +target i686 haswell ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/binary32.cton b/cranelift/filetests/isa/x86/binary32.cton index 5ce1b228c9..b953d663f6 100644 --- a/cranelift/filetests/isa/x86/binary32.cton +++ b/cranelift/filetests/isa/x86/binary32.cton @@ -1,7 +1,7 @@ ; binary emission of x86-32 code. test binemit set opt_level=best -isa x86 haswell +target i686 haswell ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/binary64-float.cton b/cranelift/filetests/isa/x86/binary64-float.cton index 2f17c75ea6..9bc92e686b 100644 --- a/cranelift/filetests/isa/x86/binary64-float.cton +++ b/cranelift/filetests/isa/x86/binary64-float.cton @@ -1,8 +1,7 @@ ; Binary emission of 64-bit floating point code. test binemit -set is_64bit set opt_level=best -isa x86 haswell +target x86_64 haswell ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/binary64-pic.cton b/cranelift/filetests/isa/x86/binary64-pic.cton index 8d3b2e54ab..3678906135 100644 --- a/cranelift/filetests/isa/x86/binary64-pic.cton +++ b/cranelift/filetests/isa/x86/binary64-pic.cton @@ -1,9 +1,8 @@ ; binary emission of 64-bit code. test binemit -set is_64bit set opt_level=best set is_pic -isa x86 haswell +target x86_64 haswell ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/binary64.cton b/cranelift/filetests/isa/x86/binary64.cton index 2432736e64..96788c629b 100644 --- a/cranelift/filetests/isa/x86/binary64.cton +++ b/cranelift/filetests/isa/x86/binary64.cton @@ -1,8 +1,7 @@ ; binary emission of x86-64 code. test binemit -set is_64bit set opt_level=best -isa x86 haswell +target x86_64 haswell ; The binary encodings can be verified with the command: ; diff --git a/cranelift/filetests/isa/x86/legalize-call.cton b/cranelift/filetests/isa/x86/legalize-call.cton index 0eaaba0dfa..b66e7e3a53 100644 --- a/cranelift/filetests/isa/x86/legalize-call.cton +++ b/cranelift/filetests/isa/x86/legalize-call.cton @@ -1,8 +1,7 @@ ; Test legalization of a non-colocated call in 64-bit non-PIC mode. test legalizer -set is_64bit set opt_level=best -isa x86 haswell +target x86_64 haswell function %call() { fn0 = %foo() diff --git a/cranelift/filetests/isa/x86/legalize-custom.cton b/cranelift/filetests/isa/x86/legalize-custom.cton index 8f719056cd..667c08804c 100644 --- a/cranelift/filetests/isa/x86/legalize-custom.cton +++ b/cranelift/filetests/isa/x86/legalize-custom.cton @@ -1,8 +1,7 @@ ; Test the custom legalizations. test legalizer -isa x86 -set is_64bit -isa x86 +target i686 +target x86_64 ; regex: V=v\d+ ; regex: EBB=ebb\d+ diff --git a/cranelift/filetests/isa/x86/legalize-div-traps.cton b/cranelift/filetests/isa/x86/legalize-div-traps.cton index 4d7beb59b8..b849f07e1b 100644 --- a/cranelift/filetests/isa/x86/legalize-div-traps.cton +++ b/cranelift/filetests/isa/x86/legalize-div-traps.cton @@ -1,9 +1,8 @@ ; Test the division legalizations. test legalizer -set is_64bit ; See also legalize-div.cton. set avoid_div_traps=1 -isa x86 +target x86_64 ; regex: V=v\d+ ; regex: EBB=ebb\d+ diff --git a/cranelift/filetests/isa/x86/legalize-div.cton b/cranelift/filetests/isa/x86/legalize-div.cton index 3777be659e..d3a4d359da 100644 --- a/cranelift/filetests/isa/x86/legalize-div.cton +++ b/cranelift/filetests/isa/x86/legalize-div.cton @@ -1,9 +1,8 @@ ; Test the division legalizations. test legalizer -set is_64bit ; See also legalize-div-traps.cton. set avoid_div_traps=0 -isa x86 +target x86_64 ; regex: V=v\d+ ; regex: EBB=ebb\d+ diff --git a/cranelift/filetests/isa/x86/legalize-libcall.cton b/cranelift/filetests/isa/x86/legalize-libcall.cton index fdad2a3cf2..3605f2ff7b 100644 --- a/cranelift/filetests/isa/x86/legalize-libcall.cton +++ b/cranelift/filetests/isa/x86/legalize-libcall.cton @@ -1,10 +1,9 @@ test legalizer ; Pre-SSE 4.1, we need to use runtime library calls for floating point rounding operations. -set is_64bit set is_pic set call_conv=system_v -isa x86 +target x86_64 function %floor(f32) -> f32 { ebb0(v0: f32): diff --git a/cranelift/filetests/isa/x86/legalize-memory.cton b/cranelift/filetests/isa/x86/legalize-memory.cton index fc77c757e3..13375e124d 100644 --- a/cranelift/filetests/isa/x86/legalize-memory.cton +++ b/cranelift/filetests/isa/x86/legalize-memory.cton @@ -1,7 +1,6 @@ ; Test the legalization of memory objects. test legalizer -set is_64bit -isa x86 +target x86_64 ; regex: V=v\d+ ; regex: EBB=ebb\d+ diff --git a/cranelift/filetests/isa/x86/legalize-mulhi.cton b/cranelift/filetests/isa/x86/legalize-mulhi.cton index a588f25d4e..946bcd8428 100644 --- a/cranelift/filetests/isa/x86/legalize-mulhi.cton +++ b/cranelift/filetests/isa/x86/legalize-mulhi.cton @@ -1,7 +1,5 @@ - test compile -set is_64bit -isa x86 baseline +target x86_64 baseline ; umulhi/smulhi on 64 bit operands diff --git a/cranelift/filetests/isa/x86/optimized-zero-constants-32bit.cton b/cranelift/filetests/isa/x86/optimized-zero-constants-32bit.cton index 338569d055..c90e455527 100644 --- a/cranelift/filetests/isa/x86/optimized-zero-constants-32bit.cton +++ b/cranelift/filetests/isa/x86/optimized-zero-constants-32bit.cton @@ -1,7 +1,6 @@ ; Check that floating-point constants equal to zero are optimized correctly. test binemit -set is_64bit=0 -isa x86 +target i686 function %foo() -> f32 fast { ebb0: diff --git a/cranelift/filetests/isa/x86/optimized-zero-constants.cton b/cranelift/filetests/isa/x86/optimized-zero-constants.cton index d83bfd3ade..44060e9b97 100644 --- a/cranelift/filetests/isa/x86/optimized-zero-constants.cton +++ b/cranelift/filetests/isa/x86/optimized-zero-constants.cton @@ -1,7 +1,6 @@ ; Check that floating-point constants equal to zero are optimized correctly. test binemit -set is_64bit=1 -isa x86 +target x86_64 function %zero_const_32bit_no_rex() -> f32 fast { ebb0: diff --git a/cranelift/filetests/isa/x86/probestack-adjusts-sp.cton b/cranelift/filetests/isa/x86/probestack-adjusts-sp.cton index 2204886046..f0e351d84f 100644 --- a/cranelift/filetests/isa/x86/probestack-adjusts-sp.cton +++ b/cranelift/filetests/isa/x86/probestack-adjusts-sp.cton @@ -1,8 +1,7 @@ test compile -set is_64bit=1 set colocated_libcalls=1 set probestack_func_adjusts_sp=1 -isa x86 +target x86_64 ; Like %big in probestack.cton, but with the probestack function adjusting ; the stack pointer itself. diff --git a/cranelift/filetests/isa/x86/probestack-disabled.cton b/cranelift/filetests/isa/x86/probestack-disabled.cton index 282e088a3a..cbf1ed0b0d 100644 --- a/cranelift/filetests/isa/x86/probestack-disabled.cton +++ b/cranelift/filetests/isa/x86/probestack-disabled.cton @@ -1,8 +1,7 @@ test compile -set is_64bit=1 set colocated_libcalls=1 set probestack_enabled=0 -isa x86 +target x86_64 ; Like %big in probestack.cton, but with probes disabled. diff --git a/cranelift/filetests/isa/x86/probestack-noncolocated.cton b/cranelift/filetests/isa/x86/probestack-noncolocated.cton index 3248f4a142..8ec23719cc 100644 --- a/cranelift/filetests/isa/x86/probestack-noncolocated.cton +++ b/cranelift/filetests/isa/x86/probestack-noncolocated.cton @@ -1,6 +1,5 @@ test compile -set is_64bit=1 -isa x86 +target x86_64 ; Like %big in probestack.cton, but without a colocated libcall. diff --git a/cranelift/filetests/isa/x86/probestack-size.cton b/cranelift/filetests/isa/x86/probestack-size.cton index d7c92a5aa5..e413db3b1b 100644 --- a/cranelift/filetests/isa/x86/probestack-size.cton +++ b/cranelift/filetests/isa/x86/probestack-size.cton @@ -1,8 +1,7 @@ test compile -set is_64bit=1 set colocated_libcalls=1 set probestack_size_log2=13 -isa x86 +target x86_64 ; Like %big in probestack.cton, but now the probestack size is bigger ; and it no longer needs a probe. diff --git a/cranelift/filetests/isa/x86/probestack.cton b/cranelift/filetests/isa/x86/probestack.cton index 8b961da3bd..fbfd656309 100644 --- a/cranelift/filetests/isa/x86/probestack.cton +++ b/cranelift/filetests/isa/x86/probestack.cton @@ -1,7 +1,6 @@ test compile -set is_64bit=1 set colocated_libcalls=1 -isa x86 +target x86_64 ; A function with a big stack frame. This should have a stack probe. diff --git a/cranelift/filetests/isa/x86/prologue-epilogue.cton b/cranelift/filetests/isa/x86/prologue-epilogue.cton index 249f2a9ff9..a19af2c09b 100644 --- a/cranelift/filetests/isa/x86/prologue-epilogue.cton +++ b/cranelift/filetests/isa/x86/prologue-epilogue.cton @@ -1,8 +1,7 @@ test compile -set is_64bit set opt_level=best set is_pic -isa x86 haswell +target x86_64 haswell ; An empty function. diff --git a/cranelift/filetests/isa/x86/shrink.cton b/cranelift/filetests/isa/x86/shrink.cton index 1dc5fbcd42..7648a6dd22 100644 --- a/cranelift/filetests/isa/x86/shrink.cton +++ b/cranelift/filetests/isa/x86/shrink.cton @@ -1,7 +1,6 @@ test binemit -set is_64bit=1 set opt_level=best -isa x86 +target x86_64 ; Test that instruction shrinking eliminates REX prefixes when possible. diff --git a/cranelift/filetests/isa/x86/windows_fastcall_x64.cton b/cranelift/filetests/isa/x86/windows_fastcall_x64.cton index 204bd5bb70..7af721ed8e 100644 --- a/cranelift/filetests/isa/x86/windows_fastcall_x64.cton +++ b/cranelift/filetests/isa/x86/windows_fastcall_x64.cton @@ -1,8 +1,7 @@ test compile -set is_64bit set opt_level=best set is_pic -isa x86 haswell +target x86_64 haswell ; check if for one arg we use the right register function %one_arg(i64) windows_fastcall { diff --git a/cranelift/filetests/parser/instruction_encoding.cton b/cranelift/filetests/parser/instruction_encoding.cton index 7d75e4362a..9a405030a6 100644 --- a/cranelift/filetests/parser/instruction_encoding.cton +++ b/cranelift/filetests/parser/instruction_encoding.cton @@ -1,6 +1,6 @@ test cat -isa riscv +target riscv32 ; regex: WS=[ \t]* diff --git a/cranelift/filetests/postopt/basic.cton b/cranelift/filetests/postopt/basic.cton index 678cecc27c..5b65407004 100644 --- a/cranelift/filetests/postopt/basic.cton +++ b/cranelift/filetests/postopt/basic.cton @@ -1,5 +1,5 @@ test postopt -isa x86 +target i686 ; Test that compare+branch sequences are folded effectively on x86. diff --git a/cranelift/filetests/postopt/complex_memory_ops.cton b/cranelift/filetests/postopt/complex_memory_ops.cton index 8f12e61577..0977fa0d7d 100644 --- a/cranelift/filetests/postopt/complex_memory_ops.cton +++ b/cranelift/filetests/postopt/complex_memory_ops.cton @@ -1,6 +1,5 @@ test postopt -set is_64bit -isa x86 +target x86_64 function %dual_loads(i64, i64) -> i64 { ebb0(v0: i64, v1: i64): diff --git a/cranelift/filetests/preopt/div_by_const_indirect.cton b/cranelift/filetests/preopt/div_by_const_indirect.cton index 5d3f9475fc..5d3266d26a 100644 --- a/cranelift/filetests/preopt/div_by_const_indirect.cton +++ b/cranelift/filetests/preopt/div_by_const_indirect.cton @@ -1,6 +1,5 @@ - test preopt -isa x86 baseline +target i686 baseline ; Cases where the denominator is created by an iconst diff --git a/cranelift/filetests/preopt/div_by_const_non_power_of_2.cton b/cranelift/filetests/preopt/div_by_const_non_power_of_2.cton index fa3f7fa96a..1d05d4a53c 100644 --- a/cranelift/filetests/preopt/div_by_const_non_power_of_2.cton +++ b/cranelift/filetests/preopt/div_by_const_non_power_of_2.cton @@ -1,6 +1,5 @@ - test preopt -isa x86 baseline +target i686 baseline ; -------- U32 -------- diff --git a/cranelift/filetests/preopt/div_by_const_power_of_2.cton b/cranelift/filetests/preopt/div_by_const_power_of_2.cton index 2318aa1f81..a047107c26 100644 --- a/cranelift/filetests/preopt/div_by_const_power_of_2.cton +++ b/cranelift/filetests/preopt/div_by_const_power_of_2.cton @@ -1,6 +1,5 @@ - test preopt -isa x86 baseline +target i686 baseline ; -------- U32 -------- diff --git a/cranelift/filetests/preopt/rem_by_const_non_power_of_2.cton b/cranelift/filetests/preopt/rem_by_const_non_power_of_2.cton index 3d4b986213..f440aa4a6e 100644 --- a/cranelift/filetests/preopt/rem_by_const_non_power_of_2.cton +++ b/cranelift/filetests/preopt/rem_by_const_non_power_of_2.cton @@ -1,6 +1,5 @@ - test preopt -isa x86 baseline +target i686 baseline ; -------- U32 -------- diff --git a/cranelift/filetests/preopt/rem_by_const_power_of_2.cton b/cranelift/filetests/preopt/rem_by_const_power_of_2.cton index 7b537fdbb4..70bd1bbd4e 100644 --- a/cranelift/filetests/preopt/rem_by_const_power_of_2.cton +++ b/cranelift/filetests/preopt/rem_by_const_power_of_2.cton @@ -1,6 +1,5 @@ - test preopt -isa x86 baseline +target i686 baseline ; -------- U32 -------- diff --git a/cranelift/filetests/preopt/simplify.cton b/cranelift/filetests/preopt/simplify.cton index 32f19f4f03..4426b98186 100644 --- a/cranelift/filetests/preopt/simplify.cton +++ b/cranelift/filetests/preopt/simplify.cton @@ -1,5 +1,5 @@ test preopt -isa x86 +target i686 function %iadd_imm(i32) -> i32 { ebb0(v0: i32): diff --git a/cranelift/filetests/regalloc/aliases.cton b/cranelift/filetests/regalloc/aliases.cton index eb84c77f98..b9b76c3f1d 100644 --- a/cranelift/filetests/regalloc/aliases.cton +++ b/cranelift/filetests/regalloc/aliases.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell function %value_aliases(i32, f32, i64 vmctx) baldrdash { gv0 = vmctx diff --git a/cranelift/filetests/regalloc/basic.cton b/cranelift/filetests/regalloc/basic.cton index c24f87c1f9..d10ea726ce 100644 --- a/cranelift/filetests/regalloc/basic.cton +++ b/cranelift/filetests/regalloc/basic.cton @@ -1,7 +1,7 @@ test regalloc ; We can add more ISAs once they have defined encodings. -isa riscv +target riscv32 ; regex: RX=%x\d+ diff --git a/cranelift/filetests/regalloc/coalesce.cton b/cranelift/filetests/regalloc/coalesce.cton index 04782fc1fc..0085ce0fd8 100644 --- a/cranelift/filetests/regalloc/coalesce.cton +++ b/cranelift/filetests/regalloc/coalesce.cton @@ -1,5 +1,5 @@ test regalloc -isa riscv +target riscv32 ; Test the coalescer. ; regex: V=v\d+ diff --git a/cranelift/filetests/regalloc/coalescing-207.cton b/cranelift/filetests/regalloc/coalescing-207.cton index d8af887da3..2fc3cfc429 100644 --- a/cranelift/filetests/regalloc/coalescing-207.cton +++ b/cranelift/filetests/regalloc/coalescing-207.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell ; Reported as https://github.com/cretonne/cretonne/issues/207 ; diff --git a/cranelift/filetests/regalloc/coalescing-216.cton b/cranelift/filetests/regalloc/coalescing-216.cton index fc986f7fec..fc4e877f68 100644 --- a/cranelift/filetests/regalloc/coalescing-216.cton +++ b/cranelift/filetests/regalloc/coalescing-216.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell ; Reported as https://github.com/cretonne/cretonne/issues/216 from the Binaryen fuzzer. ; diff --git a/cranelift/filetests/regalloc/coloring-227.cton b/cranelift/filetests/regalloc/coloring-227.cton index 2b327633c7..248f75dbef 100644 --- a/cranelift/filetests/regalloc/coloring-227.cton +++ b/cranelift/filetests/regalloc/coloring-227.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell function %pr227(i32 [%rdi], i32 [%rsi], i32 [%rdx], i32 [%rcx], i64 vmctx [%r8]) system_v { gv0 = vmctx diff --git a/cranelift/filetests/regalloc/constraints.cton b/cranelift/filetests/regalloc/constraints.cton index e4db3bf9da..a0478baae9 100644 --- a/cranelift/filetests/regalloc/constraints.cton +++ b/cranelift/filetests/regalloc/constraints.cton @@ -1,5 +1,5 @@ test regalloc -isa x86 +target i686 ; regex: V=v\d+ ; regex: REG=%r([abcd]x|[sd]i) diff --git a/cranelift/filetests/regalloc/ghost-param.cton b/cranelift/filetests/regalloc/ghost-param.cton index 2064231318..8a022b4af5 100644 --- a/cranelift/filetests/regalloc/ghost-param.cton +++ b/cranelift/filetests/regalloc/ghost-param.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell ; This test case would create an EBB parameter that was a ghost value. ; The coalescer would insert a copy of the ghost value, leading to verifier errors. diff --git a/cranelift/filetests/regalloc/global-constraints.cton b/cranelift/filetests/regalloc/global-constraints.cton index 4975adeac5..e3e59dd470 100644 --- a/cranelift/filetests/regalloc/global-constraints.cton +++ b/cranelift/filetests/regalloc/global-constraints.cton @@ -1,5 +1,5 @@ test regalloc -isa x86 +target i686 ; This test covers the troubles when values with global live ranges are defined ; by instructions with constrained register classes. diff --git a/cranelift/filetests/regalloc/global-fixed.cton b/cranelift/filetests/regalloc/global-fixed.cton index 61d4928806..eb8e23d7af 100644 --- a/cranelift/filetests/regalloc/global-fixed.cton +++ b/cranelift/filetests/regalloc/global-fixed.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %foo() system_v { ebb4: diff --git a/cranelift/filetests/regalloc/infinite-interference.cton b/cranelift/filetests/regalloc/infinite-interference.cton index 8f07c4cf77..bce607b7f6 100644 --- a/cranelift/filetests/regalloc/infinite-interference.cton +++ b/cranelift/filetests/regalloc/infinite-interference.cton @@ -1,5 +1,5 @@ test regalloc -isa riscv +target riscv32 ; Here, the coalescer initially builds vreg0 = [v1, v2, v3] ; diff --git a/cranelift/filetests/regalloc/iterate.cton b/cranelift/filetests/regalloc/iterate.cton index 44e1265a96..c7ad214432 100644 --- a/cranelift/filetests/regalloc/iterate.cton +++ b/cranelift/filetests/regalloc/iterate.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell function u0:9(i64 [%rdi], f32 [%xmm0], f64 [%xmm1], i32 [%rsi], i32 [%rdx], i64 vmctx [%r14]) -> i64 [%rax] baldrdash { ebb0(v0: i64, v1: f32, v2: f64, v3: i32, v4: i32, v5: i64): diff --git a/cranelift/filetests/regalloc/multi-constraints.cton b/cranelift/filetests/regalloc/multi-constraints.cton index 590d93eb38..d0b6f7faf0 100644 --- a/cranelift/filetests/regalloc/multi-constraints.cton +++ b/cranelift/filetests/regalloc/multi-constraints.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell ; Test combinations of constraints. ; diff --git a/cranelift/filetests/regalloc/output-interference.cton b/cranelift/filetests/regalloc/output-interference.cton index ac2bb537c7..ab027a72fb 100644 --- a/cranelift/filetests/regalloc/output-interference.cton +++ b/cranelift/filetests/regalloc/output-interference.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %test(i64) -> i64 system_v { ebb0(v0: i64): diff --git a/cranelift/filetests/regalloc/reload-208.cton b/cranelift/filetests/regalloc/reload-208.cton index 259c4a169b..6b4dc74292 100644 --- a/cranelift/filetests/regalloc/reload-208.cton +++ b/cranelift/filetests/regalloc/reload-208.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 haswell +target x86_64 haswell ; regex: V=v\d+ diff --git a/cranelift/filetests/regalloc/reload.cton b/cranelift/filetests/regalloc/reload.cton index d0a9646808..517b0990d1 100644 --- a/cranelift/filetests/regalloc/reload.cton +++ b/cranelift/filetests/regalloc/reload.cton @@ -1,5 +1,5 @@ test regalloc -isa riscv enable_e +target riscv32 enable_e ; regex: V=v\d+ diff --git a/cranelift/filetests/regalloc/schedule-moves.cton b/cranelift/filetests/regalloc/schedule-moves.cton index 946bcc9cf3..afd652ece9 100644 --- a/cranelift/filetests/regalloc/schedule-moves.cton +++ b/cranelift/filetests/regalloc/schedule-moves.cton @@ -1,5 +1,5 @@ test regalloc -isa x86 haswell +target i686 haswell function %pr165() system_v { ebb0: diff --git a/cranelift/filetests/regalloc/spill-noregs.cton b/cranelift/filetests/regalloc/spill-noregs.cton index ffb9f041c1..6e0b2baabb 100644 --- a/cranelift/filetests/regalloc/spill-noregs.cton +++ b/cranelift/filetests/regalloc/spill-noregs.cton @@ -1,6 +1,5 @@ test regalloc -set is_64bit -isa x86 +target x86_64 ; Test case found by the Binaryen fuzzer. ; diff --git a/cranelift/filetests/regalloc/spill.cton b/cranelift/filetests/regalloc/spill.cton index 7205d6a851..21731f321a 100644 --- a/cranelift/filetests/regalloc/spill.cton +++ b/cranelift/filetests/regalloc/spill.cton @@ -12,7 +12,7 @@ test regalloc ; regex: V=v\d+ ; regex: WS=\s+ -isa riscv enable_e +target riscv32 enable_e ; In straight-line code, the first value defined is spilled. ; That is in order: diff --git a/cranelift/filetests/regalloc/unreachable_code.cton b/cranelift/filetests/regalloc/unreachable_code.cton index 8bfffc22a2..9d11ded01a 100644 --- a/cranelift/filetests/regalloc/unreachable_code.cton +++ b/cranelift/filetests/regalloc/unreachable_code.cton @@ -1,9 +1,8 @@ ; Use "test compile" here otherwise the dead blocks won't be eliminated. test compile -set is_64bit set probestack_enabled=0 -isa x86 haswell +target x86_64 haswell ; This function contains unreachable blocks which trip up the register ; allocator if they don't get cleared out. diff --git a/cranelift/filetests/regalloc/x86-regres.cton b/cranelift/filetests/regalloc/x86-regres.cton index e396fb1022..66c3d45c2e 100644 --- a/cranelift/filetests/regalloc/x86-regres.cton +++ b/cranelift/filetests/regalloc/x86-regres.cton @@ -1,6 +1,6 @@ test regalloc -isa x86 +target i686 ; regex: V=v\d+ diff --git a/cranelift/filetests/verifier/flags.cton b/cranelift/filetests/verifier/flags.cton index 55d9bdf4e1..8a6abe8b4d 100644 --- a/cranelift/filetests/verifier/flags.cton +++ b/cranelift/filetests/verifier/flags.cton @@ -1,5 +1,5 @@ test verifier -isa x86 +target i686 ; Simple, correct use of CPU flags. function %simple(i32) -> i32 { diff --git a/cranelift/filetests/wasm/control.cton b/cranelift/filetests/wasm/control.cton index 30d4240490..a34bbeb935 100644 --- a/cranelift/filetests/wasm/control.cton +++ b/cranelift/filetests/wasm/control.cton @@ -1,11 +1,9 @@ ; Test basic code generation for control flow WebAssembly instructions. test compile -set is_64bit=0 -isa x86 haswell +target i686 haswell -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %br_if(i32) -> i32 { ebb0(v0: i32): diff --git a/cranelift/filetests/wasm/conversions.cton b/cranelift/filetests/wasm/conversions.cton index 5ca8072067..0b7630da0d 100644 --- a/cranelift/filetests/wasm/conversions.cton +++ b/cranelift/filetests/wasm/conversions.cton @@ -1,8 +1,7 @@ ; Test code generation for WebAssembly type conversion operators. test compile -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %i32_wrap_i64(i64) -> i32 { ebb0(v0: i64): diff --git a/cranelift/filetests/wasm/f32-arith.cton b/cranelift/filetests/wasm/f32-arith.cton index 7ce8eb4142..c439d2e798 100644 --- a/cranelift/filetests/wasm/f32-arith.cton +++ b/cranelift/filetests/wasm/f32-arith.cton @@ -1,17 +1,10 @@ ; Test basic code generation for f32 arithmetic WebAssembly instructions. test compile -set is_64bit=0 -isa x86 haswell - -set is_64bit=0 -isa x86 baseline - -set is_64bit=1 -isa x86 haswell - -set is_64bit=1 -isa x86 baseline +target i686 haswell +target i686 baseline +target x86_64 haswell +target x86_64 baseline ; Constants. diff --git a/cranelift/filetests/wasm/f32-compares.cton b/cranelift/filetests/wasm/f32-compares.cton index 0cdee58ef3..e314646b1c 100644 --- a/cranelift/filetests/wasm/f32-compares.cton +++ b/cranelift/filetests/wasm/f32-compares.cton @@ -1,11 +1,9 @@ ; Test code generation for WebAssembly f32 comparison operators. test compile -set is_64bit=0 -isa x86 haswell +target i686 haswell -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %f32_eq(f32, f32) -> i32 { ebb0(v0: f32, v1: f32): diff --git a/cranelift/filetests/wasm/f32-memory64.cton b/cranelift/filetests/wasm/f32-memory64.cton index a6e0d54af7..42b183311b 100644 --- a/cranelift/filetests/wasm/f32-memory64.cton +++ b/cranelift/filetests/wasm/f32-memory64.cton @@ -3,8 +3,7 @@ test compile ; We only test on 64-bit since the heap_addr instructions and vmctx parameters ; explicitly mention the pointer width. -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %f32_load(i32, i64 vmctx) -> f32 { gv0 = vmctx diff --git a/cranelift/filetests/wasm/f64-arith.cton b/cranelift/filetests/wasm/f64-arith.cton index 150d9a0d8e..7209ed6024 100644 --- a/cranelift/filetests/wasm/f64-arith.cton +++ b/cranelift/filetests/wasm/f64-arith.cton @@ -1,11 +1,8 @@ ; Test basic code generation for f64 arithmetic WebAssembly instructions. test compile -set is_64bit=1 -isa x86 haswell - -set is_64bit=1 -isa x86 baseline +target x86_64 haswell +target x86_64 baseline ; Constants. diff --git a/cranelift/filetests/wasm/f64-compares.cton b/cranelift/filetests/wasm/f64-compares.cton index ff1b9526d0..5d51ebb443 100644 --- a/cranelift/filetests/wasm/f64-compares.cton +++ b/cranelift/filetests/wasm/f64-compares.cton @@ -1,11 +1,9 @@ ; Test code generation for WebAssembly f64 comparison operators. test compile -set is_64bit=0 -isa x86 haswell +target i686 haswell -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %f64_eq(f64, f64) -> i32 { ebb0(v0: f64, v1: f64): diff --git a/cranelift/filetests/wasm/f64-memory64.cton b/cranelift/filetests/wasm/f64-memory64.cton index 0a15e69a37..b495dfd344 100644 --- a/cranelift/filetests/wasm/f64-memory64.cton +++ b/cranelift/filetests/wasm/f64-memory64.cton @@ -3,8 +3,7 @@ test compile ; We only test on 64-bit since the heap_addr instructions and vmctx parameters ; explicitly mention the pointer width. -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %f64_load(i32, i64 vmctx) -> f64 { gv0 = vmctx diff --git a/cranelift/filetests/wasm/i32-arith.cton b/cranelift/filetests/wasm/i32-arith.cton index f6ee971c69..8c92613150 100644 --- a/cranelift/filetests/wasm/i32-arith.cton +++ b/cranelift/filetests/wasm/i32-arith.cton @@ -1,17 +1,10 @@ ; Test basic code generation for i32 arithmetic WebAssembly instructions. test compile -set is_64bit=0 -isa x86 haswell - -set is_64bit=0 -isa x86 baseline - -set is_64bit=1 -isa x86 haswell - -set is_64bit=1 -isa x86 baseline +target i686 haswell +target i686 baseline +target x86_64 haswell +target x86_64 baseline ; Constants. diff --git a/cranelift/filetests/wasm/i32-compares.cton b/cranelift/filetests/wasm/i32-compares.cton index a36df1b28a..1b43c5938a 100644 --- a/cranelift/filetests/wasm/i32-compares.cton +++ b/cranelift/filetests/wasm/i32-compares.cton @@ -1,11 +1,9 @@ ; Test code generation for WebAssembly i32 comparison operators. test compile -set is_64bit=0 -isa x86 haswell +target i686 haswell -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %i32_eqz(i32) -> i32 { ebb0(v0: i32): diff --git a/cranelift/filetests/wasm/i32-memory64.cton b/cranelift/filetests/wasm/i32-memory64.cton index 319609e9d3..b32325561a 100644 --- a/cranelift/filetests/wasm/i32-memory64.cton +++ b/cranelift/filetests/wasm/i32-memory64.cton @@ -3,8 +3,7 @@ test compile ; We only test on 64-bit since the heap_addr instructions and vmctx parameters ; explicitly mention the pointer width. -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %i32_load(i32, i64 vmctx) -> i32 { gv0 = vmctx diff --git a/cranelift/filetests/wasm/i64-arith.cton b/cranelift/filetests/wasm/i64-arith.cton index 52016039e0..c4cd4a4507 100644 --- a/cranelift/filetests/wasm/i64-arith.cton +++ b/cranelift/filetests/wasm/i64-arith.cton @@ -1,11 +1,8 @@ ; Test basic code generation for i64 arithmetic WebAssembly instructions. test compile -set is_64bit=1 -isa x86 haswell - -set is_64bit=1 -isa x86 baseline +target x86_64 haswell +target x86_64 baseline ; Constants. diff --git a/cranelift/filetests/wasm/i64-compares.cton b/cranelift/filetests/wasm/i64-compares.cton index 4679268018..e137b7e19c 100644 --- a/cranelift/filetests/wasm/i64-compares.cton +++ b/cranelift/filetests/wasm/i64-compares.cton @@ -1,8 +1,7 @@ ; Test code generation for WebAssembly i64 comparison operators. test compile -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %i64_eqz(i64) -> i32 { ebb0(v0: i64): diff --git a/cranelift/filetests/wasm/i64-memory64.cton b/cranelift/filetests/wasm/i64-memory64.cton index 7c9836dbf3..76a1a02e4b 100644 --- a/cranelift/filetests/wasm/i64-memory64.cton +++ b/cranelift/filetests/wasm/i64-memory64.cton @@ -3,8 +3,7 @@ test compile ; We only test on 64-bit since the heap_addr instructions and vmctx parameters ; explicitly mention the pointer width. -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %i64_load(i32, i64 vmctx) -> i64 { gv0 = vmctx diff --git a/cranelift/filetests/wasm/select.cton b/cranelift/filetests/wasm/select.cton index 7f1c26e724..f5f55cda24 100644 --- a/cranelift/filetests/wasm/select.cton +++ b/cranelift/filetests/wasm/select.cton @@ -1,11 +1,9 @@ ; Test basic code generation for the select WebAssembly instruction. test compile -set is_64bit=0 -isa x86 haswell +target i686 haswell -set is_64bit=1 -isa x86 haswell +target x86_64 haswell function %select_i32(i32, i32, i32) -> i32 { ebb0(v0: i32, v1: i32, v2: i32): diff --git a/cranelift/fuzz/Cargo.toml b/cranelift/fuzz/Cargo.toml index d48922c1f4..f1169e2763 100644 --- a/cranelift/fuzz/Cargo.toml +++ b/cranelift/fuzz/Cargo.toml @@ -20,6 +20,9 @@ git = "https://github.com/rust-fuzz/libfuzzer-sys.git" [dependencies.cretonne-wasm] path = "../lib/wasm" +[dependencies.target-lexicon] +version = "0.0.0" + # Prevent this from interfering with workspaces [workspace] members = ["."] diff --git a/cranelift/fuzz/fuzz_translate_module.rs b/cranelift/fuzz/fuzz_translate_module.rs index 45180c14af..d398483961 100644 --- a/cranelift/fuzz/fuzz_translate_module.rs +++ b/cranelift/fuzz/fuzz_translate_module.rs @@ -3,13 +3,16 @@ extern crate libfuzzer_sys; extern crate binaryen; extern crate cretonne_wasm; +#[macro_use] +extern crate target_lexicon; use cretonne_wasm::{translate_module, DummyEnvironment}; +use std::str::FromStr; fuzz_target!(|data: &[u8]| { let binaryen_module = binaryen::tools::translate_to_fuzz_mvp(data); let wasm = binaryen_module.write(); - let mut dummy_environ = DummyEnvironment::default(); + let mut dummy_environ = DummyEnvironment::with_triple(triple!("x86_64")); translate_module(&wasm, &mut dummy_environ).unwrap(); }); diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index 37f70df364..7eea32262e 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -9,7 +9,8 @@ use cretonne_codegen::{binemit, ir}; use cretonne_reader::parse_test; use std::path::Path; use std::path::PathBuf; -use utils::{parse_sets_and_isa, read_to_string}; +use target_lexicon::Architecture; +use utils::{parse_sets_and_triple, read_to_string}; struct PrintRelocs { flag_print: bool, @@ -64,7 +65,7 @@ pub fn run( flag_set: &[String], flag_isa: &str, ) -> Result<(), String> { - let parsed = parse_sets_and_isa(flag_set, flag_isa)?; + let parsed = parse_sets_and_triple(flag_set, flag_isa)?; for filename in files { let path = Path::new(&filename); @@ -136,23 +137,28 @@ fn handle_module( } fn get_disassembler(isa: &TargetIsa) -> Result { - let cs = match isa.name() { - "riscv" => return Err(String::from("No disassembler for RiscV")), - "x86" => { - if isa.flags().is_64bit() { - Capstone::new() - .x86() - .mode(arch::x86::ArchMode::Mode64) - .build() - } else { - Capstone::new() - .x86() - .mode(arch::x86::ArchMode::Mode32) - .build() - } + let cs = match isa.triple().architecture { + Architecture::Riscv32 | Architecture::Riscv64 => { + return Err(String::from("No disassembler for RiscV")) } - "arm32" => Capstone::new().arm().mode(arch::arm::ArchMode::Arm).build(), - "arm64" => Capstone::new() + Architecture::I386 | Architecture::I586 | Architecture::I686 => Capstone::new() + .x86() + .mode(arch::x86::ArchMode::Mode32) + .build(), + Architecture::X86_64 => Capstone::new() + .x86() + .mode(arch::x86::ArchMode::Mode64) + .build(), + Architecture::Arm + | Architecture::Armv4t + | Architecture::Armv5te + | Architecture::Armv7 + | Architecture::Armv7s => Capstone::new().arm().mode(arch::arm::ArchMode::Arm).build(), + Architecture::Thumbv6m | Architecture::Thumbv7em | Architecture::Thumbv7m => Capstone::new( + ).arm() + .mode(arch::arm::ArchMode::Thumb) + .build(), + Architecture::Aarch64 => Capstone::new() .arm64() .mode(arch::arm64::ArchMode::Arm) .build(), diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index d1805d6dc8..370e6d5c65 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -27,6 +27,7 @@ cfg_if! { mod wasm; } } +extern crate target_lexicon; use cretonne_codegen::{timing, VERSION}; use docopt::Docopt; @@ -47,8 +48,8 @@ Usage: cton-util cat ... cton-util filecheck [-v] cton-util print-cfg ... - cton-util compile [-vpT] [--set ]... [--isa ] ... - cton-util wasm [-ctvpTs] [--set ]... [--isa ] ... + cton-util compile [-vpT] [--set ]... [--target ] ... + cton-util wasm [-ctvpTs] [--set ]... [--target ] ... cton-util --help | --version Options: @@ -64,7 +65,8 @@ Options: -p, --print print the resulting Cretonne IR -h, --help print this help message --set= configure Cretonne settings - --isa= specify the Cretonne ISA + --target= + specify the Cretonne target --version print the Cretonne version "; @@ -83,7 +85,7 @@ struct Args { flag_print: bool, flag_verbose: bool, flag_set: Vec, - flag_isa: String, + flag_target: String, flag_time_passes: bool, flag_print_size: bool, } @@ -116,7 +118,7 @@ fn cton_util() -> CommandResult { args.arg_file, args.flag_print, &args.flag_set, - &args.flag_isa, + &args.flag_target, ) } else if args.cmd_wasm { #[cfg(feature = "wasm")] @@ -127,7 +129,7 @@ fn cton_util() -> CommandResult { args.flag_check_translation, args.flag_print, &args.flag_set, - &args.flag_isa, + &args.flag_target, args.flag_print_size, ); diff --git a/cranelift/src/utils.rs b/cranelift/src/utils.rs index ee879d0843..138d4f5dcc 100644 --- a/cranelift/src/utils.rs +++ b/cranelift/src/utils.rs @@ -7,6 +7,8 @@ use cretonne_reader::{parse_options, Location}; use std::fs::File; use std::io::{self, Read}; use std::path::Path; +use std::str::FromStr; +use target_lexicon::Triple; /// Read an entire file into a string. pub fn read_to_string>(path: P) -> io::Result { @@ -40,8 +42,11 @@ impl OwnedFlagsOrIsa { } } -/// Parse "set" and "isa" commands. -pub fn parse_sets_and_isa(flag_set: &[String], flag_isa: &str) -> Result { +/// Parse "set" and "triple" commands. +pub fn parse_sets_and_triple( + flag_set: &[String], + flag_triple: &str, +) -> Result { let mut flag_builder = settings::builder(); parse_options( flag_set.iter().map(|x| x.as_str()), @@ -49,12 +54,21 @@ pub fn parse_sets_and_isa(flag_set: &[String], flag_isa: &str) -> Result format!("unknown ISA '{}'", isa_name), - isa::LookupError::Unsupported => format!("support for ISA '{}' not enabled", isa_name), + let mut words = flag_triple.trim().split_whitespace(); + // Look for `target foo`. + if let Some(triple_name) = words.next() { + let triple = match Triple::from_str(triple_name) { + Ok(triple) => triple, + Err(parse_error) => return Err(format!("{}", parse_error)), + }; + let mut isa_builder = isa::lookup(triple).map_err(|err| match err { + isa::LookupError::SupportDisabled => { + format!("support for triple '{}' is disabled", triple_name) + } + isa::LookupError::Unsupported => format!( + "support for triple '{}' is not implemented yet", + triple_name + ), })?; // Apply the ISA-specific settings to `isa_builder`. parse_options(words, &mut isa_builder, &Location { line_number: 0 }) diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 4c1907b6ce..13356a4282 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -12,7 +12,7 @@ use std::error::Error; use std::path::Path; use std::path::PathBuf; use term; -use utils::{parse_sets_and_isa, read_to_end}; +use utils::{parse_sets_and_triple, read_to_end}; use wabt::wat2wasm; macro_rules! vprintln { @@ -38,10 +38,10 @@ pub fn run( flag_check_translation: bool, flag_print: bool, flag_set: &[String], - flag_isa: &str, + flag_triple: &str, flag_print_size: bool, ) -> Result<(), String> { - let parsed = parse_sets_and_isa(flag_set, flag_isa)?; + let parsed = parse_sets_and_triple(flag_set, flag_triple)?; for filename in files { let path = Path::new(&filename); @@ -79,9 +79,7 @@ fn handle_module( vprint!(flag_verbose, "Translating... "); terminal.reset().unwrap(); - let mut data = read_to_end(path.clone()).map_err(|err| { - String::from(err.description()) - })?; + let mut data = read_to_end(path.clone()).map_err(|err| String::from(err.description()))?; if !data.starts_with(&[b'\0', b'a', b's', b'm']) { data = match wat2wasm(&data) { @@ -90,10 +88,9 @@ fn handle_module( }; } - let mut dummy_environ = DummyEnvironment::with_flags(fisa.flags.clone()); - translate_module(&data, &mut dummy_environ).map_err( - |e| e.to_string(), - )?; + let mut dummy_environ = + DummyEnvironment::with_triple_flags(fisa.isa.unwrap().triple().clone(), fisa.flags.clone()); + translate_module(&data, &mut dummy_environ).map_err(|e| e.to_string())?; terminal.fg(term::color::GREEN).unwrap(); vprintln!(flag_verbose, "ok"); @@ -142,24 +139,22 @@ fn handle_module( let mut context = Context::new(); context.func = func.clone(); if flag_check_translation { - context.verify(fisa).map_err(|err| { - pretty_verifier_error(&context.func, fisa.isa, &err) - })?; + context + .verify(fisa) + .map_err(|err| pretty_verifier_error(&context.func, fisa.isa, &err))?; } else if let Some(isa) = fisa.isa { - let compiled_size = context.compile(isa).map_err(|err| { - pretty_error(&context.func, fisa.isa, err) - })?; + let compiled_size = context + .compile(isa) + .map_err(|err| pretty_error(&context.func, fisa.isa, err))?; if flag_print_size { println!( "Function #{} code size: {} bytes", - func_index, - compiled_size + func_index, compiled_size ); total_module_code_size += compiled_size; println!( "Function #{} bytecode size: {} bytes", - func_index, - dummy_environ.func_bytecode_sizes[def_index] + func_index, dummy_environ.func_bytecode_sizes[def_index] ); } } else { diff --git a/lib/codegen/Cargo.toml b/lib/codegen/Cargo.toml index 26bf497347..0e7b5f32ea 100644 --- a/lib/codegen/Cargo.toml +++ b/lib/codegen/Cargo.toml @@ -15,6 +15,7 @@ cretonne-entity = { path = "../entity", version = "0.8.0", default-features = fa failure = { version = "0.1.1", default-features = false, features = ["derive"] } failure_derive = { version = "0.1.1", default-features = false } hashmap_core = { version = "0.1.4", optional = true } +target-lexicon = { version = "0.0.0", default-features = false } # It is a goal of the cretonne-codegen crate to have minimal external dependencies. # Please don't add any unless they are essential to the task of creating binary # machine code. Integration tests that need external dependencies can be diff --git a/lib/codegen/meta/base/settings.py b/lib/codegen/meta/base/settings.py index 5753c35273..8e88a45abc 100644 --- a/lib/codegen/meta/base/settings.py +++ b/lib/codegen/meta/base/settings.py @@ -27,8 +27,6 @@ enable_verifier = BoolSetting( """, default=True) -is_64bit = BoolSetting("Enable 64-bit code generation") - call_conv = EnumSetting( """ Default calling convention: @@ -89,8 +87,6 @@ avoid_div_traps = BoolSetting( this setting has no effect - explicit checks are always inserted. """) -is_compressed = BoolSetting("Enable compressed instructions") - enable_float = BoolSetting( """ Enable the use of floating-point instructions diff --git a/lib/codegen/src/isa/arm32/mod.rs b/lib/codegen/src/isa/arm32/mod.rs index 560c71248c..bb0214b3ec 100644 --- a/lib/codegen/src/isa/arm32/mod.rs +++ b/lib/codegen/src/isa/arm32/mod.rs @@ -15,32 +15,43 @@ use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use regalloc; use std::boxed::Box; use std::fmt; +use target_lexicon::{Architecture, Triple}; #[allow(dead_code)] struct Isa { + triple: Triple, shared_flags: shared_settings::Flags, isa_flags: settings::Flags, cpumode: &'static [shared_enc_tables::Level1Entry], } /// Get an ISA builder for creating ARM32 targets. -pub fn isa_builder() -> IsaBuilder { +pub fn isa_builder(triple: Triple) -> IsaBuilder { IsaBuilder { + triple, setup: settings::builder(), constructor: isa_constructor, } } fn isa_constructor( + triple: Triple, shared_flags: shared_settings::Flags, builder: shared_settings::Builder, ) -> Box { - let level1 = if shared_flags.is_compressed() { - &enc_tables::LEVEL1_T32[..] - } else { - &enc_tables::LEVEL1_A32[..] + let level1 = match triple.architecture { + Architecture::Thumbv6m | Architecture::Thumbv7em | Architecture::Thumbv7m => { + &enc_tables::LEVEL1_T32[..] + } + Architecture::Arm + | Architecture::Armv4t + | Architecture::Armv5te + | Architecture::Armv7 + | Architecture::Armv7s => &enc_tables::LEVEL1_A32[..], + _ => panic!(), }; Box::new(Isa { + triple, isa_flags: settings::Flags::new(&shared_flags, builder), shared_flags, cpumode: level1, @@ -52,6 +63,10 @@ impl TargetIsa for Isa { "arm32" } + fn triple(&self) -> &Triple { + &self.triple + } + fn flags(&self) -> &shared_settings::Flags { &self.shared_flags } diff --git a/lib/codegen/src/isa/arm64/mod.rs b/lib/codegen/src/isa/arm64/mod.rs index 240e92883d..50a43b13fc 100644 --- a/lib/codegen/src/isa/arm64/mod.rs +++ b/lib/codegen/src/isa/arm64/mod.rs @@ -15,26 +15,31 @@ use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use regalloc; use std::boxed::Box; use std::fmt; +use target_lexicon::Triple; #[allow(dead_code)] struct Isa { + triple: Triple, shared_flags: shared_settings::Flags, isa_flags: settings::Flags, } /// Get an ISA builder for creating ARM64 targets. -pub fn isa_builder() -> IsaBuilder { +pub fn isa_builder(triple: Triple) -> IsaBuilder { IsaBuilder { + triple, setup: settings::builder(), constructor: isa_constructor, } } fn isa_constructor( + triple: Triple, shared_flags: shared_settings::Flags, builder: shared_settings::Builder, ) -> Box { Box::new(Isa { + triple, isa_flags: settings::Flags::new(&shared_flags, builder), shared_flags, }) @@ -45,6 +50,10 @@ impl TargetIsa for Isa { "arm64" } + fn triple(&self) -> &Triple { + &self.triple + } + fn flags(&self) -> &shared_settings::Flags { &self.shared_flags } diff --git a/lib/codegen/src/isa/mod.rs b/lib/codegen/src/isa/mod.rs index d9f4851e68..fc7c166bac 100644 --- a/lib/codegen/src/isa/mod.rs +++ b/lib/codegen/src/isa/mod.rs @@ -20,13 +20,18 @@ //! appropriate for the requested ISA: //! //! ``` +//! # extern crate cretonne_codegen; +//! # #[macro_use] extern crate target_lexicon; +//! # fn main() { //! use cretonne_codegen::settings::{self, Configurable}; //! use cretonne_codegen::isa; +//! use std::str::FromStr; +//! use target_lexicon::Triple; //! //! let shared_builder = settings::builder(); //! let shared_flags = settings::Flags::new(shared_builder); //! -//! match isa::lookup("riscv") { +//! match isa::lookup(triple!("riscv32")) { //! Err(_) => { //! // The RISC-V target ISA is not available. //! } @@ -35,6 +40,7 @@ //! let isa = isa_builder.finish(shared_flags); //! } //! } +//! # } //! ``` //! //! The configured target ISA trait object is a `Box` which can be used for multiple @@ -55,6 +61,7 @@ use settings; use settings::CallConv; use std::boxed::Box; use std::fmt; +use target_lexicon::{Architecture, Triple}; use timing; #[cfg(build_riscv)] @@ -80,51 +87,61 @@ mod stack; macro_rules! isa_builder { ($module:ident, $name:ident) => {{ #[cfg($name)] - fn $name() -> Result { - Ok($module::isa_builder()) + fn $name(triple: Triple) -> Result { + Ok($module::isa_builder(triple)) }; #[cfg(not($name))] - fn $name() -> Result { + fn $name(_triple: Triple) -> Result { Err(LookupError::Unsupported) } - $name() + $name }}; } /// Look for a supported ISA with the given `name`. /// Return a builder that can create a corresponding `TargetIsa`. -pub fn lookup(name: &str) -> Result { - match name { - "riscv" => isa_builder!(riscv, build_riscv), - "x86" => isa_builder!(x86, build_x86), - "arm32" => isa_builder!(arm32, build_arm32), - "arm64" => isa_builder!(arm64, build_arm64), - _ => Err(LookupError::Unknown), +pub fn lookup(triple: Triple) -> Result { + match triple.architecture { + Architecture::Riscv32 | Architecture::Riscv64 => isa_builder!(riscv, build_riscv)(triple), + Architecture::I386 | Architecture::I586 | Architecture::I686 | Architecture::X86_64 => { + isa_builder!(x86, build_x86)(triple) + } + Architecture::Thumbv6m + | Architecture::Thumbv7em + | Architecture::Thumbv7m + | Architecture::Arm + | Architecture::Armv4t + | Architecture::Armv5te + | Architecture::Armv7 + | Architecture::Armv7s => isa_builder!(arm32, build_arm32)(triple), + Architecture::Aarch64 => isa_builder!(arm64, build_arm64)(triple), + _ => Err(LookupError::Unsupported), } } /// Describes reason for target lookup failure #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum LookupError { - /// Unknown Target - Unknown, + /// Support for this target was disabled in the current build. + SupportDisabled, - /// Target known but not built and thus not supported + /// Support for this target has not yet been implemented. Unsupported, } /// Builder for a `TargetIsa`. /// Modify the ISA-specific settings before creating the `TargetIsa` trait object with `finish`. pub struct Builder { + triple: Triple, setup: settings::Builder, - constructor: fn(settings::Flags, settings::Builder) -> Box, + constructor: fn(Triple, settings::Flags, settings::Builder) -> Box, } impl Builder { /// Combine the ISA-specific settings with the provided ISA-independent settings and allocate a /// fully configured `TargetIsa` trait object. pub fn finish(self, shared_flags: settings::Flags) -> Box { - (self.constructor)(shared_flags, self.setup) + (self.constructor)(self.triple, shared_flags, self.setup) } } @@ -151,9 +168,17 @@ pub trait TargetIsa: fmt::Display { /// Get the name of this ISA. fn name(&self) -> &'static str; + /// Get the target triple that was used to make this trait object. + fn triple(&self) -> &Triple; + /// Get the ISA-independent flags that were used to make this trait object. fn flags(&self) -> &settings::Flags; + /// Get the pointer type of this ISA. + fn pointer_type(&self) -> ir::Type { + ir::Type::int(u16::from(self.triple().pointer_width().unwrap().bits())).unwrap() + } + /// Does the CPU implement scalar comparisons using a CPU flags register? fn uses_cpu_flags(&self) -> bool { false @@ -252,7 +277,7 @@ pub trait TargetIsa: fmt::Display { use ir::stackslot::{StackOffset, StackSize}; use stack_layout::layout_stack; - let word_size = if self.flags().is_64bit() { 8 } else { 4 }; + let word_size = StackSize::from(self.triple().pointer_width().unwrap().bytes()); // Account for the SpiderMonkey standard prologue pushes. if func.signature.call_conv == CallConv::Baldrdash { diff --git a/lib/codegen/src/isa/riscv/abi.rs b/lib/codegen/src/isa/riscv/abi.rs index f45dd31426..ed7230d2cb 100644 --- a/lib/codegen/src/isa/riscv/abi.rs +++ b/lib/codegen/src/isa/riscv/abi.rs @@ -11,12 +11,12 @@ use abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion}; use ir::{self, AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, Type}; use isa::RegClass; use regalloc::RegisterSet; -use settings as shared_settings; use std::i32; +use target_lexicon::Triple; struct Args { - pointer_bits: u16, - pointer_bytes: u32, + pointer_bits: u8, + pointer_bytes: u8, pointer_type: Type, regs: u32, reg_limit: u32, @@ -24,11 +24,11 @@ struct Args { } impl Args { - fn new(bits: u16, enable_e: bool) -> Self { + fn new(bits: u8, enable_e: bool) -> Self { Self { pointer_bits: bits, - pointer_bytes: u32::from(bits) / 8, - pointer_type: Type::int(bits).unwrap(), + pointer_bytes: bits / 8, + pointer_type: Type::int(u16::from(bits)).unwrap(), regs: 0, reg_limit: if enable_e { 6 } else { 8 }, offset: 0, @@ -51,15 +51,15 @@ impl ArgAssigner for Args { } // Large integers and booleans are broken down to fit in a register. - if !ty.is_float() && ty.bits() > self.pointer_bits { + if !ty.is_float() && ty.bits() > u16::from(self.pointer_bits) { // Align registers and stack to a multiple of two pointers. self.regs = align(self.regs, 2); - self.offset = align(self.offset, 2 * self.pointer_bytes); + self.offset = align(self.offset, 2 * u32::from(self.pointer_bytes)); return ValueConversion::IntSplit.into(); } // Small integers are extended to the size of a pointer register. - if ty.is_int() && ty.bits() < self.pointer_bits { + if ty.is_int() && ty.bits() < u16::from(self.pointer_bits) { match arg.extension { ArgumentExtension::None => {} ArgumentExtension::Uext => return ValueConversion::Uext(self.pointer_type).into(), @@ -79,7 +79,7 @@ impl ArgAssigner for Args { } else { // Assign a stack location. let loc = ArgumentLoc::Stack(self.offset as i32); - self.offset += self.pointer_bytes; + self.offset += u32::from(self.pointer_bytes); debug_assert!(self.offset <= i32::MAX as u32); loc.into() } @@ -89,11 +89,11 @@ impl ArgAssigner for Args { /// Legalize `sig` for RISC-V. pub fn legalize_signature( sig: &mut ir::Signature, - flags: &shared_settings::Flags, + triple: &Triple, isa_flags: &settings::Flags, current: bool, ) { - let bits = if flags.is_64bit() { 64 } else { 32 }; + let bits = triple.pointer_width().unwrap().bits(); let mut args = Args::new(bits, isa_flags.enable_e()); legalize_args(&mut sig.params, &mut args); @@ -102,7 +102,7 @@ pub fn legalize_signature( legalize_args(&mut sig.returns, &mut rets); if current { - let ptr = Type::int(bits).unwrap(); + let ptr = Type::int(u16::from(bits)).unwrap(); // Add the link register as an argument and return value. // diff --git a/lib/codegen/src/isa/riscv/mod.rs b/lib/codegen/src/isa/riscv/mod.rs index f704a5e7ff..aff23390e5 100644 --- a/lib/codegen/src/isa/riscv/mod.rs +++ b/lib/codegen/src/isa/riscv/mod.rs @@ -15,32 +15,37 @@ use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use regalloc; use std::boxed::Box; use std::fmt; +use target_lexicon::{PointerWidth, Triple}; #[allow(dead_code)] struct Isa { + triple: Triple, shared_flags: shared_settings::Flags, isa_flags: settings::Flags, cpumode: &'static [shared_enc_tables::Level1Entry], } /// Get an ISA builder for creating RISC-V targets. -pub fn isa_builder() -> IsaBuilder { +pub fn isa_builder(triple: Triple) -> IsaBuilder { IsaBuilder { + triple, setup: settings::builder(), constructor: isa_constructor, } } fn isa_constructor( + triple: Triple, shared_flags: shared_settings::Flags, builder: shared_settings::Builder, ) -> Box { - let level1 = if shared_flags.is_64bit() { - &enc_tables::LEVEL1_RV64[..] - } else { - &enc_tables::LEVEL1_RV32[..] + let level1 = match triple.pointer_width().unwrap() { + PointerWidth::U16 => panic!("16-bit RISC-V unrecognized"), + PointerWidth::U32 => &enc_tables::LEVEL1_RV32[..], + PointerWidth::U64 => &enc_tables::LEVEL1_RV64[..], }; Box::new(Isa { + triple, isa_flags: settings::Flags::new(&shared_flags, builder), shared_flags, cpumode: level1, @@ -52,6 +57,10 @@ impl TargetIsa for Isa { "riscv" } + fn triple(&self) -> &Triple { + &self.triple + } + fn flags(&self) -> &shared_settings::Flags { &self.shared_flags } @@ -85,7 +94,7 @@ impl TargetIsa for Isa { } fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) { - abi::legalize_signature(sig, &self.shared_flags, &self.isa_flags, current) + abi::legalize_signature(sig, &self.triple, &self.isa_flags, current) } fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass { @@ -117,7 +126,9 @@ mod tests { use ir::{Function, InstructionData, Opcode}; use isa; use settings::{self, Configurable}; + use std::str::FromStr; use std::string::{String, ToString}; + use target_lexicon; fn encstr(isa: &isa::TargetIsa, enc: Result) -> String { match enc { @@ -128,10 +139,11 @@ mod tests { #[test] fn test_64bitenc() { - let mut shared_builder = settings::builder(); - shared_builder.enable("is_64bit").unwrap(); + let shared_builder = settings::builder(); let shared_flags = settings::Flags::new(shared_builder); - let isa = isa::lookup("riscv").unwrap().finish(shared_flags); + let isa = isa::lookup(triple!("riscv64")) + .unwrap() + .finish(shared_flags); let mut func = Function::new(); let ebb = func.dfg.make_ebb(); @@ -178,10 +190,11 @@ mod tests { // Same as above, but for RV32. #[test] fn test_32bitenc() { - let mut shared_builder = settings::builder(); - shared_builder.set("is_64bit", "false").unwrap(); + let shared_builder = settings::builder(); let shared_flags = settings::Flags::new(shared_builder); - let isa = isa::lookup("riscv").unwrap().finish(shared_flags); + let isa = isa::lookup(triple!("riscv32")) + .unwrap() + .finish(shared_flags); let mut func = Function::new(); let ebb = func.dfg.make_ebb(); @@ -232,13 +245,12 @@ mod tests { #[test] fn test_rv32m() { - let mut shared_builder = settings::builder(); - shared_builder.set("is_64bit", "false").unwrap(); + let shared_builder = settings::builder(); let shared_flags = settings::Flags::new(shared_builder); // Set the supports_m stting which in turn enables the use_m predicate that unlocks // encodings for imul. - let mut isa_builder = isa::lookup("riscv").unwrap(); + let mut isa_builder = isa::lookup(triple!("riscv32")).unwrap(); isa_builder.enable("supports_m").unwrap(); let isa = isa_builder.finish(shared_flags); diff --git a/lib/codegen/src/isa/x86/abi.rs b/lib/codegen/src/isa/x86/abi.rs index e7511482ca..89c5c30549 100644 --- a/lib/codegen/src/isa/x86/abi.rs +++ b/lib/codegen/src/isa/x86/abi.rs @@ -11,10 +11,10 @@ use ir::{get_probestack_funcref, AbiParam, ArgumentExtension, ArgumentLoc, Argum use isa::{RegClass, RegUnit, TargetIsa}; use regalloc::RegisterSet; use result; -use settings as shared_settings; use settings::CallConv; use stack_layout::layout_stack; use std::i32; +use target_lexicon::{PointerWidth, Triple}; /// Argument registers for x86-64 static ARG_GPRS: [RU; 6] = [RU::rdi, RU::rsi, RU::rdx, RU::rcx, RU::r8, RU::r9]; @@ -29,8 +29,8 @@ static ARG_GPRS_WIN_FASTCALL_X64: [RU; 4] = [RU::rcx, RU::rdx, RU::r8, RU::r9]; static RET_GPRS_WIN_FASTCALL_X64: [RU; 1] = [RU::rax]; struct Args { - pointer_bytes: u32, - pointer_bits: u16, + pointer_bytes: u8, + pointer_bits: u8, pointer_type: ir::Type, gpr: &'static [RU], gpr_used: usize, @@ -41,7 +41,7 @@ struct Args { } impl Args { - fn new(bits: u16, gpr: &'static [RU], fpr_limit: usize, call_conv: CallConv) -> Self { + fn new(bits: u8, gpr: &'static [RU], fpr_limit: usize, call_conv: CallConv) -> Self { let offset = if let CallConv::WindowsFastcall = call_conv { // [1] "The caller is responsible for allocating space for parameters to the callee, // and must always allocate sufficient space to store four register parameters" @@ -51,9 +51,9 @@ impl Args { }; Self { - pointer_bytes: u32::from(bits) / 8, + pointer_bytes: bits / 8, pointer_bits: bits, - pointer_type: ir::Type::int(bits).unwrap(), + pointer_type: ir::Type::int(u16::from(bits)).unwrap(), gpr, gpr_used: 0, fpr_limit, @@ -75,12 +75,12 @@ impl ArgAssigner for Args { } // Large integers and booleans are broken down to fit in a register. - if !ty.is_float() && ty.bits() > self.pointer_bits { + if !ty.is_float() && ty.bits() > u16::from(self.pointer_bits) { return ValueConversion::IntSplit.into(); } // Small integers are extended to the size of a pointer register. - if ty.is_int() && ty.bits() < self.pointer_bits { + if ty.is_int() && ty.bits() < u16::from(self.pointer_bits) { match arg.extension { ArgumentExtension::None => {} ArgumentExtension::Uext => return ValueConversion::Uext(self.pointer_type).into(), @@ -122,27 +122,31 @@ impl ArgAssigner for Args { // Assign a stack location. let loc = ArgumentLoc::Stack(self.offset as i32); - self.offset += self.pointer_bytes; + self.offset += u32::from(self.pointer_bytes); debug_assert!(self.offset <= i32::MAX as u32); loc.into() } } /// Legalize `sig`. -pub fn legalize_signature(sig: &mut ir::Signature, flags: &shared_settings::Flags, _current: bool) { +pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bool) { let bits; let mut args; - if flags.is_64bit() { - bits = 64; - args = if sig.call_conv == CallConv::WindowsFastcall { - Args::new(bits, &ARG_GPRS_WIN_FASTCALL_X64[..], 4, sig.call_conv) - } else { - Args::new(bits, &ARG_GPRS[..], 8, sig.call_conv) - }; - } else { - bits = 32; - args = Args::new(bits, &[], 0, sig.call_conv); + match triple.pointer_width().unwrap() { + PointerWidth::U16 => panic!(), + PointerWidth::U32 => { + bits = 32; + args = Args::new(bits, &[], 0, sig.call_conv); + } + PointerWidth::U64 => { + bits = 64; + args = if sig.call_conv == CallConv::WindowsFastcall { + Args::new(bits, &ARG_GPRS_WIN_FASTCALL_X64[..], 4, sig.call_conv) + } else { + Args::new(bits, &ARG_GPRS[..], 8, sig.call_conv) + }; + } } legalize_args(&mut sig.params, &mut args); @@ -167,13 +171,13 @@ pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass { } /// Get the set of allocatable registers for `func`. -pub fn allocatable_registers(_func: &ir::Function, flags: &shared_settings::Flags) -> RegisterSet { +pub fn allocatable_registers(_func: &ir::Function, triple: &Triple) -> RegisterSet { let mut regs = RegisterSet::new(); regs.take(GPR, RU::rsp as RegUnit); regs.take(GPR, RU::rbp as RegUnit); // 32-bit arch only has 8 registers. - if !flags.is_64bit() { + if triple.pointer_width().unwrap() != PointerWidth::U64 { for i in 8..16 { regs.take(GPR, GPR.unit(i)); regs.take(FPR, FPR.unit(i)); @@ -184,34 +188,36 @@ pub fn allocatable_registers(_func: &ir::Function, flags: &shared_settings::Flag } /// Get the set of callee-saved registers. -fn callee_saved_gprs(flags: &shared_settings::Flags) -> &'static [RU] { - if flags.is_64bit() { - if flags.call_conv() == CallConv::WindowsFastcall { - // "registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15 are considered nonvolatile - // and must be saved and restored by a function that uses them." - // as per https://msdn.microsoft.com/en-us/library/6t169e9c.aspx - // RSP & RSB are not listed below, since they are restored automatically during - // a function call. If that wasn't the case, function calls (RET) would not work. - &[ - RU::rbx, - RU::rdi, - RU::rsi, - RU::r12, - RU::r13, - RU::r14, - RU::r15, - ] - } else { - &[RU::rbx, RU::r12, RU::r13, RU::r14, RU::r15] +fn callee_saved_gprs(isa: &TargetIsa) -> &'static [RU] { + match isa.triple().pointer_width().unwrap() { + PointerWidth::U16 => panic!(), + PointerWidth::U32 => &[RU::rbx, RU::rsi, RU::rdi], + PointerWidth::U64 => { + if isa.flags().call_conv() == CallConv::WindowsFastcall { + // "registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15 are considered nonvolatile + // and must be saved and restored by a function that uses them." + // as per https://msdn.microsoft.com/en-us/library/6t169e9c.aspx + // RSP & RSB are not listed below, since they are restored automatically during + // a function call. If that wasn't the case, function calls (RET) would not work. + &[ + RU::rbx, + RU::rdi, + RU::rsi, + RU::r12, + RU::r13, + RU::r14, + RU::r15, + ] + } else { + &[RU::rbx, RU::r12, RU::r13, RU::r14, RU::r15] + } } - } else { - &[RU::rbx, RU::rsi, RU::rdi] } } -fn callee_saved_gprs_used(flags: &shared_settings::Flags, func: &ir::Function) -> RegisterSet { +fn callee_saved_gprs_used(isa: &TargetIsa, func: &ir::Function) -> RegisterSet { let mut all_callee_saved = RegisterSet::empty(); - for reg in callee_saved_gprs(flags) { + for reg in callee_saved_gprs(isa) { all_callee_saved.free(GPR, *reg as RegUnit); } @@ -271,7 +277,7 @@ pub fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> // Baldrdash on 32-bit x86 always aligns its stack pointer to 16 bytes. let stack_align = 16; - let word_size = if isa.flags().is_64bit() { 8 } else { 4 }; + let word_size = StackSize::from(isa.triple().pointer_width().unwrap().bytes()); let bytes = StackSize::from(isa.flags().baldrdash_prologue_words()) * word_size; let mut ss = ir::StackSlotData::new(ir::StackSlotKind::IncomingArg, bytes); @@ -285,7 +291,7 @@ pub fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> /// Implementation of the fastcall-based Win64 calling convention described at [1] /// [1] https://msdn.microsoft.com/en-us/library/ms235286.aspx pub fn fastcall_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { - if !isa.flags().is_64bit() { + if isa.triple().pointer_width().unwrap() != PointerWidth::U64 { panic!("TODO: windows-fastcall: x86-32 not implemented yet"); } @@ -293,14 +299,10 @@ pub fn fastcall_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> r // which are aligned to 16 bytes in order to aid performance" let stack_align = 16; - let word_size = if isa.flags().is_64bit() { 8 } else { 4 }; - let reg_type = if isa.flags().is_64bit() { - ir::types::I64 - } else { - ir::types::I32 - }; + let word_size = isa.triple().pointer_width().unwrap().bytes() as usize; + let reg_type = isa.pointer_type(); - let csrs = callee_saved_gprs_used(isa.flags(), func); + let csrs = callee_saved_gprs_used(isa, func); // [1] "Space is allocated on the call stack as a shadow store for callees to save" // This shadow store contains the parameters which are passed through registers (ARG_GPRS) @@ -364,14 +366,11 @@ pub fn system_v_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> r // The original 32-bit x86 ELF ABI had a 4-byte aligned stack pointer, but // newer versions use a 16-byte aligned stack pointer. let stack_align = 16; - let word_size = if isa.flags().is_64bit() { 8 } else { 4 }; - let reg_type = if isa.flags().is_64bit() { - ir::types::I64 - } else { - ir::types::I32 - }; + let pointer_width = isa.triple().pointer_width().unwrap(); + let word_size = pointer_width.bytes() as usize; + let reg_type = ir::Type::int(u16::from(pointer_width.bits())).unwrap(); - let csrs = callee_saved_gprs_used(isa.flags(), func); + let csrs = callee_saved_gprs_used(isa, func); // The reserved stack area is composed of: // return address + frame pointer + all callee-saved registers @@ -463,7 +462,8 @@ fn insert_common_prologue( let callee = get_probestack_funcref(pos.func, reg_type, rax, isa); // Make the call. - let call = if !isa.flags().is_pic() && isa.flags().is_64bit() + let call = if !isa.flags().is_pic() + && isa.triple().pointer_width().unwrap() == PointerWidth::U64 && !pos.func.dfg.ext_funcs[callee].colocated { // 64-bit non-PIC non-colocated calls need to be legalized to call_indirect. diff --git a/lib/codegen/src/isa/x86/mod.rs b/lib/codegen/src/isa/x86/mod.rs index e77b7d5c78..6e2c035d38 100644 --- a/lib/codegen/src/isa/x86/mod.rs +++ b/lib/codegen/src/isa/x86/mod.rs @@ -16,33 +16,38 @@ use regalloc; use result; use std::boxed::Box; use std::fmt; +use target_lexicon::{PointerWidth, Triple}; use timing; #[allow(dead_code)] struct Isa { + triple: Triple, shared_flags: shared_settings::Flags, isa_flags: settings::Flags, cpumode: &'static [shared_enc_tables::Level1Entry], } /// Get an ISA builder for creating x86 targets. -pub fn isa_builder() -> IsaBuilder { +pub fn isa_builder(triple: Triple) -> IsaBuilder { IsaBuilder { + triple, setup: settings::builder(), constructor: isa_constructor, } } fn isa_constructor( + triple: Triple, shared_flags: shared_settings::Flags, builder: shared_settings::Builder, ) -> Box { - let level1 = if shared_flags.is_64bit() { - &enc_tables::LEVEL1_I64[..] - } else { - &enc_tables::LEVEL1_I32[..] + let level1 = match triple.pointer_width().unwrap() { + PointerWidth::U16 => unimplemented!("x86-16"), + PointerWidth::U32 => &enc_tables::LEVEL1_I32[..], + PointerWidth::U64 => &enc_tables::LEVEL1_I64[..], }; Box::new(Isa { + triple, isa_flags: settings::Flags::new(&shared_flags, builder), shared_flags, cpumode: level1, @@ -54,6 +59,10 @@ impl TargetIsa for Isa { "x86" } + fn triple(&self) -> &Triple { + &self.triple + } + fn flags(&self) -> &shared_settings::Flags { &self.shared_flags } @@ -95,7 +104,7 @@ impl TargetIsa for Isa { } fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) { - abi::legalize_signature(sig, &self.shared_flags, current) + abi::legalize_signature(sig, &self.triple, current) } fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass { @@ -103,7 +112,7 @@ impl TargetIsa for Isa { } fn allocatable_registers(&self, func: &ir::Function) -> regalloc::RegisterSet { - abi::allocatable_registers(func, &self.shared_flags) + abi::allocatable_registers(func, &self.triple) } fn emit_inst( diff --git a/lib/codegen/src/legalizer/call.rs b/lib/codegen/src/legalizer/call.rs index d2e0ca542e..365ba3988d 100644 --- a/lib/codegen/src/legalizer/call.rs +++ b/lib/codegen/src/legalizer/call.rs @@ -28,11 +28,7 @@ pub fn expand_call( _ => panic!("Wanted call: {}", func.dfg.display_inst(inst, None)), }; - let ptr_ty = if isa.flags().is_64bit() { - ir::types::I64 - } else { - ir::types::I32 - }; + let ptr_ty = isa.pointer_type(); let sig = func.dfg.ext_funcs[func_ref].signature; diff --git a/lib/codegen/src/legalizer/mod.rs b/lib/codegen/src/legalizer/mod.rs index 95a6666b2d..b3d6d6c0ce 100644 --- a/lib/codegen/src/legalizer/mod.rs +++ b/lib/codegen/src/legalizer/mod.rs @@ -283,11 +283,7 @@ pub fn expand_stack_check( ir::InstructionData::UnaryGlobalVar { global_var, .. } => global_var, _ => panic!("Want stack_check: {}", func.dfg.display_inst(inst, isa)), }; - let ptr_ty = if isa.flags().is_64bit() { - ir::types::I64 - } else { - ir::types::I32 - }; + let ptr_ty = isa.pointer_type(); let mut pos = FuncCursor::new(func).at_inst(inst); pos.use_srcloc(inst); diff --git a/lib/codegen/src/lib.rs b/lib/codegen/src/lib.rs index 05d781dcd7..cfcae5d344 100644 --- a/lib/codegen/src/lib.rs +++ b/lib/codegen/src/lib.rs @@ -52,6 +52,11 @@ extern crate alloc; extern crate failure; #[macro_use] extern crate failure_derive; +#[cfg(test)] +#[macro_use] +extern crate target_lexicon; +#[cfg(not(test))] +extern crate target_lexicon; pub use context::Context; pub use legalizer::legalize_function; diff --git a/lib/codegen/src/regalloc/pressure.rs b/lib/codegen/src/regalloc/pressure.rs index 355fce582e..a85bef28ca 100644 --- a/lib/codegen/src/regalloc/pressure.rs +++ b/lib/codegen/src/regalloc/pressure.rs @@ -275,6 +275,8 @@ mod tests { use regalloc::RegisterSet; use std::borrow::Borrow; use std::boxed::Box; + use std::str::FromStr; + use target_lexicon; // Make an arm32 `TargetIsa`, if possible. fn arm32() -> Option> { @@ -284,7 +286,9 @@ mod tests { let shared_builder = settings::builder(); let shared_flags = settings::Flags::new(shared_builder); - isa::lookup("arm32").ok().map(|b| b.finish(shared_flags)) + isa::lookup(triple!("arm")) + .ok() + .map(|b| b.finish(shared_flags)) } // Get a register class by name. diff --git a/lib/codegen/src/regalloc/solver.rs b/lib/codegen/src/regalloc/solver.rs index af935b2104..d5d000fa95 100644 --- a/lib/codegen/src/regalloc/solver.rs +++ b/lib/codegen/src/regalloc/solver.rs @@ -1134,6 +1134,8 @@ mod tests { use isa::{RegClass, RegInfo, RegUnit, TargetIsa}; use regalloc::RegisterSet; use std::boxed::Box; + use std::str::FromStr; + use target_lexicon; // Make an arm32 `TargetIsa`, if possible. fn arm32() -> Option> { @@ -1143,7 +1145,9 @@ mod tests { let shared_builder = settings::builder(); let shared_flags = settings::Flags::new(shared_builder); - isa::lookup("arm32").ok().map(|b| b.finish(shared_flags)) + isa::lookup(triple!("arm")) + .ok() + .map(|b| b.finish(shared_flags)) } // Get a register class by name. diff --git a/lib/codegen/src/settings.rs b/lib/codegen/src/settings.rs index 85a3a46b2f..d66cbae7c1 100644 --- a/lib/codegen/src/settings.rs +++ b/lib/codegen/src/settings.rs @@ -361,13 +361,11 @@ mod tests { "[shared]\n\ opt_level = \"default\"\n\ enable_verifier = true\n\ - is_64bit = false\n\ call_conv = \"fast\"\n\ is_pic = false\n\ colocated_libcalls = false\n\ return_at_end = false\n\ avoid_div_traps = false\n\ - is_compressed = false\n\ enable_float = true\n\ enable_nan_canonicalization = false\n\ enable_simd = true\n\ diff --git a/lib/faerie/Cargo.toml b/lib/faerie/Cargo.toml index f1923ef09e..b09b16c688 100644 --- a/lib/faerie/Cargo.toml +++ b/lib/faerie/Cargo.toml @@ -11,9 +11,10 @@ readme = "README.md" [dependencies] cretonne-codegen = { path = "../codegen", version = "0.8.0" } cretonne-module = { path = "../module", version = "0.8.0" } -faerie = "0.3.0" +faerie = "0.4.0" goblin = "0.0.14" failure = "0.1.1" +target-lexicon = { version = "0.0.0" } [badges] maintenance = { status = "experimental" } diff --git a/lib/faerie/src/backend.rs b/lib/faerie/src/backend.rs index 571ed1db77..14b4729e26 100644 --- a/lib/faerie/src/backend.rs +++ b/lib/faerie/src/backend.rs @@ -9,7 +9,7 @@ use cretonne_module::{Backend, DataContext, DataDescription, Init, Linkage, Modu use faerie; use failure::Error; use std::fs::File; -use target; +use target_lexicon::BinaryFormat; use traps::{FaerieTrapManifest, FaerieTrapSink}; #[derive(Debug)] @@ -27,8 +27,7 @@ pub enum FaerieTrapCollection { pub struct FaerieBuilder { isa: Box, name: String, - format: container::Format, - faerie_target: faerie::Target, + format: BinaryFormat, collect_traps: FaerieTrapCollection, libcall_names: Box String>, } @@ -50,7 +49,7 @@ impl FaerieBuilder { pub fn new( isa: Box, name: String, - format: container::Format, + format: BinaryFormat, collect_traps: FaerieTrapCollection, libcall_names: Box String>, ) -> Result { @@ -59,12 +58,10 @@ impl FaerieBuilder { "faerie requires TargetIsa be PIC".to_owned(), )); } - let faerie_target = target::translate(&*isa)?; Ok(Self { isa, name, format, - faerie_target, collect_traps, libcall_names, }) @@ -92,7 +89,7 @@ impl FaerieBuilder { pub struct FaerieBackend { isa: Box, artifact: faerie::Artifact, - format: container::Format, + format: BinaryFormat, trap_manifest: Option, libcall_names: Box String>, } @@ -119,8 +116,8 @@ impl Backend for FaerieBackend { /// Create a new `FaerieBackend` using the given Cretonne target. fn new(builder: FaerieBuilder) -> Self { Self { + artifact: faerie::Artifact::new(builder.isa.triple().clone(), builder.name), isa: builder.isa, - artifact: faerie::Artifact::new(builder.faerie_target, builder.name), format: builder.format, trap_manifest: match builder.collect_traps { FaerieTrapCollection::Enabled => Some(FaerieTrapManifest::new()), @@ -290,7 +287,6 @@ impl Backend for FaerieBackend { fn finish(self) -> FaerieProduct { FaerieProduct { artifact: self.artifact, - format: self.format, trap_manifest: self.trap_manifest, } } @@ -305,8 +301,6 @@ pub struct FaerieProduct { /// Optional trap manifest. Contains `FaerieTrapManifest` when `FaerieBuilder.collect_traps` is /// set to `FaerieTrapCollection::Enabled`. pub trap_manifest: Option, - /// The format that the builder specified for output. - format: container::Format, } impl FaerieProduct { @@ -317,18 +311,12 @@ impl FaerieProduct { /// Call `emit` on the faerie `Artifact`, producing bytes in memory. pub fn emit(&self) -> Result, Error> { - match self.format { - container::Format::ELF => self.artifact.emit::(), - container::Format::MachO => self.artifact.emit::(), - } + self.artifact.emit() } /// Call `write` on the faerie `Artifact`, writing to a file. pub fn write(&self, sink: File) -> Result<(), Error> { - match self.format { - container::Format::ELF => self.artifact.write::(sink), - container::Format::MachO => self.artifact.write::(sink), - } + self.artifact.write(sink) } } @@ -358,7 +346,7 @@ fn translate_data_linkage(linkage: Linkage, writable: bool) -> faerie::Decl { } struct FaerieRelocSink<'a> { - format: container::Format, + format: BinaryFormat, artifact: &'a mut faerie::Artifact, name: &'a str, namespace: &'a ModuleNamespace<'a, FaerieBackend>, diff --git a/lib/faerie/src/container.rs b/lib/faerie/src/container.rs index c78f05878c..117482020c 100644 --- a/lib/faerie/src/container.rs +++ b/lib/faerie/src/container.rs @@ -1,6 +1,7 @@ //! Utilities for working with Faerie container formats. use cretonne_codegen::binemit::Reloc; +use target_lexicon::BinaryFormat; /// An object file format. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -13,9 +14,9 @@ pub enum Format { /// Translate from a Cretonne `Reloc` to a raw object-file-format-specific /// relocation code. -pub fn raw_relocation(reloc: Reloc, format: Format) -> u32 { +pub fn raw_relocation(reloc: Reloc, format: BinaryFormat) -> u32 { match format { - Format::ELF => { + BinaryFormat::Elf => { use goblin::elf; match reloc { Reloc::Abs4 => elf::reloc::R_X86_64_32, @@ -28,6 +29,7 @@ pub fn raw_relocation(reloc: Reloc, format: Format) -> u32 { _ => unimplemented!(), } } - Format::MachO => unimplemented!(), + BinaryFormat::Macho => unimplemented!("macho relocations"), + _ => unimplemented!("unsupported format"), } } diff --git a/lib/faerie/src/lib.rs b/lib/faerie/src/lib.rs index 7d7bb27a0a..c3f196004c 100644 --- a/lib/faerie/src/lib.rs +++ b/lib/faerie/src/lib.rs @@ -19,10 +19,10 @@ extern crate cretonne_module; extern crate faerie; extern crate failure; extern crate goblin; +extern crate target_lexicon; mod backend; mod container; -mod target; pub mod traps; pub use backend::{FaerieBackend, FaerieBuilder, FaerieProduct, FaerieTrapCollection}; diff --git a/lib/faerie/src/target.rs b/lib/faerie/src/target.rs deleted file mode 100644 index d6e3749430..0000000000 --- a/lib/faerie/src/target.rs +++ /dev/null @@ -1,21 +0,0 @@ -use cretonne_codegen::isa; -use cretonne_module::ModuleError; -use faerie::Target; - -/// Translate from a Cretonne `TargetIsa` to a Faerie `Target`. -pub fn translate(isa: &isa::TargetIsa) -> Result { - let name = isa.name(); - match name { - "x86" => Ok(if isa.flags().is_64bit() { - Target::X86_64 - } else { - Target::X86 - }), - "arm32" => Ok(Target::ARMv7), - "arm64" => Ok(Target::ARM64), - _ => Err(ModuleError::Backend(format!( - "unsupported faerie isa: {}", - name - ))), - } -} diff --git a/lib/module/src/module.rs b/lib/module/src/module.rs index 6b696d2b33..ee6943432c 100644 --- a/lib/module/src/module.rs +++ b/lib/module/src/module.rs @@ -318,11 +318,7 @@ where /// Return then pointer type for the current target. pub fn pointer_type(&self) -> ir::types::Type { - if self.backend.isa().flags().is_64bit() { - ir::types::I64 - } else { - ir::types::I32 - } + self.backend.isa().pointer_type() } /// Create a new `Context` initialized for use with this `Module`. diff --git a/lib/native/Cargo.toml b/lib/native/Cargo.toml index 17e2578339..4a6a4c1ccf 100644 --- a/lib/native/Cargo.toml +++ b/lib/native/Cargo.toml @@ -9,6 +9,7 @@ readme = "README.md" [dependencies] cretonne-codegen = { path = "../codegen", version = "0.8.0", default-features = false } +target-lexicon = { version = "0.0.0", default-features = false } [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] raw-cpuid = "3.1.0" diff --git a/lib/native/src/lib.rs b/lib/native/src/lib.rs index f9f6d4cc7a..9ab9df71c7 100644 --- a/lib/native/src/lib.rs +++ b/lib/native/src/lib.rs @@ -17,9 +17,11 @@ extern crate cretonne_codegen; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] extern crate raw_cpuid; +extern crate target_lexicon; use cretonne_codegen::isa; use cretonne_codegen::settings::{self, Configurable}; +use target_lexicon::Triple; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use raw_cpuid::CpuId; @@ -38,25 +40,8 @@ pub fn builders() -> Result<(settings::Builder, isa::Builder), &'static str> { return Err("unrecognized environment"); } - if cfg!(target_pointer_width = "64") { - flag_builder.enable("is_64bit").unwrap(); - } else if !cfg!(target_pointer_width = "32") { - return Err("unrecognized pointer size"); - } - - // TODO: Add RISC-V support once Rust supports it. - let name = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) { - "x86" - } else if cfg!(target_arch = "arm") { - "arm32" - } else if cfg!(target_arch = "aarch64") { - "arm64" - } else { - return Err("unrecognized architecture"); - }; - - let mut isa_builder = isa::lookup(name).map_err(|err| match err { - isa::LookupError::Unknown => panic!(), + let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err { + isa::LookupError::SupportDisabled => "support for architecture disabled at compile time", isa::LookupError::Unsupported => "unsupported architecture", })?; diff --git a/lib/reader/Cargo.toml b/lib/reader/Cargo.toml index d37ed2bbcf..92734dc9dc 100644 --- a/lib/reader/Cargo.toml +++ b/lib/reader/Cargo.toml @@ -10,6 +10,7 @@ readme = "README.md" [dependencies] cretonne-codegen = { path = "../codegen", version = "0.8.0" } +target-lexicon = { version = "0.0.0" } [badges] maintenance = { status = "experimental" } diff --git a/lib/reader/src/error.rs b/lib/reader/src/error.rs index 965eba3cb8..ed9eeb3cd9 100644 --- a/lib/reader/src/error.rs +++ b/lib/reader/src/error.rs @@ -40,7 +40,7 @@ macro_rules! err { ( $loc:expr, $msg:expr ) => { Err($crate::Error { location: $loc.clone(), - message: String::from($msg), + message: $msg.to_string(), }) }; diff --git a/lib/reader/src/lib.rs b/lib/reader/src/lib.rs index 687abd1b85..1fbd10a607 100644 --- a/lib/reader/src/lib.rs +++ b/lib/reader/src/lib.rs @@ -16,6 +16,7 @@ )] extern crate cretonne_codegen; +extern crate target_lexicon; pub use error::{Error, Location, Result}; pub use isaspec::{parse_options, IsaSpec}; diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 7c013cd857..0f64885147 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -22,12 +22,13 @@ use sourcemap::SourceMap; use std::mem; use std::str::FromStr; use std::{u16, u32}; +use target_lexicon::Triple; use testcommand::TestCommand; use testfile::{Comment, Details, TestFile}; /// Parse the entire `text` into a list of functions. /// -/// Any test commands or ISA declarations are ignored. +/// Any test commands or target declarations are ignored. pub fn parse_functions(text: &str) -> Result> { let _tt = timing::parse_text(); parse_test(text).map(|file| file.functions.into_iter().map(|(func, _)| func).collect()) @@ -43,7 +44,7 @@ pub fn parse_test(text: &str) -> Result { parser.start_gathering_comments(); let commands = parser.parse_test_commands(); - let isa_spec = parser.parse_isa_specs()?; + let isa_spec = parser.parse_target_specs()?; parser.token(); parser.claim_gathered_comments(AnyEntity::Function); @@ -88,10 +89,10 @@ struct Context<'a> { /// Aliases to resolve once value definitions are known. aliases: Vec, - /// Reference to the unique_isa for things like parsing ISA-specific instruction encoding + /// Reference to the unique_isa for things like parsing target-specific instruction encoding /// information. This is only `Some` if exactly one set of `isa` directives were found in the - /// prologue (it is valid to have directives for multiple different ISAs, but in that case we - /// couldn't know which ISA the provided encodings are intended for) + /// prologue (it is valid to have directives for multiple different targets, but in that case we + /// couldn't know which target the provided encodings are intended for) unique_isa: Option<&'a TargetIsa>, } @@ -667,17 +668,17 @@ impl<'a> Parser<'a> { list } - /// Parse a list of ISA specs. + /// Parse a list of target specs. /// - /// Accept a mix of `isa` and `set` command lines. The `set` commands are cumulative. + /// Accept a mix of `target` and `set` command lines. The `set` commands are cumulative. /// - pub fn parse_isa_specs(&mut self) -> Result { - // Was there any `isa` commands? - let mut seen_isa = false; - // Location of last `set` command since the last `isa`. + pub fn parse_target_specs(&mut self) -> Result { + // Was there any `target` commands? + let mut seen_target = false; + // Location of last `set` command since the last `target`. let mut last_set_loc = None; - let mut isas = Vec::new(); + let mut targets = Vec::new(); let mut flag_builder = settings::builder(); while let Some(Token::Identifier(command)) = self.token() { @@ -690,38 +691,42 @@ impl<'a> Parser<'a> { &self.loc, )?; } - "isa" => { + "target" => { let loc = self.loc; // Grab the whole line so the lexer won't go looking for tokens on the // following lines. let mut words = self.consume_line().trim().split_whitespace(); - // Look for `isa foo`. - let isa_name = match words.next() { - None => return err!(loc, "expected ISA name"), + // Look for `target foo`. + let target_name = match words.next() { Some(w) => w, + None => return err!(loc, "expected target triple"), }; - let mut isa_builder = match isa::lookup(isa_name) { - Err(isa::LookupError::Unknown) => { - return err!(loc, "unknown ISA '{}'", isa_name) + let triple = match Triple::from_str(target_name) { + Ok(triple) => triple, + Err(err) => return err!(loc, err), + }; + let mut isa_builder = match isa::lookup(triple) { + Err(isa::LookupError::SupportDisabled) => { + continue; } Err(isa::LookupError::Unsupported) => { - continue; + return err!(loc, "unsupported target '{}'", target_name) } Ok(b) => b, }; last_set_loc = None; - seen_isa = true; - // Apply the ISA-specific settings to `isa_builder`. + seen_target = true; + // Apply the target-specific settings to `isa_builder`. isaspec::parse_options(words, &mut isa_builder, &self.loc)?; // Construct a trait object with the aggregate settings. - isas.push(isa_builder.finish(settings::Flags::new(flag_builder.clone()))); + targets.push(isa_builder.finish(settings::Flags::new(flag_builder.clone()))); } _ => break, } } - if !seen_isa { - // No `isa` commands, but we allow for `set` commands. + if !seen_target { + // No `target` commands, but we allow for `set` commands. Ok(isaspec::IsaSpec::None(settings::Flags::new(flag_builder))) } else if let Some(loc) = last_set_loc { err!( @@ -729,7 +734,7 @@ impl<'a> Parser<'a> { "dangling 'set' command after ISA specification has no effect." ) } else { - Ok(isaspec::IsaSpec::Some(isas)) + Ok(isaspec::IsaSpec::Some(targets)) } } @@ -2466,14 +2471,14 @@ mod tests { fn isa_spec() { assert!( parse_test( - "isa + "target function %foo() system_v {}", ).is_err() ); assert!( parse_test( - "isa riscv + "target riscv32 set enable_float=false function %foo() system_v {}", ).is_err() diff --git a/lib/simplejit/Cargo.toml b/lib/simplejit/Cargo.toml index d672c1dc63..fb4c1d8e1a 100644 --- a/lib/simplejit/Cargo.toml +++ b/lib/simplejit/Cargo.toml @@ -15,6 +15,7 @@ cretonne-native = { path = "../native", version = "0.8.0", default-features = fa region = "0.2.0" libc = { version = "0.2.40", default-features = false } errno = "0.2.3" +target-lexicon = { version = "0.0.0", default-features = false } [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["winbase", "memoryapi"] } diff --git a/lib/simplejit/src/backend.rs b/lib/simplejit/src/backend.rs index 873578e708..889601a819 100644 --- a/lib/simplejit/src/backend.rs +++ b/lib/simplejit/src/backend.rs @@ -10,6 +10,7 @@ use libc; use memory::Memory; use std::ffi::CString; use std::ptr; +use target_lexicon::PointerWidth; #[cfg(windows)] use winapi; @@ -173,10 +174,10 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend { } } - let reloc = if self.isa.flags().is_64bit() { - Reloc::Abs8 - } else { - Reloc::Abs4 + let reloc = match self.isa.triple().pointer_width().unwrap() { + PointerWidth::U16 => panic!(), + PointerWidth::U32 => Reloc::Abs4, + PointerWidth::U64 => Reloc::Abs8, }; let mut relocs = Vec::new(); for &(offset, id) in function_relocs { diff --git a/lib/simplejit/src/lib.rs b/lib/simplejit/src/lib.rs index 3212447065..0e908dd414 100644 --- a/lib/simplejit/src/lib.rs +++ b/lib/simplejit/src/lib.rs @@ -18,6 +18,7 @@ extern crate cretonne_native; extern crate errno; extern crate libc; extern crate region; +extern crate target_lexicon; #[cfg(target_os = "windows")] extern crate winapi; diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index 3882a850cb..a0e580924e 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -15,6 +15,7 @@ cretonne-frontend = { path = "../frontend", version = "0.8.0", default-features hashmap_core = { version = "0.1.4", optional = true } failure = { version = "0.1.1", default-features = false, features = ["derive"] } failure_derive = { version = "0.1.1", default-features = false } +target-lexicon = { version = "0.0.0", default-features = false } [dev-dependencies] wabt = "0.3" diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index 8eae69fc2b..4794524b5a 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -8,6 +8,7 @@ use environ::{FuncEnvironment, GlobalValue, ModuleEnvironment, WasmResult}; use func_translator::FuncTranslator; use std::string::String; use std::vec::Vec; +use target_lexicon::Triple; use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex}; use wasmparser; @@ -39,6 +40,9 @@ impl Exportable { /// `DummyEnvironment` to allow it to be borrowed separately from the /// `FuncTranslator` field. pub struct DummyModuleInfo { + /// Target description. + pub triple: Triple, + /// Compilation setting flags. pub flags: settings::Flags, @@ -69,8 +73,9 @@ pub struct DummyModuleInfo { impl DummyModuleInfo { /// Allocates the data structures with the given flags. - pub fn with_flags(flags: settings::Flags) -> Self { + pub fn with_triple_flags(triple: Triple, flags: settings::Flags) -> Self { Self { + triple, flags, signatures: Vec::new(), imported_funcs: Vec::new(), @@ -100,14 +105,14 @@ pub struct DummyEnvironment { impl DummyEnvironment { /// Allocates the data structures with default flags. - pub fn default() -> Self { - Self::with_flags(settings::Flags::new(settings::builder())) + pub fn with_triple(triple: Triple) -> Self { + Self::with_triple_flags(triple, settings::Flags::new(settings::builder())) } /// Allocates the data structures with the given flags. - pub fn with_flags(flags: settings::Flags) -> Self { + pub fn with_triple_flags(triple: Triple, flags: settings::Flags) -> Self { Self { - info: DummyModuleInfo::with_flags(flags), + info: DummyModuleInfo::with_triple_flags(triple, flags), trans: FuncTranslator::new(), func_bytecode_sizes: Vec::new(), } @@ -143,6 +148,10 @@ impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> { } impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> { + fn triple(&self) -> &Triple { + &self.mod_info.triple + } + fn flags(&self) -> &settings::Flags { &self.mod_info.flags } diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 5b26ca785f..5b4ca58301 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -4,6 +4,7 @@ use cretonne_codegen::cursor::FuncCursor; use cretonne_codegen::ir::{self, InstBuilder}; use cretonne_codegen::settings::Flags; use std::vec::Vec; +use target_lexicon::Triple; use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex}; use wasmparser::BinaryReaderError; @@ -74,6 +75,9 @@ pub type WasmResult = Result; /// IR. The function environment provides information about the WebAssembly module as well as the /// runtime environment. pub trait FuncEnvironment { + /// Get the triple for the current compilation. + fn triple(&self) -> &Triple; + /// Get the flags for the current compilation. fn flags(&self) -> &Flags; @@ -81,11 +85,7 @@ pub trait FuncEnvironment { /// /// This returns `I64` for 64-bit architectures and `I32` for 32-bit architectures. fn native_pointer(&self) -> ir::Type { - if self.flags().is_64bit() { - ir::types::I64 - } else { - ir::types::I32 - } + ir::Type::int(u16::from(self.triple().pointer_width().unwrap().bits())).unwrap() } /// Set up the necessary preamble definitions in `func` to access the global variable diff --git a/lib/wasm/src/func_translator.rs b/lib/wasm/src/func_translator.rs index fbac424fef..9f93904381 100644 --- a/lib/wasm/src/func_translator.rs +++ b/lib/wasm/src/func_translator.rs @@ -237,6 +237,7 @@ mod tests { use cretonne_codegen::ir::types::I32; use cretonne_codegen::{ir, Context}; use environ::{DummyEnvironment, FuncEnvironment}; + use target_lexicon::Triple; #[test] fn small1() { @@ -256,7 +257,7 @@ mod tests { ]; let mut trans = FuncTranslator::new(); - let runtime = DummyEnvironment::default(); + let runtime = DummyEnvironment::with_triple(Triple::default()); let mut ctx = Context::new(); ctx.func.name = ir::ExternalName::testcase("small1"); @@ -289,7 +290,7 @@ mod tests { ]; let mut trans = FuncTranslator::new(); - let runtime = DummyEnvironment::default(); + let runtime = DummyEnvironment::with_triple(Triple::default()); let mut ctx = Context::new(); ctx.func.name = ir::ExternalName::testcase("small2"); @@ -335,7 +336,7 @@ mod tests { ]; let mut trans = FuncTranslator::new(); - let runtime = DummyEnvironment::default(); + let runtime = DummyEnvironment::with_triple(Triple::default()); let mut ctx = Context::new(); ctx.func.name = ir::ExternalName::testcase("infloop"); diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index 2c73f73953..a7ceeee389 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -34,6 +34,7 @@ extern crate hashmap_core; #[macro_use(dbg)] extern crate cretonne_codegen; extern crate cretonne_frontend; +extern crate target_lexicon; extern crate wasmparser; extern crate failure; diff --git a/lib/wasm/tests/wasm_testsuite.rs b/lib/wasm/tests/wasm_testsuite.rs index a5d5badaed..2418193f34 100644 --- a/lib/wasm/tests/wasm_testsuite.rs +++ b/lib/wasm/tests/wasm_testsuite.rs @@ -1,5 +1,7 @@ extern crate cretonne_codegen; extern crate cretonne_wasm; +#[macro_use] +extern crate target_lexicon; extern crate wabt; use cretonne_codegen::print_errors::pretty_verifier_error; @@ -11,6 +13,7 @@ use std::fs::File; use std::io; use std::io::prelude::*; use std::path::Path; +use std::str::FromStr; use wabt::wat2wasm; #[test] @@ -70,7 +73,7 @@ fn handle_module(path: &Path, flags: &Flags) { None | Some(&_) => panic!("the file extension for {:?} is not wasm or wat", path), }, }; - let mut dummy_environ = DummyEnvironment::with_flags(flags.clone()); + let mut dummy_environ = DummyEnvironment::with_triple_flags(triple!("riscv64"), flags.clone()); translate_module(&data, &mut dummy_environ).unwrap(); for func in &dummy_environ.info.function_bodies { verifier::verify_function(func, flags)