diff --git a/cranelift/docs/heapex-dyn.cton b/cranelift/docs/heapex-dyn.cton index 2be801da86..9f1f2ac078 100644 --- a/cranelift/docs/heapex-dyn.cton +++ b/cranelift/docs/heapex-dyn.cton @@ -1,6 +1,6 @@ test verifier -function %add_members(i32) -> f32 spiderwasm { +function %add_members(i32) -> f32 baldrdash { gv0 = vmctx+64 gv1 = vmctx+72 heap0 = dynamic gv0, min 0x1000, bound gv1, guard 0 diff --git a/cranelift/docs/heapex-sm32.cton b/cranelift/docs/heapex-sm32.cton index 51b0c4cbcb..61014d05f5 100644 --- a/cranelift/docs/heapex-sm32.cton +++ b/cranelift/docs/heapex-sm32.cton @@ -1,6 +1,6 @@ test verifier -function %add_members(i32) -> f32 spiderwasm { +function %add_members(i32) -> f32 baldrdash { gv0 = vmctx+64 heap0 = static gv0, min 0x1000, bound 0x10_0000, guard 0x1000 diff --git a/cranelift/docs/heapex-sm64.cton b/cranelift/docs/heapex-sm64.cton index e29fa9caf5..4755e8790a 100644 --- a/cranelift/docs/heapex-sm64.cton +++ b/cranelift/docs/heapex-sm64.cton @@ -1,6 +1,6 @@ test verifier -function %add_members(i32) -> f32 spiderwasm { +function %add_members(i32) -> f32 baldrdash { gv0 = vmctx+64 heap0 = static gv0, min 0x1000, bound 0x1_0000_0000, guard 0x8000_0000 diff --git a/cranelift/docs/langref.rst b/cranelift/docs/langref.rst index 33fc1f0694..8a8baa5b33 100644 --- a/cranelift/docs/langref.rst +++ b/cranelift/docs/langref.rst @@ -399,7 +399,28 @@ convention: param : type [paramext] [paramspecial] paramext : "uext" | "sext" paramspecial : "sret" | "link" | "fp" | "csr" | "vmctx" - callconv : "system_v" | "spiderwasm" + callconv : "fast" | "cold" | "system_v" | "fastcall" | "baldrdash" + +A function's calling convention determines exactly how arguments and return +values are passed, and how stack frames are managed. Since all of these details +depend on both the instruction set /// architecture and possibly the operating +system, a function's calling convention is only fully determined by a +`(TargetIsa, CallConv)` tuple. + +========== =========================================== +Name Description +========== =========================================== +fast not-ABI-stable convention for best performance +cold not-ABI-stable convention for infrequently executed code +system_v System V-style convention used on many platforms +fastcall Windows "fastcall" convention, also used for x64 and ARM +baldrdash SpiderMonkey WebAssembly convention +========== =========================================== + +The "not-ABI-stable" conventions do not follow an external specification and +may change between versions of Cretonne. + +The "fastcall" convention is not yet implemented. Parameters and return values have flags whose meaning is mostly target dependent. These flags support interfacing with code produced by other diff --git a/cranelift/filetests/isa/riscv/parse-encoding.cton b/cranelift/filetests/isa/riscv/parse-encoding.cton index b8220b1688..e61f43ef84 100644 --- a/cranelift/filetests/isa/riscv/parse-encoding.cton +++ b/cranelift/filetests/isa/riscv/parse-encoding.cton @@ -3,7 +3,7 @@ test legalizer isa riscv function %parse_encoding(i32 [%x5]) -> i32 [%x10] { - ; check: function %parse_encoding(i32 [%x5], i32 link [%x1]) -> i32 [%x10], i32 link [%x1] system_v { + ; check: function %parse_encoding(i32 [%x5], i32 link [%x1]) -> i32 [%x10], i32 link [%x1] fast { sig0 = (i32 [%x10]) -> i32 [%x10] system_v ; check: sig0 = (i32 [%x10]) -> i32 [%x10] system_v diff --git a/cranelift/filetests/isa/x86/abi64.cton b/cranelift/filetests/isa/x86/abi64.cton index 40321f90fb..121e5cc1a8 100644 --- a/cranelift/filetests/isa/x86/abi64.cton +++ b/cranelift/filetests/isa/x86/abi64.cton @@ -19,8 +19,8 @@ ebb0: return } -function %pass_stack_int64(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) spiderwasm { - sig0 = (i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) spiderwasm +function %pass_stack_int64(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) baldrdash { + sig0 = (i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) baldrdash fn0 = u0:0 sig0 ebb0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v8: i64, v9: i64, v10: i64, v11: i64, v12: i64, v13: i64, v14: i64, v15: i64, v16: i64, v17: i64, v18: i64, v19: i64, v20: i64): diff --git a/cranelift/filetests/isa/x86/legalize-libcall.cton b/cranelift/filetests/isa/x86/legalize-libcall.cton index 70d392e6e4..d633bd4e46 100644 --- a/cranelift/filetests/isa/x86/legalize-libcall.cton +++ b/cranelift/filetests/isa/x86/legalize-libcall.cton @@ -10,7 +10,7 @@ ebb0(v0: f32): v1 = floor v0 return v1 } -; check: function %floor(f32 [%xmm0]) -> f32 [%xmm0] system_v { -; check: sig0 = (f32) -> f32 system_v +; check: function %floor(f32 [%xmm0]) -> f32 [%xmm0] fast { +; check: sig0 = (f32) -> f32 fast ; check: fn0 = %FloorF32 sig0 ; check: v1 = call fn0(v0) diff --git a/cranelift/filetests/isa/x86/legalize-memory.cton b/cranelift/filetests/isa/x86/legalize-memory.cton index 9cb8661873..fc77c757e3 100644 --- a/cranelift/filetests/isa/x86/legalize-memory.cton +++ b/cranelift/filetests/isa/x86/legalize-memory.cton @@ -44,7 +44,7 @@ ebb1: ; SpiderMonkey VM-style static 4+2 GB heap. ; This eliminates bounds checks completely for offsets < 2GB. -function %staticheap_sm64(i32, i64 vmctx) -> f32 spiderwasm { +function %staticheap_sm64(i32, i64 vmctx) -> f32 baldrdash { gv0 = vmctx+64 heap0 = static gv0, min 0x1000, bound 0x1_0000_0000, guard 0x8000_0000 @@ -65,7 +65,7 @@ ebb0(v0: i32, v999: i64): return v4 } -function %staticheap_static_oob_sm64(i32, i64 vmctx) -> f32 spiderwasm { +function %staticheap_static_oob_sm64(i32, i64 vmctx) -> f32 baldrdash { gv0 = vmctx+64 heap0 = static gv0, min 0x1000, bound 0x1000_0000, guard 0x8000_0000 @@ -88,7 +88,7 @@ ebb0(v0: i32, v999: i64): ; SpiderMonkey VM-style static 4+2 GB heap. ; Offsets >= 2 GB do require a boundscheck. -function %staticheap_sm64(i32, i64 vmctx) -> f32 spiderwasm { +function %staticheap_sm64(i32, i64 vmctx) -> f32 baldrdash { gv0 = vmctx+64 heap0 = static gv0, min 0x1000, bound 0x1_0000_0000, guard 0x8000_0000 @@ -112,7 +112,7 @@ ebb0(v0: i32, v999: i64): ; Stack overflow check. ; The stack limit is stored in a pointer-sized global variable. -function %stkchk(i64 vmctx) spiderwasm { +function %stkchk(i64 vmctx) baldrdash { gv0 = vmctx+64 ebb0(v0: i64): diff --git a/cranelift/filetests/isa/x86/prologue-epilogue.cton b/cranelift/filetests/isa/x86/prologue-epilogue.cton index 76aa459f94..bf4bf298b5 100644 --- a/cranelift/filetests/isa/x86/prologue-epilogue.cton +++ b/cranelift/filetests/isa/x86/prologue-epilogue.cton @@ -11,7 +11,7 @@ ebb0: return } -; check: function %empty(i64 fp [%rbp]) -> i64 fp [%rbp] system_v { +; check: function %empty(i64 fp [%rbp]) -> i64 fp [%rbp] fast { ; nextln: ss0 = incoming_arg 16, offset -16 ; nextln: ; nextln: ebb0(v0: i64 [%rbp]): @@ -29,7 +29,7 @@ ebb0: return } -; check: function %one_stack_slot(i64 fp [%rbp]) -> i64 fp [%rbp] system_v { +; check: function %one_stack_slot(i64 fp [%rbp]) -> i64 fp [%rbp] fast { ; nextln: ss0 = explicit_slot 168, offset -184 ; nextln: ss1 = incoming_arg 16, offset -16 ; nextln: @@ -52,9 +52,9 @@ ebb0: return } -; check: function %call(i64 fp [%rbp]) -> i64 fp [%rbp] system_v { +; check: function %call(i64 fp [%rbp]) -> i64 fp [%rbp] fast { ; nextln: ss0 = incoming_arg 16, offset -16 -; nextln: sig0 = () system_v +; nextln: sig0 = () fast ; nextln: fn0 = %foo sig0 ; nextln: ; nextln: ebb0(v0: i64 [%rbp]): @@ -98,7 +98,7 @@ ebb0(v0: i64, v1: i64): return } -; check: function %no_spill(i64 [%rdi], i64 [%rsi], i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] system_v { +; check: function %no_spill(i64 [%rdi], i64 [%rsi], i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] fast { ; nextln: ss0 = incoming_arg 56, offset -56 ; nextln: ; nextln: ebb0(v0: i64 [%rdi], v1: i64 [%rsi], v15: i64 [%rbp], v16: i64 [%rbx], v17: i64 [%r12], v18: i64 [%r13], v19: i64 [%r14], v20: i64 [%r15]): @@ -181,7 +181,7 @@ ebb0(v0: i64, v1: i64): return } -; check: function %yes_spill(i64 [%rdi], i64 [%rsi], i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] system_v { +; check: function %yes_spill(i64 [%rdi], i64 [%rsi], i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] fast { ; check: ss0 = spill_slot ; check: ebb0(v16: i64 [%rdi], v17: i64 [%rsi], v48: i64 [%rbp], v49: i64 [%rbx], v50: i64 [%r12], v51: i64 [%r13], v52: i64 [%r14], v53: i64 [%r15]): diff --git a/cranelift/filetests/parser/branch.cton b/cranelift/filetests/parser/branch.cton index 4e35147a6b..2969c8f384 100644 --- a/cranelift/filetests/parser/branch.cton +++ b/cranelift/filetests/parser/branch.cton @@ -9,7 +9,7 @@ ebb0: ebb1: jump ebb0() } -; sameln: function %minimal() system_v { +; sameln: function %minimal() fast { ; nextln: ebb0: ; nextln: jump ebb1 ; nextln: @@ -25,7 +25,7 @@ ebb0(v90: i32): ebb1(v91: i32): jump ebb0(v91) } -; sameln: function %onearg(i32) system_v { +; sameln: function %onearg(i32) fast { ; nextln: ebb0(v90: i32): ; nextln: jump ebb1(v90) ; nextln: @@ -41,7 +41,7 @@ ebb0(v90: i32, v91: f32): ebb1(v92: i32, v93: f32): jump ebb0(v92, v93) } -; sameln: function %twoargs(i32, f32) system_v { +; sameln: function %twoargs(i32, f32) fast { ; nextln: ebb0(v90: i32, v91: f32): ; nextln: jump ebb1(v90, v91) ; nextln: @@ -57,7 +57,7 @@ ebb0(v90: i32): ebb1: brnz v90, ebb1() } -; sameln: function %minimal(i32) system_v { +; sameln: function %minimal(i32) fast { ; nextln: ebb0(v90: i32): ; nextln: brz v90, ebb1 ; nextln: @@ -72,7 +72,7 @@ ebb0(v90: i32, v91: f32): ebb1(v92: i32, v93: f32): brnz v90, ebb0(v92, v93) } -; sameln: function %twoargs(i32, f32) system_v { +; sameln: function %twoargs(i32, f32) fast { ; nextln: ebb0(v90: i32, v91: f32): ; nextln: brz v90, ebb1(v90, v91) ; nextln: @@ -94,7 +94,7 @@ ebb30: ebb40: trap user4 } -; sameln: function %jumptable(i32) system_v { +; sameln: function %jumptable(i32) fast { ; check: jt2 = jump_table 0, 0, ebb10, ebb40, ebb20, ebb30 ; check: jt200 = jump_table 0 ; check: ebb10(v3: i32): diff --git a/cranelift/filetests/parser/call.cton b/cranelift/filetests/parser/call.cton index 9d1e8def02..c75fa02393 100644 --- a/cranelift/filetests/parser/call.cton +++ b/cranelift/filetests/parser/call.cton @@ -5,18 +5,18 @@ function %mini() { ebb1: return } -; sameln: function %mini() system_v { +; sameln: function %mini() fast { ; nextln: ebb1: ; nextln: return ; nextln: } -function %r1() -> i32, f32 spiderwasm { +function %r1() -> i32, f32 baldrdash { ebb1: v1 = iconst.i32 3 v2 = f32const 0.0 return v1, v2 } -; sameln: function %r1() -> i32, f32 spiderwasm { +; sameln: function %r1() -> i32, f32 baldrdash { ; nextln: ebb1: ; nextln: v1 = iconst.i32 3 ; nextln: v2 = f32const 0.0 @@ -25,14 +25,14 @@ ebb1: function %signatures() { sig10 = () - sig11 = (i32, f64) -> i32, b1 spiderwasm + sig11 = (i32, f64) -> i32, b1 baldrdash fn5 = %foo sig11 fn8 = %bar(i32) -> b1 } -; sameln: function %signatures() system_v { -; check: sig10 = () system_v -; check: sig11 = (i32, f64) -> i32, b1 spiderwasm -; check: sig12 = (i32) -> b1 system_v +; sameln: function %signatures() fast { +; check: sig10 = () fast +; check: sig11 = (i32, f64) -> i32, b1 baldrdash +; check: sig12 = (i32) -> b1 fast ; not: fn0 ; check: fn5 = %foo sig11 ; check: fn8 = %bar sig12 @@ -88,7 +88,7 @@ function %special1(i32 sret, i32 fp, i32 csr, i32 link) -> i32 link, i32 fp, i32 ebb0(v1: i32, v2: i32, v3: i32, v4: i32): return v4, v2, v3, v1 } -; check: function %special1(i32 sret, i32 fp, i32 csr, i32 link) -> i32 link, i32 fp, i32 csr, i32 sret system_v { +; check: function %special1(i32 sret, i32 fp, i32 csr, i32 link) -> i32 link, i32 fp, i32 csr, i32 sret fast { ; check: ebb0(v1: i32, v2: i32, v3: i32, v4: i32): ; check: return v4, v2, v3, v1 ; check: } diff --git a/cranelift/filetests/parser/instruction_encoding.cton b/cranelift/filetests/parser/instruction_encoding.cton index e0a2de789a..7d75e4362a 100644 --- a/cranelift/filetests/parser/instruction_encoding.cton +++ b/cranelift/filetests/parser/instruction_encoding.cton @@ -13,7 +13,7 @@ ebb1(v0: i32 [%x8], v1: i32): @55 v9 = iadd v8, v7 @a5 [Iret#5] return v0, v8 } -; sameln: function %foo(i32, i32) system_v { +; sameln: function %foo(i32, i32) fast { ; nextln: ebb1(v0: i32 [%x8], v1: i32): ; nextln: [-,-]$WS v2 = iadd v0, v1 ; nextln: [-]$WS trap heap_oob diff --git a/cranelift/filetests/parser/keywords.cton b/cranelift/filetests/parser/keywords.cton index aaf8403c0a..e079892be7 100644 --- a/cranelift/filetests/parser/keywords.cton +++ b/cranelift/filetests/parser/keywords.cton @@ -2,4 +2,4 @@ test cat ; 'function' is not a keyword, and can be used as the name of a function too. function %function() {} -; check: function %function() system_v +; check: function %function() fast diff --git a/cranelift/filetests/parser/rewrite.cton b/cranelift/filetests/parser/rewrite.cton index 679f00d2bc..c40bd9589b 100644 --- a/cranelift/filetests/parser/rewrite.cton +++ b/cranelift/filetests/parser/rewrite.cton @@ -9,7 +9,7 @@ ebb100(v20: i32): v9200 = f64const 0x4.0p0 trap user4 } -; sameln: function %defs() system_v { +; sameln: function %defs() fast { ; nextln: ebb100(v20: i32): ; nextln: v1000 = iconst.i32x8 5 ; nextln: v9200 = f64const 0x1.0000000000000p2 @@ -23,7 +23,7 @@ ebb100(v20: i32): v200 = iadd v20, v1000 jump ebb100(v1000) } -; sameln: function %use_value() system_v { +; sameln: function %use_value() fast { ; nextln: ebb100(v20: i32): ; nextln: v1000 = iadd_imm v20, 5 ; nextln: v200 = iadd v20, v1000 diff --git a/cranelift/filetests/parser/tiny.cton b/cranelift/filetests/parser/tiny.cton index e800d44c26..2a342a666b 100644 --- a/cranelift/filetests/parser/tiny.cton +++ b/cranelift/filetests/parser/tiny.cton @@ -5,7 +5,7 @@ function %minimal() { ebb0: trap user0 } -; sameln: function %minimal() system_v { +; sameln: function %minimal() fast { ; nextln: ebb0: ; nextln: trap user0 ; nextln: } @@ -18,7 +18,7 @@ ebb0: v1 = iconst.i8 6 v2 = ishl v0, v1 } -; sameln: function %ivalues() system_v { +; sameln: function %ivalues() fast { ; nextln: ebb0: ; nextln: v0 = iconst.i32 2 ; nextln: v1 = iconst.i8 6 @@ -34,7 +34,7 @@ ebb0: v2 = bextend.b32 v1 v3 = bxor v0, v2 } -; sameln: function %bvalues() system_v { +; sameln: function %bvalues() fast { ; nextln: ebb0: ; nextln: v0 = bconst.b32 true ; nextln: v1 = bconst.b8 false @@ -47,7 +47,7 @@ function %select() { ebb0(v90: i32, v91: i32, v92: b1): v0 = select v92, v90, v91 } -; sameln: function %select() system_v { +; sameln: function %select() fast { ; nextln: ebb0(v90: i32, v91: i32, v92: b1): ; nextln: v0 = select v92, v90, v91 ; nextln: } @@ -69,7 +69,7 @@ ebb0: v1 = extractlane v0, 3 v2 = insertlane v0, 1, v1 } -; sameln: function %lanes() system_v { +; sameln: function %lanes() fast { ; nextln: ebb0: ; nextln: v0 = iconst.i32x4 2 ; nextln: v1 = extractlane v0, 3 @@ -85,7 +85,7 @@ ebb0(v90: i32, v91: i32): v3 = irsub_imm v91, 45 br_icmp eq v90, v91, ebb0(v91, v90) } -; sameln: function %icmp(i32, i32) system_v { +; sameln: function %icmp(i32, i32) fast { ; nextln: ebb0(v90: i32, v91: i32): ; nextln: v0 = icmp eq v90, v91 ; nextln: v1 = icmp ult v90, v91 @@ -101,7 +101,7 @@ ebb0(v90: f32, v91: f32): v1 = fcmp uno v90, v91 v2 = fcmp lt v90, v91 } -; sameln: function %fcmp(f32, f32) system_v { +; sameln: function %fcmp(f32, f32) fast { ; nextln: ebb0(v90: f32, v91: f32): ; nextln: v0 = fcmp eq v90, v91 ; nextln: v1 = fcmp uno v90, v91 @@ -115,7 +115,7 @@ ebb0(v90: i32, v91: f32): v0 = bitcast.i8x4 v90 v1 = bitcast.i32 v91 } -; sameln: function %bitcast(i32, f32) system_v { +; sameln: function %bitcast(i32, f32) fast { ; nextln: ebb0(v90: i32, v91: f32): ; nextln: v0 = bitcast.i8x4 v90 ; nextln: v1 = bitcast.i32 v91 @@ -135,7 +135,7 @@ ebb0: stack_store v1, ss10+2 stack_store v2, ss2 } -; sameln: function %stack() system_v { +; sameln: function %stack() fast { ; check: ss2 = explicit_slot 4 ; check: ss3 = incoming_arg 4, offset 8 ; check: ss4 = outgoing_arg 4 @@ -162,7 +162,7 @@ ebb0(v1: i32): store aligned v3, v1+12 store notrap aligned v3, v1-12 } -; sameln: function %memory(i32) system_v { +; sameln: function %memory(i32) fast { ; nextln: ebb0(v1: i32): ; nextln: v2 = load.i64 v1 ; nextln: v3 = load.i64 aligned v1 @@ -187,7 +187,7 @@ ebb0(v1: i32): regfill v1, ss0 -> %10 return } -; sameln: function %diversion(i32) system_v { +; sameln: function %diversion(i32) fast { ; nextln: ss0 = spill_slot 4 ; check: ebb0(v1: i32): ; nextln: regmove v1, %10 -> %20 @@ -204,7 +204,7 @@ ebb0: copy_special %20 -> %10 return } -; sameln: function %copy_special() system_v { +; sameln: function %copy_special() fast { ; nextln: ebb0: ; nextln: copy_special %10 -> %20 ; nextln: copy_special %20 -> %10 diff --git a/cranelift/filetests/regalloc/aliases.cton b/cranelift/filetests/regalloc/aliases.cton index 096ba99c2a..eb84c77f98 100644 --- a/cranelift/filetests/regalloc/aliases.cton +++ b/cranelift/filetests/regalloc/aliases.cton @@ -2,7 +2,7 @@ test regalloc set is_64bit isa x86 haswell -function %value_aliases(i32, f32, i64 vmctx) spiderwasm { +function %value_aliases(i32, f32, i64 vmctx) baldrdash { gv0 = vmctx heap0 = static gv0, min 0x0001_0000, bound 0x0001_0000_0000, guard 0x8000_0000 diff --git a/cranelift/filetests/regalloc/iterate.cton b/cranelift/filetests/regalloc/iterate.cton index acb97a31af..44e1265a96 100644 --- a/cranelift/filetests/regalloc/iterate.cton +++ b/cranelift/filetests/regalloc/iterate.cton @@ -2,7 +2,7 @@ test regalloc set is_64bit isa x86 haswell -function u0:9(i64 [%rdi], f32 [%xmm0], f64 [%xmm1], i32 [%rsi], i32 [%rdx], i64 vmctx [%r14]) -> i64 [%rax] spiderwasm { +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): v32 = iconst.i32 0 v6 = bitcast.f32 v32 @@ -104,9 +104,9 @@ ebb1(v31: i64): return v31 } -function u0:26(i64 vmctx [%r14]) -> i64 [%rax] spiderwasm { +function u0:26(i64 vmctx [%r14]) -> i64 [%rax] baldrdash { gv0 = vmctx+48 - sig0 = (i32 [%rdi], i64 [%rsi], i64 vmctx [%r14], i64 sigid [%rbx]) -> i64 [%rax] spiderwasm + sig0 = (i32 [%rdi], i64 [%rsi], i64 vmctx [%r14], i64 sigid [%rbx]) -> i64 [%rax] baldrdash ebb0(v0: i64): v1 = iconst.i32 32 diff --git a/cranelift/filetests/regalloc/unreachable_code.cton b/cranelift/filetests/regalloc/unreachable_code.cton index 4b4896f4a8..34d8c4c164 100644 --- a/cranelift/filetests/regalloc/unreachable_code.cton +++ b/cranelift/filetests/regalloc/unreachable_code.cton @@ -6,7 +6,7 @@ isa x86 haswell ; This function contains unreachable blocks which trip up the register ; allocator if they don't get cleared out. -function %unreachable_blocks(i64 vmctx) -> i32 spiderwasm { +function %unreachable_blocks(i64 vmctx) -> i32 baldrdash { ebb0(v0: i64): v1 = iconst.i32 0 v2 = iconst.i32 0 diff --git a/lib/codegen/meta/base/settings.py b/lib/codegen/meta/base/settings.py index ff1551c151..580f0ee33e 100644 --- a/lib/codegen/meta/base/settings.py +++ b/lib/codegen/meta/base/settings.py @@ -29,6 +29,21 @@ enable_verifier = BoolSetting( is_64bit = BoolSetting("Enable 64-bit code generation") +call_conv = EnumSetting( + """ + Default calling convention: + + - fast: not-ABI-stable convention for best performance + - cold: not-ABI-stable convention for infrequently executed code + - system_v: System V-style convention used on many platforms + - fastcall: Windows "fastcall" convention, also used for x64 and ARM + - baldrdash: SpiderMonkey WebAssembly convention + + The default calling convention may be overridden by individual + functions. + """, + 'fast', 'cold', 'system_v', 'fastcall', 'baldrdash') + # Note that Cretonne doesn't currently need an is_pie flag, because PIE is just # PIC where symbols can't be pre-empted, which can be expressed with the # `colocated` flag on external functions and global variables. @@ -75,13 +90,13 @@ enable_atomics = BoolSetting( default=True) # -# Settings specific to the `spiderwasm` calling convention. +# Settings specific to the `baldrdash` calling convention. # -spiderwasm_prologue_words = NumSetting( +baldrdash_prologue_words = NumSetting( """ - Number of pointer-sized words pushed by the spiderwasm prologue. + Number of pointer-sized words pushed by the baldrdash prologue. - Functions with the `spiderwasm` calling convention don't generate their + Functions with the `baldrdash` calling convention don't generate their own prologue and epilogue. They depend on externally generated code that pushes a fixed number of words in the prologue and restores them in the epilogue. diff --git a/lib/codegen/meta/gen_settings.py b/lib/codegen/meta/gen_settings.py index f111c6c415..5f760b88e5 100644 --- a/lib/codegen/meta/gen_settings.py +++ b/lib/codegen/meta/gen_settings.py @@ -19,6 +19,32 @@ except ImportError: pass +def gen_to_and_from_str(ty, values, fmt): + # type: (str, Tuple[str, ...], srcgen.Formatter) -> None + """ + Emit Display and FromStr implementations for enum settings. + """ + with fmt.indented('impl fmt::Display for {} {{'.format(ty), '}'): + with fmt.indented( + 'fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {', + '}'): + with fmt.indented('f.write_str(match *self {', '})'): + for v in values: + fmt.line('{}::{} => "{}",' + .format(ty, camel_case(v), v)) + + with fmt.indented('impl str::FromStr for {} {{'.format(ty), '}'): + fmt.line('type Err = ();') + with fmt.indented( + 'fn from_str(s: &str) -> result::Result {', + '}'): + with fmt.indented('match s {', '}'): + for v in values: + fmt.line('"{}" => Ok({}::{}),' + .format(v, ty, camel_case(v))) + fmt.line('_ => Err(()),') + + def gen_enum_types(sgrp, fmt): # type: (SettingGroup, srcgen.Formatter) -> None """ @@ -29,12 +55,14 @@ def gen_enum_types(sgrp, fmt): continue ty = camel_case(setting.name) fmt.doc_comment('Values for `{}`.'.format(setting)) - fmt.line('#[derive(Debug, Copy, Clone, PartialEq, Eq)]') + fmt.line('#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]') with fmt.indented('pub enum {} {{'.format(ty), '}'): for v in setting.values: fmt.doc_comment('`{}`.'.format(v)) fmt.line(camel_case(v) + ',') + gen_to_and_from_str(ty, setting.values, fmt) + def gen_getter(setting, sgrp, fmt): # type: (Setting, SettingGroup, srcgen.Formatter) -> None @@ -221,7 +249,7 @@ def gen_display(sgrp, fmt): with fmt.indented('if !d.detail.is_preset() {', '}'): fmt.line('write!(f, "{} = ", d.name)?;') fmt.line( - 'TEMPLATE.format_toml_value(d.detail,' + + 'TEMPLATE.format_toml_value(d.detail, ' + 'self.bytes[d.offset as usize], f)?;') fmt.line('writeln!(f)?;') fmt.line('Ok(())') diff --git a/lib/codegen/src/ir/extfunc.rs b/lib/codegen/src/ir/extfunc.rs index 01008946e6..540083321e 100644 --- a/lib/codegen/src/ir/extfunc.rs +++ b/lib/codegen/src/ir/extfunc.rs @@ -7,6 +7,7 @@ use ir::{ArgumentLoc, ExternalName, SigRef, Type}; use isa::{RegInfo, RegUnit}; +use settings::CallConv; use std::cmp; use std::fmt; use std::str::FromStr; @@ -342,47 +343,6 @@ impl fmt::Display for ExtFuncData { } } -/// A Calling convention. -/// -/// A function's calling convention determines exactly how arguments and return values are passed, -/// and how stack frames are managed. Since all of these details depend on both the instruction set -/// architecture and possibly the operating system, a function's calling convention is only fully -/// determined by a `(TargetIsa, CallConv)` tuple. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum CallConv { - /// The System V-style calling convention. - /// - /// This is the System V-style calling convention that a C compiler would - /// use on many platforms. - SystemV, - - /// A JIT-compiled WebAssembly function in the SpiderMonkey VM. - SpiderWASM, -} - -impl fmt::Display for CallConv { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::CallConv::*; - f.write_str(match *self { - SystemV => "system_v", - SpiderWASM => "spiderwasm", - }) - } -} - -impl FromStr for CallConv { - type Err = (); - - fn from_str(s: &str) -> Result { - use self::CallConv::*; - match s { - "system_v" => Ok(SystemV), - "spiderwasm" => Ok(SpiderWASM), - _ => Err(()), - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -418,23 +378,30 @@ mod tests { #[test] fn call_conv() { - for &cc in &[CallConv::SystemV, CallConv::SpiderWASM] { + for &cc in &[ + CallConv::Fast, + CallConv::Cold, + CallConv::SystemV, + CallConv::Fastcall, + CallConv::Baldrdash, + ] + { assert_eq!(Ok(cc), cc.to_string().parse()) } } #[test] fn signatures() { - let mut sig = Signature::new(CallConv::SpiderWASM); - assert_eq!(sig.to_string(), "() spiderwasm"); + let mut sig = Signature::new(CallConv::Baldrdash); + assert_eq!(sig.to_string(), "() baldrdash"); sig.params.push(AbiParam::new(I32)); - assert_eq!(sig.to_string(), "(i32) spiderwasm"); + assert_eq!(sig.to_string(), "(i32) baldrdash"); sig.returns.push(AbiParam::new(F32)); - assert_eq!(sig.to_string(), "(i32) -> f32 spiderwasm"); + assert_eq!(sig.to_string(), "(i32) -> f32 baldrdash"); sig.params.push(AbiParam::new(I32.by(4).unwrap())); - assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 spiderwasm"); + assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 baldrdash"); sig.returns.push(AbiParam::new(B8)); - assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8 spiderwasm"); + assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8 baldrdash"); // Test the offset computation algorithm. assert_eq!(sig.argument_bytes, None); @@ -450,7 +417,7 @@ mod tests { // Writing ABI-annotated signatures. assert_eq!( sig.to_string(), - "(i32 [24], i32x4 [8]) -> f32, b8 spiderwasm" + "(i32 [24], i32x4 [8]) -> f32, b8 baldrdash" ); } } diff --git a/lib/codegen/src/ir/function.rs b/lib/codegen/src/ir/function.rs index 5e70ff3780..10350c506c 100644 --- a/lib/codegen/src/ir/function.rs +++ b/lib/codegen/src/ir/function.rs @@ -6,11 +6,12 @@ use binemit::CodeOffset; use entity::{EntityMap, PrimaryMap}; use ir; -use ir::{CallConv, DataFlowGraph, ExternalName, Layout, Signature}; +use ir::{DataFlowGraph, ExternalName, Layout, Signature}; use ir::{Ebb, ExtFuncData, FuncRef, GlobalVar, GlobalVarData, Heap, HeapData, JumpTable, JumpTableData, SigRef, StackSlot, StackSlotData}; use ir::{EbbOffsets, InstEncodings, JumpTables, SourceLocs, StackSlots, ValueLocations}; use isa::{EncInfo, Legalize, TargetIsa, Encoding}; +use settings::CallConv; use std::fmt; use write::write_function; @@ -86,7 +87,7 @@ impl Function { /// Clear all data structures in this function. pub fn clear(&mut self) { - self.signature.clear(ir::CallConv::SystemV); + self.signature.clear(CallConv::Fast); self.stack_slots.clear(); self.global_vars.clear(); self.heaps.clear(); @@ -99,9 +100,9 @@ impl Function { self.srclocs.clear(); } - /// Create a new empty, anonymous function with a SystemV calling convention. + /// Create a new empty, anonymous function with a Fast calling convention. pub fn new() -> Self { - Self::with_name_signature(ExternalName::default(), Signature::new(CallConv::SystemV)) + Self::with_name_signature(ExternalName::default(), Signature::new(CallConv::Fast)) } /// Creates a jump table in the function, to be used by `br_table` instructions. diff --git a/lib/codegen/src/ir/mod.rs b/lib/codegen/src/ir/mod.rs index ed9771ccad..ab14a305aa 100644 --- a/lib/codegen/src/ir/mod.rs +++ b/lib/codegen/src/ir/mod.rs @@ -25,8 +25,7 @@ mod valueloc; pub use ir::builder::{InsertBuilder, InstBuilder, InstBuilderBase, InstInserterBase}; pub use ir::dfg::{DataFlowGraph, ValueDef}; pub use ir::entities::{Ebb, FuncRef, GlobalVar, Heap, Inst, JumpTable, SigRef, StackSlot, Value}; -pub use ir::extfunc::{AbiParam, ArgumentExtension, ArgumentPurpose, CallConv, ExtFuncData, - Signature}; +pub use ir::extfunc::{AbiParam, ArgumentExtension, ArgumentPurpose, ExtFuncData, Signature}; pub use ir::extname::ExternalName; pub use ir::function::Function; pub use ir::globalvar::GlobalVarData; diff --git a/lib/codegen/src/isa/mod.rs b/lib/codegen/src/isa/mod.rs index a8d8616858..ed626a60a2 100644 --- a/lib/codegen/src/isa/mod.rs +++ b/lib/codegen/src/isa/mod.rs @@ -52,6 +52,7 @@ use isa::enc_tables::Encodings; use regalloc; use result; use settings; +use settings::CallConv; use std::boxed::Box; use std::fmt; use timing; @@ -252,8 +253,8 @@ pub trait TargetIsa: fmt::Display { let word_size = if self.flags().is_64bit() { 8 } else { 4 }; // Account for the SpiderMonkey standard prologue pushes. - if func.signature.call_conv == ir::CallConv::SpiderWASM { - let bytes = StackSize::from(self.flags().spiderwasm_prologue_words()) * word_size; + if func.signature.call_conv == CallConv::Baldrdash { + let bytes = StackSize::from(self.flags().baldrdash_prologue_words()) * word_size; let mut ss = ir::StackSlotData::new(ir::StackSlotKind::IncomingArg, bytes); ss.offset = Some(-(bytes as StackOffset)); func.stack_slots.push(ss); diff --git a/lib/codegen/src/isa/x86/abi.rs b/lib/codegen/src/isa/x86/abi.rs index fe64aed5b1..0e4a43ee57 100644 --- a/lib/codegen/src/isa/x86/abi.rs +++ b/lib/codegen/src/isa/x86/abi.rs @@ -6,12 +6,12 @@ use cursor::{Cursor, CursorPosition, EncCursor}; use ir; use ir::immediates::Imm64; use ir::stackslot::{StackOffset, StackSize}; -use ir::{AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, CallConv, InstBuilder, - ValueLoc}; +use ir::{AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, InstBuilder, ValueLoc}; 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; @@ -74,7 +74,7 @@ impl ArgAssigner for Args { } // Handle special-purpose arguments. - if ty.is_int() && self.call_conv == CallConv::SpiderWASM { + if ty.is_int() && self.call_conv == CallConv::Baldrdash { match arg.purpose { // This is SpiderMonkey's `WasmTlsReg`. ArgumentPurpose::VMContext => { @@ -210,19 +210,20 @@ fn callee_saved_gprs_used(flags: &shared_settings::Flags, func: &ir::Function) - pub fn prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { match func.signature.call_conv { - ir::CallConv::SystemV => system_v_prologue_epilogue(func, isa), - ir::CallConv::SpiderWASM => spiderwasm_prologue_epilogue(func, isa), + // For now, just translate fast and cold as system_v. + CallConv::Fast | CallConv::Cold | CallConv::SystemV => { + system_v_prologue_epilogue(func, isa) + } + CallConv::Fastcall => unimplemented!("Windows calling conventions"), + CallConv::Baldrdash => baldrdash_prologue_epilogue(func, isa), } } -pub fn spiderwasm_prologue_epilogue( - func: &mut ir::Function, - isa: &TargetIsa, -) -> result::CtonResult { - // Spiderwasm on 32-bit x86 always aligns its stack pointer to 16 bytes. +pub fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { + // 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 bytes = StackSize::from(isa.flags().spiderwasm_prologue_words()) * word_size; + let bytes = StackSize::from(isa.flags().baldrdash_prologue_words()) * word_size; let mut ss = ir::StackSlotData::new(ir::StackSlotKind::IncomingArg, bytes); ss.offset = Some(-(bytes as StackOffset)); diff --git a/lib/codegen/src/legalizer/libcall.rs b/lib/codegen/src/legalizer/libcall.rs index 17f9174706..7d058f24bb 100644 --- a/lib/codegen/src/legalizer/libcall.rs +++ b/lib/codegen/src/legalizer/libcall.rs @@ -3,9 +3,10 @@ use ir; use ir::InstBuilder; use std::vec::Vec; +use isa::TargetIsa; /// Try to expand `inst` as a library call, returning true is successful. -pub fn expand_as_libcall(inst: ir::Inst, func: &mut ir::Function) -> bool { +pub fn expand_as_libcall(inst: ir::Inst, func: &mut ir::Function, isa: &TargetIsa) -> bool { // Does the opcode/ctrl_type combo even have a well-known runtime library name. let libcall = match ir::LibCall::for_inst(func.dfg[inst].opcode(), func.dfg.ctrl_typevar(inst)) { @@ -13,7 +14,8 @@ pub fn expand_as_libcall(inst: ir::Inst, func: &mut ir::Function) -> bool { None => return false, }; - let funcref = find_funcref(libcall, func).unwrap_or_else(|| make_funcref(libcall, inst, func)); + let funcref = + find_funcref(libcall, func).unwrap_or_else(|| make_funcref(libcall, inst, func, isa)); // Now we convert `inst` to a call. First save the arguments. let mut args = Vec::new(); @@ -44,9 +46,14 @@ fn find_funcref(libcall: ir::LibCall, func: &ir::Function) -> Option ir::FuncRef { - // Start with a system_v calling convention. We'll give the ISA a chance to change it. - let mut sig = ir::Signature::new(ir::CallConv::SystemV); +fn make_funcref( + libcall: ir::LibCall, + inst: ir::Inst, + func: &mut ir::Function, + isa: &TargetIsa, +) -> ir::FuncRef { + // Start with a fast calling convention. We'll give the ISA a chance to change it. + let mut sig = ir::Signature::new(isa.flags().call_conv()); for &v in func.dfg.inst_args(inst) { sig.params.push(ir::AbiParam::new(func.dfg.value_type(v))); } diff --git a/lib/codegen/src/legalizer/mod.rs b/lib/codegen/src/legalizer/mod.rs index f4f9389390..019b40c413 100644 --- a/lib/codegen/src/legalizer/mod.rs +++ b/lib/codegen/src/legalizer/mod.rs @@ -91,7 +91,7 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is // We don't have any pattern expansion for this instruction either. // Try converting it to a library call as a last resort. - if expand_as_libcall(inst, pos.func) { + if expand_as_libcall(inst, pos.func, isa) { pos.set_position(prev_pos); continue; } diff --git a/lib/codegen/src/settings.rs b/lib/codegen/src/settings.rs index f4edfc73cf..e34ee1421f 100644 --- a/lib/codegen/src/settings.rs +++ b/lib/codegen/src/settings.rs @@ -25,6 +25,7 @@ use isa::TargetIsa; use std::fmt; use std::result; use std::vec::Vec; +use std::str; /// A string-based configurator for settings groups. /// @@ -360,6 +361,7 @@ mod tests { opt_level = \"default\"\n\ enable_verifier = true\n\ is_64bit = false\n\ + call_conv = \"fast\"\n\ is_pic = false\n\ return_at_end = false\n\ avoid_div_traps = false\n\ @@ -367,12 +369,12 @@ mod tests { enable_float = true\n\ enable_simd = true\n\ enable_atomics = true\n\ - spiderwasm_prologue_words = 0\n\ + baldrdash_prologue_words = 0\n\ allones_funcaddrs = false\n" ); assert_eq!(f.opt_level(), super::OptLevel::Default); assert_eq!(f.enable_simd(), true); - assert_eq!(f.spiderwasm_prologue_words(), 0); + assert_eq!(f.baldrdash_prologue_words(), 0); } #[test] diff --git a/lib/codegen/src/write.rs b/lib/codegen/src/write.rs index a8f12d024f..b3887949c2 100644 --- a/lib/codegen/src/write.rs +++ b/lib/codegen/src/write.rs @@ -459,34 +459,34 @@ mod tests { #[test] fn basic() { let mut f = Function::new(); - assert_eq!(f.to_string(), "function u0:0() system_v {\n}\n"); + assert_eq!(f.to_string(), "function u0:0() fast {\n}\n"); f.name = ExternalName::testcase("foo"); - assert_eq!(f.to_string(), "function %foo() system_v {\n}\n"); + assert_eq!(f.to_string(), "function %foo() fast {\n}\n"); f.create_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, 4)); assert_eq!( f.to_string(), - "function %foo() system_v {\n ss0 = explicit_slot 4\n}\n" + "function %foo() fast {\n ss0 = explicit_slot 4\n}\n" ); let ebb = f.dfg.make_ebb(); f.layout.append_ebb(ebb); assert_eq!( f.to_string(), - "function %foo() system_v {\n ss0 = explicit_slot 4\n\nebb0:\n}\n" + "function %foo() fast {\n ss0 = explicit_slot 4\n\nebb0:\n}\n" ); f.dfg.append_ebb_param(ebb, types::I8); assert_eq!( f.to_string(), - "function %foo() system_v {\n ss0 = explicit_slot 4\n\nebb0(v0: i8):\n}\n" + "function %foo() fast {\n ss0 = explicit_slot 4\n\nebb0(v0: i8):\n}\n" ); f.dfg.append_ebb_param(ebb, types::F32.by(4).unwrap()); assert_eq!( f.to_string(), - "function %foo() system_v {\n ss0 = explicit_slot 4\n\nebb0(v0: i8, v1: f32x4):\n}\n" + "function %foo() fast {\n ss0 = explicit_slot 4\n\nebb0(v0: i8, v1: f32x4):\n}\n" ); } } diff --git a/lib/faerie/src/backend.rs b/lib/faerie/src/backend.rs index 55af088295..4835156637 100644 --- a/lib/faerie/src/backend.rs +++ b/lib/faerie/src/backend.rs @@ -23,6 +23,10 @@ impl FaerieBuilder { /// Create a new `FaerieBuilder` using the given Cretonne target, that /// can be passed to /// [`Module::new`](cretonne_module/struct.Module.html#method.new]. + /// + /// Note: To support calls JIT'd functions from Rust or other compiled + /// code, it's necessary for the `call_conv` setting in `isa`'s flags + /// to match the host platform. pub fn new( isa: Box, name: String, diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 70d2d43820..1f2c818f99 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -596,8 +596,9 @@ mod tests { use Variable; use cretonne_codegen::entity::EntityRef; use cretonne_codegen::ir::types::*; - use cretonne_codegen::ir::{AbiParam, CallConv, ExternalName, Function, InstBuilder, Signature}; + use cretonne_codegen::ir::{AbiParam, ExternalName, Function, InstBuilder, Signature}; use cretonne_codegen::settings; + use cretonne_codegen::settings::CallConv; use cretonne_codegen::verifier::verify_function; use frontend::{FunctionBuilder, FunctionBuilderContext}; diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index 494fecb414..65d76fd279 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -36,9 +36,9 @@ //! extern crate cretonne_frontend; //! //! use cretonne_codegen::entity::EntityRef; -//! use cretonne_codegen::ir::{ExternalName, CallConv, Function, Signature, AbiParam, InstBuilder}; +//! use cretonne_codegen::ir::{ExternalName, Function, Signature, AbiParam, InstBuilder}; //! use cretonne_codegen::ir::types::*; -//! use cretonne_codegen::settings; +//! use cretonne_codegen::settings::{self, CallConv}; //! use cretonne_frontend::{FunctionBuilderContext, FunctionBuilder, Variable}; //! use cretonne_codegen::verifier::verify_function; //! diff --git a/lib/native/src/lib.rs b/lib/native/src/lib.rs index e84be550e2..ff3d0632c2 100644 --- a/lib/native/src/lib.rs +++ b/lib/native/src/lib.rs @@ -34,12 +34,21 @@ use raw_cpuid::CpuId; pub fn builders() -> Result<(settings::Builder, isa::Builder), &'static str> { let mut flag_builder = settings::builder(); - // TODO: Add RISC-V support once Rust supports it. + if cfg!(unix) { + flag_builder.set("call_conv", "system_v").unwrap(); + } else if cfg!(windows) { + flag_builder.set("call_conv", "fastcall").unwrap(); + } else { + 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") { diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index e96e415afc..8ee584075c 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -6,7 +6,7 @@ use cretonne_codegen::ir::entities::AnyEntity; use cretonne_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32}; use cretonne_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs}; use cretonne_codegen::ir::types::VOID; -use cretonne_codegen::ir::{AbiParam, ArgumentExtension, ArgumentLoc, CallConv, Ebb, ExtFuncData, +use cretonne_codegen::ir::{AbiParam, ArgumentExtension, ArgumentLoc, Ebb, ExtFuncData, ExternalName, FuncRef, Function, GlobalVar, GlobalVarData, Heap, HeapBase, HeapData, HeapStyle, JumpTable, JumpTableData, MemFlags, Opcode, SigRef, Signature, StackSlot, StackSlotData, StackSlotKind, @@ -14,6 +14,7 @@ use cretonne_codegen::ir::{AbiParam, ArgumentExtension, ArgumentLoc, CallConv, E use cretonne_codegen::isa::{self, Encoding, RegUnit, TargetIsa}; use cretonne_codegen::packed_option::ReservedValue; use cretonne_codegen::{settings, timing}; +use cretonne_codegen::settings::CallConv; use error::{Error, Location, Result}; use isaspec; use lexer::{self, Lexer, Token}; @@ -188,7 +189,7 @@ impl<'a> Context<'a> { fn add_sig(&mut self, sig: SigRef, data: Signature, loc: &Location) -> Result<()> { while self.function.dfg.signatures.next_key().index() <= sig.index() { self.function.import_signature( - Signature::new(CallConv::SystemV), + Signature::new(CallConv::Fast), ); } self.function.dfg.signatures[sig] = data; @@ -862,8 +863,8 @@ impl<'a> Parser<'a> { // signature ::= * "(" [paramlist] ")" ["->" retlist] [callconv] // fn parse_signature(&mut self, unique_isa: Option<&TargetIsa>) -> Result { - // Calling convention defaults to `system_v`, but can be changed. - let mut sig = Signature::new(CallConv::SystemV); + // Calling convention defaults to `fast`, but can be changed. + let mut sig = Signature::new(CallConv::Fast); self.match_token( Token::LPar, @@ -2402,7 +2403,8 @@ mod tests { use cretonne_codegen::ir::StackSlotKind; use cretonne_codegen::ir::entities::AnyEntity; use cretonne_codegen::ir::types; - use cretonne_codegen::ir::{ArgumentExtension, ArgumentPurpose, CallConv}; + use cretonne_codegen::ir::{ArgumentExtension, ArgumentPurpose}; + use cretonne_codegen::settings::CallConv; use error::Error; use isaspec::IsaSpec; use testfile::{Comment, Details}; @@ -2451,19 +2453,19 @@ mod tests { assert_eq!(sig.returns.len(), 0); assert_eq!(sig.call_conv, CallConv::SystemV); - let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 spiderwasm") + let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 baldrdash") .parse_signature(None) .unwrap(); assert_eq!( sig2.to_string(), - "(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 spiderwasm" + "(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 baldrdash" ); - assert_eq!(sig2.call_conv, CallConv::SpiderWASM); + assert_eq!(sig2.call_conv, CallConv::Baldrdash); // Old-style signature without a calling convention. assert_eq!( Parser::new("()").parse_signature(None).unwrap().to_string(), - "() system_v" + "() fast" ); assert_eq!( Parser::new("() notacc") diff --git a/lib/umbrella/src/lib.rs b/lib/umbrella/src/lib.rs index de89cd5788..f28fb45547 100644 --- a/lib/umbrella/src/lib.rs +++ b/lib/umbrella/src/lib.rs @@ -25,12 +25,12 @@ pub extern crate cretonne_frontend as frontend; pub mod prelude { pub use codegen; pub use codegen::entity::EntityRef; - pub use codegen::ir::{AbiParam, InstBuilder, Value, Ebb, Signature, CallConv, Type, - JumpTableData, MemFlags}; + pub use codegen::ir::{AbiParam, InstBuilder, Value, Ebb, Signature, Type, JumpTableData, + MemFlags}; pub use codegen::ir::types; pub use codegen::ir::condcodes::{IntCC, FloatCC}; pub use codegen::ir::immediates::{Ieee32, Ieee64}; - pub use codegen::settings::{self, Configurable}; + pub use codegen::settings::{self, Configurable, CallConv}; pub use codegen::isa; pub use frontend::{FunctionBuilderContext, FunctionBuilder, Variable}; diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index e04bd5f180..2b1fbfbfc7 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -271,6 +271,10 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ } impl<'data> ModuleEnvironment<'data> for DummyEnvironment { + fn flags(&self) -> &settings::Flags { + &self.info.flags + } + fn get_func_name(&self, func_index: FunctionIndex) -> ir::ExternalName { get_func_name(func_index) } diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 51aba3fd7e..cc9e4eb771 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -160,6 +160,9 @@ pub trait FuncEnvironment { /// [`translate_module`](fn.translate_module.html) function. These methods should not be called /// by the user, they are only for `cretonne-wasm` internal use. pub trait ModuleEnvironment<'data> { + /// Get the flags for the current compilation. + fn flags(&self) -> &Flags; + /// Return the name for the given function index. fn get_func_name(&self, func_index: FunctionIndex) -> ir::ExternalName; diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index c243348d5a..a9ca07a8df 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -7,7 +7,7 @@ //! The special case of the initialize expressions for table elements offsets or global variables //! is handled, according to the semantics of WebAssembly, to only specific expressions that are //! interpreted on the fly. -use cretonne_codegen::ir::{self, AbiParam, CallConv, Signature}; +use cretonne_codegen::ir::{self, AbiParam, Signature}; use environ::ModuleEnvironment; use std::str::from_utf8; use std::string::String; @@ -35,7 +35,7 @@ pub fn parse_function_signatures( ref params, ref returns, }) => { - let mut sig = Signature::new(CallConv::SystemV); + let mut sig = Signature::new(environ.flags().call_conv()); sig.params.extend(params.iter().map(|ty| { let cret_arg: ir::Type = type_to_type(ty).expect( "only numeric types are supported in function signatures",