Skip to content

Commit 12c6a75

Browse files
committed
Auto merge of #54012 - denismerigoux:cg-llvm-gen, r=<try>
rustc_codegen_llvm: traitification of LLVM-specific CodegenCx and Builder methods This PR is the continuation of #52461 in the grand plan of #45274 to allow for multiple codegen backends. A first attempt at this was #52987 but since @irinagpopa is no longer working on it I'm taking ownership of the PR. The changes are refactoring only and do not affect the logic of the code. Performance should not be impacted since all parametrization is done with generics (no trait objects). The `librustc_codegen_llvm` crate now contains a new folder `interfaces` that describes with traits part of how the compiler interfaces with LLVM during codegen. `CodegenCx` and `Builder` implement those traits. Many things are still missing. All the calls to LLVM are not yet under a trait, and later LLVM-agnostic code should be parametrized.
2 parents a8c11d2 + 5a880b7 commit 12c6a75

Some content is hidden

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

42 files changed

+2387
-1464
lines changed

src/librustc_codegen_llvm/abi.rs

+64-43
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@
1111
use llvm::{self, AttributePlace};
1212
use base;
1313
use builder::{Builder, MemFlags};
14-
use common::{ty_fn_sig, C_usize};
14+
use common::ty_fn_sig;
1515
use context::CodegenCx;
1616
use mir::place::PlaceRef;
1717
use mir::operand::OperandValue;
1818
use type_::Type;
1919
use type_of::{LayoutLlvmExt, PointerKind};
2020
use value::Value;
2121

22+
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
23+
2224
use rustc_target::abi::{LayoutOf, Size, TyLayout};
2325
use rustc::ty::{self, Ty};
2426
use rustc::ty::layout;
@@ -104,29 +106,29 @@ impl ArgAttributesExt for ArgAttributes {
104106
}
105107

