Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
cd41ee20
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,发现更多精彩内容 >>
提交
cd41ee20
编写于
4月 09, 2013
作者:
J
James Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add #[start] attribute to define a new entry point function
上级
412a0705
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
173 addition
and
45 deletion
+173
-45
src/librustc/driver/driver.rs
src/librustc/driver/driver.rs
+2
-1
src/librustc/driver/session.rs
src/librustc/driver/session.rs
+12
-1
src/librustc/middle/resolve.rs
src/librustc/middle/resolve.rs
+26
-4
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/base.rs
+54
-33
src/librustc/middle/typeck/mod.rs
src/librustc/middle/typeck/mod.rs
+65
-6
src/test/run-pass/attr-start.rs
src/test/run-pass/attr-start.rs
+14
-0
未找到文件。
src/librustc/driver/driver.rs
浏览文件 @
cd41ee20
...
...
@@ -698,7 +698,8 @@ pub fn build_session_(sopts: @session::options,
parse_sess
:
p_s
,
codemap
:
cm
,
// For a library crate, this is always none
main_fn
:
@
mut
None
,
entry_fn
:
@
mut
None
,
entry_type
:
@
mut
None
,
span_diagnostic
:
span_diagnostic_handler
,
filesearch
:
filesearch
,
building_library
:
@
mut
false
,
...
...
src/librustc/driver/session.rs
浏览文件 @
cd41ee20
...
...
@@ -144,6 +144,16 @@ pub struct crate_metadata {
data
:
~
[
u8
]
}
// The type of entry function, so
// users can have their own entry
// functions that don't start a
// scheduler
#[deriving(Eq)]
pub
enum
EntryFnType
{
EntryMain
,
EntryStart
}
pub
struct
Session_
{
targ_cfg
:
@
config
,
opts
:
@
options
,
...
...
@@ -151,7 +161,8 @@ pub struct Session_ {
parse_sess
:
@
mut
ParseSess
,
codemap
:
@
codemap
::
CodeMap
,
// For a library crate, this is always none
main_fn
:
@
mut
Option
<
(
node_id
,
codemap
::
span
)
>
,
entry_fn
:
@
mut
Option
<
(
node_id
,
codemap
::
span
)
>
,
entry_type
:
@
mut
Option
<
EntryFnType
>
,
span_diagnostic
:
@
diagnostic
::
span_handler
,
filesearch
:
@
filesearch
::
FileSearch
,
building_library
:
@
mut
bool
,
...
...
src/librustc/middle/resolve.rs
浏览文件 @
cd41ee20
...
...
@@ -801,6 +801,8 @@ pub fn Resolver(session: Session,
attr_main_fn
:
None
,
main_fns
:
~
[],
start_fn
:
None
,
def_map
:
@
mut
HashMap
::
new
(),
export_map2
:
@
mut
HashMap
::
new
(),
trait_map
:
HashMap
::
new
(),
...
...
@@ -860,9 +862,13 @@ pub struct Resolver {
// The function that has attribute named 'main'
attr_main_fn
:
Option
<
(
node_id
,
span
)
>
,
// The functions named 'main'
// The functions that could be main functions
main_fns
:
~
[
Option
<
(
node_id
,
span
)
>
],
// The function that has the attribute 'start' on it
start_fn
:
Option
<
(
node_id
,
span
)
>
,
def_map
:
DefMap
,
export_map2
:
ExportMap2
,
trait_map
:
TraitMap
,
...
...
@@ -3538,6 +3544,7 @@ fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) {
item_fn
(
ref
fn_decl
,
_
,
_
,
ref
generics
,
ref
block
)
=>
{
// If this is the main function, we must record it in the
// session.
// FIXME #4404 android JNI hacks
if
!*
self
.session.building_library
||
self
.session.targ_cfg.os
==
session
::
os_android
{
...
...
@@ -3557,6 +3564,16 @@ fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) {
~
"multiple 'main' functions"
);
}
}
if
attrs_contains_name
(
item
.attrs
,
~
"start"
)
{
if
self
.start_fn
.is_none
()
{
self
.start_fn
=
Some
((
item
.id
,
item
.span
));
}
else
{
self
.session
.span_err
(
item
.span
,
~
"multiple 'start' functions"
);
}
}
}
self
.resolve_function
(
OpaqueFunctionRibKind
,
...
...
@@ -5096,7 +5113,7 @@ fn enforce_default_binding_mode(@mut self,
//
fn
check_duplicate_main
(
@
mut
self
)
{
let
this
=
&
mut
*
self
;
if
this
.attr_main_fn
.is_none
()
{
if
this
.attr_main_fn
.is_none
()
&&
this
.start_fn
.is_none
()
{
if
this
.main_fns
.len
()
>=
1u
{
let
mut
i
=
1u
;
while
i
<
this
.main_fns
.len
()
{
...
...
@@ -5106,10 +5123,15 @@ fn check_duplicate_main(@mut self) {
~
"multiple 'main' functions"
);
i
+=
1
;
}
*
this
.session.main_fn
=
this
.main_fns
[
0
];
*
this
.session.entry_fn
=
this
.main_fns
[
0
];
*
this
.session.entry_type
=
Some
(
session
::
EntryMain
);
}
}
else
if
!
this
.start_fn
.is_none
()
{
*
this
.session.entry_fn
=
this
.start_fn
;
*
this
.session.entry_type
=
Some
(
session
::
EntryStart
);
}
else
{
*
this
.session.main_fn
=
this
.attr_main_fn
;
*
this
.session.entry_fn
=
this
.attr_main_fn
;
*
this
.session.entry_type
=
Some
(
session
::
EntryMain
);
}
}
...
...
src/librustc/middle/trans/base.rs
浏览文件 @
cd41ee20
...
...
@@ -2197,28 +2197,32 @@ pub fn register_fn_fuller(ccx: @CrateContext,
ccx
.item_symbols
.insert
(
node_id
,
ps
);
// FIXME #4404 android JNI hacks
let
is_
main
=
is_main
_fn
(
&
ccx
.sess
,
node_id
)
&&
let
is_
entry
=
is_entry
_fn
(
&
ccx
.sess
,
node_id
)
&&
(
!*
ccx
.sess.building_library
||
(
*
ccx
.sess.building_library
&&
ccx
.sess.targ_cfg.os
==
session
::
os_android
));
if
is_
main
{
create_main
_wrapper
(
ccx
,
sp
,
llfn
);
}
if
is_
entry
{
create_entry
_wrapper
(
ccx
,
sp
,
llfn
);
}
llfn
}
pub
fn
is_
main
_fn
(
sess
:
&
Session
,
node_id
:
ast
::
node_id
)
->
bool
{
match
*
sess
.
main
_fn
{
Some
((
main_id
,
_
))
=>
node_id
==
main
_id
,
pub
fn
is_
entry
_fn
(
sess
:
&
Session
,
node_id
:
ast
::
node_id
)
->
bool
{
match
*
sess
.
entry
_fn
{
Some
((
entry_id
,
_
))
=>
node_id
==
entry
_id
,
None
=>
false
}
}
// Create a _rust_main(args: ~[str]) function which will be called from the
// runtime rust_start function
pub
fn
create_
main
_wrapper
(
ccx
:
@
CrateContext
,
pub
fn
create_
entry
_wrapper
(
ccx
:
@
CrateContext
,
_
sp
:
span
,
main_llfn
:
ValueRef
)
{
let
llfn
=
create_main
(
ccx
,
main_llfn
);
create_entry_fn
(
ccx
,
llfn
);
let
et
=
ccx
.sess.entry_type
.unwrap
();
if
et
==
session
::
EntryMain
{
let
llfn
=
create_main
(
ccx
,
main_llfn
);
create_entry_fn
(
ccx
,
llfn
,
true
);
}
else
{
create_entry_fn
(
ccx
,
main_llfn
,
false
);
}
fn
create_main
(
ccx
:
@
CrateContext
,
main_llfn
:
ValueRef
)
->
ValueRef
{
let
nt
=
ty
::
mk_nil
(
ccx
.tcx
);
...
...
@@ -2242,7 +2246,7 @@ fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef {
return
llfdecl
;
}
fn
create_entry_fn
(
ccx
:
@
CrateContext
,
rust_main
:
ValueRef
)
{
fn
create_entry_fn
(
ccx
:
@
CrateContext
,
rust_main
:
ValueRef
,
use_start_lang_item
:
bool
)
{
let
llfty
=
T_fn
(
~
[
ccx
.int_type
,
T_ptr
(
T_ptr
(
T_i8
()))],
ccx
.int_type
);
// FIXME #4404 android JNI hacks
...
...
@@ -2264,34 +2268,51 @@ fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef) {
unsafe
{
llvm
::
LLVMPositionBuilderAtEnd
(
bld
,
llbb
);
}
let
crate_map
=
ccx
.crate_map
;
let
start_def_id
=
ccx
.tcx.lang_items
.start_fn
();
let
start_fn
=
if
start_def_id
.crate
==
ast
::
local_crate
{
ccx
.sess
.bug
(
~
"start lang item is never in the local crate"
)
}
else
{
let
start_fn_type
=
csearch
::
get_type
(
ccx
.tcx
,
start_def_id
)
.ty
;
trans_external_path
(
ccx
,
start_def_id
,
start_fn_type
)
};
let
retptr
=
unsafe
{
llvm
::
LLVMBuildAlloca
(
bld
,
ccx
.int_type
,
noname
())
};
let
args
=
unsafe
{
let
opaque_rust_main
=
llvm
::
LLVMBuildPointerCast
(
bld
,
rust_main
,
T_ptr
(
T_i8
()),
noname
());
let
opaque_crate_map
=
llvm
::
LLVMBuildPointerCast
(
bld
,
crate_map
,
T_ptr
(
T_i8
()),
noname
());
~
[
retptr
,
C_null
(
T_opaque_box_ptr
(
ccx
)),
opaque_rust_main
,
llvm
::
LLVMGetParam
(
llfn
,
0
as
c_uint
),
llvm
::
LLVMGetParam
(
llfn
,
1
as
c_uint
),
opaque_crate_map
]
let
crate_map
=
ccx
.crate_map
;
let
opaque_crate_map
=
unsafe
{
llvm
::
LLVMBuildPointerCast
(
bld
,
crate_map
,
T_ptr
(
T_i8
()),
noname
())};
let
(
start_fn
,
args
)
=
if
use_start_lang_item
{
let
start_def_id
=
ccx
.tcx.lang_items
.start_fn
();
let
start_fn
=
if
start_def_id
.crate
==
ast
::
local_crate
{
ccx
.sess
.bug
(
~
"start lang item is never in the local crate"
)
}
else
{
let
start_fn_type
=
csearch
::
get_type
(
ccx
.tcx
,
start_def_id
)
.ty
;
trans_external_path
(
ccx
,
start_def_id
,
start_fn_type
)
};
let
args
=
unsafe
{
let
opaque_rust_main
=
llvm
::
LLVMBuildPointerCast
(
bld
,
rust_main
,
T_ptr
(
T_i8
()),
noname
());
~
[
retptr
,
C_null
(
T_opaque_box_ptr
(
ccx
)),
opaque_rust_main
,
llvm
::
LLVMGetParam
(
llfn
,
0
as
c_uint
),
llvm
::
LLVMGetParam
(
llfn
,
1
as
c_uint
),
opaque_crate_map
]
};
(
start_fn
,
args
)
}
else
{
debug!
(
"using user-defined start fn"
);
let
args
=
unsafe
{
~
[
retptr
,
C_null
(
T_opaque_box_ptr
(
ccx
)),
llvm
::
LLVMGetParam
(
llfn
,
0
as
c_uint
),
llvm
::
LLVMGetParam
(
llfn
,
1
as
c_uint
),
opaque_crate_map
]
};
(
rust_main
,
args
)
};
unsafe
{
...
...
src/librustc/middle/typeck/mod.rs
浏览文件 @
cd41ee20
...
...
@@ -50,6 +50,8 @@
use
core
::
prelude
::
*
;
use
driver
::
session
;
use
middle
::
resolve
;
use
middle
::
ty
;
use
util
::
common
::
time
;
...
...
@@ -62,7 +64,8 @@
use
std
::
list
;
use
syntax
::
codemap
::
span
;
use
syntax
::
print
::
pprust
::
*
;
use
syntax
::{
ast
,
ast_map
};
use
syntax
::{
ast
,
ast_map
,
abi
};
use
syntax
::
opt_vec
;
#[path
=
"check/mod.rs"
]
pub
mod
check
;
...
...
@@ -325,12 +328,68 @@ fn check_main_fn_ty(ccx: @mut CrateCtxt,
}
}
fn
check_for_main_fn
(
ccx
:
@
mut
CrateCtxt
)
{
fn
check_start_fn_ty
(
ccx
:
@
mut
CrateCtxt
,
start_id
:
ast
::
node_id
,
start_span
:
span
)
{
let
tcx
=
ccx
.tcx
;
let
start_t
=
ty
::
node_id_to_type
(
tcx
,
start_id
);
match
ty
::
get
(
start_t
)
.sty
{
ty
::
ty_bare_fn
(
_
)
=>
{
match
tcx
.items
.find
(
&
start_id
)
{
Some
(
&
ast_map
::
node_item
(
it
,
_
))
=>
{
match
it
.node
{
ast
::
item_fn
(
_
,
_
,
_
,
ref
ps
,
_
)
if
ps
.is_parameterized
()
=>
{
tcx
.sess
.span_err
(
start_span
,
~
"start function is not allowed to have type
\
parameters"
);
return
;
}
_
=>
()
}
}
_
=>
()
}
fn
arg
(
m
:
ast
::
rmode
,
ty
:
ty
::
t
)
->
ty
::
arg
{
ty
::
arg
{
mode
:
ast
::
expl
(
m
),
ty
:
ty
}
}
let
se_ty
=
ty
::
mk_bare_fn
(
tcx
,
ty
::
BareFnTy
{
purity
:
ast
::
impure_fn
,
abis
:
abi
::
AbiSet
::
Rust
(),
sig
:
ty
::
FnSig
{
bound_lifetime_names
:
opt_vec
::
Empty
,
inputs
:
~
[
arg
(
ast
::
by_copy
,
ty
::
mk_int
(
tcx
)),
arg
(
ast
::
by_copy
,
ty
::
mk_imm_ptr
(
tcx
,
ty
::
mk_imm_ptr
(
tcx
,
ty
::
mk_u8
(
tcx
)))),
arg
(
ast
::
by_copy
,
ty
::
mk_imm_ptr
(
tcx
,
ty
::
mk_u8
(
tcx
)))],
output
:
ty
::
mk_int
(
tcx
)}
});
require_same_types
(
tcx
,
None
,
false
,
start_span
,
start_t
,
se_ty
,
||
fmt!
(
"start function expects type: `%s`"
,
ppaux
::
ty_to_str
(
ccx
.tcx
,
se_ty
)));
}
_
=>
{
tcx
.sess
.span_bug
(
start_span
,
~
"start has a non-function type: found `"
+
ppaux
::
ty_to_str
(
tcx
,
start_t
)
+
~
"`"
);
}
}
}
fn
check_for_entry_fn
(
ccx
:
@
mut
CrateCtxt
)
{
let
tcx
=
ccx
.tcx
;
if
!*
tcx
.sess.building_library
{
match
*
tcx
.sess.main_fn
{
Some
((
id
,
sp
))
=>
check_main_fn_ty
(
ccx
,
id
,
sp
),
None
=>
tcx
.sess
.err
(
~
"main function not found"
)
match
*
tcx
.sess.entry_fn
{
Some
((
id
,
sp
))
=>
match
*
tcx
.sess.entry_type
{
Some
(
session
::
EntryMain
)
=>
check_main_fn_ty
(
ccx
,
id
,
sp
),
Some
(
session
::
EntryStart
)
=>
check_start_fn_ty
(
ccx
,
id
,
sp
),
None
=>
tcx
.sess
.bug
(
~
"entry function without a type"
)
},
None
=>
tcx
.sess
.err
(
~
"entry function not found"
)
}
}
}
...
...
@@ -357,7 +416,7 @@ pub fn check_crate(tcx: ty::ctxt,
time
(
time_passes
,
~
"type checking"
,
||
check
::
check_item_types
(
ccx
,
crate
));
check_for_
main
_fn
(
ccx
);
check_for_
entry
_fn
(
ccx
);
tcx
.sess
.abort_if_errors
();
(
ccx
.method_map
,
ccx
.vtable_map
)
}
...
...
src/test/run-pass/attr-start.rs
0 → 100644
浏览文件 @
cd41ee20
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[start]
fn
start
(
argc
:
int
,
argv
:
**
u8
,
crate_map
:
*
u8
)
->
int
{
return
0
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录