Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 10 pull requests #135825

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cf34545
CI: build FreeBSD artifacts on FreeBSD 13.4
asomers Oct 27, 2024
0454d79
Fixup: fix clang command lines in another file
asomers Jan 12, 2025
b2b12ae
Add an example of using `carrying_mul_add` to write wider multiplication
scottmcm Jan 20, 2025
8dec09f
support wasm inline assembly in naked functions
folkertdev Jan 15, 2025
bcf478b
work around the `wasm32-unknown-unknown` ABI being broken
folkertdev Jan 17, 2025
a175e8d
CI: free disk on linux arm runner
marcoieni Jan 20, 2025
9d6a1c9
Shorten linker output even more when `--verbose` is not present
jyn514 Jan 18, 2025
9d88b82
Ignore `mermaid.min.js`
jyn514 Jan 20, 2025
51af4d6
Add Kobzol on vacation
Kobzol Jan 21, 2025
00381ea
Make it possible to build GCC on CI
Kobzol Jan 2, 2025
cd9dcfc
ci: use ghcr buildkit image
marcoieni Jan 21, 2025
587b9c6
[cfg_match] Document the use of expressions
c410-f3r Jan 21, 2025
047e679
Rollup merge of #132232 - asomers:fbsd-13.4, r=Mark-Simulacrum
jieyouxu Jan 21, 2025
b4e2fb5
Rollup merge of #135625 - c410-f3r:cfg-match-foo-bar-baz, r=tgross35,…
jieyouxu Jan 21, 2025
3753fbf
Rollup merge of #135638 - Kobzol:gcc-ci, r=onur-ozkan
jieyouxu Jan 21, 2025
8395924
Rollup merge of #135648 - folkertdev:naked-asm-wasm, r=bjorn3
jieyouxu Jan 21, 2025
89d5c81
Rollup merge of #135707 - jyn514:linker-messages-2, r=bjorn3
jieyouxu Jan 21, 2025
dbc4adb
Rollup merge of #135750 - scottmcm:cma-example, r=cuviper
jieyouxu Jan 21, 2025
8d3906b
Rollup merge of #135779 - marcoieni:free-disk-arm-runner, r=Kobzol
jieyouxu Jan 21, 2025
e1b5523
Rollup merge of #135793 - jyn514:gitignore, r=jieyouxu
jieyouxu Jan 21, 2025
3370a20
Rollup merge of #135810 - Kobzol:kobzol-parental-leave, r=Kobzol
jieyouxu Jan 21, 2025
fde77e9
Rollup merge of #135814 - marcoieni:use-buildkit-ghcr, r=Kobzol
jieyouxu Jan 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ __pycache__/
node_modules
package-lock.json
package.json
/src/doc/rustc-dev-guide/mermaid.min.js