106108
pub trait LlvmType {
107-
fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type;
109+
fn llvm_type(&self, cx: &CodegenCx<'ll, '_, &'ll Value>) -> &'ll Type;
108110
}
109111

110112
impl LlvmType for Reg {
111-
fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
113+
fn llvm_type(&self, cx: &CodegenCx<'ll, '_, &'ll Value>) -> &'ll Type {
112114
match self.kind {
113-
RegKind::Integer => Type::ix(cx, self.size.bits()),
115+
RegKind::Integer => cx.type_ix(self.size.bits()),
114116
RegKind::Float => {
115117
match self.size.bits() {
116-
32 => Type::f32(cx),
117-
64 => Type::f64(cx),
118+
32 => cx.type_f32(),
119+
64 => cx.type_f64(),
118120
_ => bug!("unsupported float: {:?}", self)
119121
}
120122
}
121123
RegKind::Vector => {
122-
Type::vector(Type::i8(cx), self.size.bytes())
124+
cx.type_vector(cx.type_i8(), self.size.bytes())
123125
}
124126
}
125127
}
126128
}
127129

128130
impl LlvmType for CastTarget {
129-
fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
131+
fn llvm_type(&self, cx: &CodegenCx<'ll, '_, &'ll Value>) -> &'ll Type {
130132
let rest_ll_unit = self.rest.unit.llvm_type(cx);
131133
let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 {
132134
(0, 0)
@@ -143,7 +145,7 @@ impl LlvmType for CastTarget {
143145

144146
// Simplify to array when all chunks are the same size and type
145147
if rem_bytes == 0 {
146-
return Type::array(rest_ll_unit, rest_count);
148+
return cx.type_array(rest_ll_unit, rest_count);
147149
}
148150
}
149151

@@ -158,35 +160,49 @@ impl LlvmType for CastTarget {
158160
if rem_bytes != 0 {
159161
// Only integers can be really split further.
160162
assert_eq!(self.rest.unit.kind, RegKind::Integer);
161-
args.push(Type::ix(cx, rem_bytes * 8));
163+
args.push(cx.type_ix(rem_bytes * 8));
162164
}
163165

164-
Type::struct_(cx, &args, false)
166+
cx.type_struct(&args, false)
165167
}
166168
}
167169

168170
pub trait ArgTypeExt<'ll, 'tcx> {
169-
fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
170-
fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>);
171-
fn store_fn_arg(&self, bx: &Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>);
171+
fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx, &'ll Value>) -> &'ll Type;
172+
fn store(
173+
&self,
174+
bx: &Builder<'_, 'll, 'tcx, &'ll Value>,
175+
val: &'ll Value,
176+
dst: PlaceRef<'tcx, &'ll Value>
177+
);
178+
fn store_fn_arg(
179+
&self,
180+
bx: &Builder<'_, 'll, 'tcx, &'ll Value>,
181+
idx: &mut usize, dst: PlaceRef<'tcx, &'ll Value>
182+
);
172183
}
173184

174185
impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
175186
/// Get the LLVM type for a place of the original Rust type of
176187
/// this argument/return, i.e. the result of `type_of::type_of`.
177-
fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
188+
fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx, &'ll Value>) -> &'ll Type {
178189
self.layout.llvm_type(cx)
179190
}
180191

181192
/// Store a direct/indirect value described by this ArgType into a
182193
/// place for the original Rust type of this argument/return.
183194
/// Can be used for both storing formal arguments into Rust variables
184195
/// or results of call/invoke instructions into their destinations.
185-
fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>) {
196+
fn store(
197+
&self,
198+
bx: &Builder<'_, 'll, 'tcx, &'ll Value>,
199+
val: &'ll Value,
200+
dst: PlaceRef<'tcx, &'ll Value>
201+
) {
186202
if self.is_ignore() {
187203
return;
188204
}
189-
let cx = bx.cx;
205+
let cx = bx.cx();
190206
if self.is_sized_indirect() {
191207
OperandValue::Ref(val, None, self.layout.align).store(bx, dst)
192208
} else if self.is_unsized_indirect() {
@@ -196,7 +212,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
196212
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
197213
let can_store_through_cast_ptr = false;
198214
if can_store_through_cast_ptr {
199-
let cast_dst = bx.pointercast(dst.llval, cast.llvm_type(cx).ptr_to());
215+
let cast_dst = bx.pointercast(dst.llval, cx.type_ptr_to(cast.llvm_type(cx)));
200216
bx.store(val, cast_dst, self.layout.align);
201217
} else {
202218
// The actual return type is a struct, but the ABI
@@ -224,9 +240,9 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
224240

225241
// ...and then memcpy it to the intended destination.
226242
base::call_memcpy(bx,
227-
bx.pointercast(dst.llval, Type::i8p(cx)),
228-
bx.pointercast(llscratch, Type::i8p(cx)),
229-
C_usize(cx, self.layout.size.bytes()),
243+
bx.pointercast(dst.llval, cx.type_i8p()),
244+
bx.pointercast(llscratch, cx.type_i8p()),
245+
cx.const_usize(self.layout.size.bytes()),
230246
self.layout.align.min(scratch_align),
231247
MemFlags::empty());
232248

@@ -237,7 +253,12 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
237253
}
238254
}
239255

240-
fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>) {
256+
fn store_fn_arg(
257+
&self,
258+
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
259+
idx: &mut usize,
260+
dst: PlaceRef<'tcx, &'ll Value>
261+
) {
241262
let mut next = || {
242263
let val = llvm::get_param(bx.llfn(), *idx as c_uint);
243264
*idx += 1;
@@ -259,47 +280,47 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
259280
}
260281

261282
pub trait FnTypeExt<'tcx> {
262-
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
283+
fn of_instance(cx: &CodegenCx<'ll, 'tcx, &'ll Value>, instance: &ty::Instance<'tcx>)
263284
-> Self;
264-
fn new(cx: &CodegenCx<'ll, 'tcx>,
285+
fn new(cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
265286
sig: ty::FnSig<'tcx>,
266287
extra_args: &[Ty<'tcx>]) -> Self;
267-
fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
288+
fn new_vtable(cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
268289
sig: ty::FnSig<'tcx>,
269290
extra_args: &[Ty<'tcx>]) -> Self;
270291
fn new_internal(
271-
cx: &CodegenCx<'ll, 'tcx>,
292+
cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
272293
sig: ty::FnSig<'tcx>,
273294
extra_args: &[Ty<'tcx>],
274295
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
275296
) -> Self;
276297
fn adjust_for_abi(&mut self,
277-
cx: &CodegenCx<'ll, 'tcx>,
298+
cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
278299
abi: Abi);
279-
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
300+
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx, &'ll Value>) -> &'ll Type;
280301
fn llvm_cconv(&self) -> llvm::CallConv;
281302
fn apply_attrs_llfn(&self, llfn: &'ll Value);
282-
fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
303+
fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx, &'ll Value>, callsite: &'ll Value);
283304
}
284305

285306
impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
286-
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
307+
fn of_instance(cx: &CodegenCx<'ll, 'tcx, &'ll Value>, instance: &ty::Instance<'tcx>)
287308
-> Self {
288309
let fn_ty = instance.ty(cx.tcx);
289310
let sig = ty_fn_sig(cx, fn_ty);
290311
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
291312
FnType::new(cx, sig, &[])
292313
}
293314

294-
fn new(cx: &CodegenCx<'ll, 'tcx>,
315+
fn new(cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
295316
sig: ty::FnSig<'tcx>,
296317
extra_args: &[Ty<'tcx>]) -> Self {
297318
FnType::new_internal(cx, sig, extra_args, |ty, _| {
298319
ArgType::new(cx.layout_of(ty))
299320
})
300321
}
301322

302-
fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
323+
fn new_vtable(cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
303324
sig: ty::FnSig<'tcx>,
304325
extra_args: &[Ty<'tcx>]) -> Self {
305326
FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
@@ -326,7 +347,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
326347
}
327348

328349
fn new_internal(
329-
cx: &CodegenCx<'ll, 'tcx>,
350+
cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
330351
sig: ty::FnSig<'tcx>,
331352
extra_args: &[Ty<'tcx>],
332353
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
@@ -507,7 +528,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
507528
}
508529

509530
fn adjust_for_abi(&mut self,
510-
cx: &CodegenCx<'ll, 'tcx>,
531+
cx: &CodegenCx<'ll, 'tcx, &'ll Value>,
511532
abi: Abi) {
512533
if abi == Abi::Unadjusted { return }
513534

@@ -574,7 +595,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
574595
}
575596
}
576597

577-
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
598+
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx, &'ll Value>) -> &'ll Type {
578599
let args_capacity: usize = self.args.iter().map(|arg|
579600
if arg.pad.is_some() { 1 } else { 0 } +
580601
if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
@@ -584,14 +605,14 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
584605
);
585606

586607
let llreturn_ty = match self.ret.mode {
587-
PassMode::Ignore => Type::void(cx),
608+
PassMode::Ignore => cx.type_void(),
588609
PassMode::Direct(_) | PassMode::Pair(..) => {
589610
self.ret.layout.immediate_llvm_type(cx)
590611
}
591612
PassMode::Cast(cast) => cast.llvm_type(cx),
592613
PassMode::Indirect(..) => {
593-
llargument_tys.push(self.ret.memory_ty(cx).ptr_to());
594-
Type::void(cx)
614+
llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
615+
cx.type_void()
595616
}
596617
};
597618

@@ -617,15 +638,15 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
617638
continue;
618639
}
619640
PassMode::Cast(cast) => cast.llvm_type(cx),
620-
PassMode::Indirect(_, None) => arg.memory_ty(cx).ptr_to(),
641+
PassMode::Indirect(_, None) => cx.type_ptr_to(arg.memory_ty(cx)),
621642
};
622643
llargument_tys.push(llarg_ty);
623644
}
624645

625646
if self.variadic {
626-
Type::variadic_func(&llargument_tys, llreturn_ty)
647+
cx.type_variadic_func(&llargument_tys, llreturn_ty)
627648
} else {
628-
Type::func(&llargument_tys, llreturn_ty)
649+
cx.type_func(&llargument_tys, llreturn_ty)
629650
}
630651
}
631652

@@ -680,7 +701,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
680701
}
681702
}
682703

683-
fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
704+
fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx, &'ll Value>, callsite: &'ll Value) {
684705
let mut i = 0;
685706
let mut apply = |attrs: &ArgAttributes| {
686707
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
@@ -699,7 +720,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
699720
// by the LLVM verifier.
700721
match scalar.value {
701722
layout::Int(..) if !scalar.is_bool() => {
702-
let range = scalar.valid_range_exclusive(bx.cx);
723+
let range = scalar.valid_range_exclusive(bx.cx());
703724
if range.start != range.end {
704725
bx.range_metadata(callsite, range);
705726
}

src/librustc_codegen_llvm/asm.rs

+12-18
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,25 @@
99
// except according to those terms.
1010

1111
use llvm;
12-
use common::*;
13-
use type_::Type;
12+
use context::CodegenCx;
1413
use type_of::LayoutLlvmExt;
1514
use builder::Builder;
1615
use value::Value;
1716

1817
use rustc::hir;
18+
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
1919

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

2323
use std::ffi::CString;
24-
use syntax::ast::AsmDialect;
2524
use libc::{c_uint, c_char};
2625

2726
// Take an inline assembly expression and splat it out via LLVM
2827
pub fn codegen_inline_asm(
29-
bx: &Builder<'a, 'll, 'tcx>,
28+
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
3029
ia: &hir::InlineAsm,
31-
outputs: Vec<PlaceRef<'ll, 'tcx>>,
30+
outputs: Vec<PlaceRef<'tcx, &'ll Value>>,
3231
mut inputs: Vec<&'ll Value>
3332
) {
3433
let mut ext_constraints = vec![];
@@ -44,7 +43,7 @@ pub fn codegen_inline_asm(
4443
if out.is_indirect {
4544
indirect_outputs.push(place.load(bx).immediate());
4645
} else {
47-
output_types.push(place.layout.llvm_type(bx.cx));
46+
output_types.push(place.layout.llvm_type(bx.cx()));
4847
}
4948
}
5049
if !indirect_outputs.is_empty() {
@@ -76,14 +75,9 @@ pub fn codegen_inline_asm(
7675
// Depending on how many outputs we have, the return type is different
7776
let num_outputs = output_types.len();
7877
let output_type = match num_outputs {
79-
0 => Type::void(bx.cx),
78+
0 => bx.cx().type_void(),
8079
1 => output_types[0],
81-
_ => Type::struct_(bx.cx, &output_types, false)
82-
};
83-
84-
let dialect = match ia.dialect {
85-
AsmDialect::Att => llvm::AsmDialect::Att,
86-
AsmDialect::Intel => llvm::AsmDialect::Intel,
80+
_ => bx.cx().type_struct(&output_types, false)
8781
};
8882

8983
let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
@@ -95,7 +89,7 @@ pub fn codegen_inline_asm(
9589
output_type,
9690
ia.volatile,
9791
ia.alignstack,
98-
dialect
92+
ia.dialect
9993
);
10094

10195
// Again, based on how many outputs we have
@@ -109,17 +103,17 @@ pub fn codegen_inline_asm(
109103
// back to source locations. See #17552.
110104
unsafe {
111105
let key = "srcloc";
112-
let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx,
106+
let kind = llvm::LLVMGetMDKindIDInContext(bx.cx().llcx,
113107
key.as_ptr() as *const c_char, key.len() as c_uint);
114108

115-
let val: &'ll Value = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
109+
let val: &'ll Value = bx.cx().const_i32(ia.ctxt.outer().as_u32() as i32);
116110

117111
llvm::LLVMSetMetadata(r, kind,
118-
llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
112+
llvm::LLVMMDNodeInContext(bx.cx().llcx, &val, 1));
119113
}
120114
}
121115

122-
pub fn codegen_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
116+
pub fn codegen_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx, &'a Value>,
123117
ga: &hir::GlobalAsm) {
124118
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
125119
unsafe {

0 commit comments

Comments
 (0)