From a69770308c195c88c14c2e3ff98a1adeecb9990a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 9 Jun 2022 22:14:33 -0400 Subject: [PATCH 01/13] Add patch to allow testing stdarch --- ...1-Add-stdarch-Cargo.toml-for-testing.patch | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 patches/0001-Add-stdarch-Cargo.toml-for-testing.patch diff --git a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch new file mode 100644 index 000000000000..93c63b5dcacf --- /dev/null +++ b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch @@ -0,0 +1,39 @@ +From c3821e02fbd6cb5ad6e06d759fccdc9073712375 Mon Sep 17 00:00:00 2001 +From: Antoni Boucher +Date: Tue, 7 Jun 2022 21:40:13 -0400 +Subject: [PATCH] Add stdarch Cargo.toml for testing + +--- + library/stdarch/Cargo.toml | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + create mode 100644 library/stdarch/Cargo.toml + +diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml +new file mode 100644 +index 0000000..fbe0a95 +--- /dev/null ++++ b/library/stdarch/Cargo.toml +@@ -0,0 +1,20 @@ ++[workspace] ++members = [ ++ "crates/core_arch", ++ "crates/std_detect", ++ "crates/stdarch-gen", ++ "examples/" ++] ++exclude = [ ++ "crates/wasm-assert-instr-tests" ++] ++ ++[profile.release] ++debug = true ++opt-level = 3 ++incremental = true ++ ++[profile.bench] ++debug = 1 ++opt-level = 3 ++incremental = true +-- +2.26.2.7.g19db9cfb68.dirty + From 1777cdd644c67d82f306142ef77cce6f33719f54 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 9 Jun 2022 22:15:24 -0400 Subject: [PATCH 02/13] Add antoyo in TODOs --- src/intrinsic/simd.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 8f9862414e60..842b4a92080c 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -216,7 +216,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, let variable = bx.current_func().new_local(None, vector.get_type(), "new_vector"); bx.llbb().add_assignment(None, variable, vector); let lvalue = bx.context.new_vector_access(None, variable.to_rvalue(), index); - // TODO: if simd_insert is constant, use BIT_REF. + // TODO(antoyo): if simd_insert is constant, use BIT_REF. bx.llbb().add_assignment(None, lvalue, value); return Ok(variable.to_rvalue()); } @@ -545,9 +545,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, }, (true, true) => { // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition - // TODO: improve using conditional operators if possible. + // TODO(antoyo): improve using conditional operators if possible. let arg_type = lhs.get_type(); - // TODO: convert lhs and rhs to unsigned. + // TODO(antoyo): convert lhs and rhs to unsigned. let sum = lhs + rhs; let vector_type = arg_type.dyncast_vector().expect("vector type"); let unit = vector_type.get_num_units(); @@ -581,7 +581,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, // negative of the right operand. Find a proper subtraction algorithm. let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); - // TODO: convert lhs and rhs to unsigned. + // TODO(antoyo): convert lhs and rhs to unsigned. let sum = lhs + rhs; let vector_type = arg_type.dyncast_vector().expect("vector type"); let unit = vector_type.get_num_units(); From 910ec42566c08819de7732bea910fa53f99fd530 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 19 Jun 2022 18:58:08 -0400 Subject: [PATCH 03/13] Fixes to make stdarch tests compile --- src/base.rs | 22 ++++++++++++++++++++-- src/builder.rs | 2 +- src/common.rs | 14 ++++++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/base.rs b/src/base.rs index 19c981309d75..2f688fd66b2a 100644 --- a/src/base.rs +++ b/src/base.rs @@ -83,7 +83,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_ context.add_command_line_option("-mavx2"); // FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU. // Only add if the CPU supports it. - /*context.add_command_line_option("-mavx512f"); + context.add_command_line_option("-mavx512f"); context.add_command_line_option("-msha"); context.add_command_line_option("-mpclmul"); context.add_command_line_option("-mfma"); @@ -91,7 +91,25 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_ context.add_command_line_option("-mavx512vpopcntdq"); context.add_command_line_option("-mavx512vl"); context.add_command_line_option("-m64"); - context.add_command_line_option("-mbmi");*/ + context.add_command_line_option("-mbmi"); + context.add_command_line_option("-mgfni"); + context.add_command_line_option("-mavxvnni"); + context.add_command_line_option("-mavx512vnni"); + context.add_command_line_option("-mavx512bw"); + context.add_command_line_option("-mf16c"); + context.add_command_line_option("-mavx512bitalg"); + context.add_command_line_option("-maes"); + context.add_command_line_option("-mxsavec"); + context.add_command_line_option("-mbmi2"); + context.add_command_line_option("-mavx512bf16"); + context.add_command_line_option("-mrtm"); + context.add_command_line_option("-mvaes"); + context.add_command_line_option("-mvpclmulqdq"); + context.add_command_line_option("-mavx"); + context.add_command_line_option("-mavx512vbmi2"); + context.add_command_line_option("-mavx512vbmi"); + context.add_command_line_option("-mavx512ifma"); + context.add_command_line_option("-mavx512cd"); for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); } diff --git a/src/builder.rs b/src/builder.rs index 4aad171cb78e..08930387ccb2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -213,7 +213,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let actual_ty = actual_val.get_type(); if expected_ty != actual_ty { - if !actual_ty.is_vector() && !expected_ty.is_vector() && actual_ty.is_integral() && expected_ty.is_integral() { + if !actual_ty.is_vector() && !expected_ty.is_vector() && (actual_ty.is_integral() && expected_ty.is_integral()) || (actual_ty.get_pointee().is_some() && expected_ty.get_pointee().is_some()) { self.context.new_cast(None, actual_val, expected_ty) } else if on_stack_param_indices.contains(&index) { diff --git a/src/common.rs b/src/common.rs index ce341406eaf4..e0e35bea782b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -177,8 +177,18 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } let value = self.const_uint_big(self.type_ix(bitsize), data); - // TODO(bjorn3): assert size is correct - self.const_bitcast(value, ty) + let bytesize = layout.size(self).bytes(); + if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() { + // NOTE: since the intrinsic _xabort is called with a bitcast, which + // is non-const, but expects a constant, do a normal cast instead of a bitcast. + // FIXME(antoyo): fix bitcast to work in constant contexts. + // TODO: perhaps only use bitcast for pointers? + self.context.new_cast(None, value, ty) + } + else { + // TODO(bjorn3): assert size is correct + self.const_bitcast(value, ty) + } } Scalar::Ptr(ptr, _size) => { let (alloc_id, offset) = ptr.into_parts(); From 4094923789f99cc64b5a8c9353d232a22b820a93 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 19 Jun 2022 20:19:26 -0400 Subject: [PATCH 04/13] Disable avx512 --- src/base.rs | 22 +++++++++++----------- src/lib.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/base.rs b/src/base.rs index 2f688fd66b2a..943001423844 100644 --- a/src/base.rs +++ b/src/base.rs @@ -83,33 +83,33 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_ context.add_command_line_option("-mavx2"); // FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU. // Only add if the CPU supports it. - context.add_command_line_option("-mavx512f"); + //context.add_command_line_option("-mavx512f"); context.add_command_line_option("-msha"); context.add_command_line_option("-mpclmul"); context.add_command_line_option("-mfma"); context.add_command_line_option("-mfma4"); - context.add_command_line_option("-mavx512vpopcntdq"); - context.add_command_line_option("-mavx512vl"); + //context.add_command_line_option("-mavx512vpopcntdq"); + //context.add_command_line_option("-mavx512vl"); context.add_command_line_option("-m64"); context.add_command_line_option("-mbmi"); context.add_command_line_option("-mgfni"); context.add_command_line_option("-mavxvnni"); - context.add_command_line_option("-mavx512vnni"); - context.add_command_line_option("-mavx512bw"); + //context.add_command_line_option("-mavx512vnni"); + //context.add_command_line_option("-mavx512bw"); context.add_command_line_option("-mf16c"); - context.add_command_line_option("-mavx512bitalg"); + //context.add_command_line_option("-mavx512bitalg"); context.add_command_line_option("-maes"); context.add_command_line_option("-mxsavec"); context.add_command_line_option("-mbmi2"); - context.add_command_line_option("-mavx512bf16"); + //context.add_command_line_option("-mavx512bf16"); context.add_command_line_option("-mrtm"); context.add_command_line_option("-mvaes"); context.add_command_line_option("-mvpclmulqdq"); context.add_command_line_option("-mavx"); - context.add_command_line_option("-mavx512vbmi2"); - context.add_command_line_option("-mavx512vbmi"); - context.add_command_line_option("-mavx512ifma"); - context.add_command_line_option("-mavx512cd"); + //context.add_command_line_option("-mavx512vbmi2"); + //context.add_command_line_option("-mavx512vbmi"); + //context.add_command_line_option("-mavx512ifma"); + //context.add_command_line_option("-mavx512cd"); for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); } diff --git a/src/lib.rs b/src/lib.rs index b8db4c9540b7..f83c1e536357 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -304,7 +304,7 @@ pub fn target_features(sess: &Session) -> Vec { // Probably using the equivalent of __builtin_cpu_supports. #[cfg(feature="master")] { - _feature.contains("sse") || _feature.contains("avx") + (_feature.contains("sse") || _feature.contains("avx")) && !_feature.contains("avx512") } #[cfg(not(feature="master"))] { From 1c4ca283df4e918ce2fdba1c5826c957a8daad3d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 22 Jun 2022 17:48:54 -0400 Subject: [PATCH 05/13] Support #[target(enable)] function attribute --- Cargo.lock | 9 +++- Cargo.toml | 5 +- src/attributes.rs | 114 ++++++++++++++++++++++++++++++++++++++++++++++ src/base.rs | 28 +++++++----- src/callee.rs | 7 ++- src/declare.rs | 5 +- src/lib.rs | 22 +++++++++ src/mono_item.rs | 5 +- 8 files changed, 174 insertions(+), 21 deletions(-) create mode 100644 src/attributes.rs diff --git a/Cargo.lock b/Cargo.lock index 6df2102470fe..e52e742ec6ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,7 +41,6 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#bdb86fb5092895ff5589726b33250010c64d93f6" dependencies = [ "gccjit_sys", ] @@ -49,7 +48,6 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#bdb86fb5092895ff5589726b33250010c64d93f6" dependencies = [ "libc 0.1.12", ] @@ -215,6 +213,7 @@ dependencies = [ "ar", "gccjit", "lang_tester", + "smallvec", "target-lexicon", "tempfile", ] @@ -228,6 +227,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + [[package]] name = "target-lexicon" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index 211d19a8dc89..26a0e92923d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,11 +22,12 @@ default = ["master"] master = ["gccjit/master"] [dependencies] -gccjit = { git = "https://github.com/antoyo/gccjit.rs" } +#gccjit = { git = "https://github.com/antoyo/gccjit.rs" } # Local copy. -#gccjit = { path = "../gccjit.rs" } +gccjit = { path = "../gccjit.rs" } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } target-lexicon = "0.10.0" ar = "0.8.0" diff --git a/src/attributes.rs b/src/attributes.rs new file mode 100644 index 000000000000..c52b10ee20a8 --- /dev/null +++ b/src/attributes.rs @@ -0,0 +1,114 @@ +use gccjit::{FnAttribute, Function}; +use rustc_attr::InstructionSetAttr; +use rustc_codegen_ssa::target_features::tied_target_features; +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::ty; +use rustc_session::Session; +use rustc_span::symbol::sym; +use smallvec::{smallvec, SmallVec}; + +use crate::context::CodegenCx; + +// Given a map from target_features to whether they are enabled or disabled, +// ensure only valid combinations are allowed. +pub fn check_tied_features( + sess: &Session, + features: &FxHashMap<&str, bool>, +) -> Option<&'static [&'static str]> { + for tied in tied_target_features(sess) { + // Tied features must be set to the same value, or not set at all + let mut tied_iter = tied.iter(); + let enabled = features.get(tied_iter.next().unwrap()); + if tied_iter.any(|f| enabled != features.get(f)) { + return Some(tied); + } + } + None +} + +// TODO: maybe move to a new module gcc_util. +// To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { + let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; + match (arch, s) { + ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"], + ("x86", "pclmulqdq") => smallvec!["pclmul"], + ("x86", "rdrand") => smallvec!["rdrnd"], + ("x86", "bmi1") => smallvec!["bmi"], + ("x86", "cmpxchg16b") => smallvec!["cx16"], + ("x86", "avx512vaes") => smallvec!["vaes"], + ("x86", "avx512gfni") => smallvec!["gfni"], + ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], + // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'. + ("x86", "avx512vbmi2") => smallvec!["avx512vbmi2", "avx512bw"], + // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'. + ("x86", "avx512bitalg") => smallvec!["avx512bitalg", "avx512bw"], + ("aarch64", "rcpc2") => smallvec!["rcpc-immo"], + ("aarch64", "dpb") => smallvec!["ccpp"], + ("aarch64", "dpb2") => smallvec!["ccdp"], + ("aarch64", "frintts") => smallvec!["fptoint"], + ("aarch64", "fcma") => smallvec!["complxnum"], + ("aarch64", "pmuv3") => smallvec!["perfmon"], + ("aarch64", "paca") => smallvec!["pauth"], + ("aarch64", "pacg") => smallvec!["pauth"], + // Rust ties fp and neon together. In LLVM neon implicitly enables fp, + // but we manually enable neon when a feature only implicitly enables fp + ("aarch64", "f32mm") => smallvec!["f32mm", "neon"], + ("aarch64", "f64mm") => smallvec!["f64mm", "neon"], + ("aarch64", "fhm") => smallvec!["fp16fml", "neon"], + ("aarch64", "fp16") => smallvec!["fullfp16", "neon"], + ("aarch64", "jsconv") => smallvec!["jsconv", "neon"], + ("aarch64", "sve") => smallvec!["sve", "neon"], + ("aarch64", "sve2") => smallvec!["sve2", "neon"], + ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"], + ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"], + ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"], + ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"], + (_, s) => smallvec![s], + } +} + +/// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) +/// attributes. +pub fn from_fn_attrs<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + func: Function<'gcc>, + instance: ty::Instance<'tcx>, +) { + let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); + + let function_features = + codegen_fn_attrs.target_features.iter().map(|f| f.as_str()).collect::>(); + + if let Some(f) = check_tied_features(cx.tcx.sess, &function_features.iter().map(|f| (*f, true)).collect()) { + let span = cx.tcx + .get_attr(instance.def_id(), sym::target_feature) + .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); + let msg = format!( + "the target features {} must all be either enabled or disabled together", + f.join(", ") + ); + let mut err = cx.tcx.sess.struct_span_err(span, &msg); + err.help("add the missing features in a `target_feature` attribute"); + err.emit(); + return; + } + + let mut function_features = function_features + .iter() + .flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter()) + .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { + InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO: support removing feature. + InstructionSetAttr::ArmT32 => "thumb-mode", + })) + .collect::>(); + + // TODO(antoyo): check if we really need global backend features. (Maybe they could be applied + // globally?) + let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str()); + function_features.extend(&mut global_features); + let target_features = function_features.join(","); + if !target_features.is_empty() { + func.add_attribute(FnAttribute::Target, &target_features); + } +} diff --git a/src/base.rs b/src/base.rs index 943001423844..2f77978df1ed 100644 --- a/src/base.rs +++ b/src/base.rs @@ -79,37 +79,41 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_ // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); // TODO(antoyo): only add the following cli argument if the feature is supported. - context.add_command_line_option("-msse2"); + /*context.add_command_line_option("-msse2"); context.add_command_line_option("-mavx2"); // FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU. // Only add if the CPU supports it. - //context.add_command_line_option("-mavx512f"); context.add_command_line_option("-msha"); context.add_command_line_option("-mpclmul"); context.add_command_line_option("-mfma"); context.add_command_line_option("-mfma4"); - //context.add_command_line_option("-mavx512vpopcntdq"); - //context.add_command_line_option("-mavx512vl"); context.add_command_line_option("-m64"); context.add_command_line_option("-mbmi"); context.add_command_line_option("-mgfni"); context.add_command_line_option("-mavxvnni"); - //context.add_command_line_option("-mavx512vnni"); - //context.add_command_line_option("-mavx512bw"); context.add_command_line_option("-mf16c"); - //context.add_command_line_option("-mavx512bitalg"); context.add_command_line_option("-maes"); context.add_command_line_option("-mxsavec"); context.add_command_line_option("-mbmi2"); - //context.add_command_line_option("-mavx512bf16"); context.add_command_line_option("-mrtm"); context.add_command_line_option("-mvaes"); context.add_command_line_option("-mvpclmulqdq"); context.add_command_line_option("-mavx"); - //context.add_command_line_option("-mavx512vbmi2"); - //context.add_command_line_option("-mavx512vbmi"); - //context.add_command_line_option("-mavx512ifma"); - //context.add_command_line_option("-mavx512cd"); + + if env::var("CG_GCCJIT_ENABLE_AVX512").as_deref() == Ok("1") { + context.add_command_line_option("-mavx512f"); + context.add_command_line_option("-mavx512vpopcntdq"); + context.add_command_line_option("-mavx512vl"); + context.add_command_line_option("-mavx512vnni"); + context.add_command_line_option("-mavx512bw"); + context.add_command_line_option("-mavx512bitalg"); + context.add_command_line_option("-mavx512bf16"); + context.add_command_line_option("-mavx512vbmi2"); + context.add_command_line_option("-mavx512vbmi"); + context.add_command_line_option("-mavx512ifma"); + context.add_command_line_option("-mavx512cd"); + }*/ + for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); } diff --git a/src/callee.rs b/src/callee.rs index 76419b103d04..5557f886b287 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -4,6 +4,7 @@ use rustc_middle::ty::{self, Instance, TypeFoldable}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use crate::abi::FnAbiGccExt; +use crate::attributes; use crate::context::CodegenCx; /// Codegens a reference to a fn/method item, monomorphizing and @@ -67,8 +68,12 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) cx.linkage.set(FunctionType::Extern); let func = cx.declare_fn(&sym, &fn_abi); + attributes::from_fn_attrs(cx, func, instance); + // TODO(antoyo): set linkage and attributes. - func + + // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. + unsafe { std::mem::transmute(func) } }; cx.function_instances.borrow_mut().insert(instance, func); diff --git a/src/declare.rs b/src/declare.rs index a619e2f77125..5f6360a7da53 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -79,12 +79,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { unsafe { std::mem::transmute(func) } } - pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> { + pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self); let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, ¶ms, variadic); self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); - // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. - unsafe { std::mem::transmute(func) } + func } pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> LValue<'gcc> { diff --git a/src/lib.rs b/src/lib.rs index f83c1e536357..1ca2394abdc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ #![warn(unused_lifetimes)] extern crate rustc_ast; +extern crate rustc_attr; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; @@ -32,6 +33,7 @@ mod abi; mod allocator; mod archive; mod asm; +mod attributes; mod back; mod base; mod builder; @@ -188,6 +190,24 @@ pub struct GccContext { context: Context<'static>, } +impl GccContext { + fn new<'tcx>(tcx: TyCtxt<'tcx>) -> Self { + let context = create_context(tcx); + Self { + context, + } + } +} + +fn create_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { + let context = Context::default(); + if tcx.sess.target.is_builtin { + //let features = global_gcc_features(sess, false); + println!("Features: {:?}", tcx.sess.opts.cg.target_feature); + } + context +} + unsafe impl Send for GccContext {} // FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm". Try to disable it here. unsafe impl Sync for GccContext {} @@ -302,6 +322,8 @@ pub fn target_features(sess: &Session) -> Vec { .filter(|_feature| { // TODO(antoyo): implement a way to get enabled feature in libgccjit. // Probably using the equivalent of __builtin_cpu_supports. + // TODO: maybe use whatever outputs the following command: + // gcc -march=native -Q --help=target #[cfg(feature="master")] { (_feature.contains("sse") || _feature.contains("avx")) && !_feature.contains("avx512") diff --git a/src/mono_item.rs b/src/mono_item.rs index e21d40b6c37e..60a42846bd3d 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -5,6 +5,7 @@ use rustc_middle::ty::{self, Instance, TypeFoldable}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_span::def_id::DefId; +use crate::attributes; use crate::base; use crate::context::CodegenCx; use crate::type_of::LayoutGccExt; @@ -28,9 +29,11 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); - let _decl = self.declare_fn(symbol_name, &fn_abi); + let decl = self.declare_fn(symbol_name, &fn_abi); //let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); + attributes::from_fn_attrs(self, decl, instance); + // TODO(antoyo): call set_link_section() to allow initializing argc/argv. // TODO(antoyo): set unique comdat. // TODO(antoyo): use inline attribute from there in linkage.set() above. From 6205f1a0c590381bef30a6faf6bd55ba13d9c05a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 26 Jun 2022 11:00:04 -0400 Subject: [PATCH 06/13] Reenable target flags --- src/base.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base.rs b/src/base.rs index 2f77978df1ed..84d48d8591a7 100644 --- a/src/base.rs +++ b/src/base.rs @@ -79,7 +79,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_ // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); // TODO(antoyo): only add the following cli argument if the feature is supported. - /*context.add_command_line_option("-msse2"); + context.add_command_line_option("-msse2"); context.add_command_line_option("-mavx2"); // FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU. // Only add if the CPU supports it. @@ -112,7 +112,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_ context.add_command_line_option("-mavx512vbmi"); context.add_command_line_option("-mavx512ifma"); context.add_command_line_option("-mavx512cd"); - }*/ + } for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); From 9db55d2f54e869be328c2f0926786f8fd0ec84a4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 26 Jun 2022 14:28:06 -0400 Subject: [PATCH 07/13] Fix vector comparison now returning a vector of integers --- src/builder.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/builder.rs b/src/builder.rs index 08930387ccb2..867fd531f504 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1490,6 +1490,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let zeros = self.context.new_rvalue_from_vector(None, cond_type, &zeros); let masks = self.context.new_comparison(None, ComparisonOp::NotEquals, cond, zeros); + // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make + // the & operation work. + let masks = self.bitcast_if_needed(masks, then_val.get_type()); let then_vals = masks & then_val; let ones = vec![self.context.new_rvalue_one(element_type); num_units]; @@ -1509,6 +1512,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn difference_or_zero<'gcc>(a: RValue<'gcc>, b: RValue<'gcc>, context: &'gcc Context<'gcc>) -> RValue<'gcc> { let difference = a - b; let masks = context.new_comparison(None, ComparisonOp::GreaterThanEquals, b, a); + // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make + // the & operation work. + let a_type = a.get_type(); + let masks = + if masks.get_type() != a_type { + context.new_bitcast(None, masks, a_type) + } + else { + masks + }; difference & masks } From 85036a5afaa0fc7926c91e8d3f557661864833f1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 29 Jun 2022 21:05:40 -0400 Subject: [PATCH 08/13] Use gccjit from repo --- Cargo.lock | 2 ++ Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e52e742ec6ce..ff09a08b5afe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,6 +41,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" +source = "git+https://github.com/antoyo/gccjit.rs#a8997afb665dc467c1bdbddf04877143683f0cce" dependencies = [ "gccjit_sys", ] @@ -48,6 +49,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" +source = "git+https://github.com/antoyo/gccjit.rs#a8997afb665dc467c1bdbddf04877143683f0cce" dependencies = [ "libc 0.1.12", ] diff --git a/Cargo.toml b/Cargo.toml index 26a0e92923d5..3ac354ea4942 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ default = ["master"] master = ["gccjit/master"] [dependencies] -#gccjit = { git = "https://github.com/antoyo/gccjit.rs" } +gccjit = { git = "https://github.com/antoyo/gccjit.rs" } # Local copy. -gccjit = { path = "../gccjit.rs" } +#gccjit = { path = "../gccjit.rs" } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } target-lexicon = "0.10.0" From 16ca66d66439a29b38369e60ba7259b338fbedfc Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 29 Jun 2022 21:06:00 -0400 Subject: [PATCH 09/13] Fix build only --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 32fe8cf0586b..5258775a6d51 100755 --- a/test.sh +++ b/test.sh @@ -107,7 +107,7 @@ else fi if (( $build_only == 1 )); then - echo "Since it's `build-only`, exiting..." + echo "Since it's 'build-only', exiting..." exit fi From d19a5ea868968ddf1ad65fee1e7a85191388aa69 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 29 Jun 2022 21:10:20 -0400 Subject: [PATCH 10/13] Fix all command --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 5258775a6d51..594b63dfd0d8 100755 --- a/test.sh +++ b/test.sh @@ -324,7 +324,7 @@ function all() { } if [ ${#funcs[@]} -eq 0 ]; then - echo "No command passed, running `--all`..." + echo "No command passed, running '--all'..." all else for t in ${funcs[@]}; do From fea51f391ed91c487dda81d50389474b768441c7 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 29 Jun 2022 21:31:02 -0400 Subject: [PATCH 11/13] Fix warnings --- src/attributes.rs | 6 +++++- src/base.rs | 14 -------------- src/intrinsic/llvm.rs | 2 +- src/intrinsic/simd.rs | 4 +++- src/lib.rs | 18 ------------------ 5 files changed, 9 insertions(+), 35 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index c52b10ee20a8..c9ba0ecb877a 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -1,4 +1,6 @@ -use gccjit::{FnAttribute, Function}; +#[cfg_attr(not(feature="master"), allow(unused_imports))] +use gccjit::FnAttribute; +use gccjit::Function; use rustc_attr::InstructionSetAttr; use rustc_codegen_ssa::target_features::tied_target_features; use rustc_data_structures::fx::FxHashMap; @@ -72,6 +74,7 @@ fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, + #[cfg_attr(not(feature="master"), allow(unused_variables))] func: Function<'gcc>, instance: ty::Instance<'tcx>, ) { @@ -109,6 +112,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>( function_features.extend(&mut global_features); let target_features = function_features.join(","); if !target_features.is_empty() { + #[cfg(feature="master")] func.add_attribute(FnAttribute::Target, &target_features); } } diff --git a/src/base.rs b/src/base.rs index 84d48d8591a7..9d81a01e7a61 100644 --- a/src/base.rs +++ b/src/base.rs @@ -100,20 +100,6 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_ context.add_command_line_option("-mvpclmulqdq"); context.add_command_line_option("-mavx"); - if env::var("CG_GCCJIT_ENABLE_AVX512").as_deref() == Ok("1") { - context.add_command_line_option("-mavx512f"); - context.add_command_line_option("-mavx512vpopcntdq"); - context.add_command_line_option("-mavx512vl"); - context.add_command_line_option("-mavx512vnni"); - context.add_command_line_option("-mavx512bw"); - context.add_command_line_option("-mavx512bitalg"); - context.add_command_line_option("-mavx512bf16"); - context.add_command_line_option("-mavx512vbmi2"); - context.add_command_line_option("-mavx512vbmi"); - context.add_command_line_option("-mavx512ifma"); - context.add_command_line_option("-mavx512cd"); - } - for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); } diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index f623bc5fb10c..f00c1b301097 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -287,9 +287,9 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc, 'tcx>, mut return_value: RValue<'gcc>, func_name: &str, args: &[RValue<'gcc>], args_adjusted: bool) -> RValue<'gcc> { match func_name { "__builtin_ia32_vfmaddss3_round" | "__builtin_ia32_vfmaddsd3_round" => { - let zero = builder.context.new_rvalue_zero(builder.int_type); #[cfg(feature="master")] { + let zero = builder.context.new_rvalue_zero(builder.int_type); return_value = builder.context.new_vector_access(None, return_value, zero).to_rvalue(); } }, diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 842b4a92080c..9c2a1401a154 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -1,4 +1,6 @@ -use gccjit::{BinaryOp, RValue, Type, ToRValue, ComparisonOp, UnaryOp}; +#[cfg_attr(not(feature="master"), allow(unused_imports))] +use gccjit::{ToRValue, ComparisonOp, UnaryOp}; +use gccjit::{BinaryOp, RValue, Type}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{TypeKind, span_invalid_monomorphization_error}; use rustc_codegen_ssa::mir::operand::OperandRef; diff --git a/src/lib.rs b/src/lib.rs index 1ca2394abdc2..cb1d848eb670 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -190,24 +190,6 @@ pub struct GccContext { context: Context<'static>, } -impl GccContext { - fn new<'tcx>(tcx: TyCtxt<'tcx>) -> Self { - let context = create_context(tcx); - Self { - context, - } - } -} - -fn create_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { - let context = Context::default(); - if tcx.sess.target.is_builtin { - //let features = global_gcc_features(sess, false); - println!("Features: {:?}", tcx.sess.opts.cg.target_feature); - } - context -} - unsafe impl Send for GccContext {} // FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm". Try to disable it here. unsafe impl Sync for GccContext {} From b14b440f3aa54eb4a58d803a28fe19cf9abf7734 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 30 Jun 2022 17:19:01 -0400 Subject: [PATCH 12/13] Format --- src/attributes.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index c9ba0ecb877a..4937e475944c 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -13,15 +13,12 @@ use crate::context::CodegenCx; // Given a map from target_features to whether they are enabled or disabled, // ensure only valid combinations are allowed. -pub fn check_tied_features( - sess: &Session, - features: &FxHashMap<&str, bool>, -) -> Option<&'static [&'static str]> { +pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> { for tied in tied_target_features(sess) { // Tied features must be set to the same value, or not set at all let mut tied_iter = tied.iter(); let enabled = features.get(tied_iter.next().unwrap()); - if tied_iter.any(|f| enabled != features.get(f)) { + if tied_iter.any(|feature| enabled != features.get(feature)) { return Some(tied); } } @@ -81,16 +78,13 @@ pub fn from_fn_attrs<'gcc, 'tcx>( let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); let function_features = - codegen_fn_attrs.target_features.iter().map(|f| f.as_str()).collect::>(); + codegen_fn_attrs.target_features.iter().map(|features| features.as_str()).collect::>(); - if let Some(f) = check_tied_features(cx.tcx.sess, &function_features.iter().map(|f| (*f, true)).collect()) { + if let Some(features) = check_tied_features(cx.tcx.sess, &function_features.iter().map(|features| (*features, true)).collect()) { let span = cx.tcx .get_attr(instance.def_id(), sym::target_feature) .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); - let msg = format!( - "the target features {} must all be either enabled or disabled together", - f.join(", ") - ); + let msg = format!("the target features {} must all be either enabled or disabled together", features.join(", ")); let mut err = cx.tcx.sess.struct_span_err(span, &msg); err.help("add the missing features in a `target_feature` attribute"); err.emit(); From 5f4777e55da380a97336d09ca61ea615ef1dd315 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 6 Jul 2022 23:05:14 -0400 Subject: [PATCH 13/13] Add name in TODO --- src/attributes.rs | 4 ++-- src/common.rs | 2 +- src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index 4937e475944c..e570b583decb 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -25,7 +25,7 @@ pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> None } -// TODO: maybe move to a new module gcc_util. +// TODO(antoyo): maybe move to a new module gcc_util. // To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; @@ -95,7 +95,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>( .iter() .flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter()) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { - InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO: support removing feature. + InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO(antoyo): support removing feature. InstructionSetAttr::ArmT32 => "thumb-mode", })) .collect::>(); diff --git a/src/common.rs b/src/common.rs index e0e35bea782b..d55ad87e19bf 100644 --- a/src/common.rs +++ b/src/common.rs @@ -182,7 +182,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // NOTE: since the intrinsic _xabort is called with a bitcast, which // is non-const, but expects a constant, do a normal cast instead of a bitcast. // FIXME(antoyo): fix bitcast to work in constant contexts. - // TODO: perhaps only use bitcast for pointers? + // TODO(antoyo): perhaps only use bitcast for pointers? self.context.new_cast(None, value, ty) } else { diff --git a/src/lib.rs b/src/lib.rs index cb1d848eb670..b3cbf344ad13 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -304,7 +304,7 @@ pub fn target_features(sess: &Session) -> Vec { .filter(|_feature| { // TODO(antoyo): implement a way to get enabled feature in libgccjit. // Probably using the equivalent of __builtin_cpu_supports. - // TODO: maybe use whatever outputs the following command: + // TODO(antoyo): maybe use whatever outputs the following command: // gcc -march=native -Q --help=target #[cfg(feature="master")] {