Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
caea0449
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
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,发现更多精彩内容 >>
提交
caea0449
编写于
3月 04, 2015
作者:
S
Simonas Kazlauskas
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move a big attribute fn into trans::attributes
上级
deb097a1
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
199 addition
and
195 deletion
+199
-195
src/librustc_trans/trans/attributes.rs
src/librustc_trans/trans/attributes.rs
+184
-9
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/base.rs
+8
-178
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/closure.rs
+1
-1
src/librustc_trans/trans/foreign.rs
src/librustc_trans/trans/foreign.rs
+3
-4
src/librustc_trans/trans/monomorphize.rs
src/librustc_trans/trans/monomorphize.rs
+3
-3
未找到文件。
src/librustc_trans/trans/attributes.rs
浏览文件 @
caea0449
...
...
@@ -9,13 +9,17 @@
// except according to those terms.
//! Set and unset common attributes on LLVM values.
use
libc
::{
c_uint
,
c_ulonglong
};
use
llvm
::{
self
,
ValueRef
,
AttrHelper
};
use
middle
::
ty
::{
self
,
ClosureTyper
};
use
syntax
::
abi
;
use
syntax
::
ast
;
use
syntax
::
attr
::
InlineAttr
;
pub
use
syntax
::
attr
::
InlineAttr
::
*
;
pub
use
syntax
::
attr
::
InlineAttr
;
use
trans
::
base
;
use
trans
::
common
;
use
trans
::
context
::
CrateContext
;
use
libc
::{
c_uint
,
c_ulonglong
}
;
use
trans
::
machine
;
use
trans
::
type_of
;
/// Mark LLVM function to use split stack.
#[inline]
...
...
@@ -33,11 +37,12 @@ pub fn split_stack(val: ValueRef, set: bool) {
/// Mark LLVM function to use provided inline heuristic.
#[inline]
pub
fn
inline
(
val
:
ValueRef
,
inline
:
InlineAttr
)
{
use
self
::
InlineAttr
::
*
;
match
inline
{
Inline
Hint
=>
llvm
::
SetFunctionAttribute
(
val
,
llvm
::
InlineHintAttribute
),
Inline
Always
=>
llvm
::
SetFunctionAttribute
(
val
,
llvm
::
AlwaysInlineAttribute
),
Inline
Never
=>
llvm
::
SetFunctionAttribute
(
val
,
llvm
::
NoInlineAttribute
),
Inline
None
=>
{
Hint
=>
llvm
::
SetFunctionAttribute
(
val
,
llvm
::
InlineHintAttribute
),
Always
=>
llvm
::
SetFunctionAttribute
(
val
,
llvm
::
AlwaysInlineAttribute
),
Never
=>
llvm
::
SetFunctionAttribute
(
val
,
llvm
::
NoInlineAttribute
),
None
=>
{
let
attr
=
llvm
::
InlineHintAttribute
|
llvm
::
AlwaysInlineAttribute
|
llvm
::
NoInlineAttribute
;
...
...
@@ -88,7 +93,7 @@ pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
/// attributes.
pub
fn
convert_fn_attrs_to_llvm
(
ccx
:
&
CrateContext
,
attrs
:
&
[
ast
::
Attribute
],
llfn
:
ValueRef
)
{
pub
fn
from_fn_attrs
(
ccx
:
&
CrateContext
,
attrs
:
&
[
ast
::
Attribute
],
llfn
:
ValueRef
)
{
use
syntax
::
attr
::
*
;
inline
(
llfn
,
find_inline_attr
(
Some
(
ccx
.sess
()
.diagnostic
()),
attrs
));
...
...
@@ -106,3 +111,173 @@ pub fn convert_fn_attrs_to_llvm(ccx: &CrateContext, attrs: &[ast::Attribute], ll
}
}
}
/// Composite function which converts function type into LLVM attributes for the function.
pub
fn
from_fn_type
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
fn_type
:
ty
::
Ty
<
'tcx
>
)
->
llvm
::
AttrBuilder
{
use
middle
::
ty
::{
BrAnon
,
ReLateBound
};
let
function_type
;
let
(
fn_sig
,
abi
,
env_ty
)
=
match
fn_type
.sty
{
ty
::
ty_bare_fn
(
_
,
ref
f
)
=>
(
&
f
.sig
,
f
.abi
,
None
),
ty
::
ty_closure
(
closure_did
,
substs
)
=>
{
let
typer
=
common
::
NormalizingClosureTyper
::
new
(
ccx
.tcx
());
function_type
=
typer
.closure_type
(
closure_did
,
substs
);
let
self_type
=
base
::
self_type_for_closure
(
ccx
,
closure_did
,
fn_type
);
(
&
function_type
.sig
,
abi
::
RustCall
,
Some
(
self_type
))
}
_
=>
ccx
.sess
()
.bug
(
"expected closure or function."
)
};
let
fn_sig
=
ty
::
erase_late_bound_regions
(
ccx
.tcx
(),
fn_sig
);
let
mut
attrs
=
llvm
::
AttrBuilder
::
new
();
let
ret_ty
=
fn_sig
.output
;
// These have an odd calling convention, so we need to manually
// unpack the input ty's
let
input_tys
=
match
fn_type
.sty
{
ty
::
ty_closure
(
..
)
=>
{
assert
!
(
abi
==
abi
::
RustCall
);
match
fn_sig
.inputs
[
0
]
.sty
{
ty
::
ty_tup
(
ref
inputs
)
=>
{
let
mut
full_inputs
=
vec!
[
env_ty
.expect
(
"Missing closure environment"
)];
full_inputs
.push_all
(
inputs
);
full_inputs
}
_
=>
ccx
.sess
()
.bug
(
"expected tuple'd inputs"
)
}
},
ty
::
ty_bare_fn
(
..
)
if
abi
==
abi
::
RustCall
=>
{
let
mut
inputs
=
vec!
[
fn_sig
.inputs
[
0
]];
match
fn_sig
.inputs
[
1
]
.sty
{
ty
::
ty_tup
(
ref
t_in
)
=>
{
inputs
.push_all
(
&
t_in
[
..
]);
inputs
}
_
=>
ccx
.sess
()
.bug
(
"expected tuple'd inputs"
)
}
}
_
=>
fn_sig
.inputs
.clone
()
};
// Index 0 is the return value of the llvm func, so we start at 1
let
mut
first_arg_offset
=
1
;
if
let
ty
::
FnConverging
(
ret_ty
)
=
ret_ty
{
// A function pointer is called without the declaration
// available, so we have to apply any attributes with ABI
// implications directly to the call instruction. Right now,
// the only attribute we need to worry about is `sret`.
if
type_of
::
return_uses_outptr
(
ccx
,
ret_ty
)
{
let
llret_sz
=
machine
::
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
ret_ty
));
// The outptr can be noalias and nocapture because it's entirely
// invisible to the program. We also know it's nonnull as well
// as how many bytes we can dereference
attrs
.arg
(
1
,
llvm
::
StructRetAttribute
)
.arg
(
1
,
llvm
::
NoAliasAttribute
)
.arg
(
1
,
llvm
::
NoCaptureAttribute
)
.arg
(
1
,
llvm
::
DereferenceableAttribute
(
llret_sz
));
// Add one more since there's an outptr
first_arg_offset
+=
1
;
}
else
{
// The `noalias` attribute on the return value is useful to a
// function ptr caller.
match
ret_ty
.sty
{
// `~` pointer return values never alias because ownership
// is transferred
ty
::
ty_uniq
(
it
)
if
!
common
::
type_is_sized
(
ccx
.tcx
(),
it
)
=>
{}
ty
::
ty_uniq
(
_
)
=>
{
attrs
.ret
(
llvm
::
NoAliasAttribute
);
}
_
=>
{}
}
// We can also mark the return value as `dereferenceable` in certain cases
match
ret_ty
.sty
{
// These are not really pointers but pairs, (pointer, len)
ty
::
ty_uniq
(
it
)
|
ty
::
ty_rptr
(
_
,
ty
::
mt
{
ty
:
it
,
..
})
if
!
common
::
type_is_sized
(
ccx
.tcx
(),
it
)
=>
{}
ty
::
ty_uniq
(
inner
)
|
ty
::
ty_rptr
(
_
,
ty
::
mt
{
ty
:
inner
,
..
})
=>
{
let
llret_sz
=
machine
::
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
inner
));
attrs
.ret
(
llvm
::
DereferenceableAttribute
(
llret_sz
));
}
_
=>
{}
}
if
let
ty
::
ty_bool
=
ret_ty
.sty
{
attrs
.ret
(
llvm
::
ZExtAttribute
);
}
}
}
for
(
idx
,
&
t
)
in
input_tys
.iter
()
.enumerate
()
.map
(|(
i
,
v
)|
(
i
+
first_arg_offset
,
v
))
{
match
t
.sty
{
// this needs to be first to prevent fat pointers from falling through
_
if
!
common
::
type_is_immediate
(
ccx
,
t
)
=>
{
let
llarg_sz
=
machine
::
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
t
));
// For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also
// program-invisible so can't possibly capture
attrs
.arg
(
idx
,
llvm
::
NoAliasAttribute
)
.arg
(
idx
,
llvm
::
NoCaptureAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llarg_sz
));
}
ty
::
ty_bool
=>
{
attrs
.arg
(
idx
,
llvm
::
ZExtAttribute
);
}
// `~` pointer parameters never alias because ownership is transferred
ty
::
ty_uniq
(
inner
)
=>
{
let
llsz
=
machine
::
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
inner
));
attrs
.arg
(
idx
,
llvm
::
NoAliasAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
}
// `&mut` pointer parameters never alias other parameters, or mutable global data
//
// `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
// `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on
// memory dependencies rather than pointer equality
ty
::
ty_rptr
(
b
,
mt
)
if
mt
.mutbl
==
ast
::
MutMutable
||
!
ty
::
type_contents
(
ccx
.tcx
(),
mt
.ty
)
.interior_unsafe
()
=>
{
let
llsz
=
machine
::
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
mt
.ty
));
attrs
.arg
(
idx
,
llvm
::
NoAliasAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
if
mt
.mutbl
==
ast
::
MutImmutable
{
attrs
.arg
(
idx
,
llvm
::
ReadOnlyAttribute
);
}
if
let
ReLateBound
(
_
,
BrAnon
(
_
))
=
*
b
{
attrs
.arg
(
idx
,
llvm
::
NoCaptureAttribute
);
}
}
// When a reference in an argument has no named lifetime, it's impossible for that
// reference to escape this function (returned or stored beyond the call by a closure).
ty
::
ty_rptr
(
&
ReLateBound
(
_
,
BrAnon
(
_
)),
mt
)
=>
{
let
llsz
=
machine
::
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
mt
.ty
));
attrs
.arg
(
idx
,
llvm
::
NoCaptureAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
}
// & pointer parameters are also never null and we know exactly how
// many bytes we can dereference
ty
::
ty_rptr
(
_
,
mt
)
=>
{
let
llsz
=
machine
::
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
mt
.ty
));
attrs
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
}
_
=>
()
}
}
attrs
}
src/librustc_trans/trans/base.rs
浏览文件 @
caea0449
...
...
@@ -227,7 +227,7 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
let
f
=
decl_rust_fn
(
ccx
,
fn_ty
,
name
);
let
attrs
=
csearch
::
get_item_attrs
(
&
ccx
.sess
()
.cstore
,
did
);
attributes
::
convert_fn_attrs_to_llvm
(
ccx
,
&
attrs
[
..
],
f
);
attributes
::
from_fn_attrs
(
ccx
,
&
attrs
[
..
],
f
);
ccx
.externs
()
.borrow_mut
()
.insert
(
name
.to_string
(),
f
);
f
...
...
@@ -770,7 +770,7 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
_
=>
{
let
llfn
=
foreign
::
register_foreign_item_fn
(
ccx
,
fn_ty
.abi
,
t
,
&
name
[
..
]);
let
attrs
=
csearch
::
get_item_attrs
(
&
ccx
.sess
()
.cstore
,
did
);
attributes
::
convert_fn_attrs_to_llvm
(
ccx
,
&
attrs
,
llfn
);
attributes
::
from_fn_attrs
(
ccx
,
&
attrs
,
llfn
);
llfn
}
}
...
...
@@ -792,7 +792,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
return
(
C_null
(
Type
::
i8
(
bcx
.ccx
())),
bcx
);
}
let
attributes
=
get_fn_llvm_attributes
(
bcx
.ccx
(),
fn_ty
);
let
attributes
=
attributes
::
from_fn_type
(
bcx
.ccx
(),
fn_ty
);
match
bcx
.opt_node_id
{
None
=>
{
...
...
@@ -2226,176 +2226,6 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
llfn
}
pub
fn
get_fn_llvm_attributes
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
fn_ty
:
Ty
<
'tcx
>
)
->
llvm
::
AttrBuilder
{
use
middle
::
ty
::{
BrAnon
,
ReLateBound
};
let
function_type
;
let
(
fn_sig
,
abi
,
env_ty
)
=
match
fn_ty
.sty
{
ty
::
ty_bare_fn
(
_
,
ref
f
)
=>
(
&
f
.sig
,
f
.abi
,
None
),
ty
::
ty_closure
(
closure_did
,
substs
)
=>
{
let
typer
=
common
::
NormalizingClosureTyper
::
new
(
ccx
.tcx
());
function_type
=
typer
.closure_type
(
closure_did
,
substs
);
let
self_type
=
self_type_for_closure
(
ccx
,
closure_did
,
fn_ty
);
(
&
function_type
.sig
,
RustCall
,
Some
(
self_type
))
}
_
=>
ccx
.sess
()
.bug
(
"expected closure or function."
)
};
let
fn_sig
=
ty
::
erase_late_bound_regions
(
ccx
.tcx
(),
fn_sig
);
let
mut
attrs
=
llvm
::
AttrBuilder
::
new
();
let
ret_ty
=
fn_sig
.output
;
// These have an odd calling convention, so we need to manually
// unpack the input ty's
let
input_tys
=
match
fn_ty
.sty
{
ty
::
ty_closure
(
..
)
=>
{
assert
!
(
abi
==
RustCall
);
match
fn_sig
.inputs
[
0
]
.sty
{
ty
::
ty_tup
(
ref
inputs
)
=>
{
let
mut
full_inputs
=
vec!
[
env_ty
.expect
(
"Missing closure environment"
)];
full_inputs
.push_all
(
inputs
);
full_inputs
}
_
=>
ccx
.sess
()
.bug
(
"expected tuple'd inputs"
)
}
},
ty
::
ty_bare_fn
(
..
)
if
abi
==
RustCall
=>
{
let
mut
inputs
=
vec!
[
fn_sig
.inputs
[
0
]];
match
fn_sig
.inputs
[
1
]
.sty
{
ty
::
ty_tup
(
ref
t_in
)
=>
{
inputs
.push_all
(
&
t_in
[
..
]);
inputs
}
_
=>
ccx
.sess
()
.bug
(
"expected tuple'd inputs"
)
}
}
_
=>
fn_sig
.inputs
.clone
()
};
// Index 0 is the return value of the llvm func, so we start at 1
let
mut
first_arg_offset
=
1
;
if
let
ty
::
FnConverging
(
ret_ty
)
=
ret_ty
{
// A function pointer is called without the declaration
// available, so we have to apply any attributes with ABI
// implications directly to the call instruction. Right now,
// the only attribute we need to worry about is `sret`.
if
type_of
::
return_uses_outptr
(
ccx
,
ret_ty
)
{
let
llret_sz
=
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
ret_ty
));
// The outptr can be noalias and nocapture because it's entirely
// invisible to the program. We also know it's nonnull as well
// as how many bytes we can dereference
attrs
.arg
(
1
,
llvm
::
StructRetAttribute
)
.arg
(
1
,
llvm
::
NoAliasAttribute
)
.arg
(
1
,
llvm
::
NoCaptureAttribute
)
.arg
(
1
,
llvm
::
DereferenceableAttribute
(
llret_sz
));
// Add one more since there's an outptr
first_arg_offset
+=
1
;
}
else
{
// The `noalias` attribute on the return value is useful to a
// function ptr caller.
match
ret_ty
.sty
{
// `~` pointer return values never alias because ownership
// is transferred
ty
::
ty_uniq
(
it
)
if
!
common
::
type_is_sized
(
ccx
.tcx
(),
it
)
=>
{}
ty
::
ty_uniq
(
_
)
=>
{
attrs
.ret
(
llvm
::
NoAliasAttribute
);
}
_
=>
{}
}
// We can also mark the return value as `dereferenceable` in certain cases
match
ret_ty
.sty
{
// These are not really pointers but pairs, (pointer, len)
ty
::
ty_uniq
(
it
)
|
ty
::
ty_rptr
(
_
,
ty
::
mt
{
ty
:
it
,
..
})
if
!
common
::
type_is_sized
(
ccx
.tcx
(),
it
)
=>
{}
ty
::
ty_uniq
(
inner
)
|
ty
::
ty_rptr
(
_
,
ty
::
mt
{
ty
:
inner
,
..
})
=>
{
let
llret_sz
=
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
inner
));
attrs
.ret
(
llvm
::
DereferenceableAttribute
(
llret_sz
));
}
_
=>
{}
}
if
let
ty
::
ty_bool
=
ret_ty
.sty
{
attrs
.ret
(
llvm
::
ZExtAttribute
);
}
}
}
for
(
idx
,
&
t
)
in
input_tys
.iter
()
.enumerate
()
.map
(|(
i
,
v
)|
(
i
+
first_arg_offset
,
v
))
{
match
t
.sty
{
// this needs to be first to prevent fat pointers from falling through
_
if
!
type_is_immediate
(
ccx
,
t
)
=>
{
let
llarg_sz
=
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
t
));
// For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also
// program-invisible so can't possibly capture
attrs
.arg
(
idx
,
llvm
::
NoAliasAttribute
)
.arg
(
idx
,
llvm
::
NoCaptureAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llarg_sz
));
}
ty
::
ty_bool
=>
{
attrs
.arg
(
idx
,
llvm
::
ZExtAttribute
);
}
// `~` pointer parameters never alias because ownership is transferred
ty
::
ty_uniq
(
inner
)
=>
{
let
llsz
=
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
inner
));
attrs
.arg
(
idx
,
llvm
::
NoAliasAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
}
// `&mut` pointer parameters never alias other parameters, or mutable global data
//
// `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
// `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on
// memory dependencies rather than pointer equality
ty
::
ty_rptr
(
b
,
mt
)
if
mt
.mutbl
==
ast
::
MutMutable
||
!
ty
::
type_contents
(
ccx
.tcx
(),
mt
.ty
)
.interior_unsafe
()
=>
{
let
llsz
=
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
mt
.ty
));
attrs
.arg
(
idx
,
llvm
::
NoAliasAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
if
mt
.mutbl
==
ast
::
MutImmutable
{
attrs
.arg
(
idx
,
llvm
::
ReadOnlyAttribute
);
}
if
let
ReLateBound
(
_
,
BrAnon
(
_
))
=
*
b
{
attrs
.arg
(
idx
,
llvm
::
NoCaptureAttribute
);
}
}
// When a reference in an argument has no named lifetime, it's impossible for that
// reference to escape this function (returned or stored beyond the call by a closure).
ty
::
ty_rptr
(
&
ReLateBound
(
_
,
BrAnon
(
_
)),
mt
)
=>
{
let
llsz
=
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
mt
.ty
));
attrs
.arg
(
idx
,
llvm
::
NoCaptureAttribute
)
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
}
// & pointer parameters are also never null and we know exactly how
// many bytes we can dereference
ty
::
ty_rptr
(
_
,
mt
)
=>
{
let
llsz
=
llsize_of_real
(
ccx
,
type_of
::
type_of
(
ccx
,
mt
.ty
));
attrs
.arg
(
idx
,
llvm
::
DereferenceableAttribute
(
llsz
));
}
_
=>
()
}
}
attrs
}
// only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
pub
fn
register_fn_llvmty
(
ccx
:
&
CrateContext
,
sp
:
Span
,
...
...
@@ -2605,7 +2435,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
sym
,
i
.id
)
};
attributes
::
convert_fn_attrs_to_llvm
(
ccx
,
&
i
.attrs
,
llfn
);
attributes
::
from_fn_attrs
(
ccx
,
&
i
.attrs
,
llfn
);
llfn
}
...
...
@@ -2666,7 +2496,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
let
ty
=
ty
::
node_id_to_type
(
ccx
.tcx
(),
ni
.id
);
let
name
=
foreign
::
link_name
(
&*
ni
);
let
llfn
=
foreign
::
register_foreign_item_fn
(
ccx
,
abi
,
ty
,
&
name
);
attributes
::
convert_fn_attrs_to_llvm
(
ccx
,
&
ni
.attrs
,
llfn
);
attributes
::
from_fn_attrs
(
ccx
,
&
ni
.attrs
,
llfn
);
llfn
}
ast
::
ForeignItemStatic
(
..
)
=>
{
...
...
@@ -2698,7 +2528,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
}
_
=>
ccx
.sess
()
.bug
(
"NodeVariant, shouldn't happen"
)
};
attributes
::
inline
(
llfn
,
attributes
::
InlineHint
);
attributes
::
inline
(
llfn
,
attributes
::
Inline
Attr
::
Hint
);
llfn
}
...
...
@@ -2720,7 +2550,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
&
struct_item
.attrs
);
let
llfn
=
register_fn
(
ccx
,
struct_item
.span
,
sym
,
ctor_id
,
ty
);
attributes
::
inline
(
llfn
,
attributes
::
InlineHint
);
attributes
::
inline
(
llfn
,
attributes
::
Inline
Attr
::
Hint
);
llfn
}
...
...
@@ -2755,7 +2585,7 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId,
}
else
{
foreign
::
register_rust_fn_with_foreign_abi
(
ccx
,
span
,
sym
,
id
)
};
attributes
::
convert_fn_attrs_to_llvm
(
ccx
,
&
attrs
,
llfn
);
attributes
::
from_fn_attrs
(
ccx
,
&
attrs
,
llfn
);
return
llfn
;
}
else
{
ccx
.sess
()
.span_bug
(
span
,
"expected bare rust function"
);
...
...
src/librustc_trans/trans/closure.rs
浏览文件 @
caea0449
...
...
@@ -165,7 +165,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
let
llfn
=
decl_internal_rust_fn
(
ccx
,
function_type
,
&
symbol
[
..
]);
// set an inline hint for all closures
attributes
::
inline
(
llfn
,
attributes
::
InlineHint
);
attributes
::
inline
(
llfn
,
attributes
::
Inline
Attr
::
Hint
);
debug!
(
"get_or_create_declaration_if_closure(): inserting new
\
closure {:?} (type {})"
,
...
...
src/librustc_trans/trans/foreign.rs
浏览文件 @
caea0449
...
...
@@ -209,7 +209,6 @@ pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let
llfn
=
get_extern_fn
(
ccx
,
&
mut
*
ccx
.externs
()
.borrow_mut
(),
name
,
cc
,
llfn_ty
,
fty
);
add_argument_attributes
(
&
tys
,
llfn
);
llfn
}
...
...
@@ -484,7 +483,7 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
}
let
llfn
=
register_foreign_item_fn
(
ccx
,
abi
,
ty
,
&
lname
);
base
::
set_llv
m_fn_attrs
(
ccx
,
&
foreign_item
.attrs
,
llfn
);
attributes
::
fro
m_fn_attrs
(
ccx
,
&
foreign_item
.attrs
,
llfn
);
// Unlike for other items, we shouldn't call
// `base::update_linkage` here. Foreign items have
// special linkage requirements, which are handled
...
...
@@ -625,7 +624,7 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
id
,
t
.repr
(
tcx
));
let
llfn
=
base
::
decl_internal_rust_fn
(
ccx
,
t
,
&
ps
[
..
]);
attributes
::
convert_fn_attrs_to_llvm
(
ccx
,
attrs
,
llfn
);
attributes
::
from_fn_attrs
(
ccx
,
attrs
,
llfn
);
base
::
trans_fn
(
ccx
,
decl
,
body
,
llfn
,
param_substs
,
id
,
&
[]);
llfn
}
...
...
@@ -818,7 +817,7 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Perform the call itself
debug!
(
"calling llrustfn = {}, t = {}"
,
ccx
.tn
()
.val_to_string
(
llrustfn
),
t
.repr
(
ccx
.tcx
()));
let
attributes
=
base
::
get_fn_llvm_attributes
(
ccx
,
t
);
let
attributes
=
attributes
::
from_fn_type
(
ccx
,
t
);
let
llrust_ret_val
=
builder
.call
(
llrustfn
,
&
llrust_args
,
Some
(
attributes
));
// Get the return value where the foreign fn expects it.
...
...
src/librustc_trans/trans/monomorphize.rs
浏览文件 @
caea0449
...
...
@@ -151,7 +151,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
};
let
setup_lldecl
=
|
lldecl
,
attrs
:
&
[
ast
::
Attribute
]|
{
base
::
update_linkage
(
ccx
,
lldecl
,
None
,
base
::
OriginalTranslation
);
attributes
::
convert_fn_attrs_to_llvm
(
ccx
,
attrs
,
lldecl
);
attributes
::
from_fn_attrs
(
ccx
,
attrs
,
lldecl
);
let
is_first
=
!
ccx
.available_monomorphizations
()
.borrow
()
.contains
(
&
s
);
if
is_first
{
...
...
@@ -200,7 +200,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let
tvs
=
ty
::
enum_variants
(
ccx
.tcx
(),
local_def
(
parent
));
let
this_tv
=
tvs
.iter
()
.find
(|
tv
|
{
tv
.id.node
==
fn_id
.node
})
.unwrap
();
let
d
=
mk_lldecl
(
abi
::
Rust
);
attributes
::
inline
(
d
,
attributes
::
InlineHint
);
attributes
::
inline
(
d
,
attributes
::
Inline
Attr
::
Hint
);
match
v
.node.kind
{
ast
::
TupleVariantKind
(
ref
args
)
=>
{
trans_enum_variant
(
ccx
,
...
...
@@ -259,7 +259,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
ast_map
::
NodeStructCtor
(
struct_def
)
=>
{
let
d
=
mk_lldecl
(
abi
::
Rust
);
attributes
::
inline
(
d
,
attributes
::
InlineHint
);
attributes
::
inline
(
d
,
attributes
::
Inline
Attr
::
Hint
);
base
::
trans_tuple_struct
(
ccx
,
&
struct_def
.fields
,
struct_def
.ctor_id
.expect
(
"ast-mapped tuple struct
\
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录