Skip to content

Commit d1752ca

Browse files
committed
Initial support for dynamically linked crates
1 parent 49e5e4e commit d1752ca

File tree

68 files changed

+1531
-117
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1531
-117
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
13101310
// create a fake body so that the entire rest of the compiler doesn't have to deal with
13111311
// this as a special case.
13121312
return self.lower_fn_body(decl, contract, |this| {
1313-
if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) {
1313+
if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic))
1314+
|| this.tcx.is_sdylib_interface_build()
1315+
{
13141316
let span = this.lower_span(span);
13151317
let empty_block = hir::Block {
13161318
hir_id: this.next_id(),

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ struct AstValidator<'a> {
8282
/// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
8383
extern_mod_safety: Option<Safety>,
8484

85+
is_sdylib_interface: bool,
86+
8587
lint_buffer: &'a mut LintBuffer,
8688
}
8789

@@ -948,7 +950,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
948950
self.check_defaultness(item.span, *defaultness);
949951

950952
let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
951-
if body.is_none() && !is_intrinsic {
953+
if body.is_none() && !is_intrinsic && !self.is_sdylib_interface {
952954
self.dcx().emit_err(errors::FnWithoutBody {
953955
span: item.span,
954956
replace_span: self.ending_semi_or_hi(item.span),
@@ -1435,7 +1437,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14351437
});
14361438
}
14371439
AssocItemKind::Fn(box Fn { body, .. }) => {
1438-
if body.is_none() {
1440+
if body.is_none() && !self.is_sdylib_interface {
14391441
self.dcx().emit_err(errors::AssocFnWithoutBody {
14401442
span: item.span,
14411443
replace_span: self.ending_semi_or_hi(item.span),
@@ -1683,6 +1685,7 @@ pub fn check_crate(
16831685
sess: &Session,
16841686
features: &Features,
16851687
krate: &Crate,
1688+
is_sdylib_interface: bool,
16861689
lints: &mut LintBuffer,
16871690
) -> bool {
16881691
let mut validator = AstValidator {
@@ -1694,6 +1697,7 @@ pub fn check_crate(
16941697
outer_impl_trait_span: None,
16951698
disallow_tilde_const: Some(TildeConstReason::Item),
16961699
extern_mod_safety: None,
1700+
is_sdylib_interface,
16971701
lint_buffer: lints,
16981702
};
16991703
visit::walk_crate(&mut validator, krate);

compiler/rustc_ast_pretty/src/pprust/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use std::borrow::Cow;
77
use rustc_ast as ast;
88
use rustc_ast::token::{Token, TokenKind};
99
use rustc_ast::tokenstream::{TokenStream, TokenTree};
10-
pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate};
10+
pub use state::{
11+
AnnNode, Comments, PpAnn, PrintState, State, print_crate, print_crate_as_interface,
12+
};
1113

1214
/// Print the token kind precisely, without converting `$crate` into its respective crate name.
1315
pub fn token_kind_to_string(tok: &TokenKind) -> Cow<'static, str> {

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ pub struct State<'a> {
221221
pub s: pp::Printer,
222222
comments: Option<Comments<'a>>,
223223
ann: &'a (dyn PpAnn + 'a),
224+
is_sdylib_interface: bool,
224225
}
225226

226227
const INDENT_UNIT: isize = 4;
@@ -236,10 +237,39 @@ pub fn print_crate<'a>(
236237
is_expanded: bool,
237238
edition: Edition,
238239
g: &AttrIdGenerator,
240+
) -> String {
241+
let mut s = State {
242+
s: pp::Printer::new(),
243+
comments: Some(Comments::new(sm, filename, input)),
244+
ann,
245+
is_sdylib_interface: false,
246+
};
247+
248+
print_crate_inner(&mut s, krate, is_expanded, edition, g);
249+
250+
s.ann.post(&mut s, AnnNode::Crate(krate));
251+
s.s.eof()
252+
}
253+
254+
pub fn print_crate_as_interface(
255+
krate: &ast::Crate,
256+
edition: Edition,
257+
g: &AttrIdGenerator,
239258
) -> String {
240259
let mut s =
241-
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
260+
State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_sdylib_interface: true };
242261

262+
print_crate_inner(&mut s, krate, false, edition, g);
263+
s.s.eof()
264+
}
265+
266+
fn print_crate_inner<'a>(
267+
s: &mut State<'a>,
268+
krate: &ast::Crate,
269+
is_expanded: bool,
270+
edition: Edition,
271+
g: &AttrIdGenerator,
272+
) {
243273
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
244274
// We need to print `#![no_std]` (and its feature gate) so that
245275
// compiling pretty-printed source won't inject libstd again.
@@ -277,8 +307,6 @@ pub fn print_crate<'a>(
277307
s.print_item(item);
278308
}
279309
s.print_remaining_comments();
280-
s.ann.post(&mut s, AnnNode::Crate(krate));
281-
s.s.eof()
282310
}
283311

284312
/// Should two consecutive tokens be printed with a space between them?
@@ -1083,7 +1111,7 @@ impl<'a> PrintState<'a> for State<'a> {
10831111

10841112
impl<'a> State<'a> {
10851113
pub fn new() -> State<'a> {
1086-
State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
1114+
State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_sdylib_interface: false }
10871115
}
10881116

10891117
fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)

