Skip to content

Commit

Permalink
correctly emit .hidden
Browse files Browse the repository at this point in the history
  • Loading branch information
folkertdev committed Jul 26, 2024
1 parent 878810f commit c54e5c1
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 25 deletions.
72 changes: 54 additions & 18 deletions compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::common;
use crate::mir::FunctionCx;
use crate::traits::{AsmMethods, BuilderMethods, GlobalAsmOperandRef};
use crate::traits::{AsmMethods, BuilderMethods, GlobalAsmOperandRef, MiscMethods};
use rustc_attr::InstructionSetAttr;
use rustc_middle::bug;
use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
use rustc_middle::mir::InlineAsmOperand;
use rustc_middle::ty;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
Expand Down Expand Up @@ -29,7 +31,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let operands: Vec<_> =
operands.iter().map(|op| self.inline_to_global_operand(op)).collect();

let (begin, end) = crate::mir::naked_asm::prefix_and_suffix(cx.tcx(), instance);
let item_data = cx.codegen_unit().items().get(&MonoItem::Fn(instance)).unwrap();
let (begin, end) = crate::mir::naked_asm::prefix_and_suffix(cx.tcx(), instance, item_data);

let mut template_vec = Vec::new();
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(begin));
Expand Down Expand Up @@ -90,7 +93,33 @@ impl AsmBinaryFormat {
}
}

fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (String, String) {
fn linkage_directive(linkage: Linkage) -> Option<&'static str> {
if true {
// this is required. emitting nothing or .weak will emit
//
// > Global is external, but doesn't have external or weak linkage!
//
// and then aborts compilation
return Some(".globl");
}

match linkage {
Linkage::External => Some(".globl"),
Linkage::WeakAny | Linkage::WeakODR => Some(".weak"),
Linkage::LinkOnceAny | Linkage::LinkOnceODR => Some(".weak"),
Linkage::Internal | Linkage::Private => None, // just doesn't emit any attribute
Linkage::ExternalWeak => None, // terminates with sigill on godbolt
Linkage::AvailableExternally => None, // does not even emit the definition
Linkage::Appending => None, // only valid on global variables
Linkage::Common => None, // function may not have common linkage
}
}

fn prefix_and_suffix<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
item_data: &MonoItemData,
) -> (String, String) {
use std::fmt::Write;

let target = &tcx.sess.target;
Expand All @@ -109,19 +138,16 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
.and_then(|attr| attr.value_str())
.map(|attr| attr.as_str().to_string());

let instruction_set =
tcx.get_attr(instance.def.def_id(), sym::instruction_set).and_then(|attr| attr.value_str());

let attrs = tcx.codegen_fn_attrs(instance.def_id());
let (arch_prefix, arch_suffix) = if is_arm {
(
match instruction_set {
match attrs.instruction_set {
None => match is_thumb {
true => ".thumb\n.thumb_func",
false => ".arm",
},
Some(sym::a32) => ".arm",
Some(sym::t32) => ".thumb\n.thumb_func",
Some(other) => bug!("invalid instruction set: {other}"),
Some(InstructionSetAttr::ArmA32) => ".arm",
Some(InstructionSetAttr::ArmT32) => ".thumb\n.thumb_func",
},
match is_thumb {
true => ".thumb",
Expand Down Expand Up @@ -150,10 +176,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri

writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap();
writeln!(begin, ".balign 4").unwrap();
writeln!(begin, ".globl {asm_name}").unwrap();
writeln!(begin, ".hidden {asm_name}").unwrap();
if let Some(linkage) = linkage_directive(item_data.linkage) {
writeln!(begin, "{linkage} {asm_name}").unwrap();
}
if let Visibility::Hidden = item_data.visibility {
writeln!(begin, ".hidden {asm_name}").unwrap();
}
writeln!(begin, ".type {asm_name}, {function}").unwrap();
if let Some(instruction_set) = instruction_set {
if let Some(instruction_set) = attrs.instruction_set {
writeln!(begin, "{}", instruction_set.as_str()).unwrap();
}
if !arch_prefix.is_empty() {
Expand All @@ -172,9 +202,13 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
let section = opt_section.unwrap_or("__TEXT,__text".to_string());
writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap();
writeln!(begin, ".balign 4").unwrap();
writeln!(begin, ".globl {asm_name}").unwrap();
writeln!(begin, ".private_extern {asm_name}").unwrap();
if let Some(instruction_set) = instruction_set {
if let Some(linkage) = linkage_directive(item_data.linkage) {
writeln!(begin, "{linkage} {asm_name}").unwrap();
}
if let Visibility::Hidden = item_data.visibility {
writeln!(begin, ".private_extern {asm_name}").unwrap();
}
if let Some(instruction_set) = attrs.instruction_set {
writeln!(begin, "{}", instruction_set.as_str()).unwrap();
}
writeln!(begin, "{asm_name}:").unwrap();
Expand All @@ -189,12 +223,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
let section = opt_section.unwrap_or(format!(".text.{asm_name}"));
writeln!(begin, ".pushsection {},\"xr\"", section).unwrap();
writeln!(begin, ".balign 4").unwrap();
writeln!(begin, ".globl {asm_name}").unwrap();
if let Some(linkage) = linkage_directive(item_data.linkage) {
writeln!(begin, "{linkage} {asm_name}").unwrap();
}
writeln!(begin, ".def {asm_name}").unwrap();
writeln!(begin, ".scl 2").unwrap();
writeln!(begin, ".type 32").unwrap();
writeln!(begin, ".endef {asm_name}").unwrap();
if let Some(instruction_set) = instruction_set {
if let Some(instruction_set) = attrs.instruction_set {
writeln!(begin, "{}", instruction_set.as_str()).unwrap();
}
writeln!(begin, "{asm_name}:").unwrap();
Expand Down
14 changes: 7 additions & 7 deletions tests/codegen/naked-fn/naked-functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
#![crate_type = "lib"]
#![feature(naked_functions)]
use std::arch::{asm, global_asm};
// CHECK: module asm ".intel_syntax"
// CHECK: .pushsection .text.naked_empty,\22ax\22, @progbits
// CHECK: .balign 4"
// CHECK: .globl naked_empty"
// CHECK: .hidden naked_empty"
// CHECK: .type naked_empty, @function"
// CHECK: module asm ".intel_syntax
// CHECK: .pushsection .text.naked_empty,\22ax\22, @progbit
// CHECK: .balign 4
// CHECK: .globl naked_empty
// CHECK-NOT: .hidden naked_empty
// CHECK: .type naked_empty, @function
// CHECK-LABEL: naked_empty:
// CHECK: ret
// CHECK: .popsection
Expand All @@ -26,7 +26,7 @@ pub unsafe extern "C" fn naked_empty() {
// CHECK: .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits
// CHECK: .balign 4
// CHECK: .globl naked_with_args_and_return
// CHECK: .hidden naked_with_args_and_return
// CHECK-NOT: .hidden naked_with_args_and_return
// CHECK: .type naked_with_args_and_return, @function
// CHECK-LABEL: naked_with_args_and_return:
// CHECK: lea rax, [rdi + rsi]
Expand Down

0 comments on commit c54e5c1

Please sign in to comment.