Skip to content

Commit

Permalink
Great separation of librustc_codegen_llvm: librustc_codegen_ssa compiles
Browse files Browse the repository at this point in the history
  • Loading branch information
denismerigoux authored and eddyb committed Nov 16, 2018
1 parent 915382f commit c0a428e
Show file tree
Hide file tree
Showing 41 changed files with 1,634 additions and 1,470 deletions.
924 changes: 9 additions & 915 deletions src/librustc_codegen_llvm/base.rs

Large diffs are not rendered by default.

8 changes: 0 additions & 8 deletions src/librustc_codegen_llvm/builder.rs
Expand Up @@ -53,14 +53,6 @@ fn noname() -> *const c_char {
&CNULL
}

bitflags! {
pub struct MemFlags: u8 {
const VOLATILE = 1 << 0;
const NONTEMPORAL = 1 << 1;
const UNALIGNED = 1 << 2;
}
}

impl BackendTypes for Builder<'_, 'll, 'tcx> {
type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
Expand Down
32 changes: 0 additions & 32 deletions src/librustc_codegen_llvm/callee.rs
Expand Up @@ -202,35 +202,3 @@ pub fn get_fn(

llfn
}

pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>(
cx: &Cx,
def_id: DefId,
substs: &'tcx Substs<'tcx>,
) -> Cx::Value {
cx.get_fn(
ty::Instance::resolve(
cx.tcx(),
ty::ParamEnv::reveal_all(),
def_id,
substs
).unwrap()
)
}

pub fn resolve_and_get_fn_for_vtable<'tcx,
Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
>(
cx: &Cx,
def_id: DefId,
substs: &'tcx Substs<'tcx>,
) -> Cx::Value {
cx.get_fn(
ty::Instance::resolve_for_vtable(
cx.tcx(),
ty::ParamEnv::reveal_all(),
def_id,
substs
).unwrap()
)
}
85 changes: 0 additions & 85 deletions src/librustc_codegen_llvm/common.rs
Expand Up @@ -405,88 +405,3 @@ pub fn struct_in_context(
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
((hi as u128) << 64) | (lo as u128)
}

pub fn langcall(tcx: TyCtxt,
span: Option<Span>,
msg: &str,
li: LangItem)
-> DefId {
tcx.lang_items().require(li).unwrap_or_else(|s| {
let msg = format!("{} {}", msg, s);
match span {
Some(span) => tcx.sess.span_fatal(span, &msg[..]),
None => tcx.sess.fatal(&msg[..]),
}
})
}

// To avoid UB from LLVM, these two functions mask RHS with an
// appropriate mask unconditionally (i.e. the fallback behavior for
// all shifts). For 32- and 64-bit types, this matches the semantics
// of Java. (See related discussion on #1877 and #10183.)

pub fn build_unchecked_lshift<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
bx: &Bx,
lhs: Bx::Value,
rhs: Bx::Value
) -> Bx::Value {
let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
let rhs = shift_mask_rhs(bx, rhs);
bx.shl(lhs, rhs)
}

pub fn build_unchecked_rshift<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
bx: &Bx,
lhs_t: Ty<'tcx>,
lhs: Bx::Value,
rhs: Bx::Value
) -> Bx::Value {
let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
let rhs = shift_mask_rhs(bx, rhs);
let is_signed = lhs_t.is_signed();
if is_signed {
bx.ashr(lhs, rhs)
} else {
bx.lshr(lhs, rhs)
}
}

fn shift_mask_rhs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
bx: &Bx,
rhs: Bx::Value
) -> Bx::Value {
let rhs_llty = bx.cx().val_ty(rhs);
bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
}

