diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 74d7fc16215800530c4d547ff26bdd5d6c6d4519..ef59ad486eefe5fa12be6cebef0f19de2fc282a1 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -927,12 +927,8 @@ fn codegen_asm_terminator( 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 126e70e8c48dad2bc1d90af033938ca865ecf535..129f9691ea521b4d7405c0a570d5b945a2e32c8f 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -1243,7 +1243,7 @@ pub enum InlineAsmOperand<'tcx> { value: Box>, }, SymStatic { - value: Box>, + def_id: DefId, }, } @@ -1639,9 +1639,11 @@ pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { 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 966a709c8a2ce9f6d1dd7a589b0b8dd62ecaea34..5f9fcdca516b1ae802515bbbbc656dfb226be0be 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -564,10 +564,10 @@ fn super_terminator_kind(&mut self, ); } } - 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 18a6189507090c2ba16dc9f90e498a7b0002831d..17fa641ae6c17d1c6edd2ee56e348d677d1454ca 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -209,7 +209,7 @@ fn visit_terminator_kind(&mut self, kind: &TerminatorKind<'tcx>, location: Locat } } 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 786424e870f8edb7bfe93306f548bdff93867ab4..b703237a18e111b3f76c7e56f5b8090a4b7200b8 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -760,7 +760,7 @@ fn visit_terminator_before_primary_effect( } } 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 4f6ccdafdda18bb713da955c16c6001d50d0340c..41c7bd95a96cc1e877fe7e63362e76f3bdef3e84 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -439,7 +439,7 @@ fn gather_terminator(&mut self, term: &Terminator<'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 f3d3666b99f9f0467a6decd2324ede09a26628b0..994d1e69f2e3e709cefadfa34f4205121b151bf7 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -634,9 +634,19 @@ fn visit_terminator_kind(&mut self, kind: &mir::TerminatorKind<'tcx>, location: } 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 76096fc2299fba3b1d02b8dfe1b7a412566711cd..0d5bd4c7e61b90a5448f5c593a25bc9930b2a827 100644 --- a/src/librustc_mir_build/build/expr/into.rs +++ b/src/librustc_mir_build/build/expr/into.rs @@ -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(); diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 971a89796e281c6bd8ba70faf8630d545f21d12a..703f6ef8dc41e91fcc74c4e3ff8256f477d37dc1 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -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 } } _ => { diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs index d3ec5595365b423e1259622e4efb9a936e0bb88d..ccff510f2d4e5ca7d49ca2087018394bbf93e669 100644 --- a/src/librustc_mir_build/hair/mod.rs +++ b/src/librustc_mir_build/hair/mod.rs @@ -377,7 +377,7 @@ impl<'tcx> ExprRef<'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 83a3672af49ce620b3b534a0587c689889d5c660..8cff16aa75f695a76479b8185bd3cdf282524ce4 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 @@ fn f2() -> i32 { 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); + }); }