Skip to content

Commit fbdf1d2

Browse files
committed
Auto merge of #64000 - Centril:rollup-70s9ar3, r=Centril
Rollup of 4 pull requests Successful merges: - #62734 (Hide trait default methods) - #63953 (bootstrap: allow specifying mirror for bootstrap compiler download.) - #63956 (rustc: Handle modules in "fat" LTO more robustly) - #63979 (std: Remove the `wasm_syscall` feature) Failed merges: r? @ghost
2 parents 7445622 + d920aa0 commit fbdf1d2

File tree

23 files changed

+116
-451
lines changed

23 files changed

+116
-451
lines changed

config.toml.example

-5
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,6 @@
382382
# This is the name of the directory in which codegen backends will get installed
383383
#codegen-backends-dir = "codegen-backends"
384384

385-
# Flag indicating whether `libstd` calls an imported function to handle basic IO
386-
# when targeting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown`
387-
# target, as without this option the test output will not be captured.
388-
#wasm-syscall = false
389-
390385
# Indicates whether LLD will be compiled and made available in the sysroot for
391386
# rustc to execute.
392387
#lld = false

src/bootstrap/bootstrap.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ class RustBuild(object):
320320
def __init__(self):
321321
self.cargo_channel = ''
322322
self.date = ''
323-
self._download_url = 'https://static.rust-lang.org'
323+
self._download_url = ''
324324
self.rustc_channel = ''
325325
self.build = ''
326326
self.build_dir = os.path.join(os.getcwd(), "build")
@@ -733,9 +733,19 @@ def update_submodules(self):
733733
self.update_submodule(module[0], module[1], recorded_submodules)
734734
print("Submodules updated in %.2f seconds" % (time() - start_time))
735735

736+
def set_normal_environment(self):
737+
"""Set download URL for normal environment"""
738+
if 'RUSTUP_DIST_SERVER' in os.environ:
739+
self._download_url = os.environ['RUSTUP_DIST_SERVER']
740+
else:
741+
self._download_url = 'https://static.rust-lang.org'
742+
736743
def set_dev_environment(self):
737744
"""Set download URL for development environment"""
738-
self._download_url = 'https://dev-static.rust-lang.org'
745+
if 'RUSTUP_DEV_DIST_SERVER' in os.environ:
746+
self._download_url = os.environ['RUSTUP_DEV_DIST_SERVER']
747+
else:
748+
self._download_url = 'https://dev-static.rust-lang.org'
739749

740750
def check_vendored_status(self):
741751
"""Check that vendoring is configured properly"""
@@ -828,6 +838,8 @@ def bootstrap(help_triggered):
828838

829839
if 'dev' in data:
830840
build.set_dev_environment()
841+
else:
842+
build.set_normal_environment()
831843

832844
build.update_submodules()
833845

src/bootstrap/config.rs

