Skip to content

Commit c71c6cc

Browse files
committed
Generalized mir::codegen_mir (and all subsequent functions)
1 parent 8b9ff39 commit c71c6cc

40 files changed

+1704
-1182
lines changed

src/librustc_codegen_llvm/abi.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ use mir::operand::OperandValue;
1717
use type_::Type;
1818
use type_of::{LayoutLlvmExt, PointerKind};
1919
use value::Value;
20+
use rustc_target::abi::call::ArgType;
2021

21-
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods};
22+
use interfaces::*;
2223

2324
use rustc_target::abi::{LayoutOf, Size, TyLayout};
24-
use rustc::ty::{self, Ty};
25+
use rustc::ty::{self, Ty, Instance};
2526
use rustc::ty::layout;
2627

2728
use libc::c_uint;
@@ -279,6 +280,27 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
279280
}
280281
}
281282

283+
impl<'a, 'll: 'a, 'tcx: 'll> ArgTypeMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value> {
284+
fn store_fn_arg(
285+
&self,
286+
ty: &ArgType<'tcx, Ty<'tcx>>,
287+
idx: &mut usize, dst: PlaceRef<'tcx, <Self::CodegenCx as Backend>::Value>
288+
) {
289+
ty.store_fn_arg(&self, idx, dst)
290+
}
291+
fn store_arg_ty(
292+
&self,
293+
ty: &ArgType<'tcx, Ty<'tcx>>,
294+
val: &'ll Value,
295+
dst: PlaceRef<'tcx, &'ll Value>
296+
) {
297+
ty.store(&self, val, dst)
298+
}
299+
fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> &'ll Type {
300+
ty.memory_ty(self.cx())
301+
}
302+
}
303+
282304
pub trait FnTypeExt<'tcx> {
283305
fn of_instance(cx: &CodegenCx<'ll, 'tcx, &'ll Value>, instance: &ty::Instance<'tcx>) -> Self;
284306
fn new(cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
@@ -754,3 +776,29 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
754776
}
755777
}
756778
}
779+
780+
impl AbiMethods<'tcx> for CodegenCx<'ll, 'tcx, &'ll Value> {
781+
fn new_fn_type(&self, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType<'tcx, Ty<'tcx>> {
782+
FnType::new(&self, sig, extra_args)
783+
}
784+
fn new_vtable(
785+
&self,
786+
sig: ty::FnSig<'tcx>,
787+
extra_args: &[Ty<'tcx>]
788+
) -> FnType<'tcx, Ty<'tcx>> {
789+
FnType::new_vtable(&self, sig, extra_args)
790+
}
791+
fn fn_type_of_instance(&self, instance: &Instance<'tcx>) -> FnType<'tcx, Ty<'tcx>> {
792+
FnType::of_instance(&self, instance)
793+
}
794+
}
795+
796+
impl AbiBuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value> {
797+
fn apply_attrs_callsite(
798+
&self,
799+
ty: &FnType<'tcx, Ty<'tcx>>,
800+
callsite: <Self::CodegenCx as Backend>::Value
801+
) {
802+
ty.apply_attrs_callsite(&self, callsite)
803+
}
804+
}

src/librustc_codegen_llvm/asm.rs

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,43 @@ use builder::Builder;
1515
use value::Value;
1616

1717
use rustc::hir;
18-
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods};
18+
use interfaces::*;
1919

2020
use mir::place::PlaceRef;
2121
use mir::operand::OperandValue;
2222

2323
use std::ffi::CString;
2424
use libc::{c_uint, c_char};
2525

26-
// Take an inline assembly expression and splat it out via LLVM
27-
pub fn codegen_inline_asm(
28-
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
29-
ia: &hir::InlineAsm,
30-
outputs: Vec<PlaceRef<'tcx, &'ll Value>>,
31-
mut inputs: Vec<&'ll Value>
32-
) -> bool {
33-
let mut ext_constraints = vec![];
34-
let mut output_types = vec![];
35-
36-
// Prepare the output operands
37-
let mut indirect_outputs = vec![];
38-
for (i, (out, place)) in ia.outputs.iter().zip(&outputs).enumerate() {
39-
if out.is_rw {
40-
inputs.push(bx.load_ref(place).immediate());
41-
ext_constraints.push(i.to_string());
26+
27+
impl AsmBuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value> {
28+
// Take an inline assembly expression and splat it out via LLVM
29+
fn codegen_inline_asm(
30+
&self,
31+
ia: &hir::InlineAsm,
32+
outputs: Vec<PlaceRef<'tcx, &'ll Value>>,
33+
mut inputs: Vec<&'ll Value>
34+
) -> bool {
35+
let mut ext_constraints = vec![];
36+
let mut output_types = vec![];
37+
38+
// Prepare the output operands
39+
let mut indirect_outputs = vec![];
40+
for (i, (out, place)) in ia.outputs.iter().zip(&outputs).enumerate() {
41+
if out.is_rw {
42+
inputs.push(self.load_ref(place).immediate());
43+
ext_constraints.push(i.to_string());
44+
}
45+
if out.is_indirect {
46+
indirect_outputs.push(self.load_ref(place).immediate());
47+
} else {
48+
output_types.push(place.layout.llvm_type(self.cx()));
49+
}
4250
}
43-
if out.is_indirect {
44-
indirect_outputs.push(bx.load_ref(place).immediate());
45-
} else {
46-
output_types.push(place.layout.llvm_type(bx.cx()));
51+
if !indirect_outputs.is_empty() {
52+
indirect_outputs.extend_from_slice(&inputs);
53+
inputs = indirect_outputs;
4754
}
48-
}
49-
if !indirect_outputs.is_empty() {
50-
indirect_outputs.extend_from_slice(&inputs);
51-
inputs = indirect_outputs;
52-
}
5355

5456
let clobbers = ia.clobbers.iter()
5557
.map(|s| format!("~{{{}}}", &s));
@@ -103,26 +105,28 @@ pub fn codegen_inline_asm(
103105
OperandValue::Immediate(v).store(bx, place);
104106
}
105107

106-
// Store mark in a metadata node so we can map LLVM errors
107-
// back to source locations. See #17552.
108-
unsafe {
109-
let key = "srcloc";
110-
let kind = llvm::LLVMGetMDKindIDInContext(bx.cx().llcx,
111-
key.as_ptr() as *const c_char, key.len() as c_uint);
108+
// Store mark in a metadata node so we can map LLVM errors
109+
// back to source locations. See #17552.
110+
unsafe {
111+
let key = "srcloc";
112+
let kind = llvm::LLVMGetMDKindIDInContext(self.cx().llcx,
113+
key.as_ptr() as *const c_char, key.len() as c_uint);
112114

113-
let val: &'ll Value = bx.cx().const_i32(ia.ctxt.outer().as_u32() as i32);
115+
let val: &'ll Value = self.cx().const_i32(ia.ctxt.outer().as_u32() as i32);
114116

115-
llvm::LLVMSetMetadata(r, kind,
116-
llvm::LLVMMDNodeInContext(bx.cx().llcx, &val, 1));
117+
llvm::LLVMSetMetadata(r, kind,
118+
llvm::LLVMMDNodeInContext(self.cx().llcx, &val, 1));
119+
}
117120
}
118121

119122
return true;
120123
}
121124

122-
pub fn codegen_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx, &'a Value>,
123-
ga: &hir::GlobalAsm) {
124-
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
125-
unsafe {
126-
llvm::LLVMRustAppendModuleInlineAsm(cx.llmod, asm.as_ptr());
125+
impl AsmMethods for CodegenCx<'ll, 'tcx, &'ll Value> {
126+
fn codegen_global_asm(&self, ga: &hir::GlobalAsm) {
127+
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
128+
unsafe {
129+
llvm::LLVMRustAppendModuleInlineAsm(self.llmod, asm.as_ptr());
130+
}
127131
}
128132
}

src/librustc_codegen_llvm/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
1616
use rustc::session::Session;
1717
use rustc::session::config::Sanitizer;
1818
use rustc::ty::TyCtxt;
19-
use rustc::ty::layout::HasTyCtxt;
2019
use rustc::ty::query::Providers;
2120
use rustc_data_structures::sync::Lrc;
2221
use rustc_data_structures::fx::FxHashMap;
2322
use rustc_target::spec::PanicStrategy;
23+
use interfaces::*;
2424

2525
use attributes;
2626
use llvm::{self, Attribute};

src/librustc_codegen_llvm/base.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ use rustc_mir::monomorphize::item::DefPathBasedNames;
5858
use common::{self, IntPredicate, RealPredicate, TypeKind};
5959
use context::CodegenCx;
6060
use debuginfo;
61-
use declare;
6261
use meth;
6362
use mir;
6463
use monomorphize::Instance;
@@ -395,15 +394,18 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
395394
sess.target.target.options.is_like_msvc
396395
}
397396

398-
pub fn call_assume(bx: &Builder<'_, 'll, '_, &'ll Value>, val: &'ll Value) {
397+
pub fn call_assume<'a, 'll: 'a, 'tcx: 'll, Bx : BuilderMethods<'a, 'll ,'tcx>>(
398+
bx: &Bx,
399+
val: <Bx::CodegenCx as Backend>::Value
400+
) {
399401
let assume_intrinsic = bx.cx().get_intrinsic("llvm.assume");
400402
bx.call(assume_intrinsic, &[val], None);
401403
}
402404

403-
pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll, Builder : BuilderMethods<'a, 'll ,'tcx>>(
404-
bx: &Builder,
405-
val: <Builder::CodegenCx as Backend>::Value
406-
) -> <Builder::CodegenCx as Backend>::Value {
405+
pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll, Bx : BuilderMethods<'a, 'll ,'tcx>>(
406+
bx: &Bx,
407+
val: <Bx::CodegenCx as Backend>::Value
408+
) -> <Bx::CodegenCx as Backend>::Value {
407409
if bx.cx().val_ty(val) == bx.cx().type_i1() {
408410
bx.zext(val, bx.cx().type_i8())
409411
} else {
@@ -449,7 +451,7 @@ pub fn memcpy_ty<'a, 'll: 'a, 'tcx: 'll, Builder : BuilderMethods<'a, 'll, 'tcx>
449451
bx.call_memcpy(dst, src, bx.cx().const_usize(size), align, flags);
450452
}
451453

452-
pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx, &'a Value>, instance: Instance<'tcx>) {
454+
pub fn codegen_instance<'a, 'll: 'a, 'tcx: 'll>(cx: &'a CodegenCx<'ll, 'tcx, &'ll Value>, instance: Instance<'tcx>) {
453455
let _s = if cx.sess().codegen_stats() {
454456
let mut instance_name = String::new();
455457
DefPathBasedNames::new(cx.tcx, true, true)
@@ -474,7 +476,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx, &'a Value>, instance:
474476
cx.stats.borrow_mut().n_closures += 1;
475477

476478
let mir = cx.tcx.instance_mir(instance.def);
477-
mir::codegen_mir(cx, lldecl, &mir, instance, sig);
479+
mir::codegen_mir::<'a, 'll, 'tcx, Builder<'a, 'll, 'tcx, &'ll Value>>(cx, lldecl, &mir, instance, sig);
478480
}
479481

480482
pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
@@ -535,15 +537,15 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx<'ll, '_, &'ll Value>) {
535537
&main_ret_ty.no_late_bound_regions().unwrap(),
536538
);
537539

538-
if declare::get_defined_value(cx, "main").is_some() {
540+
if cx.get_defined_value("main").is_some() {
539541
// FIXME: We should be smart and show a better diagnostic here.
540542
cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
541543
.help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
542544
.emit();
543545
cx.sess().abort_if_errors();
544546
bug!();
545547
}
546-
let llfn = declare::declare_cfn(cx, "main", llfty);
548+
let llfn = cx.declare_cfn("main", llfty);
547549

548550
// `main` should respect same config for frame pointer elimination as rest of code
549551
attributes::set_frame_pointer_elimination(cx, llfn);

src/librustc_codegen_llvm/builder.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use value::Value;
1818
use libc::{c_uint, c_char};
1919
use rustc::ty::TyCtxt;
2020
use rustc::ty::layout::{self, Align, Size};
21-
use rustc::session::{config, Session};
21+
use rustc::session::config;
2222
use rustc_data_structures::small_c_str::SmallCStr;
2323
use interfaces::*;
2424
use syntax;
@@ -99,10 +99,6 @@ impl BuilderMethods<'a, 'll, 'tcx>
9999
Builder::new_block(self.cx, self.llfn(), name)
100100
}
101101

102-
fn sess(&self) -> &Session {
103-
self.cx.sess()
104-
}
105-
106102
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
107103
self.cx.tcx
108104
}
@@ -605,7 +601,7 @@ impl BuilderMethods<'a, 'll, 'tcx>
605601

606602

607603
fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
608-
if self.sess().target.target.arch == "amdgpu" {
604+
if self.cx().sess().target.target.arch == "amdgpu" {
609605
// amdgpu/LLVM does something weird and thinks a i64 value is
610606
// split into a v2i32, halving the bitwidth LLVM expects,
611607
// tripping an assertion. So, for now, just disable this
@@ -1381,7 +1377,7 @@ impl BuilderMethods<'a, 'll, 'tcx>
13811377
return;
13821378
}
13831379
let cx = &self.cx();
1384-
let ptr_width = &self.sess().target.target.target_pointer_width;
1380+
let ptr_width = &self.cx().sess().target.target.target_pointer_width;
13851381
let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
13861382
let memcpy = cx.get_intrinsic(&key);
13871383
let src_ptr = &self.pointercast(src, cx.type_i8p());
@@ -1400,7 +1396,7 @@ impl BuilderMethods<'a, 'll, 'tcx>
14001396
align: &'ll Value,
14011397
volatile: bool,
14021398
) -> &'ll Value {
1403-
let ptr_width = &self.sess().target.target.target_pointer_width;
1399+
let ptr_width = &self.cx().sess().target.target.target_pointer_width;
14041400
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
14051401
let llintrinsicfn = &self.cx().get_intrinsic(&intrinsic_key);
14061402
let volatile = &self.cx().const_bool(volatile);
@@ -1425,4 +1421,14 @@ impl BuilderMethods<'a, 'll, 'tcx>
14251421
fn cx(&self) -> &'a CodegenCx<'ll, 'tcx, &'ll Value> {
14261422
&self.cx
14271423
}
1424+
1425+
fn delete_basic_block(&self, bb: &'ll BasicBlock) {
1426+
unsafe {
1427+
llvm::LLVMDeleteBasicBlock(bb);
1428+
}
1429+
}
1430+
1431+
fn do_not_inline(&self, llret: &'ll Value) {
1432+
llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
1433+
}
14281434
}

src/librustc_codegen_llvm/callee.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
//! closure.
1616
1717
use attributes;
18-
use common::{self, CodegenCx};
19-
use consts;
20-
use declare;
18+
use common;
2119
use llvm;
2220
use monomorphize::Instance;
23-
use type_of::LayoutLlvmExt;
21+
use context::CodegenCx;
2422
use value::Value;
2523
use interfaces::*;
2624

@@ -40,16 +38,16 @@ pub fn get_fn(
4038
cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
4139
instance: Instance<'tcx>,
4240
) -> &'ll Value {
43-
let tcx = cx.tcx;
41+
let tcx = cx.tcx();
4442

4543
debug!("get_fn(instance={:?})", instance);
4644

4745
assert!(!instance.substs.needs_infer());
4846
assert!(!instance.substs.has_escaping_regions());
4947
assert!(!instance.substs.has_param_types());
5048

51-
let fn_ty = instance.ty(cx.tcx);
52-
if let Some(&llfn) = cx.instances.borrow().get(&instance) {
49+
let fn_ty = instance.ty(*cx.tcx());
50+
if let Some(&llfn) = cx.instances().borrow().get(&instance) {
5351
return llfn;
5452
}
5553

@@ -58,9 +56,9 @@ pub fn get_fn(
5856

5957
// Create a fn pointer with the substituted signature.
6058
let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(cx, fn_ty));
61-
let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx);
59+
let llptrty = cx.backend_type(&cx.layout_of(fn_ptr_ty));
6260

63-
let llfn = if let Some(llfn) = declare::get_declared_value(cx, &sym) {
61+
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
6462
// This is subtle and surprising, but sometimes we have to bitcast
6563
// the resulting fn pointer. The reason has to do with external
6664
// functions. If you have two crates that both bind the same C
@@ -86,17 +84,17 @@ pub fn get_fn(
8684
// other weird situations. Annoying.
8785
if cx.val_ty(llfn) != llptrty {
8886
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
89-
consts::ptrcast(llfn, llptrty)
87+
cx.static_ptrcast(llfn, llptrty)
9088
} else {
9189
debug!("get_fn: not casting pointer!");
9290
llfn
9391
}
9492
} else {
95-
let llfn = declare::declare_fn(cx, &sym, fn_ty);
93+
let llfn = cx.declare_fn(&sym, fn_ty);
9694
assert_eq!(cx.val_ty(llfn), llptrty);
9795
debug!("get_fn: not casting pointer!");
9896

99-
if instance.def.is_inline(tcx) {
97+
if instance.def.is_inline(*tcx) {
10098
attributes::inline(cx, llfn, attributes::InlineAttr::Hint);
10199
}
102100
attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()));

0 commit comments

Comments
 (0)