Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_codegen_llvm: traitification of LLVM-specific CodegenCx and Builder methods #55627

Merged
merged 73 commits into from
Nov 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
5a9e6b8
rustc_codegen_llvm: begin generalizing over backend values.
irinagpopa Aug 2, 2018
c76fc3d
Work around to fix issue https://github.com/rust-lang/rust/issues/53912
denismerigoux Sep 6, 2018
83b2152
Reduced line length to pass tidy
denismerigoux Aug 3, 2018
34c5dc0
Generalized base.rs#call_memcpy and everything that it uses
denismerigoux Aug 7, 2018
14798d6
Generalized BasicBlocks in BuilderMethods trait
denismerigoux Aug 20, 2018
51b7f27
Generalized IntPredicate in the BuilderMethods trait
denismerigoux Aug 20, 2018
8590336
Generalized RealPredicate
denismerigoux Aug 21, 2018
bc86624
Removed useless traits for IntPredicate and RealPredicate
denismerigoux Aug 21, 2018
1bcb4df
Generalized OperandBundleDef in BuilderMethods
denismerigoux Aug 21, 2018
2755891
Generalized AtomicRmwBinOp for BuilderMethods
denismerigoux Aug 21, 2018
b699866
Generalized AtomicOrdering for BuilderMethods
denismerigoux Aug 21, 2018
b761538
Generalized SynchronisationScope for BuilderMethods
denismerigoux Aug 21, 2018
1ca7506
Generalized AsmDialect for BuilderMethods
denismerigoux Aug 21, 2018
9c41e1a
Removed genericity over Value in various functions
denismerigoux Aug 22, 2018
89825f2
Use associated types instead of type parameters inside the BuilderMet…
denismerigoux Aug 22, 2018
a16d85b
Removed parasite yaml file and put explicit lifetimes
denismerigoux Aug 23, 2018
7a2670e
Use real type names rather than Self::
denismerigoux Aug 23, 2018
d577ec7
New files and folders for traits
denismerigoux Aug 28, 2018
3889c2d
New Backend trait containing associated types
denismerigoux Aug 28, 2018
8714e6b
Traitification of common.rs methods
denismerigoux Aug 28, 2018
d325844
Replaced Codegen field access by trait method
denismerigoux Aug 28, 2018
83e07f9
Added self argument for Codegen CommonMethod trait methods
denismerigoux Aug 29, 2018
3aee772
Split CommonMethods to accomodate for use in back/write.rs
denismerigoux Aug 29, 2018
4cc18d3
CommonWriteMethods are not static any more
denismerigoux Aug 29, 2018
33eee83
Removed code duplication for CommonWriteMethods
denismerigoux Aug 30, 2018
6c5b990
All CommonMethods now real methods (not static)
denismerigoux Aug 30, 2018
3e77f2f
Use the method form for CodegenCx everywhere
denismerigoux Aug 30, 2018
5f28e0a
Added definition of type trait
denismerigoux Aug 30, 2018
730b13a
Traitification of type_ methods
denismerigoux Sep 5, 2018
6d42574
Prefixed const methods with "const" instead of "c"
denismerigoux Sep 6, 2018
e224f06
Prefixed type methods & removed trait impl for write::CodegenContext
denismerigoux Sep 6, 2018
a1d0d4f
Removing LLVM content from CommonMethods -> ConstMethods
denismerigoux Sep 6, 2018
4787b7c
Removed phantomdata no longer necessary
denismerigoux Sep 6, 2018
1929ac2
Fixed typos
denismerigoux Sep 7, 2018
c487b82
Attempt at including CodegenCx within Builder with Associated types
denismerigoux Sep 7, 2018
0514c7b
Generalized some base.rs methods
denismerigoux Sep 7, 2018
d77e34f
Generalized memset and memcpy
denismerigoux Sep 7, 2018
3c082a2
Added StaticMethods trait
denismerigoux Sep 10, 2018
a5aeb8e
Transfered memcpy and memset to BuilderMethods
denismerigoux Sep 10, 2018
0a1c509
Traitified IntrinsicCallMethods
denismerigoux Sep 11, 2018
484e07c
[eddyb/rebase cleanup] s/&self./self.
eddyb Nov 7, 2018
034f697
Generalized base::unsized_info
denismerigoux Sep 13, 2018
78dd95f
Generalized base::unsize_thin_ptr
denismerigoux Sep 13, 2018
cbe31a4
Generalized base::coerce_unsized_into
denismerigoux Sep 14, 2018
6a993fe
Generalized mir::codegen_mir (and all subsequent functions)
denismerigoux Sep 20, 2018
441a7c1
Generalized mono_item.rs and base.rs:codegen_instance
denismerigoux Sep 21, 2018
b14f3e5
Adapt code to latest rustc master changes
denismerigoux Sep 24, 2018
ac34068
Generalized base:maybe_create_entry_wrapper
denismerigoux Sep 24, 2018
97825a3
Move doc to trait declarations
denismerigoux Sep 24, 2018
8d530db
Generalized base:codegen_crate
denismerigoux Sep 25, 2018
91a2a80
Renamed lifetimes for better understanding
denismerigoux Sep 26, 2018
6819e6e
Preparing the generalization of base:compile_coodegen_unit
denismerigoux Sep 26, 2018
4ba09ab
Added compile codegen to backend trait
denismerigoux Sep 27, 2018
39fd4d9
Starting to move backend-agnostic code into codegen_utils
denismerigoux Sep 28, 2018
566fa4d
Moved common.rs enums
denismerigoux Sep 28, 2018
35b40f5
[eddyb/rebase cleanup] abstracted Funclet
eddyb Nov 13, 2018
b06836e
[eddyb/rebase cleanup] move type_{needs_drop,is_sized,is_freeze} to r…
eddyb Nov 13, 2018
b02e5cc
Moved Backend interface into rustc_codegen_utils
denismerigoux Oct 1, 2018
c9f26c2
Beginning of moving all backend-agnostic code to rustc_codegen_ssa
denismerigoux Oct 1, 2018
915382f
Moved DeclareMethods, MiscMethods and StaticMethods
denismerigoux Oct 2, 2018
c0a428e
Great separation of librustc_codegen_llvm: librustc_codegen_ssa compiles
denismerigoux Oct 3, 2018
015e444
Finished moving backend-agnostic code to rustc_codegen_ssa
denismerigoux Oct 3, 2018
1ebdfbb
Added some docs + start to &mut self builder methods
denismerigoux Oct 4, 2018
54dd3a4
All Builder methods now take &mut self instead of &self
denismerigoux Oct 5, 2018
b25b804
Added default impl for DerivedTypeMethods + empty impl for Cranelift …
denismerigoux Oct 9, 2018
b9e5cf9
Separating the back folder between backend-agnostic and LLVM-specific…
denismerigoux Oct 23, 2018
bf7f8cd
Added README explaining the refactoring
denismerigoux Oct 22, 2018
9bb6663
[eddyb] rustc_codegen_ssa: handle LLVM unsafety correctly.
eddyb Nov 16, 2018
9f49a26
[eddyb] rustc_codegen_utils: remove extraneous `#![allow(dead_code)]`.
eddyb Nov 16, 2018
47c84c4
[eddyb] rustc_codegen_llvm: remove unnecessary `'a` from `LlvmCodegen…
eddyb Nov 16, 2018
d1410ad
[eddyb] rustc_codegen_ssa: avoid a `Clone` bound on `TargetMachine`.
eddyb Nov 16, 2018
0b56924
[eddyb] rustc_codegen_ssa: rename `interfaces` to `traits`.
eddyb Nov 16, 2018
756f84d
[eddyb] rustc_codegen_llvm: remove unused parametrization of `Codegen…
eddyb Nov 16, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2122,23 +2122,32 @@ dependencies = [
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_codegen_ssa 0.0.0",
"rustc_llvm 0.0.0",
]

