Skip to content

Commit 524d140

Browse files
committed
Lower TLS to calls for rvalues directly
1 parent c044df2 commit 524d140

File tree

3 files changed

+32
-172
lines changed

3 files changed

+32
-172
lines changed

Diff for: compiler/rustc_codegen_ssa/src/mir/block.rs

+19-52
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ use crate::MemFlags;
1212
use rustc_ast as ast;
1313
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1414
use rustc_hir::lang_items::LangItem;
15-
use rustc_hir::Unsafety;
16-
use rustc_index::vec::{Idx, IndexVec};
15+
use rustc_index::vec::Idx;
1716
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
1817
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
1918
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
@@ -744,58 +743,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
744743
let source_info = terminator.source_info;
745744
let span = source_info.span;
746745

747-
let thread_local_shim_call = if !self.call_thread_local_shims.is_empty() {
748-
self.call_thread_local_shims.iter().find(|e| &e.0 == func).map(|e| e.1)
749-
} else {
750-
None
751-
};
746+
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
747+
let callee = self.codegen_operand(bx, func);
752748

753-
let (sig, instance, mut llfn) = match thread_local_shim_call {
754-
Some(thread_local) => {
755-
// Replace thread local dummy calls with calls to the real shim
756-
let instance = ty::Instance {
757-
def: ty::InstanceDef::ThreadLocalShim(thread_local),
758-
substs: ty::InternalSubsts::empty(),
759-
};
760-
let ty = mir::Rvalue::ThreadLocalRef(thread_local).ty(&IndexVec::new(), bx.tcx());
761-
(
762-
ty::Binder::dummy(bx.tcx().mk_fn_sig(
763-
[].iter(),
764-
&ty,
765-
false,
766-
Unsafety::Normal,
767-
Abi::Unadjusted,
768-
)),
769-
Some(instance),
770-
None,
771-
)
772-
}
773-
None => {
774-
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
775-
let callee = self.codegen_operand(bx, func);
776-
777-
let sig = callee.layout.ty.fn_sig(bx.tcx());
778-
779-
match *callee.layout.ty.kind() {
780-
ty::FnDef(def_id, substs) => (
781-
sig,
782-
Some(
783-
ty::Instance::expect_resolve(
784-
bx.tcx(),
785-
ty::ParamEnv::reveal_all(),
786-
def_id,
787-
substs,
788-
)
789-
.polymorphize(bx.tcx()),
790-
),
791-
None,
792-
),
793-
ty::FnPtr(_) => (sig, None, Some(callee.immediate())),
794-
_ => bug!("{} is not callable", callee.layout.ty),
795-
}
796-
}
749+
let (instance, mut llfn) = match *callee.layout.ty.kind() {
750+
ty::FnDef(def_id, substs) => (
751+
Some(
752+
ty::Instance::expect_resolve(
753+
bx.tcx(),
754+
ty::ParamEnv::reveal_all(),
755+
def_id,
756+
substs,
757+
)
758+
.polymorphize(bx.tcx()),
759+
),
760+
None,
761+
),
762+
ty::FnPtr(_) => (None, Some(callee.immediate())),
763+
_ => bug!("{} is not callable", callee.layout.ty),
797764
};
798-
799765
let def = instance.map(|i| i.def);
800766

801767
if let Some(ty::InstanceDef::DropGlue(_, None)) = def {
@@ -807,6 +773,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
807773
// FIXME(eddyb) avoid computing this if possible, when `instance` is
808774
// available - right now `sig` is only needed for getting the `abi`
809775
// and figuring out how many extra args were passed to a C-variadic `fn`.
776+
let sig = callee.layout.ty.fn_sig(bx.tcx());
810777
let abi = sig.abi();
811778

812779
// Handle intrinsics old codegen wants Expr's for, ourselves.

Diff for: compiler/rustc_codegen_ssa/src/mir/mod.rs

+1-119
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
use crate::base;
22
use crate::traits::*;
3-
use rustc_hir::def_id::DefId;
4-
use rustc_index::vec::Idx;
53
use rustc_middle::mir;
64
use rustc_middle::mir::interpret::ErrorHandled;
7-
use rustc_middle::mir::visit::MutVisitor;
8-
use rustc_middle::mir::visit::Visitor;
95
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
10-
use rustc_middle::ty::TyCtxt;
116
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
12-
use rustc_span::DUMMY_SP;
137
use rustc_target::abi::call::{FnAbi, PassMode};
148

159
use std::iter;
@@ -49,9 +43,6 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
4943

5044
fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
5145

52-
// Used to replace call terminators with a call to a thread local shim.
53-
call_thread_local_shims: Vec<(mir::Operand<'tcx>, DefId)>,
54-
5546
/// When unwinding is initiated, we have to store this personality
5647
/// value somewhere so that we can load it and re-use it in the
5748
/// resume instruction. The personality is (afaik) some kind of
@@ -151,112 +142,6 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
151142
}
152143
}
153144

154-
struct FindThreadLocal(bool);
155-
156-
impl<'tcx> Visitor<'tcx> for FindThreadLocal {
157-
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) {
158-
if let mir::Rvalue::ThreadLocalRef(..) = rvalue {
159-
self.0 = true;
160-
}
161-
self.super_rvalue(rvalue, location);
162-
}
163-
}
164-
165-
struct ReplaceThreadLocal<'tcx> {
166-
tcx: TyCtxt<'tcx>,
167-
local_start: usize,
168-
list: Vec<DefId>,
169-
}
170-
171-
impl<'tcx> MutVisitor<'tcx> for ReplaceThreadLocal<'tcx> {
172-
fn tcx(&self) -> TyCtxt<'tcx> {
173-
self.tcx
174-
}
175-
176-
fn visit_rvalue(&mut self, rvalue: &mut mir::Rvalue<'tcx>, location: mir::Location) {
177-
if let mir::Rvalue::ThreadLocalRef(def_id) = *rvalue {
178-
if !def_id.is_local() {
179-
*rvalue = mir::Rvalue::Use(mir::Operand::Copy(mir::Place {
180-
local: mir::Local::new(self.local_start + self.list.len()),
181-
projection: self.tcx.intern_place_elems(&[]),
182-
}));
183-
self.list.push(def_id);
184-
}
185-
}
186-
self.super_rvalue(rvalue, location);
187-
}
188-
}
189-
190-
// Convert thread local references to thread local function shims if necessary
191-
fn convert_tls_rvalues<'tcx>(
192-
tcx: TyCtxt<'tcx>,
193-
mir: &mut &'tcx mir::Body<'tcx>,
194-
) -> Vec<(mir::Operand<'tcx>, DefId)> {
195-
if tcx.sess.target.dll_tls_export {
196-
// The target supports DLL TLS exports. We don't need to do anything
197-
return Vec::new();
198-
}
199-
200-
// Fast path to look for any thread locals
201-
let mut visitor = FindThreadLocal(false);
202-
visitor.visit_body(&mir);
203-
if !visitor.0 {
204-
return Vec::new();
205-
}
206-
207-
// Don't modify shims
208-
if let ty::InstanceDef::ThreadLocalShim(..) = mir.source.instance {
209-
return Vec::new();
210-
}
211-
212-
let mut result = Vec::new();
213-
let mut body = mir.clone();
214-
215-
let mut visitor =
216-
ReplaceThreadLocal { tcx, local_start: mir.local_decls.len(), list: Vec::new() };
217-
visitor.visit_body(&mut body);
218-
219-
for (i, &def_id) in visitor.list.iter().enumerate() {
220-
let ty = mir::Rvalue::ThreadLocalRef(def_id).ty(&IndexVec::new(), tcx);
221-
body.local_decls.push(mir::LocalDecl::new(ty, DUMMY_SP));
222-
let local = mir::Local::new(visitor.local_start + i);
223-
let place = mir::Place { local, projection: tcx.intern_place_elems(&[]) };
224-
let func = mir::Operand::Copy(place);
225-
226-
result.push((func.clone(), def_id));
227-
228-
let blocks = body.basic_blocks.as_mut();
229-
230-
let new_entry = mir::BasicBlock::new(blocks.len());
231-
232-
let entry = std::mem::replace(
233-
&mut blocks[mir::BasicBlock::new(0)],
234-
mir::BasicBlockData {
235-
statements: Vec::new(),
236-
terminator: Some(mir::Terminator {
237-
source_info: mir::SourceInfo::outermost(DUMMY_SP),
238-
kind: mir::TerminatorKind::Call {
239-
func,
240-
args: Vec::new(),
241-
destination: place,
242-
target: Some(new_entry),
243-
cleanup: None,
244-
from_hir_call: false,
245-
fn_span: DUMMY_SP,
246-
},
247-
}),
248-
is_cleanup: false,
249-
},
250-
);
251-
252-
blocks.push(entry);
253-
}
254-
255-
*mir = tcx.arena.alloc(body);
256-
257-
result
258-
}
259-
260145
///////////////////////////////////////////////////////////////////////////
261146