compiler/rustc_ast_pretty/src/pprust/state/item.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ impl<'a> State<'a> {
159159

160160
/// Pretty-prints an item.
161161
pub(crate) fn print_item(&mut self, item: &ast::Item) {
162+
if self.is_sdylib_interface && item.span.is_dummy() {
163+
// Do not print prelude for interface files.
164+
return;
165+
}
162166
self.hardbreak_if_not_bol();
163167
self.maybe_print_comment(item.span.lo());
164168
self.print_outer_attributes(&item.attrs);
@@ -693,6 +697,12 @@ impl<'a> State<'a> {
693697
self.nbsp();
694698
self.print_contract(contract);
695699
}
700+
if self.is_sdylib_interface {
701+
self.word(";");
702+
self.end(); // end inner head-block
703+
self.end(); // end outer head-block
704+
return;
705+
}
696706
if let Some(body) = body {
697707
self.nbsp();
698708
self.print_block_with_attrs(body, attrs);

compiler/rustc_codegen_gcc/src/back/lto.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level};
4444

4545
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
4646
match crate_type {
47-
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
47+
CrateType::Executable
48+
| CrateType::Dylib
49+
| CrateType::Staticlib
50+
| CrateType::Cdylib
51+
| CrateType::Sdylib => true,
4852
CrateType::Rlib | CrateType::ProcMacro => false,
4953
}
5054
}

compiler/rustc_codegen_llvm/src/back/lto.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ fn crate_type_allows_lto(crate_type: CrateType) -> bool {
4141
| CrateType::Dylib
4242
| CrateType::Staticlib
4343
| CrateType::Cdylib
44-
| CrateType::ProcMacro => true,
44+
| CrateType::ProcMacro
45+
| CrateType::Sdylib => true,
4546
CrateType::Rlib => false,
4647
}
4748
}

compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,11 @@ pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
9595
// in the `.debug_gdb_scripts` section. For that reason, we make sure that the
9696
// section is only emitted for leaf crates.
9797
let embed_visualizers = cx.tcx.crate_types().iter().any(|&crate_type| match crate_type {
98-
CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => {
98+
CrateType::Executable
99+
| CrateType::Dylib
100+
| CrateType::Cdylib
101+
| CrateType::Staticlib
102+
| CrateType::Sdylib => {
99103
// These are crate types for which we will embed pretty printers since they
100104
// are treated as leaf crates.
101105
true

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,9 +1054,10 @@ fn link_natively(
10541054
strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-debug"])
10551055
}
10561056
// Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988)
1057-
(Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => {
1058-
strip_with_external_utility(sess, stripcmd, out_filename, &["-x"])
1059-
}
1057+
(
1058+
Strip::Symbols,
1059+
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib,
1060+
) => strip_with_external_utility(sess, stripcmd, out_filename, &["-x"]),
10601061
(Strip::Symbols, _) => {
10611062
strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-all"])
10621063
}
@@ -1244,8 +1245,10 @@ fn add_sanitizer_libraries(
12441245
// which should be linked to both executables and dynamic libraries.
12451246
// Everywhere else the runtimes are currently distributed as static
12461247
// libraries which should be linked to executables only.
1247-
if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro)
1248-
&& !(sess.target.is_like_darwin || sess.target.is_like_msvc)
1248+
if matches!(
1249+
crate_type,
1250+
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib
1251+
) && !(sess.target.is_like_darwin || sess.target.is_like_msvc)
12491252
{
12501253
return;
12511254
}
@@ -1939,6 +1942,7 @@ fn add_late_link_args(
19391942
codegen_results: &CodegenResults,
19401943
) {
19411944
let any_dynamic_crate = crate_type == CrateType::Dylib
1945+
|| crate_type == CrateType::Sdylib
19421946
|| codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
19431947
*ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
19441948
});

compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1815,7 +1815,7 @@ pub(crate) fn linked_symbols(
18151815
crate_type: CrateType,
18161816
) -> Vec<(String, SymbolExportKind)> {
18171817
match crate_type {
1818-
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => (),
1818+
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib | CrateType::Sdylib => (),
18191819
CrateType::Staticlib | CrateType::ProcMacro | CrateType::Rlib => {
18201820
return Vec::new();
18211821
}

0 commit comments

Comments
 (0)