Generalized base.rs#call_memcpy and everything that it uses
Generalized operand.rs#nontemporal_store and fixed tidy issues Generalized operand.rs#nontemporal_store's implem even more With a BuilderMethod trait implemented by Builder for LLVM Cleaned builder.rs : no more code duplication, no more ValueTrait Full traitification of builder.rs
This commit is contained in:
parent
83b2152ce4
commit
34c5dc045f
1
.atom-build.yml
Normal file
1
.atom-build.yml
Normal file
@ -0,0 +1 @@
|
||||
cmd: ./x.py -i check
|
@ -19,6 +19,8 @@ use type_::Type;
|
||||
use type_of::{LayoutLlvmExt, PointerKind};
|
||||
use value::Value;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout;
|
||||
@ -119,7 +121,7 @@ impl LlvmType for Reg {
|
||||
}
|
||||
}
|
||||
RegKind::Vector => {
|
||||
Type::vector(Type::i8(cx), self.size.bytes())
|
||||
Type::vector::<Value>(Type::i8(cx), self.size.bytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 Type::array::<Value>(rest_ll_unit, rest_count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,7 +169,12 @@ impl LlvmType for CastTarget {
|
||||
|
||||
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<'tcx, &'ll Value>);
|
||||
fn store(
|
||||
&self,
|
||||
bx: &Builder<'_, 'll, 'tcx>,
|
||||
val: &'ll Value,
|
||||
dst: PlaceRef<'tcx, &'ll Value>,
|
||||
);
|
||||
fn store_fn_arg(
|
||||
&self,
|
||||
bx: &Builder<'_, 'll, 'tcx>,
|
||||
@ -187,7 +194,12 @@ 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<'tcx, &'ll Value>) {
|
||||
fn store(
|
||||
&self,
|
||||
bx: &Builder<'_, 'll, 'tcx>,
|
||||
val: &'ll Value,
|
||||
dst: PlaceRef<'tcx, &'ll Value>,
|
||||
) {
|
||||
if self.is_ignore() {
|
||||
return;
|
||||
}
|
||||
@ -663,9 +675,9 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
|
||||
if self.variadic {
|
||||
Type::variadic_func(&llargument_tys, llreturn_ty)
|
||||
Type::variadic_func::<Value>(&llargument_tys, llreturn_ty)
|
||||
} else {
|
||||
Type::func(&llargument_tys, llreturn_ty)
|
||||
Type::func::<Value>(&llargument_tys, llreturn_ty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ use builder::Builder;
|
||||
use value::Value;
|
||||
|
||||
use rustc::hir;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use mir::place::PlaceRef;
|
||||
use mir::operand::OperandValue;
|
||||
|
@ -127,7 +127,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
|
||||
.filter(|l| !l.is_empty())
|
||||
}
|
||||
|
||||
pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
||||
pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_, &'ll Value>, llfn: &'ll Value) {
|
||||
let cpu = llvm_util::target_cpu(cx.tcx.sess);
|
||||
let target_cpu = CString::new(cpu).unwrap();
|
||||
llvm::AddFunctionAttrStringValue(
|
||||
|
@ -49,6 +49,7 @@ use context::{is_pie_binary, get_reloc_model};
|
||||
use common::{C_bytes_in_context, val_ty};
|
||||
use jobserver::{Client, Acquired};
|
||||
use rustc_demangle;
|
||||
use value::Value;
|
||||
|
||||
use std::any::Any;
|
||||
use std::ffi::{CString, CStr};
|
||||
@ -2574,7 +2575,7 @@ fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::M
|
||||
"\x01__imp_"
|
||||
};
|
||||
unsafe {
|
||||
let i8p_ty = Type::i8p_llcx(llcx);
|
||||
let i8p_ty = Type::i8p_llcx::<Value>(llcx);
|
||||
let globals = base::iter_globals(llmod)
|
||||
.filter(|&val| {
|
||||
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&
|
||||
|
@ -75,6 +75,8 @@ use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use std::any::Any;
|
||||
use std::cmp;
|
||||
use std::ffi::CString;
|
||||
@ -86,7 +88,7 @@ use syntax_pos::symbol::InternedString;
|
||||
use syntax::attr;
|
||||
use rustc::hir::{self, CodegenFnAttrs};
|
||||
|
||||
use value::Value;
|
||||
use value::{Value, ValueTrait};
|
||||
|
||||
use mir::operand::OperandValue;
|
||||
|
||||
@ -387,9 +389,14 @@ pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) {
|
||||
bx.call(assume_intrinsic, &[val], None);
|
||||
}
|
||||
|
||||
pub fn from_immediate(bx: &Builder<'_, 'll, '_>, val: &'ll Value) -> &'ll Value {
|
||||
if val_ty(val) == Type::i1(bx.cx) {
|
||||
bx.zext(val, Type::i8(bx.cx))
|
||||
pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll,
|
||||
Value : ?Sized,
|
||||
Builder: BuilderMethods<'a, 'll, 'tcx, Value>>(
|
||||
bx: &Builder,
|
||||
val: &'ll Value
|
||||
) -> &'ll Value where Value : ValueTrait {
|
||||
if val_ty(val) == Type::i1(bx.cx()) {
|
||||
bx.zext(val, Type::i8(bx.cx()))
|
||||
} else {
|
||||
val
|
||||
}
|
||||
@ -417,15 +424,17 @@ pub fn to_immediate_scalar(
|
||||
val
|
||||
}
|
||||
|
||||
pub fn call_memcpy(
|
||||
bx: &Builder<'_, 'll, '_>,
|
||||
pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll,
|
||||
Value : ?Sized,
|
||||
Builder: BuilderMethods<'a, 'll, 'tcx, Value>>(
|
||||
bx: &Builder,
|
||||
dst: &'ll Value,
|
||||
dst_align: Align,
|
||||
src: &'ll Value,
|
||||
src_align: Align,
|
||||
n_bytes: &'ll Value,
|
||||
flags: MemFlags,
|
||||
) {
|
||||
) where Value : ValueTrait {
|
||||
if flags.contains(MemFlags::NONTEMPORAL) {
|
||||
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
||||
let val = bx.load(src, src_align);
|
||||
@ -433,7 +442,7 @@ pub fn call_memcpy(
|
||||
bx.store_with_flags(val, ptr, dst_align, flags);
|
||||
return;
|
||||
}
|
||||
let cx = bx.cx;
|
||||
let cx = bx.cx();
|
||||
let src_ptr = bx.pointercast(src, Type::i8p(cx));
|
||||
let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
|
||||
let size = bx.intcast(n_bytes, cx.isize_ty, false);
|
||||
@ -441,21 +450,23 @@ pub fn call_memcpy(
|
||||
bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile);
|
||||
}
|
||||
|
||||
pub fn memcpy_ty(
|
||||
bx: &Builder<'_, 'll, 'tcx>,
|
||||
pub fn memcpy_ty<'a, 'll: 'a, 'tcx: 'll,
|
||||
Value : ?Sized,
|
||||
Builder: BuilderMethods<'a, 'll, 'tcx, Value>>(
|
||||
bx: &Builder,
|
||||
dst: &'ll Value,
|
||||
dst_align: Align,
|
||||
src: &'ll Value,
|
||||
src_align: Align,
|
||||
layout: TyLayout<'tcx>,
|
||||
flags: MemFlags,
|
||||
) {
|
||||
) where Value : ValueTrait {
|
||||
let size = layout.size.bytes();
|
||||
if size == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx, size), flags);
|
||||
call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx(), size), flags);
|
||||
}
|
||||
|
||||
pub fn call_memset(
|
||||
@ -545,7 +556,8 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
|
||||
rust_main_def_id: DefId,
|
||||
use_start_lang_item: bool,
|
||||
) {
|
||||
let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
|
||||
let llfty =
|
||||
Type::func::<Value>(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
|
||||
|
||||
let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
|
||||
// Given that `main()` has no arguments,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,11 +23,12 @@ use consts;
|
||||
use declare;
|
||||
use type_::Type;
|
||||
use type_of::LayoutLlvmExt;
|
||||
use value::Value;
|
||||
use value::{Value, ValueTrait};
|
||||
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{HasDataLayout, LayoutOf};
|
||||
use rustc::hir;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use libc::{c_uint, c_char};
|
||||
|
||||
@ -110,9 +111,9 @@ impl Funclet<'ll> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn val_ty(v: &'ll Value) -> &'ll Type {
|
||||
pub fn val_ty<Value : ?Sized>(v: &'ll Value) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMTypeOf(v)
|
||||
llvm::LLVMTypeOf(v.to_llvm())
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,21 +124,21 @@ pub fn C_null(t: &'ll Type) -> &'ll Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_undef(t: &'ll Type) -> &'ll Value {
|
||||
pub fn C_undef<Value : ?Sized>(t: &'ll Type) -> &'ll Value where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMGetUndef(t)
|
||||
Value::of_llvm(llvm::LLVMGetUndef(t))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value {
|
||||
pub fn C_int<Value : ?Sized>(t: &'ll Type, i: i64) -> &'ll Value where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMConstInt(t, i as u64, True)
|
||||
Value::of_llvm(llvm::LLVMConstInt(t, i as u64, True))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value {
|
||||
pub fn C_uint<Value : ?Sized>(t: &'ll Type, i: u64) -> &'ll Value where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMConstInt(t, i, False)
|
||||
Value::of_llvm(llvm::LLVMConstInt(t, i, False))
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,11 +149,17 @@ pub fn C_uint_big(t: &'ll Type, u: u128) -> &'ll Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_bool(cx: &CodegenCx<'ll, '_>, val: bool) -> &'ll Value {
|
||||
pub fn C_bool<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
val: bool
|
||||
) -> &'ll Value where Value : ValueTrait {
|
||||
C_uint(Type::i1(cx), val as u64)
|
||||
}
|
||||
|
||||
pub fn C_i32(cx: &CodegenCx<'ll, '_>, i: i32) -> &'ll Value {
|
||||
pub fn C_i32<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
i: i32
|
||||
) -> &'ll Value where Value : ValueTrait {
|
||||
C_int(Type::i32(cx), i as i64)
|
||||
}
|
||||
|
||||
@ -164,7 +171,10 @@ pub fn C_u64(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
|
||||
C_uint(Type::i64(cx), i)
|
||||
}
|
||||
|
||||
pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
|
||||
pub fn C_usize<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
i: u64
|
||||
) -> &'ll Value where Value : ValueTrait {
|
||||
let bit_size = cx.data_layout().pointer_size.bits();
|
||||
if bit_size < 64 {
|
||||
// make sure it doesn't overflow
|
||||
|
@ -18,7 +18,7 @@ use callee;
|
||||
use base;
|
||||
use declare;
|
||||
use monomorphize::Instance;
|
||||
use value::Value;
|
||||
use value::{Value, ValueTrait};
|
||||
|
||||
use monomorphize::partitioning::CodegenUnit;
|
||||
use type_::Type;
|
||||
@ -283,7 +283,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
||||
None
|
||||
};
|
||||
|
||||
let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
|
||||
let isize_ty = Type::ix_llcx::<Value>(llcx, tcx.data_layout.pointer_size.bits());
|
||||
|
||||
CodegenCx {
|
||||
tcx,
|
||||
@ -315,7 +315,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
|
||||
impl<'b, 'tcx, Value : ?Sized> CodegenCx<'b, 'tcx, &'b Value> where Value : ValueTrait {
|
||||
pub fn sess<'a>(&'a self) -> &'a Session {
|
||||
&self.tcx.sess
|
||||
}
|
||||
@ -327,7 +327,9 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
|
||||
|
||||
declare_intrinsic(self, key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, 'tcx> CodegenCx<'b, 'tcx, &'b Value> {
|
||||
/// Generate a new symbol name with the given prefix. This symbol name must
|
||||
/// only be used for definitions with `internal` or `private` linkage.
|
||||
pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
|
||||
@ -377,7 +379,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
|
||||
} else {
|
||||
"rust_eh_personality"
|
||||
};
|
||||
let fty = Type::variadic_func(&[], Type::i32(self));
|
||||
let fty = Type::variadic_func::<Value>(&[], Type::i32(self));
|
||||
declare::declare_cfn(self, name, fty)
|
||||
}
|
||||
};
|
||||
@ -478,28 +480,31 @@ impl LayoutOf for CodegenCx<'ll, 'tcx> {
|
||||
}
|
||||
|
||||
/// Declare any llvm intrinsics that you might need
|
||||
fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> {
|
||||
fn declare_intrinsic<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
key: &str
|
||||
) -> Option<&'ll Value> where Value : ValueTrait {
|
||||
macro_rules! ifn {
|
||||
($name:expr, fn() -> $ret:expr) => (
|
||||
if key == $name {
|
||||
let f = declare::declare_cfn(cx, $name, Type::func(&[], $ret));
|
||||
llvm::SetUnnamedAddr(f, false);
|
||||
let f = declare::declare_cfn(cx, $name, Type::func::<Value>(&[], $ret));
|
||||
llvm::SetUnnamedAddr(f.to_llvm(), false);
|
||||
cx.intrinsics.borrow_mut().insert($name, f.clone());
|
||||
return Some(f);
|
||||
}
|
||||
);
|
||||
($name:expr, fn(...) -> $ret:expr) => (
|
||||
if key == $name {
|
||||
let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], $ret));
|
||||
llvm::SetUnnamedAddr(f, false);
|
||||
let f = declare::declare_cfn(cx, $name, Type::variadic_func::<Value>(&[], $ret));
|
||||
llvm::SetUnnamedAddr(f.to_llvm(), false);
|
||||
cx.intrinsics.borrow_mut().insert($name, f.clone());
|
||||
return Some(f);
|
||||
}
|
||||
);
|
||||
($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
|
||||
if key == $name {
|
||||
let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], $ret));
|
||||
llvm::SetUnnamedAddr(f, false);
|
||||
let f = declare::declare_cfn(cx, $name, Type::func::<Value>(&[$($arg),*], $ret));
|
||||
llvm::SetUnnamedAddr(f.to_llvm(), false);
|
||||
cx.intrinsics.borrow_mut().insert($name, f.clone());
|
||||
return Some(f);
|
||||
}
|
||||
@ -520,14 +525,14 @@ fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> {
|
||||
let t_f32 = Type::f32(cx);
|
||||
let t_f64 = Type::f64(cx);
|
||||
|
||||
let t_v2f32 = Type::vector(t_f32, 2);
|
||||
let t_v4f32 = Type::vector(t_f32, 4);
|
||||
let t_v8f32 = Type::vector(t_f32, 8);
|
||||
let t_v16f32 = Type::vector(t_f32, 16);
|
||||
let t_v2f32 = Type::vector::<Value>(t_f32, 2);
|
||||
let t_v4f32 = Type::vector::<Value>(t_f32, 4);
|
||||
let t_v8f32 = Type::vector::<Value>(t_f32, 8);
|
||||
let t_v16f32 = Type::vector::<Value>(t_f32, 16);
|
||||
|
||||
let t_v2f64 = Type::vector(t_f64, 2);
|
||||
let t_v4f64 = Type::vector(t_f64, 4);
|
||||
let t_v8f64 = Type::vector(t_f64, 8);
|
||||
let t_v2f64 = Type::vector::<Value>(t_f64, 2);
|
||||
let t_v4f64 = Type::vector::<Value>(t_f64, 4);
|
||||
let t_v8f64 = Type::vector::<Value>(t_f64, 8);
|
||||
|
||||
ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
|
||||
ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
|
||||
|
@ -18,6 +18,7 @@ use declare;
|
||||
use rustc::session::config::DebugInfo;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use syntax::attr;
|
||||
|
||||
@ -55,7 +56,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
|
||||
let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
|
||||
|
||||
unsafe {
|
||||
let llvm_type = Type::array(Type::i8(cx),
|
||||
let llvm_type = Type::array::<Value>(Type::i8(cx),
|
||||
section_contents.len() as u64);
|
||||
|
||||
let section_var = declare::define_global(cx, section_var_name,
|
||||
|
@ -45,6 +45,7 @@ use syntax_pos::{self, Span, Pos};
|
||||
use syntax::ast;
|
||||
use syntax::symbol::{Symbol, InternedString};
|
||||
use rustc::ty::layout::{self, LayoutOf};
|
||||
use traits::BuilderMethods;
|
||||
|
||||
pub mod gdb;
|
||||
mod utils;
|
||||
|
@ -17,6 +17,7 @@ use super::FunctionDebugContext;
|
||||
use llvm;
|
||||
use llvm::debuginfo::DIScope;
|
||||
use builder::Builder;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use libc::c_uint;
|
||||
use syntax_pos::{Span, Pos};
|
||||
@ -78,7 +79,10 @@ impl InternalDebugLocation<'ll> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_debug_location(bx: &Builder<'_, 'll, '_>, debug_location: InternalDebugLocation<'ll>) {
|
||||
pub fn set_debug_location(
|
||||
bx: &Builder<'_, 'll, '_>,
|
||||
debug_location: InternalDebugLocation<'ll>
|
||||
) {
|
||||
let metadata_node = match debug_location {
|
||||
KnownLocation { scope, line, col } => {
|
||||
// For MSVC, set the column number to zero.
|
||||
|
@ -31,7 +31,7 @@ use abi::{Abi, FnType, FnTypeExt};
|
||||
use attributes;
|
||||
use context::CodegenCx;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
use value::{Value, ValueTrait};
|
||||
|
||||
|
||||
/// Declare a global value.
|
||||
@ -51,12 +51,12 @@ pub fn declare_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> &'l
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
fn declare_raw_fn(
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
fn declare_raw_fn<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
name: &str,
|
||||
callconv: llvm::CallConv,
|
||||
ty: &'ll Type,
|
||||
) -> &'ll Value {
|
||||
) -> &'ll Value where Value : ValueTrait {
|
||||
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
|
||||
let namebuf = SmallCStr::new(name);
|
||||
let llfn = unsafe {
|
||||
@ -105,7 +105,7 @@ fn declare_raw_fn(
|
||||
|
||||
attributes::non_lazy_bind(cx.sess(), llfn);
|
||||
|
||||
llfn
|
||||
Value::of_llvm(llfn)
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +116,11 @@ fn declare_raw_fn(
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
pub fn declare_cfn(cx: &CodegenCx<'ll, '_>, name: &str, fn_type: &'ll Type) -> &'ll Value {
|
||||
pub fn declare_cfn<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
name: &str,
|
||||
fn_type: &'ll Type
|
||||
) -> &'ll Value where Value : ValueTrait {
|
||||
declare_raw_fn(cx, name, llvm::CCallConv, fn_type)
|
||||
}
|
||||
|
||||
@ -168,7 +172,7 @@ pub fn define_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> Opti
|
||||
/// Declare a private global
|
||||
///
|
||||
/// Use this function when you intend to define a global without a name.
|
||||
pub fn define_private_global(cx: &CodegenCx<'ll, '_>, ty: &'ll Type) -> &'ll Value {
|
||||
pub fn define_private_global(cx: &CodegenCx<'ll, '_, &'ll Value>, ty: &'ll Type) -> &'ll Value {
|
||||
unsafe {
|
||||
llvm::LLVMRustInsertPrivateGlobal(cx.llmod, ty)
|
||||
}
|
||||
|
@ -21,9 +21,13 @@ use meth;
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use rustc::ty::{self, Ty};
|
||||
use value::Value;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Option<&'ll Value>)
|
||||
-> (&'ll Value, &'ll Value) {
|
||||
pub fn size_and_align_of_dst(
|
||||
bx: &Builder<'_, 'll, 'tcx>,
|
||||
t: Ty<'tcx>,
|
||||
info: Option<&'ll Value>
|
||||
) -> (&'ll Value, &'ll Value) {
|
||||
debug!("calculate size of DST: {}; with lost info: {:?}",
|
||||
t, info);
|
||||
if bx.cx.type_is_sized(t) {
|
||||
|
@ -31,6 +31,8 @@ use syntax::symbol::Symbol;
|
||||
use builder::Builder;
|
||||
use value::Value;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use rustc::session::Session;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -591,7 +593,7 @@ pub fn codegen_intrinsic_call(
|
||||
Vector(ref t, ref llvm_elem, length) => {
|
||||
let t = llvm_elem.as_ref().unwrap_or(t);
|
||||
let elem = one(ty_to_type(cx, t));
|
||||
vec![Type::vector(elem, length as u64)]
|
||||
vec![Type::vector::<Value>(elem, length as u64)]
|
||||
}
|
||||
Aggregate(false, ref contents) => {
|
||||
let elems = contents.iter()
|
||||
@ -640,7 +642,10 @@ pub fn codegen_intrinsic_call(
|
||||
}
|
||||
intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => {
|
||||
let llvm_elem = one(ty_to_type(bx.cx, llvm_elem));
|
||||
vec![bx.bitcast(arg.immediate(), Type::vector(llvm_elem, length as u64))]
|
||||
vec![
|
||||
bx.bitcast(arg.immediate(),
|
||||
Type::vector::<Value>(llvm_elem, length as u64))
|
||||
]
|
||||
}
|
||||
intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
|
||||
// the LLVM intrinsic uses a smaller integer
|
||||
@ -668,7 +673,7 @@ pub fn codegen_intrinsic_call(
|
||||
intrinsics::IntrinsicDef::Named(name) => {
|
||||
let f = declare::declare_cfn(cx,
|
||||
name,
|
||||
Type::func(&inputs, outputs));
|
||||
Type::func::<Value>(&inputs, outputs));
|
||||
bx.call(f, &llargs, None)
|
||||
}
|
||||
};
|
||||
@ -1155,7 +1160,7 @@ fn generic_simd_intrinsic(
|
||||
}
|
||||
// truncate the mask to a vector of i1s
|
||||
let i1 = Type::i1(bx.cx);
|
||||
let i1xn = Type::vector(i1, m_len as u64);
|
||||
let i1xn = Type::vector::<Value>(i1, m_len as u64);
|
||||
let m_i1s = bx.trunc(args[0].immediate(), i1xn);
|
||||
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
|
||||
}
|
||||
@ -1296,7 +1301,7 @@ fn generic_simd_intrinsic(
|
||||
elem_ty = elem_ty.ptr_to();
|
||||
no_pointers -= 1;
|
||||
}
|
||||
Type::vector(elem_ty, vec_len as u64)
|
||||
Type::vector::<Value>(elem_ty, vec_len as u64)
|
||||
}
|
||||
|
||||
|
||||
@ -1379,7 +1384,7 @@ fn generic_simd_intrinsic(
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = Type::i1(bx.cx);
|
||||
let i1xn = Type::vector(i1, in_len as u64);
|
||||
let i1xn = Type::vector::<Value>(i1, in_len as u64);
|
||||
(bx.trunc(args[2].immediate(), i1xn), i1xn)
|
||||
};
|
||||
|
||||
@ -1394,8 +1399,11 @@ fn generic_simd_intrinsic(
|
||||
let llvm_intrinsic = format!("llvm.masked.gather.{}.{}",
|
||||
llvm_elem_vec_str, llvm_pointer_vec_str);
|
||||
let f = declare::declare_cfn(bx.cx, &llvm_intrinsic,
|
||||
Type::func(&[llvm_pointer_vec_ty, alignment_ty, mask_ty,
|
||||
llvm_elem_vec_ty], llvm_elem_vec_ty));
|
||||
Type::func::<Value>(&[
|
||||
llvm_pointer_vec_ty,
|
||||
alignment_ty,
|
||||
mask_ty,
|
||||
llvm_elem_vec_ty], llvm_elem_vec_ty));
|
||||
llvm::SetUnnamedAddr(f, false);
|
||||
let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()],
|
||||
None);
|
||||
@ -1476,7 +1484,7 @@ fn generic_simd_intrinsic(
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = Type::i1(bx.cx);
|
||||
let i1xn = Type::vector(i1, in_len as u64);
|
||||
let i1xn = Type::vector::<Value>(i1, in_len as u64);
|
||||
(bx.trunc(args[2].immediate(), i1xn), i1xn)
|
||||
};
|
||||
|
||||
@ -1493,7 +1501,7 @@ fn generic_simd_intrinsic(
|
||||
let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}",
|
||||
llvm_elem_vec_str, llvm_pointer_vec_str);
|
||||
let f = declare::declare_cfn(bx.cx, &llvm_intrinsic,
|
||||
Type::func(&[llvm_elem_vec_ty,
|
||||
Type::func::<Value>(&[llvm_elem_vec_ty,
|
||||
llvm_pointer_vec_ty,
|
||||
alignment_ty,
|
||||
mask_ty], ret_t));
|
||||
@ -1628,7 +1636,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
||||
|
||||
// boolean reductions operate on vectors of i1s:
|
||||
let i1 = Type::i1(bx.cx);
|
||||
let i1xn = Type::vector(i1, in_len as u64);
|
||||
let i1xn = Type::vector::<Value>(i1, in_len as u64);
|
||||
bx.trunc(args[0].immediate(), i1xn)
|
||||
};
|
||||
return match in_elem.sty {
|
||||
|
@ -102,6 +102,8 @@ mod back {
|
||||
pub mod wasm;
|
||||
}
|
||||
|
||||
mod traits;
|
||||
|
||||
mod abi;
|
||||
mod allocator;
|
||||
mod asm;
|
||||
|
@ -17,6 +17,8 @@ use monomorphize;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout::HasDataLayout;
|
||||
use debuginfo;
|
||||
@ -48,7 +50,11 @@ impl<'a, 'tcx> VirtualIndex {
|
||||
ptr
|
||||
}
|
||||
|
||||
pub fn get_usize(self, bx: &Builder<'a, 'll, 'tcx>, llvtable: &'ll Value) -> &'ll Value {
|
||||
pub fn get_usize(
|
||||
self,
|
||||
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
|
||||
llvtable: &'ll Value
|
||||
) -> &'ll Value {
|
||||
// Load the data pointer from the object.
|
||||
debug!("get_int({:?}, {:?})", llvtable, self);
|
||||
|
||||
|
@ -26,6 +26,8 @@ use type_of::LayoutLlvmExt;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Pos;
|
||||
|
||||
@ -98,16 +100,17 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||
}
|
||||
};
|
||||
|
||||
let funclet_br = |this: &mut Self, bx: Builder<'_, 'll, '_>, target: mir::BasicBlock| {
|
||||
let (lltarget, is_cleanupret) = lltarget(this, target);
|
||||
if is_cleanupret {
|
||||
// micro-optimization: generate a `ret` rather than a jump
|
||||
// to a trampoline.
|
||||
bx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget));
|
||||
} else {
|
||||
bx.br(lltarget);
|
||||
}
|
||||
};
|
||||
let funclet_br =
|
||||
|this: &mut Self, bx: Builder<'_, 'll, '_, &'ll Value>, target: mir::BasicBlock| {
|
||||
let (lltarget, is_cleanupret) = lltarget(this, target);
|
||||
if is_cleanupret {
|
||||
// micro-optimization: generate a `ret` rather than a jump
|
||||
// to a trampoline.
|
||||
bx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget));
|
||||
} else {
|
||||
bx.br(lltarget);
|
||||
}
|
||||
};
|
||||
|
||||
let do_call = |
|
||||
this: &mut Self,
|
||||
@ -843,7 +846,10 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'tcx, &'ll Value> {
|
||||
fn get_personality_slot(
|
||||
&mut self,
|
||||
bx: &Builder<'a, 'll, 'tcx, &'ll Value>
|
||||
) -> PlaceRef<'tcx, &'ll Value> {
|
||||
let cx = bx.cx;
|
||||
if let Some(slot) = self.personality_slot {
|
||||
slot
|
||||
|
@ -26,6 +26,7 @@ use type_::Type;
|
||||
use syntax::ast::Mutability;
|
||||
use syntax::source_map::Span;
|
||||
use value::Value;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use super::super::callee;
|
||||
use super::FunctionCx;
|
||||
|
@ -26,6 +26,7 @@ use monomorphize::Instance;
|
||||
use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
|
||||
use syntax::symbol::keywords;
|
||||
@ -119,7 +120,11 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn set_debug_loc(&mut self, bx: &Builder<'_, 'll, '_>, source_info: mir::SourceInfo) {
|
||||
pub fn set_debug_loc(
|
||||
&mut self,
|
||||
bx: &Builder<'_, 'll, '_, &'ll Value>,
|
||||
source_info: mir::SourceInfo
|
||||
) {
|
||||
let (scope, span) = self.debug_loc(source_info);
|
||||
debuginfo::set_source_location(&self.debug_context, bx, scope, span);
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ use type_of::LayoutLlvmExt;
|
||||
use type_::Type;
|
||||
use glue;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use super::{FunctionCx, LocalRef};
|
||||
@ -260,7 +262,11 @@ impl OperandValue<&'ll Value> {
|
||||
self.store_with_flags(bx, dest, MemFlags::empty());
|
||||
}
|
||||
|
||||
pub fn volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'tcx, &'ll Value>) {
|
||||
pub fn volatile_store(
|
||||
self,
|
||||
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
|
||||
dest: PlaceRef<'tcx, &'ll Value>
|
||||
) {
|
||||
self.store_with_flags(bx, dest, MemFlags::VOLATILE);
|
||||
}
|
||||
|
||||
@ -271,14 +277,23 @@ impl OperandValue<&'ll Value> {
|
||||
) {
|
||||
self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'tcx, &'ll Value>) {
|
||||
impl<'a, 'll: 'a, 'tcx: 'll, Value : ?Sized> OperandValue<&'ll Value> where
|
||||
Value : ValueTrait,
|
||||
Builder<'a, 'll, 'tcx, &'ll Value>: BuilderMethods<'a, 'll, 'tcx, Value>
|
||||
{
|
||||
pub fn nontemporal_store(
|
||||
self,
|
||||
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
|
||||
dest: PlaceRef<'tcx, &'ll Value>
|
||||
) {
|
||||
self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL);
|
||||
}
|
||||
|
||||
fn store_with_flags(
|
||||
fn store_with_flags<Builder: BuilderMethods<'a, 'll, 'tcx, Value>>(
|
||||
self,
|
||||
bx: &Builder<'a, 'll, 'tcx>,
|
||||
bx: &Builder,
|
||||
dest: PlaceRef<'tcx, &'ll Value>,
|
||||
flags: MemFlags,
|
||||
) {
|
||||
@ -309,11 +324,13 @@ impl OperandValue<&'ll Value> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OperandValue<&'ll Value> {
|
||||
pub fn store_unsized(
|
||||
self,
|
||||
bx: &Builder<'a, 'll, 'tcx>,
|
||||
indirect_dest: PlaceRef<'tcx, &'ll Value>,
|
||||
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
|
||||
indirect_dest: PlaceRef<'tcx, &'ll Value>
|
||||
) {
|
||||
debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest);
|
||||
let flags = MemFlags::empty();
|
||||
@ -334,13 +351,13 @@ impl OperandValue<&'ll Value> {
|
||||
let min_align = Align::from_bits(8, 8).unwrap();
|
||||
|
||||
// Allocate an appropriate region on the stack, and copy the value into it
|
||||
let (llsize, _) = glue::size_and_align_of_dst(&bx, unsized_ty, Some(llextra));
|
||||
let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
|
||||
let lldst = bx.array_alloca(Type::i8(bx.cx), llsize, "unsized_tmp", max_align);
|
||||
base::call_memcpy(&bx, lldst, max_align, llptr, min_align, llsize, flags);
|
||||
base::call_memcpy(bx, lldst, max_align, llptr, min_align, llsize, flags);
|
||||
|
||||
// Store the allocated region and the extra to the indirect place.
|
||||
let indirect_operand = OperandValue::Pair(lldst, llextra);
|
||||
indirect_operand.store(&bx, indirect_dest);
|
||||
indirect_operand.store(bx, indirect_dest);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ use value::Value;
|
||||
use glue;
|
||||
use mir::constant::const_alloc_to_llvm;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use super::{FunctionCx, LocalRef};
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
|
||||
@ -280,7 +282,11 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||
}
|
||||
|
||||
/// Obtain the actual discriminant of a value.
|
||||
pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value {
|
||||
pub fn codegen_get_discr(
|
||||
self,
|
||||
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
|
||||
cast_to: Ty<'tcx>
|
||||
) -> &'ll Value {
|
||||
let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
|
||||
if self.layout.abi.is_uninhabited() {
|
||||
return C_undef(cast_to);
|
||||
|
@ -28,6 +28,8 @@ use type_::Type;
|
||||
use type_of::LayoutLlvmExt;
|
||||
use value::Value;
|
||||
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use super::{FunctionCx, LocalRef};
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::place::PlaceRef;
|
||||
@ -178,12 +180,12 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_rvalue_unsized(
|
||||
&mut self,
|
||||
bx: Builder<'a, 'll, 'tcx>,
|
||||
indirect_dest: PlaceRef<'tcx, &'ll Value>,
|
||||
rvalue: &mir::Rvalue<'tcx>,
|
||||
) -> Builder<'a, 'll, 'tcx> {
|
||||
pub fn codegen_rvalue_unsized(&mut self,
|
||||
bx: Builder<'a, 'll, 'tcx, &'ll Value>,
|
||||
indirect_dest: PlaceRef<'tcx, &'ll Value>,
|
||||
rvalue: &mir::Rvalue<'tcx>)
|
||||
-> Builder<'a, 'll, 'tcx, &'ll Value>
|
||||
{
|
||||
debug!("codegen_rvalue_unsized(indirect_dest.llval={:?}, rvalue={:?})",
|
||||
indirect_dest.llval, rvalue);
|
||||
|
||||
@ -198,11 +200,11 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_rvalue_operand(&mut self,
|
||||
bx: Builder<'a, 'll, 'tcx>,
|
||||
rvalue: &mir::Rvalue<'tcx>)
|
||||
-> (Builder<'a, 'll, 'tcx>, OperandRef<'tcx, &'ll Value>)
|
||||
{
|
||||
pub fn codegen_rvalue_operand(
|
||||
&mut self,
|
||||
bx: Builder<'a, 'll, 'tcx, &'ll Value>,
|
||||
rvalue: &mir::Rvalue<'tcx>
|
||||
) -> (Builder<'a, 'll, 'tcx, &'ll Value>, OperandRef<'tcx, &'ll Value>) {
|
||||
assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue);
|
||||
|
||||
match *rvalue {
|
||||
@ -750,7 +752,11 @@ enum OverflowOp {
|
||||
Add, Sub, Mul
|
||||
}
|
||||
|
||||
fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder<'_, 'll, '_>, ty: Ty) -> &'ll Value {
|
||||
fn get_overflow_intrinsic(
|
||||
oop: OverflowOp,
|
||||
bx: &Builder<'_, 'll, '_, &'ll Value>,
|
||||
ty: Ty
|
||||
) -> &'ll Value {
|
||||
use syntax::ast::IntTy::*;
|
||||
use syntax::ast::UintTy::*;
|
||||
use rustc::ty::{Int, Uint};
|
||||
|
@ -12,6 +12,7 @@ use rustc::mir;
|
||||
|
||||
use asm;
|
||||
use builder::Builder;
|
||||
use traits::BuilderMethods;
|
||||
|
||||
use super::FunctionCx;
|
||||
use super::LocalRef;
|
||||
|
283
src/librustc_codegen_llvm/traits.rs
Normal file
283
src/librustc_codegen_llvm/traits.rs
Normal file
@ -0,0 +1,283 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
|
||||
use llvm::{IntPredicate, RealPredicate, OperandBundleDef};
|
||||
use llvm::{self, BasicBlock};
|
||||
use common::*;
|
||||
use type_::Type;
|
||||
use libc::c_char;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::layout::{Align, Size};
|
||||
use rustc::session::Session;
|
||||
use builder::MemFlags;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Range;
|
||||
|
||||
|
||||
pub trait BuilderMethods<'a, 'll :'a, 'tcx: 'll, Value : ?Sized> {
|
||||
fn new_block<'b>(
|
||||
cx: &'a CodegenCx<'ll, 'tcx, &'ll Value>,
|
||||
llfn: &'ll Value,
|
||||
name: &'b str
|
||||
) -> Self;
|
||||
fn with_cx(cx: &'a CodegenCx<'ll, 'tcx, &'ll Value>) -> Self;
|
||||
fn build_sibling_block<'b>(&self, name: &'b str) -> Self;
|
||||
fn sess(&self) -> &Session;
|
||||
fn cx(&self) -> &'a CodegenCx<'ll, 'tcx, &'ll Value>;
|
||||
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
|
||||
fn llfn(&self) -> &'ll Value;
|
||||
fn llbb(&self) -> &'ll BasicBlock;
|
||||
fn count_insn(&self, category: &str);
|
||||
|
||||
fn set_value_name(&self, value: &'ll Value, name: &str);
|
||||
fn position_at_end(&self, llbb: &'ll BasicBlock);
|
||||
fn position_at_start(&self, llbb: &'ll BasicBlock);
|
||||
fn ret_void(&self);
|
||||
fn ret(&self, v: &'ll Value);
|
||||
fn br(&self, dest: &'ll BasicBlock);
|
||||
fn cond_br(
|
||||
&self,
|
||||
cond: &'ll Value,
|
||||
then_llbb: &'ll BasicBlock,
|
||||
else_llbb: &'ll BasicBlock,
|
||||
);
|
||||
fn switch(
|
||||
&self,
|
||||
v: &'ll Value,
|
||||
else_llbb: &'ll BasicBlock,
|
||||
num_cases: usize,
|
||||
) -> &'ll Value;
|
||||
fn invoke(
|
||||
&self,
|
||||
llfn: &'ll Value,
|
||||
args: &[&'ll Value],
|
||||
then: &'ll BasicBlock,
|
||||
catch: &'ll BasicBlock,
|
||||
bundle: Option<&OperandBundleDef<'ll>>
|
||||
) -> &'ll Value;
|
||||
fn unreachable(&self);
|
||||
fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn exactudiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn sdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn exactsdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn srem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn frem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn lshr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn ashr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn and(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn or(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn xor(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn neg(&self, v: &'ll Value) -> &'ll Value;
|
||||
fn fneg(&self, v: &'ll Value) -> &'ll Value;
|
||||
fn not(&self, v: &'ll Value) -> &'ll Value;
|
||||
|
||||
fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value;
|
||||
fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value;
|
||||
fn array_alloca(
|
||||
&self,
|
||||
ty: &'ll Type,
|
||||
len: &'ll Value,
|
||||
name: &str,
|
||||
align: Align
|
||||
) -> &'ll Value;
|
||||
|
||||
fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value;
|
||||
fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value;
|
||||
fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, size: Size) -> &'ll Value;
|
||||
|
||||
fn range_metadata(&self, load: &'ll Value, range: Range<u128>);
|
||||
fn nonnull_metadata(&self, load: &'ll Value);
|
||||
|
||||
fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value;
|
||||
fn store_with_flags(
|
||||
&self,
|
||||
val: &'ll Value,
|
||||
ptr: &'ll Value,
|
||||
align: Align,
|
||||
flags: MemFlags,
|
||||
) -> &'ll Value;
|
||||
fn atomic_store(
|
||||
&self,
|
||||
val: &'ll Value,
|
||||
ptr: &'ll Value,
|
||||
order: AtomicOrdering,
|
||||
size: Size
|
||||
);
|
||||
|
||||
fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value;
|
||||
fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value;
|
||||
fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value;
|
||||
|
||||
fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value;
|
||||
fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
|
||||
fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
|
||||
fn empty_phi(&self, ty: &'ll Type) -> &'ll Value;
|
||||
fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value;
|
||||
fn inline_asm_call(
|
||||
&self,
|
||||
asm: *const c_char,
|
||||
cons: *const c_char,
|
||||
inputs: &[&'ll Value],
|
||||
output: &'ll Type,
|
||||
volatile: bool,
|
||||
alignstack: bool,
|
||||
dia: AsmDialect
|
||||
) -> Option<&'ll Value>;
|
||||
|
||||
|
||||
fn memcpy(&self, dst: &'ll Value, dst_align: u64,
|
||||
src: &'ll Value, src_align: u64,
|
||||
size: &'ll Value, is_volatile: bool) -> &'ll Value;
|
||||
fn memmove(&self, dst: &'ll Value, dst_align: u64,
|
||||
src: &'ll Value, src_align: u64,
|
||||
size: &'ll Value, is_volatile: bool) -> &'ll Value;
|
||||
|
||||
fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value;
|
||||
fn select(
|
||||
&self, cond: &'ll Value,
|
||||
then_val: &'ll Value,
|
||||
else_val: &'ll Value,
|
||||
) -> &'ll Value;
|
||||
|
||||
fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value;
|
||||
fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value;
|
||||
fn insert_element(
|
||||
&self, vec: &'ll Value,
|
||||
elt: &'ll Value,
|
||||
idx: &'ll Value,
|
||||
) -> &'ll Value;
|
||||
fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value;
|
||||
fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value;
|
||||
fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value;
|
||||
fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value;
|
||||
fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value;
|
||||
fn insert_value(
|
||||
&self,
|
||||
agg_val: &'ll Value,
|
||||
elt: &'ll Value,
|
||||
idx: u64
|
||||
) -> &'ll Value;
|
||||
|
||||
fn landing_pad(
|
||||
&self,
|
||||
ty: &'ll Type,
|
||||
pers_fn: &'ll Value,
|
||||
num_clauses: usize
|
||||
) -> &'ll Value;
|
||||
fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value);
|
||||
fn set_cleanup(&self, landing_pad: &'ll Value);
|
||||
fn resume(&self, exn: &'ll Value) -> &'ll Value;
|
||||
fn cleanup_pad(
|
||||
&self,
|
||||
parent: Option<&'ll Value>,
|
||||
args: &[&'ll Value]
|
||||
) -> &'ll Value;
|
||||
fn cleanup_ret(
|
||||
&self, cleanup: &'ll Value,
|
||||
unwind: Option<&'ll BasicBlock>,
|
||||
) -> &'ll Value;
|
||||
fn catch_pad(
|
||||
&self,
|
||||
parent: &'ll Value,
|
||||
args: &[&'ll Value]
|
||||
) -> &'ll Value;
|
||||
fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value;
|
||||
fn catch_switch(
|
||||
&self,
|
||||
parent: Option<&'ll Value>,
|
||||
unwind: Option<&'ll BasicBlock>,
|
||||
num_handlers: usize,
|
||||
) -> &'ll Value;
|
||||
fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock);
|
||||
fn set_personality_fn(&self, personality: &'ll Value);
|
||||
|
||||
fn atomic_cmpxchg(
|
||||
&self,
|
||||
dst: &'ll Value,
|
||||
cmp: &'ll Value,
|
||||
src: &'ll Value,
|
||||
order: AtomicOrdering,
|
||||
failure_order: AtomicOrdering,
|
||||
weak: llvm::Bool,
|
||||
) -> &'ll Value;
|
||||
fn atomic_rmw(
|
||||
&self,
|
||||
op: AtomicRmwBinOp,
|
||||
dst: &'ll Value,
|
||||
src: &'ll Value,
|
||||
order: AtomicOrdering,
|
||||
) -> &'ll Value;
|
||||
fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope);
|
||||
fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock);
|
||||
fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock);
|
||||
fn set_invariant_load(&self, load: &'ll Value);
|
||||
|
||||
fn check_store(
|
||||
&self,
|
||||
val: &'ll Value,
|
||||
ptr: &'ll Value
|
||||
) -> &'ll Value;
|
||||
fn check_call<'b>(
|
||||
&self,
|
||||
typ: &str,
|
||||
llfn: &'ll Value,
|
||||
args: &'b [&'ll Value]
|
||||
) -> Cow<'b, [&'ll Value]>;
|
||||
fn lifetime_start(&self, ptr: &'ll Value, size: Size);
|
||||
fn lifetime_end(&self, ptr: &'ll Value, size: Size);
|
||||
|
||||
fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size);
|
||||
|
||||
fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
|
||||
bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value;
|
||||
fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value;
|
||||
}
|
@ -16,6 +16,7 @@ use llvm;
|
||||
use llvm::{Bool, False, True, TypeKind};
|
||||
|
||||
use context::CodegenCx;
|
||||
use value::{Value, ValueTrait};
|
||||
|
||||
use syntax::ast;
|
||||
use rustc::ty::layout::{self, Align, Size};
|
||||
@ -40,107 +41,143 @@ impl fmt::Debug for Type {
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn void(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn void<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMVoidTypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn metadata<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMRustMetadataTypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i1(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn i1<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMInt1TypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i8(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn i8<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMInt8TypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
|
||||
pub fn i8_llcx<Value : ?Sized>(llcx: &llvm::Context) -> &Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMInt8TypeInContext(llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i16(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn i16<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
|
||||
llvm::LLVMInt16TypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn i32<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMInt32TypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn i64<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMInt64TypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i128(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn i128<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMIntTypeInContext(cx.llcx, 128)
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an integer type with the given number of bits, e.g. i24
|
||||
pub fn ix(cx: &CodegenCx<'ll, '_>, num_bits: u64) -> &'ll Type {
|
||||
pub fn ix<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
num_bits: u64
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an integer type with the given number of bits, e.g. i24
|
||||
pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type {
|
||||
pub fn ix_llcx<Value : ?Sized>(
|
||||
llcx: &llvm::Context,
|
||||
num_bits: u64
|
||||
) -> &Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn f32<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMFloatTypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn f64<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMDoubleTypeInContext(cx.llcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bool(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn bool<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
Type::i8(cx)
|
||||
}
|
||||
|
||||
pub fn char(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn char<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
Type::i32(cx)
|
||||
}
|
||||
|
||||
pub fn i8p(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn i8p<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
Type::i8(cx).ptr_to()
|
||||
}
|
||||
|
||||
pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
|
||||
Type::i8_llcx(llcx).ptr_to()
|
||||
pub fn i8p_llcx<Value : ?Sized>(llcx: &llvm::Context) -> &Type where Value : ValueTrait {
|
||||
Type::i8_llcx::<Value>(llcx).ptr_to()
|
||||
}
|
||||
|
||||
pub fn isize(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn isize<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
cx.isize_ty
|
||||
}
|
||||
|
||||
pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
pub fn c_int<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
match &cx.tcx.sess.target.target.target_c_int_width[..] {
|
||||
"16" => Type::i16(cx),
|
||||
"32" => Type::i32(cx),
|
||||
@ -149,7 +186,10 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type {
|
||||
pub fn int_from_ty<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
t: ast::IntTy
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
match t {
|
||||
ast::IntTy::Isize => cx.isize_ty,
|
||||
ast::IntTy::I8 => Type::i8(cx),
|
||||
@ -160,7 +200,10 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type {
|
||||
pub fn uint_from_ty<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
t: ast::UintTy
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
match t {
|
||||
ast::UintTy::Usize => cx.isize_ty,
|
||||
ast::UintTy::U8 => Type::i8(cx),
|
||||
@ -171,28 +214,41 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn float_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::FloatTy) -> &'ll Type {
|
||||
pub fn float_from_ty<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
t: ast::FloatTy
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
match t {
|
||||
ast::FloatTy::F32 => Type::f32(cx),
|
||||
ast::FloatTy::F64 => Type::f64(cx),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
pub fn func<Value : ?Sized>(
|
||||
args: &[&'ll Type],
|
||||
ret: &'ll Type
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMFunctionType(ret, args.as_ptr(),
|
||||
args.len() as c_uint, False)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn variadic_func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
pub fn variadic_func<Value : ?Sized>(
|
||||
args: &[&'ll Type],
|
||||
ret: &'ll Type
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMFunctionType(ret, args.as_ptr(),
|
||||
args.len() as c_uint, True)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn struct_(cx: &CodegenCx<'ll, '_>, els: &[&'ll Type], packed: bool) -> &'ll Type {
|
||||
pub fn struct_<Value : ?Sized>(
|
||||
cx: &CodegenCx<'ll, '_, &'ll Value>,
|
||||
els: &[&'ll Type],
|
||||
packed: bool
|
||||
) -> &'ll Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
|
||||
els.len() as c_uint,
|
||||
@ -208,13 +264,13 @@ impl Type {
|
||||
}
|
||||
|
||||
|
||||
pub fn array(ty: &Type, len: u64) -> &Type {
|
||||
pub fn array<Value : ?Sized>(ty: &Type, len: u64) -> &Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMRustArrayType(ty, len)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vector(ty: &Type, len: u64) -> &Type {
|
||||
pub fn vector<Value : ?Sized>(ty: &Type, len: u64) -> &Type where Value : ValueTrait {
|
||||
unsafe {
|
||||
llvm::LLVMVectorType(ty, len as c_uint)
|
||||
}
|
||||
@ -307,7 +363,7 @@ impl Type {
|
||||
let size = size.bytes();
|
||||
let unit_size = unit.size().bytes();
|
||||
assert_eq!(size % unit_size, 0);
|
||||
Type::array(Type::from_integer(cx, unit), size / unit_size)
|
||||
Type::array::<Value>(Type::from_integer(cx, unit), size / unit_size)
|
||||
}
|
||||
|
||||
pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
|
||||
|
@ -16,6 +16,7 @@ use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
|
||||
use rustc_target::abi::FloatTy;
|
||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
@ -40,7 +41,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
return Type::x86_mmx(cx)
|
||||
} else {
|
||||
let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
|
||||
return Type::vector(element, count);
|
||||
return Type::vector::<Value>(element, count);
|
||||
}
|
||||
}
|
||||
layout::Abi::ScalarPair(..) => {
|
||||
@ -93,7 +94,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
layout::FieldPlacement::Array { count, .. } => {
|
||||
Type::array(layout.field(cx, 0).llvm_type(cx), count)
|
||||
Type::array::<Value>(layout.field(cx, 0).llvm_type(cx), count)
|
||||
}
|
||||
layout::FieldPlacement::Arbitrary { .. } => {
|
||||
match name {
|
||||
|
@ -15,7 +15,10 @@ use llvm;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
pub trait ValueTrait: fmt::Debug {}
|
||||
pub trait ValueTrait: fmt::Debug {
|
||||
fn to_llvm(&self) -> &llvm::Value;
|
||||
fn of_llvm(&llvm::Value) -> &Self;
|
||||
}
|
||||
|
||||
impl PartialEq for Value {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
@ -23,7 +26,14 @@ impl PartialEq for Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueTrait for Value {}
|
||||
impl ValueTrait for Value {
|
||||
fn to_llvm(&self) -> &llvm::Value {
|
||||
&self
|
||||
}
|
||||
fn of_llvm(v: &llvm::Value) -> &Self {
|
||||
&v
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Value {}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user