Skip to content

Commit

Permalink
Rollup merge of rust-lang#73033 - Amanieu:asm-tls, r=oli-obk
Browse files Browse the repository at this point in the history
Fix #[thread_local] statics as asm! sym operands

The `asm!` RFC specifies that `#[thread_local]` statics may be used as `sym` operands for inline assembly.

This also fixes a regression in the handling of `#[thread_local]` during monomorphization which caused link-time errors with multiple codegen units, most likely introduced by rust-lang#71192.

r? @oli-obk
  • Loading branch information
Dylan-DPC authored Jun 11, 2020
2 parents a37c32e + 74befd9 commit 2e42476
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 45 deletions.
8 changes: 2 additions & 6 deletions src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,12 +927,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
span_bug!(span, "invalid type for asm sym (fn)");
}
}
mir::InlineAsmOperand::SymStatic { ref value } => {
if let Some(def_id) = value.check_static_ptr(bx.tcx()) {
InlineAsmOperandRef::SymStatic { def_id }
} else {
span_bug!(span, "invalid type for asm sym (static)");
}
mir::InlineAsmOperand::SymStatic { def_id } => {
InlineAsmOperandRef::SymStatic { def_id }
}
})
.collect();
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_middle/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,7 @@ pub enum InlineAsmOperand<'tcx> {
value: Box<Constant<'tcx>>,
},
SymStatic {
value: Box<Constant<'tcx>>,
def_id: DefId,
},
}

Expand Down Expand Up @@ -1639,9 +1639,11 @@ impl<'tcx> TerminatorKind<'tcx> {
InlineAsmOperand::Const { value } => {
write!(fmt, "const {:?}", value)?;
}
InlineAsmOperand::SymFn { value }
| InlineAsmOperand::SymStatic { value } => {
write!(fmt, "sym {:?}", value)?;
InlineAsmOperand::SymFn { value } => {
write!(fmt, "sym_fn {:?}", value)?;
}
InlineAsmOperand::SymStatic { def_id } => {
write!(fmt, "sym_static {:?}", def_id)?;
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_middle/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,10 @@ macro_rules! make_mir_visitor {
);
}
}
InlineAsmOperand::SymFn { value }
| InlineAsmOperand::SymStatic { value } => {
InlineAsmOperand::SymFn { value } => {
self.visit_constant(value, source_location);
}
InlineAsmOperand::SymStatic { def_id: _ } => {}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/invalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
}
InlineAsmOperand::SymFn { value: _ }
| InlineAsmOperand::SymStatic { value: _ } => {}
| InlineAsmOperand::SymStatic { def_id: _ } => {}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
}
}
InlineAsmOperand::SymFn { value: _ }
| InlineAsmOperand::SymStatic { value: _ } => {}
| InlineAsmOperand::SymStatic { def_id: _ } => {}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/dataflow/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
}
}
InlineAsmOperand::SymFn { value: _ }
| InlineAsmOperand::SymStatic { value: _ } => {}
| InlineAsmOperand::SymStatic { def_id: _ } => {}
}
}
}
Expand Down
16 changes: 13 additions & 3 deletions src/librustc_mir/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,9 +634,19 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
}
mir::TerminatorKind::InlineAsm { ref operands, .. } => {
for op in operands {
if let mir::InlineAsmOperand::SymFn { value } = op {
let fn_ty = self.monomorphize(value.literal.ty);
visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
match *op {
mir::InlineAsmOperand::SymFn { ref value } => {
let fn_ty = self.monomorphize(value.literal.ty);
visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
}
mir::InlineAsmOperand::SymStatic { def_id } => {
let instance = Instance::mono(self.tcx, def_id);
if should_monomorphize_locally(self.tcx, &instance) {
trace!("collecting asm sym static {:?}", def_id);
self.output.push(MonoItem::Static(def_id));
}
}
_ => {}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir_build/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
hair::InlineAsmOperand::SymFn { expr } => {
mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) }
}
hair::InlineAsmOperand::SymStatic { expr } => {
mir::InlineAsmOperand::SymStatic { value: box this.as_constant(expr) }
hair::InlineAsmOperand::SymStatic { def_id } => {
mir::InlineAsmOperand::SymStatic { def_id }
}
})
.collect();
Expand Down
21 changes: 2 additions & 19 deletions src/librustc_mir_build/hair/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,25 +467,8 @@ fn make_mirror_unadjusted<'a, 'tcx>(
}
}

Res::Def(DefKind::Static, id) => {
ty = cx.tcx.static_ptr_ty(id);
let ptr = cx.tcx.create_static_alloc(id);
InlineAsmOperand::SymStatic {
expr: Expr {
ty,
temp_lifetime,
span: expr.span,
kind: ExprKind::StaticRef {
literal: ty::Const::from_scalar(
cx.tcx,
Scalar::Ptr(ptr.into()),
ty,
),
def_id: id,
},
}
.to_ref(),
}
Res::Def(DefKind::Static, def_id) => {
InlineAsmOperand::SymStatic { def_id }
}

_ => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir_build/hair/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ crate enum InlineAsmOperand<'tcx> {
expr: ExprRef<'tcx>,
},
SymStatic {
expr: ExprRef<'tcx>,
def_id: DefId,
},
}

Expand Down
52 changes: 47 additions & 5 deletions src/test/ui/asm/sym.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// no-system-llvm
// only-x86_64
// only-linux
// run-pass

#![feature(asm, track_caller)]
#![feature(asm, track_caller, thread_local)]

extern "C" fn f1() -> i32 {
111
Expand All @@ -15,9 +16,9 @@ fn f2() -> i32 {
}

macro_rules! call {
($func:path) => {{
let result: i32;
($func:path) => {
unsafe {
let result: i32;
asm!("call {}", sym $func,
out("rax") result,
out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
Expand All @@ -27,12 +28,53 @@ macro_rules! call {
out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
);
result
}
result
}}
}
}

macro_rules! static_addr {
($s:expr) => {
unsafe {
let result: *const u32;
// LEA performs a RIP-relative address calculation and returns the address
asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
result
}
}
}
macro_rules! static_tls_addr {
($s:expr) => {
unsafe {
let result: *const u32;
asm!(
"
# Load TLS base address
mov {out}, qword ptr fs:[0]
# Calculate the address of sym in the TLS block. The @tpoff
# relocation gives the offset of the symbol from the start
# of the TLS block.
lea {out}, [{out} + {sym}@tpoff]
",
out = out(reg) result,
sym = sym $s
);
result
}
}
}

static S1: u32 = 111;
#[thread_local]
static S2: u32 = 222;

fn main() {
assert_eq!(call!(f1), 111);
assert_eq!(call!(f2), 222);
assert_eq!(static_addr!(S1), &S1 as *const u32);
assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
std::thread::spawn(|| {
assert_eq!(static_addr!(S1), &S1 as *const u32);
assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
});
}

0 comments on commit 2e42476

Please sign in to comment.