winch: Use aarch64 backend for code emission. (#5652)

This patch introduces basic aarch64 code generation by using
`cranelift-codegen`'s backend.

This commit *does not*:

* Change the semantics of the code generation
* Adds support for other Wasm instructions

The most notable change in this patch is how addressing modes are handled at the
MacroAssembler layer: instead of having a canonical address representation, this
patch introduces the addressing mode as an associated type in the
MacroAssembler trait. This approach has the advantage that gives each ISA enough
flexiblity to describe the addressing modes and their constraints in isolation
without having to worry on how a particular addressing mode is going to affect
other ISAs. In the case of Aarch64 this becomes useful to describe indexed
addressing modes (particularly from the stack pointer).

This patch uses the concept of a shadow stack pointer (x28) as a workaround to
Aarch64's stack pointer 16-byte alignment. This constraint is enforced by:

* Introducing specialized addressing modes when using the real stack pointer; this
enables auditing when the real stack pointer is used. As of this change, the
real stack pointer is only used in the function's prologue and epilogue.

* Asserting that the real stack pointer is not used as a base for addressing
modes.

* Ensuring that at any point during the code generation process where the stack
pointer changes (e.g. when stack space is allocated / deallocated) the value of
the real stack pointer is copied into the shadow stack pointer.
This commit is contained in:
Saúl Cabrera
2023-02-02 17:24:11 -05:00
committed by GitHub
parent a2a0a9ef5b
commit 426c49b8e3
18 changed files with 840 additions and 65 deletions

View File

@@ -0,0 +1,18 @@
;;! target = "aarch64"
(module
(export "main" (func $main))
(func $main (result i32)
(i32.const 10)
(i32.const 20)
i32.add)
)
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 500180d2 mov x16, #0xa
;; 10: e003102a mov w0, w16
;; 14: 00500011 add w0, w0, #0x14
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret

View File

@@ -0,0 +1,38 @@
;;! target = "aarch64"
(module
(export "main" (func $main))
(func $main (result i32)
(local $foo i32)
(local $bar i32)
(i32.const 10)
(local.set $foo)
(i32.const 20)
(local.set $bar)
(local.get $foo)
(local.get $bar)
i32.add)
)
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 100080d2 mov x16, #0
;; 18: 900300f8 stur x16, [x28]
;; 1c: 500180d2 mov x16, #0xa
;; 20: e003102a mov w0, w16
;; 24: 804300b8 stur w0, [x28, #4]
;; 28: 900280d2 mov x16, #0x14
;; 2c: e003102a mov w0, w16
;; 30: 800300b8 stur w0, [x28]
;; 34: 800340b8 ldur w0, [x28]
;; 38: 814340b8 ldur w1, [x28, #4]
;; 3c: 2160200b add w1, w1, w0, uxtx
;; 40: e00301aa mov x0, x1
;; 44: ff230091 add sp, sp, #8
;; 48: fc030091 mov x28, sp
;; 4c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 50: c0035fd6 ret

View File

@@ -0,0 +1,25 @@
;;! target = "aarch64"
(module
(export "main" (func $main))
(func $main (param i32) (param i32) (result i32)
(local.get 0)
(local.get 1)
i32.add)
)
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 804300b8 stur w0, [x28, #4]
;; 18: 810300b8 stur w1, [x28]
;; 1c: 800340b8 ldur w0, [x28]
;; 20: 814340b8 ldur w1, [x28, #4]
;; 24: 2160200b add w1, w1, w0, uxtx
;; 28: e00301aa mov x0, x1
;; 2c: ff230091 add sp, sp, #8
;; 30: fc030091 mov x28, sp
;; 34: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 38: c0035fd6 ret

View File

@@ -0,0 +1,15 @@
;;! target = "aarch64"
(module
(func (result i32)
(i32.const 42)
)
)
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 500580d2 mov x16, #0x2a
;; 10: e00310aa mov x0, x16
;; 14: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 18: c0035fd6 ret

View File

@@ -52,6 +52,18 @@ fn disassembler_for(isa: &dyn TargetIsa) -> Result<Capstone> {
.build()
.map_err(|e| anyhow::format_err!("{}", e))?,
Architecture::Aarch64 { .. } => {
let mut cs = Capstone::new()
.arm64()
.mode(arch::arm64::ArchMode::Arm)
.build()
.map_err(|e| anyhow::format_err!("{}", e))?;
cs.set_skipdata(true)
.map_err(|e| anyhow::format_err!("{}", e))?;
cs
}
_ => bail!("Unsupported ISA"),
};