Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ed476b02
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,发现更多精彩内容 >>
提交
ed476b02
编写于
9月 17, 2014
作者:
S
Stuart Pernsteiner
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
support LTO against libraries built with codegen-units > 1
上级
ad9ed40e
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
120 addition
and
107 deletion
+120
-107
src/librustc/back/link.rs
src/librustc/back/link.rs
+14
-10
src/librustc/back/lto.rs
src/librustc/back/lto.rs
+72
-65
src/librustc/back/write.rs
src/librustc/back/write.rs
+32
-29
src/test/run-pass/sepcomp-lib-lto.rs
src/test/run-pass/sepcomp-lib-lto.rs
+2
-3
未找到文件。
src/librustc/back/link.rs
浏览文件 @
ed476b02
...
...
@@ -659,19 +659,18 @@ fn link_rlib<'a>(sess: &'a Session,
ab
.add_file
(
&
metadata
)
.unwrap
();
remove
(
sess
,
&
metadata
);
if
sess
.opts.cg.codegen_units
==
1
{
// For LTO purposes, the bytecode of this library is also
// inserted into the archive. We currently do this only when
// codegen_units == 1, so we don't have to deal with multiple
// bitcode files per crate.
//
// For LTO purposes, the bytecode of this library is also inserted
// into the archive. If codegen_units > 1, we insert each of the
// bitcode files.
for
i
in
range
(
0
,
sess
.opts.cg.codegen_units
)
{
// Note that we make sure that the bytecode filename in the
// archive is never exactly 16 bytes long by adding a 16 byte
// extension to it. This is to work around a bug in LLDB that
// would cause it to crash if the name of a file in an archive
// was exactly 16 bytes.
let
bc_filename
=
obj_filename
.with_extension
(
"bc"
);
let
bc_deflated_filename
=
obj_filename
.with_extension
(
"bytecode.deflate"
);
let
bc_filename
=
obj_filename
.with_extension
(
format!
(
"{}.bc"
,
i
)
.as_slice
());
let
bc_deflated_filename
=
obj_filename
.with_extension
(
format!
(
"{}.bytecode.deflate"
,
i
)
.as_slice
());
let
bc_data
=
match
fs
::
File
::
open
(
&
bc_filename
)
.read_to_end
()
{
Ok
(
buffer
)
=>
buffer
,
...
...
@@ -705,8 +704,13 @@ fn link_rlib<'a>(sess: &'a Session,
ab
.add_file
(
&
bc_deflated_filename
)
.unwrap
();
remove
(
sess
,
&
bc_deflated_filename
);
if
!
sess
.opts.cg.save_temps
&&
!
sess
.opts.output_types
.contains
(
&
OutputTypeBitcode
)
{
// See the bottom of back::write::run_passes for an explanation
// of when we do and don't keep .0.bc files around.
let
user_wants_numbered_bitcode
=
sess
.opts.output_types
.contains
(
&
OutputTypeBitcode
)
&&
sess
.opts.cg.codegen_units
>
1
;
if
!
sess
.opts.cg.save_temps
&&
!
user_wants_numbered_bitcode
{
remove
(
sess
,
&
bc_filename
);
}
}
...
...
src/librustc/back/lto.rs
浏览文件 @
ed476b02
...
...
@@ -21,6 +21,7 @@
use
libc
;
use
flate
;
use
std
::
iter
;
use
std
::
mem
;
pub
fn
run
(
sess
:
&
session
::
Session
,
llmod
:
ModuleRef
,
...
...
@@ -60,78 +61,84 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
let
file
=
path
.filename_str
()
.unwrap
();
let
file
=
file
.slice
(
3
,
file
.len
()
-
5
);
// chop off lib/.rlib
debug!
(
"reading {}"
,
file
);
let
bc_encoded
=
time
(
sess
.time_passes
(),
format!
(
"read {}.bytecode.deflate"
,
name
)
.as_slice
(),
(),
|
_
|
{
archive
.read
(
format!
(
"{}.bytecode.deflate"
,
file
)
.as_slice
())
});
let
bc_encoded
=
match
bc_encoded
{
Some
(
data
)
=>
data
,
None
=>
{
sess
.fatal
(
format!
(
"missing compressed bytecode in {}
\
(perhaps it was compiled with -C codegen-units > 1)"
,
path
.display
())
.as_slice
());
},
};
let
bc_extractor
=
if
is_versioned_bytecode_format
(
bc_encoded
)
{
|
_
|
{
// Read the version
let
version
=
extract_bytecode_format_version
(
bc_encoded
);
if
version
==
1
{
// The only version existing so far
let
data_size
=
extract_compressed_bytecode_size_v1
(
bc_encoded
);
let
compressed_data
=
bc_encoded
.slice
(
link
::
RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET
,
link
::
RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET
+
data_size
as
uint
);
match
flate
::
inflate_bytes
(
compressed_data
)
{
Some
(
inflated
)
=>
inflated
,
for
i
in
iter
::
count
(
0u
,
1
)
{
let
bc_encoded
=
time
(
sess
.time_passes
(),
format!
(
"check for {}.{}.bytecode.deflate"
,
name
,
i
)
.as_slice
(),
(),
|
_
|
{
archive
.read
(
format!
(
"{}.{}.bytecode.deflate"
,
file
,
i
)
.as_slice
())
});
let
bc_encoded
=
match
bc_encoded
{
Some
(
data
)
=>
data
,
None
=>
{
if
i
==
0
{
// No bitcode was found at all.
sess
.fatal
(
format!
(
"missing compressed bytecode in {}"
,
path
.display
())
.as_slice
());
}
// No more bitcode files to read.
break
;
},
};
let
bc_extractor
=
if
is_versioned_bytecode_format
(
bc_encoded
)
{
|
_
|
{
// Read the version
let
version
=
extract_bytecode_format_version
(
bc_encoded
);
if
version
==
1
{
// The only version existing so far
let
data_size
=
extract_compressed_bytecode_size_v1
(
bc_encoded
);
let
compressed_data
=
bc_encoded
.slice
(
link
::
RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET
,
link
::
RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET
+
data_size
as
uint
);
match
flate
::
inflate_bytes
(
compressed_data
)
{
Some
(
inflated
)
=>
inflated
,
None
=>
{
sess
.fatal
(
format!
(
"failed to decompress bc of `{}`"
,
name
)
.as_slice
())
}
}
}
else
{
sess
.fatal
(
format!
(
"Unsupported bytecode format version {}"
,
version
)
.as_slice
())
}
}
}
else
{
// the object must be in the old, pre-versioning format, so simply
// inflate everything and let LLVM decide if it can make sense of it
|
_
|
{
match
flate
::
inflate_bytes
(
bc_encoded
)
{
Some
(
bc
)
=>
bc
,
None
=>
{
sess
.fatal
(
format!
(
"failed to decompress bc of `{}`"
,
name
)
.as_slice
())
}
}
}
else
{
sess
.fatal
(
format!
(
"Unsupported bytecode format version {}"
,
version
)
.as_slice
())
}
}
}
else
{
// the object must be in the old, pre-versioning format, so simply
// inflate everything and let LLVM decide if it can make sense of it
|
_
|
{
match
flate
::
inflate_bytes
(
bc_encoded
)
{
Some
(
bc
)
=>
bc
,
None
=>
{
sess
.fatal
(
format!
(
"failed to decompress bc of `{}`"
,
name
)
.as_slice
())
}
};
let
bc_decoded
=
time
(
sess
.time_passes
(),
format!
(
"decode {}.{}.bc"
,
file
,
i
)
.as_slice
(),
(),
bc_extractor
);
let
ptr
=
bc_decoded
.as_slice
()
.as_ptr
();
debug!
(
"linking {}, part {}"
,
name
,
i
);
time
(
sess
.time_passes
(),
format!
(
"ll link {}.{}"
,
name
,
i
)
.as_slice
(),
(),
|()|
unsafe
{
if
!
llvm
::
LLVMRustLinkInExternalBitcode
(
llmod
,
ptr
as
*
const
libc
::
c_char
,
bc_decoded
.len
()
as
libc
::
size_t
)
{
write
::
llvm_err
(
sess
.diagnostic
()
.handler
(),
format!
(
"failed to load bc of `{}`"
,
name
.as_slice
()));
}
}
};
let
bc_decoded
=
time
(
sess
.time_passes
(),
format!
(
"decode {}.bc"
,
file
)
.as_slice
(),
(),
bc_extractor
);
let
ptr
=
bc_decoded
.as_slice
()
.as_ptr
();
debug!
(
"linking {}"
,
name
);
time
(
sess
.time_passes
(),
format!
(
"ll link {}"
,
name
)
.as_slice
(),
(),
|()|
unsafe
{
if
!
llvm
::
LLVMRustLinkInExternalBitcode
(
llmod
,
ptr
as
*
const
libc
::
c_char
,
bc_decoded
.len
()
as
libc
::
size_t
)
{
write
::
llvm_err
(
sess
.diagnostic
()
.handler
(),
format!
(
"failed to load bc of `{}`"
,
name
.as_slice
()));
}
});
});
}
}
// Internalize everything but the reachable symbols of the current module
...
...
src/librustc/back/write.rs
浏览文件 @
ed476b02
...
...
@@ -540,13 +540,12 @@ pub fn run_passes(sess: &Session,
metadata_config
.emit_bc
=
true
;
}
// Emit
a bitcode file
for the crate if we're emitting an rlib.
// Emit
bitcode files
for the crate if we're emitting an rlib.
// Whenever an rlib is created, the bitcode is inserted into the
// archive in order to allow LTO against it.
let
needs_crate_bitcode
=
sess
.crate_types
.borrow
()
.contains
(
&
config
::
CrateTypeRlib
)
&&
sess
.opts.output_types
.contains
(
&
OutputTypeExe
)
&&
sess
.opts.cg.codegen_units
==
1
;
sess
.opts.output_types
.contains
(
&
OutputTypeExe
);
if
needs_crate_bitcode
{
modules_config
.emit_bc
=
true
;
}
...
...
@@ -602,19 +601,8 @@ pub fn run_passes(sess: &Session,
// Process the work items, optionally using worker threads.
if
sess
.opts.cg.codegen_units
==
1
{
run_work_singlethreaded
(
sess
,
trans
.reachable
.as_slice
(),
work_items
);
if
needs_crate_bitcode
{
// The only bitcode file produced (aside from metadata) was
// "crate.0.bc". Rename to "crate.bc" since that's what
// `link_rlib` expects to find.
fs
::
copy
(
&
crate_output
.with_extension
(
"0.bc"
),
&
crate_output
.temp_path
(
OutputTypeBitcode
))
.unwrap
();
}
}
else
{
run_work_multithreaded
(
sess
,
work_items
,
sess
.opts.cg.codegen_units
);
assert
!
(
!
needs_crate_bitcode
,
"can't produce a crate bitcode file from multiple compilation units"
);
}
// All codegen is finished.
...
...
@@ -624,14 +612,14 @@ pub fn run_passes(sess: &Session,
// Produce final compile outputs.
let
copy_if_one_unit
=
|
ext
:
&
str
,
output_type
:
OutputType
|
{
let
copy_if_one_unit
=
|
ext
:
&
str
,
output_type
:
OutputType
,
keep_numbered
:
bool
|
{
// Three cases:
if
sess
.opts.cg.codegen_units
==
1
{
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
fs
::
copy
(
&
crate_output
.with_extension
(
ext
),
&
crate_output
.path
(
output_type
))
.unwrap
();
if
!
sess
.opts.cg.save_temps
{
if
!
sess
.opts.cg.save_temps
&&
!
keep_numbered
{
// The user just wants `foo.x`, not `foo.0.x`.
remove
(
sess
,
&
crate_output
.with_extension
(
ext
));
}
...
...
@@ -716,17 +704,18 @@ pub fn run_passes(sess: &Session,
// Flag to indicate whether the user explicitly requested bitcode.
// Otherwise, we produced it only as a temporary output, and will need
// to get rid of it.
// FIXME: Since we don't support LTO anyway, maybe we can avoid
// producing the temporary .0.bc's in the first place?
let
mut
save_bitcode
=
false
;
let
mut
user_wants_bitcode
=
false
;
for
output_type
in
output_types
.iter
()
{
match
*
output_type
{
OutputTypeBitcode
=>
{
save_bitcode
=
true
;
copy_if_one_unit
(
"0.bc"
,
OutputTypeBitcode
);
user_wants_bitcode
=
true
;
// Copy to .bc, but always keep the .0.bc. There is a later
// check to figure out if we should delete .0.bc files, or keep
// them for making an rlib.
copy_if_one_unit
(
"0.bc"
,
OutputTypeBitcode
,
true
);
},
OutputTypeLlvmAssembly
=>
{
copy_if_one_unit
(
"0.ll"
,
OutputTypeLlvmAssembly
);
},
OutputTypeAssembly
=>
{
copy_if_one_unit
(
"0.s"
,
OutputTypeAssembly
);
},
OutputTypeLlvmAssembly
=>
{
copy_if_one_unit
(
"0.ll"
,
OutputTypeLlvmAssembly
,
false
);
},
OutputTypeAssembly
=>
{
copy_if_one_unit
(
"0.s"
,
OutputTypeAssembly
,
false
);
},
OutputTypeObject
=>
{
link_obj
(
&
crate_output
.path
(
OutputTypeObject
));
},
OutputTypeExe
=>
{
// If OutputTypeObject is already in the list, then
...
...
@@ -739,7 +728,7 @@ pub fn run_passes(sess: &Session,
},
}
}
let
save_bitcode
=
save
_bitcode
;
let
user_wants_bitcode
=
user_wants
_bitcode
;
// Clean up unwanted temporary files.
...
...
@@ -755,22 +744,36 @@ pub fn run_passes(sess: &Session,
if
!
sess
.opts.cg.save_temps
{
// Remove the temporary .0.o objects. If the user didn't
// explicitly request bitcode (with --emit=bc), we must remove
// .0.bc as well. (We don't touch the crate.bc that may have been
// produced earlier.)
// explicitly request bitcode (with --emit=bc), and the bitcode is not
// needed for building an rlib, then we must remove .0.bc as well.
// Specific rules for keeping .0.bc:
// - If we're building an rlib (`needs_crate_bitcode`), then keep
// it.
// - If the user requested bitcode (`user_wants_bitcode`), and
// codegen_units > 1, then keep it.
// - If the user requested bitcode but codegen_units == 1, then we
// can toss .0.bc because we copied it to .bc earlier.
// - If we're not building an rlib and the user didn't request
// bitcode, then delete .0.bc.
// If you change how this works, also update back::link::link_rlib,
// where .0.bc files are (maybe) deleted after making an rlib.
let
keep_numbered_bitcode
=
needs_crate_bitcode
||
(
user_wants_bitcode
&&
sess
.opts.cg.codegen_units
>
1
);
for
i
in
range
(
0
,
trans
.modules
.len
())
{
if
modules_config
.emit_obj
{
let
ext
=
format!
(
"{}.o"
,
i
);
remove
(
sess
,
&
crate_output
.with_extension
(
ext
.as_slice
()));
}
if
modules_config
.emit_bc
&&
!
save
_bitcode
{
if
modules_config
.emit_bc
&&
!
keep_numbered
_bitcode
{
let
ext
=
format!
(
"{}.bc"
,
i
);
remove
(
sess
,
&
crate_output
.with_extension
(
ext
.as_slice
()));
}
}
if
metadata_config
.emit_bc
&&
!
save
_bitcode
{
if
metadata_config
.emit_bc
&&
!
user_wants
_bitcode
{
remove
(
sess
,
&
crate_output
.with_extension
(
"metadata.bc"
));
}
}
...
...
src/test/
compile-fail
/sepcomp-lib-lto.rs
→
src/test/
run-pass
/sepcomp-lib-lto.rs
浏览文件 @
ed476b02
...
...
@@ -8,12 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
Make sure we give a sane error message when the user requests LTO with a
//
library built with -C codegen-units > 1
.
//
Check that we can use `-Z lto` when linking against libraries that were
//
separately compiled
.
// aux-build:sepcomp_lib.rs
// compile-flags: -Z lto
// error-pattern:missing compressed bytecode
// no-prefer-dynamic
extern
crate
sepcomp_lib
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录