## Rustdoc GUI tests
tests/rustdoc-gui/src/**.lock
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3537,6 +3537,7 @@ dependencies = [
"ar_archive_writer",
"arrayvec",
"bitflags",
"bstr",
"cc",
"either",
"itertools",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
ar_archive_writer = "0.4.2"
arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
bstr = "1.11.3"
# Pinned so `cargo update` bumps don't cause breakage. Please also update the
# `cc` in `rustc_llvm` if you update the `cc` here.
cc = "=1.2.7"
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub(crate) struct Command {
args: Vec<OsString>,
env: Vec<(OsString, OsString)>,
env_remove: Vec<OsString>,
env_clear: bool,
}

#[derive(Clone)]
Expand All @@ -36,7 +37,13 @@ impl Command {
}

fn _new(program: Program) -> Command {
Command { program, args: Vec::new(), env: Vec::new(), env_remove: Vec::new() }
Command {
program,
args: Vec::new(),
env: Vec::new(),
env_remove: Vec::new(),
env_clear: false,
}
}

pub(crate) fn arg<P: AsRef<OsStr>>(&mut self, arg: P) -> &mut Command {
Expand Down Expand Up @@ -79,6 +86,11 @@ impl Command {
self
}

pub(crate) fn env_clear(&mut self) -> &mut Command {
self.env_clear = true;
self
}

fn _env_remove(&mut self, key: &OsStr) {
self.env_remove.push(key.to_owned());
}
Expand Down Expand Up @@ -106,6 +118,9 @@ impl Command {
for k in &self.env_remove {
ret.env_remove(k);
}
if self.env_clear {
ret.env_clear();
}
ret
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@ fn link_natively(
command: cmd,
escaped_output,
verbose: sess.opts.verbose,
sysroot_dir: sess.sysroot.clone(),
};
sess.dcx().emit_err(err);
// If MSVC's `link.exe` was expected but the return code
Expand Down
62 changes: 47 additions & 15 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ pub(crate) struct LinkingFailed<'a> {
pub command: Command,
pub escaped_output: String,
pub verbose: bool,
pub sysroot_dir: PathBuf,
}

impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
Expand All @@ -364,6 +365,8 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
if self.verbose {
diag.note(format!("{:?}", self.command));
} else {
self.command.env_clear();

enum ArgGroup {
Regular(OsString),
Objects(usize),
Expand Down Expand Up @@ -398,26 +401,55 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
args.push(ArgGroup::Regular(arg));
}
}
self.command.args(args.into_iter().map(|arg_group| match arg_group {
ArgGroup::Regular(arg) => arg,
ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")),
ArgGroup::Rlibs(dir, rlibs) => {
let mut arg = dir.into_os_string();
arg.push("/{");
let mut first = true;
for rlib in rlibs {
if !first {
arg.push(",");
let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+\.rlib$").unwrap();
self.command.args(args.into_iter().map(|arg_group| {
match arg_group {
// SAFETY: we are only matching on ASCII, not any surrogate pairs, so any replacements we do will still be valid.
ArgGroup::Regular(arg) => unsafe {
use bstr::ByteSlice;
OsString::from_encoded_bytes_unchecked(
arg.as_encoded_bytes().replace(
self.sysroot_dir.as_os_str().as_encoded_bytes(),
b"<sysroot>",
),
)
},
ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")),
ArgGroup::Rlibs(mut dir, rlibs) => {
let is_sysroot_dir = match dir.strip_prefix(&self.sysroot_dir) {
Ok(short) => {
dir = Path::new("<sysroot>").join(short);
true
}
Err(_) => false,
};
let mut arg = dir.into_os_string();
arg.push("/{");
let mut first = true;
for mut rlib in rlibs {
if !first {
arg.push(",");
}
first = false;
if is_sysroot_dir {
// SAFETY: Regex works one byte at a type, and our regex will not match surrogate pairs (because it only matches ascii).
rlib = unsafe {
OsString::from_encoded_bytes_unchecked(
crate_hash
.replace(rlib.as_encoded_bytes(), b"-*")
.into_owned(),
)
};
}
arg.push(rlib);
}
first = false;
arg.push(rlib);
arg.push("}.rlib");
arg
}
arg.push("}");
arg
}
}));

diag.note(format!("{:?}", self.command));
diag.note(format!("{:?}", self.command).trim_start_matches("env -i").to_owned());
diag.note("some arguments are omitted. use `--verbose` to show all linker arguments");
}

Expand Down
173 changes: 168 additions & 5 deletions compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
use rustc_attr_parsing::InstructionSetAttr;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
use rustc_middle::mir::{Body, InlineAsmOperand};
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{Instance, TyCtxt};
use rustc_middle::{bug, ty};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug, ty};
use rustc_span::sym;
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
use rustc_target::spec::WasmCAbi;

use crate::common;
use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods};
Expand Down Expand Up @@ -32,7 +36,8 @@ pub(crate) fn codegen_naked_asm<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

let item_data = cx.codegen_unit().items().get(&MonoItem::Fn(instance)).unwrap();
let name = cx.mangled_name(instance);
let (begin, end) = prefix_and_suffix(cx.tcx(), instance, &name, item_data);
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
let (begin, end) = prefix_and_suffix(cx.tcx(), instance, &name, item_data, fn_abi);

let mut template_vec = Vec::new();
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(begin.into()));
Expand Down Expand Up @@ -103,6 +108,7 @@ enum AsmBinaryFormat {
Elf,
Macho,
Coff,
Wasm,
}

impl AsmBinaryFormat {
Expand All @@ -111,6 +117,8 @@ impl AsmBinaryFormat {
Self::Coff
} else if target.is_like_osx {
Self::Macho
} else if target.is_like_wasm {
Self::Wasm
} else {
Self::Elf
}
Expand All @@ -122,6 +130,7 @@ fn prefix_and_suffix<'tcx>(
instance: Instance<'tcx>,
asm_name: &str,
item_data: &MonoItemData,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> (String, String) {
use std::fmt::Write;

Expand Down Expand Up @@ -169,7 +178,7 @@ fn prefix_and_suffix<'tcx>(
}
Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR => {
match asm_binary_format {
AsmBinaryFormat::Elf | AsmBinaryFormat::Coff => {
AsmBinaryFormat::Elf | AsmBinaryFormat::Coff | AsmBinaryFormat::Wasm => {
writeln!(w, ".weak {asm_name}")?;
}
AsmBinaryFormat::Macho => {
Expand Down Expand Up @@ -264,7 +273,161 @@ fn prefix_and_suffix<'tcx>(
writeln!(end, "{}", arch_suffix).unwrap();
}
}
AsmBinaryFormat::Wasm => {
let section = link_section.unwrap_or(format!(".text.{asm_name}"));

writeln!(begin, ".section {section},\"\",@").unwrap();
// wasm functions cannot be aligned, so skip
write_linkage(&mut begin).unwrap();
if let Visibility::Hidden = item_data.visibility {
writeln!(begin, ".hidden {asm_name}").unwrap();
}
writeln!(begin, ".type {asm_name}, @function").unwrap();
if !arch_prefix.is_empty() {
writeln!(begin, "{}", arch_prefix).unwrap();
}
writeln!(begin, "{asm_name}:").unwrap();
writeln!(
begin,
".functype {asm_name} {}",
wasm_functype(tcx, fn_abi, instance.def_id())
)
.unwrap();

writeln!(end).unwrap();
// .size is ignored for function symbols, so we can skip it
writeln!(end, "end_function").unwrap();
}
}

(begin, end)
}

/// The webassembly type signature for the given function.
///
/// Used by the `.functype` directive on wasm targets.
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId) -> String {
let mut signature = String::with_capacity(64);

let ptr_type = match tcx.data_layout.pointer_size.bits() {
32 => "i32",
64 => "i64",
other => bug!("wasm pointer size cannot be {other} bits"),
};

// FIXME: remove this once the wasm32-unknown-unknown ABI is fixed
// please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
// basically the commit introducing this comment should be reverted
if let PassMode::Pair { .. } = fn_abi.ret.mode {
let _ = WasmCAbi::Legacy;
span_bug!(
tcx.def_span(def_id),
"cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
);
}

let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });

signature.push('(');

if hidden_return {
signature.push_str(ptr_type);
if !fn_abi.args.is_empty() {
signature.push_str(", ");
}
}

let mut it = fn_abi.args.iter().peekable();
while let Some(arg_abi) = it.next() {
wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id);
if it.peek().is_some() {
signature.push_str(", ");
}
}

signature.push_str(") -> (");

if !hidden_return {
wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id);
}

signature.push(')');

signature
}

fn wasm_type<'tcx>(
tcx: TyCtxt<'tcx>,
signature: &mut String,
arg_abi: &ArgAbi<'_, Ty<'tcx>>,
ptr_type: &'static str,
def_id: DefId,
) {
match arg_abi.mode {
PassMode::Ignore => { /* do nothing */ }
PassMode::Direct(_) => {
let direct_type = match arg_abi.layout.backend_repr {
BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type),
BackendRepr::Vector { .. } => "v128",
BackendRepr::Memory { .. } => {
// FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
let _ = WasmCAbi::Legacy;
span_bug!(
tcx.def_span(def_id),
"cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
);
}
other => unreachable!("unexpected BackendRepr: {:?}", other),
};

