Skip to content

Commit b1421de

Browse files
committed
Support inline asm on AArch64
Also stop changing the frame pointer on x86_64. This confuses unwinders.
1 parent a47b9fd commit b1421de

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed

example/mini_core.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,12 @@ pub macro cfg() {
683683
/* compiler built-in */
684684
}
685685

686+
#[rustc_builtin_macro]
687+
#[rustc_macro_transparency = "semitransparent"]
688+
pub macro asm() {
689+
/* compiler built-in */
690+
}
691+
686692
#[rustc_builtin_macro]
687693
#[rustc_macro_transparency = "semitransparent"]
688694
pub macro global_asm() {

src/global_asm.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,22 @@ use std::sync::Arc;
99
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1010
use rustc_hir::{InlineAsmOperand, ItemId};
1111
use rustc_session::config::{OutputFilenames, OutputType};
12+
use rustc_target::asm::InlineAsmArch;
1213

1314
use crate::prelude::*;
1415

1516
pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
1617
let item = tcx.hir().item(item_id);
1718
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
18-
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
19-
global_asm.push_str("\n.intel_syntax noprefix\n");
20-
} else {
21-
global_asm.push_str("\n.att_syntax\n");
19+
let is_x86 =
20+
matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
21+
22+
if is_x86 {
23+
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
24+
global_asm.push_str("\n.intel_syntax noprefix\n");
25+
} else {
26+
global_asm.push_str("\n.att_syntax\n");
27+
}
2228
}
2329
for piece in asm.template {
2430
match *piece {
@@ -65,7 +71,11 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
6571
}
6672
}
6773
}
68-
global_asm.push_str("\n.att_syntax\n\n");
74+
75+
global_asm.push('\n');
76+
if is_x86 {
77+
global_asm.push_str(".att_syntax\n\n");
78+
}
6979
} else {
7080
bug!("Expected GlobalAsm found {:?}", item);
7181
}
@@ -115,11 +125,12 @@ pub(crate) fn compile_global_asm(
115125
}
116126

117127
// Remove all LLVM style comments
118-
let global_asm = global_asm
128+
let mut global_asm = global_asm
119129
.lines()
120130
.map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
121131
.collect::<Vec<_>>()
122132
.join("\n");
133+
global_asm.push('\n');
123134

124135
let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
125136

src/inline_asm.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -701,21 +701,32 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
701701
match arch {
702702
InlineAsmArch::X86_64 => {
703703
generated_asm.push_str(" push rbp\n");
704-
generated_asm.push_str(" mov rbp,rdi\n");
704+
generated_asm.push_str(" mov rbp,rsp\n");
705+
generated_asm.push_str(" push rbx\n"); // rbx is callee saved
706+
// rbx is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
707+
generated_asm.push_str(" mov rbx,rdi\n");
705708
}
706709
InlineAsmArch::RiscV64 => {
707710
generated_asm.push_str(" addi sp, sp, -16\n");
708711
generated_asm.push_str(" sd ra, 8(sp)\n");
709712
generated_asm.push_str(" sd s0, 0(sp)\n");
710713
generated_asm.push_str(" mv s0, a0\n");
711714
}
715+
InlineAsmArch::AArch64 => {
716+
generated_asm.push_str(" stp fp, lr, [sp, #-32]!\n");
717+
generated_asm.push_str(" mov fp, sp\n");
718+
generated_asm.push_str(" str x19, [sp, #24]\n"); // x19 is callee saved
719+
// x19 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
720+
generated_asm.push_str(" mov x19, x0\n");
721+
}
712722
_ => unimplemented!("prologue for {:?}", arch),
713723
}
714724
}
715725

716726
fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) {
717727
match arch {
718728
InlineAsmArch::X86_64 => {
729+
generated_asm.push_str(" pop rbx\n");
719730
generated_asm.push_str(" pop rbp\n");
720731
generated_asm.push_str(" ret\n");
721732
}
@@ -725,6 +736,11 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
725736
generated_asm.push_str(" addi sp, sp, 16\n");
726737
generated_asm.push_str(" ret\n");
727738
}
739+
InlineAsmArch::AArch64 => {
740+
generated_asm.push_str(" ldr x19, [sp, #24]\n");
741+
generated_asm.push_str(" ldp fp, lr, [sp], #32\n");
742+
generated_asm.push_str(" ret\n");
743+
}
728744
_ => unimplemented!("epilogue for {:?}", arch),
729745
}
730746
}
@@ -737,6 +753,9 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
737753
InlineAsmArch::RiscV64 => {
738754
generated_asm.push_str(" ebreak\n");
739755
}
756+
InlineAsmArch::AArch64 => {
757+
generated_asm.push_str(" brk #0x1");
758+
}
740759
_ => unimplemented!("epilogue_noreturn for {:?}", arch),
741760
}
742761
}
@@ -749,7 +768,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
749768
) {
750769
match arch {
751770
InlineAsmArch::X86_64 => {
752-
write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap();
771+
write!(generated_asm, " mov [rbx+0x{:x}], ", offset.bytes()).unwrap();
753772
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
754773
generated_asm.push('\n');
755774
}
@@ -758,6 +777,11 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
758777
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
759778
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
760779
}
780+
InlineAsmArch::AArch64 => {
781+
generated_asm.push_str(" str ");
782+
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
783+
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
784+
}
761785
_ => unimplemented!("save_register for {:?}", arch),
762786
}
763787
}
@@ -772,13 +796,18 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
772796
InlineAsmArch::X86_64 => {
773797
generated_asm.push_str(" mov ");
774798
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
775-
writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap();
799+
writeln!(generated_asm, ", [rbx+0x{:x}]", offset.bytes()).unwrap();
776800
}
777801
InlineAsmArch::RiscV64 => {
778802
generated_asm.push_str(" ld ");
779803
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
780804
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
781805
}
806+
InlineAsmArch::AArch64 => {
807+
generated_asm.push_str(" ldr ");
808+
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
809+
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
810+
}
782811
_ => unimplemented!("restore_register for {:?}", arch),
783812
}
784813
}

0 commit comments

Comments
 (0)