Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
730b13ab
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
730b13ab
编写于
9月 05, 2018
作者:
D
Denis Merigoux
提交者:
Eduard-Mihai Burtescu
11月 16, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Traitification of type_ methods
The methods are now attached to CodegenCx instead of Type
上级
5f28e0a0
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
402 addition
and
407 deletion
+402
-407
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/abi.rs
+17
-17
src/librustc_codegen_llvm/asm.rs
src/librustc_codegen_llvm/asm.rs
+3
-4
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/back/write.rs
+9
-1
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/base.rs
+19
-19
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/builder.rs
+12
-12
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/common.rs
+16
-11
src/librustc_codegen_llvm/consts.rs
src/librustc_codegen_llvm/consts.rs
+4
-4
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/context.rs
+27
-26
src/librustc_codegen_llvm/debuginfo/gdb.rs
src/librustc_codegen_llvm/debuginfo/gdb.rs
+2
-3
src/librustc_codegen_llvm/interfaces/type_.rs
src/librustc_codegen_llvm/interfaces/type_.rs
+4
-6
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/intrinsic.rs
+47
-47
src/librustc_codegen_llvm/meth.rs
src/librustc_codegen_llvm/meth.rs
+7
-5
src/librustc_codegen_llvm/mir/block.rs
src/librustc_codegen_llvm/mir/block.rs
+6
-6
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/constant.rs
+5
-5
src/librustc_codegen_llvm/mir/mod.rs
src/librustc_codegen_llvm/mir/mod.rs
+1
-2
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_codegen_llvm/mir/operand.rs
+3
-4
src/librustc_codegen_llvm/mir/place.rs
src/librustc_codegen_llvm/mir/place.rs
+11
-12
src/librustc_codegen_llvm/mir/rvalue.rs
src/librustc_codegen_llvm/mir/rvalue.rs
+33
-22
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_llvm/type_.rs
+152
-178
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_llvm/type_of.rs
+24
-23
未找到文件。
src/librustc_codegen_llvm/abi.rs
浏览文件 @
730b13ab
...
...
@@ -18,7 +18,7 @@
use
type_of
::{
LayoutLlvmExt
,
PointerKind
};
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
rustc_target
::
abi
::{
HasDataLayout
,
LayoutOf
,
Size
,
TyLayout
,
Abi
as
LayoutAbi
};
use
rustc
::
ty
::{
self
,
Ty
};
...
...
@@ -111,16 +111,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
.ix
(
self
.size
.bits
()),
RegKind
::
Float
=>
{
match
self
.size
.bits
()
{
32
=>
Type
::
f32
(
cx
),
64
=>
Type
::
f64
(
cx
),
32
=>
cx
.f32
(
),
64
=>
cx
.f64
(
),
_
=>
bug!
(
"unsupported float: {:?}"
,
self
)
}
}
RegKind
::
Vector
=>
{
Type
::
vector
(
Type
::
i8
(
cx
),
self
.size
.bytes
())
cx
.vector
(
cx
.i8
(
),
self
.size
.bytes
())
}
}
}
...
...
@@ -144,7 +144,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
// 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
.
array
(
rest_ll_unit
,
rest_count
);
}
}
...
...
@@ -159,10 +159,10 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
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
.ix
(
rem_bytes
*
8
));
}
Type
::
struct_
(
cx
,
&
args
,
false
)
cx
.struct_
(
&
args
,
false
)
}
}
...
...
@@ -212,7 +212,7 @@ fn store(
// 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
,
c
ast
.llvm_type
(
cx
)
.ptr_to
(
));
let
cast_dst
=
bx
.pointercast
(
dst
.llval
,
c
x
.ptr_to
(
cast
.llvm_type
(
cx
)
));
bx
.store
(
val
,
cast_dst
,
self
.layout.align
);
}
else
{
// The actual return type is a struct, but the ABI
...
...
@@ -240,9 +240,9 @@ fn store(
// ...and then memcpy it to the intended destination.
base
::
call_memcpy
(
bx
,
bx
.pointercast
(
dst
.llval
,
Type
::
i8p
(
cx
)),
bx
.pointercast
(
dst
.llval
,
cx
.i8p
(
)),
self
.layout.align
,
bx
.pointercast
(
llscratch
,
Type
::
i8p
(
cx
)),
bx
.pointercast
(
llscratch
,
cx
.i8p
(
)),
scratch_align
,
cx
.c_usize
(
self
.layout.size
.bytes
()),
MemFlags
::
empty
());
...
...
@@ -635,14 +635,14 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
);
let
llreturn_ty
=
match
self
.ret.mode
{
PassMode
::
Ignore
=>
Type
::
void
(
cx
),
PassMode
::
Ignore
=>
cx
.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
.ptr_to
(
self
.ret
.memory_ty
(
cx
)
));
cx
.void
(
)
}
};
...
...
@@ -668,15 +668,15 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
continue
;
}
PassMode
::
Cast
(
cast
)
=>
cast
.llvm_type
(
cx
),
PassMode
::
Indirect
(
_
,
None
)
=>
arg
.memory_ty
(
cx
)
.ptr_to
(
),
PassMode
::
Indirect
(
_
,
None
)
=>
cx
.ptr_to
(
arg
.memory_ty
(
cx
)
),
};
llargument_tys
.push
(
llarg_ty
);
}
if
self
.variadic
{
Type
::
variadic_func
(
&
llargument_tys
,
llreturn_ty
)
cx
.
variadic_func
(
&
llargument_tys
,
llreturn_ty
)
}
else
{
Type
::
func
(
&
llargument_tys
,
llreturn_ty
)
cx
.
func
(
&
llargument_tys
,
llreturn_ty
)
}
}
...
...
src/librustc_codegen_llvm/asm.rs
浏览文件 @
730b13ab
...
...
@@ -10,13 +10,12 @@
use
llvm
;
use
context
::
CodegenCx
;
use
type_
::
Type
;
use
type_of
::
LayoutLlvmExt
;
use
builder
::
Builder
;
use
value
::
Value
;
use
rustc
::
hir
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
mir
::
place
::
PlaceRef
;
use
mir
::
operand
::
OperandValue
;
...
...
@@ -76,9 +75,9 @@ pub fn codegen_inline_asm(
// Depending on how many outputs we have, the return type is different
let
num_outputs
=
output_types
.len
();
let
output_type
=
match
num_outputs
{
0
=>
Type
::
void
(
bx
.cx
()
),
0
=>
bx
.cx
()
.void
(
),
1
=>
output_types
[
0
],
_
=>
Type
::
struct_
(
bx
.cx
(),
&
output_types
,
false
)
_
=>
bx
.cx
()
.struct_
(
&
output_types
,
false
)
};
let
asm
=
CString
::
new
(
ia
.asm
.as_str
()
.as_bytes
())
.unwrap
();
...
...
src/librustc_codegen_llvm/back/write.rs
浏览文件 @
730b13ab
...
...
@@ -456,6 +456,14 @@ fn c_struct_in_context(
}
}
impl
CodegenContext
<
'll
>
{
pub
fn
ptr_to
(
&
self
,
ty
:
&
'll
Type
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMPointerType
(
ty
,
0
)
}
}
}
pub
struct
DiagnosticHandlers
<
'a
>
{
data
:
*
mut
(
&
'a
CodegenContext
<
'a
>
,
&
'a
Handler
),
...
...
@@ -2609,7 +2617,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
(
cgcx
,
llcx
);
let
globals
=
base
::
iter_globals
(
llmod
)
.filter
(|
&
val
|
{
llvm
::
LLVMRustGetLinkage
(
val
)
==
llvm
::
Linkage
::
ExternalLinkage
&&
...
...
src/librustc_codegen_llvm/base.rs
浏览文件 @
730b13ab
...
...
@@ -74,7 +74,7 @@
use
rustc_data_structures
::
sync
::
Lrc
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
CommonWriteMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
CommonWriteMethods
,
TypeMethods
};
use
std
::
any
::
Any
;
use
std
::
cmp
;
...
...
@@ -234,13 +234,13 @@ pub fn unsize_thin_ptr(
(
&
ty
::
RawPtr
(
ty
::
TypeAndMut
{
ty
:
a
,
..
}),
&
ty
::
RawPtr
(
ty
::
TypeAndMut
{
ty
:
b
,
..
}))
=>
{
assert
!
(
bx
.cx
()
.type_is_sized
(
a
));
let
ptr_ty
=
bx
.cx
()
.
layout_of
(
b
)
.llvm_type
(
bx
.cx
())
.ptr_to
(
);
let
ptr_ty
=
bx
.cx
()
.
ptr_to
(
bx
.cx
()
.layout_of
(
b
)
.llvm_type
(
bx
.cx
())
);
(
bx
.pointercast
(
src
,
ptr_ty
),
unsized_info
(
bx
.cx
(),
a
,
b
,
None
))
}
(
&
ty
::
Adt
(
def_a
,
_
),
&
ty
::
Adt
(
def_b
,
_
))
if
def_a
.is_box
()
&&
def_b
.is_box
()
=>
{
let
(
a
,
b
)
=
(
src_ty
.boxed_ty
(),
dst_ty
.boxed_ty
());
assert
!
(
bx
.cx
()
.type_is_sized
(
a
));
let
ptr_ty
=
bx
.cx
()
.
layout_of
(
b
)
.llvm_type
(
bx
.cx
())
.ptr_to
(
);
let
ptr_ty
=
bx
.cx
()
.
ptr_to
(
bx
.cx
()
.layout_of
(
b
)
.llvm_type
(
bx
.cx
())
);
(
bx
.pointercast
(
src
,
ptr_ty
),
unsized_info
(
bx
.cx
(),
a
,
b
,
None
))
}
(
&
ty
::
Adt
(
def_a
,
_
),
&
ty
::
Adt
(
def_b
,
_
))
=>
{
...
...
@@ -353,14 +353,14 @@ fn cast_shift_rhs<'ll, F, G>(bx: &Builder<'_, 'll, '_>,
if
op
.is_shift
()
{
let
mut
rhs_llty
=
bx
.cx
()
.val_ty
(
rhs
);
let
mut
lhs_llty
=
bx
.cx
()
.val_ty
(
lhs
);
if
rhs_llty
.kind
(
)
==
TypeKind
::
Vector
{
rhs_llty
=
rhs_llty
.element_type
(
)
if
bx
.cx
()
.kind
(
rhs_llty
)
==
TypeKind
::
Vector
{
rhs_llty
=
bx
.cx
()
.element_type
(
rhs_llty
)
}
if
lhs_llty
.kind
(
)
==
TypeKind
::
Vector
{
lhs_llty
=
lhs_llty
.element_type
(
)
if
bx
.cx
()
.kind
(
lhs_llty
)
==
TypeKind
::
Vector
{
lhs_llty
=
bx
.cx
()
.element_type
(
lhs_llty
)
}
let
rhs_sz
=
rhs_llty
.int_width
(
);
let
lhs_sz
=
lhs_llty
.int_width
(
);
let
rhs_sz
=
bx
.cx
()
.int_width
(
rhs_llty
);
let
lhs_sz
=
bx
.cx
()
.int_width
(
lhs_llty
);
if
lhs_sz
<
rhs_sz
{
trunc
(
rhs
,
lhs_llty
)
}
else
if
lhs_sz
>
rhs_sz
{
...
...
@@ -393,8 +393,8 @@ pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll>(
bx
:
&
Builder
<
'_
,
'll
,
'_
,
&
'll
Value
>
,
val
:
&
'll
Value
)
->
&
'll
Value
{
if
bx
.cx
()
.val_ty
(
val
)
==
Type
::
i1
(
bx
.cx
()
)
{
bx
.zext
(
val
,
Type
::
i8
(
bx
.cx
()
))
if
bx
.cx
()
.val_ty
(
val
)
==
bx
.cx
()
.i1
(
)
{
bx
.zext
(
val
,
bx
.cx
()
.i8
(
))
}
else
{
val
}
...
...
@@ -417,7 +417,7 @@ pub fn to_immediate_scalar(
scalar
:
&
layout
::
Scalar
,
)
->
&
'll
Value
{
if
scalar
.is_bool
()
{
return
bx
.trunc
(
val
,
Type
::
i1
(
bx
.cx
()
));
return
bx
.trunc
(
val
,
bx
.cx
()
.i1
(
));
}
val
}
...
...
@@ -434,13 +434,13 @@ pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll>(
if
flags
.contains
(
MemFlags
::
NONTEMPORAL
)
{
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
let
val
=
bx
.load
(
src
,
src_align
);
let
ptr
=
bx
.pointercast
(
dst
,
bx
.cx
()
.
val_ty
(
val
)
.ptr_to
(
));
let
ptr
=
bx
.pointercast
(
dst
,
bx
.cx
()
.
ptr_to
(
bx
.cx
()
.val_ty
(
val
)
));
bx
.store_with_flags
(
val
,
ptr
,
dst_align
,
flags
);
return
;
}
let
cx
=
bx
.cx
();
let
src_ptr
=
bx
.pointercast
(
src
,
Type
::
i8p
(
cx
));
let
dst_ptr
=
bx
.pointercast
(
dst
,
Type
::
i8p
(
cx
));
let
src_ptr
=
bx
.pointercast
(
src
,
cx
.i8p
(
));
let
dst_ptr
=
bx
.pointercast
(
dst
,
cx
.i8p
(
));
let
size
=
bx
.intcast
(
n_bytes
,
cx
.isize_ty
,
false
);
let
volatile
=
flags
.contains
(
MemFlags
::
VOLATILE
);
bx
.memcpy
(
dst_ptr
,
dst_align
.abi
(),
src_ptr
,
src_align
.abi
(),
size
,
volatile
);
...
...
@@ -551,7 +551,7 @@ fn create_entry_fn(
use_start_lang_item
:
bool
,
)
{
let
llfty
=
Type
::
func
(
&
[
Type
::
c_int
(
cx
),
Type
::
i8p
(
cx
)
.ptr_to
()],
Type
::
c_int
(
cx
));
cx
.func
(
&
[
cx
.t_int
(),
cx
.ptr_to
(
cx
.i8p
())],
cx
.t_int
(
));
let
main_ret_ty
=
cx
.tcx
.fn_sig
(
rust_main_def_id
)
.output
();
// Given that `main()` has no arguments,
...
...
@@ -594,7 +594,7 @@ fn create_entry_fn(
start_def_id
,
cx
.tcx
.intern_substs
(
&
[
main_ret_ty
.into
()]),
);
(
start_fn
,
vec!
[
bx
.pointercast
(
rust_main
,
Type
::
i8p
(
cx
)
.ptr_to
(
)),
(
start_fn
,
vec!
[
bx
.pointercast
(
rust_main
,
cx
.ptr_to
(
cx
.i8p
()
)),
arg_argc
,
arg_argv
])
}
else
{
debug!
(
"using user-defined start fn"
);
...
...
@@ -602,7 +602,7 @@ fn create_entry_fn(
};
let
result
=
bx
.call
(
start_fn
,
&
args
,
None
);
bx
.ret
(
bx
.intcast
(
result
,
Type
::
c_int
(
cx
),
true
));
bx
.ret
(
bx
.intcast
(
result
,
cx
.t_int
(
),
true
));
}
}
...
...
@@ -1151,7 +1151,7 @@ fn module_codegen<'a, 'tcx>(
if
!
cx
.used_statics
.borrow
()
.is_empty
()
{
let
name
=
const_cstr!
(
"llvm.used"
);
let
section
=
const_cstr!
(
"llvm.metadata"
);
let
array
=
cx
.c_array
(
Type
::
i8
(
&
cx
)
.ptr_to
(
),
&*
cx
.used_statics
.borrow
());
let
array
=
cx
.c_array
(
&
cx
.ptr_to
(
cx
.i8
()
),
&*
cx
.used_statics
.borrow
());
unsafe
{
let
g
=
llvm
::
LLVMAddGlobal
(
cx
.llmod
,
...
...
src/librustc_codegen_llvm/builder.rs
浏览文件 @
730b13ab
...
...
@@ -19,7 +19,7 @@
use
rustc
::
ty
::
layout
::{
Align
,
Size
};
use
rustc
::
session
::{
config
,
Session
};
use
rustc_data_structures
::
small_c_str
::
SmallCStr
;
use
interfaces
::{
BuilderMethods
,
Backend
,
CommonMethods
,
CommonWriteMethods
};
use
interfaces
::{
BuilderMethods
,
Backend
,
CommonMethods
,
CommonWriteMethods
,
TypeMethods
};
use
syntax
;
use
std
::
borrow
::
Cow
;
...
...
@@ -765,7 +765,7 @@ fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
})
.collect
::
<
Vec
<
_
>>
();
debug!
(
"Asm Output Type: {:?}"
,
output
);
let
fty
=
type_
::
Type
::
func
(
&
argtys
[
..
],
output
);
let
fty
=
&
self
.cx
()
.
func
(
&
argtys
[
..
],
output
);
unsafe
{
// Ask LLVM to verify that the constraints are well-formed.
let
constraints_ok
=
llvm
::
LLVMRustInlineAsmVerify
(
fty
,
cons
);
...
...
@@ -861,10 +861,10 @@ fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'
fn
vector_splat
(
&
self
,
num_elts
:
usize
,
elt
:
&
'll
Value
)
->
&
'll
Value
{
unsafe
{
let
elt_ty
=
self
.cx
.val_ty
(
elt
);
let
undef
=
llvm
::
LLVMGetUndef
(
type_
::
Type
::
vector
(
elt_ty
,
num_elts
as
u64
));
let
undef
=
llvm
::
LLVMGetUndef
(
&
self
.cx
()
.
vector
(
elt_ty
,
num_elts
as
u64
));
let
vec
=
self
.insert_element
(
undef
,
elt
,
self
.cx
.c_i32
(
0
));
let
vec_i32_ty
=
type_
::
Type
::
vector
(
type_
::
Type
::
i32
(
self
.cx
),
num_elts
as
u64
);
self
.shuffle_vector
(
vec
,
undef
,
self
.cx
.c_null
(
vec_i32_ty
))
let
vec_i32_ty
=
&
self
.cx
()
.vector
(
&
self
.cx
()
.i32
(
),
num_elts
as
u64
);
self
.shuffle_vector
(
vec
,
undef
,
self
.cx
()
.c_null
(
vec_i32_ty
))
}
}
...
...
@@ -1142,9 +1142,9 @@ fn check_store<'b>(&self,
ptr
:
&
'll
Value
)
->
&
'll
Value
{
let
dest_ptr_ty
=
self
.cx
.val_ty
(
ptr
);
let
stored_ty
=
self
.cx
.val_ty
(
val
);
let
stored_ptr_ty
=
s
tored_ty
.ptr_to
(
);
let
stored_ptr_ty
=
s
elf
.cx
.ptr_to
(
stored_ty
);
assert_eq!
(
dest_ptr_ty
.kind
(
),
llvm
::
TypeKind
::
Pointer
);
assert_eq!
(
self
.cx
.kind
(
dest_ptr_ty
),
llvm
::
TypeKind
::
Pointer
);
if
dest_ptr_ty
==
stored_ptr_ty
{
ptr
...
...
@@ -1163,14 +1163,14 @@ fn check_call<'b>(&self,
args
:
&
'b
[
&
'll
Value
])
->
Cow
<
'b
,
[
&
'll
Value
]
>
{
let
mut
fn_ty
=
self
.cx
.val_ty
(
llfn
);
// Strip off pointers
while
fn_ty
.kind
(
)
==
llvm
::
TypeKind
::
Pointer
{
fn_ty
=
fn_ty
.element_type
(
);
while
self
.cx
.kind
(
fn_ty
)
==
llvm
::
TypeKind
::
Pointer
{
fn_ty
=
self
.cx
.element_type
(
fn_ty
);
}
assert
!
(
fn_ty
.kind
(
)
==
llvm
::
TypeKind
::
Function
,
assert
!
(
self
.cx
.kind
(
fn_ty
)
==
llvm
::
TypeKind
::
Function
,
"builder::{} not passed a function, but {:?}"
,
typ
,
fn_ty
);
let
param_tys
=
fn_ty
.func_params
(
);
let
param_tys
=
self
.cx
.func_params
(
fn_ty
);
let
all_args_match
=
param_tys
.iter
()
.zip
(
args
.iter
()
.map
(|
&
v
|
self
.cx
()
.val_ty
(
v
)))
...
...
@@ -1227,7 +1227,7 @@ fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size)
let
lifetime_intrinsic
=
self
.cx
.get_intrinsic
(
intrinsic
);
let
ptr
=
self
.pointercast
(
ptr
,
type_
::
Type
::
i8p
(
self
.cx
));
let
ptr
=
self
.pointercast
(
ptr
,
self
.cx
.i8p
(
));
self
.call
(
lifetime_intrinsic
,
&
[
self
.cx
.c_u64
(
size
),
ptr
],
None
);
}
...
...
src/librustc_codegen_llvm/common.rs
浏览文件 @
730b13ab
...
...
@@ -24,7 +24,7 @@
use
type_
::
Type
;
use
type_of
::
LayoutLlvmExt
;
use
value
::
Value
;
use
interfaces
::{
Backend
,
CommonMethods
,
CommonWriteMethods
};
use
interfaces
::{
Backend
,
CommonMethods
,
CommonWriteMethods
,
TypeMethods
};
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
rustc
::
ty
::
layout
::{
HasDataLayout
,
LayoutOf
};
...
...
@@ -236,19 +236,19 @@ fn c_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
}
fn
c_bool
(
&
self
,
val
:
bool
)
->
&
'll
Value
{
&
self
.c_uint
(
Type
::
i1
(
&
self
),
val
as
u64
)
&
self
.c_uint
(
&
self
.i1
(
),
val
as
u64
)
}
fn
c_i32
(
&
self
,
i
:
i32
)
->
&
'll
Value
{
&
self
.c_int
(
Type
::
i32
(
&
self
),
i
as
i64
)
&
self
.c_int
(
&
self
.i32
(
),
i
as
i64
)
}
fn
c_u32
(
&
self
,
i
:
u32
)
->
&
'll
Value
{
&
self
.c_uint
(
Type
::
i32
(
&
self
),
i
as
u64
)
&
self
.c_uint
(
&
self
.i32
(
),
i
as
u64
)
}
fn
c_u64
(
&
self
,
i
:
u64
)
->
&
'll
Value
{
&
self
.c_uint
(
Type
::
i64
(
&
self
),
i
)
&
self
.c_uint
(
&
self
.i64
(
),
i
)
}
fn
c_usize
(
&
self
,
i
:
u64
)
->
&
'll
Value
{
...
...
@@ -262,7 +262,7 @@ fn c_usize(&self, i: u64) -> &'ll Value {
}
fn
c_u8
(
&
self
,
i
:
u8
)
->
&
'll
Value
{
&
self
.c_uint
(
Type
::
i8
(
&
self
),
i
as
u64
)
&
self
.c_uint
(
&
self
.i8
(
),
i
as
u64
)
}
...
...
@@ -300,7 +300,7 @@ fn c_cstr(
fn
c_str_slice
(
&
self
,
s
:
LocalInternedString
)
->
&
'll
Value
{
let
len
=
s
.len
();
let
cs
=
consts
::
ptrcast
(
&
self
.c_cstr
(
s
,
false
),
&
self
.
layout_of
(
&
self
.tcx
.mk_str
())
.llvm_type
(
&
self
)
.ptr_to
(
));
&
self
.
ptr_to
(
&
self
.layout_of
(
&
self
.tcx
.mk_str
())
.llvm_type
(
&
self
)
));
&
self
.c_fat_ptr
(
cs
,
&
self
.c_usize
(
len
as
u64
))
}
...
...
@@ -505,11 +505,11 @@ pub fn shift_mask_val(
mask_llty
:
&
'll
Type
,
invert
:
bool
)
->
&
'll
Value
{
let
kind
=
llty
.kind
(
);
let
kind
=
bx
.cx
()
.kind
(
llty
);
match
kind
{
TypeKind
::
Integer
=>
{
// i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
let
val
=
llty
.int_width
(
)
-
1
;
let
val
=
bx
.cx
()
.int_width
(
llty
)
-
1
;
if
invert
{
bx
.cx
.c_int
(
mask_llty
,
!
val
as
i64
)
}
else
{
...
...
@@ -517,8 +517,13 @@ pub fn shift_mask_val(
}
},
TypeKind
::
Vector
=>
{
let
mask
=
shift_mask_val
(
bx
,
llty
.element_type
(),
mask_llty
.element_type
(),
invert
);
bx
.vector_splat
(
mask_llty
.vector_length
(),
mask
)
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
),
}
...
...
src/librustc_codegen_llvm/consts.rs
浏览文件 @
730b13ab
...
...
@@ -24,7 +24,7 @@
use
type_of
::
LayoutLlvmExt
;
use
value
::
Value
;
use
rustc
::
ty
::{
self
,
Ty
};
use
interfaces
::
CommonWriteMethods
;
use
interfaces
::
{
CommonWriteMethods
,
TypeMethods
}
;
use
rustc
::
ty
::
layout
::{
Align
,
LayoutOf
};
...
...
@@ -313,8 +313,8 @@ pub fn codegen_static<'a, 'tcx>(
// boolean SSA values are i1, but they have to be stored in i8 slots,
// otherwise some LLVM optimization passes don't work as expected
let
mut
val_llty
=
cx
.val_ty
(
v
);
let
v
=
if
val_llty
==
Type
::
i1
(
cx
)
{
val_llty
=
Type
::
i8
(
cx
);
let
v
=
if
val_llty
==
cx
.i1
(
)
{
val_llty
=
cx
.i8
(
);
llvm
::
LLVMConstZExt
(
v
,
val_llty
)
}
else
{
v
...
...
@@ -432,7 +432,7 @@ pub fn codegen_static<'a, 'tcx>(
if
attrs
.flags
.contains
(
CodegenFnAttrFlags
::
USED
)
{
// This static will be stored in the llvm.used variable which is an array of i8*
let
cast
=
llvm
::
LLVMConstPointerCast
(
g
,
Type
::
i8p
(
cx
));
let
cast
=
llvm
::
LLVMConstPointerCast
(
g
,
cx
.i8p
(
));
cx
.used_statics
.borrow_mut
()
.push
(
cast
);
}
}
...
...
src/librustc_codegen_llvm/context.rs
浏览文件 @
730b13ab
...
...
@@ -23,6 +23,7 @@
use
monomorphize
::
partitioning
::
CodegenUnit
;
use
type_
::
Type
;
use
type_of
::
PointeeInfo
;
use
interfaces
::
TypeMethods
;
use
rustc_data_structures
::
base_n
;
use
rustc_data_structures
::
small_c_str
::
SmallCStr
;
...
...
@@ -379,7 +380,7 @@ pub fn eh_personality(&self) -> &'b Value {
}
else
{
"rust_eh_personality"
};
let
fty
=
Type
::
variadic_func
(
&
[],
Type
::
i32
(
self
));
let
fty
=
&
self
.variadic_func
(
&
[],
&
self
.i32
(
));
declare
::
declare_cfn
(
self
,
name
,
fty
)
}
};
...
...
@@ -487,7 +488,7 @@ fn declare_intrinsic(
macro_rules!
ifn
{
(
$name:expr
,
fn
()
->
$ret:expr
)
=>
(
if
key
==
$name
{
let
f
=
declare
::
declare_cfn
(
cx
,
$name
,
Type
::
func
(
&
[],
$ret
));
let
f
=
declare
::
declare_cfn
(
cx
,
$name
,
cx
.
func
(
&
[],
$ret
));
llvm
::
SetUnnamedAddr
(
f
,
false
);
cx
.intrinsics
.borrow_mut
()
.insert
(
$name
,
f
.clone
());
return
Some
(
f
);
...
...
@@ -495,7 +496,7 @@ fn declare_intrinsic(
);
(
$name:expr
,
fn
(
...
)
->
$ret:expr
)
=>
(
if
key
==
$name
{
let
f
=
declare
::
declare_cfn
(
cx
,
$name
,
Type
::
variadic_func
(
&
[],
$ret
));
let
f
=
declare
::
declare_cfn
(
cx
,
$name
,
cx
.
variadic_func
(
&
[],
$ret
));
llvm
::
SetUnnamedAddr
(
f
,
false
);
cx
.intrinsics
.borrow_mut
()
.insert
(
$name
,
f
.clone
());
return
Some
(
f
);
...
...
@@ -503,7 +504,7 @@ fn declare_intrinsic(
);
(
$name:expr
,
fn
(
$
(
$arg:expr
),
*
)
->
$ret:expr
)
=>
(
if
key
==
$name
{
let
f
=
declare
::
declare_cfn
(
cx
,
$name
,
Type
::
func
(
&
[
$
(
$arg
),
*
],
$ret
));
let
f
=
declare
::
declare_cfn
(
cx
,
$name
,
cx
.
func
(
&
[
$
(
$arg
),
*
],
$ret
));
llvm
::
SetUnnamedAddr
(
f
,
false
);
cx
.intrinsics
.borrow_mut
()
.insert
(
$name
,
f
.clone
());
return
Some
(
f
);
...
...
@@ -511,28 +512,28 @@ fn declare_intrinsic(
);
}
macro_rules!
mk_struct
{
(
$
(
$field_ty:expr
),
*
)
=>
(
Type
::
struct_
(
cx
,
&
[
$
(
$field_ty
),
*
],
false
))
(
$
(
$field_ty:expr
),
*
)
=>
(
cx
.struct_
(
&
[
$
(
$field_ty
),
*
],
false
))
}
let
i8p
=
Type
::
i8p
(
cx
);
let
void
=
Type
::
void
(
cx
);
let
i1
=
Type
::
i1
(
cx
);
let
t_i8
=
Type
::
i8
(
cx
);
let
t_i16
=
Type
::
i16
(
cx
);
let
t_i32
=
Type
::
i32
(
cx
);
let
t_i64
=
Type
::
i64
(
cx
);
let
t_i128
=
Type
::
i128
(
cx
);
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_v2f64
=
Type
::
vector
(
t_f64
,
2
);
let
t_v4f64
=
Type
::
vector
(
t_f64
,
4
);
let
t_v8f64
=
Type
::
vector
(
t_f64
,
8
);
let
i8p
=
cx
.i8p
(
);
let
void
=
cx
.void
(
);
let
i1
=
cx
.i1
(
);
let
t_i8
=
cx
.i8
(
);
let
t_i16
=
cx
.i16
(
);
let
t_i32
=
cx
.i32
(
);
let
t_i64
=
cx
.i64
(
);
let
t_i128
=
cx
.i128
(
);
let
t_f32
=
cx
.f32
(
);
let
t_f64
=
cx
.f64
(
);
let
t_v2f32
=
cx
.
vector
(
t_f32
,
2
);
let
t_v4f32
=
cx
.
vector
(
t_f32
,
4
);
let
t_v8f32
=
cx
.
vector
(
t_f32
,
8
);
let
t_v16f32
=
cx
.
vector
(
t_f32
,
16
);
let
t_v2f64
=
cx
.
vector
(
t_f64
,
2
);
let
t_v4f64
=
cx
.
vector
(
t_f64
,
4
);
let
t_v8f64
=
cx
.
vector
(
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
);
...
...
@@ -785,8 +786,8 @@ fn declare_intrinsic(
ifn!
(
"llvm.prefetch"
,
fn
(
i8p
,
t_i32
,
t_i32
,
t_i32
)
->
void
);
if
cx
.sess
()
.opts.debuginfo
!=
DebugInfo
::
None
{
ifn!
(
"llvm.dbg.declare"
,
fn
(
Type
::
metadata
(
cx
),
Type
::
metadata
(
cx
))
->
void
);
ifn!
(
"llvm.dbg.value"
,
fn
(
Type
::
metadata
(
cx
),
t_i64
,
Type
::
metadata
(
cx
))
->
void
);
ifn!
(
"llvm.dbg.declare"
,
fn
(
cx
.metadata
(),
cx
.metadata
(
))
->
void
);
ifn!
(
"llvm.dbg.value"
,
fn
(
cx
.metadata
(),
t_i64
,
cx
.metadata
(
))
->
void
);
}
None
...
...
src/librustc_codegen_llvm/debuginfo/gdb.rs
浏览文件 @
730b13ab
...
...
@@ -16,9 +16,8 @@
use
builder
::
Builder
;
use
declare
;
use
rustc
::
session
::
config
::
DebugInfo
;
use
type_
::
Type
;
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
syntax
::
attr
;
...
...
@@ -56,7 +55,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
let
section_contents
=
b
"
\x01
gdb_load_rust_pretty_printers.py
\0
"
;
unsafe
{
let
llvm_type
=
Type
::
array
(
Type
::
i8
(
cx
),
let
llvm_type
=
cx
.array
(
cx
.i8
(
),
section_contents
.len
()
as
u64
);
let
section_var
=
declare
::
define_global
(
cx
,
section_var_name
,
...
...
src/librustc_codegen_llvm/interfaces/type_.rs
浏览文件 @
730b13ab
...
...
@@ -22,22 +22,20 @@ pub trait TypeMethods : Backend {
fn
ix
(
&
self
,
num_bites
:
u64
)
->
Self
::
Type
;
fn
f32
(
&
self
)
->
Self
::
Type
;
fn
f64
(
&
self
)
->
Self
::
Type
;
fn
bool
(
&
self
)
->
Self
::
Type
;
fn
char
(
&
self
)
->
Self
::
Type
;
fn
i8p
(
&
self
)
->
Self
::
Type
;
fn
x86_mmx
(
&
self
)
->
Self
::
Type
;
fn
func
(
&
self
,
args
:
&
[
Self
::
Type
],
ret
:
Self
::
Type
)
->
Self
::
Type
;
fn
variadic_func
(
&
self
,
args
:
&
[
Self
::
Type
])
->
Self
::
Type
;
fn
variadic_func
(
&
self
,
args
:
&
[
Self
::
Type
]
,
ret
:
Self
::
Type
)
->
Self
::
Type
;
fn
struct_
(
&
self
,
els
:
&
[
Self
::
Type
],
packed
:
bool
)
->
Self
::
Type
;
fn
named_struct
(
&
self
,
name
:
&
str
)
->
Self
::
Type
;
fn
array
(
&
self
,
ty
:
Self
::
Type
,
len
:
u64
)
->
Self
::
Type
;
fn
vector
(
&
self
,
ty
:
Self
::
Type
,
len
:
u64
)
->
Self
::
Type
;
fn
kind
(
&
self
,
ty
:
Self
::
Type
)
->
Self
::
TypeKind
;
fn
set_struct_body
(
&
self
,
els
:
&
[
Self
::
Type
],
packed
:
bool
);
fn
set_struct_body
(
&
self
,
ty
:
Self
::
Type
,
els
:
&
[
Self
::
Type
],
packed
:
bool
);
fn
ptr_to
(
&
self
,
ty
:
Self
::
Type
)
->
Self
::
Type
;
fn
element_type
(
&
self
,
ty
:
Self
::
Type
)
->
Self
::
Type
;
fn
vector_length
(
&
self
,
ty
:
Self
::
Type
)
->
usize
;
fn
func_params
(
&
self
,
ty
:
Self
::
Type
)
->
Vec
<
Self
::
Type
>
;
fn
float_width
(
&
self
,
ty
:
Self
::
Type
)
->
usize
;
fn
int_width
(
&
self
,
ty
:
Self
::
Type
)
->
u
size
;
fn
int_width
(
&
self
,
ty
:
Self
::
Type
)
->
u
64
;
}
src/librustc_codegen_llvm/intrinsic.rs
浏览文件 @
730b13ab
...
...
@@ -32,7 +32,7 @@
use
builder
::
Builder
;
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
rustc
::
session
::
Session
;
use
syntax_pos
::
Span
;
...
...
@@ -252,7 +252,7 @@ pub fn codegen_intrinsic_call(
let
tp_ty
=
substs
.type_at
(
0
);
let
mut
ptr
=
args
[
0
]
.immediate
();
if
let
PassMode
::
Cast
(
ty
)
=
fn_ty
.ret.mode
{
ptr
=
bx
.pointercast
(
ptr
,
ty
.llvm_type
(
cx
)
.ptr_to
(
));
ptr
=
bx
.pointercast
(
ptr
,
bx
.cx
()
.ptr_to
(
ty
.llvm_type
(
cx
)
));
}
let
load
=
bx
.volatile_load
(
ptr
);
let
align
=
if
name
==
"unaligned_volatile_load"
{
...
...
@@ -338,7 +338,7 @@ pub fn codegen_intrinsic_call(
args
[
1
]
.immediate
()
],
None
);
let
val
=
bx
.extract_value
(
pair
,
0
);
let
overflow
=
bx
.zext
(
bx
.extract_value
(
pair
,
1
),
Type
::
bool
(
cx
));
let
overflow
=
bx
.zext
(
bx
.extract_value
(
pair
,
1
),
cx
.bool
(
));
let
dest
=
result
.project_field
(
bx
,
0
);
bx
.store
(
val
,
dest
.llval
,
dest
.align
);
...
...
@@ -388,7 +388,7 @@ pub fn codegen_intrinsic_call(
}
else
{
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
let
width
=
cx
.c_uint
(
Type
::
ix
(
cx
,
width
),
width
);
let
width
=
cx
.c_uint
(
cx
.ix
(
width
),
width
);
let
shift
=
bx
.urem
(
raw_shift
,
width
);
let
inv_shift
=
bx
.urem
(
bx
.sub
(
width
,
raw_shift
),
width
);
let
shift1
=
bx
.shl
(
val
,
if
is_left
{
shift
}
else
{
inv_shift
});
...
...
@@ -495,7 +495,7 @@ pub fn codegen_intrinsic_call(
failorder
,
weak
);
let
val
=
bx
.extract_value
(
pair
,
0
);
let
success
=
bx
.zext
(
bx
.extract_value
(
pair
,
1
),
Type
::
bool
(
bx
.cx
()
));
let
success
=
bx
.zext
(
bx
.extract_value
(
pair
,
1
),
bx
.cx
()
.bool
(
));
let
dest
=
result
.project_field
(
bx
,
0
);
bx
.store
(
val
,
dest
.llval
,
dest
.align
);
...
...
@@ -582,32 +582,32 @@ fn one<T>(x: Vec<T>) -> T {
fn
ty_to_type
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
t
:
&
intrinsics
::
Type
)
->
Vec
<&
'll
Type
>
{
use
intrinsics
::
Type
::
*
;
match
*
t
{
Void
=>
vec!
[
Type
::
void
(
cx
)],
Void
=>
vec!
[
cx
.void
(
)],
Integer
(
_
signed
,
_
width
,
llvm_width
)
=>
{
vec!
[
Type
::
ix
(
cx
,
llvm_width
as
u64
)]
vec!
[
cx
.ix
(
llvm_width
as
u64
)]
}
Float
(
x
)
=>
{
match
x
{
32
=>
vec!
[
Type
::
f32
(
cx
)],
64
=>
vec!
[
Type
::
f64
(
cx
)],
32
=>
vec!
[
cx
.f32
(
)],
64
=>
vec!
[
cx
.f64
(
)],
_
=>
bug!
()
}
}
Pointer
(
ref
t
,
ref
llvm_elem
,
_
const
)
=>
{
let
t
=
llvm_elem
.as_ref
()
.unwrap_or
(
t
);
let
elem
=
one
(
ty_to_type
(
cx
,
t
));
vec!
[
elem
.ptr_to
(
)]
vec!
[
cx
.ptr_to
(
elem
)]
}
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!
[
cx
.
vector
(
elem
,
length
as
u64
)]
}
Aggregate
(
false
,
ref
contents
)
=>
{
let
elems
=
contents
.iter
()
.map
(|
t
|
one
(
ty_to_type
(
cx
,
t
)))
.collect
::
<
Vec
<
_
>>
();
vec!
[
Type
::
struct_
(
cx
,
&
elems
,
false
)]
vec!
[
cx
.struct_
(
&
elems
,
false
)]
}
Aggregate
(
true
,
ref
contents
)
=>
{
contents
.iter
()
...
...
@@ -646,20 +646,20 @@ fn modify_as_needed(
}
intrinsics
::
Type
::
Pointer
(
_
,
Some
(
ref
llvm_elem
),
_
)
=>
{
let
llvm_elem
=
one
(
ty_to_type
(
bx
.cx
(),
llvm_elem
));
vec!
[
bx
.pointercast
(
arg
.immediate
(),
llvm_elem
.ptr_to
(
))]
vec!
[
bx
.pointercast
(
arg
.immediate
(),
bx
.cx
()
.ptr_to
(
llvm_elem
))]
}
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
))
bx
.cx
()
.
vector
(
llvm_elem
,
length
as
u64
))
]
}
intrinsics
::
Type
::
Integer
(
_
,
width
,
llvm_width
)
if
width
!=
llvm_width
=>
{
// the LLVM intrinsic uses a smaller integer
// size than the C intrinsic's signature, so
// we have to trim it down here.
vec!
[
bx
.trunc
(
arg
.immediate
(),
Type
::
ix
(
bx
.cx
(),
llvm_width
as
u64
))]
vec!
[
bx
.trunc
(
arg
.immediate
(),
bx
.cx
()
.ix
(
llvm_width
as
u64
))]
}
_
=>
vec!
[
arg
.immediate
()],
}
...
...
@@ -681,7 +681,7 @@ fn modify_as_needed(
intrinsics
::
IntrinsicDef
::
Named
(
name
)
=>
{
let
f
=
declare
::
declare_cfn
(
cx
,
name
,
Type
::
func
(
&
inputs
,
outputs
));
cx
.
func
(
&
inputs
,
outputs
));
bx
.call
(
f
,
&
llargs
,
None
)
}
};
...
...
@@ -705,7 +705,7 @@ fn modify_as_needed(
if
!
fn_ty
.ret
.is_ignore
()
{
if
let
PassMode
::
Cast
(
ty
)
=
fn_ty
.ret.mode
{
let
ptr
=
bx
.pointercast
(
result
.llval
,
ty
.llvm_type
(
cx
)
.ptr_to
(
));
let
ptr
=
bx
.pointercast
(
result
.llval
,
cx
.ptr_to
(
ty
.llvm_type
(
cx
)
));
bx
.store
(
llval
,
ptr
,
result
.align
);
}
else
{
OperandRef
::
from_immediate_or_packed_pair
(
bx
,
llval
,
result
.layout
)
...
...
@@ -727,8 +727,8 @@ fn copy_intrinsic(
let
(
size
,
align
)
=
cx
.size_and_align_of
(
ty
);
let
size
=
cx
.c_usize
(
size
.bytes
());
let
align
=
align
.abi
();
let
dst_ptr
=
bx
.pointercast
(
dst
,
Type
::
i8p
(
cx
));
let
src_ptr
=
bx
.pointercast
(
src
,
Type
::
i8p
(
cx
));
let
dst_ptr
=
bx
.pointercast
(
dst
,
cx
.i8p
(
));
let
src_ptr
=
bx
.pointercast
(
src
,
cx
.i8p
(
));
if
allow_overlap
{
bx
.memmove
(
dst_ptr
,
align
,
src_ptr
,
align
,
bx
.mul
(
size
,
count
),
volatile
)
}
else
{
...
...
@@ -748,7 +748,7 @@ fn memset_intrinsic(
let
(
size
,
align
)
=
cx
.size_and_align_of
(
ty
);
let
size
=
cx
.c_usize
(
size
.bytes
());
let
align
=
cx
.c_i32
(
align
.abi
()
as
i32
);
let
dst
=
bx
.pointercast
(
dst
,
Type
::
i8p
(
cx
));
let
dst
=
bx
.pointercast
(
dst
,
cx
.i8p
(
));
call_memset
(
bx
,
dst
,
val
,
bx
.mul
(
size
,
count
),
align
,
volatile
)
}
...
...
@@ -763,7 +763,7 @@ fn try_intrinsic(
if
bx
.sess
()
.no_landing_pads
()
{
bx
.call
(
func
,
&
[
data
],
None
);
let
ptr_align
=
bx
.tcx
()
.data_layout.pointer_align
;
bx
.store
(
bx
.cx
()
.c_null
(
Type
::
i8p
(
&
bx
.cx
()
)),
dest
,
ptr_align
);
bx
.store
(
cx
.c_null
(
cx
.i8p
(
)),
dest
,
ptr_align
);
}
else
if
wants_msvc_seh
(
bx
.sess
())
{
codegen_msvc_try
(
bx
,
cx
,
func
,
data
,
local_ptr
,
dest
);
}
else
{
...
...
@@ -839,7 +839,7 @@ fn codegen_msvc_try(
// }
//
// More information can be found in libstd's seh.rs implementation.
let
i64p
=
Type
::
i64
(
cx
)
.ptr_to
(
);
let
i64p
=
cx
.ptr_to
(
cx
.i64
()
);
let
ptr_align
=
bx
.tcx
()
.data_layout.pointer_align
;
let
slot
=
bx
.alloca
(
i64p
,
"slot"
,
ptr_align
);
bx
.invoke
(
func
,
&
[
data
],
normal
.llbb
(),
catchswitch
.llbb
(),
None
);
...
...
@@ -930,12 +930,12 @@ fn codegen_gnu_try(
// being thrown. The second value is a "selector" indicating which of
// the landing pad clauses the exception's type had been matched to.
// rust_try ignores the selector.
let
lpad_ty
=
Type
::
struct_
(
cx
,
&
[
Type
::
i8p
(
cx
),
Type
::
i32
(
cx
)],
false
);
let
lpad_ty
=
cx
.struct_
(
&
[
cx
.i8p
(),
cx
.i32
(
)],
false
);
let
vals
=
catch
.landing_pad
(
lpad_ty
,
bx
.cx
()
.eh_personality
(),
1
);
catch
.add_clause
(
vals
,
bx
.cx
()
.c_null
(
Type
::
i8p
(
cx
)));
catch
.add_clause
(
vals
,
bx
.cx
()
.c_null
(
cx
.i8p
(
)));
let
ptr
=
catch
.extract_value
(
vals
,
0
);
let
ptr_align
=
bx
.tcx
()
.data_layout.pointer_align
;
catch
.store
(
ptr
,
catch
.bitcast
(
local_ptr
,
Type
::
i8p
(
cx
)
.ptr_to
(
)),
ptr_align
);
catch
.store
(
ptr
,
catch
.bitcast
(
local_ptr
,
cx
.ptr_to
(
cx
.i8p
()
)),
ptr_align
);
catch
.ret
(
cx
.c_i32
(
1
));
});
...
...
@@ -1078,7 +1078,7 @@ fn generic_simd_intrinsic(
found `{}` with length {}"
,
in_len
,
in_ty
,
ret_ty
,
out_len
);
require!
(
llret_ty
.element_type
()
.kind
(
)
==
TypeKind
::
Integer
,
require!
(
bx
.cx
()
.kind
(
bx
.cx
()
.element_type
(
llret_ty
)
)
==
TypeKind
::
Integer
,
"expected return type with integer elements, found `{}` with non-integer `{}`"
,
ret_ty
,
ret_ty
.simd_type
(
tcx
));
...
...
@@ -1167,8 +1167,8 @@ fn generic_simd_intrinsic(
_
=>
return_error!
(
"mask element type is `{}`, expected `i_`"
,
m_elem_ty
)
}
// truncate the mask to a vector of i1s
let
i1
=
Type
::
i1
(
bx
.cx
()
);
let
i1xn
=
Type
::
vector
(
i1
,
m_len
as
u64
);
let
i1
=
bx
.cx
()
.i1
(
);
let
i1xn
=
bx
.cx
()
.
vector
(
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
()));
}
...
...
@@ -1300,16 +1300,16 @@ fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize,
mut
no_pointers
:
usize
)
->
&
'll
Type
{
// FIXME: use cx.layout_of(ty).llvm_type() ?
let
mut
elem_ty
=
match
elem_ty
.sty
{
ty
::
Int
(
v
)
=>
Type
::
int_from_ty
(
cx
,
v
),
ty
::
Uint
(
v
)
=>
Type
::
uint_from_ty
(
cx
,
v
),
ty
::
Float
(
v
)
=>
Type
::
float_from_ty
(
cx
,
v
),
ty
::
Int
(
v
)
=>
cx
.int_from_ty
(
v
),
ty
::
Uint
(
v
)
=>
cx
.uint_from_ty
(
v
),
ty
::
Float
(
v
)
=>
cx
.float_from_ty
(
v
),
_
=>
unreachable!
(),
};
while
no_pointers
>
0
{
elem_ty
=
elem_ty
.ptr_to
(
);
elem_ty
=
cx
.ptr_to
(
elem_ty
);
no_pointers
-=
1
;
}
Type
::
vector
(
elem_ty
,
vec_len
as
u64
)
cx
.
vector
(
elem_ty
,
vec_len
as
u64
)
}
...
...
@@ -1386,13 +1386,13 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
}
// Alignment of T, must be a constant integer value:
let
alignment_ty
=
Type
::
i32
(
bx
.cx
()
);
let
alignment_ty
=
bx
.cx
()
.i32
(
);
let
alignment
=
bx
.cx
()
.c_i32
(
bx
.cx
()
.align_of
(
in_elem
)
.abi
()
as
i32
);
// 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
i1
=
bx
.cx
()
.i1
(
);
let
i1xn
=
bx
.cx
()
.
vector
(
i1
,
in_len
as
u64
);
(
bx
.trunc
(
args
[
2
]
.immediate
(),
i1xn
),
i1xn
)
};
...
...
@@ -1407,7 +1407,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
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
(
&
[
bx
.cx
()
.
func
(
&
[
llvm_pointer_vec_ty
,
alignment_ty
,
mask_ty
,
...
...
@@ -1486,17 +1486,17 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
}
// Alignment of T, must be a constant integer value:
let
alignment_ty
=
Type
::
i32
(
bx
.cx
()
);
let
alignment_ty
=
bx
.cx
()
.i32
(
);
let
alignment
=
bx
.cx
()
.c_i32
(
bx
.cx
()
.align_of
(
in_elem
)
.abi
()
as
i32
);
// 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
i1
=
bx
.cx
()
.i1
(
);
let
i1xn
=
bx
.cx
()
.
vector
(
i1
,
in_len
as
u64
);
(
bx
.trunc
(
args
[
2
]
.immediate
(),
i1xn
),
i1xn
)
};
let
ret_t
=
Type
::
void
(
bx
.cx
()
);
let
ret_t
=
bx
.cx
()
.void
(
);
// Type of the vector of pointers:
let
llvm_pointer_vec_ty
=
llvm_vector_ty
(
bx
.cx
(),
underlying_ty
,
in_len
,
pointer_count
);
...
...
@@ -1509,7 +1509,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
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
,
bx
.cx
()
.
func
(
&
[
llvm_elem_vec_ty
,
llvm_pointer_vec_ty
,
alignment_ty
,
mask_ty
],
ret_t
));
...
...
@@ -1565,8 +1565,8 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
}
else
{
// unordered arithmetic reductions do not:
match
f
.bit_width
()
{
32
=>
bx
.cx
()
.c_undef
(
Type
::
f32
(
bx
.cx
()
)),
64
=>
bx
.cx
()
.c_undef
(
Type
::
f64
(
bx
.cx
()
)),
32
=>
bx
.cx
()
.c_undef
(
bx
.cx
()
.f32
(
)),
64
=>
bx
.cx
()
.c_undef
(
bx
.cx
()
.f64
(
)),
v
=>
{
return_error!
(
r#"
unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#
,
...
...
@@ -1643,8 +1643,8 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
}
// boolean reductions operate on vectors of i1s:
let
i1
=
Type
::
i1
(
bx
.cx
()
);
let
i1xn
=
Type
::
vector
(
i1
,
in_len
as
u64
);
let
i1
=
bx
.cx
()
.i1
(
);
let
i1xn
=
bx
.cx
()
.
vector
(
i1
,
in_len
as
u64
);
bx
.trunc
(
args
[
0
]
.immediate
(),
i1xn
)
};
return
match
in_elem
.sty
{
...
...
@@ -1654,7 +1654,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
if
!
$boolean
{
r
}
else
{
bx
.zext
(
r
,
Type
::
bool
(
bx
.cx
()
))
bx
.zext
(
r
,
bx
.cx
()
.bool
(
))
}
)
},
...
...
src/librustc_codegen_llvm/meth.rs
浏览文件 @
730b13ab
...
...
@@ -14,10 +14,9 @@
use
builder
::
Builder
;
use
consts
;
use
monomorphize
;
use
type_
::
Type
;
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
rustc
::
ty
::{
self
,
Ty
};
use
rustc
::
ty
::
layout
::
HasDataLayout
;
...
...
@@ -41,7 +40,10 @@ pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>,
// Load the data pointer from the object.
debug!
(
"get_fn({:?}, {:?})"
,
llvtable
,
self
);
let
llvtable
=
bx
.pointercast
(
llvtable
,
fn_ty
.ptr_to_llvm_type
(
bx
.cx
())
.ptr_to
());
let
llvtable
=
bx
.pointercast
(
llvtable
,
bx
.cx
()
.ptr_to
(
fn_ty
.ptr_to_llvm_type
(
bx
.cx
()))
);
let
ptr_align
=
bx
.tcx
()
.data_layout.pointer_align
;
let
ptr
=
bx
.load
(
bx
.inbounds_gep
(
llvtable
,
&
[
bx
.cx
()
.c_usize
(
self
.0
)]),
...
...
@@ -61,7 +63,7 @@ pub fn get_usize(
// Load the data pointer from the object.
debug!
(
"get_int({:?}, {:?})"
,
llvtable
,
self
);
let
llvtable
=
bx
.pointercast
(
llvtable
,
Type
::
isize
(
bx
.cx
())
.ptr_to
(
));
let
llvtable
=
bx
.pointercast
(
llvtable
,
bx
.cx
()
.ptr_to
(
bx
.cx
()
.isize
()
));
let
usize_align
=
bx
.tcx
()
.data_layout.pointer_align
;
let
ptr
=
bx
.load
(
bx
.inbounds_gep
(
llvtable
,
&
[
bx
.cx
()
.c_usize
(
self
.0
)]),
...
...
@@ -96,7 +98,7 @@ pub fn get_vtable(
}
// Not in the cache. Build it.
let
nullptr
=
cx
.c_null
(
Type
::
i8p
(
cx
));
let
nullptr
=
cx
.c_null
(
cx
.i8p
(
));
let
methods
=
tcx
.vtable_methods
(
trait_ref
.with_self_ty
(
tcx
,
ty
));
let
methods
=
methods
.iter
()
.cloned
()
.map
(|
opt_mth
|
{
...
...
src/librustc_codegen_llvm/mir/block.rs
浏览文件 @
730b13ab
...
...
@@ -26,7 +26,7 @@
use
type_
::
Type
;
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
syntax
::
symbol
::
Symbol
;
use
syntax_pos
::
Pos
;
...
...
@@ -268,7 +268,7 @@ fn codegen_terminator(&mut self,
}
};
bx
.load
(
bx
.pointercast
(
llslot
,
cast_ty
.llvm_type
(
bx
.cx
())
.ptr_to
(
)),
bx
.pointercast
(
llslot
,
bx
.cx
()
.ptr_to
(
cast_ty
.llvm_type
(
bx
.cx
())
)),
self
.fn_ty.ret.layout.align
)
}
};
...
...
@@ -560,7 +560,7 @@ fn codegen_terminator(&mut self,
let
dest
=
match
ret_dest
{
_
if
fn_ty
.ret
.is_indirect
()
=>
llargs
[
0
],
ReturnDest
::
Nothing
=>
{
bx
.cx
()
.c_undef
(
fn_ty
.ret
.memory_ty
(
bx
.cx
())
.ptr_to
(
))
bx
.cx
()
.c_undef
(
bx
.cx
()
.ptr_to
(
fn_ty
.ret
.memory_ty
(
bx
.cx
())
))
}
ReturnDest
::
IndirectOperand
(
dst
,
_
)
|
ReturnDest
::
Store
(
dst
)
=>
dst
.llval
,
...
...
@@ -801,7 +801,7 @@ fn codegen_argument(&mut self,
if
by_ref
&&
!
arg
.is_indirect
()
{
// Have to load the argument, maybe while casting it.
if
let
PassMode
::
Cast
(
ty
)
=
arg
.mode
{
llval
=
bx
.load
(
bx
.pointercast
(
llval
,
ty
.llvm_type
(
bx
.cx
())
.ptr_to
(
)),
llval
=
bx
.load
(
bx
.pointercast
(
llval
,
bx
.cx
()
.ptr_to
(
ty
.llvm_type
(
bx
.cx
())
)),
align
.min
(
arg
.layout.align
));
}
else
{
// We can't use `PlaceRef::load` here because the argument
...
...
@@ -902,7 +902,7 @@ fn landing_pad_uncached(&mut self, target_bb: &'ll BasicBlock) -> &'ll BasicBloc
fn
landing_pad_type
(
&
self
)
->
&
'll
Type
{
let
cx
=
self
.cx
;
Type
::
struct_
(
cx
,
&
[
Type
::
i8p
(
cx
),
Type
::
i32
(
cx
)],
false
)
cx
.struct_
(
&
[
cx
.i8p
(),
cx
.i32
(
)],
false
)
}
fn
unreachable_block
(
&
mut
self
)
->
&
'll
BasicBlock
{
...
...
@@ -1014,7 +1014,7 @@ fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>,
dst
:
PlaceRef
<
'tcx
,
&
'll
Value
>
)
{
let
src
=
self
.codegen_operand
(
bx
,
src
);
let
llty
=
src
.layout
.llvm_type
(
bx
.cx
());
let
cast_ptr
=
bx
.pointercast
(
dst
.llval
,
llty
.ptr_to
(
));
let
cast_ptr
=
bx
.pointercast
(
dst
.llval
,
bx
.cx
()
.ptr_to
(
llty
));
let
align
=
src
.layout.align
.min
(
dst
.layout.align
);
src
.val
.store
(
bx
,
PlaceRef
::
new_sized
(
cast_ptr
,
src
.layout
,
align
));
}
...
...
src/librustc_codegen_llvm/mir/constant.rs
浏览文件 @
730b13ab
...
...
@@ -25,7 +25,7 @@
use
syntax
::
ast
::
Mutability
;
use
syntax
::
source_map
::
Span
;
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
super
::
super
::
callee
;
use
super
::
FunctionCx
;
...
...
@@ -40,11 +40,11 @@ pub fn scalar_to_llvm(
match
cv
{
Scalar
::
Bits
{
size
:
0
,
..
}
=>
{
assert_eq!
(
0
,
layout
.value
.size
(
cx
)
.bytes
());
cx
.c_undef
(
Type
::
ix
(
cx
,
0
))
cx
.c_undef
(
cx
.ix
(
0
))
},
Scalar
::
Bits
{
bits
,
size
}
=>
{
assert_eq!
(
size
as
u64
,
layout
.value
.size
(
cx
)
.bytes
());
let
llval
=
cx
.c_uint_big
(
Type
::
ix
(
cx
,
bitsize
),
bits
);
let
llval
=
cx
.c_uint_big
(
cx
.ix
(
bitsize
),
bits
);
if
layout
.value
==
layout
::
Pointer
{
unsafe
{
llvm
::
LLVMConstIntToPtr
(
llval
,
llty
)
}
}
else
{
...
...
@@ -72,7 +72,7 @@ pub fn scalar_to_llvm(
None
=>
bug!
(
"missing allocation {:?}"
,
ptr
.alloc_id
),
};
let
llval
=
unsafe
{
llvm
::
LLVMConstInBoundsGEP
(
consts
::
bitcast
(
base_addr
,
Type
::
i8p
(
cx
)),
consts
::
bitcast
(
base_addr
,
cx
.i8p
(
)),
&
cx
.c_usize
(
ptr
.offset
.bytes
()),
1
,
)
};
...
...
@@ -109,7 +109,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
value
:
layout
::
Primitive
::
Pointer
,
valid_range
:
0
..=!
0
},
Type
::
i8p
(
cx
)
cx
.i8p
(
)
));
next_offset
=
offset
+
pointer_size
;
}
...
...
src/librustc_codegen_llvm/mir/mod.rs
浏览文件 @
730b13ab
...
...
@@ -23,7 +23,6 @@
use
debuginfo
::{
self
,
declare_local
,
VariableAccess
,
VariableKind
,
FunctionDebugContext
};
use
monomorphize
::
Instance
;
use
abi
::{
ArgTypeExt
,
FnType
,
FnTypeExt
,
PassMode
};
use
type_
::
Type
;
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
...
...
@@ -420,7 +419,7 @@ fn create_funclets(
// C++ personality function, but `catch (...)` has no type so
// it's null. The 64 here is actually a bitfield which
// represents that this is a catch-all block.
let
null
=
bx
.cx
()
.c_null
(
Type
::
i8p
(
bx
.cx
()
));
let
null
=
bx
.cx
()
.c_null
(
bx
.cx
()
.i8p
(
));
let
sixty_four
=
bx
.cx
()
.c_i32
(
64
);
cleanup
=
cp_bx
.catch_pad
(
cs
,
&
[
null
,
sixty_four
,
null
]);
cp_bx
.br
(
llbb
);
...
...
src/librustc_codegen_llvm/mir/operand.rs
浏览文件 @
730b13ab
...
...
@@ -18,10 +18,9 @@
use
builder
::{
Builder
,
MemFlags
};
use
value
::
Value
;
use
type_of
::
LayoutLlvmExt
;
use
type_
::
Type
;
use
glue
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
std
::
fmt
;
...
...
@@ -349,7 +348,7 @@ pub fn store_unsized(
// 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
lldst
=
bx
.array_alloca
(
Type
::
i8
(
bx
.cx
()
),
llsize
,
"unsized_tmp"
,
max_align
);
let
lldst
=
bx
.array_alloca
(
bx
.cx
()
.i8
(
),
llsize
,
"unsized_tmp"
,
max_align
);
base
::
call_memcpy
(
bx
,
lldst
,
max_align
,
llptr
,
min_align
,
llsize
,
flags
);
// Store the allocated region and the extra to the indirect place.
...
...
@@ -463,7 +462,7 @@ pub fn codegen_operand(&mut self,
// We've errored, so we don't have to produce working code.
let
layout
=
bx
.cx
()
.layout_of
(
ty
);
PlaceRef
::
new_sized
(
bx
.cx
()
.c_undef
(
layout
.llvm_type
(
bx
.cx
())
.ptr_to
(
)),
bx
.cx
()
.c_undef
(
bx
.cx
()
.ptr_to
(
layout
.llvm_type
(
bx
.cx
())
)),
layout
,
layout
.align
,
)
.load
(
bx
)
...
...
src/librustc_codegen_llvm/mir/place.rs
浏览文件 @
730b13ab
...
...
@@ -18,12 +18,11 @@
use
common
::{
CodegenCx
,
IntPredicate
};
use
consts
;
use
type_of
::
LayoutLlvmExt
;
use
type_
::
Type
;
use
value
::
Value
;
use
glue
;
use
mir
::
constant
::
const_alloc_to_llvm
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
TypeMethods
};
use
super
::{
FunctionCx
,
LocalRef
};
use
super
::
operand
::{
OperandRef
,
OperandValue
};
...
...
@@ -68,11 +67,11 @@ pub fn from_const_alloc(
let
base_addr
=
consts
::
addr_of
(
bx
.cx
(),
init
,
layout
.align
,
None
);
let
llval
=
unsafe
{
LLVMConstInBoundsGEP
(
consts
::
bitcast
(
base_addr
,
Type
::
i8p
(
bx
.cx
()
)),
consts
::
bitcast
(
base_addr
,
bx
.cx
()
.i8p
(
)),
&
bx
.cx
()
.c_usize
(
offset
.bytes
()),
1
,
)};
let
llval
=
consts
::
bitcast
(
llval
,
layout
.llvm_type
(
bx
.cx
())
.ptr_to
(
));
let
llval
=
consts
::
bitcast
(
llval
,
bx
.cx
()
.ptr_to
(
layout
.llvm_type
(
bx
.cx
())
));
PlaceRef
::
new_sized
(
llval
,
layout
,
alloc
.align
)
}
...
...
@@ -160,7 +159,7 @@ pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'tcx, &'ll Value>
let
load
=
bx
.load
(
llptr
,
self
.align
);
scalar_load_metadata
(
load
,
scalar
);
if
scalar
.is_bool
()
{
bx
.trunc
(
load
,
Type
::
i1
(
bx
.cx
()
))
bx
.trunc
(
load
,
bx
.cx
()
.i1
(
))
}
else
{
load
}
...
...
@@ -197,7 +196,7 @@ pub fn project_field(
};
PlaceRef
{
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
llval
:
bx
.pointercast
(
llval
,
field
.llvm_type
(
cx
)
.ptr_to
(
)),
llval
:
bx
.pointercast
(
llval
,
cx
.ptr_to
(
field
.llvm_type
(
cx
)
)),
llextra
:
if
cx
.type_has_metadata
(
field
.ty
)
{
self
.llextra
}
else
{
...
...
@@ -266,7 +265,7 @@ pub fn project_field(
debug!
(
"struct_field_ptr: DST field offset: {:?}"
,
offset
);
// Cast and adjust pointer
let
byte_ptr
=
bx
.pointercast
(
self
.llval
,
Type
::
i8p
(
cx
));
let
byte_ptr
=
bx
.pointercast
(
self
.llval
,
cx
.i8p
(
));
let
byte_ptr
=
bx
.gep
(
byte_ptr
,
&
[
offset
]);
// Finally, cast back to the type expected
...
...
@@ -274,7 +273,7 @@ pub fn project_field(
debug!
(
"struct_field_ptr: Field type is {:?}"
,
ll_fty
);
PlaceRef
{
llval
:
bx
.pointercast
(
byte_ptr
,
ll_fty
.ptr_to
(
)),
llval
:
bx
.pointercast
(
byte_ptr
,
bx
.cx
()
.ptr_to
(
ll_fty
)),
llextra
:
self
.llextra
,
layout
:
field
,
align
:
effective_field_align
,
...
...
@@ -380,7 +379,7 @@ pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: Vari
bx
.sess
()
.target.target.arch
==
"aarch64"
{
// Issue #34427: As workaround for LLVM bug on ARM,
// use memset of 0 before assigning niche value.
let
llptr
=
bx
.pointercast
(
self
.llval
,
Type
::
i8
(
bx
.cx
())
.ptr_to
(
));
let
llptr
=
bx
.pointercast
(
self
.llval
,
bx
.cx
()
.ptr_to
(
bx
.cx
()
.i8
()
));
let
fill_byte
=
bx
.cx
()
.c_u8
(
0
);
let
(
size
,
align
)
=
self
.layout
.size_and_align
();
let
size
=
bx
.cx
()
.c_usize
(
size
.bytes
());
...
...
@@ -423,7 +422,7 @@ pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: Varia
// Cast to the appropriate variant struct type.
let
variant_ty
=
downcast
.layout
.llvm_type
(
bx
.cx
());
downcast
.llval
=
bx
.pointercast
(
downcast
.llval
,
variant_ty
.ptr_to
(
));
downcast
.llval
=
bx
.pointercast
(
downcast
.llval
,
bx
.cx
()
.ptr_to
(
variant_ty
));
downcast
}
...
...
@@ -484,7 +483,7 @@ pub fn codegen_place(&mut self,
// so we generate an abort
let
fnname
=
bx
.cx
()
.get_intrinsic
(
&
(
"llvm.trap"
));
bx
.call
(
fnname
,
&
[],
None
);
let
llval
=
bx
.cx
()
.c_undef
(
layout
.llvm_type
(
bx
.cx
())
.ptr_to
(
));
let
llval
=
bx
.cx
()
.c_undef
(
bx
.cx
()
.ptr_to
(
layout
.llvm_type
(
bx
.cx
())
));
PlaceRef
::
new_sized
(
llval
,
layout
,
layout
.align
)
}
}
...
...
@@ -544,7 +543,7 @@ pub fn codegen_place(&mut self,
// Cast the place pointer type to the new
// array or slice type (*[%_; new_len]).
subslice
.llval
=
bx
.pointercast
(
subslice
.llval
,
subslice
.layout
.llvm_type
(
bx
.cx
())
.ptr_to
(
));
bx
.cx
()
.ptr_to
(
subslice
.layout
.llvm_type
(
bx
.cx
())
));
subslice
}
...
...
src/librustc_codegen_llvm/mir/rvalue.rs
浏览文件 @
730b13ab
...
...
@@ -26,7 +26,7 @@
use
type_of
::
LayoutLlvmExt
;
use
value
::
Value
;
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
CommonWriteMethods
};
use
interfaces
::{
BuilderMethods
,
CommonMethods
,
CommonWriteMethods
,
TypeMethods
};
use
super
::{
FunctionCx
,
LocalRef
};
use
super
::
operand
::{
OperandRef
,
OperandValue
};
...
...
@@ -117,7 +117,7 @@ pub fn codegen_rvalue(&mut self,
// Use llvm.memset.p0i8.* to initialize byte arrays
let
v
=
base
::
from_immediate
(
&
bx
,
v
);
if
bx
.cx
()
.val_ty
(
v
)
==
Type
::
i8
(
bx
.cx
()
)
{
if
bx
.cx
()
.val_ty
(
v
)
==
bx
.cx
()
.i8
(
)
{
base
::
call_memset
(
&
bx
,
start
,
v
,
size
,
align
,
false
);
return
bx
;
}
...
...
@@ -349,8 +349,8 @@ pub fn codegen_rvalue_operand(
bx
.intcast
(
llval
,
ll_t_out
,
signed
)
}
(
CastTy
::
Float
,
CastTy
::
Float
)
=>
{
let
srcsz
=
ll_t_in
.float_width
(
);
let
dstsz
=
ll_t_out
.float_width
(
);
let
srcsz
=
bx
.cx
()
.float_width
(
ll_t_in
);
let
dstsz
=
bx
.cx
()
.float_width
(
ll_t_out
);
if
dstsz
>
srcsz
{
bx
.fpext
(
llval
,
ll_t_out
)
}
else
if
srcsz
>
dstsz
{
...
...
@@ -828,7 +828,9 @@ fn cast_int_to_float(bx: &Builder<'_, 'll, '_>,
// Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
// It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
// LLVM's uitofp produces undef in those cases, so we manually check for that case.
let
is_u128_to_f32
=
!
signed
&&
int_ty
.int_width
()
==
128
&&
float_ty
.float_width
()
==
32
;
let
is_u128_to_f32
=
!
signed
&&
bx
.cx
()
.int_width
(
int_ty
)
==
128
&&
bx
.cx
()
.float_width
(
float_ty
)
==
32
;
if
is_u128_to_f32
{
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
// and for everything else LLVM's uitofp works just fine.
...
...
@@ -883,39 +885,48 @@ fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
// On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
// we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
// This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
fn
compute_clamp_bounds
<
F
:
Float
>
(
signed
:
bool
,
int_ty
:
&
Type
)
->
(
u128
,
u128
)
{
let
rounded_min
=
F
::
from_i128_r
(
int_min
(
signed
,
int_ty
),
Round
::
TowardZero
);
assert_eq!
(
rounded_min
.status
,
Status
::
OK
);
let
rounded_max
=
F
::
from_u128_r
(
int_max
(
signed
,
int_ty
),
Round
::
TowardZero
);
assert
!
(
rounded_max
.value
.is_finite
());
(
rounded_min
.value
.to_bits
(),
rounded_max
.value
.to_bits
())
}
fn
int_max
(
signed
:
bool
,
int_ty
:
&
Type
)
->
u128
{
let
shift_amount
=
128
-
int_ty
.int_width
();
let
int_max
=
|
signed
:
bool
,
int_ty
:
&
'll
Type
|
->
u128
{
let
shift_amount
=
128
-
bx
.cx
()
.int_width
(
int_ty
);
if
signed
{
i128
::
MAX
as
u128
>>
shift_amount
}
else
{
u128
::
MAX
>>
shift_amount
}
}
fn
int_min
(
signed
:
bool
,
int_ty
:
&
Type
)
->
i128
{
}
;
let
int_min
=
|
signed
:
bool
,
int_ty
:
&
'll
Type
|
->
i128
{
if
signed
{
i128
::
MIN
>>
(
128
-
int_ty
.int_width
(
))
i128
::
MIN
>>
(
128
-
bx
.cx
()
.int_width
(
int_ty
))
}
else
{
0
}
}
};
let
compute_clamp_bounds_single
=
|
signed
:
bool
,
int_ty
:
&
'll
Type
|
->
(
u128
,
u128
)
{
let
rounded_min
=
ieee
::
Single
::
from_i128_r
(
int_min
(
signed
,
int_ty
),
Round
::
TowardZero
);
assert_eq!
(
rounded_min
.status
,
Status
::
OK
);
let
rounded_max
=
ieee
::
Single
::
from_u128_r
(
int_max
(
signed
,
int_ty
),
Round
::
TowardZero
);
assert
!
(
rounded_max
.value
.is_finite
());
(
rounded_min
.value
.to_bits
(),
rounded_max
.value
.to_bits
())
};
let
compute_clamp_bounds_double
=
|
signed
:
bool
,
int_ty
:
&
'll
Type
|
->
(
u128
,
u128
)
{
let
rounded_min
=
ieee
::
Double
::
from_i128_r
(
int_min
(
signed
,
int_ty
),
Round
::
TowardZero
);
assert_eq!
(
rounded_min
.status
,
Status
::
OK
);
let
rounded_max
=
ieee
::
Double
::
from_u128_r
(
int_max
(
signed
,
int_ty
),
Round
::
TowardZero
);
assert
!
(
rounded_max
.value
.is_finite
());
(
rounded_min
.value
.to_bits
(),
rounded_max
.value
.to_bits
())
};
let
float_bits_to_llval
=
|
bits
|
{
let
bits_llval
=
match
float_ty
.float_width
(
)
{
let
bits_llval
=
match
bx
.cx
()
.float_width
(
float_ty
)
{
32
=>
bx
.cx
()
.c_u32
(
bits
as
u32
),
64
=>
bx
.cx
()
.c_u64
(
bits
as
u64
),
n
=>
bug!
(
"unsupported float width {}"
,
n
),
};
consts
::
bitcast
(
bits_llval
,
float_ty
)
};
let
(
f_min
,
f_max
)
=
match
float_ty
.float_width
(
)
{
32
=>
compute_clamp_bounds
::
<
ieee
::
Single
>
(
signed
,
int_ty
),
64
=>
compute_clamp_bounds
::
<
ieee
::
Double
>
(
signed
,
int_ty
),
let
(
f_min
,
f_max
)
=
match
bx
.cx
()
.float_width
(
float_ty
)
{
32
=>
compute_clamp_bounds
_single
(
signed
,
int_ty
),
64
=>
compute_clamp_bounds
_double
(
signed
,
int_ty
),
n
=>
bug!
(
"unsupported float width {}"
,
n
),
};
let
f_min
=
float_bits_to_llval
(
f_min
);
...
...
src/librustc_codegen_llvm/type_.rs
浏览文件 @
730b13ab
...
...
@@ -16,10 +16,12 @@
use
llvm
::{
Bool
,
False
,
True
,
TypeKind
};
use
context
::
CodegenCx
;
use
interfaces
::
TypeMethods
;
use
syntax
::
ast
;
use
rustc
::
ty
::
layout
::{
self
,
Align
,
Size
};
use
rustc_data_structures
::
small_c_str
::
SmallCStr
;
use
back
::
write
;
use
std
::
fmt
;
...
...
@@ -39,191 +41,85 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl
Type
{
pub
fn
void
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMVoidTypeInContext
(
cx
.llcx
)
}
}
impl
TypeMethods
for
CodegenCx
<
'll
,
'tcx
>
{
pub
fn
metadata
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
void
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVM
RustMetadataTypeInContext
(
cx
.llcx
)
llvm
::
LLVM
VoidTypeInContext
(
self
.llcx
)
}
}
pub
fn
i1
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
metadata
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVM
Int1TypeInContext
(
cx
.llcx
)
llvm
::
LLVM
RustMetadataTypeInContext
(
self
.llcx
)
}
}
pub
fn
i8
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
i1
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMInt
8TypeInContext
(
cx
.llcx
)
llvm
::
LLVMInt
1TypeInContext
(
self
.llcx
)
}
}
pub
fn
i8_llcx
(
llcx
:
&
llvm
::
Context
)
->
&
Type
{
fn
i8
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMInt8TypeInContext
(
llcx
)
llvm
::
LLVMInt8TypeInContext
(
self
.
llcx
)
}
}
pub
fn
i16
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
i16
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMInt16TypeInContext
(
cx
.llcx
)
llvm
::
LLVMInt16TypeInContext
(
self
.llcx
)
}
}
pub
fn
i32
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
i32
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMInt32TypeInContext
(
cx
.llcx
)
llvm
::
LLVMInt32TypeInContext
(
self
.llcx
)
}
}
pub
fn
i64
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
i64
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMInt64TypeInContext
(
cx
.llcx
)
llvm
::
LLVMInt64TypeInContext
(
self
.llcx
)
}
}
pub
fn
i128
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
i128
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMIntTypeInContext
(
cx
.llcx
,
128
)
llvm
::
LLVMIntTypeInContext
(
self
.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
{
fn
ix
(
&
self
,
num_bits
:
u64
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMIntTypeInContext
(
cx
.llcx
,
num_bits
as
c_uint
)
llvm
::
LLVMIntTypeInContext
(
self
.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
{
fn
f32
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVM
IntTypeInContext
(
llcx
,
num_bits
as
c_uint
)
llvm
::
LLVM
FloatTypeInContext
(
self
.llcx
)
}
}
pub
fn
f32
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
f64
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVM
FloatTypeInContext
(
cx
.llcx
)
llvm
::
LLVM
DoubleTypeInContext
(
self
.llcx
)
}
}
pub
fn
f64
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
fn
x86_mmx
(
&
self
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMDoubleTypeInContext
(
cx
.llcx
)
}
}
pub
fn
bool
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
Type
::
i8
(
cx
)
}
pub
fn
char
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
Type
::
i32
(
cx
)
}
pub
fn
i8p
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
Type
::
i8
(
cx
)
.ptr_to
()
}
pub
fn
i8p_llcx
(
llcx
:
&
llvm
::
Context
)
->
&
Type
{
Type
::
i8_llcx
(
llcx
)
.ptr_to
()
}
pub
fn
isize
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
cx
.isize_ty
}
pub
fn
c_int
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
match
&
cx
.tcx.sess.target.target.target_c_int_width
[
..
]
{
"16"
=>
Type
::
i16
(
cx
),
"32"
=>
Type
::
i32
(
cx
),
"64"
=>
Type
::
i64
(
cx
),
width
=>
bug!
(
"Unsupported target_c_int_width: {}"
,
width
),
}
}
pub
fn
int_from_ty
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
t
:
ast
::
IntTy
)
->
&
'll
Type
{
match
t
{
ast
::
IntTy
::
Isize
=>
cx
.isize_ty
,
ast
::
IntTy
::
I8
=>
Type
::
i8
(
cx
),
ast
::
IntTy
::
I16
=>
Type
::
i16
(
cx
),
ast
::
IntTy
::
I32
=>
Type
::
i32
(
cx
),
ast
::
IntTy
::
I64
=>
Type
::
i64
(
cx
),
ast
::
IntTy
::
I128
=>
Type
::
i128
(
cx
),
}
}
pub
fn
uint_from_ty
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
t
:
ast
::
UintTy
)
->
&
'll
Type
{
match
t
{
ast
::
UintTy
::
Usize
=>
cx
.isize_ty
,
ast
::
UintTy
::
U8
=>
Type
::
i8
(
cx
),
ast
::
UintTy
::
U16
=>
Type
::
i16
(
cx
),
ast
::
UintTy
::
U32
=>
Type
::
i32
(
cx
),
ast
::
UintTy
::
U64
=>
Type
::
i64
(
cx
),
ast
::
UintTy
::
U128
=>
Type
::
i128
(
cx
),
}
}
pub
fn
float_from_ty
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
t
:
ast
::
FloatTy
)
->
&
'll
Type
{
match
t
{
ast
::
FloatTy
::
F32
=>
Type
::
f32
(
cx
),
ast
::
FloatTy
::
F64
=>
Type
::
f64
(
cx
),
llvm
::
LLVMX86MMXTypeInContext
(
self
.llcx
)
}
}
pub
fn
func
(
fn
func
(
&
self
,
args
:
&
[
&
'll
Type
],
ret
:
&
'll
Type
)
->
&
'll
Type
{
...
...
@@ -233,7 +129,8 @@ pub fn func(
}
}
pub
fn
variadic_func
(
fn
variadic_func
(
&
self
,
args
:
&
[
&
'll
Type
],
ret
:
&
'll
Type
)
->
&
'll
Type
{
...
...
@@ -243,84 +140,84 @@ pub fn variadic_func(
}
}
pub
fn
struct_
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
fn
struct_
(
&
self
,
els
:
&
[
&
'll
Type
],
packed
:
bool
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMStructTypeInContext
(
cx
.llcx
,
els
.as_ptr
(),
llvm
::
LLVMStructTypeInContext
(
self
.llcx
,
els
.as_ptr
(),
els
.len
()
as
c_uint
,
packed
as
Bool
)
}
}
pub
fn
named_struct
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
name
:
&
str
)
->
&
'll
Type
{
fn
named_struct
(
&
self
,
name
:
&
str
)
->
&
'll
Type
{
let
name
=
SmallCStr
::
new
(
name
);
unsafe
{
llvm
::
LLVMStructCreateNamed
(
cx
.llcx
,
name
.as_ptr
())
llvm
::
LLVMStructCreateNamed
(
self
.llcx
,
name
.as_ptr
())
}
}
pub
fn
array
(
ty
:
&
Type
,
len
:
u64
)
->
&
Type
{
fn
array
(
&
self
,
ty
:
&
'll
Type
,
len
:
u64
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMRustArrayType
(
ty
,
len
)
}
}
pub
fn
vector
(
ty
:
&
Type
,
len
:
u64
)
->
&
Type
{
fn
vector
(
&
self
,
ty
:
&
'll
Type
,
len
:
u64
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMVectorType
(
ty
,
len
as
c_uint
)
}
}
pub
fn
kind
(
&
self
)
->
TypeKind
{
fn
kind
(
&
self
,
ty
:
&
'll
Type
)
->
TypeKind
{
unsafe
{
llvm
::
LLVMRustGetTypeKind
(
self
)
llvm
::
LLVMRustGetTypeKind
(
ty
)
}
}
pub
fn
set_struct_body
(
&
'll
self
,
els
:
&
[
&
'll
Type
],
packed
:
bool
)
{
fn
set_struct_body
(
&
self
,
ty
:
&
'll
Type
,
els
:
&
[
&
'll
Type
],
packed
:
bool
)
{
unsafe
{
llvm
::
LLVMStructSetBody
(
self
,
els
.as_ptr
(),
llvm
::
LLVMStructSetBody
(
ty
,
els
.as_ptr
(),
els
.len
()
as
c_uint
,
packed
as
Bool
)
}
}
pub
fn
ptr_to
(
&
self
)
->
&
Type
{
assert_ne!
(
self
.kind
(),
TypeKind
::
Function
,
fn
ptr_to
(
&
self
,
ty
:
&
'll
Type
)
->
&
'll
Type
{
assert_ne!
(
self
.kind
(
ty
),
TypeKind
::
Function
,
"don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead"
);
unsafe
{
llvm
::
LLVMPointerType
(
self
,
0
)
llvm
::
LLVMPointerType
(
ty
,
0
)
}
}
pub
fn
element_type
(
&
self
)
->
&
Type
{
fn
element_type
(
&
self
,
ty
:
&
'll
Type
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMGetElementType
(
self
)
llvm
::
LLVMGetElementType
(
ty
)
}
}
/// Return the number of elements in `self` if it is a LLVM vector type.
pub
fn
vector_length
(
&
self
)
->
usize
{
fn
vector_length
(
&
self
,
ty
:
&
'll
Type
)
->
usize
{
unsafe
{
llvm
::
LLVMGetVectorSize
(
self
)
as
usize
llvm
::
LLVMGetVectorSize
(
ty
)
as
usize
}
}
pub
fn
func_params
(
&
self
)
->
Vec
<&
Type
>
{
fn
func_params
(
&
self
,
ty
:
&
'll
Type
)
->
Vec
<&
'll
Type
>
{
unsafe
{
let
n_args
=
llvm
::
LLVMCountParamTypes
(
self
)
as
usize
;
let
n_args
=
llvm
::
LLVMCountParamTypes
(
ty
)
as
usize
;
let
mut
args
=
Vec
::
with_capacity
(
n_args
);
llvm
::
LLVMGetParamTypes
(
self
,
args
.as_mut_ptr
());
llvm
::
LLVMGetParamTypes
(
ty
,
args
.as_mut_ptr
());
args
.set_len
(
n_args
);
args
}
}
pub
fn
float_width
(
&
self
)
->
usize
{
match
self
.kind
()
{
fn
float_width
(
&
self
,
ty
:
&
'll
Type
)
->
usize
{
match
self
.kind
(
ty
)
{
TypeKind
::
Float
=>
32
,
TypeKind
::
Double
=>
64
,
TypeKind
::
X86_FP80
=>
80
,
...
...
@@ -330,44 +227,121 @@ pub fn float_width(&self) -> usize {
}
/// Retrieve the bit width of the integer type `self`.
pub
fn
int_width
(
&
self
)
->
u64
{
fn
int_width
(
&
self
,
ty
:
&
'll
Type
)
->
u64
{
unsafe
{
llvm
::
LLVMGetIntTypeWidth
(
ty
)
as
u64
}
}
}
impl
Type
{
pub
fn
i8_llcx
(
llcx
:
&
llvm
::
Context
)
->
&
Type
{
unsafe
{
llvm
::
LLVMInt8TypeInContext
(
llcx
)
}
}
// Creates an integer type with the given number of bits, e.g. i24
pub
fn
ix_llcx
(
llcx
:
&
llvm
::
Context
,
num_bits
:
u64
)
->
&
Type
{
unsafe
{
llvm
::
LLVMGetIntTypeWidth
(
self
)
as
u64
llvm
::
LLVMIntTypeInContext
(
llcx
,
num_bits
as
c_uint
)
}
}
pub
fn
i8p_llcx
(
cx
:
&
write
::
CodegenContext
<
'll
>
,
llcx
:
&
'll
llvm
::
Context
)
->
&
'll
Type
{
cx
.ptr_to
(
Type
::
i8_llcx
(
llcx
))
}
}
impl
CodegenCx
<
'll
,
'tcx
>
{
pub
fn
bool
(
&
self
)
->
&
'll
Type
{
self
.i8
()
}
pub
fn
i8p
(
&
self
)
->
&
'll
Type
{
self
.ptr_to
(
self
.i8
())
}
pub
fn
isize
(
&
self
)
->
&
'll
Type
{
self
.isize_ty
}
pub
fn
t_int
(
&
self
)
->
&
'll
Type
{
match
&
self
.sess
()
.target.target.target_c_int_width
[
..
]
{
"16"
=>
self
.i16
(),
"32"
=>
self
.i32
(),
"64"
=>
self
.i64
(),
width
=>
bug!
(
"Unsupported target_c_int_width: {}"
,
width
),
}
}
pub
fn
int_from_ty
(
&
self
,
t
:
ast
::
IntTy
)
->
&
'll
Type
{
match
t
{
ast
::
IntTy
::
Isize
=>
self
.isize_ty
,
ast
::
IntTy
::
I8
=>
self
.i8
(),
ast
::
IntTy
::
I16
=>
self
.i16
(),
ast
::
IntTy
::
I32
=>
self
.i32
(),
ast
::
IntTy
::
I64
=>
self
.i64
(),
ast
::
IntTy
::
I128
=>
self
.i128
(),
}
}
pub
fn
uint_from_ty
(
&
self
,
t
:
ast
::
UintTy
)
->
&
'll
Type
{
match
t
{
ast
::
UintTy
::
Usize
=>
self
.isize_ty
,
ast
::
UintTy
::
U8
=>
self
.i8
(),
ast
::
UintTy
::
U16
=>
self
.i16
(),
ast
::
UintTy
::
U32
=>
self
.i32
(),
ast
::
UintTy
::
U64
=>
self
.i64
(),
ast
::
UintTy
::
U128
=>
self
.i128
(),
}
}
pub
fn
from_integer
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
i
:
layout
::
Integer
)
->
&
'll
Type
{
pub
fn
float_from_ty
(
&
self
,
t
:
ast
::
FloatTy
)
->
&
'll
Type
{
match
t
{
ast
::
FloatTy
::
F32
=>
self
.f32
(),
ast
::
FloatTy
::
F64
=>
self
.f64
(),
}
}
pub
fn
from_integer
(
&
self
,
i
:
layout
::
Integer
)
->
&
'll
Type
{
use
rustc
::
ty
::
layout
::
Integer
::
*
;
match
i
{
I8
=>
Type
::
i8
(
cx
),
I16
=>
Type
::
i16
(
cx
),
I32
=>
Type
::
i32
(
cx
),
I64
=>
Type
::
i64
(
cx
),
I128
=>
Type
::
i128
(
cx
),
I8
=>
self
.i8
(
),
I16
=>
self
.i16
(
),
I32
=>
self
.i32
(
),
I64
=>
self
.i64
(
),
I128
=>
self
.i128
(
),
}
}
/// Return a LLVM type that has at most the required alignment,
/// as a conservative approximation for unknown pointee types.
pub
fn
pointee_for_abi_align
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
align
:
Align
)
->
&
'll
Type
{
pub
fn
pointee_for_abi_align
(
&
self
,
align
:
Align
)
->
&
'll
Type
{
// FIXME(eddyb) We could find a better approximation if ity.align < align.
let
ity
=
layout
::
Integer
::
approximate_abi_align
(
cx
,
align
);
Type
::
from_integer
(
cx
,
ity
)
let
ity
=
layout
::
Integer
::
approximate_abi_align
(
self
,
align
);
self
.from_integer
(
ity
)
}
/// Return a LLVM type that has at most the required alignment,
/// and exactly the required size, as a best-effort padding array.
pub
fn
padding_filler
(
cx
:
&
CodegenCx
<
'll
,
'_
>
,
size
:
Size
,
align
:
Align
)
->
&
'll
Type
{
let
unit
=
layout
::
Integer
::
approximate_abi_align
(
cx
,
align
);
pub
fn
padding_filler
(
&
self
,
size
:
Size
,
align
:
Align
)
->
&
'll
Type
{
let
unit
=
layout
::
Integer
::
approximate_abi_align
(
self
,
align
);
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
)
}
pub
fn
x86_mmx
(
cx
:
&
CodegenCx
<
'll
,
'_
>
)
->
&
'll
Type
{
unsafe
{
llvm
::
LLVMX86MMXTypeInContext
(
cx
.llcx
)
}
self
.array
(
self
.from_integer
(
unit
),
size
/
unit_size
)
}
}
src/librustc_codegen_llvm/type_of.rs
浏览文件 @
730b13ab
...
...
@@ -16,6 +16,7 @@
use
rustc_target
::
abi
::
FloatTy
;
use
rustc_mir
::
monomorphize
::
item
::
DefPathBasedNames
;
use
type_
::
Type
;
use
interfaces
::
TypeMethods
;
use
std
::
fmt
::
Write
;
...
...
@@ -37,14 +38,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
(
cx
.sess
()
.target.target.arch
==
"x86"
||
cx
.sess
()
.target.target.arch
==
"x86_64"
);
if
use_x86_mmx
{
return
Type
::
x86_mmx
(
cx
)
return
cx
.x86_mmx
(
)
}
else
{
let
element
=
layout
.scalar_llvm_type_at
(
cx
,
element
,
Size
::
ZERO
);
return
Type
::
vector
(
element
,
count
);
return
cx
.
vector
(
element
,
count
);
}
}
layout
::
Abi
::
ScalarPair
(
..
)
=>
{
return
Type
::
struct_
(
cx
,
&
[
return
cx
.struct_
(
&
[
layout
.scalar_pair_element_llvm_type
(
cx
,
0
,
false
),
layout
.scalar_pair_element_llvm_type
(
cx
,
1
,
false
),
],
false
);
...
...
@@ -79,30 +80,30 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
match
layout
.fields
{
layout
::
FieldPlacement
::
Union
(
_
)
=>
{
let
fill
=
Type
::
padding_filler
(
cx
,
layout
.size
,
layout
.align
);
let
fill
=
cx
.padding_filler
(
layout
.size
,
layout
.align
);
let
packed
=
false
;
match
name
{
None
=>
{
Type
::
struct_
(
cx
,
&
[
fill
],
packed
)
cx
.struct_
(
&
[
fill
],
packed
)
}
Some
(
ref
name
)
=>
{
let
llty
=
Type
::
named_struct
(
cx
,
name
);
llty
.set_struct_body
(
&
[
fill
],
packed
);
let
llty
=
cx
.named_struct
(
name
);
cx
.set_struct_body
(
llty
,
&
[
fill
],
packed
);
llty
}
}
}
layout
::
FieldPlacement
::
Array
{
count
,
..
}
=>
{
Type
::
array
(
layout
.field
(
cx
,
0
)
.llvm_type
(
cx
),
count
)
cx
.
array
(
layout
.field
(
cx
,
0
)
.llvm_type
(
cx
),
count
)
}
layout
::
FieldPlacement
::
Arbitrary
{
..
}
=>
{
match
name
{
None
=>
{
let
(
llfields
,
packed
)
=
struct_llfields
(
cx
,
layout
);
Type
::
struct_
(
cx
,
&
llfields
,
packed
)
cx
.struct_
(
&
llfields
,
packed
)
}
Some
(
ref
name
)
=>
{
let
llty
=
Type
::
named_struct
(
cx
,
name
);
let
llty
=
cx
.named_struct
(
name
);
*
defer
=
Some
((
llty
,
layout
));
llty
}
...
...
@@ -136,7 +137,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
let
padding
=
target_offset
-
offset
;
let
padding_align
=
prev_effective_align
.min
(
effective_field_align
);
assert_eq!
(
offset
.abi_align
(
padding_align
)
+
padding
,
target_offset
);
result
.push
(
Type
::
padding_filler
(
cx
,
padding
,
padding_align
));
result
.push
(
cx
.padding_filler
(
padding
,
padding_align
));
debug!
(
" padding before: {:?}"
,
padding
);
result
.push
(
field
.llvm_type
(
cx
));
...
...
@@ -153,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
assert_eq!
(
offset
.abi_align
(
padding_align
)
+
padding
,
layout
.size
);
debug!
(
"struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}"
,
padding
,
offset
,
layout
.size
);
result
.push
(
Type
::
padding_filler
(
cx
,
padding
,
padding_align
));
result
.push
(
cx
.padding_filler
(
padding
,
padding_align
));
assert_eq!
(
result
.len
(),
1
+
field_count
*
2
);
}
else
{
debug!
(
"struct_llfields: offset: {:?} stride: {:?}"
,
...
...
@@ -255,10 +256,10 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
let
llty
=
match
self
.ty.sty
{
ty
::
Ref
(
_
,
ty
,
_
)
|
ty
::
RawPtr
(
ty
::
TypeAndMut
{
ty
,
..
})
=>
{
cx
.
layout_of
(
ty
)
.llvm_type
(
cx
)
.ptr_to
(
)
cx
.
ptr_to
(
cx
.layout_of
(
ty
)
.llvm_type
(
cx
)
)
}
ty
::
Adt
(
def
,
_
)
if
def
.is_box
()
=>
{
cx
.
layout_of
(
self
.ty
.boxed_ty
())
.llvm_type
(
cx
)
.ptr_to
(
)
cx
.
ptr_to
(
cx
.layout_of
(
self
.ty
.boxed_ty
())
.llvm_type
(
cx
)
)
}
ty
::
FnPtr
(
sig
)
=>
{
let
sig
=
cx
.tcx
.normalize_erasing_late_bound_regions
(
...
...
@@ -307,7 +308,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
if
let
Some
((
llty
,
layout
))
=
defer
{
let
(
llfields
,
packed
)
=
struct_llfields
(
cx
,
layout
);
llty
.set_struct_body
(
&
llfields
,
packed
)
cx
.set_struct_body
(
llty
,
&
llfields
,
packed
)
}
llty
...
...
@@ -316,7 +317,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
fn
immediate_llvm_type
<
'a
>
(
&
self
,
cx
:
&
CodegenCx
<
'a
,
'tcx
>
)
->
&
'a
Type
{
if
let
layout
::
Abi
::
Scalar
(
ref
scalar
)
=
self
.abi
{
if
scalar
.is_bool
()
{
return
Type
::
i1
(
cx
);
return
cx
.i1
(
);
}
}
self
.llvm_type
(
cx
)
...
...
@@ -325,17 +326,17 @@ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
fn
scalar_llvm_type_at
<
'a
>
(
&
self
,
cx
:
&
CodegenCx
<
'a
,
'tcx
>
,
scalar
:
&
layout
::
Scalar
,
offset
:
Size
)
->
&
'a
Type
{
match
scalar
.value
{
layout
::
Int
(
i
,
_
)
=>
Type
::
from_integer
(
cx
,
i
),
layout
::
Float
(
FloatTy
::
F32
)
=>
Type
::
f32
(
cx
),
layout
::
Float
(
FloatTy
::
F64
)
=>
Type
::
f64
(
cx
),
layout
::
Int
(
i
,
_
)
=>
cx
.from_integer
(
i
),
layout
::
Float
(
FloatTy
::
F32
)
=>
cx
.f32
(
),
layout
::
Float
(
FloatTy
::
F64
)
=>
cx
.f64
(
),
layout
::
Pointer
=>
{
// If we know the alignment, pick something better than i8.
let
pointee
=
if
let
Some
(
pointee
)
=
self
.pointee_info_at
(
cx
,
offset
)
{
Type
::
pointee_for_abi_align
(
cx
,
pointee
.align
)
cx
.pointee_for_abi_align
(
pointee
.align
)
}
else
{
Type
::
i8
(
cx
)
cx
.i8
(
)
};
pointee
.ptr_to
(
)
cx
.ptr_to
(
pointee
)
}
}
}
...
...
@@ -369,7 +370,7 @@ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
// when immediate. We need to load/store `bool` as `i8` to avoid
// crippling LLVM optimizations or triggering other LLVM bugs with `i1`.
if
immediate
&&
scalar
.is_bool
()
{
return
Type
::
i1
(
cx
);
return
cx
.i1
(
);
}
let
offset
=
if
index
==
0
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录