262147
#[instrument(level = "debug", skip(cx))]
@@ -268,9 +153,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
268153

269154
let llfn = cx.get_fn(instance);
270155

271-
let mut mir = cx.tcx().instance_mir(instance.def);
272-
273-
let call_thread_local_shims = convert_tls_rvalues(cx.tcx(), &mut mir);
156+
let mir = cx.tcx().instance_mir(instance.def);
274157

275158
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
276159
debug!("fn_abi: {:?}", fn_abi);
@@ -300,7 +183,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
300183
llfn,
301184
fn_abi,
302185
cx,
303-
call_thread_local_shims,
304186
personality_slot: None,
305187
cached_llbbs,
306188
unreachable_block: None,

Diff for: compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
462462

463463
mir::Rvalue::ThreadLocalRef(def_id) => {
464464
assert!(bx.cx().tcx().is_static(def_id));
465-
let static_ = bx.get_static(def_id);
466465
let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
466+
let static_ = if !def_id.is_local() && !bx.cx().tcx().sess.target.dll_tls_export {
467+
let instance = ty::Instance {
468+
def: ty::InstanceDef::ThreadLocalShim(def_id),
469+
substs: ty::InternalSubsts::empty(),
470+
};
471+
let fn_ptr = bx.get_fn_addr(instance);
472+
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
473+
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
474+
bx.call(fn_ty, Some(fn_abi), fn_ptr, &[], None)
475+
} else {
476+
bx.get_static(def_id)
477+
};
467478
OperandRef { val: OperandValue::Immediate(static_), layout }
468479
}
469480
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),

0 commit comments

Comments
 (0)