From 74befd955bfe23418369064888dc0f08f59c024f Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 5 Jun 2020 15:52:38 +0100 Subject: [PATCH] Fix #[thread_local] statics as asm! sym operands --- src/librustc_codegen_ssa/mir/block.rs | 8 +-- src/librustc_middle/mir/mod.rs | 10 ++-- src/librustc_middle/mir/visit.rs | 4 +- src/librustc_mir/borrow_check/invalidation.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 2 +- .../dataflow/move_paths/builder.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 16 ++++-- src/librustc_mir_build/build/expr/into.rs | 4 +- src/librustc_mir_build/hair/cx/expr.rs | 21 +------- src/librustc_mir_build/hair/mod.rs | 2 +- src/test/ui/asm/sym.rs | 52 +++++++++++++++++-- 11 files changed, 78 insertions(+), 45 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 6c18e753d790b..c8038e5e0fccb 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -921,12 +921,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(); diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 904424462bfe7..9df42679ade04 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -1240,7 +1240,7 @@ pub enum InlineAsmOperand<'tcx> { value: Box>, }, SymStatic { - value: Box>, + def_id: DefId, }, } @@ -1636,9 +1636,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)?; } } } diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index 351dc33dbe355..220dfa80f06ad 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -563,10 +563,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: _ } => {} } } } diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 9c23ee74413cb..a0935517aaaea 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -208,7 +208,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } } InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { value: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } => {} } } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index d17c111d0c42c..8f2977039280b 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -759,7 +759,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc } } InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { value: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } => {} } } } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index da02211d002a8..4e8b796d500d9 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -439,7 +439,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } } InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { value: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } => {} } } } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 297b899ef0bd6..c4dadf0938b58 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -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)); + } + } + _ => {} } } } diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs index d5d1ddc5b7d7b..6b8d13de96a33 100644 --- a/src/librustc_mir_build/build/expr/into.rs +++ b/src/librustc_mir_build/build/expr/into.rs @@ -353,8 +353,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(); diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index d0b35f3212251..ef038a132d9ac 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -465,25 +465,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 } } _ => { diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs index c869699bb20e4..5f280e8568cd4 100644 --- a/src/librustc_mir_build/hair/mod.rs +++ b/src/librustc_mir_build/hair/mod.rs @@ -374,7 +374,7 @@ crate enum InlineAsmOperand<'tcx> { expr: ExprRef<'tcx>, }, SymStatic { - expr: ExprRef<'tcx>, + def_id: DefId, }, } diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs index 83a3672af49ce..8cff16aa75f69 100644 --- a/src/test/ui/asm/sym.rs +++ b/src/test/ui/asm/sym.rs @@ -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 @@ -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") _, @@ -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); + }); }