-3
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ pub struct Config {
122122

123123
// libstd features
124124
pub backtrace: bool, // support for RUST_BACKTRACE
125-
pub wasm_syscall: bool,
126125

127126
// misc
128127
pub low_priority: bool,
@@ -318,7 +317,6 @@ struct Rust {
318317
save_toolstates: Option<String>,
319318
codegen_backends: Option<Vec<String>>,
320319
codegen_backends_dir: Option<String>,
321-
wasm_syscall: Option<bool>,
322320
lld: Option<bool>,
323321
lldb: Option<bool>,
324322
llvm_tools: Option<bool>,
@@ -558,7 +556,6 @@ impl Config {
558556
if let Some(true) = rust.incremental {
559557
config.incremental = true;
560558
}
561-
set(&mut config.wasm_syscall, rust.wasm_syscall);
562559
set(&mut config.lld_enabled, rust.lld);
563560
set(&mut config.lldb_enabled, rust.lldb);
564561
set(&mut config.llvm_tools_enabled, rust.llvm_tools);

src/bootstrap/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,6 @@ impl Build {
495495
if self.config.profiler {
496496
features.push_str(" profiler");
497497
}
498-
if self.config.wasm_syscall {
499-
features.push_str(" wasm_syscall");
500-
}
501498
features
502499
}
503500

src/bootstrap/test.rs

-10
Original file line numberDiff line numberDiff line change
@@ -1811,16 +1811,6 @@ impl Step for Crate {
18111811
.expect("nodejs not configured"),
18121812
);
18131813
} else if target.starts_with("wasm32") {
1814-
// Warn about running tests without the `wasm_syscall` feature enabled.
1815-
// The javascript shim implements the syscall interface so that test
1816-
// output can be correctly reported.
1817-
if !builder.config.wasm_syscall {
1818-
builder.info(
1819-
"Libstd was built without `wasm_syscall` feature enabled: \
1820-
test output may not be visible."
1821-
);
1822-
}
1823-
18241814
// On the wasm32-unknown-unknown target we're using LTO which is
18251815
// incompatible with `-C prefer-dynamic`, so disable that here
18261816
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");

src/etc/wasm32-shim.js

+1-107
Original file line numberDiff line numberDiff line change
@@ -15,113 +15,7 @@ const buffer = fs.readFileSync(process.argv[2]);
1515
Error.stackTraceLimit = 20;
1616

1717
let m = new WebAssembly.Module(buffer);
18-
19-
let memory = null;
20-
21-
function viewstruct(data, fields) {
22-
return new Uint32Array(memory.buffer).subarray(data/4, data/4 + fields);
23-
}
24-
25-
function copystr(a, b) {
26-
let view = new Uint8Array(memory.buffer).subarray(a, a + b);
27-
return String.fromCharCode.apply(null, view);
28-
}
29-
30-
function syscall_write([fd, ptr, len]) {
31-
let s = copystr(ptr, len);
32-
switch (fd) {
33-
case 1: process.stdout.write(s); break;
34-
case 2: process.stderr.write(s); break;
35-
}
36-
}
37-
38-
function syscall_exit([code]) {
39-
process.exit(code);
40-
}
41-
42-
function syscall_args(params) {
43-
let [ptr, len] = params;
44-
45-
// Calculate total required buffer size
46-
let totalLen = -1;
47-
for (let i = 2; i < process.argv.length; ++i) {
48-
totalLen += Buffer.byteLength(process.argv[i]) + 1;
49-
}
50-
if (totalLen < 0) { totalLen = 0; }
51-
params[2] = totalLen;
52-
53-
// If buffer is large enough, copy data
54-
if (len >= totalLen) {
55-
let view = new Uint8Array(memory.buffer);
56-
for (let i = 2; i < process.argv.length; ++i) {
57-
let value = process.argv[i];
58-
Buffer.from(value).copy(view, ptr);
59-
ptr += Buffer.byteLength(process.argv[i]) + 1;
60-
}
61-
}
62-
}
63-
64-
function syscall_getenv(params) {
65-
let [keyPtr, keyLen, valuePtr, valueLen] = params;
66-
67-
let key = copystr(keyPtr, keyLen);
68-
let value = process.env[key];
69-
70-
if (value == null) {
71-
params[4] = 0xFFFFFFFF;
72-
} else {
73-
let view = new Uint8Array(memory.buffer);
74-
let totalLen = Buffer.byteLength(value);
75-
params[4] = totalLen;
76-
if (valueLen >= totalLen) {
77-
Buffer.from(value).copy(view, valuePtr);
78-
}
79-
}
80-
}
81-
82-
function syscall_time(params) {
83-
let t = Date.now();
84-
let secs = Math.floor(t / 1000);
85-
let millis = t % 1000;
86-
params[1] = Math.floor(secs / 0x100000000);
87-
params[2] = secs % 0x100000000;
88-
params[3] = Math.floor(millis * 1000000);
89-
}
90-
91-
let imports = {};
92-
imports.env = {
93-
// These are generated by LLVM itself for various intrinsic calls. Hopefully
94-
// one day this is not necessary and something will automatically do this.
95-
fmod: function(x, y) { return x % y; },
96-
exp2: function(x) { return Math.pow(2, x); },
97-
exp2f: function(x) { return Math.pow(2, x); },
98-
ldexp: function(x, y) { return x * Math.pow(2, y); },
99-
ldexpf: function(x, y) { return x * Math.pow(2, y); },
100-
sin: Math.sin,
101-
sinf: Math.sin,
102-
cos: Math.cos,
103-
cosf: Math.cos,
104-
log: Math.log,
105-
log2: Math.log2,
106-
log10: Math.log10,
107-
log10f: Math.log10,
108-
109-
rust_wasm_syscall: function(index, data) {
110-
switch (index) {
111-
case 1: syscall_write(viewstruct(data, 3)); return true;
112-
case 2: syscall_exit(viewstruct(data, 1)); return true;
113-
case 3: syscall_args(viewstruct(data, 3)); return true;
114-
case 4: syscall_getenv(viewstruct(data, 5)); return true;
115-
case 6: syscall_time(viewstruct(data, 4)); return true;
116-
default:
117-
console.log("Unsupported syscall: " + index);
118-
return false;
119-
}
120-
}
121-
};
122-
123-
let instance = new WebAssembly.Instance(m, imports);
124-
memory = instance.exports.memory;
18+
let instance = new WebAssembly.Instance(m, {});
12519
try {
12620
instance.exports.main();
12721
} catch (e) {

src/librustc_codegen_llvm/back/lto.rs

+41-45
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,40 @@ pub(crate) fn prepare_thin(
183183

184184
fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
185185
diag_handler: &Handler,
186-
mut modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
186+
modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
187187
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
188188
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
189189
symbol_white_list: &[*const libc::c_char])
190190
-> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError>
191191
{
192192
info!("going for a fat lto");
193193

194+
// Sort out all our lists of incoming modules into two lists.
195+
//
196+
// * `serialized_modules` (also and argument to this function) contains all
197+
// modules that are serialized in-memory.
198+
// * `in_memory` contains modules which are already parsed and in-memory,
199+
// such as from multi-CGU builds.
200+
//
201+
// All of `cached_modules` (cached from previous incremental builds) can
202+
// immediately go onto the `serialized_modules` modules list and then we can
203+
// split the `modules` array into these two lists.
204+
let mut in_memory = Vec::new();
205+
serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| {
206+
info!("pushing cached module {:?}", wp.cgu_name);
207+
(buffer, CString::new(wp.cgu_name).unwrap())
208+
}));
209+
for module in modules {
210+
match module {
211+
FatLTOInput::InMemory(m) => in_memory.push(m),
212+
FatLTOInput::Serialized { name, buffer } => {
213+
info!("pushing serialized module {:?}", name);
214+
let buffer = SerializedModule::Local(buffer);
215+
serialized_modules.push((buffer, CString::new(name).unwrap()));
216+
}
217+
}
218+
}
219+
194220
// Find the "costliest" module and merge everything into that codegen unit.
195221
// All the other modules will be serialized and reparsed into the new
196222
// context, so this hopefully avoids serializing and parsing the largest
@@ -200,14 +226,8 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
200226
// file copy operations in the backend work correctly. The only other kind
201227
// of module here should be an allocator one, and if your crate is smaller
202228
// than the allocator module then the size doesn't really matter anyway.
203-
let costliest_module = modules.iter()
229+
let costliest_module = in_memory.iter()
204230
.enumerate()
205-
.filter_map(|(i, module)| {
206-
match module {
207-
FatLTOInput::InMemory(m) => Some((i, m)),
208-
FatLTOInput::Serialized { .. } => None,
209-
}
210-
})
211231
.filter(|&(_, module)| module.kind == ModuleKind::Regular)
212232
.map(|(i, module)| {
213233
let cost = unsafe {
@@ -223,26 +243,14 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
223243
// re-executing the LTO passes. If that's the case deserialize the first
224244
// module and create a linker with it.
225245
let module: ModuleCodegen<ModuleLlvm> = match costliest_module {
226-
Some((_cost, i)) => {
227-
match modules.remove(i) {
228-
FatLTOInput::InMemory(m) => m,
229-
FatLTOInput::Serialized { .. } => unreachable!(),
230-
}
231-
}
246+
Some((_cost, i)) => in_memory.remove(i),
232247
None => {
233-
let pos = modules.iter().position(|m| {
234-
match m {
235-
FatLTOInput::InMemory(_) => false,
236-
FatLTOInput::Serialized { .. } => true,
237-
}
238-
}).expect("must have at least one serialized module");
239-
let (name, buffer) = match modules.remove(pos) {
240-
FatLTOInput::Serialized { name, buffer } => (name, buffer),
241-
FatLTOInput::InMemory(_) => unreachable!(),
242-
};
248+
assert!(serialized_modules.len() > 0, "must have at least one serialized module");
249+
let (buffer, name) = serialized_modules.remove(0);
250+
info!("no in-memory regular modules to choose from, parsing {:?}", name);
243251
ModuleCodegen {
244-
module_llvm: ModuleLlvm::parse(cgcx, &name, &buffer, diag_handler)?,
245-
name,
252+
module_llvm: ModuleLlvm::parse(cgcx, &name, buffer.data(), diag_handler)?,
253+
name: name.into_string().unwrap(),
246254
kind: ModuleKind::Regular,
247255
}
248256
}
@@ -265,25 +273,13 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
265273
// and we want to move everything to the same LLVM context. Currently the
266274
// way we know of to do that is to serialize them to a string and them parse
267275
// them later. Not great but hey, that's why it's "fat" LTO, right?
268-
let mut new_modules = modules.into_iter().map(|module| {
269-
match module {
270-
FatLTOInput::InMemory(module) => {
271-
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
272-
let llmod_id = CString::new(&module.name[..]).unwrap();
273-
(SerializedModule::Local(buffer), llmod_id)
274-
}
275-
FatLTOInput::Serialized { name, buffer } => {
276-
let llmod_id = CString::new(name).unwrap();
277-
(SerializedModule::Local(buffer), llmod_id)
278-
}
279-
}
280-
}).collect::<Vec<_>>();
276+
for module in in_memory {
277+
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
278+
let llmod_id = CString::new(&module.name[..]).unwrap();
279+
serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
280+
}
281281
// Sort the modules to ensure we produce deterministic results.
282-
new_modules.sort_by(|module1, module2| module1.1.partial_cmp(&module2.1).unwrap());
283-
serialized_modules.extend(new_modules);
284-
serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| {
285-
(buffer, CString::new(wp.cgu_name).unwrap())
286-
}));
282+
serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1));
287283

288284
// For all serialized bitcode files we parse them and link them in as we did
289285
// above, this is all mostly handled in C++. Like above, though, we don't
@@ -850,7 +846,7 @@ fn module_name_to_str(c_str: &CStr) -> &str {
850846
bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e))
851847
}
852848

853-
fn parse_module<'a>(
849+
pub fn parse_module<'a>(
854850
cx: &'a llvm::Context,
855851
name: &CStr,
856852
data: &[u8],

src/librustc_codegen_llvm/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use syntax_pos::symbol::InternedString;
5454
pub use llvm_util::target_features;
5555
use std::any::Any;
5656
use std::sync::{mpsc, Arc};
57+
use std::ffi::CStr;
5758

5859
use rustc::dep_graph::DepGraph;
5960
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
@@ -386,13 +387,13 @@ impl ModuleLlvm {
386387

387388
fn parse(
388389
cgcx: &CodegenContext<LlvmCodegenBackend>,
389-
name: &str,
390-
buffer: &back::lto::ModuleBuffer,
390+
name: &CStr,
391+
buffer: &[u8],
391392
handler: &Handler,
392393
) -> Result<Self, FatalError> {
393394
unsafe {
394395
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
395-
let llmod_raw = buffer.parse(name, llcx, handler)?;
396+
let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?;
396397
let tm = match (cgcx.tm_factory.0)() {
397398
Ok(m) => m,
398399
Err(e) => {

0 commit comments

Comments
 (0)