signature.push_str(direct_type);
}
PassMode::Pair(_, _) => match arg_abi.layout.backend_repr {
BackendRepr::ScalarPair(a, b) => {
signature.push_str(wasm_primitive(a.primitive(), ptr_type));
signature.push_str(", ");
signature.push_str(wasm_primitive(b.primitive(), ptr_type));
}
other => unreachable!("{other:?}"),
},
PassMode::Cast { pad_i32, ref cast } => {
// For wasm, Cast is used for single-field primitive wrappers like `struct Wrapper(i64);`
assert!(!pad_i32, "not currently used by wasm calling convention");
assert!(cast.prefix[0].is_none(), "no prefix");
assert_eq!(cast.rest.total, arg_abi.layout.size, "single item");

let wrapped_wasm_type = match cast.rest.unit.kind {
RegKind::Integer => match cast.rest.unit.size.bytes() {
..=4 => "i32",
..=8 => "i64",
_ => ptr_type,
},
RegKind::Float => match cast.rest.unit.size.bytes() {
..=4 => "f32",
..=8 => "f64",
_ => ptr_type,
},
RegKind::Vector => "v128",
};

signature.push_str(wrapped_wasm_type);
}
PassMode::Indirect { .. } => signature.push_str(ptr_type),
}
}

fn wasm_primitive(primitive: Primitive, ptr_type: &'static str) -> &'static str {
match primitive {
Primitive::Int(integer, _) => match integer {
Integer::I8 | Integer::I16 | Integer::I32 => "i32",
Integer::I64 => "i64",
Integer::I128 => "i64, i64",
},
Primitive::Float(float) => match float {
Float::F16 | Float::F32 => "f32",
Float::F64 => "f64",
Float::F128 => "i64, i64",
},
Primitive::Pointer(_) => ptr_type,
}
}
Loading
Loading