Skip to content

Commit 9436eae

Browse files
authored
Merge pull request rust-lang#1403 from rust-lang/use_llvm_backend_as_assembler
Support and stabilize inline asm on all platforms
2 parents 6d30a7d + 69c6aa5 commit 9436eae

File tree

7 files changed

+99
-316
lines changed

7 files changed

+99
-316
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ smallvec = "1.8.1"
3535

3636
[features]
3737
# Enable features not ready to be enabled when compiling as part of rustc
38-
unstable-features = ["jit", "inline_asm"]
38+
unstable-features = ["jit", "inline_asm_sym"]
3939
jit = ["cranelift-jit", "libloading"]
40-
inline_asm = []
40+
inline_asm_sym = []
4141

4242
[package.metadata.rust-analyzer]
4343
rustc_private = true

scripts/setup_rust_fork.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ set -e
44
# Compiletest expects all standard library paths to start with /rustc/FAKE_PREFIX.
55
# CG_CLIF_STDLIB_REMAP_PATH_PREFIX will cause cg_clif's build system to pass
66
# --remap-path-prefix to handle this.
7-
CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build
7+
# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we
8+
# the LLVM backend isn't compiled in here.
9+
CG_CLIF_FORCE_GNU_AS=1 CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build
810

911
echo "[SETUP] Rust fork"
1012
git clone https://github.com/rust-lang/rust.git || true

scripts/test_bootstrap.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src}
1111
cp ../Cargo.* compiler/rustc_codegen_cranelift/
1212
cp -r ../src compiler/rustc_codegen_cranelift/src
1313

14-
./x.py build --stage 1 library/std
14+
# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we
15+
# the LLVM backend isn't compiled in here.
16+
CG_CLIF_FORCE_GNU_AS=1 ./x.py build --stage 1 library/std
1517
popd

src/global_asm.rs

+80-33
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
4646
global_asm.push_str(&string);
4747
}
4848
InlineAsmOperand::SymFn { anon_const } => {
49+
if cfg!(not(feature = "inline_asm_sym")) {
50+
tcx.sess.span_err(
51+
item.span,
52+
"asm! and global_asm! sym operands are not yet supported",
53+
);
54+
}
55+
4956
let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
5057
let instance = match ty.kind() {
5158
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
@@ -57,6 +64,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
5764
global_asm.push_str(symbol.name);
5865
}
5966
InlineAsmOperand::SymStatic { path: _, def_id } => {
67+
if cfg!(not(feature = "inline_asm_sym")) {
68+
tcx.sess.span_err(
69+
item.span,
70+
"asm! and global_asm! sym operands are not yet supported",
71+
);
72+
}
73+
6074
let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
6175
let symbol = tcx.symbol_name(instance);
6276
global_asm.push_str(symbol.name);
@@ -81,22 +95,23 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
8195
}
8296
}
8397

84-
pub(crate) fn asm_supported(tcx: TyCtxt<'_>) -> bool {
85-
cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows
86-
}
87-
8898
#[derive(Debug)]
8999
pub(crate) struct GlobalAsmConfig {
90-
asm_enabled: bool,
91100
assembler: PathBuf,
101+
target: String,
92102
pub(crate) output_filenames: Arc<OutputFilenames>,
93103
}
94104

95105
impl GlobalAsmConfig {
96106
pub(crate) fn new(tcx: TyCtxt<'_>) -> Self {
97107
GlobalAsmConfig {
98-
asm_enabled: asm_supported(tcx),
99108
assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"),
109+
target: match &tcx.sess.opts.target_triple {
110+
rustc_target::spec::TargetTriple::TargetTriple(triple) => triple.clone(),
111+
rustc_target::spec::TargetTriple::TargetJson { path_for_rustdoc, .. } => {
112+
path_for_rustdoc.to_str().unwrap().to_owned()
113+
}
114+
},
100115
output_filenames: tcx.output_filenames(()).clone(),
101116
}
102117
}
@@ -111,21 +126,6 @@ pub(crate) fn compile_global_asm(
111126
return Ok(None);
112127
}
113128

114-
if !config.asm_enabled {
115-
if global_asm.contains("__rust_probestack") {
116-
return Ok(None);
117-
}
118-
119-
if cfg!(not(feature = "inline_asm")) {
120-
return Err(
121-
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift"
122-
.to_owned(),
123-
);
124-
} else {
125-
return Err("asm! and global_asm! are not yet supported on Windows".to_owned());
126-
}
127-
}
128-
129129
// Remove all LLVM style comments
130130
let mut global_asm = global_asm
131131
.lines()
@@ -134,20 +134,67 @@ pub(crate) fn compile_global_asm(
134134
.join("\n");
135135
global_asm.push('\n');
136136

137-
let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
137+
let global_asm_object_file = add_file_stem_postfix(
138+
config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)),
139+
".asm",
140+
);
138141

139142
// Assemble `global_asm`
140-
let global_asm_object_file = add_file_stem_postfix(output_object_file, ".asm");
141-
let mut child = Command::new(&config.assembler)
142-
.arg("-o")
143-
.arg(&global_asm_object_file)
144-
.stdin(Stdio::piped())
145-
.spawn()
146-
.expect("Failed to spawn `as`.");
147-
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
148-
let status = child.wait().expect("Failed to wait for `as`.");
149-
if !status.success() {
150-
return Err(format!("Failed to assemble `{}`", global_asm));
143+
if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() {
144+
let mut child = Command::new(&config.assembler)
145+
.arg("-o")
146+
.arg(&global_asm_object_file)
147+
.stdin(Stdio::piped())
148+
.spawn()
149+
.expect("Failed to spawn `as`.");
150+
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
151+
let status = child.wait().expect("Failed to wait for `as`.");
152+
if !status.success() {
153+
return Err(format!("Failed to assemble `{}`", global_asm));
154+
}
155+
} else {
156+
let mut child = Command::new(std::env::current_exe().unwrap())
157+
.arg("--target")
158+
.arg(&config.target)
159+
.arg("--crate-type")
160+
.arg("staticlib")
161+
.arg("--emit")
162+
.arg("obj")
163+
.arg("-o")
164+
.arg(&global_asm_object_file)
165+
.arg("-")
166+
.arg("-Abad_asm_style")
167+
.arg("-Zcodegen-backend=llvm")
168+
.stdin(Stdio::piped())
169+
.spawn()
170+
.expect("Failed to spawn `as`.");
171+
let mut stdin = child.stdin.take().unwrap();
172+
stdin
173+
.write_all(
174+
br####"
175+
#![feature(decl_macro, no_core, rustc_attrs)]
176+
#![allow(internal_features)]
177+
#![no_core]
178+
#[rustc_builtin_macro]
179+
#[rustc_macro_transparency = "semitransparent"]
180+
macro global_asm() { /* compiler built-in */ }
181+
global_asm!(r###"
182+
"####,
183+
)
184+
.unwrap();
185+
stdin.write_all(global_asm.as_bytes()).unwrap();
186+
stdin
187+
.write_all(
188+
br####"
189+
"###);
190+
"####,
191+
)
192+
.unwrap();
193+
std::mem::drop(stdin);
194+
let status = child.wait().expect("Failed to wait for `as`.");
195+
if !status.success() {
196+
return Err(format!("Failed to assemble `{}`", global_asm));
197+
}
151198
}
152199

153200
Ok(Some(global_asm_object_file))

0 commit comments

Comments
 (0)