[[package]]
name = "rustc_codegen_ssa"
version = "0.0.0"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rustc_codegen_utils"
version = "0.0.0"
dependencies = [
"flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_allocator 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_incremental 0.0.0",
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_target 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_llvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ test = false
cc = "1.0.1"
num_cpus = "1.0"
rustc-demangle = "0.1.4"
rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
rustc_llvm = { path = "../librustc_llvm" }
memmap = "0.6"

Expand Down
146 changes: 108 additions & 38 deletions src/librustc_codegen_llvm/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@
// except according to those terms.

use llvm::{self, AttributePlace};
use base;
use builder::{Builder, MemFlags};
use common::C_usize;
use rustc_codegen_ssa::MemFlags;
use builder::Builder;
use context::CodegenCx;
use mir::place::PlaceRef;
use mir::operand::OperandValue;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::mir::operand::OperandValue;
use type_::Type;
use type_of::{LayoutLlvmExt, PointerKind};
use value::Value;
use rustc_target::abi::call::ArgType;

use rustc_codegen_ssa::traits::*;

use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
use rustc::ty::{self, Ty};
use rustc::ty::{self, Ty, Instance};
use rustc::ty::layout;

use libc::c_uint;
Expand Down Expand Up @@ -110,16 +112,16 @@ pub trait LlvmType {
impl LlvmType for Reg {
fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
match self.kind {
RegKind::Integer => Type::ix(cx, self.size.bits()),
RegKind::Integer => cx.type_ix(self.size.bits()),
RegKind::Float => {
match self.size.bits() {
32 => Type::f32(cx),
64 => Type::f64(cx),
32 => cx.type_f32(),
64 => cx.type_f64(),
_ => bug!("unsupported float: {:?}", self)
}
}
RegKind::Vector => {
Type::vector(Type::i8(cx), self.size.bytes())
cx.type_vector(cx.type_i8(), self.size.bytes())
}
}
}
Expand All @@ -143,7 +145,7 @@ impl LlvmType for CastTarget {

// Simplify to array when all chunks are the same size and type
if rem_bytes == 0 {
return Type::array(rest_ll_unit, rest_count);
return cx.type_array(rest_ll_unit, rest_count);
}
}

Expand All @@ -158,17 +160,27 @@ impl LlvmType for CastTarget {
if rem_bytes != 0 {
// Only integers can be really split further.
assert_eq!(self.rest.unit.kind, RegKind::Integer);
args.push(Type::ix(cx, rem_bytes * 8));
args.push(cx.type_ix(rem_bytes * 8));
}

Type::struct_(cx, &args, false)
cx.type_struct(&args, false)
}
}

pub trait ArgTypeExt<'ll, 'tcx> {
fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>);
fn store_fn_arg(&self, bx: &Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>);
fn store(
&self,
bx: &mut Builder<'_, 'll, 'tcx>,
val: &'ll Value,
dst: PlaceRef<'tcx, &'ll Value>,
);
fn store_fn_arg(
&self,
bx: &mut Builder<'_, 'll, 'tcx>,
idx: &mut usize,
dst: PlaceRef<'tcx, &'ll Value>,
);
}

impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
Expand All @@ -182,11 +194,15 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
/// place for the original Rust type of this argument/return.
/// Can be used for both storing formal arguments into Rust variables
/// or results of call/invoke instructions into their destinations.
fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>) {
fn store(
&self,
bx: &mut Builder<'_, 'll, 'tcx>,
val: &'ll Value,
dst: PlaceRef<'tcx, &'ll Value>,
) {
if self.is_ignore() {
return;
}
let cx = bx.cx;
if self.is_sized_indirect() {
OperandValue::Ref(val, None, self.layout.align).store(bx, dst)
} else if self.is_unsized_indirect() {
Expand All @@ -196,7 +212,8 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
let can_store_through_cast_ptr = false;
if can_store_through_cast_ptr {
let cast_dst = bx.pointercast(dst.llval, cast.llvm_type(cx).ptr_to());
let cast_ptr_llty = bx.cx().type_ptr_to(cast.llvm_type(bx.cx()));
let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty);
bx.store(val, cast_dst, self.layout.align);
} else {
// The actual return type is a struct, but the ABI
Expand All @@ -214,22 +231,23 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
// bitcasting to the struct type yields invalid cast errors.

// We instead thus allocate some scratch space...
let scratch_size = cast.size(cx);
let scratch_align = cast.align(cx);
let llscratch = bx.alloca(cast.llvm_type(cx), "abi_cast", scratch_align);
let scratch_size = cast.size(bx.cx());
let scratch_align = cast.align(bx.cx());
let llscratch = bx.alloca(cast.llvm_type(bx.cx()), "abi_cast", scratch_align);
bx.lifetime_start(llscratch, scratch_size);

// ...where we first store the value...
bx.store(val, llscratch, scratch_align);

// ...and then memcpy it to the intended destination.
base::call_memcpy(bx,
bx.pointercast(dst.llval, Type::i8p(cx)),
self.layout.align,
bx.pointercast(llscratch, Type::i8p(cx)),
scratch_align,
C_usize(cx, self.layout.size.bytes()),
MemFlags::empty());
bx.memcpy(
dst.llval,
self.layout.align,
llscratch,
scratch_align,
bx.cx().const_usize(self.layout.size.bytes()),
MemFlags::empty()
);

bx.lifetime_end(llscratch, scratch_size);
}
Expand All @@ -238,7 +256,12 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
}
}

fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>) {
fn store_fn_arg(
&self,
bx: &mut Builder<'a, 'll, 'tcx>,
idx: &mut usize,
dst: PlaceRef<'tcx, &'ll Value>,
) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a LLVM-ism, does Cranelift support getting at the function params from a builder? What I'd do instead is also pass a slice of values, alongside the index.

let mut next = || {
let val = llvm::get_param(bx.llfn(), *idx as c_uint);
*idx += 1;
Expand All @@ -259,6 +282,27 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
}
}

impl ArgTypeMethods<'tcx> for Builder<'a, 'll, 'tcx> {
fn store_fn_arg(
&mut self,
ty: &ArgType<'tcx, Ty<'tcx>>,
idx: &mut usize, dst: PlaceRef<'tcx, Self::Value>
) {
ty.store_fn_arg(self, idx, dst)
}
fn store_arg_ty(
&mut self,
ty: &ArgType<'tcx, Ty<'tcx>>,
val: &'ll Value,
dst: PlaceRef<'tcx, &'ll Value>
) {
ty.store(self, val, dst)
}
fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> &'ll Type {
ty.memory_ty(self.cx())
}
}

pub trait FnTypeExt<'tcx> {
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self;
fn new(cx: &CodegenCx<'ll, 'tcx>,
Expand All @@ -280,7 +324,7 @@ pub trait FnTypeExt<'tcx> {
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
fn llvm_cconv(&self) -> llvm::CallConv;
fn apply_attrs_llfn(&self, llfn: &'ll Value);
fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
}

impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
Expand Down Expand Up @@ -614,14 +658,14 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
);

let llreturn_ty = match self.ret.mode {
PassMode::Ignore => Type::void(cx),
PassMode::Ignore => cx.type_void(),
PassMode::Direct(_) | PassMode::Pair(..) => {
self.ret.layout.immediate_llvm_type(cx)
}
PassMode::Cast(cast) => cast.llvm_type(cx),
PassMode::Indirect(..) => {
llargument_tys.push(self.ret.memory_ty(cx).ptr_to());
Type::void(cx)
llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
cx.type_void()
}
};

Expand All @@ -647,15 +691,15 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
continue;
}
PassMode::Cast(cast) => cast.llvm_type(cx),
PassMode::Indirect(_, None) => arg.memory_ty(cx).ptr_to(),
PassMode::Indirect(_, None) => cx.type_ptr_to(arg.memory_ty(cx)),
};
llargument_tys.push(llarg_ty);
}

if self.variadic {
Type::variadic_func(&llargument_tys, llreturn_ty)
cx.type_variadic_func(&llargument_tys, llreturn_ty)
} else {
Type::func(&llargument_tys, llreturn_ty)
cx.type_func(&llargument_tys, llreturn_ty)
}
}

Expand Down Expand Up @@ -717,7 +761,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
}
}

fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
let mut i = 0;
let mut apply = |attrs: &ArgAttributes| {
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
Expand All @@ -736,7 +780,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
// by the LLVM verifier.
if let layout::Int(..) = scalar.value {
if !scalar.is_bool() {
let range = scalar.valid_range_exclusive(bx.cx);
let range = scalar.valid_range_exclusive(bx.cx());
if range.start != range.end {
bx.range_metadata(callsite, range);
}
Expand Down Expand Up @@ -769,3 +813,29 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
}
}
}

impl AbiMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn new_fn_type(&self, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType<'tcx, Ty<'tcx>> {
FnType::new(&self, sig, extra_args)
}
fn new_vtable(
&self,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]
) -> FnType<'tcx, Ty<'tcx>> {
FnType::new_vtable(&self, sig, extra_args)
}
fn fn_type_of_instance(&self, instance: &Instance<'tcx>) -> FnType<'tcx, Ty<'tcx>> {
FnType::of_instance(&self, instance)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do any of these depend on anything LLVM-specific? IMO these could be moved into rustc_codegen_ssa or even rustc itself!

}

impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
fn apply_attrs_callsite(
&mut self,
ty: &FnType<'tcx, Ty<'tcx>>,
callsite: Self::Value
) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think it might be better if instead of the "apply attrs" LLVM-ism, the call/invoke methods of Builder took an FnType and internally called the LLVM-only apply_attrs_callsite.

ty.apply_attrs_callsite(self, callsite)
}
}
Loading