pub fn shift_mask_val<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
bx: &Bx,
llty: Bx::Type,
mask_llty: Bx::Type,
invert: bool
) -> Bx::Value {
let kind = bx.cx().type_kind(llty);
match kind {
TypeKind::Integer => {
// i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
let val = bx.cx().int_width(llty) - 1;
if invert {
bx.cx().const_int(mask_llty, !val as i64)
} else {
bx.cx().const_uint(mask_llty, val)
}
},
TypeKind::Vector => {
let mask = shift_mask_val(
bx,
bx.cx().element_type(llty),
bx.cx().element_type(mask_llty),
invert
);
bx.vector_splat(bx.cx().vector_length(mask_llty), mask)
},
_ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
}
}
52 changes: 52 additions & 0 deletions src/librustc_codegen_llvm/consts.rs
Expand Up @@ -31,6 +31,58 @@ use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags};

use std::ffi::{CStr, CString};

pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
let dl = cx.data_layout();
let pointer_size = dl.pointer_size.bytes() as usize;

let mut next_offset = 0;
for &(offset, ((), alloc_id)) in alloc.relocations.iter() {
let offset = offset.bytes();
assert_eq!(offset as usize as u64, offset);
let offset = offset as usize;
if offset > next_offset {
llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset]));
}
let ptr_offset = read_target_uint(
dl.endian,
&alloc.bytes[offset..(offset + pointer_size)],
).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
llvals.push(cx.scalar_to_backend(
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
&layout::Scalar {
value: layout::Primitive::Pointer,
valid_range: 0..=!0
},
cx.type_i8p()
));
next_offset = offset + pointer_size;
}
if alloc.bytes.len() >= next_offset {
llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..]));
}

cx.const_struct(&llvals, true)
}

pub fn codegen_static_initializer(
cx: &CodegenCx<'ll, 'tcx>,
def_id: DefId,
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
let instance = ty::Instance::mono(cx.tcx, def_id);
let cid = GlobalId {
instance,
promoted: None,
};
let param_env = ty::ParamEnv::reveal_all();
let static_ = cx.tcx.const_eval(param_env.and(cid))?;

let alloc = match static_.val {
ConstValue::ByRef(_, alloc, n) if n.bytes() == 0 => alloc,
_ => bug!("static const eval returned {:#?}", static_),
};
Ok((const_alloc_to_llvm(cx, alloc), alloc))
}

fn set_global_alignment(cx: &CodegenCx<'ll, '_>,
gv: &'ll Value,
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_codegen_llvm/context.rs
Expand Up @@ -10,6 +10,7 @@

use attributes;
use llvm;
use llvm_util;
use rustc::dep_graph::DepGraphSafe;
use rustc::hir;
use debuginfo;
Expand Down Expand Up @@ -445,6 +446,9 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
attributes::apply_target_cpu_attr(self, llfn)
}

fn closure_env_needs_indirect_debuginfo(&self) {
llvm_util::get_major_version() < 6
}

fn create_used_variable(&self) {
let name = const_cstr!("llvm.used");
Expand Down
15 changes: 0 additions & 15 deletions src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
Expand Up @@ -26,21 +26,6 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};

use syntax_pos::BytePos;

#[derive(Clone, Copy, Debug)]
pub struct MirDebugScope<D> {
pub scope_metadata: Option<D>,
// Start and end offsets of the file to which this DIScope belongs.
// These are used to quickly determine whether some span refers to the same file.
pub file_start_pos: BytePos,
pub file_end_pos: BytePos,
}

impl<D> MirDebugScope<D> {
pub fn is_valid(&self) -> bool {
self.scope_metadata.is_some()
}
}

/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
/// If debuginfo is disabled, the returned vector is empty.
pub fn create_mir_scopes(
Expand Down
71 changes: 16 additions & 55 deletions src/librustc_codegen_llvm/debuginfo/mod.rs
Expand Up @@ -111,54 +111,6 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
}
}

pub enum FunctionDebugContext<D> {
RegularContext(FunctionDebugContextData<D>),
DebugInfoDisabled,
FunctionWithoutDebugInfo,
}

