Skip to content

Commit 6a993fe

Browse files
denismerigouxeddyb
authored andcommitted
Generalized mir::codegen_mir (and all subsequent functions)
1 parent cbe31a4 commit 6a993fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1735
-1347
lines changed

src/librustc_codegen_llvm/abi.rs

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

20-
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods};
21+
use interfaces::*;
2122

2223
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
23-
use rustc::ty::{self, Ty};
24+
use rustc::ty::{self, Ty, Instance};
2425
use rustc::ty::layout;
2526

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

284+
impl ArgTypeMethods<'tcx> for Builder<'a, 'll, 'tcx> {
285+
fn store_fn_arg(
286+
&self,
287+
ty: &ArgType<'tcx, Ty<'tcx>>,
288+
idx: &mut usize, dst: PlaceRef<'tcx, Self::Value>
289+
) {
290+
ty.store_fn_arg(self, idx, dst)
291+
}
292+
fn store_arg_ty(
293+
&self,
294+
ty: &ArgType<'tcx, Ty<'tcx>>,
295+
val: &'ll Value,
296+
dst: PlaceRef<'tcx, &'ll Value>
297+
) {
298+
ty.store(self, val, dst)
299+
}
300+
fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> &'ll Type {
301+
ty.memory_ty(self.cx())
302+
}
303+
}
304+
283305
pub trait FnTypeExt<'tcx> {
284306
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self;
285307
fn new(cx: &CodegenCx<'ll, 'tcx>,
@@ -790,3 +812,29 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
790812
}
791813
}
792814
}
815+
816+
impl AbiMethods<'tcx> for CodegenCx<'ll, 'tcx> {
817+
fn new_fn_type(&self, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType<'tcx, Ty<'tcx>> {
818+
FnType::new(&self, sig, extra_args)
819+
}
820+
fn new_vtable(
821+
&self,
822+
sig: ty::FnSig<'tcx>,
823+
extra_args: &[Ty<'tcx>]
824+
) -> FnType<'tcx, Ty<'tcx>> {
825+
FnType::new_vtable(&self, sig, extra_args)
826+
}
827+
fn fn_type_of_instance(&self, instance: &Instance<'tcx>) -> FnType<'tcx, Ty<'tcx>> {
828+
FnType::of_instance(&self, instance)
829+
}
830+
}
831+
832+
impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
833+
fn apply_attrs_callsite(
834+
&self,
835+
ty: &FnType<'tcx, Ty<'tcx>>,
836+
callsite: Self::Value
837+
) {
838+
ty.apply_attrs_callsite(self, callsite)
839+
}
840+
}

src/librustc_codegen_llvm/asm.rs

Lines changed: 96 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -15,114 +15,118 @@ 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>,
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_operand(place).immediate());
41-
ext_constraints.push(i.to_string());
26+
27+
impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
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_operand(place).immediate());
43+
ext_constraints.push(i.to_string());
44+
}
45+
if out.is_indirect {
46+
indirect_outputs.push(self.load_operand(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_operand(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

54-
let clobbers = ia.clobbers.iter()
55-
.map(|s| format!("~{{{}}}", &s));
56-
57-
// Default per-arch clobbers
58-
// Basically what clang does
59-
let arch_clobbers = match &bx.sess().target.target.arch[..] {
60-
"x86" | "x86_64" => vec!["~{dirflag}", "~{fpsr}", "~{flags}"],
61-
"mips" | "mips64" => vec!["~{$1}"],
62-
_ => Vec::new()
63-
};
64-
65-
let all_constraints =
66-
ia.outputs.iter().map(|out| out.constraint.to_string())
67-
.chain(ia.inputs.iter().map(|s| s.to_string()))
68-
.chain(ext_constraints)
69-
.chain(clobbers)
70-
.chain(arch_clobbers.iter().map(|s| s.to_string()))
71-
.collect::<Vec<String>>().join(",");
72-
73-
debug!("Asm Constraints: {}", &all_constraints);
74-
75-
// Depending on how many outputs we have, the return type is different
76-
let num_outputs = output_types.len();
77-
let output_type = match num_outputs {
78-
0 => bx.cx().type_void(),
79-
1 => output_types[0],
80-
_ => bx.cx().type_struct(&output_types, false)
81-
};
82-
83-
let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
84-
let constraint_cstr = CString::new(all_constraints).unwrap();
85-
let r = bx.inline_asm_call(
86-
asm.as_ptr(),
87-
constraint_cstr.as_ptr(),
88-
&inputs,
89-
output_type,
90-
ia.volatile,
91-
ia.alignstack,
92-
ia.dialect
93-
);
94-
if r.is_none() {
95-
return false;
96-
}
97-
let r = r.unwrap();
56+
let clobbers = ia.clobbers.iter()
57+
.map(|s| format!("~{{{}}}", &s));
58+
59+
// Default per-arch clobbers
60+
// Basically what clang does
61+
let arch_clobbers = match &self.cx().sess().target.target.arch[..] {
62+
"x86" | "x86_64" => vec!["~{dirflag}", "~{fpsr}", "~{flags}"],
63+
"mips" | "mips64" => vec!["~{$1}"],
64+
_ => Vec::new()
65+
};
66+
67+
let all_constraints =
68+
ia.outputs.iter().map(|out| out.constraint.to_string())
69+
.chain(ia.inputs.iter().map(|s| s.to_string()))
70+
.chain(ext_constraints)
71+
.chain(clobbers)
72+
.chain(arch_clobbers.iter().map(|s| s.to_string()))
73+
.collect::<Vec<String>>().join(",");
74+
75+
debug!("Asm Constraints: {}", &all_constraints);
76+
77+
// Depending on how many outputs we have, the return type is different
78+
let num_outputs = output_types.len();
79+
let output_type = match num_outputs {
80+
0 => self.cx().type_void(),
81+
1 => output_types[0],
82+
_ => self.cx().type_struct(&output_types, false)
83+
};
84+
85+
let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
86+
let constraint_cstr = CString::new(all_constraints).unwrap();
87+
let r = self.inline_asm_call(
88+
asm.as_ptr(),
89+
constraint_cstr.as_ptr(),
90+
&inputs,
91+
output_type,
92+
ia.volatile,
93+
ia.alignstack,
94+
ia.dialect
95+
);
96+
if r.is_none() {
97+
return false;
98+
}
99+
let r = r.unwrap();
98100

99-
// Again, based on how many outputs we have
100-
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
101-
for (i, (_, &place)) in outputs.enumerate() {
102-
let v = if num_outputs == 1 { r } else { bx.extract_value(r, i as u64) };
103-
OperandValue::Immediate(v).store(bx, place);
104-
}
101+
// Again, based on how many outputs we have
102+
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
103+
for (i, (_, &place)) in outputs.enumerate() {
104+
let v = if num_outputs == 1 { r } else { self.extract_value(r, i as u64) };
105+
OperandValue::Immediate(v).store(self, place);
106+
}
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-
}
117+
llvm::LLVMSetMetadata(r, kind,
118+
llvm::LLVMMDNodeInContext(self.cx().llcx, &val, 1));
119+
}
118120

119-
return true;
121+
true
122+
}
120123
}
121124

