diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index f3e07fd08ee8e..60a2101c689cc 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -25,9 +25,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cfg-if" @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#54be27e41fff7b6ab532e2e21a82df50a12b9ad3" +source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" dependencies = [ "gccjit_sys", ] @@ -64,7 +64,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#54be27e41fff7b6ab532e2e21a82df50a12b9ad3" +source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" dependencies = [ "libc 0.1.12", ] @@ -85,7 +85,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", - "libc 0.2.98", + "libc 0.2.102", "wasi", ] @@ -101,7 +101,7 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc 0.2.98", + "libc 0.2.102", ] [[package]] @@ -122,7 +122,7 @@ checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090" dependencies = [ "fm", "getopts", - "libc 0.2.98", + "libc 0.2.102", "num_cpus", "termcolor", "threadpool", @@ -138,15 +138,15 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "num_cpus" @@ -155,7 +155,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", - "libc 0.2.98", + "libc 0.2.102", ] [[package]] @@ -181,7 +181,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ - "libc 0.2.98", + "libc 0.2.102", "rand_chacha", "rand_core", "rand_hc", @@ -217,9 +217,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -284,7 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if", - "libc 0.2.98", + "libc 0.2.102", "rand", "redox_syscall", "remove_dir_all", @@ -311,9 +311,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "wait-timeout" @@ -321,7 +321,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ - "libc 0.2.98", + "libc 0.2.102", ] [[package]] diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index 1f27d721fabbb..709d93c6edb05 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -115,3 +115,21 @@ p loc->m_line * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. + +### How to build a cross-compiling libgccjit + +#### Building libgccjit + + * Follow these instructions: https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ with the following changes: + * Configure gcc with `../gcc/configure --enable-host-shared --disable-multilib --enable-languages=c,jit,c++ --disable-bootstrap --enable-checking=release --prefix=/opt/m68k-gcc/ --target=m68k-linux --without-headers`. + * Some shells, like fish, don't define the environment variable `$MACHTYPE`. + * Add `CFLAGS="-Wno-error=attributes -g -O2"` at the end of the configure command for building glibc (`CFLAGS="-Wno-error=attributes -Wno-error=array-parameter -Wno-error=stringop-overflow -Wno-error=array-bounds -g -O2"` for glibc 2.31, which is useful for Debian). + +#### Configuring rustc_codegen_gcc + + * Set `TARGET_TRIPLE="m68k-unknown-linux-gnu"` in config.sh. + * Since rustc doesn't support this architecture yet, set it back to `TARGET_TRIPLE="mips-unknown-linux-gnu"` (or another target having the same attributes). Alternatively, create a [target specification file](https://book.avr-rust.com/005.1-the-target-specification-json-file.html) (note that the `arch` specified in this file must be supported by the rust compiler). + * Set `linker='-Clinker=m68k-linux-gcc'`. + * Set the path to the cross-compiling libgccjit in `gcc_path`. + * Disable the 128-bit integer types if the target doesn't support them by using `let i128_type = context.new_type::();` in `context.rs` (same for u128_type). + * (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?). diff --git a/compiler/rustc_codegen_gcc/config.sh b/compiler/rustc_codegen_gcc/config.sh index 98caeb7407e08..87df2f2102bcd 100644 --- a/compiler/rustc_codegen_gcc/config.sh +++ b/compiler/rustc_codegen_gcc/config.sh @@ -21,12 +21,15 @@ fi HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ") TARGET_TRIPLE=$HOST_TRIPLE -#TARGET_TRIPLE="aarch64-unknown-linux-gnu" +#TARGET_TRIPLE="m68k-unknown-linux-gnu" linker='' RUN_WRAPPER='' if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - if [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then + if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then + TARGET_TRIPLE="mips-unknown-linux-gnu" + linker='-Clinker=m68k-linux-gcc' + elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. linker='-Clinker=aarch64-linux-gnu-gcc' RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu' @@ -35,7 +38,7 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then fi fi -export RUSTFLAGS="$linker -Cpanic=abort -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot" +export RUSTFLAGS="$linker -Cpanic=abort -Zsymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot" # FIXME(antoyo): remove once the atomic shim is gone if [[ `uname` == 'Darwin' ]]; then diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain index a03d26c0467e1..d311a33f807b7 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -1 +1 @@ -nightly-2021-09-17 +nightly-2021-09-28 diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index a684c34b64410..3b77097e9ad00 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -6,7 +6,7 @@ use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods, use rustc_hir::LlvmInlineAsmInner; use rustc_middle::{bug, ty::Instance}; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use rustc_target::asm::*; use std::borrow::Cow; @@ -173,7 +173,20 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { continue }, (Register(reg_name), None) => { - clobbers.push(reg_name); + // `clobber_abi` can add lots of clobbers that are not supported by the target, + // such as AVX-512 registers, so we just ignore unsupported registers + let is_target_supported = reg.reg_class().supported_types(asm_arch).iter() + .any(|&(_, feature)| { + if let Some(feature) = feature { + self.tcx.sess.target_features.contains(&Symbol::intern(feature)) + } else { + true // Register class is unconditionally supported + } + }); + + if is_target_supported && !clobbers.contains(®_name) { + clobbers.push(reg_name); + } continue } }; @@ -526,16 +539,20 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { let constraint = match reg { // For vector registers LLVM wants the register name to match the type size. InlineAsmRegOrRegClass::Reg(reg) => { - // TODO(antoyo): add support for vector register. - match reg.name() { - "ax" => "a", - "bx" => "b", - "cx" => "c", - "dx" => "d", - "si" => "S", - "di" => "D", - // For registers like r11, we have to create a register variable: https://stackoverflow.com/a/31774784/389119 - name => return ConstraintOrRegister::Register(name), + match reg { + InlineAsmReg::X86(_) => { + // TODO(antoyo): add support for vector register. + // + // // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119 + return ConstraintOrRegister::Register(match reg.name() { + // Some of registers' names does not map 1-1 from rust to gcc + "st(0)" => "st", + + name => name, + }); + } + + _ => unimplemented!(), } }, InlineAsmRegOrRegClass::RegClass(reg) => match reg { diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 2963a3d49a20e..9fd043607fc7e 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -1,5 +1,4 @@ use std::env; -use std::sync::Once; use std::time::Instant; use gccjit::{ @@ -7,7 +6,6 @@ use gccjit::{ FunctionType, GlobalKind, }; -use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::dep_graph; use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::middle::exported_symbols; @@ -20,7 +18,7 @@ use rustc_codegen_ssa::traits::DebugInfoMethods; use rustc_session::config::DebugInfo; use rustc_span::Symbol; -use crate::{GccContext, create_function_calling_initializers}; +use crate::GccContext; use crate::builder::Builder; use crate::context::CodegenCx; @@ -97,15 +95,6 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul { let cx = CodegenCx::new(&context, cgu, tcx); - static START: Once = Once::new(); - START.call_once(|| { - let initializer_name = format!("__gccGlobalCrateInit{}", tcx.crate_name(LOCAL_CRATE)); - let func = context.new_function(None, FunctionType::Exported, context.new_type::<()>(), &[], initializer_name, false); - let block = func.new_block("initial"); - create_function_calling_initializers(tcx, &context, block); - block.end_with_void_return(None); - }); - let mono_items = cgu.items_in_deterministic_order(tcx); for &(mono_item, (linkage, visibility)) in &mono_items { mono_item.predefine::>(&cx, linkage, visibility); @@ -124,8 +113,6 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul if cx.sess().opts.debuginfo != DebugInfo::None { cx.debuginfo_finalize(); } - - cx.global_init_block.end_with_void_return(None); } ModuleCodegen { diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 5d06d71953c66..ac908418ee4bf 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -31,11 +31,12 @@ use rustc_codegen_ssa::traits::{ StaticBuilderMethods, }; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_span::Span; use rustc_span::def_id::DefId; use rustc_target::abi::{ self, + call::FnAbi, Align, HasDataLayout, Size, @@ -347,6 +348,20 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { } } +impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + self.cx.handle_fn_abi_err(err, span, fn_abi_request) + } +} + impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> { type Target = CodegenCx<'gcc, 'tcx>; @@ -505,7 +520,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they // should be the same. let typ = a.get_type().to_signed(self); - let a = self.context.new_cast(None, a, typ); let b = self.context.new_cast(None, b, typ); a / b } @@ -1052,11 +1066,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } /* Comparisons */ - fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { - if lhs.get_type() != rhs.get_type() { + fn icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { + let left_type = lhs.get_type(); + let right_type = rhs.get_type(); + if left_type != right_type { + // NOTE: because libgccjit cannot compare function pointers. + if left_type.is_function_ptr_type().is_some() && right_type.is_function_ptr_type().is_some() { + lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer()); + rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer()); + } // NOTE: hack because we try to cast a vector type to the same vector type. - if format!("{:?}", lhs.get_type()) != format!("{:?}", rhs.get_type()) { - rhs = self.context.new_cast(None, rhs, lhs.get_type()); + else if format!("{:?}", left_type) != format!("{:?}", right_type) { + rhs = self.context.new_cast(None, rhs, left_type); } } self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) @@ -1210,6 +1231,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { else { panic!("Unexpected type {:?}", value_type); }; + + let lvalue_type = lvalue.to_rvalue().get_type(); + let value = + // NOTE: sometimes, rustc will create a value with the wrong type. + if lvalue_type != value.get_type() { + self.context.new_cast(None, value, lvalue_type) + } + else { + value + }; + self.llbb().add_assignment(None, lvalue, value); aggregate_value @@ -1413,7 +1445,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> { fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> { // Forward to the `get_static` method of `CodegenCx` - self.cx().get_static(def_id) + self.cx().get_static(def_id).get_address(None) } } diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs index e402e0e91f133..76419b103d049 100644 --- a/compiler/rustc_codegen_gcc/src/callee.rs +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -1,8 +1,7 @@ use gccjit::{FunctionType, RValue}; use rustc_codegen_ssa::traits::BaseTypeMethods; -use rustc_middle::ty::{Instance, TypeFoldable}; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; -use rustc_target::abi::call::FnAbi; +use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use crate::abi::FnAbiGccExt; use crate::context::CodegenCx; @@ -20,13 +19,13 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) assert!(!instance.substs.needs_infer()); assert!(!instance.substs.has_escaping_bound_vars()); - if let Some(&func) = cx.instances.borrow().get(&instance) { + if let Some(&func) = cx.function_instances.borrow().get(&instance) { return func; } let sym = tcx.symbol_name(instance).name; - let fn_abi = FnAbi::of_instance(cx, instance, &[]); + let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); let func = if let Some(func) = cx.get_declared_value(&sym) { @@ -72,7 +71,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) func }; - cx.instances.borrow_mut().insert(instance, func); + cx.function_instances.borrow_mut().insert(instance, func); func } diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index a24fe0df911a6..bda08b653f059 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -1,6 +1,7 @@ use std::convert::TryFrom; use std::convert::TryInto; +use gccjit::LValue; use gccjit::{Block, CType, RValue, Type, ToRValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ @@ -10,7 +11,6 @@ use rustc_codegen_ssa::traits::{ MiscMethods, StaticMethods, }; -use rustc_middle::bug; use rustc_middle::mir::Mutability; use rustc_middle::ty::ScalarInt; use rustc_middle::ty::layout::{TyAndLayout, LayoutOf}; @@ -27,28 +27,25 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { bytes_in_context(self, bytes) } - fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> RValue<'gcc> { + fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> LValue<'gcc> { // TODO(antoyo): handle null_terminated. if let Some(&value) = self.const_cstr_cache.borrow().get(&symbol) { - return value.to_rvalue(); + return value; } let global = self.global_string(&*symbol.as_str()); - self.const_cstr_cache.borrow_mut().insert(symbol, global.dereference(None)); + self.const_cstr_cache.borrow_mut().insert(symbol, global); global } - fn global_string(&self, string: &str) -> RValue<'gcc> { + fn global_string(&self, string: &str) -> LValue<'gcc> { // TODO(antoyo): handle non-null-terminated strings. let string = self.context.new_string_literal(&*string); let sym = self.generate_local_symbol_name("str"); - // NOTE: TLS is always off for a string litteral. - // NOTE: string litterals do not have a link section. - let global = self.define_global(&sym, self.val_ty(string), false, None) - .unwrap_or_else(|| bug!("symbol `{}` is already defined", sym)); - self.global_init_block.add_assignment(None, global.dereference(None), string); - global.to_rvalue() + let global = self.declare_private_global(&sym, self.val_ty(string)); + global.global_set_initializer_value(string); + global // TODO(antoyo): set linkage. } @@ -76,10 +73,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> { let context = &cx.context; - let typ = context.new_array_type(None, context.new_type::(), bytes.len() as i32); - let global = cx.declare_unnamed_global(typ); - global.global_set_initializer(bytes); - global.to_rvalue() + let byte_type = context.new_type::(); + let typ = context.new_array_type(None, byte_type, bytes.len() as i32); + let elements: Vec<_> = + bytes.iter() + .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) + .collect(); + context.new_rvalue_from_array(None, typ, &elements) } pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool { @@ -180,7 +180,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn const_str(&self, s: Symbol) -> (RValue<'gcc>, RValue<'gcc>) { let len = s.as_str().len(); - let cs = self.const_ptrcast(self.const_cstr(s, false), + let cs = self.const_ptrcast(self.const_cstr(s, false).get_address(None), self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self, true)), ); (cs, self.const_usize(len as u64)) @@ -191,16 +191,9 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { .map(|value| value.get_type()) .collect(); // TODO(antoyo): cache the type? It's anonymous, so probably not. - let name = fields.iter().map(|typ| format!("{:?}", typ)).collect::>().join("_"); let typ = self.type_struct(&fields, packed); - let structure = self.global_init_func.new_local(None, typ, &name); let struct_type = typ.is_struct().expect("struct type"); - for (index, value) in values.iter().enumerate() { - let field = struct_type.get_field(index as i32); - let field_lvalue = structure.access_field(None, field); - self.global_init_block.add_assignment(None, field_lvalue, *value); - } - self.lvalue_to_rvalue(structure) + self.context.new_rvalue_from_struct(None, struct_type, values) } fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option { @@ -260,19 +253,18 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { }, GlobalAlloc::Static(def_id) => { assert!(self.tcx.is_static(def_id)); - self.get_static(def_id) + self.get_static(def_id).get_address(None) }, }; let ptr_type = base_addr.get_type(); let base_addr = self.const_bitcast(base_addr, self.usize_type); let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64); let ptr = self.const_bitcast(base_addr + offset, ptr_type); - let value = ptr.dereference(None); if layout.value != Pointer { - self.const_bitcast(value.to_rvalue(), ty) + self.const_bitcast(ptr.dereference(None).to_rvalue(), ty) } else { - self.const_bitcast(value.get_address(None), ty) + self.const_bitcast(ptr, ty) } } } @@ -310,6 +302,7 @@ pub trait SignType<'gcc, 'tcx> { fn is_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; fn is_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; fn to_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; + fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; } impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> { @@ -341,6 +334,27 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> { self.clone() } } + + fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + if self.is_i8(cx) { + cx.u8_type + } + else if self.is_i16(cx) { + cx.u16_type + } + else if self.is_i32(cx) { + cx.u32_type + } + else if self.is_i64(cx) { + cx.u64_type + } + else if self.is_i128(cx) { + cx.u128_type + } + else { + self.clone() + } + } } pub trait TypeReflection<'gcc, 'tcx> { diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index df13fa79f0696..205498acc3187 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -1,4 +1,4 @@ -use gccjit::{RValue, Type}; +use gccjit::{LValue, RValue, ToRValue, Type}; use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods}; use rustc_hir as hir; use rustc_hir::Node; @@ -14,7 +14,6 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRan use crate::base; use crate::context::CodegenCx; -use crate::mangled_std_symbols::{ARGC, ARGV, ARGV_INIT_ARRAY}; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -45,17 +44,13 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { fn codegen_static(&self, def_id: DefId, is_mutable: bool) { let attrs = self.tcx.codegen_fn_attrs(def_id); - let instance = Instance::mono(self.tcx, def_id); - let name = &*self.tcx.symbol_name(instance).name; - - let (value, alloc) = + let value = match codegen_static_initializer(&self, def_id) { - Ok(value) => value, + Ok((value, _)) => value, // Error has already been reported Err(_) => return, }; - let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); let global = self.get_static(def_id); // boolean SSA values are i1, but they have to be stored in i8 slots, @@ -73,45 +68,16 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); let gcc_type = self.layout_of(ty).gcc_type(self, true); - let global = - if val_llty == gcc_type { - global + // TODO(antoyo): set alignment. + + let value = + if value.get_type() != gcc_type { + self.context.new_bitcast(None, value, gcc_type) } else { - // If we created the global with the wrong type, - // correct the type. - // TODO(antoyo): set value name, linkage and visibility. - - let new_global = self.get_or_insert_global(&name, val_llty, is_tls, attrs.link_section); - - // To avoid breaking any invariants, we leave around the old - // global for the moment; we'll replace all references to it - // with the new global later. (See base::codegen_backend.) - //self.statics_to_rauw.borrow_mut().push((global, new_global)); - new_global + value }; - // TODO(antoyo): set alignment and initializer. - let value = self.rvalue_as_lvalue(value); - let value = value.get_address(None); - let dest_typ = global.get_type(); - let value = self.context.new_cast(None, value, dest_typ); - - // NOTE: do not init the variables related to argc/argv because it seems we cannot - // overwrite those variables. - // FIXME(antoyo): correctly support global variable initialization. - let skip_init = [ - ARGV_INIT_ARRAY, - ARGC, - ARGV, - ]; - if !skip_init.iter().any(|symbol_name| name.starts_with(symbol_name)) { - // TODO(antoyo): switch to set_initializer when libgccjit supports that. - let memcpy = self.context.get_builtin_function("memcpy"); - let dst = self.context.new_cast(None, global, self.type_i8p()); - let src = self.context.new_cast(None, value, self.type_ptr_to(self.type_void())); - let size = self.context.new_rvalue_from_long(self.sizet_type, alloc.size().bytes() as i64); - self.global_init_block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size])); - } + global.global_set_initializer_value(value); // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. @@ -175,7 +141,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { } if attrs.flags.contains(CodegenFnAttrFlags::USED) { - self.add_used_global(global); + self.add_used_global(global.to_rvalue()); } } @@ -191,38 +157,31 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn static_addr_of_mut(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> { - let (name, gv) = + let global = match kind { Some(kind) if !self.tcx.sess.fewer_names() => { let name = self.generate_local_symbol_name(kind); // TODO(antoyo): check if it's okay that TLS is off here. // TODO(antoyo): check if it's okay that link_section is None here. // TODO(antoyo): set alignment here as well. - let gv = self.define_global(&name[..], self.val_ty(cv), false, None).unwrap_or_else(|| { - bug!("symbol `{}` is already defined", name); - }); + let global = self.define_global(&name[..], self.val_ty(cv), false, None); // TODO(antoyo): set linkage. - (name, gv) + global } _ => { - let index = self.global_gen_sym_counter.get(); - let name = format!("global_{}_{}", index, self.codegen_unit.name()); let typ = self.val_ty(cv).get_aligned(align.bytes()); - let global = self.define_private_global(typ); - (name, global) + let global = self.declare_unnamed_global(typ); + global }, }; // FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used // globally. - // NOTE: global seems to only be global in a module. So save the name instead of the value - // to import it later. - self.global_names.borrow_mut().insert(cv, name); - self.global_init_block.add_assignment(None, gv.dereference(None), cv); + global.global_set_initializer_value(cv); // TODO(antoyo): set unnamed address. - gv + global.get_address(None) } - pub fn get_static(&self, def_id: DefId) -> RValue<'gcc> { + pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> { let instance = Instance::mono(self.tcx, def_id); let fn_attrs = self.tcx.codegen_fn_attrs(def_id); if let Some(&global) = self.instances.borrow().get(&instance) { @@ -380,7 +339,7 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id Ok((const_alloc_to_gcc(cx, alloc), alloc)) } -fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> RValue<'gcc> { +fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> { let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); let llty = cx.layout_of(ty).gcc_type(cx, true); if let Some(linkage) = attrs.linkage { @@ -410,13 +369,9 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); real_name.push_str(&sym); - let global2 = - cx.define_global(&real_name, llty, is_tls, attrs.link_section).unwrap_or_else(|| { - cx.sess().span_fatal(span, &format!("symbol `{}` is already defined", &sym)) - }); + let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section); // TODO(antoyo): set linkage. - let lvalue = global2.dereference(None); - cx.global_init_block.add_assignment(None, lvalue, global1); + global2.global_set_initializer_value(global1.get_address(None)); // TODO(antoyo): use global_set_initializer() when it will work. global2 } diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index ef687dd22c6da..7677ade7314e5 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -21,10 +21,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::span_bug; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers}; +use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers}; use rustc_session::Session; use rustc_span::{Span, Symbol}; -use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; +use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; use crate::callee::get_fn; @@ -46,10 +46,6 @@ pub struct CodegenCx<'gcc, 'tcx> { pub current_func: RefCell>>, pub normal_function_addresses: RefCell>>, - /// The function where globals are initialized. - pub global_init_func: Function<'gcc>, - pub global_init_block: Block<'gcc>, - pub functions: RefCell>>, pub tls_model: gccjit::TlsModel, @@ -89,23 +85,20 @@ pub struct CodegenCx<'gcc, 'tcx> { pub types_with_fields_to_set: RefCell, (Struct<'gcc>, TyAndLayout<'tcx>)>>, /// Cache instances of monomorphic and polymorphic items - pub instances: RefCell, RValue<'gcc>>>, + pub instances: RefCell, LValue<'gcc>>>, + /// Cache function instances of monomorphic and polymorphic items + pub function_instances: RefCell, RValue<'gcc>>>, /// Cache generated vtables pub vtables: RefCell, Option>), RValue<'gcc>>>, /// Cache of emitted const globals (value -> global) pub const_globals: RefCell, RValue<'gcc>>>, - pub init_argv_var: RefCell, - pub argv_initialized: Cell, - /// Cache of constant strings, pub const_cstr_cache: RefCell>>, /// Cache of globals. pub globals: RefCell>>, - // TODO(antoyo): remove global_names. - pub global_names: RefCell, String>>, /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell, @@ -118,16 +111,9 @@ pub struct CodegenCx<'gcc, 'tcx> { /// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such, /// `const_undef()` returns struct as pointer so that they can later be assigned a value. /// As such, this set remembers which of these pointers were returned by this function so that - /// they can be derefered later. + /// they can be deferenced later. /// FIXME(antoyo): fix the rustc API to avoid having this hack. pub structs_as_pointer: RefCell>>, - - /// Store the pointer of different types for safety. - /// When casting the values back to their original types, check that they are indeed that type - /// with these sets. - /// FIXME(antoyo): remove when the API supports more types. - #[cfg(debug_assertions)] - lvalues: RefCell>>, } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -180,10 +166,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { functions.insert(builtin.to_string(), context.get_builtin_function(builtin)); } - let global_init_func = context.new_function(None, FunctionType::Exported, context.new_type::<()>(), &[], - &format!("__gccGlobalInit{}", unit_name(&codegen_unit)), false); - let global_init_block = global_init_func.new_block("initial"); - Self { check_overflow, codegen_unit, @@ -192,8 +174,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { current_func: RefCell::new(None), normal_function_addresses: Default::default(), functions: RefCell::new(functions), - global_init_func, - global_init_block, tls_model, @@ -221,15 +201,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { double_type, linkage: Cell::new(FunctionType::Internal), - #[cfg(debug_assertions)] - lvalues: Default::default(), instances: Default::default(), + function_instances: Default::default(), vtables: Default::default(), const_globals: Default::default(), - init_argv_var: RefCell::new(String::new()), - argv_initialized: Cell::new(false), const_cstr_cache: Default::default(), - global_names: Default::default(), globals: Default::default(), scalar_types: Default::default(), types: Default::default(), @@ -244,12 +220,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } - pub fn lvalue_to_rvalue(&self, value: LValue<'gcc>) -> RValue<'gcc> { - #[cfg(debug_assertions)] - self.lvalues.borrow_mut().insert(value); - unsafe { std::mem::transmute(value) } - } - pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> { let function: Function<'gcc> = unsafe { std::mem::transmute(value) }; debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(), @@ -257,11 +227,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { function } - pub fn rvalue_as_lvalue(&self, value: RValue<'gcc>) -> LValue<'gcc> { - let lvalue: LValue<'gcc> = unsafe { std::mem::transmute(value) }; - lvalue - } - pub fn sess(&self) -> &Session { &self.tcx.sess } @@ -436,6 +401,43 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { } } +impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.sess().span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + } + } + } +} + impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> { fn param_env(&self) -> ParamEnv<'tcx> { ParamEnv::reveal_all() diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 8661532a3595e..4d3b4f04badec 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -1,11 +1,9 @@ -use gccjit::{FunctionType, RValue}; +use gccjit::RValue; use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind}; -use rustc_codegen_ssa::traits::{BuilderMethods, DebugInfoBuilderMethods, DebugInfoMethods}; -use rustc_middle::middle::cstore::CrateDepKind; +use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods}; use rustc_middle::mir; use rustc_middle::ty::{Instance, Ty}; use rustc_span::{SourceFile, Span, Symbol}; -use rustc_span::def_id::LOCAL_CRATE; use rustc_target::abi::Size; use rustc_target::abi::call::FnAbi; @@ -20,25 +18,6 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { } fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { - // TODO(antoyo): replace with gcc_jit_context_new_global_with_initializer() if it's added: - // https://gcc.gnu.org/pipermail/jit/2020q3/001225.html - // - // Call the function to initialize global values here. - // We assume this is only called for the main function. - use std::iter; - - for crate_num in self.cx.tcx.crates(()).iter().copied().chain(iter::once(LOCAL_CRATE)) { - // FIXME(antoyo): better way to find if a crate is of proc-macro type? - if crate_num == LOCAL_CRATE || self.cx.tcx.dep_kind(crate_num) != CrateDepKind::MacrosOnly { - // NOTE: proc-macro crates are not included in the executable, so don't call their - // initialization routine. - let initializer_name = format!("__gccGlobalCrateInit{}", self.cx.tcx.crate_name(crate_num)); - let codegen_init_func = self.context.new_function(None, FunctionType::Extern, self.context.new_type::<()>(), &[], - initializer_name, false); - self.llbb().add_eval(None, self.context.new_call(None, codegen_init_func, &[])); - } - } - // TODO(antoyo): insert reference to gdb debug scripts section global. } diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index c1382bf2f4a71..b43f68f878d7a 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -7,10 +7,9 @@ use rustc_target::abi::call::FnAbi; use crate::abi::FnAbiGccExt; use crate::context::{CodegenCx, unit_name}; use crate::intrinsic::llvm; -use crate::mangled_std_symbols::{ARGV_INIT_ARRAY, ARGV_INIT_WRAPPER}; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> RValue<'gcc> { + pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> LValue<'gcc> { if self.globals.borrow().contains_key(name) { let typ = self.globals.borrow().get(name).expect("global").get_type(); let global = self.context.new_global(None, GlobalKind::Imported, typ, name); @@ -20,7 +19,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { if let Some(link_section) = link_section { global.set_link_section(&link_section.as_str()); } - global.get_address(None) + global } else { self.declare_global(name, ty, is_tls, link_section) @@ -34,13 +33,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.context.new_global(None, GlobalKind::Exported, ty, &name) } - pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> RValue<'gcc> { - let global = self.context.new_global(None, linkage, ty, name) - .get_address(None); - self.globals.borrow_mut().insert(name.to_string(), global); - // NOTE: global seems to only be global in a module. So save the name instead of the value - // to import it later. - self.global_names.borrow_mut().insert(global, name.to_string()); + pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> { + let global = self.context.new_global(None, linkage, ty, name); + let global_address = global.get_address(None); + self.globals.borrow_mut().insert(name.to_string(), global_address); global } @@ -51,19 +47,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { unsafe { std::mem::transmute(func) } } - pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> RValue<'gcc> { - // FIXME(antoyo): correctly support global variable initialization. - if name.starts_with(ARGV_INIT_ARRAY) { - // NOTE: hack to avoid having to update the names in mangled_std_symbols: we save the - // name of the variable now to actually declare it later. - *self.init_argv_var.borrow_mut() = name.to_string(); - - let global = self.context.new_global(None, GlobalKind::Imported, ty, name); - if let Some(link_section) = link_section { - global.set_link_section(&link_section.as_str()); - } - return global.get_address(None); - } + pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> LValue<'gcc> { let global = self.context.new_global(None, GlobalKind::Exported, ty, name); if is_tls { global.set_tls_model(self.tls_model); @@ -71,11 +55,15 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { if let Some(link_section) = link_section { global.set_link_section(&link_section.as_str()); } - let global = global.get_address(None); - self.globals.borrow_mut().insert(name.to_string(), global); - // NOTE: global seems to only be global in a module. So save the name instead of the value - // to import it later. - self.global_names.borrow_mut().insert(global, name.to_string()); + let global_address = global.get_address(None); + self.globals.borrow_mut().insert(name.to_string(), global_address); + global + } + + pub fn declare_private_global(&self, name: &str, ty: Type<'gcc>) -> LValue<'gcc> { + let global = self.context.new_global(None, GlobalKind::Internal, ty, name); + let global_address = global.get_address(None); + self.globals.borrow_mut().insert(name.to_string(), global_address); global } @@ -94,51 +82,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> { - // NOTE: hack to avoid having to update the names in mangled_std_symbols: we found the name - // of the variable earlier, so we declare it now. - // Since we don't correctly support initializers yet, we initialize this variable manually - // for now. - if name.starts_with(ARGV_INIT_WRAPPER) && !self.argv_initialized.get() { - let global_name = &*self.init_argv_var.borrow(); - let return_type = self.type_void(); - let params = [ - self.context.new_parameter(None, self.int_type, "argc"), - self.context.new_parameter(None, self.u8_type.make_pointer().make_pointer(), "argv"), - self.context.new_parameter(None, self.u8_type.make_pointer().make_pointer(), "envp"), - ]; - let function = self.context.new_function(None, FunctionType::Extern, return_type, ¶ms, name, false); - let initializer = function.get_address(None); - - let param_types = [ - self.int_type, - self.u8_type.make_pointer().make_pointer(), - self.u8_type.make_pointer().make_pointer(), - ]; - let ty = self.context.new_function_pointer_type(None, return_type, ¶m_types, false); - - let global = self.context.new_global(None, GlobalKind::Exported, ty, global_name); - global.set_link_section(".init_array.00099"); - global.global_set_initializer_value(initializer); - let global = global.get_address(None); - self.globals.borrow_mut().insert(global_name.to_string(), global); - // NOTE: global seems to only be global in a module. So save the name instead of the value - // to import it later. - self.global_names.borrow_mut().insert(global, global_name.to_string()); - self.argv_initialized.set(true); - } let (return_type, params, variadic) = fn_abi.gcc_type(self); let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, ¶ms, variadic); // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. unsafe { std::mem::transmute(func) } } - pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> Option> { - Some(self.get_or_insert_global(name, ty, is_tls, link_section)) - } - - pub fn define_private_global(&self, ty: Type<'gcc>) -> RValue<'gcc> { - let global = self.declare_unnamed_global(ty); - global.get_address(None) + pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> LValue<'gcc> { + self.get_or_insert_global(name, ty, is_tls, link_section) } pub fn get_declared_value(&self, name: &str) -> Option> { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 3dc4f61a7ac3c..45978e1409023 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -18,7 +18,7 @@ use rustc_target::spec::PanicStrategy; use crate::abi::GccType; use crate::builder::Builder; -use crate::common::TypeReflection; +use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; use crate::type_of::LayoutGccExt; use crate::intrinsic::simd::generic_simd_intrinsic; @@ -520,163 +520,176 @@ fn int_type_width_signed<'gcc, 'tcx>(ty: Ty<'tcx>, cx: &CodegenCx<'gcc, 'tcx>) - impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn bit_reverse(&mut self, width: u64, value: RValue<'gcc>) -> RValue<'gcc> { - let typ = value.get_type(); + let result_type = value.get_type(); + let typ = result_type.to_unsigned(self.cx); + + let value = + if result_type.is_signed(self.cx) { + self.context.new_bitcast(None, value, typ) + } + else { + value + }; + let context = &self.cx.context; - match width { - 8 => { - // First step. - let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 4)); - let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 4)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 2)); - let step2 = self.or(left, right); - - // Third step. - let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 1)); - let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 1)); - let step3 = self.or(left, right); - - step3 - }, - 16 => { - // First step. - let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 1)); - let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 1)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 2)); - let step2 = self.or(left, right); - - // Third step. - let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 4)); - let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 4)); - let step3 = self.or(left, right); - - // Fourth step. - let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 8)); - let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 8)); - let step4 = self.or(left, right); - - step4 - }, - 32 => { - // TODO(antoyo): Refactor with other implementations. - // First step. - let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 1)); - let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 1)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 2)); - let step2 = self.or(left, right); - - // Third step. - let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 4)); - let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 4)); - let step3 = self.or(left, right); - - // Fourth step. - let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 8)); - let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 8)); - let step4 = self.or(left, right); - - // Fifth step. - let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 16)); - let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 16)); - let step5 = self.or(left, right); - - step5 - }, - 64 => { - // First step. - let left = self.shl(value, context.new_rvalue_from_long(typ, 32)); - let right = self.lshr(value, context.new_rvalue_from_long(typ, 32)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 15)); - let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead? - let right = self.lshr(right, context.new_rvalue_from_long(typ, 17)); - let step2 = self.or(left, right); - - // Third step. - let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10)); - let left = self.xor(step2, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 10)); - let left = self.or(temp, left); - let step3 = self.xor(left, step2); - - // Fourth step. - let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4)); - let left = self.xor(step3, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 4)); - let left = self.or(temp, left); - let step4 = self.xor(left, step3); - - // Fifth step. - let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2)); - let left = self.xor(step4, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 2)); - let left = self.or(temp, left); - let step5 = self.xor(left, step4); - - step5 - }, - 128 => { - // TODO(antoyo): find a more efficient implementation? - let sixty_four = self.context.new_rvalue_from_long(typ, 64); - let high = self.context.new_cast(None, value >> sixty_four, self.u64_type); - let low = self.context.new_cast(None, value, self.u64_type); + let result = + match width { + 8 => { + // First step. + let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0)); + let left = self.lshr(left, context.new_rvalue_from_int(typ, 4)); + let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F)); + let right = self.shl(right, context.new_rvalue_from_int(typ, 4)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC)); + let left = self.lshr(left, context.new_rvalue_from_int(typ, 2)); + let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33)); + let right = self.shl(right, context.new_rvalue_from_int(typ, 2)); + let step2 = self.or(left, right); + + // Third step. + let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA)); + let left = self.lshr(left, context.new_rvalue_from_int(typ, 1)); + let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55)); + let right = self.shl(right, context.new_rvalue_from_int(typ, 1)); + let step3 = self.or(left, right); + + step3 + }, + 16 => { + // First step. + let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 1)); + let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 1)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 2)); + let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 2)); + let step2 = self.or(left, right); + + // Third step. + let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 4)); + let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 4)); + let step3 = self.or(left, right); + + // Fourth step. + let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 8)); + let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 8)); + let step4 = self.or(left, right); + + step4 + }, + 32 => { + // TODO(antoyo): Refactor with other implementations. + // First step. + let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 1)); + let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 1)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 2)); + let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 2)); + let step2 = self.or(left, right); + + // Third step. + let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 4)); + let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 4)); + let step3 = self.or(left, right); + + // Fourth step. + let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 8)); + let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 8)); + let step4 = self.or(left, right); + + // Fifth step. + let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 16)); + let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 16)); + let step5 = self.or(left, right); + + step5 + }, + 64 => { + // First step. + let left = self.shl(value, context.new_rvalue_from_long(typ, 32)); + let right = self.lshr(value, context.new_rvalue_from_long(typ, 32)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 15)); + let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead? + let right = self.lshr(right, context.new_rvalue_from_long(typ, 17)); + let step2 = self.or(left, right); + + // Third step. + let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10)); + let left = self.xor(step2, left); + let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F)); + + let left = self.shl(temp, context.new_rvalue_from_long(typ, 10)); + let left = self.or(temp, left); + let step3 = self.xor(left, step2); + + // Fourth step. + let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4)); + let left = self.xor(step3, left); + let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421)); + + let left = self.shl(temp, context.new_rvalue_from_long(typ, 4)); + let left = self.or(temp, left); + let step4 = self.xor(left, step3); + + // Fifth step. + let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2)); + let left = self.xor(step4, left); + let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842)); + + let left = self.shl(temp, context.new_rvalue_from_long(typ, 2)); + let left = self.or(temp, left); + let step5 = self.xor(left, step4); + + step5 + }, + 128 => { + // TODO(antoyo): find a more efficient implementation? + let sixty_four = self.context.new_rvalue_from_long(typ, 64); + let high = self.context.new_cast(None, value >> sixty_four, self.u64_type); + let low = self.context.new_cast(None, value, self.u64_type); - let reversed_high = self.bit_reverse(64, high); - let reversed_low = self.bit_reverse(64, low); + let reversed_high = self.bit_reverse(64, high); + let reversed_low = self.bit_reverse(64, low); - let new_low = self.context.new_cast(None, reversed_high, typ); - let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four; + let new_low = self.context.new_cast(None, reversed_high, typ); + let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four; - new_low | new_high - }, - _ => { - panic!("cannot bit reverse with width = {}", width); - }, - } + new_low | new_high + }, + _ => { + panic!("cannot bit reverse with width = {}", width); + }, + }; + + self.context.new_bitcast(None, result, result_type) } fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { @@ -746,6 +759,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { + let result_type = arg.get_type(); + let arg = + if result_type.is_signed(self.cx) { + let new_type = result_type.to_unsigned(self.cx); + self.context.new_bitcast(None, arg, new_type) + } + else { + arg + }; let arg_type = arg.get_type(); let (count_trailing_zeroes, expected_type) = if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) { @@ -796,7 +818,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let res = self.context.new_array_access(None, result, index); - return self.context.new_cast(None, res, arg_type); + return self.context.new_bitcast(None, res, result_type); } else { unimplemented!("count_trailing_zeroes for {:?}", arg_type); @@ -810,7 +832,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { arg }; let res = self.context.new_call(None, count_trailing_zeroes, &[arg]); - self.context.new_cast(None, res, arg_type) + self.context.new_bitcast(None, res, result_type) } fn int_width(&self, typ: Type<'gcc>) -> i64 { @@ -819,7 +841,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> { // TODO(antoyo): use the optimized version with fewer operations. - let value_type = value.get_type(); + let result_type = value.get_type(); + let value_type = result_type.to_unsigned(self.cx); + + let value = + if result_type.is_signed(self.cx) { + self.context.new_bitcast(None, value, value_type) + } + else { + value + }; if value_type.is_u128(&self.cx) { // TODO(antoyo): implement in the normal algorithm below to have a more efficient @@ -830,7 +861,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let high = self.context.new_call(None, popcount, &[high]); let low = self.context.new_cast(None, value, self.cx.ulonglong_type); let low = self.context.new_call(None, popcount, &[low]); - return high + low; + let res = high + low; + return self.context.new_bitcast(None, res, result_type); } // First step. @@ -855,7 +887,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = left + right; if value_type.is_u8(&self.cx) { - return value; + return self.context.new_bitcast(None, value, result_type); } // Fourth step. @@ -866,7 +898,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = left + right; if value_type.is_u16(&self.cx) { - return value; + return self.context.new_bitcast(None, value, result_type); } // Fifth step. @@ -877,7 +909,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = left + right; if value_type.is_u32(&self.cx) { - return value; + return self.context.new_bitcast(None, value, result_type); } // Sixth step. @@ -887,7 +919,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let right = shifted & mask; let value = left + right; - value + self.context.new_bitcast(None, value, result_type) } // Algorithm from: https://blog.regehr.org/archives/1063 diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 793e5c48d0a36..f3c02e2634ff6 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -43,7 +43,6 @@ mod coverageinfo; mod debuginfo; mod declare; mod intrinsic; -mod mangled_std_symbols; mod mono_item; mod type_; mod type_of; @@ -51,7 +50,7 @@ mod type_of; use std::any::Any; use std::sync::Arc; -use gccjit::{Block, Context, FunctionType, OptimizationLevel}; +use gccjit::{Context, OptimizationLevel}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::base::codegen_crate; @@ -64,13 +63,11 @@ use rustc_errors::{ErrorReported, Handler}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{CrateType, Lto, OptLevel, OutputFilenames}; +use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; use rustc_span::Symbol; use rustc_span::fatal_error::FatalError; -use crate::context::unit_name; - pub struct PrintOnPanic String>(pub F); impl String> Drop for PrintOnPanic { @@ -109,16 +106,8 @@ impl CodegenBackend for GccCodegenBackend { Ok((codegen_results, work_products)) } - fn link(&self, sess: &Session, mut codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> { + fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> { use rustc_codegen_ssa::back::link::link_binary; - if let Some(symbols) = codegen_results.crate_info.exported_symbols.get_mut(&CrateType::Dylib) { - // TODO:(antoyo): remove when global initializer work without calling a function at runtime. - // HACK: since this codegen add some symbols (e.g. __gccGlobalCrateInit) and the UI - // tests load libstd.so as a dynamic library, and rustc use a version-script to specify - // the symbols visibility, we add * to export all symbols. - // It seems other symbols from libstd/libcore are causing some issues here as well. - symbols.push("*".to_string()); - } link_binary::>( sess, @@ -203,6 +192,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn run_fat_lto(_cgcx: &CodegenContext, mut modules: Vec>, _cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result, FatalError> { // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins. // NOTE: implemented elsewhere. + // TODO: what is implemented elsewhere ^ ? let module = match modules.remove(0) { FatLTOInput::InMemory(module) => module, @@ -273,15 +263,6 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { } } -fn create_function_calling_initializers<'gcc, 'tcx>(tcx: TyCtxt<'tcx>, context: &Context<'gcc>, block: Block<'gcc>) { - let codegen_units = tcx.collect_and_partition_mono_items(()).1; - for codegen_unit in codegen_units { - let codegen_init_func = context.new_function(None, FunctionType::Extern, context.new_type::<()>(), &[], - &format!("__gccGlobalInit{}", unit_name(&codegen_unit)), false); - block.add_eval(None, context.new_call(None, codegen_init_func, &[])); - } -} - fn handle_native(name: &str) -> &str { if name != "native" { return name; diff --git a/compiler/rustc_codegen_gcc/src/mangled_std_symbols.rs b/compiler/rustc_codegen_gcc/src/mangled_std_symbols.rs deleted file mode 100644 index b0c3f214d66c1..0000000000000 --- a/compiler/rustc_codegen_gcc/src/mangled_std_symbols.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub const ARGV_INIT_ARRAY: &str = "_ZN3std3sys4unix4args3imp15ARGV_INIT_ARRAY"; -pub const ARGV_INIT_WRAPPER: &str = "_ZN3std3sys4unix4args3imp15ARGV_INIT_ARRAY12init_wrapper"; -pub const ARGC: &str = "_ZN3std3sys4unix4args3imp4ARGC"; -pub const ARGV: &str = "_ZN3std3sys4unix4args3imp4ARGV"; diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index cedeb54f60bf2..e21d40b6c37e3 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -2,9 +2,8 @@ use rustc_codegen_ssa::traits::PreDefineMethods; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::{self, Instance, TypeFoldable}; -use rustc_middle::ty::layout::{FnAbiExt, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_span::def_id::DefId; -use rustc_target::abi::call::FnAbi; use crate::base; use crate::context::CodegenCx; @@ -18,12 +17,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let gcc_type = self.layout_of(ty).gcc_type(self, true); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); - let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section).unwrap_or_else(|| { - self.sess().span_fatal( - self.tcx.def_span(def_id), - &format!("symbol `{}` is already defined", symbol_name), - ) - }); + let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); // TODO(antoyo): set linkage and visibility. self.instances.borrow_mut().insert(instance, global); @@ -32,7 +26,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, _visibility: Visibility, symbol_name: &str) { assert!(!instance.substs.needs_infer()); - let fn_abi = FnAbi::of_instance(self, instance, &[]); + 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 attrs = self.tcx.codegen_fn_attrs(instance.def_id()); diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 2ff2ee7b85226..9c39c8f91a1ff 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -4,7 +4,7 @@ use gccjit::{Struct, Type}; use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods}; use rustc_middle::bug; use rustc_middle::ty::{self, Ty, TypeFoldable}; -use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_target::abi::{self, Abi, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants}; use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; @@ -160,7 +160,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { ty::Adt(def, _) if def.is_box() => { cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).gcc_type(cx, true)) } - ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])), + ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())), _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO), }; cx.scalar_types.borrow_mut().insert(self.ty, ty); diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh index 12df1f8af2f0b..944d0ce516e0f 100755 --- a/compiler/rustc_codegen_gcc/test.sh +++ b/compiler/rustc_codegen_gcc/test.sh @@ -17,6 +17,7 @@ export LIBRARY_PATH="$GCC_PATH" if [[ "$1" == "--release" ]]; then export CHANNEL='release' CARGO_INCREMENTAL=1 cargo rustc --release + shift else echo $LD_LIBRARY_PATH export CHANNEL='debug' @@ -25,52 +26,60 @@ fi source config.sh -rm -r target/out || true -mkdir -p target/out/gccjit +function clean() { + rm -r target/out || true + mkdir -p target/out/gccjit +} -echo "[BUILD] mini_core" -$RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE +function mini_tests() { + echo "[BUILD] mini_core" + $RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE -echo "[BUILD] example" -$RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE + echo "[BUILD] example" + $RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE -echo "[AOT] mini_core_hello_world" -$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE -$RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd + echo "[AOT] mini_core_hello_world" + $RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd +} -echo "[BUILD] sysroot" -time ./build_sysroot/build_sysroot.sh +function build_sysroot() { + echo "[BUILD] sysroot" + time ./build_sysroot/build_sysroot.sh +} -echo "[AOT] arbitrary_self_types_pointers_and_wrappers" -$RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE -$RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers +function std_tests() { + echo "[AOT] arbitrary_self_types_pointers_and_wrappers" + $RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers -echo "[AOT] alloc_system" -$RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" + echo "[AOT] alloc_system" + $RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" -echo "[AOT] alloc_example" -$RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE -$RUN_WRAPPER ./target/out/alloc_example + echo "[AOT] alloc_example" + $RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/alloc_example -echo "[AOT] dst_field_align" -# FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed. -$RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE -$RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false) + echo "[AOT] dst_field_align" + # FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed. + $RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false) -echo "[AOT] std_example" -$RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE -$RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE + echo "[AOT] std_example" + $RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE -echo "[AOT] subslice-patterns-const-eval" -$RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE -$RUN_WRAPPER ./target/out/subslice-patterns-const-eval + echo "[AOT] subslice-patterns-const-eval" + $RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/subslice-patterns-const-eval -echo "[AOT] track-caller-attribute" -$RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE -$RUN_WRAPPER ./target/out/track-caller-attribute + echo "[AOT] track-caller-attribute" + $RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/track-caller-attribute -echo "[BUILD] mod_bench" -$RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE + echo "[BUILD] mod_bench" + $RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE +} # FIXME(antoyo): linker gives multiple definitions error on Linux #echo "[BUILD] sysroot in release mode" @@ -95,11 +104,13 @@ $RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE #fi #popd -pushd build_sysroot/sysroot_src/library/core/tests -echo "[TEST] libcore" -rm -r ./target || true -../../../../../cargo.sh test -popd +function test_libcore() { + pushd build_sysroot/sysroot_src/library/core/tests + echo "[TEST] libcore" + rm -r ./target || true + ../../../../../cargo.sh test + popd +} # TODO(antoyo): uncomment when it works. #pushd regex @@ -130,20 +141,21 @@ popd #echo "[BENCH RUN] mod_bench" #hyperfine --runs ${RUN_RUNS:-10} ./target/out/mod_bench{,_inline} ./target/out/mod_bench_llvm_* -echo -echo "[TEST] rust-lang/rust" +function test_rustc() { + echo + echo "[TEST] rust-lang/rust" -rust_toolchain=$(cat rust-toolchain) + rust_toolchain=$(cat rust-toolchain) -git clone https://github.com/rust-lang/rust.git || true -cd rust -git fetch -git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') -export RUSTFLAGS= + git clone https://github.com/rust-lang/rust.git || true + cd rust + git fetch + git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') + export RUSTFLAGS= -rm config.toml || true + rm config.toml || true -cat > config.toml < config.toml <