impl<D> FunctionDebugContext<D> {
pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData<D> {
match *self {
FunctionDebugContext::RegularContext(ref data) => data,
FunctionDebugContext::DebugInfoDisabled => {
span_bug!(span, "{}", Self::debuginfo_disabled_message());
}
FunctionDebugContext::FunctionWithoutDebugInfo => {
span_bug!(span, "{}", Self::should_be_ignored_message());
}
}
}

fn debuginfo_disabled_message() -> &'static str {
"debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
}

fn should_be_ignored_message() -> &'static str {
"debuginfo: Error trying to access FunctionDebugContext for function that should be \
ignored by debug info!"
}
}

pub struct FunctionDebugContextData<D> {
fn_metadata: D,
source_locations_enabled: Cell<bool>,
pub defining_crate: CrateNum,
}

pub enum VariableAccess<'a, V> {
// The llptr given is an alloca containing the variable's value
DirectVariable { alloca: V },
// The llptr given is an alloca containing the start of some pointer chain
// leading to the variable's content.
IndirectVariable { alloca: V, address_operations: &'a [i64] }
}

pub enum VariableKind {
ArgumentVariable(usize /*index*/),
LocalVariable,
}

/// Create any deferred debug metadata nodes
pub fn finalize(cx: &CodegenCx) {
if cx.dbg_cx.is_none() {
Expand Down Expand Up @@ -578,15 +530,24 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}

fn extend_scope_to_file(
&self,
scope_metadata: &'ll DIScope,
file: &syntax_pos::SourceFile,
defining_crate: CrateNum,
) -> &'ll DILexicalBlock {
metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
}
&self,
scope_metadata: &'ll DIScope,
file: &syntax_pos::SourceFile,
defining_crate: CrateNum,
) -> &'ll DILexicalBlock {
metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
}

fn debuginfo_finalize(&self) {
finalize(self)
}

fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> &[i64] {
unsafe {
[llvm::LLVMRustDIBuilderCreateOpDeref(),
llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
byte_offset_of_var_in_env as i64,
llvm::LLVMRustDIBuilderCreateOpDeref()]
};
}
}
12 changes: 0 additions & 12 deletions src/librustc_codegen_llvm/debuginfo/source_loc.rs
Expand Up @@ -50,18 +50,6 @@ pub fn set_source_location<D>(
set_debug_location(bx, dbg_loc);
}

/// Enables emitting source locations for the given functions.
///
/// Since we don't want source locations to be emitted for the function prelude,
/// they are disabled when beginning to codegen a new function. This functions
/// switches source location emitting on and must therefore be called before the
/// first real statement/expression of the function is codegened.
pub fn start_emitting_source_locations<D>(dbg_context: &FunctionDebugContext<D>) {
if let FunctionDebugContext::RegularContext(ref data) = *dbg_context {
data.source_locations_enabled.set(true);
}
}


#[derive(Copy, Clone, PartialEq)]
pub enum InternalDebugLocation<'ll> {
Expand Down
33 changes: 0 additions & 33 deletions src/librustc_codegen_llvm/diagnostics.rs
Expand Up @@ -47,37 +47,4 @@ unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok!
```
"##,

E0668: r##"
Malformed inline assembly rejected by LLVM.
LLVM checks the validity of the constraints and the assembly string passed to
it. This error implies that LLVM seems something wrong with the inline
assembly call.
In particular, it can happen if you forgot the closing bracket of a register
constraint (see issue #51430):
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
#![feature(asm)]
fn main() {
let rax: u64;
unsafe {
asm!("" :"={rax"(rax));
println!("Accumulator is: {}", rax);
}
}
```
"##,

E0669: r##"
Cannot convert inline assembly operand to a single LLVM value.
This error usually happens when trying to pass in a value to an input inline
assembly operand that is actually a pair of values. In particular, this can
happen when trying to pass in a slice, for instance a `&str`. In Rust, these
values are represented internally as a pair of values, the pointer and its
length. When passed as an input operand, this pair of values can not be
coerced into a register and thus we must fail with an error.
"##,

}

0 comments on commit c0a428e

Please sign in to comment.