122-
pub fn codegen_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
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<'tcx> for CodegenCx<'ll, 'tcx> {
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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc::ty::query::Providers;
2121
use rustc_data_structures::sync::Lrc;
2222
use rustc_data_structures::fx::FxHashMap;
2323
use rustc_target::spec::PanicStrategy;
24+
use interfaces::*;
2425

2526
use attributes;
2627
use llvm::{self, Attribute};

src/librustc_codegen_llvm/base.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ use rustc_mir::monomorphize::item::DefPathBasedNames;
5757
use common::{self, IntPredicate, RealPredicate, TypeKind};
5858
use context::CodegenCx;
5959
use debuginfo;
60-
use declare;
6160
use meth;
6261
use mir;
6362
use monomorphize::Instance;
@@ -392,15 +391,18 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
392391
sess.target.target.options.is_like_msvc
393392
}
394393

395-
pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) {
394+
pub fn call_assume<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
395+
bx: &Bx,
396+
val: Bx::Value
397+
) {
396398
let assume_intrinsic = bx.cx().get_intrinsic("llvm.assume");
397399
bx.call(assume_intrinsic, &[val], None);
398400
}
399401

400-
pub fn from_immediate<'a, 'tcx: 'a, Builder: BuilderMethods<'a, 'tcx>>(
401-
bx: &Builder,
402-
val: Builder::Value
403-
) -> Builder::Value {
402+
pub fn from_immediate<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
403+
bx: &Bx,
404+
val: Bx::Value
405+
) -> Bx::Value {
404406
if bx.cx().val_ty(val) == bx.cx().type_i1() {
405407
bx.zext(val, bx.cx().type_i8())
406408
} else {
@@ -447,7 +449,7 @@ pub fn memcpy_ty<'a, 'tcx: 'a, Builder: BuilderMethods<'a, 'tcx>>(
447449
bx.memcpy(dst, dst_align, src, src_align, bx.cx().const_usize(size), flags);
448450
}
449451

450-
pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
452+
pub fn codegen_instance(cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) {
451453
let _s = if cx.sess().codegen_stats() {
452454
let mut instance_name = String::new();
453455
DefPathBasedNames::new(cx.tcx, true, true)
@@ -471,7 +473,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'
471473
cx.stats.borrow_mut().n_closures += 1;
472474

473475
let mir = cx.tcx.instance_mir(instance.def);
474-
mir::codegen_mir(cx, lldecl, &mir, instance, sig);
476+
mir::codegen_mir::<Builder>(cx, lldecl, &mir, instance, sig);
475477
}
476478

477479
pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
@@ -532,15 +534,15 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
532534
&main_ret_ty.no_bound_vars().unwrap(),
533535
);
534536

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

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

0 commit comments

Comments
 (0)