Support inline asm on AArch64
Also stop changing the frame pointer on x86_64. This confuses unwinders.
This commit is contained in:
parent
a47b9fd2e6
commit
b1421dea1d
@ -683,6 +683,12 @@ fn index(&self, index: usize) -> &Self::Output {
|
|||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
|
pub macro asm() {
|
||||||
|
/* compiler built-in */
|
||||||
|
}
|
||||||
|
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[rustc_macro_transparency = "semitransparent"]
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
pub macro global_asm() {
|
pub macro global_asm() {
|
||||||
|
@ -9,17 +9,23 @@
|
|||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_hir::{InlineAsmOperand, ItemId};
|
use rustc_hir::{InlineAsmOperand, ItemId};
|
||||||
use rustc_session::config::{OutputFilenames, OutputType};
|
use rustc_session::config::{OutputFilenames, OutputType};
|
||||||
|
use rustc_target::asm::InlineAsmArch;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
|
pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
|
||||||
let item = tcx.hir().item(item_id);
|
let item = tcx.hir().item(item_id);
|
||||||
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
|
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
|
||||||
|
let is_x86 =
|
||||||
|
matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
|
||||||
|
|
||||||
|
if is_x86 {
|
||||||
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
|
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
|
||||||
global_asm.push_str("\n.intel_syntax noprefix\n");
|
global_asm.push_str("\n.intel_syntax noprefix\n");
|
||||||
} else {
|
} else {
|
||||||
global_asm.push_str("\n.att_syntax\n");
|
global_asm.push_str("\n.att_syntax\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for piece in asm.template {
|
for piece in asm.template {
|
||||||
match *piece {
|
match *piece {
|
||||||
InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
|
InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
|
||||||
@ -65,7 +71,11 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
global_asm.push_str("\n.att_syntax\n\n");
|
|
||||||
|
global_asm.push('\n');
|
||||||
|
if is_x86 {
|
||||||
|
global_asm.push_str(".att_syntax\n\n");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bug!("Expected GlobalAsm found {:?}", item);
|
bug!("Expected GlobalAsm found {:?}", item);
|
||||||
}
|
}
|
||||||
@ -115,11 +125,12 @@ pub(crate) fn compile_global_asm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove all LLVM style comments
|
// Remove all LLVM style comments
|
||||||
let global_asm = global_asm
|
let mut global_asm = global_asm
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
|
.map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
global_asm.push('\n');
|
||||||
|
|
||||||
let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
|
let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
|
||||||
|
|
||||||
|
@ -701,7 +701,10 @@ fn prologue(generated_asm: &mut String, arch: InlineAsmArch) {
|
|||||||
match arch {
|
match arch {
|
||||||
InlineAsmArch::X86_64 => {
|
InlineAsmArch::X86_64 => {
|
||||||
generated_asm.push_str(" push rbp\n");
|
generated_asm.push_str(" push rbp\n");
|
||||||
generated_asm.push_str(" mov rbp,rdi\n");
|
generated_asm.push_str(" mov rbp,rsp\n");
|
||||||
|
generated_asm.push_str(" push rbx\n"); // rbx is callee saved
|
||||||
|
// rbx is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
|
||||||
|
generated_asm.push_str(" mov rbx,rdi\n");
|
||||||
}
|
}
|
||||||
InlineAsmArch::RiscV64 => {
|
InlineAsmArch::RiscV64 => {
|
||||||
generated_asm.push_str(" addi sp, sp, -16\n");
|
generated_asm.push_str(" addi sp, sp, -16\n");
|
||||||
@ -709,6 +712,13 @@ fn prologue(generated_asm: &mut String, arch: InlineAsmArch) {
|
|||||||
generated_asm.push_str(" sd s0, 0(sp)\n");
|
generated_asm.push_str(" sd s0, 0(sp)\n");
|
||||||
generated_asm.push_str(" mv s0, a0\n");
|
generated_asm.push_str(" mv s0, a0\n");
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::AArch64 => {
|
||||||
|
generated_asm.push_str(" stp fp, lr, [sp, #-32]!\n");
|
||||||
|
generated_asm.push_str(" mov fp, sp\n");
|
||||||
|
generated_asm.push_str(" str x19, [sp, #24]\n"); // x19 is callee saved
|
||||||
|
// x19 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
|
||||||
|
generated_asm.push_str(" mov x19, x0\n");
|
||||||
|
}
|
||||||
_ => unimplemented!("prologue for {:?}", arch),
|
_ => unimplemented!("prologue for {:?}", arch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -716,6 +726,7 @@ fn prologue(generated_asm: &mut String, arch: InlineAsmArch) {
|
|||||||
fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) {
|
fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) {
|
||||||
match arch {
|
match arch {
|
||||||
InlineAsmArch::X86_64 => {
|
InlineAsmArch::X86_64 => {
|
||||||
|
generated_asm.push_str(" pop rbx\n");
|
||||||
generated_asm.push_str(" pop rbp\n");
|
generated_asm.push_str(" pop rbp\n");
|
||||||
generated_asm.push_str(" ret\n");
|
generated_asm.push_str(" ret\n");
|
||||||
}
|
}
|
||||||
@ -725,6 +736,11 @@ fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) {
|
|||||||
generated_asm.push_str(" addi sp, sp, 16\n");
|
generated_asm.push_str(" addi sp, sp, 16\n");
|
||||||
generated_asm.push_str(" ret\n");
|
generated_asm.push_str(" ret\n");
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::AArch64 => {
|
||||||
|
generated_asm.push_str(" ldr x19, [sp, #24]\n");
|
||||||
|
generated_asm.push_str(" ldp fp, lr, [sp], #32\n");
|
||||||
|
generated_asm.push_str(" ret\n");
|
||||||
|
}
|
||||||
_ => unimplemented!("epilogue for {:?}", arch),
|
_ => unimplemented!("epilogue for {:?}", arch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -737,6 +753,9 @@ fn epilogue_noreturn(generated_asm: &mut String, arch: InlineAsmArch) {
|
|||||||
InlineAsmArch::RiscV64 => {
|
InlineAsmArch::RiscV64 => {
|
||||||
generated_asm.push_str(" ebreak\n");
|
generated_asm.push_str(" ebreak\n");
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::AArch64 => {
|
||||||
|
generated_asm.push_str(" brk #0x1");
|
||||||
|
}
|
||||||
_ => unimplemented!("epilogue_noreturn for {:?}", arch),
|
_ => unimplemented!("epilogue_noreturn for {:?}", arch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -749,7 +768,7 @@ fn save_register(
|
|||||||
) {
|
) {
|
||||||
match arch {
|
match arch {
|
||||||
InlineAsmArch::X86_64 => {
|
InlineAsmArch::X86_64 => {
|
||||||
write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap();
|
write!(generated_asm, " mov [rbx+0x{:x}], ", offset.bytes()).unwrap();
|
||||||
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
|
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
|
||||||
generated_asm.push('\n');
|
generated_asm.push('\n');
|
||||||
}
|
}
|
||||||
@ -758,6 +777,11 @@ fn save_register(
|
|||||||
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
|
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
|
||||||
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
|
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::AArch64 => {
|
||||||
|
generated_asm.push_str(" str ");
|
||||||
|
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
|
||||||
|
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
|
||||||
|
}
|
||||||
_ => unimplemented!("save_register for {:?}", arch),
|
_ => unimplemented!("save_register for {:?}", arch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -772,13 +796,18 @@ fn restore_register(
|
|||||||
InlineAsmArch::X86_64 => {
|
InlineAsmArch::X86_64 => {
|
||||||
generated_asm.push_str(" mov ");
|
generated_asm.push_str(" mov ");
|
||||||
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
|
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
|
||||||
writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap();
|
writeln!(generated_asm, ", [rbx+0x{:x}]", offset.bytes()).unwrap();
|
||||||
}
|
}
|
||||||
InlineAsmArch::RiscV64 => {
|
InlineAsmArch::RiscV64 => {
|
||||||
generated_asm.push_str(" ld ");
|
generated_asm.push_str(" ld ");
|
||||||
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
|
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
|
||||||
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
|
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::AArch64 => {
|
||||||
|
generated_asm.push_str(" ldr ");
|
||||||
|
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
|
||||||
|
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
|
||||||
|
}
|
||||||
_ => unimplemented!("restore_register for {:?}", arch),
|
_ => unimplemented!("restore_register for {:?}", arch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user